/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include "addisc.h" #include "libadutils.h" #include "idmap_priv.h" #include "ns_sldap.h" #include "namemaps.h" /* From adutils.c: */ /* A single DS */ struct idmap_nm_handle { LDAP *ad; /* LDAP connection */ /* LDAP DS info */ char *ad_host; int ad_port; /* hardwired to SASL GSSAPI only for now */ char *saslmech; unsigned saslflags; char *windomain; char *ad_unixuser_attr; char *ad_unixgroup_attr; char *nldap_winname_attr; char *default_domain; bool_t is_nldap; bool_t is_ad; int direction; ns_cred_t nsc; }; /* PRINTFLIKE1 */ static void namemap_log(char *fmt, ...) { va_list va; va_start(va, fmt); (void) vfprintf(stderr, fmt, va); va_end(va); (void) fprintf(stderr, "\n"); } static idmap_stat string2auth(const char *from, ns_auth_t *na) { if (from == NULL) { na->type = NS_LDAP_AUTH_SASL; na->tlstype = NS_LDAP_TLS_SASL; na->saslmech = NS_LDAP_SASL_GSSAPI; na->saslopt = NS_LDAP_SASLOPT_PRIV | NS_LDAP_SASLOPT_INT; return (IDMAP_SUCCESS); } if (strcasecmp(from, "simple") == 0) { na->type = NS_LDAP_AUTH_SIMPLE; na->tlstype = NS_LDAP_TLS_NONE; na->saslmech = NS_LDAP_SASL_NONE; na->saslopt = NS_LDAP_SASLOPT_NONE; } else if (strcasecmp(from, "sasl/CRAM-MD5") == 0) { na->type = NS_LDAP_AUTH_SASL; na->tlstype = NS_LDAP_TLS_SASL; na->saslmech = NS_LDAP_SASL_CRAM_MD5; na->saslopt = NS_LDAP_SASLOPT_NONE; } else if (strcasecmp(from, "sasl/DIGEST-MD5") == 0) { na->type = NS_LDAP_AUTH_SASL; na->tlstype = NS_LDAP_TLS_SASL; na->saslmech = NS_LDAP_SASL_DIGEST_MD5; na->saslopt = NS_LDAP_SASLOPT_NONE; } else if (strcasecmp(from, "sasl/GSSAPI") == 0) { na->type = NS_LDAP_AUTH_SASL; na->tlstype = NS_LDAP_TLS_SASL; na->saslmech = NS_LDAP_SASL_GSSAPI; na->saslopt = NS_LDAP_SASLOPT_PRIV | NS_LDAP_SASLOPT_INT; } else if (strcasecmp(from, "tls:simple") == 0) { na->type = NS_LDAP_AUTH_TLS; na->tlstype = NS_LDAP_TLS_SIMPLE; na->saslmech = NS_LDAP_SASL_NONE; na->saslopt = NS_LDAP_SASLOPT_NONE; } else if (strcasecmp(from, "tls:sasl/CRAM-MD5") == 0) { na->type = NS_LDAP_AUTH_TLS; na->tlstype = NS_LDAP_TLS_SASL; na->saslmech = NS_LDAP_SASL_CRAM_MD5; na->saslopt = NS_LDAP_SASLOPT_NONE; } else if (strcasecmp(from, "tls:sasl/DIGEST-MD5") == 0) { na->type = NS_LDAP_AUTH_TLS; na->tlstype = NS_LDAP_TLS_SASL; na->saslmech = NS_LDAP_SASL_DIGEST_MD5; na->saslopt = NS_LDAP_SASLOPT_NONE; } else { namemap_log( gettext("Invalid authentication method \"%s\" specified\n"), from); return (IDMAP_ERR_ARG); } return (IDMAP_SUCCESS); } static idmap_stat strings2cred(ns_cred_t *nsc, char *user, char *passwd, char *auth) { idmap_stat rc; (void) memset(nsc, 0, sizeof (ns_cred_t)); if ((rc = string2auth(auth, &nsc->auth)) != IDMAP_SUCCESS) return (rc); if (user != NULL) { nsc->cred.unix_cred.userID = strdup(user); if (nsc->cred.unix_cred.userID == NULL) return (IDMAP_ERR_MEMORY); } if (passwd != NULL) { nsc->cred.unix_cred.passwd = strdup(passwd); if (nsc->cred.unix_cred.passwd == NULL) { free(nsc->cred.unix_cred.userID); return (IDMAP_ERR_MEMORY); } } return (IDMAP_SUCCESS); } /*ARGSUSED*/ static int idmap_saslcallback(LDAP *ld, unsigned flags, void *defaults, void *prompts) { sasl_interact_t *interact; if (prompts == NULL || flags != LDAP_SASL_INTERACTIVE) return (LDAP_PARAM_ERROR); /* There should be no extra arguemnts for SASL/GSSAPI authentication */ for (interact = prompts; interact->id != SASL_CB_LIST_END; interact++) { interact->result = NULL; interact->len = 0; } return (LDAP_SUCCESS); } static idmap_stat idmap_open_ad_conn(idmap_nm_handle_t *adh) { int zero = 0; int timeoutms = 30 * 1000; int ldversion, ldap_rc; idmap_stat rc = IDMAP_SUCCESS; /* Open and bind an LDAP connection */ adh->ad = ldap_init(adh->ad_host, adh->ad_port); if (adh->ad == NULL) { namemap_log( gettext("ldap_init() to server %s port %d failed. (%s)"), CHECK_NULL(adh->ad_host), adh->ad_port, strerror(errno)); rc = IDMAP_ERR_INTERNAL; goto out; } ldversion = LDAP_VERSION3; (void) ldap_set_option(adh->ad, LDAP_OPT_PROTOCOL_VERSION, &ldversion); (void) ldap_set_option(adh->ad, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); (void) ldap_set_option(adh->ad, LDAP_OPT_TIMELIMIT, &zero); (void) ldap_set_option(adh->ad, LDAP_OPT_SIZELIMIT, &zero); (void) ldap_set_option(adh->ad, LDAP_X_OPT_CONNECT_TIMEOUT, &timeoutms); (void) ldap_set_option(adh->ad, LDAP_OPT_RESTART, LDAP_OPT_ON); ldap_rc = ldap_sasl_interactive_bind_s(adh->ad, "" /* binddn */, adh->saslmech, NULL, NULL, adh->saslflags, &idmap_saslcallback, NULL); if (ldap_rc != LDAP_SUCCESS) { (void) ldap_unbind(adh->ad); adh->ad = NULL; namemap_log( gettext("ldap_sasl_interactive_bind_s() to server " "%s port %d failed. (%s)"), CHECK_NULL(adh->ad_host), adh->ad_port, ldap_err2string(ldap_rc)); rc = IDMAP_ERR_INTERNAL; } out: return (rc); } static idmap_stat idmap_init_nldap(idmap_nm_handle_t *p) { /* * For now, there is nothing to initialize in nldap. This is just to * make it future-proof, especially standalone libsldap-proof */ p->is_nldap = TRUE; return (0); } static idmap_stat idmap_init_ad(idmap_nm_handle_t *p) { idmap_stat rc = IDMAP_SUCCESS; ad_disc_ds_t *dc = NULL; ad_disc_t ad_ctx; ad_ctx = ad_disc_init(); if (ad_ctx == NULL) { namemap_log( gettext("AD autodiscovery initialization failed")); return (IDMAP_ERR_INTERNAL); } ad_disc_refresh(ad_ctx); /* Based on the supplied or default domain, find the proper AD: */ if (ad_disc_set_DomainName(ad_ctx, p->windomain)) { rc = IDMAP_ERR_INTERNAL; namemap_log( gettext("Setting a domain name \"%s\" for autodiscovery" " failed, most likely not enough memory"), p->windomain); goto cleanup; } dc = ad_disc_get_DomainController(ad_ctx, AD_DISC_GLOBAL, NULL); if (dc == NULL) { rc = IDMAP_ERR_ARG; namemap_log( gettext("A domain controller for the " "domain \"%s\" not found."), p->windomain); goto cleanup; } p->ad_port = dc->port; p->ad_host = strdup(dc->host); if (p->ad_host == NULL) { rc = IDMAP_ERR_MEMORY; goto cleanup; } p->saslflags = LDAP_SASL_INTERACTIVE; p->saslmech = strdup("GSSAPI"); if (p->saslmech == NULL) { rc = IDMAP_ERR_MEMORY; goto cleanup; } rc = idmap_open_ad_conn(p); if (rc != IDMAP_SUCCESS) goto cleanup; p->is_ad = TRUE; cleanup: ad_disc_fini(ad_ctx); free(dc); return (rc); } void idmap_fini_namemaps(idmap_nm_handle_t *p) { if (p == NULL) return; if (p->ad_unixgroup_attr != NULL) free(p->ad_unixgroup_attr); if (p->ad_unixuser_attr != NULL) free(p->ad_unixuser_attr); if (p->nldap_winname_attr) free(p->nldap_winname_attr); if (p->windomain != NULL) free(p->windomain); if (p->default_domain != NULL) free(p->default_domain); if (p->saslmech != NULL) free(p->saslmech); if (p->ad_host != NULL) free(p->ad_host); if (p->nsc.cred.unix_cred.userID != NULL) { free(p->nsc.cred.unix_cred.userID); } if (p->nsc.cred.unix_cred.passwd != NULL) { /* No archeology: */ (void) memset(p->nsc.cred.unix_cred.passwd, 0, strlen(p->nsc.cred.unix_cred.passwd)); free(p->nsc.cred.unix_cred.passwd); } if (p->ad) (void) ldap_unbind(p->ad); free(p); } idmap_stat idmap_init_namemaps(idmap_nm_handle_t **adh, char *user, char *passwd, char *auth, char *windomain, int direction) { idmap_stat rc; idmap_nm_handle_t *p; p = (idmap_nm_handle_t *)calloc(1, sizeof (idmap_nm_handle_t)); if (p == NULL) return (IDMAP_ERR_MEMORY); rc = idmap_get_prop_str(PROP_DEFAULT_DOMAIN, &p->default_domain); if (rc != IDMAP_SUCCESS) { namemap_log( gettext("Error obtaining default domain from idmapd (%s)"), idmap_stat2string(rc)); goto cleanup; } rc = idmap_get_prop_str(PROP_AD_UNIXUSER_ATTR, &p->ad_unixuser_attr); if (rc != IDMAP_SUCCESS) { namemap_log( gettext("Error obtaining AD unixuser attribute (%s)"), idmap_stat2string(rc)); goto cleanup; } rc = idmap_get_prop_str(PROP_AD_UNIXGROUP_ATTR, &p->ad_unixgroup_attr); if (rc != IDMAP_SUCCESS) { namemap_log( gettext("Error obtaining AD unixgroup attribute (%s)"), idmap_stat2string(rc)); goto cleanup; } rc = idmap_get_prop_str(PROP_NLDAP_WINNAME_ATTR, &p->nldap_winname_attr); if (rc != IDMAP_SUCCESS) { namemap_log( gettext("Error obtaining AD unixgroup attribute (%s)"), idmap_stat2string(rc)); goto cleanup; } if (windomain != NULL) { p->windomain = strdup(windomain); if (p->windomain == NULL) { rc = IDMAP_ERR_MEMORY; goto cleanup; } } else if (!EMPTY_STRING(p->default_domain)) { p->windomain = strdup(p->default_domain); if (p->windomain == NULL) { rc = IDMAP_ERR_MEMORY; goto cleanup; } } else if (direction == IDMAP_DIRECTION_W2U) { namemap_log( gettext("Windows domain not given and idmapd daemon" " didn't provide a default one")); rc = IDMAP_ERR_ARG; goto cleanup; } p->direction = direction; if ((p->ad_unixuser_attr != NULL || p->ad_unixgroup_attr != NULL) && direction != IDMAP_DIRECTION_U2W) { rc = idmap_init_ad(p); if (rc != IDMAP_SUCCESS) { goto cleanup; } } if (p->nldap_winname_attr != NULL && direction != IDMAP_DIRECTION_W2U) { rc = idmap_init_nldap(p); if (rc != IDMAP_SUCCESS) { goto cleanup; } rc = strings2cred(&p->nsc, user, passwd, auth); if (rc != IDMAP_SUCCESS) { goto cleanup; } } cleanup: if (rc == IDMAP_SUCCESS) { *adh = p; return (IDMAP_SUCCESS); } /* There was an error: */ idmap_fini_namemaps(*adh); return (rc); } static char * dns2dn(const char *dns, const char *prefix) { int num_lvl = 1; char *buf; const char *it, *new_it; for (it = dns; it != NULL; it = strchr(it, '.')) { it ++; num_lvl ++; } buf = (char *)malloc(strlen(prefix) + strlen(dns) + 4 * num_lvl); (void) strcpy(buf, prefix); it = dns; for (;;) { new_it = strchr(it, '.'); (void) strcat(buf, "DC="); if (new_it == NULL) { (void) strcat(buf, it); break; } else { (void) strncat(buf, it, new_it - it); (void) strcat(buf, ","); } it = new_it + 1; } return (buf); } static idmap_stat extract_attribute(idmap_nm_handle_t *p, LDAPMessage *entry, char *name, char **value) { char **values = NULL; idmap_stat rc = IDMAP_SUCCESS; /* No value means it is not requested */ if (value == NULL) return (IDMAP_SUCCESS); values = ldap_get_values(p->ad, entry, name); if (values == NULL || values[0] == NULL) *value = NULL; else { *value = strdup(values[0]); if (*value == NULL) rc = IDMAP_ERR_MEMORY; } errout: ldap_value_free(values); return (rc); } /* Split winname to its name and domain part */ static idmap_stat split_fqwn(char *fqwn, char **name, char **domain) { char *at; *name = NULL; *domain = NULL; at = strchr(fqwn, '@'); if (at == NULL) { at = strchr(fqwn, '\\'); } if (at == NULL) { /* There is no domain - leave domain NULL */ *name = strdup(fqwn); if (*name == NULL) goto errout; return (IDMAP_SUCCESS); } *domain = strdup(at+1); if (*domain == NULL) goto errout; *name = (char *)malloc(at - fqwn + 1); if (*name == NULL) goto errout; (void) strlcpy(*name, fqwn, at - fqwn + 1); if (*at == '\\') { char *it = *name; *name = *domain; *domain = it; } return (IDMAP_SUCCESS); errout: free(*name); *name = NULL; free(*domain); *domain = NULL; return (IDMAP_ERR_MEMORY); } static idmap_stat unixname2dn(idmap_nm_handle_t *p, char *unixname, int is_user, char **dn, char **winname, char **windomain) { idmap_stat rc = IDMAP_SUCCESS; int rc_ns; char filter[255]; static const char *attribs[3]; ns_ldap_result_t *res; ns_ldap_error_t *errorp = NULL; char **attrs; attribs[0] = p->nldap_winname_attr; attribs[1] = "dn"; attribs[2] = NULL; (void) snprintf(filter, sizeof (filter), is_user ? "uid=%s" : "cn=%s", unixname); rc_ns = __ns_ldap_list(is_user ? "passwd" : "group", filter, NULL, attribs, NULL, 0, &res, &errorp, NULL, NULL); if (rc_ns == NS_LDAP_NOTFOUND) { namemap_log(is_user ? gettext("User %s not found.") : gettext("Group %s not found."), unixname); return (IDMAP_ERR_NOTFOUND); } else if (rc_ns != NS_LDAP_SUCCESS) { char *msg = "Cause unidentified"; if (errorp != NULL) { (void) __ns_ldap_err2str(errorp->status, &msg); } namemap_log(gettext("Ldap list failed (%s)."), msg); return (IDMAP_ERR_ARG); } if (res == NULL) { namemap_log(gettext("User %s not found"), unixname); return (IDMAP_ERR_ARG); } if (winname != NULL && windomain != NULL) { attrs = __ns_ldap_getAttr(&res->entry[0], p->nldap_winname_attr); if (attrs != NULL && attrs[0] != NULL) { rc = split_fqwn(attrs[0], winname, windomain); } else { *winname = *windomain = NULL; } } if (dn != NULL) { attrs = __ns_ldap_getAttr(&res->entry[0], "dn"); if (attrs == NULL || attrs[0] == NULL) { namemap_log(gettext("dn for %s not found"), unixname); return (IDMAP_ERR_ARG); } *dn = strdup(attrs[0]); } return (rc); } #define FILTER "(sAMAccountName=%s)" /* Puts the values of attributes to unixuser and unixgroup, unless NULL */ static idmap_stat winname2dn(idmap_nm_handle_t *p, char *winname, int *is_wuser, char **dn, char **unixuser, char **unixgroup) { idmap_stat rc = IDMAP_SUCCESS; char *base; char *filter; int flen; char *attribs[4]; int i; LDAPMessage *results = NULL; LDAPMessage *entry; int ldap_rc; /* Query: */ base = dns2dn(p->windomain, ""); if (base == NULL) { return (IDMAP_ERR_MEMORY); } i = 0; attribs[i++] = "objectClass"; if (unixuser != NULL) attribs[i++] = p->ad_unixuser_attr; if (unixgroup != NULL) attribs[i++] = p->ad_unixgroup_attr; attribs[i] = NULL; flen = snprintf(NULL, 0, FILTER, winname) + 1; if ((filter = (char *)malloc(flen)) == NULL) { free(base); return (IDMAP_ERR_MEMORY); } (void) snprintf(filter, flen, FILTER, winname); ldap_rc = ldap_search_s(p->ad, base, LDAP_SCOPE_SUBTREE, filter, attribs, 0, &results); free(base); free(filter); if (ldap_rc != LDAP_SUCCESS) { namemap_log( gettext("Ldap query to server %s port %d failed. (%s)"), p->ad_host, p->ad_port, ldap_err2string(ldap_rc)); (void) ldap_msgfree(results); return (IDMAP_ERR_OTHER); } for (entry = ldap_first_entry(p->ad, results), *dn = NULL; entry != NULL; entry = ldap_next_entry(p->ad, entry)) { char **values = NULL; int i = 0; values = ldap_get_values(p->ad, entry, "objectClass"); if (values == NULL) { (void) ldap_msgfree(results); return (IDMAP_ERR_MEMORY); } for (i = 0; i < ldap_count_values(values); i++) { /* * is_wuser can be IDMAP_UNKNOWN, in that case we accept * both User/Group */ if (*is_wuser != IDMAP_NO && strcasecmp(values[i], "User") == 0 || *is_wuser != IDMAP_YES && strcasecmp(values[i], "Group") == 0) { *dn = ldap_get_dn(p->ad, entry); if (*dn == NULL) { ldap_value_free(values); (void) ldap_msgfree(results); return (IDMAP_ERR_MEMORY); } *is_wuser = strcasecmp(values[i], "User") == 0 ? IDMAP_YES : IDMAP_NO; break; } } ldap_value_free(values); if (*dn != NULL) break; } if (*dn == NULL) { namemap_log( *is_wuser == IDMAP_YES ? gettext("User %s@%s not found") : *is_wuser == IDMAP_NO ? gettext("Group %s@%s not found") : gettext("%s@%s not found"), winname, p->windomain); return (IDMAP_ERR_NOTFOUND); } if (unixuser != NULL) rc = extract_attribute(p, entry, p->ad_unixuser_attr, unixuser); if (rc == IDMAP_SUCCESS && unixgroup != NULL) rc = extract_attribute(p, entry, p->ad_unixgroup_attr, unixgroup); (void) ldap_msgfree(results); return (rc); } /* set the given attribute to the given value. If value is NULL, unset it */ static idmap_stat idmap_ad_set(idmap_nm_handle_t *p, char *dn, char *attr, char *value) { idmap_stat rc = IDMAP_SUCCESS; int ldap_rc; char *new_values[2] = {NULL, NULL}; LDAPMod *mods[2] = {NULL, NULL}; mods[0] = (LDAPMod *)calloc(1, sizeof (LDAPMod)); mods[0]->mod_type = strdup(attr); if (value != NULL) { mods[0]->mod_op = LDAP_MOD_REPLACE; new_values[0] = strdup(value); mods[0]->mod_values = new_values; } else { mods[0]->mod_op = LDAP_MOD_DELETE; mods[0]->mod_values = NULL; } ldap_rc = ldap_modify_s(p->ad, dn, mods); if (ldap_rc != LDAP_SUCCESS) { namemap_log( gettext("Ldap modify of %s, attribute %s failed. (%s)"), dn, attr, ldap_err2string(ldap_rc)); rc = IDMAP_ERR_INTERNAL; } ldap_mods_free(mods, 0); return (rc); } /* * This function takes the p argument just for the beauty of the symmetry * with idmap_ad_set (and for future enhancements). */ static idmap_stat /* LINTED E_FUNC_ARG_UNUSED */ idmap_nldap_set(idmap_nm_handle_t *p, ns_cred_t *nsc, char *dn, char *attr, char *value, bool_t is_new, int is_user) { int ldaprc; ns_ldap_error_t *errorp = NULL; ns_ldap_attr_t *attrs[2]; attrs[0] = (ns_ldap_attr_t *)malloc(sizeof (ns_ldap_attr_t)); if (attrs == NULL) return (IDMAP_ERR_MEMORY); attrs[0]->attrname = attr; if (value != NULL) { char **newattr = (char **)calloc(2, sizeof (char *)); if (newattr == NULL) { free(attrs[0]); return (IDMAP_ERR_MEMORY); } newattr[0] = value; newattr[1] = NULL; attrs[0]->attrvalue = newattr; attrs[0]->value_count = 1; } else { attrs[0]->attrvalue = NULL; attrs[0]->value_count = 0; } attrs[1] = NULL; if (value == NULL) { ldaprc = __ns_ldap_delAttr( is_user == IDMAP_YES ? "passwd": "group", dn, (const ns_ldap_attr_t * const *)attrs, nsc, 0, &errorp); } else if (is_new) ldaprc = __ns_ldap_addAttr( is_user == IDMAP_YES ? "passwd": "group", dn, (const ns_ldap_attr_t * const *)attrs, nsc, 0, &errorp); else ldaprc = __ns_ldap_repAttr( is_user == IDMAP_YES ? "passwd": "group", dn, (const ns_ldap_attr_t * const *)attrs, nsc, 0, &errorp); if (ldaprc != NS_LDAP_SUCCESS) { char *msg = "Cause unidentified"; if (errorp != NULL) { (void) __ns_ldap_err2str(errorp->status, &msg); } namemap_log( gettext("__ns_ldap_addAttr/rep/delAttr failed (%s)"), msg); return (IDMAP_ERR_ARG); } return (IDMAP_SUCCESS); } idmap_stat idmap_set_namemap(idmap_nm_handle_t *p, char *winname, char *unixname, int is_user, int is_wuser, int direction) { idmap_stat rc = IDMAP_SUCCESS; char *dn = NULL; char *oldwinname = NULL; char *oldwindomain = NULL; if (direction == IDMAP_DIRECTION_W2U) { if (!p->is_ad) { rc = IDMAP_ERR_ARG; namemap_log( gettext("AD namemaps aren't set up.")); goto cleanup; } rc = winname2dn(p, winname, &is_wuser, &dn, NULL, NULL); if (rc != IDMAP_SUCCESS) goto cleanup; rc = idmap_ad_set(p, dn, is_user ? p->ad_unixuser_attr : p->ad_unixgroup_attr, unixname); if (rc != IDMAP_SUCCESS) goto cleanup; } if (direction == IDMAP_DIRECTION_U2W) { char *fullname; if (!p->is_nldap) { rc = IDMAP_ERR_ARG; namemap_log( gettext("Native ldap namemaps aren't set up.")); goto cleanup; } rc = unixname2dn(p, unixname, is_user, &dn, &oldwinname, &oldwindomain); if (rc != IDMAP_SUCCESS) goto cleanup; if (p->windomain == NULL) { fullname = strdup(winname); if (fullname == NULL) { rc = IDMAP_ERR_MEMORY; goto cleanup; } } else { fullname = malloc(strlen(winname) + strlen(p->windomain) + 2); if (fullname == NULL) { rc = IDMAP_ERR_MEMORY; goto cleanup; } (void) snprintf(fullname, strlen(winname) + strlen(p->windomain) + 2, "%s\\%s", p->windomain, winname); } rc = idmap_nldap_set(p, &p->nsc, dn, p->nldap_winname_attr, fullname, oldwinname == NULL ? TRUE : FALSE, is_user); free(fullname); free(oldwindomain); free(oldwinname); if (rc != IDMAP_SUCCESS) goto cleanup; } cleanup: if (dn != NULL) free(dn); if (oldwindomain != NULL) free(oldwindomain); if (oldwinname != NULL) free(oldwinname); return (rc); } idmap_stat idmap_unset_namemap(idmap_nm_handle_t *p, char *winname, char *unixname, int is_user, int is_wuser, int direction) { idmap_stat rc = IDMAP_SUCCESS; char *dn = NULL; char *oldwinname = NULL; char *oldwindomain = NULL; if (direction == IDMAP_DIRECTION_W2U) { if (!p->is_ad) { rc = IDMAP_ERR_ARG; namemap_log( gettext("AD namemaps aren't set up.")); goto cleanup; } rc = winname2dn(p, winname, &is_wuser, &dn, NULL, NULL); if (rc != IDMAP_SUCCESS) goto cleanup; rc = idmap_ad_set(p, dn, is_user ? p->ad_unixuser_attr : p->ad_unixgroup_attr, unixname); if (rc != IDMAP_SUCCESS) goto cleanup; } else { /* direction == IDMAP_DIRECTION_U2W */ if (!p->is_nldap) { rc = IDMAP_ERR_ARG; namemap_log( gettext("Native ldap namemaps aren't set up.")); goto cleanup; } rc = unixname2dn(p, unixname, is_user, &dn, NULL, NULL); if (rc != IDMAP_SUCCESS) goto cleanup; rc = idmap_nldap_set(p, &p->nsc, dn, p->nldap_winname_attr, NULL, TRUE, is_user); if (rc != IDMAP_SUCCESS) goto cleanup; } cleanup: if (oldwindomain != NULL) free(oldwindomain); if (oldwinname != NULL) free(oldwinname); if (dn != NULL) free(dn); return (rc); } idmap_stat idmap_get_namemap(idmap_nm_handle_t *p, int *is_source_ad, char **winname, char **windomain, int *is_wuser, char **unixuser, char **unixgroup) { idmap_stat rc = IDMAP_SUCCESS; char *dn = NULL; *is_source_ad = IDMAP_UNKNOWN; if (*winname != NULL) { *is_source_ad = IDMAP_YES; if (p->is_ad == FALSE) { rc = IDMAP_ERR_ARG; namemap_log( gettext("AD namemaps are not active.")); goto cleanup; /* In future maybe resolve winname and try nldap? */ } rc = winname2dn(p, *winname, is_wuser, &dn, unixuser, unixgroup); if (rc != IDMAP_SUCCESS) { namemap_log( gettext("Winname %s@%s not found in AD."), *winname, p->windomain); } } else if (*unixuser != NULL || *unixgroup != NULL) { char *unixname; int is_user; *is_source_ad = IDMAP_NO; if (p->is_nldap == FALSE) { rc = IDMAP_ERR_ARG; namemap_log( gettext("Native ldap namemaps aren't active.")); goto cleanup; /* In future maybe resolve unixname and try AD? */ } if (*unixuser != NULL) { is_user = IDMAP_YES; unixname = *unixuser; } else if (*unixgroup != NULL) { is_user = IDMAP_NO; unixname = *unixgroup; } rc = unixname2dn(p, unixname, is_user, NULL, winname, windomain); if (rc != IDMAP_SUCCESS) { namemap_log( gettext("%s %s not found in native ldap."), is_user == IDMAP_YES ? "UNIX user" : "UNIX group", unixname); goto cleanup; } } else { rc = IDMAP_ERR_ARG; goto cleanup; } cleanup: return (rc); }