components/openssh/sources/audit-solaris.c
changeset 3513 37c4496b7ed3
child 3834 f1e440f0d185
equal deleted inserted replaced
3508:fdf76823ed00 3513:37c4496b7ed3
       
     1 /*
       
     2  * CDDL HEADER START
       
     3  *
       
     4  * The contents of this file are subject to the terms of the
       
     5  * Common Development and Distribution License (the "License").
       
     6  * You may not use this file except in compliance with the License.
       
     7  *
       
     8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
     9  * or http://www.opensolaris.org/os/licensing.
       
    10  * See the License for the specific language governing permissions
       
    11  * and limitations under the License.
       
    12  *
       
    13  * When distributing Covered Code, include this CDDL HEADER in each
       
    14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
    15  * If applicable, add the following below this CDDL HEADER, with the
       
    16  * fields enclosed by brackets "[]" replaced with your own identifying
       
    17  * information: Portions Copyright [yyyy] [name of copyright owner]
       
    18  *
       
    19  * CDDL HEADER END
       
    20  */
       
    21 
       
    22 /*
       
    23  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
       
    24  */
       
    25 
       
    26 #include "includes.h"
       
    27 #if defined(USE_SOLARIS_AUDIT)
       
    28 
       
    29 #include "audit.h"
       
    30 #include "buffer.h"
       
    31 #include "key.h"
       
    32 #include "hostfile.h"
       
    33 #include "auth.h"
       
    34 #include "log.h"
       
    35 #include "packet.h"
       
    36 
       
    37 #include <errno.h>
       
    38 #include <pwd.h>
       
    39 #include <string.h>
       
    40 
       
    41 #include <bsm/adt.h>
       
    42 #include <bsm/adt_event.h>
       
    43 
       
    44 #ifdef	ADT_DEBUG
       
    45 #include <bsm/audit.h>
       
    46 #include <arpa/inet.h>
       
    47 #include <netinet/in.h>
       
    48 #include <values.h>
       
    49 #include <errno.h>
       
    50 #include <pwd.h>
       
    51 #include <stdio.h>
       
    52 #include <stdarg.h>
       
    53 #include <string.h>
       
    54 #include <ucred.h>
       
    55 #include <values.h>
       
    56 
       
    57 #include <bsm/adt.h>
       
    58 #include <bsm/audit.h>
       
    59 
       
    60 #include <sys/types.h>
       
    61 #include <sys/stat.h>
       
    62 
       
    63 /* semi private adt functions to extract information */
       
    64 
       
    65 extern void adt_get_asid(const adt_session_data_t *, au_asid_t *);
       
    66 extern void adt_get_auid(const adt_session_data_t *, au_id_t *);
       
    67 extern void adt_get_mask(const adt_session_data_t *, au_mask_t *);
       
    68 extern void adt_get_termid(const adt_session_data_t *, au_tid_addr_t *);
       
    69 
       
    70 extern void __auditd_debug(char *, ...);
       
    71 
       
    72 void
       
    73 __audit_pidinfo(void)
       
    74 {
       
    75 	adt_session_data_t *ah = NULL;
       
    76 	au_id_t	auid;
       
    77 	char *auid_name = "badname";
       
    78 	struct passwd *pwd;
       
    79 	au_asid_t asid;
       
    80 	au_mask_t mask;
       
    81 	char flags[512];
       
    82 	au_tid_addr_t tid;
       
    83 	char	pbuf[INET6_ADDRSTRLEN];
       
    84 	int	af = AF_INET;
       
    85 	int	remote;
       
    86 	int	local;
       
    87 
       
    88 	if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
       
    89 		__auditd_debug("cannot start session %s\n", strerror(errno));
       
    90 		return;
       
    91 	}
       
    92 	if (ah == NULL) {
       
    93 		__auditd_debug("ah is NULL\n");
       
    94 		return;
       
    95 	}
       
    96 	adt_get_auid(ah, &auid);
       
    97 	if ((pwd = getpwuid((uid_t)auid)) != NULL) {
       
    98 		auid_name = pwd->pw_name;
       
    99 	}
       
   100 	__auditd_debug("audit id = %s(%d)\n", auid_name, auid);
       
   101 
       
   102 	adt_get_mask(ah, &mask);
       
   103 	if (getauditflagschar(flags, &mask, NULL) < 0) {
       
   104 		(void) strlcpy(flags, "badflags", sizeof (flags));
       
   105 	}
       
   106 #ifdef	_LP64
       
   107 	__auditd_debug("preselection mask = %s(0x%lx,0x%lx)\n", flags,
       
   108 	    mask.am_success, mask.am_failure);
       
   109 #else	/* _ILP32 */
       
   110 	__auditd_debug("preselection mask = %s(0x%llx,0x%llx)\n", flags,
       
   111 	    mask.am_success, mask.am_failure);
       
   112 #endif	/* _LP64 */
       
   113 
       
   114 	adt_get_termid(ah, &tid);
       
   115 	__auditd_debug("tid type=%d, maj=%u, min=%u, addr=%x:%x:%x:%x\n",
       
   116 	    tid.at_type,
       
   117 	    (uint16_t)((tid.at_port) >> BITS(uint16_t)),
       
   118 	    (uint16_t)(tid.at_port & UINT16_MAX),
       
   119 	    tid.at_addr[0],
       
   120 	    tid.at_addr[1],
       
   121 	    tid.at_addr[2],
       
   122 	    tid.at_addr[3]);
       
   123 	if (tid.at_type == AU_IPv6) {
       
   124 		af = AF_INET6;
       
   125 	}
       
   126 	(void) inet_ntop(af, (void *)(tid.at_addr), pbuf,
       
   127 	    sizeof (pbuf));
       
   128 	remote = (tid.at_port >> BITS(uint16_t));
       
   129 	local = (tid.at_port & UINT16_MAX);
       
   130 	__auditd_debug("tid type-%d (remote,local,host)= %u,%u,%s\n",
       
   131 	    tid.at_type, remote, local, pbuf);
       
   132 	adt_get_asid(ah, &asid);
       
   133 	__auditd_debug("audit session id = %u\n",  asid);
       
   134 	(void) adt_end_session(ah);
       
   135 }
       
   136 #else	/* !ADT_DEBUG */
       
   137 /*ARGSUSED*/
       
   138 /*PRINTFLIKE1*/
       
   139 static void
       
   140 __auditd_debug(char *fmt, ...)
       
   141 {
       
   142 }
       
   143 static void
       
   144 __audit_pidinfo()
       
   145 {
       
   146 }
       
   147 #endif	/* ADT_DEBUG */
       
   148 
       
   149 #include <security/pam_appl.h>
       
   150 
       
   151 #include <sys/types.h>
       
   152 
       
   153 extern Authctxt *the_authctxt;
       
   154 
       
   155 extern const char *audit_username(void);
       
   156 extern const char *audit_event_lookup(ssh_audit_event_t);
       
   157 
       
   158 static adt_session_data_t *ah = NULL;		/* audit session handle */
       
   159 static adt_termid_t	*tid = NULL;		/* peer terminal id */
       
   160 
       
   161 static void audit_login(void);
       
   162 static void audit_logout(void);
       
   163 static void audit_fail(int);
       
   164 
       
   165 /* Below is the sshd audit API Solaris adt interpretation */
       
   166 
       
   167 /*
       
   168  * Called after a connection has been accepted but before any authentication
       
   169  * has been attempted.
       
   170  */
       
   171 /* ARGSUSED */
       
   172 void
       
   173 audit_connection_from(const char *host, int port)
       
   174 {
       
   175 	int peer = packet_get_connection_in();
       
   176 	adt_session_data_t	*ah;
       
   177 
       
   178 	if (adt_load_termid(peer, &tid) != 0) {
       
   179 		error("adt audit_connection_from: unable to load tid for %d:%s",
       
   180 		    peer, strerror(errno));
       
   181 	}
       
   182 	if (adt_start_session(&ah, NULL, 0) != 0) {
       
   183 		error("adt audit_connection_from: unable to start session "
       
   184 		    "for %s:%d:%s", host, port, strerror(errno));
       
   185 	}
       
   186 	if (adt_set_user(ah, ADT_NO_AUDIT, ADT_NO_AUDIT, 0,
       
   187 	    ADT_NO_AUDIT, tid, ADT_SETTID) != 0) {
       
   188 		error("adt audit_connection_from: unable to set user "
       
   189 		    "for %s:%d:%s", host, port, strerror(errno));
       
   190 		(void) adt_end_session(ah);
       
   191 		ah = NULL;
       
   192 	}
       
   193 	if (adt_set_proc(ah) != 0) {
       
   194 		error("adt audit_connection_from: unable to set proc "
       
   195 		    "for %s:%d:%s", host, port, strerror(errno));
       
   196 	}
       
   197 	(void) adt_end_session(ah);
       
   198 	debug("adt audit_connection_from(%s, %d): peerfd=%d", host, port,
       
   199 	    peer);
       
   200 	__auditd_debug("%d/%d:%d-adt audit_connection_from(%s, %d)ctxt=%p: "
       
   201 	    "peerfd=%d\n", getpid(), getuid(), geteuid(), host, port,
       
   202 	    (void *)the_authctxt, peer);
       
   203 	__audit_pidinfo();
       
   204 }
       
   205 
       
   206 /*
       
   207  * Called when various events occur (see audit.h for a list of possible
       
   208  * events and what they mean).
       
   209  *
       
   210  *	Entry	the_authcntxt
       
   211  */
       
   212 void
       
   213 audit_event(ssh_audit_event_t event)
       
   214 {
       
   215 	static boolean_t logged_in = B_FALSE;	/* if user did login */
       
   216 	int fail = PAM_IGNORE;		/* default unset */
       
   217 	static boolean_t did_maxtries = B_FALSE; /* if interactive and abort */
       
   218 
       
   219 	debug("adt audit_event(%s)", audit_event_lookup(event));
       
   220 	__auditd_debug("%d/%d:%d-adt audit_event(%s/%s)ctxt=%p\n",
       
   221 	    getpid(), getuid(), geteuid(), audit_event_lookup(event),
       
   222 	    audit_username(), (void *)the_authctxt);
       
   223 	__audit_pidinfo();
       
   224 
       
   225 	switch (event) {
       
   226 	case SSH_AUTH_SUCCESS:		/* authentication success */
       
   227 		logged_in = B_TRUE;
       
   228 		audit_login(); 		/* ADT_ssh; */
       
   229 		return;
       
   230 
       
   231 	case SSH_CONNECTION_CLOSE:	/* connection closed, all done */
       
   232 		if (logged_in) {
       
   233 			audit_logout();		/* ADT_logout; */
       
   234 			logged_in = B_FALSE;
       
   235 		} else {
       
   236 			error("adt audit_event logout without login");
       
   237 		}
       
   238 		return;
       
   239 
       
   240 	/* Translate fail events to Solaris PAM errors */
       
   241 
       
   242 	/* auth2.c: userauth_finish as audit_event(SSH_LOGIN_EXCEED_MAXTRIES) */
       
   243 	/* auth1.c:do_authloop audit_event(SSH_LOGIN_EXCEED_MAXTRIES) */
       
   244 	case SSH_LOGIN_EXCEED_MAXTRIES:
       
   245 		fail = PAM_MAXTRIES;
       
   246 		did_maxtries = B_TRUE;
       
   247 		break;
       
   248 
       
   249 	/* auth2.c: userauth_finish as audit_event(SSH_LOGIN_ROOT_DENIED) */
       
   250 	/* auth1.c:do_authloop audit_event(SSH_LOGIN_ROOT_DENIED) */
       
   251 	case SSH_LOGIN_ROOT_DENIED:
       
   252 		fail = PAM_PERM_DENIED;
       
   253 		break;
       
   254 
       
   255 	/* auth2.c: input_userauth_request as audit_event(SSH_INVALID_USER) */
       
   256 	/* auth.c: getpwnamallow as audit_event(SSH_INVALID_USER) */
       
   257 	case SSH_INVALID_USER:
       
   258 		fail = PAM_USER_UNKNOWN;
       
   259 		break;
       
   260 
       
   261 	/* seems unused, but translate to the Solaris PAM error */
       
   262 	case SSH_NOLOGIN:
       
   263 		fail = PAM_LOGINS_DISABLED;
       
   264 		break;
       
   265 
       
   266 	/*
       
   267 	 * auth.c in auth_log as it's walking through methods calls
       
   268 	 * audit_classify_method(method) which maps
       
   269 	 *
       
   270 	 * none		-> SSH_AUTH_FAIL_NONE
       
   271 	 * password	-> SSH_AUTH_FAIL_PASSWD
       
   272 	 *
       
   273 	 * publickey	-> SSH_AUTH_FAIL_PUBKEY
       
   274 	 * rsa		-> SSH_AUTH_FAIL_PUBKEY
       
   275 	 *
       
   276 	 * keyboard-interactive	-> SSH_AUTH_FAIL_KBDINT
       
   277 	 * challenge-response	-> SSH_AUTH_FAIL_KBDINT
       
   278 	 *
       
   279 	 * hostbased	-> SSH_AUTH_FAIL_HOSTBASED
       
   280 	 * rhosts-rsa	-> SSH_AUTH_FAIL_HOSTBASED
       
   281 	 *
       
   282 	 * gssapi-with-mic	-> SSH_AUTH_FAIL_GSSAPI
       
   283 	 *
       
   284 	 * unknown method	-> SSH_AUDIT_UNKNOWN
       
   285 	 */
       
   286 	/*
       
   287 	 * see mon_table mon_dispatch_proto20[], mon_dispatch_postauth20[],
       
   288 	 * mon_dispatch_proto15[], mon_dispatch_postauth15[]:
       
   289 	 * MONITOR_REQ_AUDIT_EVENT
       
   290 	 * called from monitor.c:mm_answer_audit_event()
       
   291 	 * SSH_AUTH_FAIL_PUBKEY, SSH_AUTH_FAIL_HOSTBASED,
       
   292 	 * SSH_AUTH_FAIL_GSSAPI, SSH_LOGIN_EXCEED_MAXTRIES,
       
   293 	 * SSH_LOGIN_ROOT_DENIED, SSH_CONNECTION_CLOSE SSH_INVALID_USER
       
   294 	 * monitor_wrap.c: mm_audit_event()
       
   295 	 */
       
   296 	case SSH_AUTH_FAIL_NONE:	/* auth type none */
       
   297 	case SSH_AUTH_FAIL_PUBKEY:	/* authtype publickey */
       
   298 		break;
       
   299 
       
   300 	case SSH_AUTH_FAIL_PASSWD:	/* auth type password */
       
   301 	case SSH_AUTH_FAIL_KBDINT:	/* authtype keyboard-interactive */
       
   302 	case SSH_AUTH_FAIL_HOSTBASED:	/* auth type hostbased */
       
   303 	case SSH_AUTH_FAIL_GSSAPI:	/* auth type gssapi-with-mic */
       
   304 	case SSH_AUDIT_UNKNOWN:		/* auth type unknown */
       
   305 		fail = PAM_AUTH_ERR;
       
   306 		break;
       
   307 
       
   308 	/* sshd.c: cleanup_exit: server specific fatal cleanup */
       
   309 	case SSH_CONNECTION_ABANDON:	/* bailing with fatal error */
       
   310 		/*
       
   311 		 * This seems to occur with OpenSSH client when
       
   312 		 * the user login shell exits.
       
   313 		 */
       
   314 		if (logged_in) {
       
   315 			audit_logout();		/* ADT_logout; */
       
   316 			logged_in = B_FALSE;
       
   317 			return;
       
   318 		} else if (!did_maxtries) {
       
   319 			fail = PAM_AUTHINFO_UNAVAIL;
       
   320 		} else {
       
   321 			/* reset saw max tries */
       
   322 			did_maxtries = FALSE;
       
   323 		}
       
   324 		break;
       
   325 
       
   326 	default:
       
   327 		error("adt audit_event: unknown event %d", event);
       
   328 		__auditd_debug("%d/%d:%d-unknown event %d",
       
   329 		    getpid(), getuid(), geteuid(), event);
       
   330 		__audit_pidinfo();
       
   331 		break;
       
   332 	}
       
   333 	audit_fail(fail);
       
   334 }
       
   335 
       
   336 /*
       
   337  * Called when a user session is started.  Argument is the tty allocated to
       
   338  * the session, or NULL if no tty was allocated.
       
   339  *
       
   340  * Note that this may be called multiple times if multiple sessions are used
       
   341  * within a single connection.
       
   342  */
       
   343 /* ARGSUSED */
       
   344 void
       
   345 audit_session_open(struct logininfo *li)
       
   346 {
       
   347 	const char *t = li->line ? li->line : "(no tty)";
       
   348 
       
   349 	debug("adt audit_session_open: user=%s:tty=%s", audit_username(),
       
   350 	    t);
       
   351 	__auditd_debug("%d/%d:%d-adt audit_session_open:ctxt=%p "
       
   352 	    "user=%s:tty=%s\n", getpid(), getuid(), geteuid(),
       
   353 	    (void *)the_authctxt, audit_username(), t);
       
   354 	__audit_pidinfo();
       
   355 }
       
   356 
       
   357 /*
       
   358  * Called when a user session is closed.  Argument is the tty allocated to
       
   359  * the session, or NULL if no tty was allocated.
       
   360  *
       
   361  * Note that this may be called multiple times if multiple sessions are used
       
   362  * within a single connection.
       
   363  */
       
   364 /* ARGSUSED */
       
   365 void
       
   366 audit_session_close(struct logininfo *li)
       
   367 {
       
   368 	const char *t = li->line ? li->line : "(no tty)";
       
   369 
       
   370 	debug("adt audit_session_close: user=%s:tty=%s", audit_username(),
       
   371 	    t);
       
   372 	__auditd_debug("%d/%d:%d-adt audit_session_close:ctxt=%p "
       
   373 	    "user=%s:tty=%s\n", getpid(), getuid(), geteuid(),
       
   374 	    (void *)the_authctxt, audit_username(), t);
       
   375 	__audit_pidinfo();
       
   376 }
       
   377 
       
   378 /*
       
   379  * This will be called when a user runs a non-interactive command.  Note that
       
   380  * it may be called multiple times for a single connection since SSH2 allows
       
   381  * multiple sessions within a single connection.
       
   382  */
       
   383 /* ARGSUSED */
       
   384 void
       
   385 audit_run_command(const char *command)
       
   386 {
       
   387 	debug("adt audit_run_command: \"%s\"", command);
       
   388 	__auditd_debug("%d/%d:%d-adt audit_run_command:ctxt=%p \"%s\"\n",
       
   389 	    getpid(), getuid(), geteuid(), (void *)the_authctxt, command);
       
   390 	__audit_pidinfo();
       
   391 }
       
   392 
       
   393 /*
       
   394  * audit_login - audit successful login
       
   395  *
       
   396  *	Entry	the_authctxt should be valid ;-)
       
   397  *		and pam_setcred called.
       
   398  *		adt_info &  ADT_INFO_PW_SUCCESS if successful
       
   399  *		password change.
       
   400  *
       
   401  *	Exit	ah = audit session established for audit_logout();
       
   402  */
       
   403 static void
       
   404 audit_login(void)
       
   405 {
       
   406 	adt_event_data_t *event;
       
   407 	uid_t uid = ADT_NO_ATTRIB;
       
   408 	gid_t gid = (gid_t)ADT_NO_ATTRIB;
       
   409 	au_id_t	auid;
       
   410 
       
   411 	if ((the_authctxt != NULL) && (the_authctxt->valid != 0)) {
       
   412 		uid = the_authctxt->pw->pw_uid;
       
   413 		gid = the_authctxt->pw->pw_gid;
       
   414 	}
       
   415 
       
   416 	if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
       
   417 		error("adt_start_session: %s", strerror(errno));
       
   418 		return;
       
   419 	}
       
   420 
       
   421 	adt_get_auid(ah, &auid);
       
   422 
       
   423 	if (adt_set_user(ah, uid, gid, uid, gid, NULL,
       
   424 	    auid == AU_NOAUDITID ? ADT_NEW : ADT_USER)) {
       
   425 		error("adt_set_user auid=%d, uid=%d", auid, uid);
       
   426 		(void) adt_end_session(ah);
       
   427 		ah = NULL;
       
   428 		free(tid);
       
   429 		tid = NULL;
       
   430 		return;
       
   431 	}
       
   432 	if ((event = adt_alloc_event(ah, ADT_ssh)) == NULL) {
       
   433 		error("adt_alloc_event(ADT_ssh): %s", strerror(errno));
       
   434 		return;
       
   435 	}
       
   436 	if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
       
   437 		error("adt_put_event(ADT_ssh, ADT_SUCCESS): %s",
       
   438 		    strerror(errno));
       
   439 	}
       
   440 	/* should audit successful password change here */
       
   441 	adt_free_event(event);
       
   442 }
       
   443 
       
   444 /*
       
   445  * audit_logout - audit the logout
       
   446  *
       
   447  *	Entry	ah = audit session.
       
   448  */
       
   449 static void
       
   450 audit_logout(void)
       
   451 {
       
   452 	adt_event_data_t *event;
       
   453 
       
   454 	if ((event = adt_alloc_event(ah, ADT_logout)) == NULL) {
       
   455 		error("adt_alloc_event(ADT_logout): %s", strerror(errno));
       
   456 		return;
       
   457 	}
       
   458 	if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
       
   459 		error("adt_put_event(ADT_logout, ADT_SUCCESS): %s",
       
   460 		    strerror(errno));
       
   461 	}
       
   462 	adt_free_event(event);
       
   463 	(void) adt_end_session(ah);
       
   464 	ah = NULL;
       
   465 	free(tid);
       
   466 	tid = NULL;
       
   467 }
       
   468 
       
   469 /*
       
   470  * audit_fail - audit login failure.
       
   471  *
       
   472  *	Entry	the_authctxt assumed to have some info.
       
   473  *			user = user who asked to be authenticated.
       
   474  *		tid = connection audit TID set by audit_connect_from();
       
   475  *
       
   476  *	N.B.	pam_strerror() prototype takes a pam handle and error number.
       
   477  *		At least on Solaris, pam_strerror never uses the pam handle.
       
   478  *		Since there doesn't seem to be a pam handle available, this
       
   479  *		code just uses NULL.
       
   480  */
       
   481 static void
       
   482 audit_fail(int pamerr)
       
   483 {
       
   484 	adt_session_data_t *ah = NULL;
       
   485 	adt_event_data_t *event;
       
   486 	uid_t	uid = ADT_NO_ATTRIB;
       
   487 	gid_t	gid = (gid_t)ADT_NO_ATTRIB;
       
   488 
       
   489 	__auditd_debug("%d/%d:%d-audit_fail(%s) ctxt=%p\n",
       
   490 	    getpid(), getuid(), geteuid(), pam_strerror(NULL, pamerr),
       
   491 	    (void *)the_authctxt);
       
   492 	if (the_authctxt != NULL) {
       
   493 		__auditd_debug("valid=%d, user=%s, uid=%d\n",
       
   494 		    the_authctxt->valid, the_authctxt->user,
       
   495 		    the_authctxt->pw->pw_uid);
       
   496 	} else {
       
   497 		__auditd_debug("\tNo autxctxt\n");
       
   498 	}
       
   499 	__audit_pidinfo();
       
   500 	if (pamerr == PAM_IGNORE) {
       
   501 		return;
       
   502 	}
       
   503 	if ((the_authctxt != NULL) || (the_authctxt->valid != 0)) {
       
   504 		uid = the_authctxt->pw->pw_uid;
       
   505 		gid = the_authctxt->pw->pw_gid;
       
   506 	} else if ((the_authctxt != NULL) || (the_authctxt->user != NULL)) {
       
   507 		struct passwd *pw;
       
   508 
       
   509 		if ((pw = getpwnam(the_authctxt->user)) != NULL) {
       
   510 			uid = pw->pw_uid;
       
   511 			gid = pw->pw_gid;
       
   512 		}
       
   513 	}
       
   514 	if (adt_start_session(&ah, NULL, 0) != 0) {
       
   515 		error("adt_start_session(ADT_ssh, 0, fail=%s):"
       
   516 		    " %s", pam_strerror(NULL, pamerr), strerror(errno));
       
   517 		__auditd_debug("%d/%d:%d-adt_start_session(ADT_ssh, "
       
   518 		    "PROC_DATA, fail=%s): %s", getpid(), getuid(),
       
   519 		    geteuid(), pam_strerror(NULL, pamerr),
       
   520 		    strerror(errno));
       
   521 		return;
       
   522 	}
       
   523 	__auditd_debug("%d/%d:%d-audit_fail+start_session() ah=%p\n",
       
   524 	    getpid(), getuid(), geteuid(), (void *)ah);
       
   525 	if (adt_set_user(ah, uid, gid, uid, gid, tid, ADT_NEW) != 0) {
       
   526 		error("adt_set_user(ADT_ssh, PROC_DATA, fail=%s): %s",
       
   527 		    pam_strerror(NULL, pamerr), strerror(errno));
       
   528 		__auditd_debug("%d/%d:%d-adt_set_user(ADT_ssh, "
       
   529 		    "PROC_DATA, fail=%s): %s", getpid(), getuid(),
       
   530 		    geteuid(), pam_strerror(NULL, pamerr),
       
   531 		    strerror(errno));
       
   532 		goto done;
       
   533 	}
       
   534 	__auditd_debug("%d/%d:%d-audit_fail+set_user() ah=%p\n", getpid(),
       
   535 	    getuid(), geteuid(), (void *)ah);
       
   536 	if ((event = adt_alloc_event(ah, ADT_ssh)) == NULL) {
       
   537 		error("adt_alloc_event(ADT_ssh, fail=%s): %s",
       
   538 		    pam_strerror(NULL, pamerr), strerror(errno));
       
   539 		__auditd_debug("%d/%d:%d-adt_set_user(ADT_ssh, 0, "
       
   540 		    "fail=%s): %s", getpid(), getuid(), geteuid(),
       
   541 		    pam_strerror(NULL, pamerr), strerror(errno));
       
   542 	} else if (adt_put_event(event, ADT_FAILURE,
       
   543 	    ADT_FAIL_PAM + pamerr) != 0) {
       
   544 		error("adt_put_event(ADT_ssh, fail=%s): %s",
       
   545 		    pam_strerror(NULL, pamerr), strerror(errno));
       
   546 		__auditd_debug("%d/%d:%d-adt_put_event(ADT_ssh, fail=%s): %s",
       
   547 		    getpid(), getuid(), geteuid(), pam_strerror(NULL, pamerr),
       
   548 		    strerror(errno));
       
   549 	}
       
   550 	__auditd_debug("%d/%d:%d-audit_fail+put_event() ah=%p\n", getpid(),
       
   551 	    getuid(), geteuid(), (void *)ah);
       
   552 	/* should audit authentication with failed password change here. */
       
   553 	adt_free_event(event);
       
   554 done:
       
   555 	(void) adt_end_session(ah);
       
   556 }
       
   557 #endif	/* USE_SOLARIS_AUDIT */