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 return (res); 175 } 176 177 if ((cnt == 0 || strcmp(profs[cnt-1], PROFILE_STOP) != 0) && 178 (kattrs = get_default_attrs(username)) != NULL) { 179 180 res = _enum_common_p(GETCONSPROF(kattrs), cb, ctxt, pres, 181 wantattr, &cnt, profs); 182 183 if (res == 0) { 184 res = _enum_common_p(GETPROF(kattrs), cb, ctxt, pres, 185 wantattr, &cnt, profs); 186 } 187 188 if (res == 0 && wantattr) 189 res = cb(NULL, kattrs, ctxt, pres); 190 191 free_default_attrs(kattrs); 192 } 193 194 free_proflist(profs, cnt); 195 196 return (res); 197 } 198 199 /* 200 * Enumerate profiles with a username argument. 201 */ 202 int 203 _enum_profs(const char *username, 204 int (*cb)(const char *, kva_t *, void *, void *), 205 void *ctxt, void *pres) 206 { 207 return (_enum_common(username, cb, ctxt, pres, B_FALSE)); 208 } 209 210 /* 211 * Enumerate attributes with a username argument. 212 */ 213 int 214 _enum_attrs(const char *username, 215 int (*cb)(const char *, kva_t *, void *, void *), 216 void *ctxt, void *pres) 217 { 218 return (_enum_common(username, cb, ctxt, pres, B_TRUE)); 219 } 220 221 222 /* 223 * Enumerate authorizations in the "auths" argument. 224 */ 225 static int 226 _enum_auths_a(const char *cauths, int (*cb)(const char *, void *, void *), 227 void *ctxt, void *pres) 228 { 229 char *auth, *last, *auths; 230 int res = 0; 231 232 if (cauths == NULL || cb == NULL) 233 return (0); 234 235 COPYTOSTACK(auths, cauths) 236 237 while (auth = strtok_r(auths, KV_SEPSTR, &last)) { 238 auths = NULL; /* For next iterations of strtok_r */ 239 240 res = cb(auth, ctxt, pres); 241 242 if (res != 0) 243 return (res); 244 } 245 return (res); 246 } 247 248 /* 249 * Magic struct and function to allow using the _enum_attrs functions to 250 * enumerate the authorizations. 251 */ 252 typedef struct ccomm2auth { 253 int (*cb)(const char *, void *, void *); 254 void *ctxt; 255 } ccomm2auth; 256 257 /*ARGSUSED*/ 258 static int 259 comm2auth(const char *name, kva_t *attr, void *ctxt, void *pres) 260 { 261 ccomm2auth *ca = ctxt; 262 char *auths; 263 264 /* Note: PROFATTR_AUTHS_KW is equal to USERATTR_AUTHS_KW */ 265 auths = kva_match(attr, PROFATTR_AUTHS_KW); 266 return (_enum_auths_a(auths, ca->cb, ca->ctxt, pres)); 267 } 268 269 /* 270 * Enumerate authorizations for username. 271 */ 272 int 273 _enum_auths(const char *username, 274 int (*cb)(const char *, void *, void *), 275 void *ctxt, void *pres) 276 { 277 ccomm2auth c2a; 278 279 if (cb == NULL) 280 return (-1); 281 282 c2a.cb = cb; 283 c2a.ctxt = ctxt; 284 285 return (_enum_common(username, comm2auth, &c2a, pres, B_TRUE)); 286 } 287 288 int 289 _auth_match(const char *pattern, const char *auth) 290 { 291 size_t len; 292 char *grant; 293 294 len = strlen(pattern); 295 296 /* 297 * If the wildcard is not in the last position in the string, don't 298 * match against it. 299 */ 300 if (pattern[len-1] != KV_WILDCHAR) 301 return (0); 302 303 /* 304 * If the strings are identical up to the wildcard and auth does not 305 * end in "grant", then we have a match. 306 */ 307 if (strncmp(pattern, auth, len-1) == 0) { 308 grant = strrchr(auth, '.'); 309 if (grant != NULL) { 310 if (strncmp(grant + 1, "grant", 5) != NULL) 311 return (1); 312 } 313 } 314 315 return (0); 316 } 317 318 static int 319 _is_authorized(const char *auth, void *authname, void *res) 320 { 321 int *resp = res; 322 323 if (strcmp(authname, auth) == 0 || 324 (strchr(auth, KV_WILDCHAR) != NULL && 325 _auth_match(auth, authname))) { 326 *resp = 1; 327 return (1); 328 } 329 330 return (0); 331 } 332 333 int 334 chkauthattr(const char *authname, const char *username) 335 { 336 int auth_granted = 0; 337 338 if (authname == NULL || username == NULL) 339 return (0); 340 341 (void) _enum_auths(username, _is_authorized, (char *)authname, 342 &auth_granted); 343 344 return (auth_granted); 345 } 346 347 #define CONSOLE_USER_LINK "/dev/vt/console_user" 348 349 static int 350 is_cons_user(const char *user) 351 { 352 struct stat cons; 353 struct passwd pw; 354 char pwbuf[NSS_BUFLEN_PASSWD]; 355 356 if (user == NULL) { 357 return (0); 358 } 359 if (stat(CONSOLE_USER_LINK, &cons) == -1) { 360 return (0); 361 } 362 if (getpwnam_r(user, &pw, pwbuf, sizeof (pwbuf)) == NULL) { 363 return (0); 364 } 365 366 return (pw.pw_uid == cons.st_uid); 367 } 368 369 static void 370 free_default_attrs(kva_t *kva) 371 { 372 int i; 373 374 for (i = 0; i < kva->length; i++) 375 free(kva->data[i].value); 376 377 free(kva); 378 } 379 380 /* 381 * Return the default attributes; this are ignored when a STOP profile 382 * was found. 383 */ 384 static kva_t * 385 get_default_attrs(const char *user) 386 { 387 void *defp; 388 kva_t *kva; 389 int i; 390 391 kva = malloc(sizeof (kva_t) + sizeof (kv_t) * NDFLTPLY); 392 393 if (kva == NULL) 394 return (NULL); 395 396 kva->data = (kv_t *)(void *)&kva[1]; 397 kva->length = 0; 398 399 if ((defp = defopen_r(AUTH_POLICY)) == NULL) 400 goto return_null; 401 402 for (i = is_cons_user(user) ? 0 : 1; i < NDFLTPLY; i++) { 403 char *cp = defread_r(dfltply[i].defkw, defp); 404 405 if (cp == NULL) 406 continue; 407 if ((cp = strdup(cp)) == NULL) 408 goto return_null; 409 410 kva->data[kva->length].key = dfltply[i].attr; 411 kva->data[kva->length++].value = cp; 412 } 413 414 (void) defclose_r(defp); 415 return (kva); 416 417 return_null: 418 if (defp != NULL) 419 (void) defclose_r(defp); 420 421 free_default_attrs(kva); 422 return (NULL); 423 } 424