Date: Wed, 24 Nov 2004 02:48:16 GMT From: Wayne Salamon <wsalamon@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 65760 for review Message-ID: <200411240248.iAO2mGHE093248@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=65760 Change 65760 by wsalamon@rickenbacker on 2004/11/24 02:47:47 Add auditing to login, which is required to set up the user process audit state. Update the man page to include audit info for login. Affected files ... .. //depot/projects/trustedbsd/audit3/usr.bin/login/Makefile#2 edit .. //depot/projects/trustedbsd/audit3/usr.bin/login/login.1#3 edit .. //depot/projects/trustedbsd/audit3/usr.bin/login/login.c#2 edit Differences ... ==== //depot/projects/trustedbsd/audit3/usr.bin/login/Makefile#2 (text+ko) ==== @@ -5,7 +5,7 @@ SRCS= login.c login_fbtab.c CFLAGS+=-DLOGALL DPADD= ${LIBUTIL} ${LIBPAM} -LDADD= -lutil ${MINUSLPAM} +LDADD= -lutil -lbsm ${MINUSLPAM} MAN= login.1 login.access.5 .if !defined(NO_SETUID_LOGIN) BINOWN= root ==== //depot/projects/trustedbsd/audit3/usr.bin/login/login.1#3 (text+ko) ==== @@ -124,6 +124,12 @@ Consult the .Xr builtin 1 manual page. +.Pp +The +.Nm +utility will submit an audit record when login succeeds or fails. Failure to +determine the current auditing state will result in an error exit from +.Nm . .Sh FILES .Bl -tag -width ".Pa /etc/login.access" -compact .It Pa /etc/fbtab @@ -143,6 +149,10 @@ .It Pa /etc/pam.d/login .Xr pam 8 configuration file +.It Pa /etc/security/audit_user +user flags for auditing +.It Pa /etc/security/audit_control +global flags for auditing .El .Sh SEE ALSO .Xr builtin 1 , ==== //depot/projects/trustedbsd/audit3/usr.bin/login/login.c#2 (text+ko) ==== @@ -61,6 +61,9 @@ #include <sys/resource.h> #include <sys/wait.h> +#include <bsm/libbsm.h> +#include <bsm/audit_uevents.h> + #include <err.h> #include <errno.h> #include <grp.h> @@ -96,6 +99,8 @@ static void sigint(int); static void timedout(int); static void usage(void); +static void au_success(); +static void au_fail(char *, int); #define TTYGRPNAME "tty" /* group to own ttys */ #define DEFAULT_BACKOFF 3 @@ -155,6 +160,11 @@ static int pam_cred_established; static int pam_session_established; +/* + * Audit data + */ +au_tid_t tid; + int main(int argc, char *argv[]) { @@ -172,6 +182,7 @@ const char *shell = NULL; login_cap_t *lc = NULL; pid_t pid; + char auditsuccess = 1; (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGINT, SIG_IGN); @@ -290,16 +301,19 @@ pam_err = pam_start("login", username, &pamc, &pamh); if (pam_err != PAM_SUCCESS) { pam_syslog("pam_start()"); + au_fail("PAM Error", 1); bail(NO_SLEEP_EXIT, 1); } pam_err = pam_set_item(pamh, PAM_TTY, tty); if (pam_err != PAM_SUCCESS) { pam_syslog("pam_set_item(PAM_TTY)"); + au_fail("PAM Error", 1); bail(NO_SLEEP_EXIT, 1); } pam_err = pam_set_item(pamh, PAM_RHOST, hostname); if (pam_err != PAM_SUCCESS) { pam_syslog("pam_set_item(PAM_RHOST)"); + au_fail("PAM Error", 1); bail(NO_SLEEP_EXIT, 1); } @@ -316,6 +330,7 @@ (uid == (uid_t)0 || uid == (uid_t)pwd->pw_uid)) { /* already authenticated */ rval = 0; + auditsuccess = 0; /* opened a terminal window only */ } else { fflag = 0; (void)setpriority(PRIO_PROCESS, 0, -4); @@ -328,6 +343,12 @@ pam_cleanup(); + /* + * we are not exiting here, but this corresponds to + * a failed login event, so set exitstatus to 1 + */ + au_fail("Login incorrect", 1); + (void)printf("Login incorrect\n"); failures++; @@ -350,6 +371,10 @@ endpwent(); + /* Audit successful login */ + if (auditsuccess) + au_success(); + /* * Establish the login class. */ @@ -746,6 +771,154 @@ return (1); } +/* + * The following tokens are included in the audit record for a successful + * login: + * header + * subject + * return + */ +static void +au_success() +{ + token_t *tok; + int aufd; + au_mask_t aumask; + auditinfo_t auinfo; + uid_t uid = pwd->pw_uid; + gid_t gid = pwd->pw_gid; + pid_t pid = getpid(); + long au_cond; + + /* If we are not auditing, don't cut an audit record; just return */ + if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { + fprintf(stderr, "login: Could not determine audit condition\n"); + exit(1); + } + if (au_cond == AUC_NOAUDIT) + return; + + /* Compute and Set the user's preselection mask */ + if(au_user_mask(pwd->pw_name, &aumask) == -1) { + fprintf(stderr, "login: Could not set audit mask\n"); + exit(1); + } + + /* Set the audit info for the user */ + auinfo.ai_auid = uid; + auinfo.ai_asid = pid; + bcopy(&tid, &auinfo.ai_termid, sizeof(auinfo.ai_termid)); + bcopy(&aumask, &auinfo.ai_mask, sizeof(auinfo.ai_mask)); + if(setaudit(&auinfo) != 0) { + fprintf(stderr, "login: setaudit failed: %s\n", + strerror(errno)); + exit(1); + } + + if((aufd = au_open()) == -1) { + fprintf(stderr, "login: Audit Error: au_open() failed\n"); + exit(1); + } + + /* The subject that is created (euid, egid of the current process) */ + if((tok = au_to_subject32(uid, geteuid(), getegid(), + uid, gid, pid, pid, &tid)) == NULL) { + fprintf(stderr, + "login: Audit Error: au_to_subject32() failed\n"); + exit(1); + } + au_write(aufd, tok); + + if((tok = au_to_return32(0, 0)) == NULL) { + fprintf(stderr, + "login: Audit Error: au_to_return32() failed\n"); + exit(1); + } + au_write(aufd, tok); + + if(au_close(aufd, 1, AUE_login) == -1) { + fprintf(stderr, "login: Audit Record was not committed.\n"); + exit(1); + } +} + +/* + * The following tokens are included in the audit record for failed + * login attempts: + * header + * subject + * text + * return + */ +static void +au_fail(char *errmsg, int na) +{ + token_t *tok; + int aufd; + long au_cond; + uid_t uid; + gid_t gid; + pid_t pid = getpid(); + + /* If we are not auditing, don't cut an audit record; just return */ + if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { + fprintf(stderr, "login: Could not determine audit condition\n"); + exit(1); + } + if (au_cond == AUC_NOAUDIT) + return; + + if((aufd = au_open()) == -1) { + fprintf(stderr, "login: Audit Error: au_open() failed\n"); + exit(1); + } + + if(na) { + /* Non attributable event */ + /* Assuming that login is not called within a user's + * session => auid,asid == -1 */ + if((tok = au_to_subject32(-1, geteuid(), getegid(), -1, -1, + pid, -1, &tid)) == NULL) { + + fprintf(stderr, + "login: Audit Error: au_to_subject32() failed\n"); + exit(1); + } + } + else { + /* we know the subject -- so use its value instead */ + uid = pwd->pw_uid; + gid = pwd->pw_gid; + if((tok = au_to_subject32(uid, geteuid(), getegid(), + uid, gid, pid, pid, &tid)) == NULL) { + fprintf(stderr, + "login: Audit Error: au_to_subject32() failed\n"); + exit(1); + } + } + au_write(aufd, tok); + + /* Include the error message */ + if((tok = au_to_text(errmsg)) == NULL) { + fprintf(stderr, "login: Audit Error: au_to_text() failed\n"); + exit(1); + } + au_write(aufd, tok); + + if((tok = au_to_return32(1, errno)) == NULL) { + fprintf(stderr, + "login: Audit Error: au_to_return32() failed\n"); + exit(1); + } + au_write(aufd, tok); + + if(au_close(aufd, 1, AUE_login) == -1) { + fprintf(stderr, + "login: Audit Error: au_close() was not committed\n"); + exit(1); + } +} + static void usage() {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200411240248.iAO2mGHE093248>