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