|
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 */ |