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 26 #include "mt.h" 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <sys/types.h> 30 #include <nss_dbdefs.h> 31 #include <string.h> 32 #include <strings.h> 33 #include <sys/systeminfo.h> 34 #include <thread.h> 35 #include <synch.h> 36 #include <nsswitch.h> 37 #include <prof_attr.h> 38 #include <exec_attr.h> 39 40 /* externs from libc */ 41 extern void _nss_db_state_destr(struct nss_db_state *); 42 43 /* externs from parse.c */ 44 extern char *_strtok_escape(char *, char *, char **); 45 extern char *_strdup_null(char *); 46 /* extern from getprofattr.c */ 47 extern int str2profattr(const char *, int, void *, char *, int); 48 49 char *_exec_wild_id(char *, const char *); 50 execstr_t *_dup_execstr(execstr_t *); 51 void _free_execstr(execstr_t *); 52 53 static char *_nsw_search_path = NULL; 54 55 /* 56 * Unsynchronized, but it affects only efficiency, not correctness 57 */ 58 59 static DEFINE_NSS_DB_ROOT(exec_root); 60 static DEFINE_NSS_GETENT(context); 61 62 void 63 _nss_initf_execattr(nss_db_params_t *p) 64 { 65 p->name = NSS_DBNAM_EXECATTR; 66 p->config_name = NSS_DBNAM_PROFATTR; /* use config for "prof_attr" */ 67 } 68 69 void 70 _nsw_initf_execattr(nss_db_params_t *p) 71 { 72 p->name = NSS_DBNAM_EXECATTR; 73 p->flags |= NSS_USE_DEFAULT_CONFIG; 74 p->default_config = _nsw_search_path; 75 } 76 77 void 78 _nsw_initf_profattr(nss_db_params_t *p) 79 { 80 p->name = NSS_DBNAM_PROFATTR; 81 p->flags |= NSS_USE_DEFAULT_CONFIG; 82 p->default_config = _nsw_search_path; 83 } 84 85 /* 86 * Return values: 0 = success, 1 = parse error, 2 = erange ... The structure 87 * pointer passed in is a structure in the caller's space wherein the field 88 * pointers would be set to areas in the buffer if need be. instring and buffer 89 * should be separate areas. 90 */ 91 int 92 str2execattr(const char *instr, int lenstr, void *ent, char *buffer, int buflen) 93 { 94 char *last = NULL; 95 char *sep = KV_TOKEN_DELIMIT; 96 execstr_t *exec = (execstr_t *)ent; 97 98 if (lenstr >= buflen) 99 return (NSS_STR_PARSE_ERANGE); 100 101 if (instr != buffer) 102 (void) strncpy(buffer, instr, buflen); 103 104 /* 105 * Remove newline that nis (yp_match) puts at the 106 * end of the entry it retrieves from the map. 107 */ 108 if (buffer[lenstr] == '\n') { 109 buffer[lenstr] = '\0'; 110 } 111 112 /* quick exit do not entry fill if not needed */ 113 if (ent == (void *)NULL) 114 return (NSS_STR_PARSE_SUCCESS); 115 116 exec->name = _strtok_escape(buffer, sep, &last); 117 exec->policy = _strtok_escape(NULL, sep, &last); 118 exec->type = _strtok_escape(NULL, sep, &last); 119 exec->res1 = _strtok_escape(NULL, sep, &last); 120 exec->res2 = _strtok_escape(NULL, sep, &last); 121 exec->id = _strtok_escape(NULL, sep, &last); 122 exec->attr = _strtok_escape(NULL, sep, &last); 123 exec->next = NULL; 124 125 return (NSS_STR_PARSE_SUCCESS); 126 } 127 128 129 void 130 _setexecattr(void) 131 { 132 nss_setent(&exec_root, _nss_initf_execattr, &context); 133 } 134 135 136 void 137 _endexecattr(void) 138 { 139 nss_endent(&exec_root, _nss_initf_execattr, &context); 140 nss_delete(&exec_root); 141 } 142 143 144 execstr_t * 145 _getexecattr(execstr_t *result, char *buffer, int buflen, int *errnop) 146 { 147 nss_status_t res; 148 nss_XbyY_args_t arg; 149 150 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2execattr); 151 res = nss_getent(&exec_root, _nss_initf_execattr, &context, &arg); 152 arg.status = res; 153 *errnop = arg.h_errno; 154 155 return ((execstr_t *)NSS_XbyY_FINI(&arg)); 156 } 157 158 execstr_t * 159 _getexecprof(char *name, 160 char *type, 161 char *id, 162 int search_flag, 163 execstr_t *result, 164 char *buffer, 165 int buflen, 166 int *errnop) 167 { 168 int getby_flag; 169 char policy_buf[BUFSIZ]; 170 const char *empty = NULL; 171 nss_status_t res = NSS_NOTFOUND; 172 nss_XbyY_args_t arg; 173 _priv_execattr _priv_exec; 174 static mutex_t _nsw_exec_lock = DEFAULTMUTEX; 175 176 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2execattr); 177 178 _priv_exec.name = (name == NULL) ? empty : (const char *)name; 179 _priv_exec.type = (type == NULL) ? empty : (const char *)type; 180 _priv_exec.id = (id == NULL) ? empty : (const char *)id; 181 #ifdef SI_SECPOLICY 182 if (sysinfo(SI_SECPOLICY, policy_buf, BUFSIZ) == -1) 183 #endif /* SI_SECPOLICY */ 184 (void) strncpy(policy_buf, DEFAULT_POLICY, BUFSIZ); 185 186 retry_policy: 187 _priv_exec.policy = IS_SEARCH_ALL(search_flag) ? empty : policy_buf; 188 _priv_exec.search_flag = search_flag; 189 _priv_exec.head_exec = NULL; 190 _priv_exec.prev_exec = NULL; 191 192 if ((name != NULL) && (id != NULL)) { 193 getby_flag = NSS_DBOP_EXECATTR_BYNAMEID; 194 } else if (name != NULL) { 195 getby_flag = NSS_DBOP_EXECATTR_BYNAME; 196 } else if (id != NULL) { 197 getby_flag = NSS_DBOP_EXECATTR_BYID; 198 } 199 200 arg.key.attrp = &(_priv_exec); 201 202 switch (getby_flag) { 203 case NSS_DBOP_EXECATTR_BYID: 204 res = nss_search(&exec_root, _nss_initf_execattr, getby_flag, 205 &arg); 206 break; 207 case NSS_DBOP_EXECATTR_BYNAMEID: 208 case NSS_DBOP_EXECATTR_BYNAME: 209 { 210 char pbuf[NSS_BUFLEN_PROFATTR]; 211 profstr_t prof; 212 nss_status_t pres; 213 nss_XbyY_args_t parg; 214 enum __nsw_parse_err pserr; 215 struct __nsw_lookup *lookups = NULL; 216 struct __nsw_switchconfig *conf = NULL; 217 218 if (conf = __nsw_getconfig(NSS_DBNAM_PROFATTR, &pserr)) 219 if ((lookups = conf->lookups) == NULL) 220 goto out; 221 NSS_XbyY_INIT(&parg, &prof, pbuf, NSS_BUFLEN_PROFATTR, 222 str2profattr); 223 parg.key.name = name; 224 do { 225 /* 226 * search the exec_attr entry only in the scope 227 * that we find the profile in. 228 * if conf = NULL, search in local files only, 229 * as we were not able to read nsswitch.conf. 230 */ 231 DEFINE_NSS_DB_ROOT(prof_root); 232 if (mutex_lock(&_nsw_exec_lock) != 0) 233 goto out; 234 _nsw_search_path = (conf == NULL) 235 ? NSS_FILES_ONLY 236 : lookups->service_name; 237 pres = nss_search(&prof_root, 238 _nsw_initf_profattr, 239 NSS_DBOP_PROFATTR_BYNAME, &parg); 240 if (pres == NSS_SUCCESS) { 241 DEFINE_NSS_DB_ROOT(pexec_root); 242 res = nss_search(&pexec_root, 243 _nsw_initf_execattr, getby_flag, 244 &arg); 245 if (pexec_root.s != NULL) 246 _nss_db_state_destr( 247 pexec_root.s); 248 } 249 if (prof_root.s != NULL) 250 _nss_db_state_destr(prof_root.s); 251 (void) mutex_unlock(&_nsw_exec_lock); 252 if ((pres == NSS_SUCCESS) || (conf == NULL)) 253 break; 254 } while (lookups && (lookups = lookups->next)); 255 } 256 break; 257 default: 258 break; 259 } 260 261 out: 262 /* 263 * If we can't find an entry for the current default policy 264 * fall back to the old "suser" policy. The nameservice is 265 * shared between different OS releases. 266 */ 267 if (!IS_SEARCH_ALL(search_flag) && 268 (res == NSS_NOTFOUND && strcmp(policy_buf, DEFAULT_POLICY) == 0)) { 269 (void) strlcpy(policy_buf, SUSER_POLICY, BUFSIZ); 270 goto retry_policy; 271 } 272 273 arg.status = res; 274 *errnop = res; 275 return ((execstr_t *)NSS_XbyY_FINI(&arg)); 276 } 277 278 279 int 280 _doexeclist(nss_XbyY_args_t *argp) 281 { 282 int status = 1; 283 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 284 execstr_t *exec = (execstr_t *)((argp->buf.result)); 285 286 if (_priv_exec->head_exec == NULL) { 287 if (_priv_exec->head_exec = _dup_execstr(exec)) 288 _priv_exec->prev_exec = _priv_exec->head_exec; 289 else 290 status = 0; 291 } else { 292 if (_priv_exec->prev_exec->next = _dup_execstr(exec)) 293 _priv_exec->prev_exec = _priv_exec->prev_exec->next; 294 else 295 status = 0; 296 } 297 (void) memset(argp->buf.buffer, NULL, argp->buf.buflen); 298 299 return (status); 300 301 } 302 303 304 /* 305 * Converts id to a wildcard string. e.g.: 306 * For type = KV_COMMAND: /usr/ccs/bin/what ---> /usr/ccs/bin/\* ---> \* 307 * For type = KV_ACTION: Dtfile;*;*;*;0 ---> *;*;*;*;* 308 * 309 * Returns NULL if id is already a wild-card. 310 */ 311 char * 312 _exec_wild_id(char *id, const char *type) 313 { 314 char c_id = '/'; 315 char *pchar = NULL; 316 317 if ((id == NULL) || (type == NULL)) 318 return (NULL); 319 320 if (strcmp(type, KV_ACTION) == 0) { 321 return ((strcmp(id, KV_ACTION_WILDCARD) == 0) ? NULL : 322 KV_ACTION_WILDCARD); 323 } else if (strcmp(type, KV_COMMAND) == 0) { 324 if ((pchar = rindex(id, c_id)) == NULL) 325 /* 326 * id = \* 327 */ 328 return (NULL); 329 else if (*(++pchar) == KV_WILDCHAR) 330 /* 331 * id = /usr/ccs/bin/\* 332 */ 333 return (pchar); 334 /* 335 * id = /usr/ccs/bin/what 336 */ 337 (void) strcpy(pchar, KV_WILDCARD); 338 return (id); 339 } 340 341 return (NULL); 342 343 } 344 345 346 execstr_t * 347 _dup_execstr(execstr_t *old_exec) 348 { 349 execstr_t *new_exec = NULL; 350 351 if (old_exec == NULL) 352 return (NULL); 353 if ((new_exec = malloc(sizeof (execstr_t))) != NULL) { 354 new_exec->name = _strdup_null(old_exec->name); 355 new_exec->type = _strdup_null(old_exec->type); 356 new_exec->policy = _strdup_null(old_exec->policy); 357 new_exec->res1 = _strdup_null(old_exec->res1); 358 new_exec->res2 = _strdup_null(old_exec->res2); 359 new_exec->id = _strdup_null(old_exec->id); 360 new_exec->attr = _strdup_null(old_exec->attr); 361 new_exec->next = old_exec->next; 362 } 363 return (new_exec); 364 } 365 366 void 367 _free_execstr(execstr_t *exec) 368 { 369 if (exec != NULL) { 370 free(exec->name); 371 free(exec->type); 372 free(exec->policy); 373 free(exec->res1); 374 free(exec->res2); 375 free(exec->id); 376 free(exec->attr); 377 _free_execstr(exec->next); 378 free(exec); 379 } 380 } 381 382 void 383 _exec_cleanup(nss_status_t res, nss_XbyY_args_t *argp) 384 { 385 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 386 387 if (res == NSS_SUCCESS) { 388 if (_priv_exec->head_exec != NULL) { 389 argp->buf.result = _priv_exec->head_exec; 390 argp->returnval = argp->buf.result; 391 } 392 } else { 393 if (_priv_exec->head_exec != NULL) 394 _free_execstr(_priv_exec->head_exec); 395 argp->returnval = NULL; 396 } 397 } 398