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