usr/src/cmd/login/login_audit.c
changeset 3050 dc042908a62a
parent 0 68f95e015346
child 11537 8eca52188202
equal deleted inserted replaced
3049:f1d94cba9e2e 3050:dc042908a62a
     1 /*
     1 /*
     2  * CDDL HEADER START
     2  * CDDL HEADER START
     3  *
     3  *
     4  * The contents of this file are subject to the terms of the
     4  * The contents of this file are subject to the terms of the
     5  * Common Development and Distribution License, Version 1.0 only
     5  * Common Development and Distribution License (the "License").
     6  * (the "License").  You may not use this file except in compliance
     6  * You may not use this file except in compliance with the License.
     7  * with the License.
       
     8  *
     7  *
     9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    10  * or http://www.opensolaris.org/os/licensing.
     9  * or http://www.opensolaris.org/os/licensing.
    11  * See the License for the specific language governing permissions
    10  * See the License for the specific language governing permissions
    12  * and limitations under the License.
    11  * and limitations under the License.
    18  * information: Portions Copyright [yyyy] [name of copyright owner]
    17  * information: Portions Copyright [yyyy] [name of copyright owner]
    19  *
    18  *
    20  * CDDL HEADER END
    19  * CDDL HEADER END
    21  */
    20  */
    22 /*
    21 /*
    23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
    22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
    24  * Use is subject to license terms.
    23  * Use is subject to license terms.
    25  */
    24  */
    26 
    25 
    27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
    26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
    28 
    27 
    29 #include <assert.h>
    28 #include <assert.h>
       
    29 #include <priv.h>
    30 #include <pwd.h>
    30 #include <pwd.h>
    31 #include <signal.h>
    31 #include <signal.h>
    32 #include <stdlib.h>
    32 #include <stdlib.h>
    33 #include <string.h>
    33 #include <string.h>
    34 #include <syslog.h>
    34 #include <syslog.h>
    37 
    37 
    38 #include <bsm/adt.h>
    38 #include <bsm/adt.h>
    39 #include <bsm/adt_event.h>
    39 #include <bsm/adt_event.h>
    40 #include "login_audit.h"
    40 #include "login_audit.h"
    41 
    41 
    42 
       
    43 
       
    44 /*
    42 /*
    45  * Key assumption:  login is single threaded.
    43  * Key assumption:  login is single threaded.
    46  */
    44  */
    47 static void audit_logout(adt_session_data_t *);
    45 static void audit_logout(adt_session_data_t *);
    48 
    46 
    67 	int			rc;
    65 	int			rc;
    68 
    66 
    69 	assert(pwd != NULL);
    67 	assert(pwd != NULL);
    70 
    68 
    71 	if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA)) {
    69 	if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA)) {
    72 		syslog(LOG_AUTH | LOG_ALERT, "audit: %m");
    70 		syslog(LOG_AUTH | LOG_ALERT, "login adt_start_session(): %m");
    73 		return;
    71 		return;
    74 	}
    72 	}
    75 	if (adt_set_user(ah, pwd->pw_uid,  pwd->pw_gid,
    73 	if (adt_set_user(ah, pwd->pw_uid,  pwd->pw_gid,
    76 	    pwd->pw_uid,  pwd->pw_gid, NULL, ADT_USER)) {
    74 	    pwd->pw_uid,  pwd->pw_gid, NULL, ADT_USER)) {
    77 		syslog(LOG_AUTH | LOG_ALERT, "audit: %m");
    75 		syslog(LOG_AUTH | LOG_ALERT, "login adt_set_user(): %m");
    78 		(void) adt_end_session(ah);
    76 		(void) adt_end_session(ah);
    79 		return;
    77 		return;
    80 	}
    78 	}
    81 	event = adt_alloc_event(ah, event_id);
    79 	event = adt_alloc_event(ah, event_id);
    82 
    80 
    93 	rc = adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS);
    91 	rc = adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS);
    94 
    92 
    95 	(void) adt_free_event(event);
    93 	(void) adt_free_event(event);
    96 	if (rc) {
    94 	if (rc) {
    97 		(void) adt_end_session(ah);
    95 		(void) adt_end_session(ah);
    98 		syslog(LOG_AUTH | LOG_ALERT, "audit: %m");
    96 		syslog(LOG_AUTH | LOG_ALERT, "login adt_put_event(): %m");
    99 		return;
    97 		return;
   100 	}
    98 	}
   101 	/*
    99 	/*
   102 	 * The code above executes whether or not audit is enabled.
   100 	 * The code above executes whether or not audit is enabled.
   103 	 * However audit_logout must only execute if audit is
   101 	 * However audit_logout must only execute if audit is
   123 audit_logout(adt_session_data_t *ah)
   121 audit_logout(adt_session_data_t *ah)
   124 {
   122 {
   125 	adt_event_data_t	*logout;
   123 	adt_event_data_t	*logout;
   126 	int			status;		/* wait status */
   124 	int			status;		/* wait status */
   127 	pid_t			pid;
   125 	pid_t			pid;
       
   126 	priv_set_t		*priv;		/* waiting process privs */
       
   127 
       
   128 	if ((logout = adt_alloc_event(ah, ADT_logout)) == NULL) {
       
   129 		syslog(LOG_AUTH | LOG_ALERT,
       
   130 		    "adt_alloc_event(ADT_logout): %m");
       
   131 		return;
       
   132 	}
       
   133 	if ((priv = priv_allocset())  == NULL) {
       
   134 		syslog(LOG_AUTH | LOG_ALERT,
       
   135 		    "login audit_logout: could not alloc privs: %m");
       
   136 		adt_free_event(logout);
       
   137 		return;
       
   138 	}
       
   139 
       
   140 	/*
       
   141 	 * The child returns and continues the login processing.
       
   142 	 * The parent's sole job is to wait for child exit, write the
       
   143 	 * logout audit record, and replay the child's exit code.
       
   144 	 */
   128 
   145 
   129 	if ((pid = fork()) == 0) {
   146 	if ((pid = fork()) == 0) {
   130 		return;
   147 		/* child */
   131 	} else if (pid == -1) {
       
   132 		syslog(LOG_AUTH | LOG_ALERT, "login: could not fork: %m");
       
   133 		exit(1);
       
   134 	} else {
       
   135 		/*
       
   136 		 * When this routine is called, the current working
       
   137 		 * directory is the user's home directory. Change it
       
   138 		 * to root for the waiting process so that the user's
       
   139 		 * home directory can be unmounted if necessary.
       
   140 		 */
       
   141 		if (chdir("/") != 0) {
       
   142 			syslog(LOG_AUTH | LOG_ALERT,
       
   143 			    "login: could not chdir: %m");
       
   144 			/* since we let the child finish we just bail */
       
   145 			exit(0);
       
   146 		}
       
   147 		while (pid != waitpid(pid, &status, 0))
       
   148 			continue;
       
   149 
       
   150 		logout = adt_alloc_event(ah, ADT_logout);
       
   151 		if (logout == NULL)
       
   152 			exit(0);
       
   153 
       
   154 		(void) adt_put_event(logout, ADT_SUCCESS, ADT_SUCCESS);
       
   155 
   148 
   156 		adt_free_event(logout);
   149 		adt_free_event(logout);
   157 		exit(0);
   150 		priv_freeset(priv);
   158 	}
   151 		return;
       
   152 	}
       
   153 	if (pid == -1) {
       
   154 		/* failure */
       
   155 
       
   156 		syslog(LOG_AUTH | LOG_ALERT,
       
   157 		    "login audit_logout: could not fork: %m");
       
   158 		adt_free_event(logout);
       
   159 		priv_freeset(priv);
       
   160 		return;
       
   161 	}
       
   162 
       
   163 	/* parent process */
       
   164 
       
   165 	/*
       
   166 	 * When this routine is called, the current working
       
   167 	 * directory is the user's home directory and there are
       
   168 	 * unknown open files. For the waiting process, change the
       
   169 	 * current directory to root and close files so that the
       
   170 	 * user's home directory and anything else can be unmounted
       
   171 	 * if necessary.
       
   172 	 */
       
   173 	if (chdir("/") != 0) {
       
   174 		syslog(LOG_AUTH | LOG_ALERT,
       
   175 		    "login audit_logut: could not chdir /: %m");
       
   176 	}
       
   177 	/*
       
   178 	 * Reduce privileges to just those needed.
       
   179 	 */
       
   180 	priv_emptyset(priv);
       
   181 	if ((priv_addset(priv, PRIV_PROC_AUDIT) != 0) ||
       
   182 	    (setppriv(PRIV_SET, PRIV_PERMITTED, priv) != 0)) {
       
   183 		syslog(LOG_AUTH | LOG_ALERT,
       
   184 		    "login audit_logout: could not reduce privs: %m");
       
   185 	}
       
   186 	closefrom(0);
       
   187 	priv_freeset(priv);
       
   188 	while (pid != waitpid(pid, &status, 0))
       
   189 		continue;
       
   190 
       
   191 	(void) adt_put_event(logout, ADT_SUCCESS, ADT_SUCCESS);
       
   192 	adt_free_event(logout);
       
   193 	(void) adt_end_session(ah);
       
   194 	exit(WEXITSTATUS(status));
   159 }
   195 }
   160 
   196 
   161 /*
   197 /*
   162  * errors are ignored since there is no action to take on error.
   198  * errors are ignored since there is no action to take on error.
   163  *
   199  *