1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 1999-2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <stdlib.h> 30*0Sstevel@tonic-gate #include "files_common.h" 31*0Sstevel@tonic-gate #include <time.h> 32*0Sstevel@tonic-gate #include <exec_attr.h> 33*0Sstevel@tonic-gate #include <strings.h> 34*0Sstevel@tonic-gate #include <sys/stat.h> 35*0Sstevel@tonic-gate #include <sys/mman.h> 36*0Sstevel@tonic-gate #include <ctype.h> 37*0Sstevel@tonic-gate #include <synch.h> 38*0Sstevel@tonic-gate #include <sys/types.h> 39*0Sstevel@tonic-gate #include <sys/uio.h> 40*0Sstevel@tonic-gate #include <unistd.h> 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate /* 43*0Sstevel@tonic-gate * files/getexecattr.c -- "files" backend for nsswitch "exec_attr" database 44*0Sstevel@tonic-gate * 45*0Sstevel@tonic-gate * _execattr_files_read_line and _execattr_files_XY_all code based on 46*0Sstevel@tonic-gate * nss_files_read_line and nss_files_XY_all respectively, from files_common.c 47*0Sstevel@tonic-gate */ 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate /* externs from libnsl */ 51*0Sstevel@tonic-gate extern int _doexeclist(nss_XbyY_args_t *); 52*0Sstevel@tonic-gate extern int _readbufline(char *, int, char *, int, int *); 53*0Sstevel@tonic-gate extern char *_exec_wild_id(char *, const char *); 54*0Sstevel@tonic-gate extern void _exec_cleanup(nss_status_t, nss_XbyY_args_t *); 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate typedef int (*_exec_XY_check_func) (nss_XbyY_args_t *); 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate /* 60*0Sstevel@tonic-gate * check_match: returns 1 if matching entry found, else returns 0. 61*0Sstevel@tonic-gate */ 62*0Sstevel@tonic-gate static int 63*0Sstevel@tonic-gate check_match(nss_XbyY_args_t *argp) 64*0Sstevel@tonic-gate { 65*0Sstevel@tonic-gate _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 66*0Sstevel@tonic-gate const char *name = _priv_exec->name; 67*0Sstevel@tonic-gate const char *type = _priv_exec->type; 68*0Sstevel@tonic-gate const char *id = _priv_exec->id; 69*0Sstevel@tonic-gate const char *policy = _priv_exec->policy; 70*0Sstevel@tonic-gate execstr_t *exec = (execstr_t *)argp->returnval; 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate if ((policy && exec->policy && (strcmp(policy, exec->policy) != 0)) || 73*0Sstevel@tonic-gate (name && exec->name && (strcmp(name, exec->name) != 0)) || 74*0Sstevel@tonic-gate (type && exec->type && (strcmp(type, exec->type) != 0)) || 75*0Sstevel@tonic-gate (id && exec->id && (strcmp(id, exec->id) != 0))) { 76*0Sstevel@tonic-gate return (0); 77*0Sstevel@tonic-gate } 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate return (1); 80*0Sstevel@tonic-gate } 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate static nss_status_t 84*0Sstevel@tonic-gate _exec_files_XY_all(files_backend_ptr_t be, 85*0Sstevel@tonic-gate nss_XbyY_args_t *argp, 86*0Sstevel@tonic-gate int getby_flag) 87*0Sstevel@tonic-gate { 88*0Sstevel@tonic-gate int parse_stat = 0; 89*0Sstevel@tonic-gate int lastlen = 0; 90*0Sstevel@tonic-gate int exec_fd = 0; 91*0Sstevel@tonic-gate int f_size = 0; 92*0Sstevel@tonic-gate time_t f_time = 0; 93*0Sstevel@tonic-gate static time_t read_time = 0; 94*0Sstevel@tonic-gate char *key = NULL; 95*0Sstevel@tonic-gate char *first; 96*0Sstevel@tonic-gate char *last; 97*0Sstevel@tonic-gate static char *f_buf = NULL; 98*0Sstevel@tonic-gate struct stat f_stat; 99*0Sstevel@tonic-gate nss_status_t res = NSS_NOTFOUND; 100*0Sstevel@tonic-gate _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 101*0Sstevel@tonic-gate static rwlock_t exec_lock; 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate if (((be->buf == NULL) && 104*0Sstevel@tonic-gate ((be->buf = (char *)calloc(1, be->minbuf)) == NULL)) || 105*0Sstevel@tonic-gate (be->filename == NULL) || 106*0Sstevel@tonic-gate (rw_rdlock(&exec_lock) != 0)) { 107*0Sstevel@tonic-gate return (NSS_UNAVAIL); 108*0Sstevel@tonic-gate } 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate /* 111*0Sstevel@tonic-gate * check the size and the time stamp on the file 112*0Sstevel@tonic-gate */ 113*0Sstevel@tonic-gate if (stat(be->filename, &f_stat) != 0) { 114*0Sstevel@tonic-gate (void) _nss_files_endent(be, 0); 115*0Sstevel@tonic-gate (void) rw_unlock(&exec_lock); 116*0Sstevel@tonic-gate return (NSS_UNAVAIL); 117*0Sstevel@tonic-gate } 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate f_size = f_stat.st_size; 120*0Sstevel@tonic-gate f_time = f_stat.st_mtime; 121*0Sstevel@tonic-gate 122*0Sstevel@tonic-gate while (f_time > read_time) { 123*0Sstevel@tonic-gate /* 124*0Sstevel@tonic-gate * file has been modified since we last read it. 125*0Sstevel@tonic-gate * read it into the buffer with rw lock. 126*0Sstevel@tonic-gate */ 127*0Sstevel@tonic-gate (void) rw_unlock(&exec_lock); 128*0Sstevel@tonic-gate if (rw_wrlock(&exec_lock) != 0) { 129*0Sstevel@tonic-gate (void) _nss_files_endent(be, 0); 130*0Sstevel@tonic-gate return (NSS_UNAVAIL); 131*0Sstevel@tonic-gate } 132*0Sstevel@tonic-gate if ((be->f = __nsl_fopen(be->filename, "r")) == 0) { 133*0Sstevel@tonic-gate (void) _nss_files_endent(be, 0); 134*0Sstevel@tonic-gate (void) rw_unlock(&exec_lock); 135*0Sstevel@tonic-gate return (NSS_UNAVAIL); 136*0Sstevel@tonic-gate } 137*0Sstevel@tonic-gate exec_fd = __nsl_fileno(be->f); 138*0Sstevel@tonic-gate if (f_buf != NULL) 139*0Sstevel@tonic-gate free(f_buf); 140*0Sstevel@tonic-gate if ((f_buf = malloc(f_size)) == NULL) { 141*0Sstevel@tonic-gate (void) _nss_files_endent(be, 0); 142*0Sstevel@tonic-gate (void) rw_unlock(&exec_lock); 143*0Sstevel@tonic-gate return (NSS_UNAVAIL); 144*0Sstevel@tonic-gate } 145*0Sstevel@tonic-gate if (read(exec_fd, f_buf, f_size) < f_size) { 146*0Sstevel@tonic-gate free(f_buf); 147*0Sstevel@tonic-gate (void) _nss_files_endent(be, 0); 148*0Sstevel@tonic-gate (void) rw_unlock(&exec_lock); 149*0Sstevel@tonic-gate return (NSS_UNAVAIL); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate read_time = f_time; 152*0Sstevel@tonic-gate (void) rw_unlock(&exec_lock); 153*0Sstevel@tonic-gate /* 154*0Sstevel@tonic-gate * verify that the file did not change after 155*0Sstevel@tonic-gate * we read it. 156*0Sstevel@tonic-gate */ 157*0Sstevel@tonic-gate if (rw_rdlock(&exec_lock) != 0) { 158*0Sstevel@tonic-gate free(f_buf); 159*0Sstevel@tonic-gate (void) _nss_files_endent(be, 0); 160*0Sstevel@tonic-gate return (NSS_UNAVAIL); 161*0Sstevel@tonic-gate } 162*0Sstevel@tonic-gate if (stat(be->filename, &f_stat) != 0) { 163*0Sstevel@tonic-gate free(f_buf); 164*0Sstevel@tonic-gate (void) _nss_files_endent(be, 0); 165*0Sstevel@tonic-gate (void) rw_unlock(&exec_lock); 166*0Sstevel@tonic-gate return (NSS_UNAVAIL); 167*0Sstevel@tonic-gate } 168*0Sstevel@tonic-gate f_size = f_stat.st_size; 169*0Sstevel@tonic-gate f_time = f_stat.st_mtime; 170*0Sstevel@tonic-gate } 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate res = NSS_NOTFOUND; 173*0Sstevel@tonic-gate while (1) { 174*0Sstevel@tonic-gate int linelen = 0; 175*0Sstevel@tonic-gate int check_stat = 0; 176*0Sstevel@tonic-gate char *instr = be->buf; 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate linelen = _readbufline(f_buf, f_size, instr, be->minbuf, 179*0Sstevel@tonic-gate &lastlen); 180*0Sstevel@tonic-gate if (linelen < 0) { 181*0Sstevel@tonic-gate /* End of file */ 182*0Sstevel@tonic-gate argp->erange = 0; 183*0Sstevel@tonic-gate break; 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate /* 187*0Sstevel@tonic-gate * If the entry doesn't contain the filter string then 188*0Sstevel@tonic-gate * it can't be the entry we want, so don't bother looking 189*0Sstevel@tonic-gate * more closely at it. 190*0Sstevel@tonic-gate */ 191*0Sstevel@tonic-gate switch (getby_flag) { 192*0Sstevel@tonic-gate case NSS_DBOP_EXECATTR_BYNAME: 193*0Sstevel@tonic-gate if (strstr(instr, _priv_exec->name) == NULL) 194*0Sstevel@tonic-gate continue; 195*0Sstevel@tonic-gate break; 196*0Sstevel@tonic-gate case NSS_DBOP_EXECATTR_BYID: 197*0Sstevel@tonic-gate if (strstr(instr, _priv_exec->id) == NULL) 198*0Sstevel@tonic-gate continue; 199*0Sstevel@tonic-gate break; 200*0Sstevel@tonic-gate case NSS_DBOP_EXECATTR_BYNAMEID: 201*0Sstevel@tonic-gate if ((strstr(instr, _priv_exec->name) == NULL) || 202*0Sstevel@tonic-gate (strstr(instr, _priv_exec->id) == NULL)) 203*0Sstevel@tonic-gate continue; 204*0Sstevel@tonic-gate break; 205*0Sstevel@tonic-gate default: 206*0Sstevel@tonic-gate break; 207*0Sstevel@tonic-gate } 208*0Sstevel@tonic-gate if ((strstr(instr, _priv_exec->policy) == NULL) || 209*0Sstevel@tonic-gate ((_priv_exec->type != NULL) && 210*0Sstevel@tonic-gate (strstr(instr, _priv_exec->type) == NULL))) 211*0Sstevel@tonic-gate continue; 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate /* 214*0Sstevel@tonic-gate * Get rid of white spaces, comments etc. 215*0Sstevel@tonic-gate */ 216*0Sstevel@tonic-gate if ((last = strchr(instr, '#')) == NULL) 217*0Sstevel@tonic-gate last = instr + linelen; 218*0Sstevel@tonic-gate *last-- = '\0'; /* Nuke '\n' or #comment */ 219*0Sstevel@tonic-gate /* 220*0Sstevel@tonic-gate * Skip leading whitespace. Normally there isn't any, 221*0Sstevel@tonic-gate * so it's not worth calling strspn(). 222*0Sstevel@tonic-gate */ 223*0Sstevel@tonic-gate for (first = instr; isspace(*first); first++) 224*0Sstevel@tonic-gate ; 225*0Sstevel@tonic-gate if (*first == '\0') 226*0Sstevel@tonic-gate continue; 227*0Sstevel@tonic-gate /* 228*0Sstevel@tonic-gate * Found something non-blank on the line. Skip back 229*0Sstevel@tonic-gate * over any trailing whitespace; since we know there's 230*0Sstevel@tonic-gate * non-whitespace earlier in the line, checking for 231*0Sstevel@tonic-gate * termination is easy. 232*0Sstevel@tonic-gate */ 233*0Sstevel@tonic-gate while (isspace(*last)) 234*0Sstevel@tonic-gate --last; 235*0Sstevel@tonic-gate linelen = last - first + 1; 236*0Sstevel@tonic-gate if (first != instr) 237*0Sstevel@tonic-gate instr = first; 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate /* 240*0Sstevel@tonic-gate * Parse the entry. 241*0Sstevel@tonic-gate */ 242*0Sstevel@tonic-gate argp->returnval = NULL; 243*0Sstevel@tonic-gate parse_stat = (*argp->str2ent)(instr, linelen, argp->buf.result, 244*0Sstevel@tonic-gate argp->buf.buffer, argp->buf.buflen); 245*0Sstevel@tonic-gate if (parse_stat == NSS_STR_PARSE_SUCCESS) { 246*0Sstevel@tonic-gate argp->returnval = argp->buf.result; 247*0Sstevel@tonic-gate if (check_match(argp)) { 248*0Sstevel@tonic-gate res = NSS_SUCCESS; 249*0Sstevel@tonic-gate if (_priv_exec->search_flag == GET_ONE) { 250*0Sstevel@tonic-gate break; 251*0Sstevel@tonic-gate } else if (_doexeclist(argp) == 0) { 252*0Sstevel@tonic-gate res = NSS_UNAVAIL; 253*0Sstevel@tonic-gate break; 254*0Sstevel@tonic-gate } 255*0Sstevel@tonic-gate } else { 256*0Sstevel@tonic-gate argp->returnval = NULL; 257*0Sstevel@tonic-gate memset(argp->buf.buffer, NULL, 258*0Sstevel@tonic-gate argp->buf.buflen); 259*0Sstevel@tonic-gate } 260*0Sstevel@tonic-gate } else if (parse_stat == NSS_STR_PARSE_ERANGE) { 261*0Sstevel@tonic-gate argp->erange = 1; 262*0Sstevel@tonic-gate break; 263*0Sstevel@tonic-gate } /* else if (parse_stat == NSS_STR_PARSE_PARSE) don't care ! */ 264*0Sstevel@tonic-gate } 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate (void) _nss_files_endent(be, 0); 267*0Sstevel@tonic-gate (void) rw_unlock(&exec_lock); 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate return (res); 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate /* 274*0Sstevel@tonic-gate * If search for exact match for id failed, get_wild checks if we have 275*0Sstevel@tonic-gate * a wild-card entry for that id. 276*0Sstevel@tonic-gate */ 277*0Sstevel@tonic-gate static nss_status_t 278*0Sstevel@tonic-gate get_wild(files_backend_ptr_t be, nss_XbyY_args_t *argp, int getby_flag) 279*0Sstevel@tonic-gate { 280*0Sstevel@tonic-gate char *orig_id = NULL; 281*0Sstevel@tonic-gate char *old_id = NULL; 282*0Sstevel@tonic-gate char *wild_id = NULL; 283*0Sstevel@tonic-gate nss_status_t res = NSS_NOTFOUND; 284*0Sstevel@tonic-gate _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate orig_id = strdup(_priv_exec->id); 287*0Sstevel@tonic-gate old_id = strdup(_priv_exec->id); 288*0Sstevel@tonic-gate wild_id = old_id; 289*0Sstevel@tonic-gate while ((wild_id = _exec_wild_id(wild_id, _priv_exec->type)) != NULL) { 290*0Sstevel@tonic-gate _priv_exec->id = wild_id; 291*0Sstevel@tonic-gate res = _exec_files_XY_all(be, argp, getby_flag); 292*0Sstevel@tonic-gate if (res == NSS_SUCCESS) 293*0Sstevel@tonic-gate break; 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate _priv_exec->id = orig_id; 296*0Sstevel@tonic-gate if (old_id) 297*0Sstevel@tonic-gate free(old_id); 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate return (res); 300*0Sstevel@tonic-gate } 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate static nss_status_t 304*0Sstevel@tonic-gate getbynam(files_backend_ptr_t be, void *a) 305*0Sstevel@tonic-gate { 306*0Sstevel@tonic-gate nss_status_t res; 307*0Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate res = _exec_files_XY_all(be, argp, NSS_DBOP_EXECATTR_BYNAME); 310*0Sstevel@tonic-gate 311*0Sstevel@tonic-gate _exec_cleanup(res, argp); 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate return (res); 314*0Sstevel@tonic-gate } 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate static nss_status_t 318*0Sstevel@tonic-gate getbyid(files_backend_ptr_t be, void *a) 319*0Sstevel@tonic-gate { 320*0Sstevel@tonic-gate nss_status_t res; 321*0Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 322*0Sstevel@tonic-gate _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate res = _exec_files_XY_all(be, argp, NSS_DBOP_EXECATTR_BYID); 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate if (res != NSS_SUCCESS) 327*0Sstevel@tonic-gate res = get_wild(be, argp, NSS_DBOP_EXECATTR_BYID); 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate _exec_cleanup(res, argp); 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate return (res); 332*0Sstevel@tonic-gate } 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate static nss_status_t 336*0Sstevel@tonic-gate getbynameid(files_backend_ptr_t be, void *a) 337*0Sstevel@tonic-gate { 338*0Sstevel@tonic-gate nss_status_t res; 339*0Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 340*0Sstevel@tonic-gate _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate res = _exec_files_XY_all(be, argp, NSS_DBOP_EXECATTR_BYNAMEID); 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate if (res != NSS_SUCCESS) 345*0Sstevel@tonic-gate res = get_wild(be, argp, NSS_DBOP_EXECATTR_BYNAMEID); 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate _exec_cleanup(res, argp); 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate return (res); 350*0Sstevel@tonic-gate } 351*0Sstevel@tonic-gate 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate static files_backend_op_t execattr_ops[] = { 354*0Sstevel@tonic-gate _nss_files_destr, 355*0Sstevel@tonic-gate _nss_files_endent, 356*0Sstevel@tonic-gate _nss_files_setent, 357*0Sstevel@tonic-gate _nss_files_getent_netdb, 358*0Sstevel@tonic-gate getbynam, 359*0Sstevel@tonic-gate getbyid, 360*0Sstevel@tonic-gate getbynameid 361*0Sstevel@tonic-gate }; 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate nss_backend_t * 364*0Sstevel@tonic-gate _nss_files_exec_attr_constr(const char *dummy1, 365*0Sstevel@tonic-gate const char *dummy2, 366*0Sstevel@tonic-gate const char *dummy3, 367*0Sstevel@tonic-gate const char *dummy4, 368*0Sstevel@tonic-gate const char *dummy5, 369*0Sstevel@tonic-gate const char *dummy6, 370*0Sstevel@tonic-gate const char *dummy7) 371*0Sstevel@tonic-gate { 372*0Sstevel@tonic-gate return (_nss_files_constr(execattr_ops, 373*0Sstevel@tonic-gate sizeof (execattr_ops)/sizeof (execattr_ops[0]), 374*0Sstevel@tonic-gate EXECATTR_FILENAME, 375*0Sstevel@tonic-gate NSS_LINELEN_EXECATTR, 376*0Sstevel@tonic-gate NULL)); 377*0Sstevel@tonic-gate } 378