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 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <alloca.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <sys/stat.h> 30 #include <pwd.h> 31 #include <nss_dbdefs.h> 32 #include <deflt.h> 33 #include <auth_attr.h> 34 #include <prof_attr.h> 35 #include <user_attr.h> 36 37 #define COPYTOSTACK(dst, csrc) { \ 38 size_t len = strlen(csrc) + 1; \ 39 dst = alloca(len); \ 40 (void) memcpy(dst, csrc, len); \ 41 } 42 43 static kva_t *get_default_attrs(const char *); 44 static void free_default_attrs(kva_t *); 45 46 /* 47 * Enumeration functions for auths and profiles; the enumeration functions 48 * take a callback with four arguments: 49 * const char * profile name (or NULL unless wantattr is false) 50 * kva_t * attributes (or NULL unless wantattr is true) 51 * void * context 52 * void * pointer to the result 53 * When the call back returns non-zero, the enumeration ends. 54 * The function might be NULL but only for profiles as we are always collecting 55 * all the profiles. 56 * Both the auths and the profiles arguments may be NULL. 57 * 58 * These should be the only implementation of the algorithm of "finding me 59 * all the profiles/athorizations/keywords/etc. 60 */ 61 62 #define CONSUSER_PROFILE_KW "consprofile" 63 #define DEF_LOCK_AFTER_RETRIES "LOCK_AFTER_RETRIES=" 64 65 static struct dfltplcy { 66 char *attr; 67 const char *defkw; 68 } dfltply[] = { 69 /* CONSUSER MUST BE FIRST! */ 70 { CONSUSER_PROFILE_KW, DEF_CONSUSER}, 71 { PROFATTR_AUTHS_KW, DEF_AUTH}, 72 { PROFATTR_PROFS_KW, DEF_PROF}, 73 { USERATTR_LIMPRIV_KW, DEF_LIMITPRIV}, 74 { USERATTR_DFLTPRIV_KW, DEF_DFLTPRIV}, 75 { USERATTR_LOCK_AFTER_RETRIES_KW, DEF_LOCK_AFTER_RETRIES} 76 }; 77 78 #define NDFLTPLY (sizeof (dfltply)/sizeof (struct dfltplcy)) 79 #define GETCONSPROF(a) (kva_match((a), CONSUSER_PROFILE_KW)) 80 #define GETPROF(a) (kva_match((a), PROFATTR_PROFS_KW)) 81 82 /* 83 * Enumerate profiles from listed profiles. 84 */ 85 int 86 _enum_common_p(const char *cprofiles, 87 int (*cb)(const char *, kva_t *, void *, void *), 88 void *ctxt, void *pres, boolean_t wantattr, 89 int *pcnt, char *profs[MAXPROFS]) 90 { 91 char *prof, *last; 92 char *profiles; 93 profattr_t *pa; 94 int i; 95 int res = 0; 96 97 if (cprofiles == NULL) 98 return (0); 99 100 if (*pcnt > 0 && strcmp(profs[*pcnt - 1], PROFILE_STOP) == NULL) 101 return (0); 102 103 COPYTOSTACK(profiles, cprofiles) 104 105 while (prof = strtok_r(profiles, KV_SEPSTR, &last)) { 106 107 profiles = NULL; /* For next iterations of strtok_r */ 108 109 for (i = 0; i < *pcnt; i++) 110 if (strcmp(profs[i], prof) == 0) 111 goto cont; 112 113 if (*pcnt >= MAXPROFS) /* oops: too many profs */ 114 return (-1); 115 116 /* Add it */ 117 profs[(*pcnt)++] = strdup(prof); 118 119 if (strcmp(profs[*pcnt - 1], PROFILE_STOP) == 0) 120 break; 121 122 /* find the profiles for this profile */ 123 pa = getprofnam(prof); 124 125 if (cb != NULL && (!wantattr || pa != NULL && pa->attr != NULL)) 126 res = cb(prof, pa ? pa->attr : NULL, ctxt, pres); 127 128 if (pa != NULL) { 129 if (res == 0 && pa->attr != NULL) { 130 res = _enum_common_p(GETPROF(pa->attr), cb, 131 ctxt, pres, wantattr, pcnt, profs); 132 } 133 free_profattr(pa); 134 } 135 if (res != 0) 136 return (res); 137 cont: 138 continue; 139 } 140 return (res); 141 } 142 143 /* 144 * Enumerate all attributes associated with a username and the profiles 145 * associated with the user. 146 */ 147 static int 148 _enum_common(const char *username, 149 int (*cb)(const char *, kva_t *, void *, void *), 150 void *ctxt, void *pres, boolean_t wantattr) 151 { 152 userattr_t *ua; 153 int res = 0; 154 int cnt = 0; 155 char *profs[MAXPROFS]; 156 kva_t *kattrs; 157 158 if (cb == NULL) 159 return (-1); 160 161 ua = getusernam(username); 162 163 if (ua != NULL) { 164 if (ua->attr != NULL) { 165 if (wantattr) 166 res = cb(NULL, ua->attr, ctxt, pres); 167 if (res == 0) { 168 res = _enum_common_p(GETPROF(ua->attr), 169 cb, ctxt, pres, wantattr, &cnt, profs); 170 } 171 } 172 free_userattr(ua); 173 if (res != 0) { 174 free_proflist(profs, cnt); 175 return (res); 176 } 177 } 178 179 if ((cnt == 0 || strcmp(profs[cnt-1], PROFILE_STOP) != 0) && 180 (kattrs = get_default_attrs(username)) != NULL) { 181 182 res = _enum_common_p(GETCONSPROF(kattrs), cb, ctxt, pres, 183 wantattr, &cnt, profs); 184 185 if (res == 0) { 186 res = _enum_common_p(GETPROF(kattrs), cb, ctxt, pres, 187 wantattr, &cnt, profs); 188 } 189 190 if (res == 0 && wantattr) 191 res = cb(NULL, kattrs, ctxt, pres); 192 193 free_default_attrs(kattrs); 194 } 195 196 free_proflist(profs, cnt); 197 198 return (res); 199 } 200 201 /* 202 * Enumerate profiles with a username argument. 203 */ 204 int 205 _enum_profs(const char *username, 206 int (*cb)(const char *, kva_t *, void *, void *), 207 void *ctxt, void *pres) 208 { 209 return (_enum_common(username, cb, ctxt, pres, B_FALSE)); 210 } 211 212 /* 213 * Enumerate attributes with a username argument. 214 */ 215 int 216 _enum_attrs(const char *username, 217 int (*cb)(const char *, kva_t *, void *, void *), 218 void *ctxt, void *pres) 219 { 220 return (_enum_common(username, cb, ctxt, pres, B_TRUE)); 221 } 222 223 224 /* 225 * Enumerate authorizations in the "auths" argument. 226 */ 227 static int 228 _enum_auths_a(const char *cauths, int (*cb)(const char *, void *, void *), 229 void *ctxt, void *pres) 230 { 231 char *auth, *last, *auths; 232 int res = 0; 233 234 if (cauths == NULL || cb == NULL) 235 return (0); 236 237 COPYTOSTACK(auths, cauths) 238 239 while (auth = strtok_r(auths, KV_SEPSTR, &last)) { 240 auths = NULL; /* For next iterations of strtok_r */ 241 242 res = cb(auth, ctxt, pres); 243 244 if (res != 0) 245 return (res); 246 } 247 return (res); 248 } 249 250 /* 251 * Magic struct and function to allow using the _enum_attrs functions to 252 * enumerate the authorizations. 253 */ 254 typedef struct ccomm2auth { 255 int (*cb)(const char *, void *, void *); 256 void *ctxt; 257 } ccomm2auth; 258 259 /*ARGSUSED*/ 260 static int 261 comm2auth(const char *name, kva_t *attr, void *ctxt, void *pres) 262 { 263 ccomm2auth *ca = ctxt; 264 char *auths; 265 266 /* Note: PROFATTR_AUTHS_KW is equal to USERATTR_AUTHS_KW */ 267 auths = kva_match(attr, PROFATTR_AUTHS_KW); 268 return (_enum_auths_a(auths, ca->cb, ca->ctxt, pres)); 269 } 270 271 /* 272 * Enumerate authorizations for username. 273 */ 274 int 275 _enum_auths(const char *username, 276 int (*cb)(const char *, void *, void *), 277 void *ctxt, void *pres) 278 { 279 ccomm2auth c2a; 280 281 if (cb == NULL) 282 return (-1); 283 284 c2a.cb = cb; 285 c2a.ctxt = ctxt; 286 287 return (_enum_common(username, comm2auth, &c2a, pres, B_TRUE)); 288 } 289 290 int 291 _auth_match(const char *pattern, const char *auth) 292 { 293 size_t len; 294 char *grant; 295 296 len = strlen(pattern); 297 298 /* 299 * If the wildcard is not in the last position in the string, don't 300 * match against it. 301 */ 302 if (pattern[len-1] != KV_WILDCHAR) 303 return (0); 304 305 /* 306 * If the strings are identical up to the wildcard and auth does not 307 * end in "grant", then we have a match. 308 */ 309 if (strncmp(pattern, auth, len-1) == 0) { 310 grant = strrchr(auth, '.'); 311 if (grant != NULL) { 312 if (strncmp(grant + 1, "grant", 5) != NULL) 313 return (1); 314 } 315 } 316 317 return (0); 318 } 319 320 static int 321 _is_authorized(const char *auth, void *authname, void *res) 322 { 323 int *resp = res; 324 325 if (strcmp(authname, auth) == 0 || 326 (strchr(auth, KV_WILDCHAR) != NULL && 327 _auth_match(auth, authname))) { 328 *resp = 1; 329 return (1); 330 } 331 332 return (0); 333 } 334 335 int 336 chkauthattr(const char *authname, const char *username) 337 { 338 int auth_granted = 0; 339 340 if (authname == NULL || username == NULL) 341 return (0); 342 343 (void) _enum_auths(username, _is_authorized, (char *)authname, 344 &auth_granted); 345 346 return (auth_granted); 347 } 348 349 #define CONSOLE_USER_LINK "/dev/vt/console_user" 350 351 static int 352 is_cons_user(const char *user) 353 { 354 struct stat cons; 355 struct passwd pw; 356 char pwbuf[NSS_BUFLEN_PASSWD]; 357 358 if (user == NULL) { 359 return (0); 360 } 361 if (stat(CONSOLE_USER_LINK, &cons) == -1) { 362 return (0); 363 } 364 if (getpwnam_r(user, &pw, pwbuf, sizeof (pwbuf)) == NULL) { 365 return (0); 366 } 367 368 return (pw.pw_uid == cons.st_uid); 369 } 370 371 static void 372 free_default_attrs(kva_t *kva) 373 { 374 int i; 375 376 for (i = 0; i < kva->length; i++) 377 free(kva->data[i].value); 378 379 free(kva); 380 } 381 382 /* 383 * Return the default attributes; this are ignored when a STOP profile 384 * was found. 385 */ 386 static kva_t * 387 get_default_attrs(const char *user) 388 { 389 void *defp; 390 kva_t *kva; 391 int i; 392 393 kva = malloc(sizeof (kva_t) + sizeof (kv_t) * NDFLTPLY); 394 395 if (kva == NULL) 396 return (NULL); 397 398 kva->data = (kv_t *)(void *)&kva[1]; 399 kva->length = 0; 400 401 if ((defp = defopen_r(AUTH_POLICY)) == NULL) 402 goto return_null; 403 404 for (i = is_cons_user(user) ? 0 : 1; i < NDFLTPLY; i++) { 405 char *cp = defread_r(dfltply[i].defkw, defp); 406 407 if (cp == NULL) 408 continue; 409 if ((cp = strdup(cp)) == NULL) 410 goto return_null; 411 412 kva->data[kva->length].key = dfltply[i].attr; 413 kva->data[kva->length++].value = cp; 414 } 415 416 (void) defclose_r(defp); 417 return (kva); 418 419 return_null: 420 if (defp != NULL) 421 (void) defclose_r(defp); 422 423 free_default_attrs(kva); 424 return (NULL); 425 } 426