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