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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <secdb.h> 29 #include <exec_attr.h> 30 #include "ldap_common.h" 31 32 33 /* exec_attr attributes filters */ 34 #define ISWILD(x) (x == NULL) ? "*" : x 35 #define _EXEC_NAME "cn" 36 #define _EXEC_POLICY "SolarisKernelSecurityPolicy" 37 #define _EXEC_TYPE "SolarisProfileType" 38 #define _EXEC_RES1 "SolarisAttrRes1" 39 #define _EXEC_RES2 "SolarisAttrRes2" 40 #define _EXEC_ID "SolarisProfileId" 41 #define _EXEC_ATTRS "SolarisAttrKeyValue" 42 #define _EXEC_GETEXECNAME "(&(objectClass=SolarisExecAttr)(cn=%s)"\ 43 "(SolarisKernelSecurityPolicy=%s)"\ 44 "(SolarisProfileType=%s))" 45 #define _EXEC_GETEXECNAME_SSD "(&(%%s)(cn=%s)"\ 46 "(SolarisKernelSecurityPolicy=%s)"\ 47 "(SolarisProfileType=%s))" 48 #define _EXEC_GETEXECID "(&(objectClass=SolarisExecAttr)"\ 49 "(SolarisProfileId=%s)"\ 50 "(SolarisKernelSecurityPolicy=%s)"\ 51 "(SolarisProfileType=%s))" 52 #define _EXEC_GETEXECID_SSD "(&(%%s)"\ 53 "(SolarisProfileId=%s)"\ 54 "(SolarisKernelSecurityPolicy=%s)"\ 55 "(SolarisProfileType=%s))" 56 #define _EXEC_GETEXECNAMEID "(&(objectClass=SolarisExecAttr)(cn=%s)"\ 57 "(SolarisProfileId=%s)"\ 58 "(SolarisKernelSecurityPolicy=%s)"\ 59 "(SolarisProfileType=%s))" 60 #define _EXEC_GETEXECNAMEID_SSD "(&(%%s)(cn=%s)"\ 61 "(SolarisProfileId=%s)"\ 62 "(SolarisKernelSecurityPolicy=%s)"\ 63 "(SolarisProfileType=%s))" 64 65 66 /* from libnsl */ 67 extern int _doexeclist(nss_XbyY_args_t *); 68 extern char *_exec_wild_id(char *, const char *); 69 extern void _exec_cleanup(nss_status_t, nss_XbyY_args_t *); 70 71 72 static const char *exec_attrs[] = { 73 _EXEC_NAME, 74 _EXEC_POLICY, 75 _EXEC_TYPE, 76 _EXEC_RES1, 77 _EXEC_RES2, 78 _EXEC_ID, 79 _EXEC_ATTRS, 80 (char *)NULL 81 }; 82 83 84 #ifdef DEBUG 85 static void 86 _print_execstr(execstr_t *exec) 87 { 88 89 (void) fprintf(stdout, " exec-name: [%s]\n", exec->name); 90 if (exec->policy != (char *)NULL) { 91 (void) fprintf(stdout, " policy: [%s]\n", exec->policy); 92 } 93 if (exec->type != (char *)NULL) { 94 (void) fprintf(stdout, " type: [%s]\n", exec->type); 95 } 96 if (exec->res1 != (char *)NULL) { 97 (void) fprintf(stdout, " res1: [%s]\n", exec->res1); 98 } 99 if (exec->res2 != (char *)NULL) { 100 (void) fprintf(stdout, " res2: [%s]\n", exec->res2); 101 } 102 if (exec->id != (char *)NULL) { 103 (void) fprintf(stdout, " id: [%s]\n", exec->id); 104 } 105 if (exec->attr != (char *)NULL) { 106 (void) fprintf(stdout, " attr: [%s]\n", exec->attr); 107 } 108 if (exec->next != (execstr_t *)NULL) { 109 (void) fprintf(stdout, " next: [%s]\n", exec->next->name); 110 (void) fprintf(stdout, "\n"); 111 _print_execstr(exec->next); 112 } 113 } 114 #endif /* DEBUG */ 115 116 117 static int 118 _exec_ldap_exec2ent(ns_ldap_entry_t *entry, nss_XbyY_args_t *argp) 119 { 120 121 int i; 122 unsigned long len = 0L; 123 int buflen = (int)0; 124 char *nullstring = (char *)NULL; 125 char *buffer = (char *)NULL; 126 char *ceiling = (char *)NULL; 127 execstr_t *exec = (execstr_t *)NULL; 128 ns_ldap_attr_t *attrptr; 129 130 buffer = argp->buf.buffer; 131 buflen = (size_t)argp->buf.buflen; 132 (void) memset(argp->buf.buffer, 0, buflen); 133 exec = (execstr_t *)(argp->buf.result); 134 ceiling = buffer + buflen; 135 exec->name = (char *)NULL; 136 exec->policy = (char *)NULL; 137 exec->type = (char *)NULL; 138 exec->res1 = (char *)NULL; 139 exec->res2 = (char *)NULL; 140 exec->id = (char *)NULL; 141 exec->attr = (char *)NULL; 142 143 for (i = 0; i < entry->attr_count; i++) { 144 attrptr = entry->attr_pair[i]; 145 if (attrptr == NULL) { 146 return ((int)NSS_STR_PARSE_PARSE); 147 } 148 if (strcasecmp(attrptr->attrname, _EXEC_NAME) == 0) { 149 if ((attrptr->attrvalue[0] == NULL) || 150 (len = strlen(attrptr->attrvalue[0])) < 1) { 151 return ((int)NSS_STR_PARSE_PARSE); 152 } 153 exec->name = buffer; 154 buffer += len + 1; 155 if (buffer >= ceiling) { 156 return ((int)NSS_STR_PARSE_ERANGE); 157 } 158 (void) strcpy(exec->name, attrptr->attrvalue[0]); 159 continue; 160 } 161 if (strcasecmp(attrptr->attrname, _EXEC_POLICY) == 0) { 162 if ((attrptr->attrvalue[0] == NULL) || 163 (len = strlen(attrptr->attrvalue[0])) < 1) { 164 exec->policy = nullstring; 165 } else { 166 exec->policy = buffer; 167 buffer += len + 1; 168 if (buffer >= ceiling) { 169 return ((int)NSS_STR_PARSE_ERANGE); 170 } 171 (void) strcpy(exec->policy, 172 attrptr->attrvalue[0]); 173 } 174 continue; 175 } 176 if (strcasecmp(attrptr->attrname, _EXEC_TYPE) == 0) { 177 if ((attrptr->attrvalue[0] == NULL) || 178 (len = strlen(attrptr->attrvalue[0])) < 1) { 179 exec->type = nullstring; 180 } else { 181 exec->type = buffer; 182 buffer += len + 1; 183 if (buffer >= ceiling) { 184 return ((int)NSS_STR_PARSE_ERANGE); 185 } 186 (void) strcpy(exec->type, 187 attrptr->attrvalue[0]); 188 } 189 continue; 190 } 191 if (strcasecmp(attrptr->attrname, _EXEC_RES1) == 0) { 192 if ((attrptr->attrvalue[0] == NULL) || 193 (len = strlen(attrptr->attrvalue[0])) < 1) { 194 exec->res1 = nullstring; 195 } else { 196 exec->res1 = buffer; 197 buffer += len + 1; 198 if (buffer >= ceiling) { 199 return ((int)NSS_STR_PARSE_ERANGE); 200 } 201 (void) strcpy(exec->res1, 202 attrptr->attrvalue[0]); 203 } 204 continue; 205 } 206 if (strcasecmp(attrptr->attrname, _EXEC_RES2) == 0) { 207 if ((attrptr->attrvalue[0] == NULL) || 208 (len = strlen(attrptr->attrvalue[0])) < 1) { 209 exec->res2 = nullstring; 210 } else { 211 exec->res2 = buffer; 212 buffer += len + 1; 213 if (buffer >= ceiling) { 214 return ((int)NSS_STR_PARSE_ERANGE); 215 } 216 (void) strcpy(exec->res2, 217 attrptr->attrvalue[0]); 218 } 219 continue; 220 } 221 if (strcasecmp(attrptr->attrname, _EXEC_ID) == 0) { 222 if ((attrptr->attrvalue[0] == NULL) || 223 (len = strlen(attrptr->attrvalue[0])) < 1) { 224 exec->id = nullstring; 225 } else { 226 exec->id = buffer; 227 buffer += len + 1; 228 if (buffer >= ceiling) { 229 return ((int)NSS_STR_PARSE_ERANGE); 230 } 231 (void) strcpy(exec->id, attrptr->attrvalue[0]); 232 } 233 continue; 234 } 235 if (strcasecmp(attrptr->attrname, _EXEC_ATTRS) == 0) { 236 if ((attrptr->attrvalue[0] == NULL) || 237 (len = strlen(attrptr->attrvalue[0])) < 1) { 238 exec->attr = nullstring; 239 } else { 240 exec->attr = buffer; 241 buffer += len + 1; 242 if (buffer >= ceiling) { 243 return ((int)NSS_STR_PARSE_ERANGE); 244 } 245 (void) strcpy(exec->attr, 246 attrptr->attrvalue[0]); 247 } 248 continue; 249 } 250 } 251 252 exec->next = (execstr_t *)NULL; 253 254 #ifdef DEBUG 255 (void) fprintf(stdout, "\n[getexecattr.c: _exec_ldap_exec2ent]\n"); 256 _print_execstr(exec); 257 #endif /* DEBUG */ 258 259 return ((int)NSS_STR_PARSE_SUCCESS); 260 } 261 262 263 /* 264 * place the results from ldap object structure into the file format 265 * returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE} 266 */ 267 static int 268 _nss_ldap_exec2str(ldap_backend_ptr be, nss_XbyY_args_t *argp) 269 { 270 int status = NSS_STR_PARSE_SUCCESS; 271 ns_ldap_result_t *result = be->result; 272 int len; 273 char *buffer, **name, **policy, **type; 274 char **res1, **res2, **id, **attr; 275 char *policy_str, *type_str, *res1_str, *res2_str; 276 char *id_str, *attr_str; 277 278 if (result == NULL) 279 return (NSS_STR_PARSE_PARSE); 280 281 (void) memset(argp->buf.buffer, 0, argp->buf.buflen); 282 283 name = __ns_ldap_getAttr(result->entry, _EXEC_NAME); 284 if (name == NULL || name[0] == NULL || 285 (strlen(name[0]) < 1)) { 286 status = NSS_STR_PARSE_PARSE; 287 goto result_exec2str; 288 } 289 290 policy = __ns_ldap_getAttr(result->entry, _EXEC_POLICY); 291 292 if (policy == NULL || policy[0] == NULL) 293 policy_str = _NO_VALUE; 294 else 295 policy_str = policy[0]; 296 297 type = __ns_ldap_getAttr(result->entry, _EXEC_TYPE); 298 if (type == NULL || type[0] == NULL) 299 type_str = _NO_VALUE; 300 else 301 type_str = type[0]; 302 303 res1 = __ns_ldap_getAttr(result->entry, _EXEC_RES1); 304 if (res1 == NULL || res1[0] == NULL) 305 res1_str = _NO_VALUE; 306 else 307 res1_str = res1[0]; 308 309 res2 = __ns_ldap_getAttr(result->entry, _EXEC_RES2); 310 if (res2 == NULL || res2[0] == NULL) 311 res2_str = _NO_VALUE; 312 else 313 res2_str = res2[0]; 314 315 id = __ns_ldap_getAttr(result->entry, _EXEC_ID); 316 if (id == NULL || id[0] == NULL) 317 id_str = _NO_VALUE; 318 else 319 id_str = id[0]; 320 321 attr = __ns_ldap_getAttr(result->entry, _EXEC_ATTRS); 322 if (attr == NULL || attr[0] == NULL) 323 attr_str = _NO_VALUE; 324 else 325 attr_str = attr[0]; 326 327 /* 7 = 6 ':' + 1 '\0' */ 328 len = strlen(name[0]) + strlen(policy_str) + strlen(type_str) + 329 strlen(res1_str) + strlen(res2_str) + strlen(id_str) + 330 strlen(attr_str) + 7; 331 332 if (len > argp->buf.buflen) { 333 status = NSS_STR_PARSE_ERANGE; 334 goto result_exec2str; 335 } 336 if (argp->buf.result != NULL) { 337 if ((be->buffer = calloc(1, len)) == NULL) { 338 status = NSS_STR_PARSE_PARSE; 339 goto result_exec2str; 340 } 341 buffer = be->buffer; 342 } else 343 buffer = argp->buf.buffer; 344 345 (void) snprintf(buffer, len, "%s:%s:%s:%s:%s:%s:%s", 346 name[0], policy_str, type_str, res1_str, 347 res2_str, id_str, attr_str); 348 /* The front end marshaller does not need the trailing null */ 349 if (argp->buf.result != NULL) 350 be->buflen = strlen(buffer); 351 result_exec2str: 352 (void) __ns_ldap_freeResult(&be->result); 353 return (status); 354 } 355 356 357 static nss_status_t 358 _exec_process_val(ldap_backend_ptr be, nss_XbyY_args_t *argp) 359 { 360 int status; 361 nss_status_t nss_stat = NSS_UNAVAIL; 362 ns_ldap_attr_t *attrptr; 363 ns_ldap_entry_t *entry; 364 ns_ldap_result_t *result = be->result; 365 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 366 367 argp->returnval = NULL; 368 attrptr = getattr(result, 0); 369 if (attrptr == NULL) { 370 (void) __ns_ldap_freeResult(&be->result); 371 return (nss_stat); 372 } 373 for (entry = result->entry; entry != NULL; entry = entry->next) { 374 status = _exec_ldap_exec2ent(entry, argp); 375 switch (status) { 376 case NSS_STR_PARSE_SUCCESS: 377 argp->returnval = argp->buf.result; 378 nss_stat = NSS_SUCCESS; 379 if (_priv_exec->search_flag == GET_ALL) { 380 if (_doexeclist(argp) == 0) { 381 nss_stat = NSS_UNAVAIL; 382 } 383 } 384 break; 385 case NSS_STR_PARSE_ERANGE: 386 argp->erange = 1; 387 nss_stat = NSS_NOTFOUND; 388 break; 389 case NSS_STR_PARSE_PARSE: 390 nss_stat = NSS_NOTFOUND; 391 break; 392 default: 393 nss_stat = NSS_UNAVAIL; 394 break; 395 } 396 397 if ((_priv_exec->search_flag == GET_ONE) || 398 (nss_stat != NSS_SUCCESS)) { 399 break; 400 } 401 } 402 403 return (nss_stat); 404 } 405 406 407 /* 408 * Check if we have either an exact match or a wild-card entry for that id. 409 */ 410 static nss_status_t 411 get_wild(ldap_backend_ptr be, nss_XbyY_args_t *argp, int getby_flag) 412 { 413 char *dup_id = NULL; 414 char *wild_id; 415 char searchfilter[SEARCHFILTERLEN]; 416 char userdata[SEARCHFILTERLEN]; 417 char name[SEARCHFILTERLEN]; 418 char id[SEARCHFILTERLEN]; 419 int ret; 420 nss_status_t nss_stat = NSS_NOTFOUND; 421 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 422 const char *policy = _priv_exec->policy; 423 const char *type = _priv_exec->type; 424 425 if (strpbrk(policy, "*()\\") != NULL || 426 type != NULL && strpbrk(type, "*()\\") != NULL) 427 return ((nss_status_t)NSS_NOTFOUND); 428 429 if (_priv_exec->id != NULL) 430 dup_id = strdup(_priv_exec->id); 431 432 switch (getby_flag) { 433 case NSS_DBOP_EXECATTR_BYNAMEID: 434 if (_ldap_filter_name(name, _priv_exec->name, 435 sizeof (name)) != 0) 436 goto go_out; 437 break; 438 } 439 440 wild_id = dup_id; 441 do { 442 if (wild_id != NULL) { 443 if (_ldap_filter_name(id, wild_id, sizeof (id)) != 0) 444 goto go_out; 445 } else 446 (void) strlcpy(id, "*", sizeof (id)); 447 448 switch (getby_flag) { 449 case NSS_DBOP_EXECATTR_BYID: 450 ret = snprintf(searchfilter, sizeof (searchfilter), 451 _EXEC_GETEXECID, id, policy, ISWILD(type)); 452 if (ret >= sizeof (searchfilter) || ret < 0) 453 goto go_out; 454 ret = snprintf(userdata, sizeof (userdata), 455 _EXEC_GETEXECID_SSD, id, policy, ISWILD(type)); 456 if (ret >= sizeof (userdata) || ret < 0) 457 goto go_out; 458 break; 459 460 case NSS_DBOP_EXECATTR_BYNAMEID: 461 ret = snprintf(searchfilter, sizeof (searchfilter), 462 _EXEC_GETEXECNAMEID, name, id, 463 policy, ISWILD(type)); 464 if (ret >= sizeof (searchfilter) || ret < 0) 465 goto go_out; 466 ret = snprintf(userdata, sizeof (userdata), 467 _EXEC_GETEXECNAMEID_SSD, name, id, 468 policy, ISWILD(type)); 469 if (ret >= sizeof (userdata) || ret < 0) 470 goto go_out; 471 break; 472 473 default: 474 goto go_out; 475 } 476 nss_stat = _nss_ldap_nocb_lookup(be, argp, _EXECATTR, 477 searchfilter, NULL, _merge_SSD_filter, userdata); 478 if (nss_stat == NSS_SUCCESS) 479 break; 480 } while ((wild_id = _exec_wild_id(wild_id, type)) != NULL); 481 482 go_out: 483 free(dup_id); 484 485 return (nss_stat); 486 } 487 488 static nss_status_t 489 exec_attr_process_val(ldap_backend_ptr be, nss_XbyY_args_t *argp) { 490 491 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 492 int stat, nss_stat = NSS_SUCCESS; 493 494 if (_priv_exec->search_flag == GET_ONE) { 495 /* ns_ldap_entry_t -> file format */ 496 stat = (*be->ldapobj2str)(be, argp); 497 498 if (stat == NSS_STR_PARSE_SUCCESS) { 499 if (argp->buf.result != NULL) { 500 /* file format -> execstr_t */ 501 stat = (*argp->str2ent)(be->buffer, 502 be->buflen, 503 argp->buf.result, 504 argp->buf.buffer, 505 argp->buf.buflen); 506 if (stat == NSS_STR_PARSE_SUCCESS) { 507 argp->returnval = argp->buf.result; 508 argp->returnlen = 1; /* irrelevant */ 509 nss_stat = NSS_SUCCESS; 510 } else { 511 argp->returnval = NULL; 512 argp->returnlen = 0; 513 nss_stat = NSS_NOTFOUND; 514 } 515 } else { 516 /* return file format in argp->buf.buffer */ 517 argp->returnval = argp->buf.buffer; 518 argp->returnlen = strlen(argp->buf.buffer); 519 nss_stat = NSS_SUCCESS; 520 } 521 } else { 522 argp->returnval = NULL; 523 argp->returnlen = 0; 524 nss_stat = NSS_NOTFOUND; 525 } 526 } else { 527 /* GET_ALL */ 528 nss_stat = _exec_process_val(be, argp); 529 _exec_cleanup(nss_stat, argp); 530 } 531 532 return (nss_stat); 533 534 } 535 536 static nss_status_t 537 getbynam(ldap_backend_ptr be, void *a) 538 { 539 char searchfilter[SEARCHFILTERLEN]; 540 char userdata[SEARCHFILTERLEN]; 541 char name[SEARCHFILTERLEN]; 542 int ret; 543 nss_status_t nss_stat; 544 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 545 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 546 const char *policy = _priv_exec->policy; 547 const char *type = _priv_exec->type; 548 549 if (strpbrk(policy, "*()\\") != NULL || 550 type != NULL && strpbrk(type, "*()\\") != NULL || 551 _ldap_filter_name(name, _priv_exec->name, sizeof (name)) != 0) 552 return ((nss_status_t)NSS_NOTFOUND); 553 ret = snprintf(searchfilter, sizeof (searchfilter), 554 _EXEC_GETEXECNAME, name, policy, ISWILD(type)); 555 if (ret >= sizeof (searchfilter) || ret < 0) 556 return ((nss_status_t)NSS_NOTFOUND); 557 ret = snprintf(userdata, sizeof (userdata), 558 _EXEC_GETEXECNAME_SSD, name, policy, ISWILD(type)); 559 if (ret >= sizeof (userdata) || ret < 0) 560 return ((nss_status_t)NSS_NOTFOUND); 561 562 nss_stat = _nss_ldap_nocb_lookup(be, argp, _EXECATTR, 563 searchfilter, NULL, _merge_SSD_filter, userdata); 564 565 if (nss_stat == NSS_SUCCESS) 566 nss_stat = exec_attr_process_val(be, argp); 567 568 return (nss_stat); 569 } 570 571 static nss_status_t 572 getbyid(ldap_backend_ptr be, void *a) 573 { 574 nss_status_t nss_stat = NSS_SUCCESS; 575 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 576 577 nss_stat = get_wild(be, argp, NSS_DBOP_EXECATTR_BYID); 578 579 if (nss_stat == NSS_SUCCESS) 580 nss_stat = exec_attr_process_val(be, argp); 581 582 return (nss_stat); 583 } 584 585 586 static nss_status_t 587 getbynameid(ldap_backend_ptr be, void *a) 588 { 589 nss_status_t nss_stat; 590 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 591 592 nss_stat = get_wild(be, argp, NSS_DBOP_EXECATTR_BYNAMEID); 593 594 if (nss_stat == NSS_SUCCESS) 595 nss_stat = exec_attr_process_val(be, argp); 596 597 return (nss_stat); 598 } 599 600 601 static ldap_backend_op_t execattr_ops[] = { 602 _nss_ldap_destr, 603 _nss_ldap_endent, 604 _nss_ldap_setent, 605 _nss_ldap_getent, 606 getbynam, 607 getbyid, 608 getbynameid 609 }; 610 611 612 /*ARGSUSED0*/ 613 nss_backend_t * 614 _nss_ldap_exec_attr_constr(const char *dummy1, 615 const char *dummy2, 616 const char *dummy3, 617 const char *dummy4, 618 const char *dummy5, 619 const char *dummy6, 620 const char *dummy7) 621 { 622 #ifdef DEBUG 623 (void) fprintf(stdout, 624 "\n[getexecattr.c: _nss_ldap_exec_attr_constr]\n"); 625 #endif 626 return ((nss_backend_t *)_nss_ldap_constr(execattr_ops, 627 sizeof (execattr_ops)/sizeof (execattr_ops[0]), _EXECATTR, 628 exec_attrs, _nss_ldap_exec2str)); 629 } 630