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