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