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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <stdio.h> 31 #include <string.h> 32 #include <stdlib.h> 33 #include <nss_dbdefs.h> 34 #include <deflt.h> 35 #include <exec_attr.h> 36 #include <user_attr.h> 37 #include <auth_attr.h> 38 #include <prof_attr.h> 39 #include <getxby_door.h> 40 #include <sys/mman.h> 41 42 43 /* Externs from libnsl */ 44 extern execstr_t *_getexecattr(execstr_t *, char *, int, int *); 45 extern void _setexecattr(void); 46 extern void _endexecattr(void); 47 extern execstr_t *_getexecprof(const char *, const char *, const char *, int, 48 execstr_t *, char *, int, int *); 49 extern userstr_t *_getusernam(const char *, userstr_t *, char *, int, int *); 50 extern userstr_t *_getuserattr(userstr_t *, char *, int, int *); 51 extern char *_strtok_escape(char *, char *, char **); 52 extern char *_strdup_null(char *); 53 54 static execattr_t *userprof(const char *, const char *, const char *, int); 55 static execattr_t *get_tail(execattr_t *); 56 static execattr_t *execstr2attr(execstr_t *); 57 static execstr_t *process_getexec(execstr_t *, char *, int, nsc_data_t *); 58 59 execattr_t * 60 getexecattr() 61 { 62 int err = 0; 63 char buf[NSS_BUFLEN_EXECATTR]; 64 execstr_t exec; 65 execstr_t *tmp; 66 67 tmp = _getexecattr(&exec, buf, NSS_BUFLEN_EXECATTR, &err); 68 69 return (execstr2attr(tmp)); 70 } 71 72 73 execattr_t * 74 getexecprof(const char *name, const char *type, const char *id, int search_flag) 75 { 76 int len_unique; 77 int err = 0; 78 int ndata = 0; 79 int adata = 0; 80 char unique[NSS_BUFLEN_EXECATTR]; 81 char buf[NSS_BUFLEN_EXECATTR]; 82 execattr_t *head = (execattr_t *)NULL; 83 execattr_t *prev = (execattr_t *)NULL; 84 execstr_t exec; 85 execstr_t *tmp; 86 execstr_t *resptr = (execstr_t *)NULL; 87 nsc_data_t *sptr = (nsc_data_t *)NULL; 88 union { 89 nsc_data_t s_d; 90 char s_b[NSS_BUFLEN_EXECATTR]; 91 } space; 92 93 (void) memset(unique, 0, NSS_BUFLEN_EXECATTR); 94 (void) memset(&exec, 0, sizeof (execstr_t)); 95 (void) memset(&space, 0, sizeof (space)); 96 97 if ((search_flag != GET_ONE) && (search_flag != GET_ALL)) { 98 return ((execattr_t *)NULL); 99 } 100 101 if ((name == NULL) && (type == NULL) && (id == NULL)) { 102 setexecattr(); 103 switch (search_flag) { 104 case GET_ONE: 105 head = getexecattr(); 106 break; 107 case GET_ALL: 108 head = getexecattr(); 109 prev = head; 110 while (prev != NULL) { 111 prev->next = getexecattr(); 112 prev = prev->next; 113 }; 114 break; 115 default: 116 head = (execattr_t *)NULL; 117 break; 118 } 119 endexecattr(); 120 return (head); 121 } 122 123 #ifdef PIC 124 /* 125 * If the search criteria is completely specified 126 * and we only want a single entry, 127 * then attempt to look up the entry using the nscd. 128 * Only commands are cached. 129 */ 130 if (name && type && (strcmp(type, KV_COMMAND) == 0) && id && 131 (search_flag == GET_ONE)) { 132 if (snprintf(unique, NSS_BUFLEN_EXECATTR, "%s:%s:%s", 133 name, type, id) >= NSS_BUFLEN_EXECATTR) { 134 errno = ERANGE; 135 return ((execattr_t *)NULL); 136 } 137 len_unique = strlen(unique); 138 if ((len_unique >= (sizeof (space) - sizeof (nsc_data_t)))) { 139 errno = ERANGE; 140 return ((execattr_t *)NULL); 141 } 142 ndata = sizeof (space); 143 adata = len_unique + sizeof (nsc_call_t) + 1; 144 space.s_d.nsc_call.nsc_callnumber = GETEXECID; 145 (void) strcpy(space.s_d.nsc_call.nsc_u.name, unique); 146 sptr = &space.s_d; 147 148 switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) { 149 case SUCCESS: /* positive cache hit */ 150 break; 151 case NOTFOUND: /* negative cache hit */ 152 return ((execattr_t *)NULL); 153 default: 154 resptr = _getexecprof(name, type, id, search_flag, 155 &exec, buf, NSS_BUFLEN_EXECATTR, &err); 156 return (execstr2attr(resptr)); 157 } 158 resptr = process_getexec(&exec, buf, NSS_BUFLEN_EXECATTR, 159 sptr); 160 161 /* 162 * check if doors reallocated the memory underneath us 163 * if they did munmap it or suffer a memory leak 164 */ 165 if (sptr != &space.s_d) 166 (void) munmap((void *)sptr, ndata); 167 168 return (execstr2attr(resptr)); 169 } /* end if (name && type && id && search_flag == GET_ONE) */ 170 #endif /* PIC */ 171 172 tmp = _getexecprof(name, 173 type, 174 id, 175 search_flag, 176 &exec, 177 buf, 178 NSS_BUFLEN_EXECATTR, 179 &err); 180 181 return (execstr2attr(tmp)); 182 } 183 184 185 execattr_t * 186 getexecuser(const char *username, const char *type, const char *id, 187 int search_flag) 188 { 189 int err = 0; 190 char buf[NSS_BUFLEN_USERATTR]; 191 userstr_t user; 192 userstr_t *utmp; 193 execattr_t *head = (execattr_t *)NULL; 194 execattr_t *prev = (execattr_t *)NULL; 195 execattr_t *new = (execattr_t *)NULL; 196 197 if ((search_flag != GET_ONE) && (search_flag != GET_ALL)) { 198 return ((execattr_t *)NULL); 199 } 200 201 if (username == NULL) { 202 setuserattr(); 203 /* avoid userstr2attr mallocs by calling libnsl directly */ 204 utmp = _getuserattr(&user, buf, NSS_BUFLEN_USERATTR, &err); 205 if (utmp == NULL) { 206 return (head); 207 } 208 switch (search_flag) { 209 case GET_ONE: 210 head = userprof((const char *)(utmp->name), type, id, 211 search_flag); 212 break; 213 case GET_ALL: 214 head = userprof((const char *)(utmp->name), type, id, 215 search_flag); 216 if (head != NULL) { 217 prev = get_tail(head); 218 } 219 while ((utmp = _getuserattr(&user, 220 buf, NSS_BUFLEN_USERATTR, &err)) != NULL) { 221 if ((new = 222 userprof((const char *)(utmp->name), 223 type, id, search_flag)) != NULL) { 224 if (prev != NULL) { 225 prev->next = new; 226 prev = get_tail(prev->next); 227 } else { 228 head = new; 229 prev = get_tail(head); 230 } 231 } 232 } 233 break; 234 default: 235 head = (execattr_t *)NULL; 236 break; 237 } 238 enduserattr(); 239 } else { 240 head = userprof(username, type, id, search_flag); 241 } 242 243 return (head); 244 } 245 246 247 execattr_t * 248 match_execattr(execattr_t *exec, const char *profname, const char *type, 249 const char *id) 250 { 251 execattr_t *execp = (execattr_t *)NULL; 252 253 for (execp = exec; execp != NULL; execp = execp->next) { 254 if ((profname && execp->name && 255 (strcmp(profname, execp->name) != 0)) || 256 (type && execp->type && (strcmp(type, execp->type) != 0)) || 257 (id && execp->id && (strcmp(id, execp->id) != 0))) 258 continue; 259 } 260 261 return (execp); 262 } 263 264 265 void 266 setexecattr() 267 { 268 _setexecattr(); 269 } 270 271 272 void 273 endexecattr() 274 { 275 _endexecattr(); 276 } 277 278 279 void 280 free_execattr(execattr_t *exec) 281 { 282 if (exec != (execattr_t *)NULL) { 283 free(exec->name); 284 free(exec->type); 285 free(exec->policy); 286 free(exec->res1); 287 free(exec->res2); 288 free(exec->id); 289 _kva_free(exec->attr); 290 free_execattr(exec->next); 291 free(exec); 292 } 293 } 294 295 296 static execattr_t * 297 userprof(const char *username, const char *type, const char *id, 298 int search_flag) 299 { 300 301 int err = 0; 302 char *last; 303 char *sep = ","; 304 char *proflist = (char *)NULL; 305 char *profname = (char *)NULL; 306 char buf[NSS_BUFLEN_USERATTR]; 307 char pwdb[NSS_BUFLEN_PASSWD]; 308 kva_t *user_attr; 309 userstr_t user; 310 userstr_t *utmp; 311 execattr_t *exec; 312 execattr_t *head = (execattr_t *)NULL; 313 execattr_t *prev = (execattr_t *)NULL; 314 struct passwd pwd; 315 316 char *profArray[MAXPROFS]; 317 int profcnt = 0; 318 int i; 319 320 /* 321 * Check if specified username is valid user 322 */ 323 if (getpwnam_r(username, &pwd, pwdb, sizeof (pwdb)) == NULL) { 324 return (head); 325 } 326 327 utmp = _getusernam(username, &user, buf, NSS_BUFLEN_USERATTR, &err); 328 if (utmp != NULL) { 329 proflist = NULL; 330 user_attr = _str2kva(user.attr, KV_ASSIGN, KV_DELIMITER); 331 if ((proflist = kva_match(user_attr, "profiles")) != NULL) { 332 /* Get the list of profiles for this user */ 333 for (profname = _strtok_escape(proflist, sep, &last); 334 profname != NULL; 335 profname = _strtok_escape(NULL, sep, &last)) { 336 getproflist(profname, profArray, &profcnt); 337 } 338 } 339 } 340 341 /* Get the list of default profiles */ 342 if (defopen(AUTH_POLICY) == NULL) { 343 proflist = defread(DEF_PROF); 344 (void) defopen(NULL); 345 } 346 if (proflist != NULL) { 347 for (profname = _strtok_escape(proflist, sep, &last); 348 profname != NULL; 349 profname = _strtok_escape(NULL, sep, &last)) { 350 getproflist(profname, profArray, &profcnt); 351 } 352 } 353 354 if (profcnt == 0) { 355 return (head); 356 } 357 358 /* Get execs from the list of profiles */ 359 for (i = 0; i < profcnt; i++) { 360 profname = profArray[i]; 361 if ((exec = getexecprof(profname, type, id, search_flag)) != 362 NULL) { 363 if (search_flag == GET_ONE) { 364 head = exec; 365 break; 366 } else if (search_flag == GET_ALL) { 367 if (head == NULL) { 368 head = exec; 369 prev = get_tail(head); 370 } else { 371 prev->next = exec; 372 prev = get_tail(exec); 373 } 374 } 375 } 376 } 377 free_proflist(profArray, profcnt); 378 return (head); 379 } 380 381 382 static execattr_t * 383 get_tail(execattr_t *exec) 384 { 385 execattr_t *i_exec = (execattr_t *)NULL; 386 execattr_t *j_exec = (execattr_t *)NULL; 387 388 if (exec != NULL) { 389 if (exec->next == NULL) { 390 j_exec = exec; 391 } else { 392 for (i_exec = exec->next; i_exec != NULL; 393 i_exec = i_exec->next) { 394 j_exec = i_exec; 395 } 396 } 397 } 398 399 return (j_exec); 400 } 401 402 403 static execattr_t * 404 execstr2attr(execstr_t *es) 405 { 406 execattr_t *newexec; 407 408 if (es == NULL) { 409 return ((execattr_t *)NULL); 410 } 411 if ((newexec = (execattr_t *)malloc(sizeof (execattr_t))) == NULL) { 412 return ((execattr_t *)NULL); 413 } 414 415 newexec->name = _do_unescape(es->name); 416 newexec->policy = _do_unescape(es->policy); 417 newexec->type = _do_unescape(es->type); 418 newexec->res1 = _do_unescape(es->res1); 419 newexec->res2 = _do_unescape(es->res2); 420 newexec->id = _do_unescape(es->id); 421 newexec->attr = _str2kva(es->attr, KV_ASSIGN, KV_DELIMITER); 422 if (es->next) { 423 newexec->next = execstr2attr((execstr_t *)(es->next)); 424 } else { 425 newexec->next = (execattr_t *)NULL; 426 } 427 return (newexec); 428 } 429 430 431 static execstr_t * 432 process_getexec( 433 execstr_t *result, 434 char *buffer, 435 int buflen, 436 nsc_data_t *sptr) 437 { 438 char *fixed; 439 #ifdef _LP64 440 execstr_t exec64; 441 442 fixed = (char *)(((uintptr_t)buffer + 7) & ~7); 443 #else 444 fixed = (char *)(((uintptr_t)buffer + 3) & ~3); 445 #endif 446 buflen -= fixed - buffer; 447 buffer = fixed; 448 449 if (sptr->nsc_ret.nsc_return_code != SUCCESS) 450 return ((execstr_t *)NULL); 451 452 #ifdef _LP64 453 if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (execstr32_t) 454 > buflen) 455 #else 456 if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (execstr_t) 457 > buflen) 458 #endif 459 { 460 errno = ERANGE; 461 return ((execstr_t *)NULL); 462 } 463 464 #ifdef _LP64 465 (void) memcpy(buffer, (sptr->nsc_ret.nsc_u.buff + sizeof (execstr32_t)), 466 (sptr->nsc_ret.nsc_bufferbytesused - sizeof (execstr32_t))); 467 exec64.name = (char *)(sptr->nsc_ret.nsc_u.exec.name + 468 (uintptr_t)buffer); 469 exec64.type = (char *)(sptr->nsc_ret.nsc_u.exec.type + 470 (uintptr_t)buffer); 471 exec64.policy = (char *)(sptr->nsc_ret.nsc_u.exec.policy + 472 (uintptr_t)buffer); 473 exec64.res1 = (char *)(sptr->nsc_ret.nsc_u.exec.res1 + 474 (uintptr_t)buffer); 475 exec64.res2 = (char *)(sptr->nsc_ret.nsc_u.exec.res2 + 476 (uintptr_t)buffer); 477 exec64.id = (char *)(sptr->nsc_ret.nsc_u.exec.id + 478 (uintptr_t)buffer); 479 exec64.attr = (char *)(sptr->nsc_ret.nsc_u.exec.attr + 480 (uintptr_t)buffer); 481 exec64.next = (execstr_t *)NULL; 482 *result = exec64; 483 #else 484 sptr->nsc_ret.nsc_u.exec.name += (uintptr_t)buffer; 485 sptr->nsc_ret.nsc_u.exec.type += (uintptr_t)buffer; 486 sptr->nsc_ret.nsc_u.exec.policy += (uintptr_t)buffer; 487 sptr->nsc_ret.nsc_u.exec.res1 += (uintptr_t)buffer; 488 sptr->nsc_ret.nsc_u.exec.res2 += (uintptr_t)buffer; 489 sptr->nsc_ret.nsc_u.exec.id += (uintptr_t)buffer; 490 sptr->nsc_ret.nsc_u.exec.attr += (uintptr_t)buffer; 491 sptr->nsc_ret.nsc_u.exec.next = (execstr_t *)NULL; 492 *result = sptr->nsc_ret.nsc_u.exec; 493 (void) memcpy(buffer, (sptr->nsc_ret.nsc_u.buff + sizeof (execstr_t)), 494 (sptr->nsc_ret.nsc_bufferbytesused - sizeof (execstr_t))); 495 #endif 496 return (result); 497 } 498 499 500 #ifdef DEBUG 501 void 502 print_execattr(execattr_t *exec) 503 { 504 extern void print_kva(kva_t *); 505 char *empty = "empty"; 506 507 if (exec != NULL) { 508 printf("name=%s\n", exec->name ? exec->name : empty); 509 printf("policy=%s\n", exec->policy ? exec->policy : empty); 510 printf("type=%s\n", exec->type ? exec->type : empty); 511 printf("res1=%s\n", exec->res1 ? exec->res1 : empty); 512 printf("res2=%s\n", exec->res2 ? exec->res2 : empty); 513 printf("id=%s\n", exec->id ? exec->id : empty); 514 printf("attr=\n"); 515 print_kva(exec->attr); 516 fflush(stdout); 517 if (exec->next) { 518 print_execattr(exec->next); 519 } 520 } else { 521 printf("NULL\n"); 522 } 523 } 524 #endif /* DEBUG */ 525