From owner-trustedbsd-audit@FreeBSD.ORG Tue Feb 14 17:28:15 2006 Return-Path: X-Original-To: trustedbsd-audit@FreeBSD.org Delivered-To: trustedbsd-audit@FreeBSD.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 217A816A43E for ; Tue, 14 Feb 2006 17:28:15 +0000 (GMT) (envelope-from csjp@FreeBSD.org) Received: from ems01.seccuris.com (ems01.seccuris.com [204.112.0.35]) by mx1.FreeBSD.org (Postfix) with SMTP id 9678B43D46 for ; Tue, 14 Feb 2006 17:28:14 +0000 (GMT) (envelope-from csjp@FreeBSD.org) Received: (qmail 63290 invoked by uid 0); 14 Feb 2006 17:32:21 -0000 Received: from unknown (HELO ?192.168.11.101?) (unknown) by unknown with SMTP; 14 Feb 2006 17:32:21 -0000 Message-ID: <43F2132D.6090401@FreeBSD.org> Date: Tue, 14 Feb 2006 11:28:13 -0600 From: "Christian S.J. Peron" User-Agent: Mozilla Thunderbird 1.0.7 (Macintosh/20050923) X-Accept-Language: en-us, en MIME-Version: 1.0 To: trustedbsd-audit@FreeBSD.org Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Mailman-Approved-At: Tue, 14 Feb 2006 18:14:47 +0000 Subject: Solaris su audit failures non fatal X-BeenThere: trustedbsd-audit@FreeBSD.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: TrustedBSD Audit Discussion List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 14 Feb 2006 17:28:15 -0000 All, Here is a recent su(1) submit I did. I basically tried to make it follow Sun's behaviour during audit failures, but I am wondering: If auditing an event fails, shouldn't the event be fatal? Doesn't CAPP require that if an event fails to be audited, it shouldn't happen? Here is the commit log: http://perforce.freebsd.org/chv.cgi?CH=91725 Change 91725 by csjp@csjp_xor on 2006/02/14 04:57:23 - Remove some more audits around PAM failures which really wouldn't be a result of the user input - Implement stdargs to audit_su() so we can specify messages which will be used to create text tokens to give more verbose information for the nature of the failures or success. - Add strings to audi_su() calls for text tokens - The user must never know about auditing operations. So change any writes to stderr to syslog(3) calls and simply return. It should be noted that this is what Solaris is doing, however CAPP is pretty clear about failed audits having to result in a failed operation. That said, I am not sure what an appropriate error message would be to report to the user in the event that we have to abort the entire operation due to a audit failure. Thoughts? Discussed with: wsalamon Affected files ... .. //depot/projects/trustedbsd/audit3/usr.bin/su/su.c#8 edit Differences ... ==== //depot/projects/trustedbsd/audit3/usr.bin/su/su.c#8 (text+ko) ==== @@ -96,6 +96,7 @@ #include #include #include +#include #include #include @@ -144,7 +145,7 @@ static void usage(void) __dead2; static void export_pam_environment(void); static int ok_to_export(const char *); -static void audit_su(au_id_t, int); +static void audit_su(au_id_t, int, const char *, ...); extern char **environ; @@ -219,7 +220,7 @@ if (strlen(user) > MAXLOGNAME - 1) { #ifdef USE_BSM_AUDIT - audit_su(getuid(), AUDIT_SU_FAILURE); + audit_su(getuid(), AUDIT_SU_FAILURE, "username too long"); #endif errx(1, "username too long"); } @@ -252,7 +253,8 @@ pwd = getpwuid(ruid); if (pwd == NULL) { #ifdef USE_BSM_AUDIT - audit_su(getuid(), AUDIT_SU_FAILURE); + audit_su(getuid(), AUDIT_SU_FAILURE, + "unable to determain invoking subject"); #endif errx(1, "who are you?"); } @@ -278,9 +280,6 @@ /* Do the whole PAM startup thing */ retcode = pam_start("su", user, &conv, &pamh); if (retcode != PAM_SUCCESS) { -#ifdef USE_BSM_AUDIT - audit_su(getuid(), AUDIT_SU_FAILURE); -#endif syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, retcode)); errx(1, "pam_start: %s", pam_strerror(pamh, retcode)); } @@ -295,14 +294,15 @@ retcode = pam_authenticate(pamh, 0); if (retcode != PAM_SUCCESS) { #ifdef USE_BSM_AUDIT - audit_su(ruid, AUDIT_SU_FAILURE); + audit_su(ruid, AUDIT_SU_FAILURE, "bad su %s to %s on %s", + username, user, mytty); #endif syslog(LOG_AUTH|LOG_WARNING, "BAD SU %s to %s on %s", username, user, mytty); errx(1, "Sorry"); } #ifdef USE_BSM_AUDIT - audit_su(ruid, AUDIT_SU_SUCCESS); + audit_su(ruid, AUDIT_SU_SUCCESS, "successful authentication"); #endif retcode = pam_get_item(pamh, PAM_USER, (const void **)&p); if (retcode == PAM_SUCCESS) @@ -313,7 +313,8 @@ pwd = getpwnam(user); if (pwd == NULL) { #ifdef USE_BSM_AUDIT - audit_su(getuid(), AUDIT_SU_FAILURE); + audit_su(getuid(), AUDIT_SU_FAILURE, + "unknown subject: %s", user); #endif errx(1, "unknown login: %s", user); } @@ -323,17 +324,20 @@ retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); if (retcode != PAM_SUCCESS) { +#ifdef USE_BSM_AUDIT + audit_su(getuid(), AUDIT_SU_FAILURE, + "pam_chauthtok: %s", + pam_strerror(pamh, retcode)); +#endif syslog(LOG_ERR, "pam_chauthtok: %s", pam_strerror(pamh, retcode)); -#ifdef USE_BSM_AUDIT - audit_su(getuid(), AUDIT_SU_FAILURE); -#endif errx(1, "Sorry"); } } if (retcode != PAM_SUCCESS) { #ifdef USE_BSM_AUDIT - audit_su(getuid(), AUDIT_SU_FAILURE); + audit_su(getuid(), AUDIT_SU_FAILURE, "pam_acct_mgmt: %s", + pam_strerror(pamh, retcode)); #endif syslog(LOG_ERR, "pam_acct_mgmt: %s", pam_strerror(pamh, retcode)); @@ -346,15 +350,13 @@ else { if (ruid != 0) { #ifdef USE_BSM_AUDIT - audit_su(getuid(), AUDIT_SU_FAILURE); + audit_su(getuid(), AUDIT_SU_FAILURE, + "only root may use -c"); #endif errx(1, "only root may use -c"); } lc = login_getclass(class); if (lc == NULL) { -#ifdef USE_BSM_AUDIT - audit_su(getuid(), AUDIT_SU_FAILURE); -#endif errx(1, "unknown class: %s", class); } } @@ -362,9 +364,6 @@ /* if asme and non-standard target shell, must be root */ if (asme) { if (ruid != 0 && !chshell(pwd->pw_shell)) { -#ifdef USE_BSM_AUDIT - audit_su(getuid(), AUDIT_SU_FAILURE); -#endif errx(1, "permission denied (shell)"); } } @@ -391,9 +390,6 @@ /* Switch to home directory */ if (asthem) { if (chdir(pwd->pw_dir) < 0) { -#ifdef USE_BSM_AUDIT - audit_su(getuid(), AUDIT_SU_FAILURE); -#endif errx(1, "no directory"); } } @@ -403,17 +399,11 @@ * initialize them first. */ if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETGROUP) < 0) { -#ifdef USE_BSM_AUDIT - audit_su(getuid(), AUDIT_SU_FAILURE); -#endif err(1, "setusercontext"); } retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED); if (retcode != PAM_SUCCESS) { -#ifdef USE_BSM_AUDIT - audit_su(getuid(), AUDIT_SU_FAILURE); -#endif syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, retcode)); errx(1, "failed to establish credentials."); @@ -421,9 +411,6 @@ if (asthem) { retcode = pam_open_session(pamh, 0); if (retcode != PAM_SUCCESS) { -#ifdef USE_BSM_AUDIT - audit_su(getuid(), AUDIT_SU_FAILURE); -#endif syslog(LOG_ERR, "pam_open_session: %s", pam_strerror(pamh, retcode)); errx(1, "failed to open session."); @@ -512,9 +499,6 @@ if ((asme || (!asthem && class == NULL)) && pwd->pw_uid) setwhat &= ~(LOGIN_SETPRIORITY | LOGIN_SETRESOURCES); if (setusercontext(lc, pwd, pwd->pw_uid, setwhat) < 0) { -#ifdef USE_BSM_AUDIT - audit_su(getuid(), AUDIT_SU_FAILURE); -#endif err(1, "setusercontext"); } @@ -647,13 +631,15 @@ #ifdef USE_BSM_AUDIT static void -audit_su(au_id_t au_ctx, int what) +audit_su(au_id_t au_ctx, int what, const char *fmt, ...) { token_t *token; long acond; int afd; au_tid_t termid; pid_t pid; + char text[1024]; + va_list ap; if (auditon(A_GETCOND, &acond, sizeof(long)) < 0) { /* @@ -662,20 +648,40 @@ */ if (errno == ENOSYS) return; - err(1, "auditon failed"); + syslog(LOG_AUTH | LOG_ERR, "audit: auditon failed: %s", + strerror(errno)); + return; } afd = au_open(); - if (afd < 0) - err(1, "au_open failed"); + if (afd < 0) { + syslog(LOG_AUTH | LOG_ERR, "au_open failed: %s", + strerror(errno)); + return; + } /* XXX what should we do for termid? */ bzero(&termid, sizeof(termid)); pid = getpid(); token = au_to_subject32(au_ctx, geteuid(), getegid(), getuid(), getgid(), pid, pid, &termid); - if (token == NULL) - errx(1, "audit: unable to build subject token"); + if (token == NULL) { + syslog(LOG_AUTH | LOG_ERR, + "audit: unable to build subject token"); + return; + } /* XXX what if au_fails? */ (void) au_write(afd, token); + if (fmt != NULL) { + va_start(ap, fmt); + vsnprintf(&text[0], sizeof(text) - 1, fmt, ap); + va_end(ap); + token = au_to_text(&text[0]); + if (token == NULL) { + syslog(LOG_AUTH | LOG_ERR, + "failed to generate text token"); + return; + } + (void) au_write(afd, token); + } switch (what) { case AUDIT_SU_FAILURE: token = au_to_return32(1, EPERM); @@ -684,10 +690,13 @@ token = au_to_return32(0, 0); break; } - if (token == NULL) - errx(1, "audit: unable to build return32 token"); + if (token == NULL) { + syslog(LOG_AUTH | LOG_ERR, + "audit: enable to build return token"); + return; + } (void) au_write(afd, token); - if (au_close(afd, 1, AUE_su) < 0) - errx(1, "audit: record not committed"); + if (au_close(afd, 1, AUE_su) < 0) + syslog(LOG_AUTH | LOG_ERR, "audit: record not committed"); } #endif -- Christian S.J. Peron csjp@FreeBSD.ORG FreeBSD Committer FreeBSD Security Team