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