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 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #include "mt.h" 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <sys/types.h> 34 #include <nss_dbdefs.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 p->name = NSS_DBNAM_EXECATTR; 70 p->config_name = NSS_DBNAM_PROFATTR; /* use config for "prof_attr" */ 71 } 72 73 void 74 _nsw_initf_execattr(nss_db_params_t *p) 75 { 76 p->name = NSS_DBNAM_EXECATTR; 77 p->flags |= NSS_USE_DEFAULT_CONFIG; 78 p->default_config = _nsw_search_path; 79 } 80 81 void 82 _nsw_initf_profattr(nss_db_params_t *p) 83 { 84 p->name = NSS_DBNAM_PROFATTR; 85 p->flags |= NSS_USE_DEFAULT_CONFIG; 86 p->default_config = _nsw_search_path; 87 } 88 89 /* 90 * Return values: 0 = success, 1 = parse error, 2 = erange ... The structure 91 * pointer passed in is a structure in the caller's space wherein the field 92 * pointers would be set to areas in the buffer if need be. instring and buffer 93 * should be separate areas. 94 */ 95 int 96 str2execattr(const char *instr, int lenstr, void *ent, char *buffer, int buflen) 97 { 98 char *last = NULL; 99 char *sep = KV_TOKEN_DELIMIT; 100 execstr_t *exec = (execstr_t *)ent; 101 102 if (exec == NULL) 103 return (NSS_STR_PARSE_PARSE); 104 105 if ((instr >= buffer && (buffer + buflen) > instr) || 106 (buffer >= instr && (instr + lenstr) > buffer)) 107 return (NSS_STR_PARSE_PARSE); 108 if (lenstr >= buflen) 109 return (NSS_STR_PARSE_ERANGE); 110 (void) strncpy(buffer, instr, buflen); 111 /* 112 * Remove newline that nis (yp_match) puts at the 113 * end of the entry it retrieves from the map. 114 */ 115 if (buffer[lenstr] == '\n') { 116 buffer[lenstr] = '\0'; 117 } 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 _nss_db_state_destr(pexec_root.s); 249 } 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 (res == NSS_NOTFOUND && strcmp(policy_buf, DEFAULT_POLICY) == 0) { 268 (void) strlcpy(policy_buf, SUSER_POLICY, BUFSIZ); 269 goto retry_policy; 270 } 271 272 arg.status = res; 273 *errnop = res; 274 return ((execstr_t *)NSS_XbyY_FINI(&arg)); 275 } 276 277 278 int 279 _doexeclist(nss_XbyY_args_t *argp) 280 { 281 int status = 1; 282 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 283 execstr_t *exec = (execstr_t *)((argp->buf.result)); 284 285 if (_priv_exec->head_exec == NULL) { 286 if (_priv_exec->head_exec = _dup_execstr(exec)) 287 _priv_exec->prev_exec = _priv_exec->head_exec; 288 else 289 status = 0; 290 } else { 291 if (_priv_exec->prev_exec->next = _dup_execstr(exec)) 292 _priv_exec->prev_exec = _priv_exec->prev_exec->next; 293 else 294 status = 0; 295 } 296 (void) memset(argp->buf.buffer, NULL, argp->buf.buflen); 297 298 return (status); 299 300 } 301 302 303 /* 304 * Converts id to a wildcard string. e.g.: 305 * For type = KV_COMMAND: /usr/ccs/bin/what ---> /usr/ccs/bin/\* ---> \* 306 * For type = KV_ACTION: Dtfile;*;*;*;0 ---> *;*;*;*;* 307 * 308 * Returns NULL if id is already a wild-card. 309 */ 310 char * 311 _exec_wild_id(char *id, const char *type) 312 { 313 char c_id = '/'; 314 char *pchar = NULL; 315 316 if ((id == NULL) || (type == NULL)) 317 return (NULL); 318 319 if (strcmp(type, KV_ACTION) == 0) { 320 return ((strcmp(id, KV_ACTION_WILDCARD) == 0) ? NULL : 321 KV_ACTION_WILDCARD); 322 } else if (strcmp(type, KV_COMMAND) == 0) { 323 if ((pchar = rindex(id, c_id)) == NULL) 324 /* 325 * id = \* 326 */ 327 return (NULL); 328 else if (*(++pchar) == KV_WILDCHAR) 329 /* 330 * id = /usr/ccs/bin/\* 331 */ 332 return (pchar); 333 /* 334 * id = /usr/ccs/bin/what 335 */ 336 (void) strcpy(pchar, KV_WILDCARD); 337 return (id); 338 } 339 340 return (NULL); 341 342 } 343 344 345 execstr_t * 346 _dup_execstr(execstr_t *old_exec) 347 { 348 execstr_t *new_exec = NULL; 349 350 if (old_exec == NULL) 351 return (NULL); 352 if ((new_exec = malloc(sizeof (execstr_t))) != NULL) { 353 new_exec->name = _strdup_null(old_exec->name); 354 new_exec->type = _strdup_null(old_exec->type); 355 new_exec->policy = _strdup_null(old_exec->policy); 356 new_exec->res1 = _strdup_null(old_exec->res1); 357 new_exec->res2 = _strdup_null(old_exec->res2); 358 new_exec->id = _strdup_null(old_exec->id); 359 new_exec->attr = _strdup_null(old_exec->attr); 360 new_exec->next = old_exec->next; 361 } 362 return (new_exec); 363 } 364 365 void 366 _free_execstr(execstr_t *exec) 367 { 368 if (exec != NULL) { 369 free(exec->name); 370 free(exec->type); 371 free(exec->policy); 372 free(exec->res1); 373 free(exec->res2); 374 free(exec->id); 375 free(exec->attr); 376 _free_execstr(exec->next); 377 free(exec); 378 } 379 } 380 381 void 382 _exec_cleanup(nss_status_t res, nss_XbyY_args_t *argp) 383 { 384 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 385 386 if (res == NSS_SUCCESS) { 387 if (_priv_exec->head_exec != NULL) { 388 argp->buf.result = _priv_exec->head_exec; 389 argp->returnval = argp->buf.result; 390 } 391 } else { 392 if (_priv_exec->head_exec != NULL) 393 _free_execstr(_priv_exec->head_exec); 394 argp->returnval = NULL; 395 } 396 } 397