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 /* 23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <ctype.h> 27 #include <libintl.h> 28 #include <strings.h> 29 #include <stdio.h> 30 #include <tsol/label.h> 31 #include "../../../lib/libsldap/common/ns_sldap.h" 32 33 34 #define SAME 0 35 36 struct mapping { 37 char *database; 38 char *def_type; 39 char *objectclass; 40 char *actual_db; 41 }; 42 43 #define PUBLICKEY 0 44 45 static struct mapping maplist[] = { 46 {"publickey", "uidnumber", "niskeyobject", "passwd"}, 47 {"publickey", "cn", "niskeyobject", "host"}, 48 {"bootparams", "cn", "bootableDevice", NULL}, 49 {"ethers", "cn", "ieee802Device", NULL}, 50 {"group", "cn", "posixgroup", NULL}, 51 {"hosts", "cn", "iphost", NULL}, 52 {"ipnodes", "cn", "iphost", NULL}, 53 {"netgroup", "cn", "nisnetgroup", NULL}, 54 {"netmasks", "ipnetworknumber", "ipnetwork", NULL}, 55 {"networks", "ipnetworknumber", "ipnetwork", NULL}, 56 {"passwd", "uid", "posixaccount", NULL}, 57 {"protocols", "cn", "ipprotocol", NULL}, 58 {"rpc", "cn", "oncrpc", NULL}, 59 {"services", "cn", "ipservice", NULL}, 60 {"aliases", "cn", "mailGroup", NULL}, 61 {"project", "SolarisProjectID", "SolarisProject", NULL}, 62 {"printers", "printer-uri", "sunPrinter", NULL}, 63 {"shadow", "uid", "shadowaccount", NULL}, 64 {"auth_attr", "cn", "SolarisAuthAttr", NULL}, 65 {"prof_attr", "cn", "SolarisProfAttr", NULL}, 66 {"exec_attr", "cn", "SolarisExecAttr", NULL}, 67 {"user_attr", "uid", "SolarisUserAttr", NULL}, 68 {"tnrhtp", "ipTnetTemplateName", "ipTnetTemplate", NULL}, 69 {"tnrhdb", "ipTnetNumber", "ipTnetHost", NULL}, 70 {NULL, NULL, NULL, NULL} 71 }; 72 73 #define PROF_ATTR_FILTER \ 74 "(&(objectclass=SolarisProfAttr)(!(SolarisKernelSecurityPolicy=*))%s)" 75 #define TNRHTP_FILTER \ 76 "(&(objectclass=ipTnetTemplate)(!(objectclass=ipTnetHost))%s)" 77 #define OC_FILTER "objectclass=%s" 78 #define OC_FLEN 15 79 #define OC_FILTER2 "(&(objectclass=%s)%s)" 80 #define OC_FLEN2 22 81 82 /* Malloc and print error message in case of failure */ 83 #define MALLOC(ptr, len) \ 84 if ((ptr = (char *)malloc(len)) == NULL) { \ 85 (void) fprintf(stderr, gettext("out of memory\n")); \ 86 } 87 88 /* 89 * Allocate memory for filter and user data. Set 90 * error to 1 if either of the mallocs fail. 91 * In addition, free the memory allocated for filter, 92 * if memory allocation for user data fails. 93 */ 94 #define MALLOC_FILTER_UDATA(ptr1, len1, ptr2, len2, error) \ 95 error = 0; \ 96 MALLOC(ptr1, len1); \ 97 if (!ptr1) { \ 98 error = 1; \ 99 } \ 100 else { \ 101 MALLOC(ptr2, len2); \ 102 if (!ptr2) { \ 103 error = 1; \ 104 free(ptr1); \ 105 } \ 106 } 107 108 void 109 printMapping() 110 { 111 int i; 112 113 (void) fprintf(stdout, 114 gettext("database default type objectclass\n")); 115 (void) fprintf(stdout, 116 gettext("============= ================= =============\n")); 117 /* first dump auto_* and automount which are not in maplist[] */ 118 (void) fprintf(stdout, "%-15s%-20s%s\n", "auto_*", "automountKey", 119 "automount"); 120 (void) fprintf(stdout, "%-15s%-20s%s\n", "automount", 121 "automountMapName", "automountMap"); 122 for (i = 0; maplist[i].database != NULL; i++) { 123 /* skip printing shadow */ 124 if (strcasecmp(maplist[i].database, "shadow") == 0) 125 continue; 126 if (!is_system_labeled()) { 127 /* 128 * do not print tnrhdb and tnrhtp if system is 129 * not configured with Trusted Extensions 130 */ 131 if ((strcasecmp(maplist[i].database, "tnrhdb") == 0) || 132 (strcasecmp(maplist[i].database, "tnrhtp") == 0)) 133 continue; 134 } 135 (void) fprintf(stdout, "%-15s%-20s%s\n", maplist[i].database, 136 maplist[i].def_type, maplist[i].objectclass); 137 } 138 } 139 140 /* 141 * set_key routine to handle user specified keys. 142 * A key can be of the form: attribute=value or value. 143 * A filter is constructed from a set of keys specified in 144 * the form (|(key1)(key2)...(keyn)) 145 * It returns: NULL if no keys are defined or 146 * the keyfilter as constructed above. 147 */ 148 149 char * 150 set_keys(char **key, char *attrtype) 151 { 152 char *keyeq = NULL; 153 char *keyfilter = NULL; 154 int len, totlen = 1; /* Terminating NULL byte */ 155 char *k, **karray; 156 char *tmpptr; 157 158 if (!key || !key[0]) /* should never contain NULL string */ 159 return (NULL); 160 161 if (key[1]) { 162 totlen += 3; 163 /* Allocate memory for '(|)' */ 164 MALLOC(keyfilter, totlen); 165 if (!keyfilter) 166 exit(2); 167 (void) snprintf(keyfilter, totlen, "(|"); 168 } 169 170 karray = key; 171 while ((k = *karray) != 0) { 172 keyeq = strchr(k, '='); 173 if (keyeq) { 174 /* make enough room for (%s) */ 175 totlen += strlen(k) + 2; 176 } else { 177 /* make enough room for (%s=%s) */ 178 totlen += strlen(attrtype) + strlen(k) + 3; 179 } 180 181 len = keyfilter ? strlen(keyfilter) : 0; 182 183 if (!(tmpptr = (char *)realloc(keyfilter, totlen))) { 184 if (keyfilter) 185 free(keyfilter); 186 (void) fprintf(stderr, gettext("out of memory\n")); 187 exit(2); 188 } 189 keyfilter = tmpptr; 190 191 if (keyeq) { 192 (void) snprintf(keyfilter + len, totlen - len, 193 "(%s)", k); 194 } else { 195 (void) snprintf(keyfilter + len, totlen - len, 196 "(%s=%s)", attrtype, k); 197 } 198 karray++; 199 } 200 201 if (key[1]) { 202 /* We allocated memory for this earlier */ 203 (void) strlcat(keyfilter, ")", totlen); 204 } 205 206 return (keyfilter); 207 } 208 209 210 /* 211 * A special set_key routine for to handle public keys. 212 * If the key starts with a digiti, view it as a user id. 213 * Otherwise, view it as a hostname. 214 * It returns: -1 no keys defined, 0 key defined but none for type 215 * specified, n>0 number of matches found. 216 */ 217 int 218 set_keys_publickey(char **key, char *attrtype, int type, char **ret) 219 { 220 char *keyeq = NULL; 221 char *keyfilter = NULL; 222 char *pre_filter = NULL; 223 char *k, **karray; 224 int count = 0; 225 int len, totlen = 1; /* Terminating NULL byte */ 226 char *tmpptr; 227 228 if (!key || !key[0]) { /* should never contain NULL string */ 229 *ret = NULL; 230 return (-1); 231 } 232 233 karray = key; 234 while ((k = *karray) != 0) { 235 keyeq = strchr(k, '='); 236 if (keyeq) { 237 /* make enough room for (%s) */ 238 totlen += strlen(k) + 2; 239 } else { 240 if ((type == 0 && isdigit(*k)) || 241 /* user type keys */ 242 (type == 1 && (!isdigit(*k)))) { 243 /* hosts type keys */ 244 /* make enough room for (%s=%s) */ 245 totlen += strlen(k) + strlen(attrtype) + 3; 246 } else { 247 karray++; 248 continue; 249 } 250 } 251 252 len = pre_filter ? strlen(pre_filter) : 0; 253 254 if (!(tmpptr = (char *)realloc(pre_filter, totlen))) { 255 if (pre_filter) 256 free(pre_filter); 257 (void) fprintf(stderr, gettext("out of memory\n")); 258 exit(2); 259 } 260 pre_filter = tmpptr; 261 262 if (keyeq) { 263 (void) snprintf(pre_filter + len, totlen - len, 264 "(%s)", k); 265 } else { 266 (void) snprintf(pre_filter + len, totlen - len, 267 "(%s=%s)", attrtype, k); 268 } 269 karray++; 270 count++; 271 } 272 if (count > 1) { 273 len = strlen(pre_filter) + 4; 274 if (!(keyfilter = (char *)malloc(len))) { 275 (void) fprintf(stderr, gettext("out of memory\n")); 276 free(pre_filter); 277 exit(2); 278 } 279 (void) snprintf(keyfilter, len, "(|%s)", pre_filter); 280 free(pre_filter); 281 *ret = keyfilter; 282 } else 283 *ret = pre_filter; 284 return (count); 285 } 286 287 /* 288 * publickey specific set_filter 289 * type 0 -> check for user publickeys 290 * type 1 -> check for hosts publickeys 291 */ 292 char * 293 set_filter_publickey(char **key, char *database, int type, char **udata) 294 { 295 char *filter = NULL; 296 char *userdata; 297 char *keyfilter = NULL; 298 int rc; 299 int filterlen, udatalen; 300 short nomem = 0; 301 302 if (!database || !udata) { 303 return (NULL); 304 } 305 306 if (strcasecmp(database, maplist[PUBLICKEY].database) == SAME) { 307 rc = set_keys_publickey(key, 308 maplist[PUBLICKEY + type].def_type, type, &keyfilter); 309 switch (rc) { 310 case -1: 311 filterlen = strlen(maplist[PUBLICKEY].objectclass) + 13; 312 udatalen = 3; 313 MALLOC_FILTER_UDATA(filter, filterlen, userdata, 314 udatalen, nomem); 315 if (!nomem) { 316 (void) snprintf(filter, filterlen, 317 "objectclass=%s", 318 maplist[PUBLICKEY].objectclass); 319 (void) snprintf(userdata, udatalen, "%%s"); 320 } 321 break; 322 case 0: 323 return (NULL); 324 default: 325 filterlen = strlen(maplist[PUBLICKEY].objectclass) + 326 strlen(keyfilter) + 18; 327 udatalen = strlen(keyfilter) + 8; 328 MALLOC_FILTER_UDATA(filter, filterlen, userdata, 329 udatalen, nomem); 330 if (!nomem) { 331 (void) snprintf(filter, filterlen, 332 "(&(objectclass=%s)%s)", 333 maplist[PUBLICKEY].objectclass, keyfilter); 334 (void) snprintf(userdata, udatalen, 335 "(&(%%s)%s)", keyfilter); 336 } 337 } 338 } else { 339 if ((keyfilter = set_keys(key, "cn")) == NULL) { 340 filterlen = 14; 341 udatalen = 3; 342 MALLOC_FILTER_UDATA(filter, filterlen, userdata, 343 udatalen, nomem); 344 if (!nomem) { 345 (void) snprintf(filter, filterlen, 346 "objectclass=*"); 347 (void) snprintf(userdata, udatalen, "%%s"); 348 } 349 } else { 350 filterlen = strlen(keyfilter) + 1; 351 udatalen = strlen(keyfilter) + 8; 352 MALLOC_FILTER_UDATA(filter, filterlen, userdata, 353 udatalen, nomem); 354 if (!nomem) { 355 (void) snprintf(filter, filterlen, "%s", 356 keyfilter); 357 (void) snprintf(userdata, udatalen, 358 "(&(%%s)%s)", keyfilter); 359 } 360 } 361 } 362 #ifdef DEBUG 363 (void) fprintf(stdout, "set_filter: filter=\"%s\"\n", filter); 364 (void) fprintf(stdout, "set_filter: userdata=\"%s\"\n", userdata); 365 #endif /* DEBUG */ 366 if (keyfilter) 367 free(keyfilter); 368 if (nomem) 369 exit(2); 370 *udata = userdata; 371 return (filter); 372 } 373 374 375 /* generic set_filter, this function is not thread safe */ 376 char * 377 set_filter(char **key, char *database, char **udata) 378 { 379 char *filter = NULL; 380 char *userdata = NULL; 381 char *keyfilter; 382 int i, filterlen, udatalen; 383 int rc, v2 = 1; 384 int dbpf, dbtp; 385 void **paramVal = NULL; 386 ns_ldap_error_t *errorp = NULL; 387 short nomem; 388 389 if (!database || !udata) { 390 return (NULL); 391 } 392 393 394 /* 395 * Check for version of the profile the client is using 396 * 397 * For version 1 profiles we do use nisMap and nisObject schema 398 * for backward compatibility with Solaris 8 clients. 399 * 400 * For version 2 profiles we use automountMap and automount as 401 * default attributes (which can then be overridden in libsldap 402 * if schema mapping is configured in the profile). 403 * 404 * If profile version is not available, use version 2 as default. 405 */ 406 rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, ¶mVal, &errorp); 407 if (rc != NS_LDAP_SUCCESS || !paramVal || !*paramVal) { 408 /* should print a message here: using v2 defaults */ 409 (void) __ns_ldap_freeError(&errorp); 410 } else { 411 if (strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0) 412 v2 = 0; 413 (void) __ns_ldap_freeParam(¶mVal); 414 } 415 416 /* 417 * starts at 2 to skip over publickey databases. 418 * These databases are handled separately. 419 */ 420 for (i = 2; maplist[i].database != NULL; i++) { 421 if (strcasecmp(database, maplist[i].database) == SAME) { 422 dbpf = 0, dbtp = 0; 423 if (strcasecmp(database, "prof_attr") == 0) 424 dbpf = 1; 425 else if (strcasecmp(database, "tnrhtp") == 0) 426 dbtp = 1; 427 if ((keyfilter = set_keys(key, maplist[i].def_type)) 428 == NULL) { 429 filterlen = strlen(maplist[i].objectclass); 430 udatalen = 3; 431 if (dbpf) 432 filterlen += strlen(PROF_ATTR_FILTER) 433 + 1; 434 else if (dbtp) 435 filterlen += strlen(TNRHTP_FILTER) + 1; 436 else 437 filterlen += OC_FLEN; 438 439 MALLOC_FILTER_UDATA(filter, filterlen, userdata, 440 udatalen, nomem); 441 if (nomem) 442 goto done; 443 if (dbpf) 444 (void) snprintf(filter, filterlen, 445 PROF_ATTR_FILTER, ""); 446 else if (dbtp) 447 (void) snprintf(filter, filterlen, 448 TNRHTP_FILTER, ""); 449 else 450 (void) snprintf(filter, filterlen, 451 OC_FILTER, 452 maplist[i].objectclass); 453 454 (void) snprintf(userdata, udatalen, "%%s"); 455 } else { 456 filterlen = strlen(maplist[i].objectclass) + 457 strlen(keyfilter); 458 if (dbpf) 459 filterlen += strlen(PROF_ATTR_FILTER) 460 + 1; 461 else if (dbtp) 462 filterlen += strlen(TNRHTP_FILTER) + 1; 463 else 464 filterlen += OC_FLEN2; 465 466 udatalen = strlen(keyfilter) + 8; 467 MALLOC_FILTER_UDATA(filter, filterlen, userdata, 468 udatalen, nomem); 469 if (nomem) 470 goto done; 471 if (dbpf) 472 (void) snprintf(filter, filterlen, 473 PROF_ATTR_FILTER, keyfilter); 474 else if (dbtp) 475 (void) snprintf(filter, filterlen, 476 TNRHTP_FILTER, keyfilter); 477 else 478 (void) snprintf(filter, filterlen, 479 OC_FILTER2, 480 maplist[i].objectclass, keyfilter); 481 482 (void) snprintf(userdata, udatalen, 483 "(&(%%s)%s)", keyfilter); 484 } 485 goto done; 486 } 487 } 488 489 /* special cases for automounter and other services */ 490 491 /* auto_* services */ 492 if (strncasecmp(database, "auto_", 5) == SAME) { 493 if (v2) { 494 if ((keyfilter = set_keys(key, "automountKey")) 495 != NULL) { 496 filterlen = strlen(keyfilter) + 27; 497 udatalen = strlen(keyfilter) + 8; 498 MALLOC_FILTER_UDATA(filter, filterlen, 499 userdata, udatalen, nomem); 500 if (!nomem) { 501 (void) snprintf(filter, filterlen, 502 "(&(objectclass=automount)%s)", 503 keyfilter); 504 (void) snprintf(userdata, udatalen, 505 "(&(%%s)%s)", keyfilter); 506 } 507 } else { 508 filterlen = 22; 509 udatalen = 3; 510 MALLOC_FILTER_UDATA(filter, filterlen, 511 userdata, udatalen, nomem); 512 if (!nomem) { 513 (void) strlcpy(filter, 514 "objectclass=automount", filterlen); 515 (void) strlcpy(userdata, "%s", 516 udatalen); 517 } 518 } 519 } else { 520 if ((keyfilter = set_keys(key, "cn")) != NULL) { 521 filterlen = strlen(keyfilter) + 27; 522 udatalen = strlen(keyfilter) + 8; 523 MALLOC_FILTER_UDATA(filter, filterlen, 524 userdata, udatalen, nomem); 525 if (!nomem) { 526 (void) snprintf(filter, filterlen, 527 "(&(objectclass=nisObject)%s)", 528 keyfilter); 529 (void) snprintf(userdata, udatalen, 530 "(&(%%s)%s)", keyfilter); 531 } 532 } else { 533 filterlen = 22; 534 udatalen = 3; 535 MALLOC_FILTER_UDATA(filter, filterlen, 536 userdata, udatalen, nomem); 537 if (!nomem) { 538 (void) strlcpy(filter, 539 "objectclass=nisObject", filterlen); 540 (void) strlcpy(userdata, "%s", 541 udatalen); 542 } 543 } 544 } 545 goto done; 546 } 547 548 /* automount service */ 549 if (strcasecmp(database, "automount") == SAME) { 550 if (v2) { 551 if ((keyfilter = set_keys(key, "automountMapName")) 552 != NULL) { 553 filterlen = strlen(keyfilter) + 30; 554 udatalen = strlen(keyfilter) + 8; 555 MALLOC_FILTER_UDATA(filter, filterlen, 556 userdata, udatalen, nomem); 557 if (!nomem) { 558 (void) snprintf(filter, filterlen, 559 "(&(objectclass=automountMap)%s)", 560 keyfilter); 561 (void) snprintf(userdata, udatalen, 562 "(&(%%s)%s)", keyfilter); 563 } 564 } else { 565 filterlen = 25; 566 udatalen = 3; 567 MALLOC_FILTER_UDATA(filter, filterlen, 568 userdata, udatalen, nomem); 569 if (!nomem) { 570 (void) strlcpy(filter, 571 "objectclass=automountMap", 572 filterlen); 573 (void) strlcpy(userdata, "%s", 574 udatalen); 575 } 576 } 577 } else { 578 if ((keyfilter = set_keys(key, "nisMapName")) 579 != NULL) { 580 filterlen = strlen(keyfilter) + 24; 581 udatalen = strlen(keyfilter) + 8; 582 MALLOC_FILTER_UDATA(filter, filterlen, 583 userdata, udatalen, nomem); 584 if (!nomem) { 585 (void) snprintf(filter, filterlen, 586 "(&(objectclass=nisMap)%s)", 587 keyfilter); 588 (void) snprintf(userdata, udatalen, 589 "(&(%%s)%s)", keyfilter); 590 } 591 } else { 592 filterlen = 19; 593 udatalen = 3; 594 MALLOC_FILTER_UDATA(filter, filterlen, 595 userdata, udatalen, nomem); 596 if (!nomem) { 597 (void) strlcpy(filter, 598 "objectclass=nisMap", filterlen); 599 (void) strlcpy(userdata, "%s", 600 udatalen); 601 } 602 } 603 } 604 goto done; 605 } 606 607 /* other services (catch all) */ 608 if ((keyfilter = set_keys(key, "cn")) == NULL) { 609 filterlen = 14; 610 udatalen = 3; 611 MALLOC_FILTER_UDATA(filter, filterlen, userdata, udatalen, 612 nomem); 613 if (!nomem) { 614 (void) snprintf(filter, filterlen, "objectclass=*"); 615 (void) strlcpy(userdata, "%s", udatalen); 616 } 617 } else { 618 filterlen = strlen(keyfilter) + 1; 619 udatalen = strlen(keyfilter) + 8; 620 MALLOC_FILTER_UDATA(filter, filterlen, userdata, udatalen, 621 nomem); 622 if (!nomem) { 623 (void) snprintf(filter, filterlen, "%s", keyfilter); 624 (void) snprintf(userdata, udatalen, "(&(%%s)%s)", 625 keyfilter); 626 } 627 } 628 629 done: 630 #ifdef DEBUG 631 (void) fprintf(stdout, "set_filter: filter=\"%s\"\n", filter); 632 (void) fprintf(stdout, "set_filter: userdata=\"%s\"\n", userdata); 633 #endif /* DEBUG */ 634 if (keyfilter) 635 free(keyfilter); 636 if (nomem) 637 exit(2); 638 *udata = userdata; 639 return (filter); 640 } 641