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 * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 27 */ 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 nss_status_t res = NSS_NOTFOUND; 174 nss_XbyY_args_t arg; 175 _priv_execattr _priv_exec; 176 static mutex_t _nsw_exec_lock = DEFAULTMUTEX; 177 178 if ((name != NULL) && (id != NULL)) { 179 getby_flag = NSS_DBOP_EXECATTR_BYNAMEID; 180 } else if (name != NULL) { 181 getby_flag = NSS_DBOP_EXECATTR_BYNAME; 182 } else if (id != NULL) { 183 getby_flag = NSS_DBOP_EXECATTR_BYID; 184 } else { 185 return (NULL); 186 } 187 188 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2execattr); 189 190 _priv_exec.name = name; 191 _priv_exec.type = type; 192 _priv_exec.id = id; 193 #ifdef SI_SECPOLICY 194 if (sysinfo(SI_SECPOLICY, policy_buf, BUFSIZ) == -1) 195 #endif /* SI_SECPOLICY */ 196 (void) strncpy(policy_buf, DEFAULT_POLICY, BUFSIZ); 197 198 retry_policy: 199 _priv_exec.policy = IS_SEARCH_ALL(search_flag) ? NULL : policy_buf; 200 _priv_exec.search_flag = search_flag; 201 _priv_exec.head_exec = NULL; 202 _priv_exec.prev_exec = NULL; 203 204 arg.key.attrp = &(_priv_exec); 205 206 switch (getby_flag) { 207 case NSS_DBOP_EXECATTR_BYID: 208 res = nss_search(&exec_root, _nss_initf_execattr, getby_flag, 209 &arg); 210 break; 211 case NSS_DBOP_EXECATTR_BYNAMEID: 212 case NSS_DBOP_EXECATTR_BYNAME: 213 { 214 char pbuf[NSS_BUFLEN_PROFATTR]; 215 profstr_t prof; 216 nss_status_t pres; 217 nss_XbyY_args_t parg; 218 enum __nsw_parse_err pserr; 219 struct __nsw_lookup *lookups = NULL; 220 struct __nsw_switchconfig *conf = NULL; 221 222 if (conf = __nsw_getconfig(NSS_DBNAM_PROFATTR, &pserr)) 223 if ((lookups = conf->lookups) == NULL) 224 goto out; 225 NSS_XbyY_INIT(&parg, &prof, pbuf, NSS_BUFLEN_PROFATTR, 226 str2profattr); 227 parg.key.name = name; 228 do { 229 /* 230 * search the exec_attr entry only in the scope 231 * that we find the profile in. 232 * if conf = NULL, search in local files only, 233 * as we were not able to read nsswitch.conf. 234 */ 235 DEFINE_NSS_DB_ROOT(prof_root); 236 if (mutex_lock(&_nsw_exec_lock) != 0) 237 goto out; 238 _nsw_search_path = (conf == NULL) 239 ? NSS_FILES_ONLY 240 : lookups->service_name; 241 pres = nss_search(&prof_root, 242 _nsw_initf_profattr, 243 NSS_DBOP_PROFATTR_BYNAME, &parg); 244 if (pres == NSS_SUCCESS) { 245 DEFINE_NSS_DB_ROOT(pexec_root); 246 res = nss_search(&pexec_root, 247 _nsw_initf_execattr, getby_flag, 248 &arg); 249 if (pexec_root.s != NULL) 250 _nss_db_state_destr( 251 pexec_root.s); 252 } 253 if (prof_root.s != NULL) 254 _nss_db_state_destr(prof_root.s); 255 (void) mutex_unlock(&_nsw_exec_lock); 256 if ((pres == NSS_SUCCESS) || (conf == NULL)) 257 break; 258 } while (lookups && (lookups = lookups->next)); 259 } 260 break; 261 default: 262 break; 263 } 264 265 out: 266 /* 267 * If we can't find an entry for the current default policy 268 * fall back to the old "suser" policy. The nameservice is 269 * shared between different OS releases. 270 */ 271 if (!IS_SEARCH_ALL(search_flag) && 272 (res == NSS_NOTFOUND && strcmp(policy_buf, DEFAULT_POLICY) == 0)) { 273 (void) strlcpy(policy_buf, SUSER_POLICY, BUFSIZ); 274 goto retry_policy; 275 } 276 277 arg.status = res; 278 *errnop = res; 279 return ((execstr_t *)NSS_XbyY_FINI(&arg)); 280 } 281 282 283 int 284 _doexeclist(nss_XbyY_args_t *argp) 285 { 286 int status = 1; 287 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 288 execstr_t *exec = (execstr_t *)((argp->buf.result)); 289 290 if (_priv_exec->head_exec == NULL) { 291 if (_priv_exec->head_exec = _dup_execstr(exec)) 292 _priv_exec->prev_exec = _priv_exec->head_exec; 293 else 294 status = 0; 295 } else { 296 if (_priv_exec->prev_exec->next = _dup_execstr(exec)) 297 _priv_exec->prev_exec = _priv_exec->prev_exec->next; 298 else 299 status = 0; 300 } 301 (void) memset(argp->buf.buffer, NULL, argp->buf.buflen); 302 303 return (status); 304 305 } 306 307 308 /* 309 * Converts id to a wildcard string. e.g.: 310 * For type = KV_COMMAND: /usr/ccs/bin/what ---> /usr/ccs/bin/\* ---> \* 311 * For type = KV_ACTION: Dtfile;*;*;*;0 ---> *;*;*;*;* 312 * 313 * Returns NULL if id is already a wild-card. 314 */ 315 char * 316 _exec_wild_id(char *id, const char *type) 317 { 318 char c_id = '/'; 319 char *pchar = NULL; 320 321 if ((id == NULL) || (type == NULL)) 322 return (NULL); 323 324 if (strcmp(type, KV_ACTION) == 0) { 325 return ((strcmp(id, KV_ACTION_WILDCARD) == 0) ? NULL : 326 KV_ACTION_WILDCARD); 327 } else if (strcmp(type, KV_COMMAND) == 0) { 328 if ((pchar = rindex(id, c_id)) == NULL) 329 /* 330 * id = \* 331 */ 332 return (NULL); 333 else if (*(++pchar) == KV_WILDCHAR) 334 /* 335 * id = /usr/ccs/bin/\* 336 */ 337 return (pchar); 338 /* 339 * id = /usr/ccs/bin/what 340 */ 341 (void) strcpy(pchar, KV_WILDCARD); 342 return (id); 343 } 344 345 return (NULL); 346 347 } 348 349 350 execstr_t * 351 _dup_execstr(execstr_t *old_exec) 352 { 353 execstr_t *new_exec = NULL; 354 355 if (old_exec == NULL) 356 return (NULL); 357 if ((new_exec = malloc(sizeof (execstr_t))) != NULL) { 358 new_exec->name = _strdup_null(old_exec->name); 359 new_exec->type = _strdup_null(old_exec->type); 360 new_exec->policy = _strdup_null(old_exec->policy); 361 new_exec->res1 = _strdup_null(old_exec->res1); 362 new_exec->res2 = _strdup_null(old_exec->res2); 363 new_exec->id = _strdup_null(old_exec->id); 364 new_exec->attr = _strdup_null(old_exec->attr); 365 new_exec->next = old_exec->next; 366 } 367 return (new_exec); 368 } 369 370 void 371 _free_execstr(execstr_t *exec) 372 { 373 if (exec != NULL) { 374 free(exec->name); 375 free(exec->type); 376 free(exec->policy); 377 free(exec->res1); 378 free(exec->res2); 379 free(exec->id); 380 free(exec->attr); 381 _free_execstr(exec->next); 382 free(exec); 383 } 384 } 385 386 void 387 _exec_cleanup(nss_status_t res, nss_XbyY_args_t *argp) 388 { 389 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 390 391 if (res == NSS_SUCCESS) { 392 if (_priv_exec->head_exec != NULL) { 393 argp->buf.result = _priv_exec->head_exec; 394 argp->returnval = argp->buf.result; 395 } 396 } else { 397 if (_priv_exec->head_exec != NULL) 398 _free_execstr(_priv_exec->head_exec); 399 argp->returnval = NULL; 400 } 401 } 402