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 (c) 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 26 #include <errno.h> 27 #include <ldap.h> 28 #include <sasl/sasl.h> 29 #include <libintl.h> 30 #include <strings.h> 31 #include <syslog.h> 32 #include <stdarg.h> 33 34 #include "addisc.h" 35 #include "libadutils.h" 36 #include "idmap_priv.h" 37 #include "ns_sldap.h" 38 #include "namemaps.h" 39 40 /* From adutils.c: */ 41 42 /* A single DS */ 43 struct idmap_nm_handle { 44 LDAP *ad; /* LDAP connection */ 45 /* LDAP DS info */ 46 char *ad_host; 47 int ad_port; 48 49 /* hardwired to SASL GSSAPI only for now */ 50 char *saslmech; 51 unsigned saslflags; 52 char *windomain; 53 char *ad_unixuser_attr; 54 char *ad_unixgroup_attr; 55 char *nldap_winname_attr; 56 char *default_domain; 57 bool_t is_nldap; 58 bool_t is_ad; 59 int direction; 60 ns_cred_t nsc; 61 }; 62 63 /* PRINTFLIKE1 */ 64 static 65 void 66 namemap_log(char *fmt, ...) 67 { 68 va_list va; 69 70 va_start(va, fmt); 71 (void) vfprintf(stderr, fmt, va); 72 va_end(va); 73 (void) fprintf(stderr, "\n"); 74 } 75 76 static 77 idmap_stat 78 string2auth(const char *from, ns_auth_t *na) 79 { 80 if (from == NULL) { 81 na->type = NS_LDAP_AUTH_SASL; 82 na->tlstype = NS_LDAP_TLS_SASL; 83 na->saslmech = NS_LDAP_SASL_GSSAPI; 84 na->saslopt = NS_LDAP_SASLOPT_PRIV | 85 NS_LDAP_SASLOPT_INT; 86 return (IDMAP_SUCCESS); 87 } 88 89 if (strcasecmp(from, "simple") == 0) { 90 na->type = NS_LDAP_AUTH_SIMPLE; 91 na->tlstype = NS_LDAP_TLS_NONE; 92 na->saslmech = NS_LDAP_SASL_NONE; 93 na->saslopt = NS_LDAP_SASLOPT_NONE; 94 } else if (strcasecmp(from, "sasl/CRAM-MD5") == 0) { 95 na->type = NS_LDAP_AUTH_SASL; 96 na->tlstype = NS_LDAP_TLS_SASL; 97 na->saslmech = NS_LDAP_SASL_CRAM_MD5; 98 na->saslopt = NS_LDAP_SASLOPT_NONE; 99 } else if (strcasecmp(from, "sasl/DIGEST-MD5") == 0) { 100 na->type = NS_LDAP_AUTH_SASL; 101 na->tlstype = NS_LDAP_TLS_SASL; 102 na->saslmech = NS_LDAP_SASL_DIGEST_MD5; 103 na->saslopt = NS_LDAP_SASLOPT_NONE; 104 } else if (strcasecmp(from, "sasl/GSSAPI") == 0) { 105 na->type = NS_LDAP_AUTH_SASL; 106 na->tlstype = NS_LDAP_TLS_SASL; 107 na->saslmech = NS_LDAP_SASL_GSSAPI; 108 na->saslopt = NS_LDAP_SASLOPT_PRIV | 109 NS_LDAP_SASLOPT_INT; 110 } else if (strcasecmp(from, "tls:simple") == 0) { 111 na->type = NS_LDAP_AUTH_TLS; 112 na->tlstype = NS_LDAP_TLS_SIMPLE; 113 na->saslmech = NS_LDAP_SASL_NONE; 114 na->saslopt = NS_LDAP_SASLOPT_NONE; 115 } else if (strcasecmp(from, "tls:sasl/CRAM-MD5") == 0) { 116 na->type = NS_LDAP_AUTH_TLS; 117 na->tlstype = NS_LDAP_TLS_SASL; 118 na->saslmech = NS_LDAP_SASL_CRAM_MD5; 119 na->saslopt = NS_LDAP_SASLOPT_NONE; 120 } else if (strcasecmp(from, "tls:sasl/DIGEST-MD5") == 0) { 121 na->type = NS_LDAP_AUTH_TLS; 122 na->tlstype = NS_LDAP_TLS_SASL; 123 na->saslmech = NS_LDAP_SASL_DIGEST_MD5; 124 na->saslopt = NS_LDAP_SASLOPT_NONE; 125 } else { 126 namemap_log( 127 gettext("Invalid authentication method \"%s\" specified\n"), 128 from); 129 return (IDMAP_ERR_ARG); 130 } 131 132 return (IDMAP_SUCCESS); 133 } 134 135 136 137 static 138 idmap_stat 139 strings2cred(ns_cred_t *nsc, char *user, char *passwd, char *auth) 140 { 141 idmap_stat rc; 142 (void) memset(nsc, 0, sizeof (ns_cred_t)); 143 144 if ((rc = string2auth(auth, &nsc->auth)) != IDMAP_SUCCESS) 145 return (rc); 146 147 if (user != NULL) { 148 nsc->cred.unix_cred.userID = strdup(user); 149 if (nsc->cred.unix_cred.userID == NULL) 150 return (IDMAP_ERR_MEMORY); 151 } 152 153 if (passwd != NULL) { 154 nsc->cred.unix_cred.passwd = strdup(passwd); 155 if (nsc->cred.unix_cred.passwd == NULL) { 156 free(nsc->cred.unix_cred.userID); 157 return (IDMAP_ERR_MEMORY); 158 } 159 } 160 161 return (IDMAP_SUCCESS); 162 } 163 164 165 166 167 168 /*ARGSUSED*/ 169 static int 170 idmap_saslcallback(LDAP *ld, unsigned flags, void *defaults, void *prompts) 171 { 172 sasl_interact_t *interact; 173 174 if (prompts == NULL || flags != LDAP_SASL_INTERACTIVE) 175 return (LDAP_PARAM_ERROR); 176 177 /* There should be no extra arguemnts for SASL/GSSAPI authentication */ 178 for (interact = prompts; interact->id != SASL_CB_LIST_END; 179 interact++) { 180 interact->result = NULL; 181 interact->len = 0; 182 } 183 return (LDAP_SUCCESS); 184 } 185 186 static 187 idmap_stat 188 idmap_open_ad_conn(idmap_nm_handle_t *adh) 189 { 190 int zero = 0; 191 int timeoutms = 30 * 1000; 192 int ldversion, ldap_rc; 193 idmap_stat rc = IDMAP_SUCCESS; 194 195 /* Open and bind an LDAP connection */ 196 adh->ad = ldap_init(adh->ad_host, adh->ad_port); 197 if (adh->ad == NULL) { 198 namemap_log( 199 gettext("ldap_init() to server %s port %d failed. (%s)"), 200 CHECK_NULL(adh->ad_host), 201 adh->ad_port, strerror(errno)); 202 rc = IDMAP_ERR_INTERNAL; 203 goto out; 204 } 205 ldversion = LDAP_VERSION3; 206 (void) ldap_set_option(adh->ad, LDAP_OPT_PROTOCOL_VERSION, &ldversion); 207 (void) ldap_set_option(adh->ad, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 208 (void) ldap_set_option(adh->ad, LDAP_OPT_TIMELIMIT, &zero); 209 (void) ldap_set_option(adh->ad, LDAP_OPT_SIZELIMIT, &zero); 210 (void) ldap_set_option(adh->ad, LDAP_X_OPT_CONNECT_TIMEOUT, &timeoutms); 211 (void) ldap_set_option(adh->ad, LDAP_OPT_RESTART, LDAP_OPT_ON); 212 ldap_rc = ldap_sasl_interactive_bind_s(adh->ad, "" /* binddn */, 213 adh->saslmech, NULL, NULL, adh->saslflags, &idmap_saslcallback, 214 NULL); 215 216 if (ldap_rc != LDAP_SUCCESS) { 217 (void) ldap_unbind(adh->ad); 218 adh->ad = NULL; 219 namemap_log( 220 gettext("ldap_sasl_interactive_bind_s() to server " 221 "%s port %d failed. (%s)"), CHECK_NULL(adh->ad_host), 222 adh->ad_port, ldap_err2string(ldap_rc)); 223 rc = IDMAP_ERR_INTERNAL; 224 } 225 226 out: 227 return (rc); 228 } 229 230 static 231 idmap_stat 232 idmap_init_nldap(idmap_nm_handle_t *p) 233 { 234 /* 235 * For now, there is nothing to initialize in nldap. This is just to 236 * make it future-proof, especially standalone libsldap-proof 237 */ 238 p->is_nldap = TRUE; 239 return (0); 240 } 241 242 static 243 idmap_stat 244 idmap_init_ad(idmap_nm_handle_t *p) 245 { 246 idmap_stat rc = IDMAP_SUCCESS; 247 idmap_ad_disc_ds_t *dc = NULL; 248 ad_disc_t ad_ctx; 249 250 ad_ctx = ad_disc_init(); 251 if (ad_ctx == NULL) { 252 namemap_log( 253 gettext("AD autodiscovery initialization failed")); 254 return (IDMAP_ERR_INTERNAL); 255 } 256 ad_disc_refresh(ad_ctx); 257 258 259 /* Based on the supplied or default domain, find the proper AD: */ 260 if (ad_disc_set_DomainName(ad_ctx, p->windomain)) { 261 rc = IDMAP_ERR_INTERNAL; 262 namemap_log( 263 gettext("Setting a domain name \"%s\" for autodiscovery" 264 " failed, most likely not enough memory"), p->windomain); 265 goto cleanup; 266 } 267 268 dc = ad_disc_get_DomainController(ad_ctx, AD_DISC_GLOBAL, NULL); 269 if (dc == NULL) { 270 rc = IDMAP_ERR_ARG; 271 namemap_log( 272 gettext("A domain controller for the " 273 "domain \"%s\" not found."), p->windomain); 274 goto cleanup; 275 } 276 277 278 p->ad_port = dc->port; 279 p->ad_host = strdup(dc->host); 280 281 if (p->ad_host == NULL) { 282 rc = IDMAP_ERR_MEMORY; 283 goto cleanup; 284 } 285 286 p->saslflags = LDAP_SASL_INTERACTIVE; 287 p->saslmech = strdup("GSSAPI"); 288 289 if (p->saslmech == NULL) { 290 rc = IDMAP_ERR_MEMORY; 291 goto cleanup; 292 } 293 294 rc = idmap_open_ad_conn(p); 295 296 if (rc != IDMAP_SUCCESS) 297 goto cleanup; 298 299 p->is_ad = TRUE; 300 301 cleanup: 302 ad_disc_fini(ad_ctx); 303 free(dc); 304 return (rc); 305 } 306 307 void 308 idmap_fini_namemaps(idmap_nm_handle_t *p) 309 { 310 if (p == NULL) 311 return; 312 313 if (p->ad_unixgroup_attr != NULL) 314 free(p->ad_unixgroup_attr); 315 316 if (p->ad_unixuser_attr != NULL) 317 free(p->ad_unixuser_attr); 318 319 if (p->nldap_winname_attr) 320 free(p->nldap_winname_attr); 321 322 if (p->windomain != NULL) 323 free(p->windomain); 324 325 if (p->default_domain != NULL) 326 free(p->default_domain); 327 328 if (p->saslmech != NULL) 329 free(p->saslmech); 330 331 if (p->ad_host != NULL) 332 free(p->ad_host); 333 334 if (p->nsc.cred.unix_cred.userID != NULL) { 335 free(p->nsc.cred.unix_cred.userID); 336 } 337 338 if (p->nsc.cred.unix_cred.passwd != NULL) { 339 /* No archeology: */ 340 (void) memset(p->nsc.cred.unix_cred.passwd, 0, 341 strlen(p->nsc.cred.unix_cred.passwd)); 342 free(p->nsc.cred.unix_cred.passwd); 343 } 344 345 if (p->ad) 346 (void) ldap_unbind(p->ad); 347 free(p); 348 349 } 350 351 352 353 idmap_stat 354 idmap_init_namemaps(idmap_handle_t *handle, idmap_nm_handle_t **adh, 355 char *user, char *passwd, char *auth, char *windomain, 356 int direction) 357 { 358 idmap_stat rc; 359 idmap_nm_handle_t *p; 360 361 p = (idmap_nm_handle_t *)calloc(1, sizeof (idmap_nm_handle_t)); 362 if (p == NULL) 363 return (IDMAP_ERR_MEMORY); 364 365 rc = idmap_get_prop_str(handle, PROP_DEFAULT_DOMAIN, 366 &p->default_domain); 367 if (rc != IDMAP_SUCCESS) { 368 namemap_log( 369 gettext("Error obtaining default domain from idmapd (%s)"), 370 idmap_stat2string(NULL, rc)); 371 goto cleanup; 372 } 373 374 rc = idmap_get_prop_str(handle, PROP_AD_UNIXUSER_ATTR, 375 &p->ad_unixuser_attr); 376 if (rc != IDMAP_SUCCESS) { 377 namemap_log( 378 gettext("Error obtaining AD unixuser attribute (%s)"), 379 idmap_stat2string(NULL, rc)); 380 goto cleanup; 381 } 382 383 rc = idmap_get_prop_str(handle, PROP_AD_UNIXGROUP_ATTR, 384 &p->ad_unixgroup_attr); 385 if (rc != IDMAP_SUCCESS) { 386 namemap_log( 387 gettext("Error obtaining AD unixgroup attribute (%s)"), 388 idmap_stat2string(NULL, rc)); 389 goto cleanup; 390 } 391 392 393 rc = idmap_get_prop_str(handle, PROP_NLDAP_WINNAME_ATTR, 394 &p->nldap_winname_attr); 395 if (rc != IDMAP_SUCCESS) { 396 namemap_log( 397 gettext("Error obtaining AD unixgroup attribute (%s)"), 398 idmap_stat2string(NULL, rc)); 399 goto cleanup; 400 } 401 402 if (windomain != NULL) { 403 p->windomain = strdup(windomain); 404 if (p->windomain == NULL) { 405 rc = IDMAP_ERR_MEMORY; 406 goto cleanup; 407 } 408 } else if (!EMPTY_STRING(p->default_domain)) { 409 p->windomain = strdup(p->default_domain); 410 if (p->windomain == NULL) { 411 rc = IDMAP_ERR_MEMORY; 412 goto cleanup; 413 } 414 } else if (direction == IDMAP_DIRECTION_W2U) { 415 namemap_log( 416 gettext("Windows domain not given and idmapd daemon" 417 " didn't provide a default one")); 418 rc = IDMAP_ERR_ARG; 419 goto cleanup; 420 } 421 422 p->direction = direction; 423 424 if ((p->ad_unixuser_attr != NULL || p->ad_unixgroup_attr != NULL) && 425 direction != IDMAP_DIRECTION_U2W) { 426 rc = idmap_init_ad(p); 427 if (rc != IDMAP_SUCCESS) { 428 goto cleanup; 429 } 430 } 431 432 if (p->nldap_winname_attr != NULL && direction != IDMAP_DIRECTION_W2U) { 433 rc = idmap_init_nldap(p); 434 if (rc != IDMAP_SUCCESS) { 435 goto cleanup; 436 } 437 438 rc = strings2cred(&p->nsc, user, passwd, auth); 439 if (rc != IDMAP_SUCCESS) { 440 goto cleanup; 441 } 442 } 443 444 cleanup: 445 446 if (rc == IDMAP_SUCCESS) { 447 *adh = p; 448 return (IDMAP_SUCCESS); 449 } 450 451 /* There was an error: */ 452 idmap_fini_namemaps(*adh); 453 return (rc); 454 } 455 456 static 457 char * 458 dns2dn(const char *dns, const char *prefix) 459 { 460 int num_lvl = 1; 461 char *buf; 462 const char *it, *new_it; 463 464 for (it = dns; it != NULL; it = strchr(it, '.')) { 465 it ++; 466 num_lvl ++; 467 } 468 469 buf = (char *)malloc(strlen(prefix) + strlen(dns) + 4 * num_lvl); 470 (void) strcpy(buf, prefix); 471 472 473 it = dns; 474 for (;;) { 475 new_it = strchr(it, '.'); 476 (void) strcat(buf, "DC="); 477 if (new_it == NULL) { 478 (void) strcat(buf, it); 479 break; 480 } else { 481 (void) strncat(buf, it, new_it - it); 482 (void) strcat(buf, ","); 483 } 484 485 it = new_it + 1; 486 } 487 488 return (buf); 489 } 490 491 492 static 493 idmap_stat 494 extract_attribute(idmap_nm_handle_t *p, LDAPMessage *entry, char *name, 495 char **value) 496 { 497 char **values = NULL; 498 idmap_stat rc = IDMAP_SUCCESS; 499 /* No value means it is not requested */ 500 if (value == NULL) 501 return (IDMAP_SUCCESS); 502 503 values = ldap_get_values(p->ad, entry, name); 504 if (values == NULL || values[0] == NULL) 505 *value = NULL; 506 else { 507 *value = strdup(values[0]); 508 if (*value == NULL) 509 rc = IDMAP_ERR_MEMORY; 510 } 511 errout: 512 ldap_value_free(values); 513 return (rc); 514 } 515 516 517 /* Split winname to its name and domain part */ 518 static 519 idmap_stat 520 split_fqwn(char *fqwn, char **name, char **domain) 521 { 522 char *at; 523 524 *name = NULL; 525 *domain = NULL; 526 527 at = strchr(fqwn, '@'); 528 if (at == NULL) { 529 at = strchr(fqwn, '\\'); 530 } 531 if (at == NULL) { 532 /* There is no domain - leave domain NULL */ 533 *name = strdup(fqwn); 534 if (*name == NULL) 535 goto errout; 536 return (IDMAP_SUCCESS); 537 } 538 539 540 *domain = strdup(at+1); 541 if (*domain == NULL) 542 goto errout; 543 *name = (char *)malloc(at - fqwn + 1); 544 if (*name == NULL) 545 goto errout; 546 (void) strlcpy(*name, fqwn, at - fqwn + 1); 547 548 if (*at == '\\') { 549 char *it = *name; 550 *name = *domain; 551 *domain = it; 552 } 553 554 return (IDMAP_SUCCESS); 555 556 557 errout: 558 free(*name); 559 *name = NULL; 560 free(*domain); 561 *domain = NULL; 562 return (IDMAP_ERR_MEMORY); 563 } 564 565 static 566 idmap_stat 567 unixname2dn(idmap_nm_handle_t *p, char *unixname, int is_user, char **dn, 568 char **winname, char **windomain) 569 { 570 idmap_stat rc = IDMAP_SUCCESS; 571 int rc_ns; 572 573 574 char filter[255]; 575 static const char *attribs[3]; 576 ns_ldap_result_t *res; 577 ns_ldap_error_t *errorp = NULL; 578 char **attrs; 579 580 581 attribs[0] = p->nldap_winname_attr; 582 attribs[1] = "dn"; 583 attribs[2] = NULL; 584 585 (void) snprintf(filter, sizeof (filter), is_user ? "uid=%s" : "cn=%s", 586 unixname); 587 588 rc_ns = __ns_ldap_list(is_user ? "passwd" : "group", 589 filter, NULL, attribs, NULL, 0, &res, &errorp, NULL, NULL); 590 591 592 if (rc_ns == NS_LDAP_NOTFOUND) { 593 namemap_log(is_user ? gettext("User %s not found.") 594 : gettext("Group %s not found."), unixname); 595 return (IDMAP_ERR_NOTFOUND); 596 } else if (rc_ns != NS_LDAP_SUCCESS) { 597 char *msg = "Cause unidentified"; 598 if (errorp != NULL) { 599 (void) __ns_ldap_err2str(errorp->status, &msg); 600 } 601 namemap_log(gettext("Ldap list failed (%s)."), msg); 602 return (IDMAP_ERR_ARG); 603 } 604 605 if (res == NULL) { 606 namemap_log(gettext("User %s not found"), unixname); 607 return (IDMAP_ERR_ARG); 608 } 609 610 if (winname != NULL && windomain != NULL) { 611 attrs = __ns_ldap_getAttr(&res->entry[0], 612 p->nldap_winname_attr); 613 if (attrs != NULL && attrs[0] != NULL) { 614 rc = split_fqwn(attrs[0], winname, windomain); 615 } else { 616 *winname = *windomain = NULL; 617 } 618 } 619 620 if (dn != NULL) { 621 attrs = __ns_ldap_getAttr(&res->entry[0], "dn"); 622 if (attrs == NULL || attrs[0] == NULL) { 623 namemap_log(gettext("dn for %s not found"), 624 unixname); 625 return (IDMAP_ERR_ARG); 626 } 627 *dn = strdup(attrs[0]); 628 } 629 630 631 return (rc); 632 633 } 634 635 #define FILTER "(sAMAccountName=%s)" 636 637 /* Puts the values of attributes to unixuser and unixgroup, unless NULL */ 638 639 static 640 idmap_stat 641 winname2dn(idmap_nm_handle_t *p, char *winname, 642 int *is_wuser, char **dn, char **unixuser, char **unixgroup) 643 { 644 idmap_stat rc = IDMAP_SUCCESS; 645 char *base; 646 char *filter; 647 int flen; 648 char *attribs[4]; 649 int i; 650 LDAPMessage *results = NULL; 651 LDAPMessage *entry; 652 int ldap_rc; 653 654 /* Query: */ 655 656 base = dns2dn(p->windomain, ""); 657 if (base == NULL) { 658 return (IDMAP_ERR_MEMORY); 659 } 660 661 i = 0; 662 attribs[i++] = "objectClass"; 663 if (unixuser != NULL) 664 attribs[i++] = p->ad_unixuser_attr; 665 if (unixgroup != NULL) 666 attribs[i++] = p->ad_unixgroup_attr; 667 attribs[i] = NULL; 668 669 flen = snprintf(NULL, 0, FILTER, winname) + 1; 670 if ((filter = (char *)malloc(flen)) == NULL) { 671 free(base); 672 return (IDMAP_ERR_MEMORY); 673 } 674 (void) snprintf(filter, flen, FILTER, winname); 675 676 ldap_rc = ldap_search_s(p->ad, base, LDAP_SCOPE_SUBTREE, filter, 677 attribs, 0, &results); 678 679 free(base); 680 free(filter); 681 682 if (ldap_rc != LDAP_SUCCESS) { 683 namemap_log( 684 gettext("Ldap query to server %s port %d failed. (%s)"), 685 p->ad_host, p->ad_port, ldap_err2string(ldap_rc)); 686 (void) ldap_msgfree(results); 687 return (IDMAP_ERR_OTHER); 688 } 689 690 691 for (entry = ldap_first_entry(p->ad, results), *dn = NULL; 692 entry != NULL; 693 entry = ldap_next_entry(p->ad, entry)) { 694 char **values = NULL; 695 int i = 0; 696 values = ldap_get_values(p->ad, entry, "objectClass"); 697 698 if (values == NULL) { 699 (void) ldap_msgfree(results); 700 return (IDMAP_ERR_MEMORY); 701 } 702 703 for (i = 0; i < ldap_count_values(values); i++) { 704 /* 705 * is_wuser can be IDMAP_UNKNOWN, in that case we accept 706 * both User/Group 707 */ 708 if (*is_wuser != IDMAP_NO && 709 strcasecmp(values[i], "User") == 0 || 710 *is_wuser != IDMAP_YES && 711 strcasecmp(values[i], "Group") == 0) { 712 *dn = ldap_get_dn(p->ad, entry); 713 if (*dn == NULL) { 714 ldap_value_free(values); 715 (void) ldap_msgfree(results); 716 return (IDMAP_ERR_MEMORY); 717 } 718 *is_wuser = strcasecmp(values[i], "User") == 0 719 ? IDMAP_YES : IDMAP_NO; 720 break; 721 } 722 } 723 724 ldap_value_free(values); 725 if (*dn != NULL) 726 break; 727 } 728 729 if (*dn == NULL) { 730 namemap_log( 731 *is_wuser == IDMAP_YES ? gettext("User %s@%s not found") : 732 *is_wuser == IDMAP_NO ? gettext("Group %s@%s not found") : 733 gettext("%s@%s not found"), winname, p->windomain); 734 return (IDMAP_ERR_NOTFOUND); 735 } 736 737 if (unixuser != NULL) 738 rc = extract_attribute(p, entry, p->ad_unixuser_attr, 739 unixuser); 740 741 if (rc == IDMAP_SUCCESS && unixgroup != NULL) 742 rc = extract_attribute(p, entry, p->ad_unixgroup_attr, 743 unixgroup); 744 745 (void) ldap_msgfree(results); 746 747 return (rc); 748 } 749 750 751 /* set the given attribute to the given value. If value is NULL, unset it */ 752 static 753 idmap_stat 754 idmap_ad_set(idmap_nm_handle_t *p, char *dn, char *attr, char *value) 755 { 756 idmap_stat rc = IDMAP_SUCCESS; 757 int ldap_rc; 758 char *new_values[2] = {NULL, NULL}; 759 LDAPMod *mods[2] = {NULL, NULL}; 760 761 mods[0] = (LDAPMod *)calloc(1, sizeof (LDAPMod)); 762 mods[0]->mod_type = strdup(attr); 763 if (value != NULL) { 764 mods[0]->mod_op = LDAP_MOD_REPLACE; 765 new_values[0] = strdup(value); 766 mods[0]->mod_values = new_values; 767 } else { 768 mods[0]->mod_op = LDAP_MOD_DELETE; 769 mods[0]->mod_values = NULL; 770 } 771 772 ldap_rc = ldap_modify_s(p->ad, dn, mods); 773 if (ldap_rc != LDAP_SUCCESS) { 774 namemap_log( 775 gettext("Ldap modify of %s, attribute %s failed. (%s)"), 776 dn, attr, ldap_err2string(ldap_rc)); 777 rc = IDMAP_ERR_INTERNAL; 778 } 779 780 781 ldap_mods_free(mods, 0); 782 return (rc); 783 } 784 785 786 /* 787 * This function takes the p argument just for the beauty of the symmetry 788 * with idmap_ad_set (and for future enhancements). 789 */ 790 static 791 idmap_stat 792 /* LINTED E_FUNC_ARG_UNUSED */ 793 idmap_nldap_set(idmap_nm_handle_t *p, ns_cred_t *nsc, char *dn, char *attr, 794 char *value, bool_t is_new, int is_user) 795 { 796 int ldaprc; 797 ns_ldap_error_t *errorp = NULL; 798 ns_ldap_attr_t *attrs[2]; 799 800 801 802 attrs[0] = (ns_ldap_attr_t *)malloc(sizeof (ns_ldap_attr_t)); 803 if (attrs == NULL) 804 return (IDMAP_ERR_MEMORY); 805 806 attrs[0]->attrname = attr; 807 808 if (value != NULL) { 809 char **newattr = (char **)calloc(2, sizeof (char *)); 810 if (newattr == NULL) { 811 free(attrs[0]); 812 return (IDMAP_ERR_MEMORY); 813 } 814 newattr[0] = value; 815 newattr[1] = NULL; 816 817 attrs[0]->attrvalue = newattr; 818 attrs[0]->value_count = 1; 819 } else { 820 attrs[0]->attrvalue = NULL; 821 attrs[0]->value_count = 0; 822 } 823 824 825 attrs[1] = NULL; 826 827 if (value == NULL) { 828 ldaprc = __ns_ldap_delAttr( 829 is_user == IDMAP_YES ? "passwd": "group", 830 dn, (const ns_ldap_attr_t * const *)attrs, 831 nsc, 0, &errorp); 832 } else if (is_new) 833 ldaprc = __ns_ldap_addAttr( 834 is_user == IDMAP_YES ? "passwd": "group", 835 dn, (const ns_ldap_attr_t * const *)attrs, 836 nsc, 0, &errorp); 837 else 838 ldaprc = __ns_ldap_repAttr( 839 is_user == IDMAP_YES ? "passwd": "group", 840 dn, (const ns_ldap_attr_t * const *)attrs, 841 nsc, 0, &errorp); 842 843 if (ldaprc != NS_LDAP_SUCCESS) { 844 char *msg = "Cause unidentified"; 845 if (errorp != NULL) { 846 (void) __ns_ldap_err2str(errorp->status, &msg); 847 } 848 namemap_log( 849 gettext("__ns_ldap_addAttr/rep/delAttr failed (%s)"), 850 msg); 851 return (IDMAP_ERR_ARG); 852 } 853 854 return (IDMAP_SUCCESS); 855 } 856 857 idmap_stat 858 idmap_set_namemap(idmap_nm_handle_t *p, char *winname, char *unixname, 859 int is_user, int is_wuser, int direction) 860 { 861 idmap_stat rc = IDMAP_SUCCESS; 862 char *dn = NULL; 863 char *oldwinname = NULL; 864 char *oldwindomain = NULL; 865 866 if (direction == IDMAP_DIRECTION_W2U) { 867 if (!p->is_ad) { 868 rc = IDMAP_ERR_ARG; 869 namemap_log( 870 gettext("AD namemaps aren't set up.")); 871 goto cleanup; 872 } 873 874 rc = winname2dn(p, winname, &is_wuser, 875 &dn, NULL, NULL); 876 if (rc != IDMAP_SUCCESS) 877 goto cleanup; 878 879 rc = idmap_ad_set(p, dn, is_user ? p->ad_unixuser_attr : 880 p->ad_unixgroup_attr, unixname); 881 if (rc != IDMAP_SUCCESS) 882 goto cleanup; 883 884 } 885 886 887 if (direction == IDMAP_DIRECTION_U2W) { 888 char *fullname; 889 890 if (!p->is_nldap) { 891 rc = IDMAP_ERR_ARG; 892 namemap_log( 893 gettext("Native ldap namemaps aren't set up.")); 894 goto cleanup; 895 } 896 897 898 rc = unixname2dn(p, unixname, is_user, &dn, 899 &oldwinname, &oldwindomain); 900 if (rc != IDMAP_SUCCESS) 901 goto cleanup; 902 903 if (p->windomain == NULL) { 904 fullname = strdup(winname); 905 if (fullname == NULL) 906 rc = IDMAP_ERR_MEMORY; 907 goto cleanup; 908 } else { 909 fullname = malloc(strlen(winname) + 910 strlen(p->windomain) + 2); 911 if (fullname == NULL) { 912 rc = IDMAP_ERR_MEMORY; 913 goto cleanup; 914 } 915 916 (void) snprintf(fullname, 917 strlen(winname) + strlen(p->windomain) + 2, 918 "%s\\%s", p->windomain, winname); 919 } 920 rc = idmap_nldap_set(p, &p->nsc, dn, p->nldap_winname_attr, 921 fullname, oldwinname == NULL ? TRUE : FALSE, is_user); 922 923 free(fullname); 924 free(oldwindomain); 925 free(oldwinname); 926 927 if (rc != IDMAP_SUCCESS) 928 goto cleanup; 929 930 } 931 932 cleanup: 933 if (dn != NULL) 934 free(dn); 935 936 if (oldwindomain != NULL) 937 free(oldwindomain); 938 939 if (oldwinname != NULL) 940 free(oldwinname); 941 942 return (rc); 943 944 } 945 946 947 idmap_stat 948 idmap_unset_namemap(idmap_nm_handle_t *p, char *winname, char *unixname, 949 int is_user, int is_wuser, int direction) 950 { 951 idmap_stat rc = IDMAP_SUCCESS; 952 char *dn = NULL; 953 char *oldwinname = NULL; 954 char *oldwindomain = NULL; 955 956 if (direction == IDMAP_DIRECTION_W2U) { 957 if (!p->is_ad) { 958 rc = IDMAP_ERR_ARG; 959 namemap_log( 960 gettext("AD namemaps aren't set up.")); 961 goto cleanup; 962 } 963 964 rc = winname2dn(p, winname, &is_wuser, 965 &dn, NULL, NULL); 966 if (rc != IDMAP_SUCCESS) 967 goto cleanup; 968 969 rc = idmap_ad_set(p, dn, is_user ? p->ad_unixuser_attr : 970 p->ad_unixgroup_attr, unixname); 971 if (rc != IDMAP_SUCCESS) 972 goto cleanup; 973 974 } else { /* direction == IDMAP_DIRECTION_U2W */ 975 if (!p->is_nldap) { 976 rc = IDMAP_ERR_ARG; 977 namemap_log( 978 gettext("Native ldap namemaps aren't set up.")); 979 goto cleanup; 980 } 981 982 rc = unixname2dn(p, unixname, is_user, &dn, NULL, NULL); 983 if (rc != IDMAP_SUCCESS) 984 goto cleanup; 985 986 rc = idmap_nldap_set(p, &p->nsc, dn, p->nldap_winname_attr, 987 NULL, TRUE, is_user); 988 if (rc != IDMAP_SUCCESS) 989 goto cleanup; 990 991 } 992 993 cleanup: 994 if (oldwindomain != NULL) 995 free(oldwindomain); 996 if (oldwinname != NULL) 997 free(oldwinname); 998 if (dn != NULL) 999 free(dn); 1000 return (rc); 1001 } 1002 1003 idmap_stat 1004 idmap_get_namemap(idmap_nm_handle_t *p, int *is_source_ad, char **winname, 1005 char **windomain, int *is_wuser, char **unixuser, char **unixgroup) 1006 { 1007 idmap_stat rc = IDMAP_SUCCESS; 1008 char *dn = NULL; 1009 1010 *is_source_ad = IDMAP_UNKNOWN; 1011 if (*winname != NULL) { 1012 *is_source_ad = IDMAP_YES; 1013 1014 if (p->is_ad == NULL) { 1015 rc = IDMAP_ERR_ARG; 1016 namemap_log( 1017 gettext("AD namemaps are not active.")); 1018 goto cleanup; 1019 /* In future maybe resolve winname and try nldap? */ 1020 } 1021 1022 rc = winname2dn(p, *winname, is_wuser, &dn, unixuser, 1023 unixgroup); 1024 if (rc != IDMAP_SUCCESS) { 1025 namemap_log( 1026 gettext("Winname %s@%s not found in AD."), 1027 *winname, p->windomain); 1028 } 1029 } else if (*unixuser != NULL || *unixgroup != NULL) { 1030 char *unixname; 1031 int is_user; 1032 1033 *is_source_ad = IDMAP_NO; 1034 1035 if (p->is_nldap == NULL) { 1036 rc = IDMAP_ERR_ARG; 1037 namemap_log( 1038 gettext("Native ldap namemaps aren't active.")); 1039 goto cleanup; 1040 /* In future maybe resolve unixname and try AD? */ 1041 } 1042 1043 if (*unixuser != NULL) { 1044 is_user = IDMAP_YES; 1045 unixname = *unixuser; 1046 } else if (*unixgroup != NULL) { 1047 is_user = IDMAP_NO; 1048 unixname = *unixgroup; 1049 } 1050 1051 rc = unixname2dn(p, unixname, is_user, NULL, winname, 1052 windomain); 1053 if (rc != IDMAP_SUCCESS) { 1054 namemap_log( 1055 gettext("%s %s not found in native ldap."), 1056 is_user == IDMAP_YES ? "UNIX user" : "UNIX group", 1057 unixname); 1058 goto cleanup; 1059 } 1060 } else { 1061 rc = IDMAP_ERR_ARG; 1062 goto cleanup; 1063 } 1064 1065 cleanup: 1066 return (rc); 1067 } 1068