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