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 * Copyright 2021 Joyent, Inc. 25 */ 26 27 #include <secdb.h> 28 #include <exec_attr.h> 29 #include "ldap_common.h" 30 31 32 /* exec_attr attributes filters */ 33 #define ISWILD(x) (x == NULL) ? "*" : x 34 #define _EXEC_NAME "cn" 35 #define _EXEC_POLICY "SolarisKernelSecurityPolicy" 36 #define _EXEC_TYPE "SolarisProfileType" 37 #define _EXEC_RES1 "SolarisAttrRes1" 38 #define _EXEC_RES2 "SolarisAttrRes2" 39 #define _EXEC_ID "SolarisProfileId" 40 #define _EXEC_ATTRS "SolarisAttrKeyValue" 41 #define _EXEC_GETEXECNAME "(&(objectClass=SolarisExecAttr)(cn=%s)"\ 42 "(SolarisKernelSecurityPolicy=%s)"\ 43 "(SolarisProfileType=%s))" 44 #define _EXEC_GETEXECNAME_SSD "(&(%%s)(cn=%s)"\ 45 "(SolarisKernelSecurityPolicy=%s)"\ 46 "(SolarisProfileType=%s))" 47 #define _EXEC_GETEXECID "(&(objectClass=SolarisExecAttr)"\ 48 "(SolarisProfileId=%s)"\ 49 "(SolarisKernelSecurityPolicy=%s)"\ 50 "(SolarisProfileType=%s))" 51 #define _EXEC_GETEXECID_SSD "(&(%%s)"\ 52 "(SolarisProfileId=%s)"\ 53 "(SolarisKernelSecurityPolicy=%s)"\ 54 "(SolarisProfileType=%s))" 55 #define _EXEC_GETEXECNAMEID "(&(objectClass=SolarisExecAttr)(cn=%s)"\ 56 "(SolarisProfileId=%s)"\ 57 "(SolarisKernelSecurityPolicy=%s)"\ 58 "(SolarisProfileType=%s))" 59 #define _EXEC_GETEXECNAMEID_SSD "(&(%%s)(cn=%s)"\ 60 "(SolarisProfileId=%s)"\ 61 "(SolarisKernelSecurityPolicy=%s)"\ 62 "(SolarisProfileType=%s))" 63 64 65 /* from libnsl */ 66 extern int _doexeclist(nss_XbyY_args_t *); 67 extern char *_exec_wild_id(char *, const char *); 68 extern void _exec_cleanup(nss_status_t, nss_XbyY_args_t *); 69 70 71 static const char *exec_attrs[] = { 72 _EXEC_NAME, 73 _EXEC_POLICY, 74 _EXEC_TYPE, 75 _EXEC_RES1, 76 _EXEC_RES2, 77 _EXEC_ID, 78 _EXEC_ATTRS, 79 (char *)NULL 80 }; 81 82 83 #ifdef DEBUG 84 static void 85 _print_execstr(execstr_t *exec) 86 { 87 88 (void) fprintf(stdout, " exec-name: [%s]\n", exec->name); 89 if (exec->policy != (char *)NULL) { 90 (void) fprintf(stdout, " policy: [%s]\n", exec->policy); 91 } 92 if (exec->type != (char *)NULL) { 93 (void) fprintf(stdout, " type: [%s]\n", exec->type); 94 } 95 if (exec->res1 != (char *)NULL) { 96 (void) fprintf(stdout, " res1: [%s]\n", exec->res1); 97 } 98 if (exec->res2 != (char *)NULL) { 99 (void) fprintf(stdout, " res2: [%s]\n", exec->res2); 100 } 101 if (exec->id != (char *)NULL) { 102 (void) fprintf(stdout, " id: [%s]\n", exec->id); 103 } 104 if (exec->attr != (char *)NULL) { 105 (void) fprintf(stdout, " attr: [%s]\n", exec->attr); 106 } 107 if (exec->next != (execstr_t *)NULL) { 108 (void) fprintf(stdout, " next: [%s]\n", exec->next->name); 109 (void) fprintf(stdout, "\n"); 110 _print_execstr(exec->next); 111 } 112 } 113 #endif /* DEBUG */ 114 115 116 static int 117 _exec_ldap_exec2ent(ns_ldap_entry_t *entry, nss_XbyY_args_t *argp) 118 { 119 120 int i; 121 unsigned long len = 0L; 122 int buflen = (int)0; 123 char *nullstring = (char *)NULL; 124 char *buffer = (char *)NULL; 125 char *ceiling = (char *)NULL; 126 execstr_t *exec = (execstr_t *)NULL; 127 ns_ldap_attr_t *attrptr; 128 129 buffer = argp->buf.buffer; 130 buflen = (size_t)argp->buf.buflen; 131 (void) memset(argp->buf.buffer, 0, buflen); 132 exec = (execstr_t *)(argp->buf.result); 133 ceiling = buffer + buflen; 134 exec->name = (char *)NULL; 135 exec->policy = (char *)NULL; 136 exec->type = (char *)NULL; 137 exec->res1 = (char *)NULL; 138 exec->res2 = (char *)NULL; 139 exec->id = (char *)NULL; 140 exec->attr = (char *)NULL; 141 142 for (i = 0; i < entry->attr_count; i++) { 143 attrptr = entry->attr_pair[i]; 144 if (attrptr == NULL) { 145 return ((int)NSS_STR_PARSE_PARSE); 146 } 147 if (strcasecmp(attrptr->attrname, _EXEC_NAME) == 0) { 148 if ((attrptr->attrvalue[0] == NULL) || 149 (len = strlen(attrptr->attrvalue[0])) < 1) { 150 return ((int)NSS_STR_PARSE_PARSE); 151 } 152 exec->name = buffer; 153 buffer += len + 1; 154 if (buffer >= ceiling) { 155 return ((int)NSS_STR_PARSE_ERANGE); 156 } 157 (void) strcpy(exec->name, attrptr->attrvalue[0]); 158 continue; 159 } 160 if (strcasecmp(attrptr->attrname, _EXEC_POLICY) == 0) { 161 if ((attrptr->attrvalue[0] == NULL) || 162 (len = strlen(attrptr->attrvalue[0])) < 1) { 163 exec->policy = nullstring; 164 } else { 165 exec->policy = buffer; 166 buffer += len + 1; 167 if (buffer >= ceiling) { 168 return ((int)NSS_STR_PARSE_ERANGE); 169 } 170 (void) strcpy(exec->policy, 171 attrptr->attrvalue[0]); 172 } 173 continue; 174 } 175 if (strcasecmp(attrptr->attrname, _EXEC_TYPE) == 0) { 176 if ((attrptr->attrvalue[0] == NULL) || 177 (len = strlen(attrptr->attrvalue[0])) < 1) { 178 exec->type = nullstring; 179 } else { 180 exec->type = buffer; 181 buffer += len + 1; 182 if (buffer >= ceiling) { 183 return ((int)NSS_STR_PARSE_ERANGE); 184 } 185 (void) strcpy(exec->type, 186 attrptr->attrvalue[0]); 187 } 188 continue; 189 } 190 if (strcasecmp(attrptr->attrname, _EXEC_RES1) == 0) { 191 if ((attrptr->attrvalue[0] == NULL) || 192 (len = strlen(attrptr->attrvalue[0])) < 1) { 193 exec->res1 = nullstring; 194 } else { 195 exec->res1 = buffer; 196 buffer += len + 1; 197 if (buffer >= ceiling) { 198 return ((int)NSS_STR_PARSE_ERANGE); 199 } 200 (void) strcpy(exec->res1, 201 attrptr->attrvalue[0]); 202 } 203 continue; 204 } 205 if (strcasecmp(attrptr->attrname, _EXEC_RES2) == 0) { 206 if ((attrptr->attrvalue[0] == NULL) || 207 (len = strlen(attrptr->attrvalue[0])) < 1) { 208 exec->res2 = nullstring; 209 } else { 210 exec->res2 = buffer; 211 buffer += len + 1; 212 if (buffer >= ceiling) { 213 return ((int)NSS_STR_PARSE_ERANGE); 214 } 215 (void) strcpy(exec->res2, 216 attrptr->attrvalue[0]); 217 } 218 continue; 219 } 220 if (strcasecmp(attrptr->attrname, _EXEC_ID) == 0) { 221 if ((attrptr->attrvalue[0] == NULL) || 222 (len = strlen(attrptr->attrvalue[0])) < 1) { 223 exec->id = nullstring; 224 } else { 225 exec->id = buffer; 226 buffer += len + 1; 227 if (buffer >= ceiling) { 228 return ((int)NSS_STR_PARSE_ERANGE); 229 } 230 (void) strcpy(exec->id, attrptr->attrvalue[0]); 231 } 232 continue; 233 } 234 if (strcasecmp(attrptr->attrname, _EXEC_ATTRS) == 0) { 235 if ((attrptr->attrvalue[0] == NULL) || 236 (len = strlen(attrptr->attrvalue[0])) < 1) { 237 exec->attr = nullstring; 238 } else { 239 exec->attr = buffer; 240 buffer += len + 1; 241 if (buffer >= ceiling) { 242 return ((int)NSS_STR_PARSE_ERANGE); 243 } 244 (void) strcpy(exec->attr, 245 attrptr->attrvalue[0]); 246 } 247 continue; 248 } 249 } 250 251 exec->next = (execstr_t *)NULL; 252 253 #ifdef DEBUG 254 (void) fprintf(stdout, "\n[getexecattr.c: _exec_ldap_exec2ent]\n"); 255 _print_execstr(exec); 256 #endif /* DEBUG */ 257 258 return ((int)NSS_STR_PARSE_SUCCESS); 259 } 260 261 262 /* 263 * place the results from ldap object structure into the file format 264 * returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE} 265 */ 266 static int 267 _nss_ldap_exec2str(ldap_backend_ptr be, nss_XbyY_args_t *argp) 268 { 269 int status = NSS_STR_PARSE_SUCCESS; 270 ns_ldap_result_t *result = be->result; 271 int len; 272 char *buffer, **name, **policy, **type; 273 char **res1, **res2, **id, **attr; 274 char *policy_str, *type_str, *res1_str, *res2_str; 275 char *id_str, *attr_str; 276 277 if (result == NULL) 278 return (NSS_STR_PARSE_PARSE); 279 280 (void) memset(argp->buf.buffer, 0, argp->buf.buflen); 281 282 name = __ns_ldap_getAttr(result->entry, _EXEC_NAME); 283 if (name == NULL || name[0] == NULL || 284 (strlen(name[0]) < 1)) { 285 status = NSS_STR_PARSE_PARSE; 286 goto result_exec2str; 287 } 288 289 policy = __ns_ldap_getAttr(result->entry, _EXEC_POLICY); 290 291 if (policy == NULL || policy[0] == NULL) 292 policy_str = _NO_VALUE; 293 else 294 policy_str = policy[0]; 295 296 type = __ns_ldap_getAttr(result->entry, _EXEC_TYPE); 297 if (type == NULL || type[0] == NULL) 298 type_str = _NO_VALUE; 299 else 300 type_str = type[0]; 301 302 res1 = __ns_ldap_getAttr(result->entry, _EXEC_RES1); 303 if (res1 == NULL || res1[0] == NULL) 304 res1_str = _NO_VALUE; 305 else 306 res1_str = res1[0]; 307 308 res2 = __ns_ldap_getAttr(result->entry, _EXEC_RES2); 309 if (res2 == NULL || res2[0] == NULL) 310 res2_str = _NO_VALUE; 311 else 312 res2_str = res2[0]; 313 314 id = __ns_ldap_getAttr(result->entry, _EXEC_ID); 315 if (id == NULL || id[0] == NULL) 316 id_str = _NO_VALUE; 317 else 318 id_str = id[0]; 319 320 attr = __ns_ldap_getAttr(result->entry, _EXEC_ATTRS); 321 if (attr == NULL || attr[0] == NULL) 322 attr_str = _NO_VALUE; 323 else 324 attr_str = attr[0]; 325 326 /* 7 = 6 ':' + 1 '\0' */ 327 len = strlen(name[0]) + strlen(policy_str) + strlen(type_str) + 328 strlen(res1_str) + strlen(res2_str) + strlen(id_str) + 329 strlen(attr_str) + 7; 330 331 if (len > argp->buf.buflen) { 332 status = NSS_STR_PARSE_ERANGE; 333 goto result_exec2str; 334 } 335 if (argp->buf.result != NULL) { 336 if ((be->buffer = calloc(1, len)) == NULL) { 337 status = NSS_STR_PARSE_PARSE; 338 goto result_exec2str; 339 } 340 buffer = be->buffer; 341 } else 342 buffer = argp->buf.buffer; 343 344 (void) snprintf(buffer, len, "%s:%s:%s:%s:%s:%s:%s", 345 name[0], policy_str, type_str, res1_str, 346 res2_str, id_str, attr_str); 347 /* The front end marshaller does not need the trailing null */ 348 if (argp->buf.result != NULL) 349 be->buflen = strlen(buffer); 350 result_exec2str: 351 (void) __ns_ldap_freeResult(&be->result); 352 return (status); 353 } 354 355 356 static nss_status_t 357 _exec_process_val(ldap_backend_ptr be, nss_XbyY_args_t *argp) 358 { 359 int status; 360 nss_status_t nss_stat = NSS_UNAVAIL; 361 ns_ldap_attr_t *attrptr; 362 ns_ldap_entry_t *entry; 363 ns_ldap_result_t *result = be->result; 364 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 365 366 argp->returnval = NULL; 367 attrptr = getattr(result, 0); 368 if (attrptr == NULL) { 369 (void) __ns_ldap_freeResult(&be->result); 370 return (nss_stat); 371 } 372 for (entry = result->entry; entry != NULL; entry = entry->next) { 373 status = _exec_ldap_exec2ent(entry, argp); 374 switch (status) { 375 case NSS_STR_PARSE_SUCCESS: 376 argp->returnval = argp->buf.result; 377 nss_stat = NSS_SUCCESS; 378 if (IS_GET_ALL(_priv_exec->search_flag)) { 379 if (_doexeclist(argp) == 0) { 380 nss_stat = NSS_UNAVAIL; 381 } 382 } 383 break; 384 case NSS_STR_PARSE_ERANGE: 385 argp->erange = 1; 386 nss_stat = NSS_NOTFOUND; 387 break; 388 case NSS_STR_PARSE_PARSE: 389 nss_stat = NSS_NOTFOUND; 390 break; 391 default: 392 nss_stat = NSS_UNAVAIL; 393 break; 394 } 395 396 if (IS_GET_ONE(_priv_exec->search_flag) || 397 (nss_stat != NSS_SUCCESS)) { 398 break; 399 } 400 } 401 402 return (nss_stat); 403 } 404 405 406 /* 407 * Check if we have either an exact match or a wild-card entry for that id. 408 */ 409 static nss_status_t 410 get_wild(ldap_backend_ptr be, nss_XbyY_args_t *argp, int getby_flag) 411 { 412 char *dup_id = NULL; 413 char *wild_id; 414 char searchfilter[SEARCHFILTERLEN]; 415 char userdata[SEARCHFILTERLEN]; 416 char name[SEARCHFILTERLEN]; 417 char id[SEARCHFILTERLEN]; 418 int ret; 419 nss_status_t nss_stat = NSS_NOTFOUND; 420 _priv_execattr *_priv_exec = (_priv_execattr *)(argp->key.attrp); 421 const char *policy = _priv_exec->policy; 422 const char *type = _priv_exec->type; 423 424 if ((policy != NULL && strpbrk(policy, "*()\\") != NULL) || 425 type != NULL && strpbrk(type, "*()\\") != NULL) 426 return ((nss_status_t)NSS_NOTFOUND); 427 428 if (_priv_exec->id != NULL) 429 dup_id = strdup(_priv_exec->id); 430 431 switch (getby_flag) { 432 case NSS_DBOP_EXECATTR_BYNAMEID: 433 if (_ldap_filter_name(name, _priv_exec->name, 434 sizeof (name)) != 0) 435 goto go_out; 436 break; 437 } 438 439 wild_id = dup_id; 440 do { 441 if (wild_id != NULL) { 442 if (_ldap_filter_name(id, wild_id, sizeof (id)) != 0) 443 goto go_out; 444 } else 445 (void) strlcpy(id, "*", sizeof (id)); 446 447 switch (getby_flag) { 448 case NSS_DBOP_EXECATTR_BYID: 449 ret = snprintf(searchfilter, sizeof (searchfilter), 450 _EXEC_GETEXECID, id, ISWILD(policy), ISWILD(type)); 451 if (ret >= sizeof (searchfilter) || ret < 0) 452 goto go_out; 453 ret = snprintf(userdata, sizeof (userdata), 454 _EXEC_GETEXECID_SSD, id, ISWILD(policy), 455 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 ISWILD(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 ISWILD(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 (IS_GET_ONE(_priv_exec->search_flag)) { 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 (policy != NULL && 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, ISWILD(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, ISWILD(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