summaryrefslogtreecommitdiff
path: root/usr/src/lib/libsecdb/common/getexecattr.c
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libsecdb/common/getexecattr.c
downloadillumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libsecdb/common/getexecattr.c')
-rw-r--r--usr/src/lib/libsecdb/common/getexecattr.c524
1 files changed, 524 insertions, 0 deletions
diff --git a/usr/src/lib/libsecdb/common/getexecattr.c b/usr/src/lib/libsecdb/common/getexecattr.c
new file mode 100644
index 0000000000..1f6782b84f
--- /dev/null
+++ b/usr/src/lib/libsecdb/common/getexecattr.c
@@ -0,0 +1,524 @@
+/*
+ * 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 <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <nss_dbdefs.h>
+#include <deflt.h>
+#include <exec_attr.h>
+#include <user_attr.h>
+#include <auth_attr.h>
+#include <prof_attr.h>
+#include <getxby_door.h>
+#include <sys/mman.h>
+
+
+/* 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 */