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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <sys/types.h> 32 #include <sys/stat.h> 33 #include <fcntl.h> 34 #include <sys/mman.h> 35 #include <limits.h> 36 #include <deflt.h> 37 #include <auth_attr.h> 38 #include <prof_attr.h> 39 #include <user_attr.h> 40 41 42 static int _is_authorized(const char *, char *); 43 static int _chk_policy_auth(const char *, char **, int *); 44 static int _chkprof_for_auth(const char *, const char *, char **, int *); 45 46 47 int 48 chkauthattr(const char *authname, const char *username) 49 { 50 int auth_granted = 0; 51 char *auths; 52 char *profiles; 53 userattr_t *user = NULL; 54 char *chkedprof[MAXPROFS]; 55 int chkedprof_cnt = 0; 56 int i; 57 58 if (authname == NULL || username == NULL) 59 return (0); 60 61 /* Check against AUTHS_GRANTED and PROFS_GRANTED in policy.conf */ 62 auth_granted = _chk_policy_auth(authname, chkedprof, &chkedprof_cnt); 63 if (auth_granted) 64 goto exit; 65 66 if ((user = getusernam(username)) == NULL) 67 goto exit; 68 69 /* Check against authorizations listed in user_attr */ 70 if ((auths = kva_match(user->attr, USERATTR_AUTHS_KW)) != NULL) { 71 auth_granted = _is_authorized(authname, auths); 72 if (auth_granted) 73 goto exit; 74 } 75 76 /* Check against authorizations specified by profiles */ 77 if ((profiles = kva_match(user->attr, USERATTR_PROFILES_KW)) != NULL) 78 auth_granted = _chkprof_for_auth(profiles, authname, 79 chkedprof, &chkedprof_cnt); 80 81 exit: 82 /* free memory allocated for checked array */ 83 for (i = 0; i < chkedprof_cnt; i++) { 84 free(chkedprof[i]); 85 } 86 87 if (user != NULL) 88 free_userattr(user); 89 90 return (auth_granted); 91 } 92 93 static int 94 _chkprof_for_auth(const char *profs, const char *authname, 95 char **chkedprof, int *chkedprof_cnt) 96 { 97 98 char *prof, *lasts, *auths, *profiles; 99 profattr_t *pa; 100 int i; 101 int checked = 0; 102 103 for (prof = strtok_r((char *)profs, ",", &lasts); prof != NULL; 104 prof = strtok_r(NULL, ",", &lasts)) { 105 106 checked = 0; 107 /* check if this profile has been checked */ 108 for (i = 0; i < *chkedprof_cnt; i++) { 109 if (strcmp(chkedprof[i], prof) == 0) { 110 checked = 1; 111 break; 112 } 113 } 114 115 if (!checked) { 116 117 chkedprof[*chkedprof_cnt] = strdup(prof); 118 *chkedprof_cnt = *chkedprof_cnt + 1; 119 120 if ((pa = getprofnam(prof)) == NULL) 121 continue; 122 123 if ((auths = kva_match(pa->attr, 124 PROFATTR_AUTHS_KW)) != NULL) { 125 if (_is_authorized(authname, auths)) { 126 free_profattr(pa); 127 return (1); 128 } 129 } 130 if ((profiles = 131 kva_match(pa->attr, PROFATTR_PROFS_KW)) != NULL) { 132 /* Check for authorization in subprofiles */ 133 if (_chkprof_for_auth(profiles, authname, 134 chkedprof, chkedprof_cnt)) { 135 free_profattr(pa); 136 return (1); 137 } 138 } 139 free_profattr(pa); 140 } 141 } 142 /* authorization not found in any profile */ 143 return (0); 144 } 145 146 int 147 _auth_match(const char *pattern, const char *auth) 148 { 149 size_t len; 150 char wildcard = KV_WILDCHAR; 151 char *grant; 152 153 len = strlen(pattern); 154 155 /* 156 * If the wildcard is not in the last position in the string, don't 157 * match against it. 158 */ 159 if (pattern[len-1] != wildcard) 160 return (0); 161 162 /* 163 * If the strings are identical up to the wildcard and auth does not 164 * end in "grant", then we have a match. 165 */ 166 if (strncmp(pattern, auth, len-1) == 0) { 167 grant = strrchr(auth, '.'); 168 if (grant != NULL) { 169 if (strncmp(grant + 1, "grant", 5) != NULL) 170 return (1); 171 } 172 } 173 174 return (0); 175 } 176 177 static int 178 _is_authorized(const char *authname, char *auths) 179 { 180 int found = 0; /* have we got a match, yet */ 181 char wildcard = '*'; 182 char *auth; /* current authorization being compared */ 183 char *buf; 184 char *lasts; 185 186 buf = strdup(auths); 187 for (auth = strtok_r(auths, ",", &lasts); auth != NULL && !found; 188 auth = strtok_r(NULL, ",", &lasts)) { 189 if (strcmp((char *)authname, auth) == 0) { 190 /* Exact match. We're done. */ 191 found = 1; 192 } else if (strchr(auth, wildcard) != NULL) { 193 if (_auth_match(auth, authname)) { 194 found = 1; 195 break; 196 } 197 } 198 } 199 200 free(buf); 201 202 return (found); 203 } 204 205 206 int 207 _get_auth_policy(char **def_auth, char **def_prof) 208 { 209 char *cp; 210 211 if (defopen(AUTH_POLICY) != 0) 212 return (-1); 213 214 cp = defread(DEF_AUTH); 215 if (cp != NULL) { 216 *def_auth = strdup(cp); 217 if (*def_auth == NULL) 218 return (-1); 219 } else { 220 *def_auth = NULL; 221 } 222 223 cp = defread(DEF_PROF); 224 if (cp != NULL) { 225 *def_prof = strdup(cp); 226 if (*def_prof == NULL) { 227 free(*def_auth); 228 return (-1); 229 } 230 } else { 231 *def_prof = NULL; 232 } 233 234 (void) defopen(NULL); 235 return (0); 236 } 237 238 void 239 _free_auth_policy(char *def_auth, char *def_prof) 240 { 241 free(def_auth); 242 free(def_prof); 243 } 244 245 /* 246 * read /etc/security/policy.conf for AUTHS_GRANTED. 247 * return 1 if found matching authname. 248 * Otherwise, read PROFS_GRANTED to see if authname exists in any 249 * default profiles. 250 */ 251 static int 252 _chk_policy_auth(const char *authname, char **chkedprof, int *chkedprof_cnt) 253 { 254 char *auths, *profs; 255 int ret = 1; 256 257 if (_get_auth_policy(&auths, &profs) != 0) 258 return (0); 259 260 if (auths != NULL) { 261 if (_is_authorized(authname, auths)) 262 goto exit; 263 } 264 265 if (profs != NULL) { 266 if (_chkprof_for_auth(profs, authname, chkedprof, 267 chkedprof_cnt)) 268 goto exit; 269 } 270 ret = 0; 271 272 exit: 273 _free_auth_policy(auths, profs); 274 return (ret); 275 } 276