Home | History | Annotate | Download | only in common
      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 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*
     28  * Interfaces to audit_user(4)  (/etc/security/audit_user)
     29  */
     30 
     31 #include <stdio.h>
     32 #include <limits.h>
     33 #include <sys/types.h>
     34 #include <string.h>
     35 #include <bsm/audit.h>
     36 #include <bsm/libbsm.h>
     37 #include <synch.h>
     38 #include <nss_dbdefs.h>
     39 #include <stdlib.h>
     40 
     41 
     42 #define	MAX_USERNAME	32	/* same size as utmpx.ut_user */
     43 
     44 
     45 static char	au_user_fname[PATH_MAX] = AUDITUSERFILE;
     46 static FILE *au_user_file = NULL;
     47 static mutex_t mutex_userfile = DEFAULTMUTEX;
     48 static int use_nsswitch = 1;
     49 static au_user_ent_t *auuserstr2ent(au_user_ent_t *, au_user_str_t *);
     50 
     51 /*
     52  * Externs from libnsl
     53  */
     54 extern void _setauuser(void);
     55 extern void _endauuser(void);
     56 extern au_user_str_t *_getauuserent(au_user_str_t *, char *, int, int *);
     57 extern au_user_str_t *_getauusernam(char *, au_user_str_t *, char *, int,
     58     int *);
     59 
     60 
     61 void
     62 setauuser()
     63 {
     64 	(void) mutex_lock(&mutex_userfile);
     65 	if (use_nsswitch)
     66 		_setauuser();
     67 	else if (au_user_file) {
     68 		(void) fseek(au_user_file, 0L, 0);
     69 	}
     70 	(void) mutex_unlock(&mutex_userfile);
     71 }
     72 
     73 
     74 void
     75 endauuser()
     76 {
     77 	(void) mutex_lock(&mutex_userfile);
     78 	if (use_nsswitch)
     79 		_endauuser();
     80 	else if (au_user_file) {
     81 		(void) fclose(au_user_file);
     82 		au_user_file = NULL;
     83 	}
     84 	(void) mutex_unlock(&mutex_userfile);
     85 }
     86 
     87 au_user_ent_t *
     88 getauuserent()
     89 {
     90 	static au_user_ent_t au_user_entry;
     91 	static char	logname[MAX_USERNAME+1];
     92 
     93 	/* initialize au_user_entry structure */
     94 	au_user_entry.au_name = logname;
     95 
     96 	return (getauuserent_r(&au_user_entry));
     97 
     98 }
     99 
    100 au_user_ent_t *
    101 getauuserent_r(au_user_ent_t *au_user_entry)
    102 {
    103 	int	i, error = 0, found = 0;
    104 	char	*s, input[256];
    105 
    106 
    107 	(void) mutex_lock(&mutex_userfile);
    108 
    109 	if (use_nsswitch) {
    110 		au_user_str_t us;
    111 		au_user_str_t *tmp;
    112 		char buf[NSS_BUFLEN_AUDITUSER];
    113 		int errp = 0;
    114 
    115 		(void) memset(buf, NULL, NSS_BUFLEN_AUDITUSER);
    116 		tmp = _getauuserent(&us, buf, NSS_BUFLEN_AUDITUSER, &errp);
    117 		(void) mutex_unlock(&mutex_userfile);
    118 		return (auuserstr2ent(au_user_entry, tmp));
    119 	}
    120 
    121 	/* open audit user file if it isn't already */
    122 	if (!au_user_file)
    123 		if (!(au_user_file = fopen(au_user_fname, "rF"))) {
    124 			(void) mutex_unlock(&mutex_userfile);
    125 			return (NULL);
    126 		}
    127 
    128 	while (fgets(input, 256, au_user_file)) {
    129 		if (input[0] != '#') {
    130 			s = input + strspn(input, " \t\r\n");
    131 			if ((*s == '\0') || (*s == '#')) {
    132 				continue;
    133 			}
    134 			found = 1;
    135 			s = input;
    136 
    137 			/* parse login name */
    138 			i = strcspn(s, ":");
    139 
    140 			s[i] = '\0';
    141 			(void) strncpy(au_user_entry->au_name, s, MAX_USERNAME);
    142 			s = &s[i+1];
    143 
    144 			/* parse first mask */
    145 			i = strcspn(s, ":");
    146 
    147 			s[i] = '\0';
    148 			if (getauditflagsbin(s,
    149 			    &au_user_entry->au_always) < 0)
    150 				error = 1;
    151 			s = &s[i+1];
    152 
    153 
    154 			/* parse second mask */
    155 
    156 			i = strcspn(s, "\n\0");
    157 
    158 			s[i] = '\0';
    159 			if (getauditflagsbin(s,
    160 			    &au_user_entry->au_never) < 0)
    161 				error = 1;
    162 
    163 
    164 			break;
    165 		}
    166 	}
    167 
    168 	(void) mutex_unlock(&mutex_userfile);
    169 
    170 	if (!error && found) {
    171 		return (au_user_entry);
    172 	} else {
    173 		return (NULL);
    174 	}
    175 }
    176 
    177 
    178 au_user_ent_t *
    179 getauusernam(char *name)
    180 {
    181 	static au_user_ent_t u;
    182 	static char	logname[MAX_USERNAME+1];
    183 
    184 	/* initialize au_user_entry structure */
    185 	u.au_name = logname;
    186 
    187 	return (getauusernam_r(&u, name));
    188 }
    189 
    190 au_user_ent_t *
    191 getauusernam_r(au_user_ent_t *u, char *name)
    192 {
    193 
    194 	if (use_nsswitch) {
    195 		au_user_str_t us;
    196 		au_user_str_t *tmp;
    197 		char buf[NSS_BUFLEN_AUDITUSER];
    198 		int errp = 0;
    199 
    200 		if (name == NULL) {
    201 			return ((au_user_ent_t *)NULL);
    202 		}
    203 		tmp = _getauusernam(name, &us, buf, NSS_BUFLEN_AUDITUSER,
    204 		    &errp);
    205 		return (auuserstr2ent(u, tmp));
    206 	}
    207 	while (getauuserent_r(u) != NULL) {
    208 		if (strcmp(u->au_name, name) == 0) {
    209 			return (u);
    210 		}
    211 	}
    212 	return ((au_user_ent_t *)NULL);
    213 }
    214 
    215 static au_user_ent_t *
    216 auuserstr2ent(au_user_ent_t *ue, au_user_str_t *us)
    217 {
    218 	if (us == NULL)
    219 		return (NULL);
    220 
    221 	if (getauditflagsbin(us->au_always, &ue->au_always) < 0) {
    222 		return (NULL);
    223 	}
    224 	if (getauditflagsbin(us->au_never, &ue->au_never) < 0) {
    225 		ue->au_never.am_success = AU_MASK_NONE;
    226 		ue->au_never.am_failure = AU_MASK_NONE;
    227 	}
    228 	(void) strncpy(ue->au_name, us->au_name, MAX_USERNAME);
    229 	return (ue);
    230 }
    231 
    232 #ifdef DEBUG
    233 void
    234 print_auuser(au_user_ent_t *ue)
    235 {
    236 	char *empty = "empty";
    237 	char *bad = "bad flags";
    238 	char always[256];
    239 	char never[256];
    240 	int retval;
    241 
    242 	if (ue == NULL) {
    243 		printf("NULL\n");
    244 		return;
    245 	}
    246 
    247 	printf("name=%s\n", ue->au_name ? ue->au_name : empty);
    248 	retval = getauditflagschar(always, ue->au_always, 0);
    249 	printf("always=%s\n", retval == 0 ? always : bad);
    250 	retval = getauditflagschar(never, ue->au_never, 0);
    251 	printf("never=%s\n", retval == 0 ? never : bad);
    252 }
    253 #endif	/* DEBUG */
    254