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