chkauthattr.c revision 12273:63678502e95e
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 43static kva_t *get_default_attrs(const char *); 44static 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 65static 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 */ 85int 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); 137cont: 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 */ 147static 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 */ 202int 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 */ 213int 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 */ 225static 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 */ 252typedef struct ccomm2auth { 253 int (*cb)(const char *, void *, void *); 254 void *ctxt; 255} ccomm2auth; 256 257/*ARGSUSED*/ 258static int 259comm2auth(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 */ 272int 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 288int 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 318static 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 333int 334chkauthattr(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 349static int 350is_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 369static void 370free_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 */ 384static kva_t * 385get_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 417return_null: 418 if (defp != NULL) 419 (void) defclose_r(defp); 420 421 free_default_attrs(kva); 422 return (NULL); 423} 424