/* * 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 (c) 1999-2001 by Sun Microsystems, Inc. * All rights reserved. * * Policy backing functions for kpolicy=suser,profiles=yes * */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include #include #include #include #include #include #include #include "sh_policy.h" static const char *username; /* * get the ruid and passwd name */ void secpolicy_init(void) { uid_t ruid; struct passwd *passwd_ent; ruid = getuid(); if ((passwd_ent = getpwuid(ruid)) == NULL) { secpolicy_print(SECPOLICY_ERROR, ERR_PASSWD); } else if ((username = strdup(passwd_ent->pw_name)) == NULL) { secpolicy_print(SECPOLICY_ERROR, ERR_MEM); } } /* * stuff pfexec full path at the begining of the argument vector * for the command to be pfexec'd * * return newly allocated argv on success, else return NULL. */ static char ** secpolicy_set_argv(char **arg_v) { register int i, j; register int arglen = 0; char **pfarg_v = (char **)NULL; if (*arg_v == NULL) { return (pfarg_v); } for (i = 0; arg_v[i] != 0; i++) { arglen += strlen(arg_v[i]); } arglen += strlen(PFEXEC); arglen++; /* for null termination */ if ((pfarg_v = (char **)calloc(1, arglen)) == NULL) { return (pfarg_v); } pfarg_v[0] = (char *)PFEXEC; for (i = 0, j = 1; arg_v[i] != 0; i++, j++) { pfarg_v[j] = arg_v[i]; } pfarg_v[j] = 0; return (pfarg_v); } /* * gets realpath for cmd. * return 0 on success, else return ENOENT. */ static int secpolicy_getrealpath(const char *cmd, char *cmd_realpath) { register char *mover; char cwd[MAXPATHLEN]; /* * What about relative paths? Were we passed one? */ mover = (char *)cmd; if (*mover != '/') { /* * Everything in here will be considered a relative * path, and therefore we need to prepend cwd to it. */ if (getcwd(cwd, MAXPATHLEN) == NULL) { secpolicy_print(SECPOLICY_ERROR, ERR_CWD); } strcat(cwd, "/"); if (strlcat(cwd, cmd, MAXPATHLEN) >= MAXPATHLEN) { return (ENOENT); } mover = cwd; } /* * Resolve ".." and other such nonsense. * Now, is there *REALLY* a file there? */ if (realpath(mover, cmd_realpath) == NULL) { return (ENOENT); } return (0); } /* * check if the command has execution attributes * return - * - NOATTRS : command in profile but has no execution attributes * - ENOMEM : memory allocation errors * - ENOENT : command not in profile */ int secpolicy_pfexec(const char *command, char **arg_v, const char **xecenv) { register int status = NOATTRS; char **pfarg_v = (char **)NULL; char cmd_realpath[MAXPATHLEN + 1]; execattr_t *exec; if ((status = secpolicy_getrealpath(command, cmd_realpath)) != 0) { return (status); } if ((exec = getexecuser(username, KV_COMMAND, (const char *)cmd_realpath, GET_ONE)) == NULL) { /* * command not in profile */ return (ENOENT); } /* * In case of "All" profile, we'd go through pfexec * if it had any attributes. */ if ((exec->attr != NULL) && (exec->attr->length != 0)) { /* * command in profile and has attributes */ free_execattr(exec); arg_v[0] = (char *)command; pfarg_v = secpolicy_set_argv(arg_v); if (pfarg_v != NULL) { errno = 0; if (xecenv == NULL) { execv(PFEXEC, (char *const *)pfarg_v); } else { execve(PFEXEC, (char *const *)pfarg_v, (char *const *)xecenv); } free(pfarg_v); status = errno; } else { status = ENOMEM; } } else { /* * command in profile, but has no attributes */ free_execattr(exec); status = NOATTRS; } return (status); }