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