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-2002 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 <stdlib.h> 30 #include <string.h> 31 #include <sys/types.h> 32 #include <exec_attr.h> 33 #include <rpcsvc/ypclnt.h> 34 #include <rpcsvc/yp_prot.h> 35 #include "nis_common.h" 36 37 38 /* extern from nis_common.c */ 39 extern void massage_netdb(const char **, int *); 40 /* externs from libnsl */ 41 extern int _doexeclist(nss_XbyY_args_t *); 42 extern char *_exec_wild_id(char *, const char *); 43 extern void _exec_cleanup(nss_status_t, nss_XbyY_args_t *); 44 45 46 typedef struct __exec_nis_args { 47 int *yp_status; 48 nss_XbyY_args_t *argp; 49 } _exec_nis_args; 50 51 52 /* 53 * check_match: returns 1 if - matching entry found and no more entries needed, 54 * or, entry cannot be found because of error; 55 * returns 0 if - no matching entry found, or, 56 * matching entry found and next match needed. 57 */ 58 static int 59 check_match(nss_XbyY_args_t *argp, int check_policy) 60 { 61 execstr_t *exec = (execstr_t *)(argp->returnval); 62 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 63 const char *name = _priv_exec->name; 64 const char *type = _priv_exec->type; 65 const char *id = _priv_exec->id; 66 const char *policy = _priv_exec->policy; 67 68 if (name && id) { 69 /* 70 * NSS_DBOP_EXECATTR_BYNAMEID searched for name and id in 71 * _exec_nis_lookup already. 72 * If we're talking to pre-Solaris9 nis servers, check policy, 73 * as policy was not a searchable column then. 74 */ 75 if ((check_policy && policy && 76 (strcmp(policy, exec->policy) != 0)) || 77 (type && (strcmp(type, exec->type) != 0))) { 78 return (0); 79 } 80 } else if ((policy && exec->policy && 81 (strcmp(policy, exec->policy) != 0)) || 82 (name && exec->name && (strcmp(name, exec->name) != 0)) || 83 (type && exec->type && (strcmp(type, exec->type) != 0)) || 84 (id && exec->id && (strcmp(id, exec->id) != 0))) { 85 return (0); 86 } 87 88 return (1); 89 } 90 91 92 static nss_status_t 93 _exec_nis_parse(const char *instr, 94 int instr_len, 95 nss_XbyY_args_t *argp, 96 int check_policy) 97 { 98 int parse_stat; 99 nss_status_t res; 100 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 101 102 parse_stat = (*argp->str2ent)(instr, instr_len, argp->buf.result, 103 argp->buf.buffer, argp->buf.buflen); 104 switch (parse_stat) { 105 case NSS_STR_PARSE_SUCCESS: 106 argp->returnval = argp->buf.result; 107 if (check_match(argp, check_policy)) { 108 res = NSS_SUCCESS; 109 if (_priv_exec->search_flag == GET_ALL) { 110 if (_doexeclist(argp) == 0) { 111 res = NSS_UNAVAIL; 112 } 113 } 114 } else { 115 res = NSS_NOTFOUND; 116 } 117 break; 118 case NSS_STR_PARSE_ERANGE: 119 argp->erange = 1; 120 res = NSS_NOTFOUND; 121 break; 122 default: 123 res = NSS_UNAVAIL; 124 break; 125 } 126 127 return (res); 128 } 129 130 /* 131 * This is the callback for yp_all. It returns 0 to indicate that it wants to 132 * be called again for further key-value pairs, or returns non-zero to stop the 133 * flow of key-value pairs. If it returns a non-zero value, it is not called 134 * again. The functional value of yp_all is then 0. 135 */ 136 static int 137 _exec_nis_cb(int instatus, 138 char *inkey, 139 int inkeylen, 140 char *inval, 141 int invallen, 142 void *indata) 143 { 144 int check_policy = 1; /* always check policy for yp_all */ 145 int stop_cb; 146 const char *filter; 147 char *key = NULL; 148 nss_status_t res; 149 _exec_nis_args *eargp = (_exec_nis_args *)indata; 150 nss_XbyY_args_t *argp = eargp->argp; 151 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 152 153 if (instatus != YP_TRUE) { 154 *(eargp->yp_status) = YPERR_YPERR; 155 return (0); /* yp_all may decide otherwise... */ 156 } 157 158 filter = (_priv_exec->name) ? _priv_exec->name : _priv_exec->id; 159 160 /* 161 * yp_all does not null terminate the entry it retrieves from the 162 * map, unlike yp_match. so we do it explicitly here. 163 */ 164 inval[invallen] = '\0'; 165 166 /* 167 * Optimization: if the entry doesn't contain the filter string then 168 * it can't be the entry we want, so don't bother looking more closely 169 * at it. 170 */ 171 if ((_priv_exec->policy && 172 (strstr(inval, _priv_exec->policy) == NULL)) || 173 (strstr(inval, filter) == NULL)) { 174 *(eargp->yp_status) = YPERR_KEY; 175 return (0); 176 } 177 178 res = _exec_nis_parse(inval, invallen, argp, check_policy); 179 180 switch (res) { 181 case NSS_SUCCESS: 182 *(eargp->yp_status) = 0; 183 stop_cb = (_priv_exec->search_flag == GET_ONE); 184 break; 185 case NSS_UNAVAIL: 186 *(eargp->yp_status) = YPERR_KEY; 187 stop_cb = 1; 188 break; 189 default: 190 *(eargp->yp_status) = YPERR_YPERR; 191 stop_cb = 0; 192 break; 193 } 194 195 return (stop_cb); 196 } 197 198 static nss_status_t 199 _exec_nis_lookup(nis_backend_ptr_t be, nss_XbyY_args_t *argp, int getby_flag) 200 { 201 int ypstatus; 202 nss_status_t res = NSS_SUCCESS; 203 nss_status_t ypres; 204 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 205 206 if (getby_flag == NSS_DBOP_EXECATTR_BYNAMEID) { 207 int check_policy = 0; 208 int vallen; 209 int parse_stat; 210 char *val; 211 char key[MAX_INPUT]; 212 213 /* 214 * Try using policy as part of search key. If that fails, 215 * (it will, in case of pre-Solaris9 nis server where policy 216 * was not searchable), try again without using policy. 217 */ 218 if (snprintf(key, MAX_INPUT, "%s%s%s%s%s", _priv_exec->name, 219 KV_TOKEN_DELIMIT, _priv_exec->policy, KV_TOKEN_DELIMIT, 220 _priv_exec->id) >= MAX_INPUT) 221 return (NSS_NOTFOUND); 222 do { 223 ypres = _nss_nis_ypmatch(be->domain, NIS_MAP_EXECATTR, 224 key, &val, &vallen, &ypstatus); 225 if ((check_policy == 0) && (ypstatus == YPERR_KEY)) { 226 (void) snprintf(key, MAX_INPUT, "%s%s%s", 227 _priv_exec->name, KV_TOKEN_DELIMIT, 228 _priv_exec->id); 229 check_policy = 1; 230 continue; 231 } else if (ypres != NSS_SUCCESS) { 232 res = ypres; 233 break; 234 } else { 235 massage_netdb((const char **)&val, &vallen); 236 res = _exec_nis_parse((const char *)val, 237 vallen, argp, check_policy); 238 break; 239 } 240 } while (res == NSS_SUCCESS); 241 } else { 242 int ypstat = YPERR_YPERR; 243 struct ypall_callback cback; 244 _exec_nis_args eargs; 245 246 eargs.yp_status = &ypstat; 247 eargs.argp = argp; 248 249 cback.foreach = _exec_nis_cb; 250 cback.data = (void *)&eargs; 251 252 /* 253 * Instead of calling yp_all() doing hard lookup, we use 254 * the alternative function, __yp_all_cflookup(), to 255 * perform soft lookup when binding to nis servers with 256 * time-out control. Other than that, these two functions 257 * do exactly the same thing. 258 */ 259 ypstatus = __yp_all_cflookup((char *)(be->domain), 260 (char *)(be->enum_map), &cback, 0); 261 262 /* 263 * For GET_ALL, check if we found anything at all. 264 */ 265 if (_priv_exec->head_exec != NULL) 266 return (NSS_SUCCESS); 267 268 switch (ypstat) { 269 case 0: 270 res = NSS_SUCCESS; 271 break; 272 case YPERR_BUSY: 273 res = NSS_TRYAGAIN; 274 break; 275 default: 276 res = NSS_UNAVAIL; 277 break; 278 } 279 280 } 281 282 return (res); 283 } 284 285 /* 286 * If search for exact match for id failed, get_wild checks if we have 287 * a wild-card entry for that id. 288 */ 289 static nss_status_t 290 get_wild(nis_backend_ptr_t be, nss_XbyY_args_t *argp, int getby_flag) 291 { 292 char *orig_id = NULL; 293 char *old_id = NULL; 294 char *wild_id = NULL; 295 nss_status_t res = NSS_NOTFOUND; 296 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 297 298 orig_id = strdup(_priv_exec->id); 299 old_id = strdup(_priv_exec->id); 300 wild_id = old_id; 301 while ((wild_id = _exec_wild_id(wild_id, _priv_exec->type)) != NULL) { 302 _priv_exec->id = wild_id; 303 res = _exec_nis_lookup(be, argp, getby_flag); 304 if (res == NSS_SUCCESS) 305 break; 306 } 307 _priv_exec->id = orig_id; 308 if (old_id) 309 free(old_id); 310 311 return (res); 312 } 313 314 315 static nss_status_t 316 getbynam(nis_backend_ptr_t be, void *a) 317 { 318 nss_status_t res; 319 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 320 321 res = _exec_nis_lookup(be, argp, NSS_DBOP_EXECATTR_BYNAME); 322 323 _exec_cleanup(res, argp); 324 325 return (res); 326 } 327 328 static nss_status_t 329 getbyid(nis_backend_ptr_t be, void *a) 330 { 331 nss_status_t res; 332 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 333 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 334 335 res = _exec_nis_lookup(be, argp, NSS_DBOP_EXECATTR_BYID); 336 337 if (res != NSS_SUCCESS) 338 res = get_wild(be, argp, NSS_DBOP_EXECATTR_BYID); 339 340 _exec_cleanup(res, argp); 341 342 return (res); 343 } 344 345 346 static nss_status_t 347 getbynameid(nis_backend_ptr_t be, void *a) 348 { 349 nss_status_t res; 350 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 351 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 352 353 res = _exec_nis_lookup(be, argp, NSS_DBOP_EXECATTR_BYNAMEID); 354 355 if (res != NSS_SUCCESS) 356 res = get_wild(be, argp, NSS_DBOP_EXECATTR_BYNAMEID); 357 358 _exec_cleanup(res, argp); 359 360 return (res); 361 } 362 363 364 static nis_backend_op_t execattr_ops[] = { 365 _nss_nis_destr, 366 _nss_nis_endent, 367 _nss_nis_setent, 368 _nss_nis_getent_netdb, 369 getbynam, 370 getbyid, 371 getbynameid 372 }; 373 374 nss_backend_t * 375 _nss_nis_exec_attr_constr(const char *dummy1, 376 const char *dummy2, 377 const char *dummy3, 378 const char *dummy4, 379 const char *dummy5, 380 const char *dummy6, 381 const char *dummy7) 382 { 383 return (_nss_nis_constr(execattr_ops, 384 sizeof (execattr_ops)/sizeof (execattr_ops[0]), 385 NIS_MAP_EXECATTR)); 386 } 387