/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include #include #include #include #include #include #include #include #include #include #include /* Externs from libnsl */ extern execstr_t *_getexecattr(execstr_t *, char *, int, int *); extern void _setexecattr(void); extern void _endexecattr(void); extern execstr_t *_getexecprof(const char *, const char *, const char *, int, execstr_t *, char *, int, int *); extern userstr_t *_getusernam(const char *, userstr_t *, char *, int, int *); extern userstr_t *_getuserattr(userstr_t *, char *, int, int *); extern char *_strtok_escape(char *, char *, char **); extern char *_strdup_null(char *); static execattr_t *userprof(const char *, const char *, const char *, int); static execattr_t *get_tail(execattr_t *); static execattr_t *execstr2attr(execstr_t *); static execstr_t *process_getexec(execstr_t *, char *, int, nsc_data_t *); execattr_t * getexecattr() { int err = 0; char buf[NSS_BUFLEN_EXECATTR]; execstr_t exec; execstr_t *tmp; tmp = _getexecattr(&exec, buf, NSS_BUFLEN_EXECATTR, &err); return (execstr2attr(tmp)); } execattr_t * getexecprof(const char *name, const char *type, const char *id, int search_flag) { int len_unique; int err = 0; int ndata = 0; int adata = 0; char unique[NSS_BUFLEN_EXECATTR]; char buf[NSS_BUFLEN_EXECATTR]; execattr_t *head = (execattr_t *)NULL; execattr_t *prev = (execattr_t *)NULL; execstr_t exec; execstr_t *tmp; execstr_t *resptr = (execstr_t *)NULL; nsc_data_t *sptr = (nsc_data_t *)NULL; union { nsc_data_t s_d; char s_b[NSS_BUFLEN_EXECATTR]; } space; (void) memset(unique, 0, NSS_BUFLEN_EXECATTR); (void) memset(&exec, 0, sizeof (execstr_t)); (void) memset(&space, 0, sizeof (space)); if ((search_flag != GET_ONE) && (search_flag != GET_ALL)) { return ((execattr_t *)NULL); } if ((name == NULL) && (type == NULL) && (id == NULL)) { setexecattr(); switch (search_flag) { case GET_ONE: head = getexecattr(); break; case GET_ALL: head = getexecattr(); prev = head; while (prev != NULL) { prev->next = getexecattr(); prev = prev->next; }; break; default: head = (execattr_t *)NULL; break; } endexecattr(); return (head); } #ifdef PIC /* * If the search criteria is completely specified * and we only want a single entry, * then attempt to look up the entry using the nscd. * Only commands are cached. */ if (name && type && (strcmp(type, KV_COMMAND) == 0) && id && (search_flag == GET_ONE)) { if (snprintf(unique, NSS_BUFLEN_EXECATTR, "%s:%s:%s", name, type, id) >= NSS_BUFLEN_EXECATTR) { errno = ERANGE; return ((execattr_t *)NULL); } len_unique = strlen(unique); if ((len_unique >= (sizeof (space) - sizeof (nsc_data_t)))) { errno = ERANGE; return ((execattr_t *)NULL); } ndata = sizeof (space); adata = len_unique + sizeof (nsc_call_t) + 1; space.s_d.nsc_call.nsc_callnumber = GETEXECID; (void) strcpy(space.s_d.nsc_call.nsc_u.name, unique); sptr = &space.s_d; switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) { case SUCCESS: /* positive cache hit */ break; case NOTFOUND: /* negative cache hit */ return ((execattr_t *)NULL); default: resptr = _getexecprof(name, type, id, search_flag, &exec, buf, NSS_BUFLEN_EXECATTR, &err); return (execstr2attr(resptr)); } resptr = process_getexec(&exec, buf, NSS_BUFLEN_EXECATTR, sptr); /* * check if doors reallocated the memory underneath us * if they did munmap it or suffer a memory leak */ if (sptr != &space.s_d) (void) munmap((void *)sptr, ndata); return (execstr2attr(resptr)); } /* end if (name && type && id && search_flag == GET_ONE) */ #endif /* PIC */ tmp = _getexecprof(name, type, id, search_flag, &exec, buf, NSS_BUFLEN_EXECATTR, &err); return (execstr2attr(tmp)); } execattr_t * getexecuser(const char *username, const char *type, const char *id, int search_flag) { int err = 0; char buf[NSS_BUFLEN_USERATTR]; userstr_t user; userstr_t *utmp; execattr_t *head = (execattr_t *)NULL; execattr_t *prev = (execattr_t *)NULL; execattr_t *new = (execattr_t *)NULL; if ((search_flag != GET_ONE) && (search_flag != GET_ALL)) { return ((execattr_t *)NULL); } if (username == NULL) { setuserattr(); /* avoid userstr2attr mallocs by calling libnsl directly */ utmp = _getuserattr(&user, buf, NSS_BUFLEN_USERATTR, &err); if (utmp == NULL) { return (head); } switch (search_flag) { case GET_ONE: head = userprof((const char *)(utmp->name), type, id, search_flag); break; case GET_ALL: head = userprof((const char *)(utmp->name), type, id, search_flag); if (head != NULL) { prev = get_tail(head); } while ((utmp = _getuserattr(&user, buf, NSS_BUFLEN_USERATTR, &err)) != NULL) { if ((new = userprof((const char *)(utmp->name), type, id, search_flag)) != NULL) { if (prev != NULL) { prev->next = new; prev = get_tail(prev->next); } else { head = new; prev = get_tail(head); } } } break; default: head = (execattr_t *)NULL; break; } enduserattr(); } else { head = userprof(username, type, id, search_flag); } return (head); } execattr_t * match_execattr(execattr_t *exec, const char *profname, const char *type, const char *id) { execattr_t *execp = (execattr_t *)NULL; for (execp = exec; execp != NULL; execp = execp->next) { if ((profname && execp->name && (strcmp(profname, execp->name) != 0)) || (type && execp->type && (strcmp(type, execp->type) != 0)) || (id && execp->id && (strcmp(id, execp->id) != 0))) continue; } return (execp); } void setexecattr() { _setexecattr(); } void endexecattr() { _endexecattr(); } void free_execattr(execattr_t *exec) { if (exec != (execattr_t *)NULL) { free(exec->name); free(exec->type); free(exec->policy); free(exec->res1); free(exec->res2); free(exec->id); _kva_free(exec->attr); free_execattr(exec->next); free(exec); } } static execattr_t * userprof(const char *username, const char *type, const char *id, int search_flag) { int err = 0; char *last; char *sep = ","; char *proflist = (char *)NULL; char *profname = (char *)NULL; char buf[NSS_BUFLEN_USERATTR]; char pwdb[NSS_BUFLEN_PASSWD]; kva_t *user_attr; userstr_t user; userstr_t *utmp; execattr_t *exec; execattr_t *head = (execattr_t *)NULL; execattr_t *prev = (execattr_t *)NULL; struct passwd pwd; char *profArray[MAXPROFS]; int profcnt = 0; int i; /* * Check if specified username is valid user */ if (getpwnam_r(username, &pwd, pwdb, sizeof (pwdb)) == NULL) { return (head); } utmp = _getusernam(username, &user, buf, NSS_BUFLEN_USERATTR, &err); if (utmp != NULL) { proflist = NULL; user_attr = _str2kva(user.attr, KV_ASSIGN, KV_DELIMITER); if ((proflist = kva_match(user_attr, "profiles")) != NULL) { /* Get the list of profiles for this user */ for (profname = _strtok_escape(proflist, sep, &last); profname != NULL; profname = _strtok_escape(NULL, sep, &last)) { getproflist(profname, profArray, &profcnt); } } } /* Get the list of default profiles */ if (defopen(AUTH_POLICY) == NULL) { proflist = defread(DEF_PROF); (void) defopen(NULL); } if (proflist != NULL) { for (profname = _strtok_escape(proflist, sep, &last); profname != NULL; profname = _strtok_escape(NULL, sep, &last)) { getproflist(profname, profArray, &profcnt); } } if (profcnt == 0) { return (head); } /* Get execs from the list of profiles */ for (i = 0; i < profcnt; i++) { profname = profArray[i]; if ((exec = getexecprof(profname, type, id, search_flag)) != NULL) { if (search_flag == GET_ONE) { head = exec; break; } else if (search_flag == GET_ALL) { if (head == NULL) { head = exec; prev = get_tail(head); } else { prev->next = exec; prev = get_tail(exec); } } } } free_proflist(profArray, profcnt); return (head); } static execattr_t * get_tail(execattr_t *exec) { execattr_t *i_exec = (execattr_t *)NULL; execattr_t *j_exec = (execattr_t *)NULL; if (exec != NULL) { if (exec->next == NULL) { j_exec = exec; } else { for (i_exec = exec->next; i_exec != NULL; i_exec = i_exec->next) { j_exec = i_exec; } } } return (j_exec); } static execattr_t * execstr2attr(execstr_t *es) { execattr_t *newexec; if (es == NULL) { return ((execattr_t *)NULL); } if ((newexec = (execattr_t *)malloc(sizeof (execattr_t))) == NULL) { return ((execattr_t *)NULL); } newexec->name = _do_unescape(es->name); newexec->policy = _do_unescape(es->policy); newexec->type = _do_unescape(es->type); newexec->res1 = _do_unescape(es->res1); newexec->res2 = _do_unescape(es->res2); newexec->id = _do_unescape(es->id); newexec->attr = _str2kva(es->attr, KV_ASSIGN, KV_DELIMITER); if (es->next) { newexec->next = execstr2attr((execstr_t *)(es->next)); } else { newexec->next = (execattr_t *)NULL; } return (newexec); } static execstr_t * process_getexec( execstr_t *result, char *buffer, int buflen, nsc_data_t *sptr) { char *fixed; #ifdef _LP64 execstr_t exec64; fixed = (char *)(((uintptr_t)buffer + 7) & ~7); #else fixed = (char *)(((uintptr_t)buffer + 3) & ~3); #endif buflen -= fixed - buffer; buffer = fixed; if (sptr->nsc_ret.nsc_return_code != SUCCESS) return ((execstr_t *)NULL); #ifdef _LP64 if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (execstr32_t) > buflen) #else if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (execstr_t) > buflen) #endif { errno = ERANGE; return ((execstr_t *)NULL); } #ifdef _LP64 (void) memcpy(buffer, (sptr->nsc_ret.nsc_u.buff + sizeof (execstr32_t)), (sptr->nsc_ret.nsc_bufferbytesused - sizeof (execstr32_t))); exec64.name = (char *)(sptr->nsc_ret.nsc_u.exec.name + (uintptr_t)buffer); exec64.type = (char *)(sptr->nsc_ret.nsc_u.exec.type + (uintptr_t)buffer); exec64.policy = (char *)(sptr->nsc_ret.nsc_u.exec.policy + (uintptr_t)buffer); exec64.res1 = (char *)(sptr->nsc_ret.nsc_u.exec.res1 + (uintptr_t)buffer); exec64.res2 = (char *)(sptr->nsc_ret.nsc_u.exec.res2 + (uintptr_t)buffer); exec64.id = (char *)(sptr->nsc_ret.nsc_u.exec.id + (uintptr_t)buffer); exec64.attr = (char *)(sptr->nsc_ret.nsc_u.exec.attr + (uintptr_t)buffer); exec64.next = (execstr_t *)NULL; *result = exec64; #else sptr->nsc_ret.nsc_u.exec.name += (uintptr_t)buffer; sptr->nsc_ret.nsc_u.exec.type += (uintptr_t)buffer; sptr->nsc_ret.nsc_u.exec.policy += (uintptr_t)buffer; sptr->nsc_ret.nsc_u.exec.res1 += (uintptr_t)buffer; sptr->nsc_ret.nsc_u.exec.res2 += (uintptr_t)buffer; sptr->nsc_ret.nsc_u.exec.id += (uintptr_t)buffer; sptr->nsc_ret.nsc_u.exec.attr += (uintptr_t)buffer; sptr->nsc_ret.nsc_u.exec.next = (execstr_t *)NULL; *result = sptr->nsc_ret.nsc_u.exec; (void) memcpy(buffer, (sptr->nsc_ret.nsc_u.buff + sizeof (execstr_t)), (sptr->nsc_ret.nsc_bufferbytesused - sizeof (execstr_t))); #endif return (result); } #ifdef DEBUG void print_execattr(execattr_t *exec) { extern void print_kva(kva_t *); char *empty = "empty"; if (exec != NULL) { printf("name=%s\n", exec->name ? exec->name : empty); printf("policy=%s\n", exec->policy ? exec->policy : empty); printf("type=%s\n", exec->type ? exec->type : empty); printf("res1=%s\n", exec->res1 ? exec->res1 : empty); printf("res2=%s\n", exec->res2 ? exec->res2 : empty); printf("id=%s\n", exec->id ? exec->id : empty); printf("attr=\n"); print_kva(exec->attr); fflush(stdout); if (exec->next) { print_execattr(exec->next); } } else { printf("NULL\n"); } } #endif /* DEBUG */