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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Policy backing functions for kpolicy=suser,profiles=yes 26 * 27 */ 28 29 #include <sys/param.h> 30 #include <grp.h> 31 #include <pwd.h> 32 #include <strings.h> 33 #include <string.h> 34 #include <errno.h> 35 #include <unistd.h> 36 #include <stdlib.h> 37 #include "sh_policy.h" 38 39 40 static char *username; 41 42 /* 43 * get the ruid and passwd name 44 */ 45 void 46 secpolicy_init(void) 47 { 48 uid_t ruid; 49 struct passwd *passwd_ent; 50 51 if (username != NULL) { 52 free(username); 53 username = NULL; 54 } 55 56 ruid = getuid(); 57 58 if ((passwd_ent = getpwuid(ruid)) == NULL) { 59 secpolicy_print(SECPOLICY_ERROR, ERR_PASSWD); 60 } else if ((username = strdup(passwd_ent->pw_name)) == NULL) { 61 secpolicy_print(SECPOLICY_ERROR, ERR_MEM); 62 } 63 } 64 65 66 /* 67 * stuff pfexec full path at the begining of the argument vector 68 * for the command to be pfexec'd 69 * 70 * return newly allocated argv on success, else return NULL. 71 */ 72 static char ** 73 secpolicy_set_argv(char **arg_v) 74 { 75 int i; 76 int arg_c = 0; 77 char **pfarg_v = NULL; 78 79 if (*arg_v == NULL) { 80 return (pfarg_v); 81 } 82 for (i = 0; arg_v[i] != NULL; i++) { 83 arg_c++; 84 } 85 /* +2 for PFEXEC and null termination */ 86 if ((pfarg_v = calloc(arg_c + 2, sizeof (char *))) == NULL) { 87 return (pfarg_v); 88 } 89 pfarg_v[0] = PFEXEC; 90 for (i = 0; i < arg_c; i++) { 91 pfarg_v[i + 1] = arg_v[i]; 92 } 93 94 return (pfarg_v); 95 } 96 97 98 /* 99 * gets realpath for cmd. 100 * return 0 on success, else return ENOENT. 101 */ 102 static int 103 secpolicy_getrealpath(const char *cmd, char *cmd_realpath) 104 { 105 register char *mover; 106 char cwd[MAXPATHLEN]; 107 108 /* 109 * What about relative paths? Were we passed one? 110 */ 111 mover = (char *)cmd; 112 if (*mover != '/') { 113 /* 114 * Everything in here will be considered a relative 115 * path, and therefore we need to prepend cwd to it. 116 */ 117 if (getcwd(cwd, MAXPATHLEN) == NULL) { 118 secpolicy_print(SECPOLICY_ERROR, ERR_CWD); 119 } 120 strcat(cwd, "/"); 121 if (strlcat(cwd, cmd, MAXPATHLEN) >= MAXPATHLEN) { 122 return (ENOENT); 123 } 124 mover = cwd; 125 } 126 /* 127 * Resolve ".." and other such nonsense. 128 * Now, is there *REALLY* a file there? 129 */ 130 if (realpath(mover, cmd_realpath) == NULL) { 131 return (ENOENT); 132 } 133 134 return (0); 135 } 136 137 138 /* 139 * check if the command has execution attributes 140 * return - 141 * - NOATTRS : command in profile but has no execution attributes 142 * - ENOMEM : memory allocation errors 143 * - ENOENT : command not in profile 144 */ 145 146 int 147 secpolicy_pfexec(const char *command, char **arg_v, const char **xecenv) 148 { 149 register int status = NOATTRS; 150 char **pfarg_v = (char **)NULL; 151 char cmd_realpath[MAXPATHLEN + 1]; 152 execattr_t *exec; 153 154 if ((status = secpolicy_getrealpath(command, cmd_realpath)) != 0) { 155 return (status); 156 } 157 if ((exec = getexecuser(username, KV_COMMAND, 158 (const char *)cmd_realpath, GET_ONE)) == NULL) { 159 /* 160 * command not in profile 161 */ 162 return (ENOENT); 163 } 164 /* 165 * In case of "All" profile, we'd go through pfexec 166 * if it had any attributes. 167 */ 168 if ((exec->attr != NULL) && (exec->attr->length != 0)) { 169 /* 170 * command in profile and has attributes 171 */ 172 free_execattr(exec); 173 arg_v[0] = (char *)command; 174 pfarg_v = secpolicy_set_argv(arg_v); 175 if (pfarg_v != NULL) { 176 errno = 0; 177 if (xecenv == NULL) { 178 execv(PFEXEC, (char *const *)pfarg_v); 179 } else { 180 execve(PFEXEC, (char *const *)pfarg_v, 181 (char *const *)xecenv); 182 } 183 free(pfarg_v); 184 status = errno; 185 } else { 186 status = ENOMEM; 187 } 188 } else { 189 /* 190 * command in profile, but has no attributes 191 */ 192 free_execattr(exec); 193 status = NOATTRS; 194 } 195 196 197 return (status); 198 } 199