xref: /illumos-gate/usr/src/cmd/idmap/idmap/namemaps.c (revision ef826847)
1479ac375Sdm /*
2479ac375Sdm  * CDDL HEADER START
3479ac375Sdm  *
4479ac375Sdm  * The contents of this file are subject to the terms of the
5479ac375Sdm  * Common Development and Distribution License (the "License").
6479ac375Sdm  * You may not use this file except in compliance with the License.
7479ac375Sdm  *
8479ac375Sdm  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9479ac375Sdm  * or http://www.opensolaris.org/os/licensing.
10479ac375Sdm  * See the License for the specific language governing permissions
11479ac375Sdm  * and limitations under the License.
12479ac375Sdm  *
13479ac375Sdm  * When distributing Covered Code, include this CDDL HEADER in each
14479ac375Sdm  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15479ac375Sdm  * If applicable, add the following below this CDDL HEADER, with the
16479ac375Sdm  * fields enclosed by brackets "[]" replaced with your own identifying
17479ac375Sdm  * information: Portions Copyright [yyyy] [name of copyright owner]
18479ac375Sdm  *
19479ac375Sdm  * CDDL HEADER END
20479ac375Sdm  */
21479ac375Sdm /*
22c5866007SKeyur Desai  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23b3700b07SGordon Ross  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
24479ac375Sdm  */
25479ac375Sdm 
26479ac375Sdm 
27479ac375Sdm #include <errno.h>
28479ac375Sdm #include <ldap.h>
29479ac375Sdm #include <sasl/sasl.h>
30479ac375Sdm #include <libintl.h>
31479ac375Sdm #include <strings.h>
327a8a68f5SJulian Pullen #include <syslog.h>
33c5866007SKeyur Desai #include <stdarg.h>
34479ac375Sdm 
357a8a68f5SJulian Pullen #include "addisc.h"
367a8a68f5SJulian Pullen #include "libadutils.h"
37c5866007SKeyur Desai #include "idmap_priv.h"
38479ac375Sdm #include "ns_sldap.h"
39c5866007SKeyur Desai #include "namemaps.h"
40479ac375Sdm 
41479ac375Sdm /* From adutils.c: */
42479ac375Sdm 
43479ac375Sdm /* A single DS */
4461b364a9Sjp struct idmap_nm_handle {
45479ac375Sdm 	LDAP			*ad;		/* LDAP connection */
46479ac375Sdm 	/* LDAP DS info */
47479ac375Sdm 	char			*ad_host;
48479ac375Sdm 	int			ad_port;
49479ac375Sdm 
50479ac375Sdm 	/* hardwired to SASL GSSAPI only for now */
51479ac375Sdm 	char			*saslmech;
52479ac375Sdm 	unsigned		saslflags;
53479ac375Sdm 	char			*windomain;
54479ac375Sdm 	char			*ad_unixuser_attr;
55479ac375Sdm 	char			*ad_unixgroup_attr;
56479ac375Sdm 	char			*nldap_winname_attr;
57479ac375Sdm 	char			*default_domain;
58479ac375Sdm 	bool_t			is_nldap;
59479ac375Sdm 	bool_t			is_ad;
6061b364a9Sjp 	int			direction;
6161b364a9Sjp 	ns_cred_t		nsc;
6261b364a9Sjp };
63479ac375Sdm 
64c5866007SKeyur Desai /* PRINTFLIKE1 */
65c5866007SKeyur Desai static
66c5866007SKeyur Desai void
namemap_log(char * fmt,...)67c5866007SKeyur Desai namemap_log(char *fmt, ...)
68c5866007SKeyur Desai {
69c5866007SKeyur Desai 	va_list va;
70c5866007SKeyur Desai 
71c5866007SKeyur Desai 	va_start(va, fmt);
72c5866007SKeyur Desai 	(void) vfprintf(stderr, fmt, va);
73c5866007SKeyur Desai 	va_end(va);
74c5866007SKeyur Desai 	(void) fprintf(stderr, "\n");
75c5866007SKeyur Desai }
76c5866007SKeyur Desai 
77479ac375Sdm static
78479ac375Sdm idmap_stat
string2auth(const char * from,ns_auth_t * na)79479ac375Sdm string2auth(const char *from, ns_auth_t *na)
80479ac375Sdm {
81479ac375Sdm 	if (from == NULL) {
82479ac375Sdm 		na->type = NS_LDAP_AUTH_SASL;
83479ac375Sdm 		na->tlstype = NS_LDAP_TLS_SASL;
84479ac375Sdm 		na->saslmech = NS_LDAP_SASL_GSSAPI;
85479ac375Sdm 		na->saslopt = NS_LDAP_SASLOPT_PRIV |
86479ac375Sdm 		    NS_LDAP_SASLOPT_INT;
87479ac375Sdm 		return (IDMAP_SUCCESS);
88479ac375Sdm 	}
89479ac375Sdm 
90479ac375Sdm 	if (strcasecmp(from, "simple") == 0) {
91479ac375Sdm 		na->type = NS_LDAP_AUTH_SIMPLE;
92479ac375Sdm 		na->tlstype = NS_LDAP_TLS_NONE;
93479ac375Sdm 		na->saslmech = NS_LDAP_SASL_NONE;
94479ac375Sdm 		na->saslopt = NS_LDAP_SASLOPT_NONE;
95479ac375Sdm 	} else if (strcasecmp(from, "sasl/CRAM-MD5") == 0) {
96479ac375Sdm 		na->type = NS_LDAP_AUTH_SASL;
97479ac375Sdm 		na->tlstype = NS_LDAP_TLS_SASL;
98479ac375Sdm 		na->saslmech = NS_LDAP_SASL_CRAM_MD5;
99479ac375Sdm 		na->saslopt = NS_LDAP_SASLOPT_NONE;
100479ac375Sdm 	} else if (strcasecmp(from, "sasl/DIGEST-MD5") == 0) {
101479ac375Sdm 		na->type = NS_LDAP_AUTH_SASL;
102479ac375Sdm 		na->tlstype = NS_LDAP_TLS_SASL;
103479ac375Sdm 		na->saslmech = NS_LDAP_SASL_DIGEST_MD5;
104479ac375Sdm 		na->saslopt = NS_LDAP_SASLOPT_NONE;
105479ac375Sdm 	} else if (strcasecmp(from, "sasl/GSSAPI") == 0) {
106479ac375Sdm 		na->type = NS_LDAP_AUTH_SASL;
107479ac375Sdm 		na->tlstype = NS_LDAP_TLS_SASL;
108479ac375Sdm 		na->saslmech = NS_LDAP_SASL_GSSAPI;
109479ac375Sdm 		na->saslopt = NS_LDAP_SASLOPT_PRIV |
110479ac375Sdm 		    NS_LDAP_SASLOPT_INT;
111479ac375Sdm 	} else if (strcasecmp(from, "tls:simple") == 0) {
112479ac375Sdm 		na->type = NS_LDAP_AUTH_TLS;
113479ac375Sdm 		na->tlstype = NS_LDAP_TLS_SIMPLE;
114479ac375Sdm 		na->saslmech = NS_LDAP_SASL_NONE;
115479ac375Sdm 		na->saslopt = NS_LDAP_SASLOPT_NONE;
116479ac375Sdm 	} else if (strcasecmp(from, "tls:sasl/CRAM-MD5") == 0) {
117479ac375Sdm 		na->type = NS_LDAP_AUTH_TLS;
118479ac375Sdm 		na->tlstype = NS_LDAP_TLS_SASL;
119479ac375Sdm 		na->saslmech = NS_LDAP_SASL_CRAM_MD5;
120479ac375Sdm 		na->saslopt = NS_LDAP_SASLOPT_NONE;
121479ac375Sdm 	} else if (strcasecmp(from, "tls:sasl/DIGEST-MD5") == 0) {
122479ac375Sdm 		na->type = NS_LDAP_AUTH_TLS;
123479ac375Sdm 		na->tlstype = NS_LDAP_TLS_SASL;
124479ac375Sdm 		na->saslmech = NS_LDAP_SASL_DIGEST_MD5;
125479ac375Sdm 		na->saslopt = NS_LDAP_SASLOPT_NONE;
126479ac375Sdm 	} else {
127c5866007SKeyur Desai 		namemap_log(
128479ac375Sdm 		    gettext("Invalid authentication method \"%s\" specified\n"),
129479ac375Sdm 		    from);
130479ac375Sdm 		return (IDMAP_ERR_ARG);
131479ac375Sdm 	}
132479ac375Sdm 
133479ac375Sdm 	return (IDMAP_SUCCESS);
134479ac375Sdm }
135479ac375Sdm 
136479ac375Sdm 
137479ac375Sdm 
138479ac375Sdm static
139479ac375Sdm idmap_stat
strings2cred(ns_cred_t * nsc,char * user,char * passwd,char * auth)140479ac375Sdm strings2cred(ns_cred_t *nsc, char *user, char *passwd, char *auth)
141479ac375Sdm {
142479ac375Sdm 	idmap_stat rc;
143479ac375Sdm 	(void) memset(nsc, 0, sizeof (ns_cred_t));
144479ac375Sdm 
145479ac375Sdm 	if ((rc = string2auth(auth, &nsc->auth)) != IDMAP_SUCCESS)
146479ac375Sdm 		return (rc);
147479ac375Sdm 
14861b364a9Sjp 	if (user != NULL) {
14961b364a9Sjp 		nsc->cred.unix_cred.userID = strdup(user);
15061b364a9Sjp 		if (nsc->cred.unix_cred.userID == NULL)
15161b364a9Sjp 			return (IDMAP_ERR_MEMORY);
15261b364a9Sjp 	}
15361b364a9Sjp 
15461b364a9Sjp 	if (passwd != NULL) {
15561b364a9Sjp 		nsc->cred.unix_cred.passwd = strdup(passwd);
15661b364a9Sjp 		if (nsc->cred.unix_cred.passwd == NULL) {
15761b364a9Sjp 			free(nsc->cred.unix_cred.userID);
15861b364a9Sjp 			return (IDMAP_ERR_MEMORY);
15961b364a9Sjp 		}
16061b364a9Sjp 	}
161479ac375Sdm 
162479ac375Sdm 	return (IDMAP_SUCCESS);
163479ac375Sdm }
164479ac375Sdm 
165479ac375Sdm 
166479ac375Sdm 
167479ac375Sdm 
168479ac375Sdm 
169479ac375Sdm /*ARGSUSED*/
170479ac375Sdm static int
idmap_saslcallback(LDAP * ld,unsigned flags,void * defaults,void * prompts)171479ac375Sdm idmap_saslcallback(LDAP *ld, unsigned flags, void *defaults, void *prompts)
172479ac375Sdm {
173479ac375Sdm 	sasl_interact_t	*interact;
174479ac375Sdm 
175479ac375Sdm 	if (prompts == NULL || flags != LDAP_SASL_INTERACTIVE)
176479ac375Sdm 		return (LDAP_PARAM_ERROR);
177479ac375Sdm 
178479ac375Sdm 	/* There should be no extra arguemnts for SASL/GSSAPI authentication */
179479ac375Sdm 	for (interact = prompts; interact->id != SASL_CB_LIST_END;
180479ac375Sdm 	    interact++) {
181479ac375Sdm 		interact->result = NULL;
182479ac375Sdm 		interact->len = 0;
183479ac375Sdm 	}
184479ac375Sdm 	return (LDAP_SUCCESS);
185479ac375Sdm }
186479ac375Sdm 
187479ac375Sdm static
188479ac375Sdm idmap_stat
idmap_open_ad_conn(idmap_nm_handle_t * adh)18961b364a9Sjp idmap_open_ad_conn(idmap_nm_handle_t *adh)
190479ac375Sdm {
191479ac375Sdm 	int zero = 0;
192479ac375Sdm 	int timeoutms = 30 * 1000;
193479ac375Sdm 	int ldversion, ldap_rc;
194479ac375Sdm 	idmap_stat rc = IDMAP_SUCCESS;
195479ac375Sdm 
196479ac375Sdm 	/* Open and bind an LDAP connection */
197479ac375Sdm 	adh->ad = ldap_init(adh->ad_host, adh->ad_port);
198479ac375Sdm 	if (adh->ad == NULL) {
199c5866007SKeyur Desai 		namemap_log(
200c5866007SKeyur Desai 		    gettext("ldap_init() to server %s port %d failed. (%s)"),
201c5866007SKeyur Desai 		    CHECK_NULL(adh->ad_host),
202479ac375Sdm 		    adh->ad_port, strerror(errno));
203479ac375Sdm 		rc = IDMAP_ERR_INTERNAL;
204479ac375Sdm 		goto out;
205479ac375Sdm 	}
206479ac375Sdm 	ldversion = LDAP_VERSION3;
207479ac375Sdm 	(void) ldap_set_option(adh->ad, LDAP_OPT_PROTOCOL_VERSION, &ldversion);
208479ac375Sdm 	(void) ldap_set_option(adh->ad, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
209479ac375Sdm 	(void) ldap_set_option(adh->ad, LDAP_OPT_TIMELIMIT, &zero);
210479ac375Sdm 	(void) ldap_set_option(adh->ad, LDAP_OPT_SIZELIMIT, &zero);
211479ac375Sdm 	(void) ldap_set_option(adh->ad, LDAP_X_OPT_CONNECT_TIMEOUT, &timeoutms);
212479ac375Sdm 	(void) ldap_set_option(adh->ad, LDAP_OPT_RESTART, LDAP_OPT_ON);
213479ac375Sdm 	ldap_rc = ldap_sasl_interactive_bind_s(adh->ad, "" /* binddn */,
214479ac375Sdm 	    adh->saslmech, NULL, NULL, adh->saslflags, &idmap_saslcallback,
215479ac375Sdm 	    NULL);
216479ac375Sdm 
217479ac375Sdm 	if (ldap_rc != LDAP_SUCCESS) {
218479ac375Sdm 		(void) ldap_unbind(adh->ad);
219479ac375Sdm 		adh->ad = NULL;
220c5866007SKeyur Desai 		namemap_log(
221c5866007SKeyur Desai 		    gettext("ldap_sasl_interactive_bind_s() to server "
222c5866007SKeyur Desai 		    "%s port %d failed. (%s)"), CHECK_NULL(adh->ad_host),
22361b364a9Sjp 		    adh->ad_port, ldap_err2string(ldap_rc));
224479ac375Sdm 		rc = IDMAP_ERR_INTERNAL;
225479ac375Sdm 	}
226479ac375Sdm 
227479ac375Sdm out:
228479ac375Sdm 	return (rc);
229479ac375Sdm }
230479ac375Sdm 
231479ac375Sdm static
232479ac375Sdm idmap_stat
idmap_init_nldap(idmap_nm_handle_t * p)23361b364a9Sjp idmap_init_nldap(idmap_nm_handle_t *p)
234479ac375Sdm {
23561b364a9Sjp /*
23661b364a9Sjp  * For now, there is nothing to initialize in nldap. This is just to
23761b364a9Sjp  * make it future-proof, especially standalone libsldap-proof
23861b364a9Sjp  */
23961b364a9Sjp 	p->is_nldap = TRUE;
24061b364a9Sjp 	return (0);
241479ac375Sdm }
242479ac375Sdm 
243479ac375Sdm static
244479ac375Sdm idmap_stat
idmap_init_ad(idmap_nm_handle_t * p)24561b364a9Sjp idmap_init_ad(idmap_nm_handle_t *p)
246479ac375Sdm {
247479ac375Sdm 	idmap_stat	rc = IDMAP_SUCCESS;
248b3700b07SGordon Ross 	ad_disc_ds_t	*dc = NULL;
249479ac375Sdm 	ad_disc_t	ad_ctx;
250479ac375Sdm 
251479ac375Sdm 	ad_ctx = ad_disc_init();
252479ac375Sdm 	if (ad_ctx == NULL) {
253c5866007SKeyur Desai 		namemap_log(
254479ac375Sdm 		    gettext("AD autodiscovery initialization failed"));
255479ac375Sdm 		return (IDMAP_ERR_INTERNAL);
256479ac375Sdm 	}
257479ac375Sdm 	ad_disc_refresh(ad_ctx);
258479ac375Sdm 
259479ac375Sdm 
260479ac375Sdm 	/* Based on the supplied or default domain, find the proper AD: */
26161b364a9Sjp 	if (ad_disc_set_DomainName(ad_ctx, p->windomain)) {
262479ac375Sdm 		rc = IDMAP_ERR_INTERNAL;
263c5866007SKeyur Desai 		namemap_log(
264479ac375Sdm 		    gettext("Setting a domain name \"%s\" for autodiscovery"
26561b364a9Sjp 		    " failed, most likely not enough memory"), p->windomain);
266479ac375Sdm 		goto cleanup;
267479ac375Sdm 	}
268479ac375Sdm 
2694d61c878SJulian Pullen 	dc = ad_disc_get_DomainController(ad_ctx, AD_DISC_GLOBAL, NULL);
270479ac375Sdm 	if (dc == NULL) {
271479ac375Sdm 		rc = IDMAP_ERR_ARG;
272c5866007SKeyur Desai 		namemap_log(
273479ac375Sdm 		    gettext("A domain controller for the "
27461b364a9Sjp 		    "domain \"%s\" not found."), p->windomain);
275479ac375Sdm 		goto cleanup;
276479ac375Sdm 	}
277479ac375Sdm 
278479ac375Sdm 
279479ac375Sdm 	p->ad_port = dc->port;
280479ac375Sdm 	p->ad_host = strdup(dc->host);
281479ac375Sdm 
282479ac375Sdm 	if (p->ad_host == NULL) {
283479ac375Sdm 		rc = IDMAP_ERR_MEMORY;
284479ac375Sdm 		goto cleanup;
285479ac375Sdm 	}
286479ac375Sdm 
287479ac375Sdm 	p->saslflags = LDAP_SASL_INTERACTIVE;
288479ac375Sdm 	p->saslmech = strdup("GSSAPI");
289479ac375Sdm 
290479ac375Sdm 	if (p->saslmech == NULL) {
291479ac375Sdm 		rc = IDMAP_ERR_MEMORY;
292479ac375Sdm 		goto cleanup;
293479ac375Sdm 	}
294479ac375Sdm 
295479ac375Sdm 	rc = idmap_open_ad_conn(p);
296479ac375Sdm 
297479ac375Sdm 	if (rc != IDMAP_SUCCESS)
298479ac375Sdm 		goto cleanup;
299479ac375Sdm 
30061b364a9Sjp 	p->is_ad = TRUE;
301479ac375Sdm 
302479ac375Sdm cleanup:
303479ac375Sdm 	ad_disc_fini(ad_ctx);
304479ac375Sdm 	free(dc);
305479ac375Sdm 	return (rc);
306479ac375Sdm }
307479ac375Sdm 
30861b364a9Sjp void
idmap_fini_namemaps(idmap_nm_handle_t * p)30961b364a9Sjp idmap_fini_namemaps(idmap_nm_handle_t *p)
310479ac375Sdm {
31161b364a9Sjp 	if (p == NULL)
31261b364a9Sjp 		return;
313479ac375Sdm 
31461b364a9Sjp 	if (p->ad_unixgroup_attr != NULL)
31561b364a9Sjp 		free(p->ad_unixgroup_attr);
316479ac375Sdm 
31761b364a9Sjp 	if (p->ad_unixuser_attr != NULL)
31861b364a9Sjp 		free(p->ad_unixuser_attr);
31961b364a9Sjp 
32061b364a9Sjp 	if (p->nldap_winname_attr)
32161b364a9Sjp 		free(p->nldap_winname_attr);
32261b364a9Sjp 
32361b364a9Sjp 	if (p->windomain != NULL)
32461b364a9Sjp 		free(p->windomain);
32561b364a9Sjp 
32661b364a9Sjp 	if (p->default_domain != NULL)
32761b364a9Sjp 		free(p->default_domain);
32861b364a9Sjp 
32961b364a9Sjp 	if (p->saslmech != NULL)
33061b364a9Sjp 		free(p->saslmech);
33161b364a9Sjp 
33261b364a9Sjp 	if (p->ad_host != NULL)
33361b364a9Sjp 		free(p->ad_host);
33461b364a9Sjp 
33561b364a9Sjp 	if (p->nsc.cred.unix_cred.userID != NULL) {
33661b364a9Sjp 		free(p->nsc.cred.unix_cred.userID);
337479ac375Sdm 	}
338479ac375Sdm 
33961b364a9Sjp 	if (p->nsc.cred.unix_cred.passwd != NULL) {
34061b364a9Sjp 		/* No archeology: */
34161b364a9Sjp 		(void) memset(p->nsc.cred.unix_cred.passwd, 0,
34261b364a9Sjp 		    strlen(p->nsc.cred.unix_cred.passwd));
34361b364a9Sjp 		free(p->nsc.cred.unix_cred.passwd);
34461b364a9Sjp 	}
345479ac375Sdm 
346479ac375Sdm 	if (p->ad)
347479ac375Sdm 		(void) ldap_unbind(p->ad);
348479ac375Sdm 	free(p);
349479ac375Sdm 
350479ac375Sdm }
351479ac375Sdm 
352479ac375Sdm 
35361b364a9Sjp 
35461b364a9Sjp idmap_stat
idmap_init_namemaps(idmap_nm_handle_t ** adh,char * user,char * passwd,char * auth,char * windomain,int direction)3551fdeec65Sjoyce mcintosh idmap_init_namemaps(idmap_nm_handle_t **adh,
35661b364a9Sjp     char *user, char *passwd, char *auth, char *windomain,
35761b364a9Sjp     int direction)
35861b364a9Sjp {
35961b364a9Sjp 	idmap_stat rc;
36061b364a9Sjp 	idmap_nm_handle_t *p;
36161b364a9Sjp 
36261b364a9Sjp 	p = (idmap_nm_handle_t *)calloc(1, sizeof (idmap_nm_handle_t));
36361b364a9Sjp 	if (p == NULL)
36461b364a9Sjp 		return (IDMAP_ERR_MEMORY);
36561b364a9Sjp 
3661fdeec65Sjoyce mcintosh 	rc = idmap_get_prop_str(PROP_DEFAULT_DOMAIN,
36761b364a9Sjp 	    &p->default_domain);
36861b364a9Sjp 	if (rc != IDMAP_SUCCESS) {
369c5866007SKeyur Desai 		namemap_log(
37061b364a9Sjp 		    gettext("Error obtaining default domain from idmapd (%s)"),
3711fdeec65Sjoyce mcintosh 		    idmap_stat2string(rc));
37261b364a9Sjp 		goto cleanup;
37361b364a9Sjp 	}
37461b364a9Sjp 
3751fdeec65Sjoyce mcintosh 	rc = idmap_get_prop_str(PROP_AD_UNIXUSER_ATTR,
37661b364a9Sjp 	    &p->ad_unixuser_attr);
37761b364a9Sjp 	if (rc != IDMAP_SUCCESS) {
378c5866007SKeyur Desai 		namemap_log(
37961b364a9Sjp 		    gettext("Error obtaining AD unixuser attribute (%s)"),
3801fdeec65Sjoyce mcintosh 		    idmap_stat2string(rc));
38161b364a9Sjp 		goto cleanup;
38261b364a9Sjp 	}
38361b364a9Sjp 
3841fdeec65Sjoyce mcintosh 	rc = idmap_get_prop_str(PROP_AD_UNIXGROUP_ATTR,
38561b364a9Sjp 	    &p->ad_unixgroup_attr);
38661b364a9Sjp 	if (rc != IDMAP_SUCCESS) {
387c5866007SKeyur Desai 		namemap_log(
38861b364a9Sjp 		    gettext("Error obtaining AD unixgroup attribute (%s)"),
3891fdeec65Sjoyce mcintosh 		    idmap_stat2string(rc));
39061b364a9Sjp 		goto cleanup;
39161b364a9Sjp 	}
39261b364a9Sjp 
39361b364a9Sjp 
3941fdeec65Sjoyce mcintosh 	rc = idmap_get_prop_str(PROP_NLDAP_WINNAME_ATTR,
39561b364a9Sjp 	    &p->nldap_winname_attr);
39661b364a9Sjp 	if (rc != IDMAP_SUCCESS) {
397c5866007SKeyur Desai 		namemap_log(
39861b364a9Sjp 		    gettext("Error obtaining AD unixgroup attribute (%s)"),
3991fdeec65Sjoyce mcintosh 		    idmap_stat2string(rc));
40061b364a9Sjp 		goto cleanup;
40161b364a9Sjp 	}
40261b364a9Sjp 
40361b364a9Sjp 	if (windomain != NULL) {
40461b364a9Sjp 		p->windomain = strdup(windomain);
40561b364a9Sjp 		if (p->windomain == NULL) {
40661b364a9Sjp 			rc = IDMAP_ERR_MEMORY;
40761b364a9Sjp 			goto cleanup;
40861b364a9Sjp 		}
40961b364a9Sjp 	} else if (!EMPTY_STRING(p->default_domain)) {
41061b364a9Sjp 		p->windomain = strdup(p->default_domain);
41161b364a9Sjp 		if (p->windomain == NULL) {
41261b364a9Sjp 			rc = IDMAP_ERR_MEMORY;
41361b364a9Sjp 			goto cleanup;
41461b364a9Sjp 		}
41561b364a9Sjp 	} else if (direction == IDMAP_DIRECTION_W2U) {
416c5866007SKeyur Desai 		namemap_log(
41761b364a9Sjp 		    gettext("Windows domain not given and idmapd daemon"
41861b364a9Sjp 		    " didn't provide a default one"));
41961b364a9Sjp 		rc = IDMAP_ERR_ARG;
42061b364a9Sjp 		goto cleanup;
42161b364a9Sjp 	}
42261b364a9Sjp 
42361b364a9Sjp 	p->direction = direction;
42461b364a9Sjp 
42561b364a9Sjp 	if ((p->ad_unixuser_attr != NULL || p->ad_unixgroup_attr != NULL) &&
42661b364a9Sjp 	    direction != IDMAP_DIRECTION_U2W) {
42761b364a9Sjp 		rc = idmap_init_ad(p);
42861b364a9Sjp 		if (rc != IDMAP_SUCCESS) {
42961b364a9Sjp 			goto cleanup;
43061b364a9Sjp 		}
43161b364a9Sjp 	}
43261b364a9Sjp 
43361b364a9Sjp 	if (p->nldap_winname_attr != NULL && direction != IDMAP_DIRECTION_W2U) {
43461b364a9Sjp 		rc = idmap_init_nldap(p);
43561b364a9Sjp 		if (rc != IDMAP_SUCCESS) {
43661b364a9Sjp 			goto cleanup;
43761b364a9Sjp 		}
43861b364a9Sjp 
43961b364a9Sjp 		rc = strings2cred(&p->nsc, user, passwd, auth);
44061b364a9Sjp 		if (rc != IDMAP_SUCCESS) {
44161b364a9Sjp 			goto cleanup;
44261b364a9Sjp 		}
44361b364a9Sjp 	}
44461b364a9Sjp 
44561b364a9Sjp cleanup:
44661b364a9Sjp 
44761b364a9Sjp 	if (rc == IDMAP_SUCCESS) {
44861b364a9Sjp 		*adh = p;
44961b364a9Sjp 		return (IDMAP_SUCCESS);
45061b364a9Sjp 	}
45161b364a9Sjp 
45261b364a9Sjp 	/* There was an error: */
45361b364a9Sjp 	idmap_fini_namemaps(*adh);
45461b364a9Sjp 	return (rc);
45561b364a9Sjp }
45661b364a9Sjp 
457479ac375Sdm static
458479ac375Sdm char *
dns2dn(const char * dns,const char * prefix)459479ac375Sdm dns2dn(const char *dns, const char *prefix)
460479ac375Sdm {
461479ac375Sdm 	int num_lvl = 1;
462479ac375Sdm 	char *buf;
463479ac375Sdm 	const char *it, *new_it;
464479ac375Sdm 
465479ac375Sdm 	for (it = dns; it != NULL; it = strchr(it, '.')) {
466479ac375Sdm 		it ++;
467479ac375Sdm 		num_lvl ++;
468479ac375Sdm 	}
469479ac375Sdm 
470479ac375Sdm 	buf = (char *)malloc(strlen(prefix) + strlen(dns) + 4 * num_lvl);
471479ac375Sdm 	(void) strcpy(buf, prefix);
472479ac375Sdm 
473479ac375Sdm 
474479ac375Sdm 	it = dns;
475479ac375Sdm 	for (;;) {
476479ac375Sdm 		new_it = strchr(it, '.');
477479ac375Sdm 		(void) strcat(buf, "DC=");
478479ac375Sdm 		if (new_it == NULL) {
479479ac375Sdm 			(void) strcat(buf, it);
480479ac375Sdm 			break;
481479ac375Sdm 		} else {
482479ac375Sdm 			(void) strncat(buf, it, new_it - it);
483479ac375Sdm 			(void) strcat(buf, ",");
484479ac375Sdm 		}
485479ac375Sdm 
486479ac375Sdm 		it = new_it + 1;
487479ac375Sdm 	}
488479ac375Sdm 
489479ac375Sdm 	return (buf);
490479ac375Sdm }
491479ac375Sdm 
492479ac375Sdm 
493479ac375Sdm static
494479ac375Sdm idmap_stat
extract_attribute(idmap_nm_handle_t * p,LDAPMessage * entry,char * name,char ** value)49561b364a9Sjp extract_attribute(idmap_nm_handle_t *p, LDAPMessage *entry, char *name,
49661b364a9Sjp     char **value)
497479ac375Sdm {
498479ac375Sdm 	char	**values = NULL;
499479ac375Sdm 	idmap_stat rc = IDMAP_SUCCESS;
500479ac375Sdm 	/* No value means it is not requested */
501479ac375Sdm 	if (value == NULL)
502479ac375Sdm 		return (IDMAP_SUCCESS);
503479ac375Sdm 
504479ac375Sdm 	values = ldap_get_values(p->ad, entry, name);
505479ac375Sdm 	if (values == NULL || values[0] == NULL)
506479ac375Sdm 		*value = NULL;
507479ac375Sdm 	else {
508479ac375Sdm 		*value = strdup(values[0]);
509479ac375Sdm 		if (*value == NULL)
510479ac375Sdm 			rc = IDMAP_ERR_MEMORY;
511479ac375Sdm 	}
512479ac375Sdm errout:
513479ac375Sdm 	ldap_value_free(values);
514479ac375Sdm 	return (rc);
515479ac375Sdm }
516479ac375Sdm 
517479ac375Sdm 
518479ac375Sdm /* Split winname to its name and domain part */
519479ac375Sdm static
520479ac375Sdm idmap_stat
split_fqwn(char * fqwn,char ** name,char ** domain)521479ac375Sdm split_fqwn(char *fqwn, char **name, char **domain)
522479ac375Sdm {
523479ac375Sdm 	char *at;
524479ac375Sdm 
525479ac375Sdm 	*name = NULL;
526479ac375Sdm 	*domain = NULL;
527479ac375Sdm 
528479ac375Sdm 	at = strchr(fqwn, '@');
529479ac375Sdm 	if (at == NULL) {
530479ac375Sdm 		at = strchr(fqwn, '\\');
531479ac375Sdm 	}
532479ac375Sdm 	if (at == NULL) {
533479ac375Sdm 	/* There is no domain - leave domain NULL */
534479ac375Sdm 		*name = strdup(fqwn);
535479ac375Sdm 		if (*name == NULL)
536479ac375Sdm 			goto errout;
537479ac375Sdm 		return (IDMAP_SUCCESS);
538479ac375Sdm 	}
539479ac375Sdm 
540479ac375Sdm 
541479ac375Sdm 	*domain = strdup(at+1);
542479ac375Sdm 	if (*domain == NULL)
543479ac375Sdm 		goto errout;
544479ac375Sdm 	*name = (char *)malloc(at - fqwn + 1);
545479ac375Sdm 	if (*name == NULL)
546479ac375Sdm 		goto errout;
547479ac375Sdm 	(void) strlcpy(*name, fqwn, at - fqwn + 1);
548479ac375Sdm 
549479ac375Sdm 	if (*at == '\\') {
550479ac375Sdm 		char *it = *name;
551479ac375Sdm 		*name = *domain;
552479ac375Sdm 		*domain = it;
553479ac375Sdm 	}
554479ac375Sdm 
555479ac375Sdm 	return (IDMAP_SUCCESS);
556479ac375Sdm 
557479ac375Sdm 
558479ac375Sdm errout:
559479ac375Sdm 	free(*name);
560479ac375Sdm 	*name = NULL;
561479ac375Sdm 	free(*domain);
562479ac375Sdm 	*domain = NULL;
563479ac375Sdm 	return (IDMAP_ERR_MEMORY);
564479ac375Sdm }
565479ac375Sdm 
566479ac375Sdm static
567479ac375Sdm idmap_stat
unixname2dn(idmap_nm_handle_t * p,char * unixname,int is_user,char ** dn,char ** winname,char ** windomain)56861b364a9Sjp unixname2dn(idmap_nm_handle_t *p, char *unixname, int is_user, char **dn,
569479ac375Sdm     char **winname, char **windomain)
570479ac375Sdm {
571479ac375Sdm 	idmap_stat rc = IDMAP_SUCCESS;
572479ac375Sdm 	int rc_ns;
573479ac375Sdm 
574479ac375Sdm 
575479ac375Sdm 	char filter[255];
576479ac375Sdm 	static const char *attribs[3];
577479ac375Sdm 	ns_ldap_result_t *res;
578479ac375Sdm 	ns_ldap_error_t *errorp = NULL;
579479ac375Sdm 	char **attrs;
580479ac375Sdm 
581479ac375Sdm 
582479ac375Sdm 	attribs[0] = p->nldap_winname_attr;
583479ac375Sdm 	attribs[1] = "dn";
584479ac375Sdm 	attribs[2] = NULL;
585479ac375Sdm 
586479ac375Sdm 	(void) snprintf(filter, sizeof (filter), is_user ? "uid=%s" : "cn=%s",
587479ac375Sdm 	    unixname);
588479ac375Sdm 
589479ac375Sdm 	rc_ns = __ns_ldap_list(is_user ? "passwd" : "group",
590479ac375Sdm 	    filter, NULL, attribs, NULL, 0, &res, &errorp, NULL, NULL);
591479ac375Sdm 
592479ac375Sdm 
593479ac375Sdm 	if (rc_ns == NS_LDAP_NOTFOUND) {
594c5866007SKeyur Desai 		namemap_log(is_user ? gettext("User %s not found.")
595479ac375Sdm 		    : gettext("Group %s not found."),  unixname);
596479ac375Sdm 		return (IDMAP_ERR_NOTFOUND);
597479ac375Sdm 	} else if (rc_ns != NS_LDAP_SUCCESS) {
598479ac375Sdm 		char *msg = "Cause unidentified";
599479ac375Sdm 		if (errorp != NULL) {
600479ac375Sdm 			(void) __ns_ldap_err2str(errorp->status, &msg);
601479ac375Sdm 		}
602c5866007SKeyur Desai 		namemap_log(gettext("Ldap list failed (%s)."), msg);
603479ac375Sdm 		return (IDMAP_ERR_ARG);
604479ac375Sdm 	}
605479ac375Sdm 
606479ac375Sdm 	if (res == NULL) {
607c5866007SKeyur Desai 		namemap_log(gettext("User %s not found"), unixname);
608479ac375Sdm 		return (IDMAP_ERR_ARG);
609479ac375Sdm 	}
610479ac375Sdm 
611479ac375Sdm 	if (winname != NULL && windomain != NULL) {
612479ac375Sdm 		attrs = __ns_ldap_getAttr(&res->entry[0],
613479ac375Sdm 		    p->nldap_winname_attr);
614479ac375Sdm 		if (attrs != NULL && attrs[0] != NULL) {
615479ac375Sdm 			rc = split_fqwn(attrs[0], winname, windomain);
616479ac375Sdm 		} else {
617479ac375Sdm 			*winname = *windomain = NULL;
618479ac375Sdm 		}
619479ac375Sdm 	}
620479ac375Sdm 
621479ac375Sdm 	if (dn != NULL) {
622479ac375Sdm 		attrs = __ns_ldap_getAttr(&res->entry[0], "dn");
623479ac375Sdm 		if (attrs == NULL || attrs[0] == NULL) {
624c5866007SKeyur Desai 			namemap_log(gettext("dn for %s not found"),
625479ac375Sdm 			    unixname);
626479ac375Sdm 			return (IDMAP_ERR_ARG);
627479ac375Sdm 		}
628479ac375Sdm 		*dn = strdup(attrs[0]);
629479ac375Sdm 	}
630479ac375Sdm 
631479ac375Sdm 
632479ac375Sdm 	return (rc);
633479ac375Sdm 
634479ac375Sdm }
635479ac375Sdm 
636479ac375Sdm #define	FILTER	"(sAMAccountName=%s)"
637479ac375Sdm 
638479ac375Sdm /* Puts the values of attributes to unixuser and unixgroup, unless NULL */
639479ac375Sdm 
640479ac375Sdm static
641479ac375Sdm idmap_stat
winname2dn(idmap_nm_handle_t * p,char * winname,int * is_wuser,char ** dn,char ** unixuser,char ** unixgroup)64261b364a9Sjp winname2dn(idmap_nm_handle_t *p, char *winname,
643479ac375Sdm     int *is_wuser, char **dn, char **unixuser, char **unixgroup)
644479ac375Sdm {
645479ac375Sdm 	idmap_stat rc = IDMAP_SUCCESS;
646479ac375Sdm 	char *base;
647479ac375Sdm 	char *filter;
648479ac375Sdm 	int flen;
649479ac375Sdm 	char *attribs[4];
650479ac375Sdm 	int i;
651479ac375Sdm 	LDAPMessage *results = NULL;
652479ac375Sdm 	LDAPMessage *entry;
653479ac375Sdm 	int ldap_rc;
654479ac375Sdm 
655479ac375Sdm 	/* Query: */
656479ac375Sdm 
657479ac375Sdm 	base = dns2dn(p->windomain, "");
658479ac375Sdm 	if (base == NULL) {
659479ac375Sdm 		return (IDMAP_ERR_MEMORY);
660479ac375Sdm 	}
661479ac375Sdm 
662479ac375Sdm 	i = 0;
663479ac375Sdm 	attribs[i++] = "objectClass";
664479ac375Sdm 	if (unixuser != NULL)
665479ac375Sdm 		attribs[i++] = p->ad_unixuser_attr;
666479ac375Sdm 	if (unixgroup != NULL)
667479ac375Sdm 		attribs[i++] = p->ad_unixgroup_attr;
668479ac375Sdm 	attribs[i] = NULL;
669479ac375Sdm 
670479ac375Sdm 	flen = snprintf(NULL, 0, FILTER, winname) + 1;
671479ac375Sdm 	if ((filter = (char *)malloc(flen)) == NULL) {
672479ac375Sdm 		free(base);
673479ac375Sdm 		return (IDMAP_ERR_MEMORY);
674479ac375Sdm 	}
675479ac375Sdm 	(void) snprintf(filter, flen, FILTER, winname);
676479ac375Sdm 
677479ac375Sdm 	ldap_rc = ldap_search_s(p->ad, base, LDAP_SCOPE_SUBTREE, filter,
678479ac375Sdm 	    attribs, 0, &results);
679479ac375Sdm 
680479ac375Sdm 	free(base);
681479ac375Sdm 	free(filter);
682479ac375Sdm 
683479ac375Sdm 	if (ldap_rc != LDAP_SUCCESS) {
684c5866007SKeyur Desai 		namemap_log(
685c5866007SKeyur Desai 		    gettext("Ldap query to server %s port %d failed. (%s)"),
686479ac375Sdm 		    p->ad_host, p->ad_port, ldap_err2string(ldap_rc));
687479ac375Sdm 		(void) ldap_msgfree(results);
688479ac375Sdm 		return (IDMAP_ERR_OTHER);
689479ac375Sdm 	}
690479ac375Sdm 
691479ac375Sdm 
692479ac375Sdm 	for (entry = ldap_first_entry(p->ad, results), *dn = NULL;
693479ac375Sdm 	    entry != NULL;
694479ac375Sdm 	    entry = ldap_next_entry(p->ad, entry)) {
695479ac375Sdm 		char	**values = NULL;
696479ac375Sdm 		int i = 0;
697479ac375Sdm 		values = ldap_get_values(p->ad, entry, "objectClass");
698479ac375Sdm 
699479ac375Sdm 		if (values == NULL) {
700479ac375Sdm 			(void) ldap_msgfree(results);
701479ac375Sdm 			return (IDMAP_ERR_MEMORY);
702479ac375Sdm 		}
703479ac375Sdm 
704479ac375Sdm 		for (i = 0; i < ldap_count_values(values); i++) {
705479ac375Sdm 		/*
706479ac375Sdm 		 * is_wuser can be IDMAP_UNKNOWN, in that case we accept
707479ac375Sdm 		 * both User/Group
708479ac375Sdm 		 */
709479ac375Sdm 			if (*is_wuser != IDMAP_NO &&
710479ac375Sdm 			    strcasecmp(values[i], "User") == 0 ||
711479ac375Sdm 			    *is_wuser != IDMAP_YES &&
712479ac375Sdm 			    strcasecmp(values[i], "Group") == 0) {
713479ac375Sdm 				*dn = ldap_get_dn(p->ad, entry);
714479ac375Sdm 				if (*dn == NULL) {
715479ac375Sdm 					ldap_value_free(values);
716479ac375Sdm 					(void) ldap_msgfree(results);
717479ac375Sdm 					return (IDMAP_ERR_MEMORY);
718479ac375Sdm 				}
719479ac375Sdm 				*is_wuser = strcasecmp(values[i], "User") == 0
720479ac375Sdm 				    ? IDMAP_YES : IDMAP_NO;
721479ac375Sdm 				break;
722479ac375Sdm 			}
723479ac375Sdm 		}
724479ac375Sdm 
725479ac375Sdm 		ldap_value_free(values);
726479ac375Sdm 		if (*dn != NULL)
727479ac375Sdm 			break;
728479ac375Sdm 	}
729479ac375Sdm 
730479ac375Sdm 	if (*dn == NULL) {
731c5866007SKeyur Desai 		namemap_log(
732479ac375Sdm 		    *is_wuser == IDMAP_YES ? gettext("User %s@%s not found") :
733479ac375Sdm 		    *is_wuser == IDMAP_NO ? gettext("Group %s@%s not found") :
734479ac375Sdm 		    gettext("%s@%s not found"), winname, p->windomain);
735479ac375Sdm 		return (IDMAP_ERR_NOTFOUND);
736479ac375Sdm 	}
737479ac375Sdm 
738479ac375Sdm 	if (unixuser != NULL)
739479ac375Sdm 		rc = extract_attribute(p, entry, p->ad_unixuser_attr,
740479ac375Sdm 		    unixuser);
741479ac375Sdm 
742479ac375Sdm 	if (rc == IDMAP_SUCCESS && unixgroup != NULL)
743479ac375Sdm 		rc = extract_attribute(p, entry, p->ad_unixgroup_attr,
744479ac375Sdm 		    unixgroup);
745479ac375Sdm 
746479ac375Sdm 	(void) ldap_msgfree(results);
747479ac375Sdm 
748479ac375Sdm 	return (rc);
749479ac375Sdm }
750479ac375Sdm 
751479ac375Sdm 
752479ac375Sdm /* set the given attribute to the given value. If value is NULL, unset it */
753479ac375Sdm static
754479ac375Sdm idmap_stat
idmap_ad_set(idmap_nm_handle_t * p,char * dn,char * attr,char * value)75561b364a9Sjp idmap_ad_set(idmap_nm_handle_t *p, char *dn, char *attr, char *value)
756479ac375Sdm {
757479ac375Sdm 	idmap_stat rc = IDMAP_SUCCESS;
758479ac375Sdm 	int ldap_rc;
759479ac375Sdm 	char *new_values[2] = {NULL, NULL};
760479ac375Sdm 	LDAPMod *mods[2] = {NULL, NULL};
761479ac375Sdm 
762479ac375Sdm 	mods[0] = (LDAPMod *)calloc(1, sizeof (LDAPMod));
763479ac375Sdm 	mods[0]->mod_type = strdup(attr);
764479ac375Sdm 	if (value != NULL) {
765479ac375Sdm 		mods[0]->mod_op = LDAP_MOD_REPLACE;
766479ac375Sdm 		new_values[0] = strdup(value);
767479ac375Sdm 		mods[0]->mod_values = new_values;
768479ac375Sdm 	} else {
769479ac375Sdm 		mods[0]->mod_op = LDAP_MOD_DELETE;
770479ac375Sdm 		mods[0]->mod_values = NULL;
771479ac375Sdm 	}
772479ac375Sdm 
773479ac375Sdm 	ldap_rc = ldap_modify_s(p->ad, dn, mods);
774479ac375Sdm 	if (ldap_rc != LDAP_SUCCESS) {
775c5866007SKeyur Desai 		namemap_log(
776c5866007SKeyur Desai 		    gettext("Ldap modify of %s, attribute %s failed. (%s)"),
777479ac375Sdm 		    dn, attr, ldap_err2string(ldap_rc));
778479ac375Sdm 		rc = IDMAP_ERR_INTERNAL;
779479ac375Sdm 	}
780479ac375Sdm 
781479ac375Sdm 
782479ac375Sdm 	ldap_mods_free(mods, 0);
783479ac375Sdm 	return (rc);
784479ac375Sdm }
785479ac375Sdm 
786479ac375Sdm 
787479ac375Sdm /*
788479ac375Sdm  * This function takes the p argument just for the beauty of the symmetry
789479ac375Sdm  * with idmap_ad_set (and for future enhancements).
790479ac375Sdm  */
791479ac375Sdm static
792479ac375Sdm idmap_stat
793479ac375Sdm /* 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)79461b364a9Sjp idmap_nldap_set(idmap_nm_handle_t *p, ns_cred_t *nsc, char *dn, char *attr,
795479ac375Sdm     char *value, bool_t is_new, int is_user)
796479ac375Sdm {
797479ac375Sdm 	int ldaprc;
798479ac375Sdm 	ns_ldap_error_t *errorp = NULL;
799479ac375Sdm 	ns_ldap_attr_t	*attrs[2];
800479ac375Sdm 
801479ac375Sdm 
802479ac375Sdm 
803479ac375Sdm 	attrs[0] = (ns_ldap_attr_t *)malloc(sizeof (ns_ldap_attr_t));
804479ac375Sdm 	if (attrs == NULL)
805479ac375Sdm 		return (IDMAP_ERR_MEMORY);
806479ac375Sdm 
807479ac375Sdm 	attrs[0]->attrname = attr;
808479ac375Sdm 
809479ac375Sdm 	if (value != NULL) {
810479ac375Sdm 		char **newattr = (char **)calloc(2, sizeof (char *));
811479ac375Sdm 		if (newattr == NULL) {
812479ac375Sdm 			free(attrs[0]);
813479ac375Sdm 			return (IDMAP_ERR_MEMORY);
814479ac375Sdm 		}
815479ac375Sdm 		newattr[0] = value;
816479ac375Sdm 		newattr[1] = NULL;
817479ac375Sdm 
818479ac375Sdm 		attrs[0]->attrvalue = newattr;
819479ac375Sdm 		attrs[0]->value_count = 1;
820479ac375Sdm 	} else {
821479ac375Sdm 		attrs[0]->attrvalue = NULL;
822479ac375Sdm 		attrs[0]->value_count = 0;
823479ac375Sdm 	}
824479ac375Sdm 
825479ac375Sdm 
826479ac375Sdm 	attrs[1] = NULL;
827479ac375Sdm 
828479ac375Sdm 	if (value == NULL) {
829479ac375Sdm 		ldaprc = __ns_ldap_delAttr(
830479ac375Sdm 		    is_user == IDMAP_YES ? "passwd": "group",
831479ac375Sdm 		    dn, (const ns_ldap_attr_t * const *)attrs,
832479ac375Sdm 		    nsc, 0, &errorp);
833479ac375Sdm 	} else if (is_new)
834479ac375Sdm 		ldaprc = __ns_ldap_addAttr(
835479ac375Sdm 		    is_user == IDMAP_YES ? "passwd": "group",
836479ac375Sdm 		    dn, (const ns_ldap_attr_t * const *)attrs,
837479ac375Sdm 		    nsc, 0, &errorp);
838479ac375Sdm 	else
839479ac375Sdm 		ldaprc = __ns_ldap_repAttr(
840479ac375Sdm 		    is_user == IDMAP_YES ? "passwd": "group",
841479ac375Sdm 		    dn, (const ns_ldap_attr_t * const *)attrs,
842479ac375Sdm 		    nsc, 0, &errorp);
843479ac375Sdm 
844479ac375Sdm 	if (ldaprc != NS_LDAP_SUCCESS) {
845479ac375Sdm 		char *msg = "Cause unidentified";
846479ac375Sdm 		if (errorp != NULL) {
847479ac375Sdm 			(void) __ns_ldap_err2str(errorp->status, &msg);
848479ac375Sdm 		}
849c5866007SKeyur Desai 		namemap_log(
850c5866007SKeyur Desai 		    gettext("__ns_ldap_addAttr/rep/delAttr failed (%s)"),
851c5866007SKeyur Desai 		    msg);
852479ac375Sdm 		return (IDMAP_ERR_ARG);
853479ac375Sdm 	}
854479ac375Sdm 
855479ac375Sdm 	return (IDMAP_SUCCESS);
856479ac375Sdm }
857479ac375Sdm 
858479ac375Sdm idmap_stat
idmap_set_namemap(idmap_nm_handle_t * p,char * winname,char * unixname,int is_user,int is_wuser,int direction)85961b364a9Sjp idmap_set_namemap(idmap_nm_handle_t *p, char *winname, char *unixname,
86061b364a9Sjp     int is_user, int is_wuser, int direction)
861479ac375Sdm {
862479ac375Sdm 	idmap_stat	rc = IDMAP_SUCCESS;
863479ac375Sdm 	char		*dn = NULL;
864479ac375Sdm 	char		*oldwinname = NULL;
865479ac375Sdm 	char		*oldwindomain = NULL;
866479ac375Sdm 
86761b364a9Sjp 	if (direction == IDMAP_DIRECTION_W2U) {
86861b364a9Sjp 		if (!p->is_ad) {
86961b364a9Sjp 			rc = IDMAP_ERR_ARG;
870c5866007SKeyur Desai 			namemap_log(
87161b364a9Sjp 			    gettext("AD namemaps aren't set up."));
872479ac375Sdm 			goto cleanup;
873479ac375Sdm 		}
874479ac375Sdm 
875479ac375Sdm 		rc = winname2dn(p, winname, &is_wuser,
876479ac375Sdm 		    &dn, NULL, NULL);
877479ac375Sdm 		if (rc != IDMAP_SUCCESS)
878479ac375Sdm 			goto cleanup;
879479ac375Sdm 
880479ac375Sdm 		rc = idmap_ad_set(p, dn, is_user ? p->ad_unixuser_attr :
881479ac375Sdm 		    p->ad_unixgroup_attr, unixname);
882479ac375Sdm 		if (rc != IDMAP_SUCCESS)
883479ac375Sdm 			goto cleanup;
884479ac375Sdm 
885479ac375Sdm 	}
886479ac375Sdm 
887479ac375Sdm 
88861b364a9Sjp 	if (direction == IDMAP_DIRECTION_U2W) {
889479ac375Sdm 		char *fullname;
890479ac375Sdm 
89161b364a9Sjp 		if (!p->is_nldap) {
89261b364a9Sjp 			rc = IDMAP_ERR_ARG;
893c5866007SKeyur Desai 			namemap_log(
89461b364a9Sjp 			    gettext("Native ldap namemaps aren't set up."));
895479ac375Sdm 			goto cleanup;
896479ac375Sdm 		}
897479ac375Sdm 
89861b364a9Sjp 
899479ac375Sdm 		rc = unixname2dn(p, unixname, is_user, &dn,
900479ac375Sdm 		    &oldwinname, &oldwindomain);
901479ac375Sdm 		if (rc != IDMAP_SUCCESS)
902479ac375Sdm 			goto cleanup;
903479ac375Sdm 
904479ac375Sdm 		if (p->windomain == NULL) {
905479ac375Sdm 			fullname = strdup(winname);
9063ad44b67SToomas Soome 			if (fullname == NULL) {
907479ac375Sdm 				rc = IDMAP_ERR_MEMORY;
908479ac375Sdm 				goto cleanup;
9093ad44b67SToomas Soome 			}
910479ac375Sdm 		} else {
911479ac375Sdm 			fullname = malloc(strlen(winname) +
912479ac375Sdm 			    strlen(p->windomain) + 2);
913479ac375Sdm 			if (fullname == NULL) {
914479ac375Sdm 				rc = IDMAP_ERR_MEMORY;
915479ac375Sdm 				goto cleanup;
916479ac375Sdm 			}
917479ac375Sdm 
918479ac375Sdm 			(void) snprintf(fullname,
919479ac375Sdm 			    strlen(winname) + strlen(p->windomain) + 2,
920479ac375Sdm 			    "%s\\%s", p->windomain, winname);
921479ac375Sdm 		}
92261b364a9Sjp 		rc = idmap_nldap_set(p, &p->nsc, dn, p->nldap_winname_attr,
923479ac375Sdm 		    fullname, oldwinname == NULL ? TRUE : FALSE, is_user);
924479ac375Sdm 
925479ac375Sdm 		free(fullname);
926479ac375Sdm 		free(oldwindomain);
927479ac375Sdm 		free(oldwinname);
928479ac375Sdm 
929479ac375Sdm 		if (rc != IDMAP_SUCCESS)
930479ac375Sdm 			goto cleanup;
931479ac375Sdm 
932479ac375Sdm 	}
933479ac375Sdm 
934479ac375Sdm cleanup:
93561b364a9Sjp 	if (dn != NULL)
93661b364a9Sjp 		free(dn);
93761b364a9Sjp 
93861b364a9Sjp 	if (oldwindomain != NULL)
93961b364a9Sjp 		free(oldwindomain);
94061b364a9Sjp 
94161b364a9Sjp 	if (oldwinname != NULL)
94261b364a9Sjp 		free(oldwinname);
94361b364a9Sjp 
944479ac375Sdm 	return (rc);
945479ac375Sdm 
946479ac375Sdm }
947479ac375Sdm 
94861b364a9Sjp 
949479ac375Sdm idmap_stat
idmap_unset_namemap(idmap_nm_handle_t * p,char * winname,char * unixname,int is_user,int is_wuser,int direction)95061b364a9Sjp idmap_unset_namemap(idmap_nm_handle_t *p, char *winname, char *unixname,
95161b364a9Sjp     int is_user, int is_wuser, int direction)
952479ac375Sdm {
953479ac375Sdm 	idmap_stat	rc = IDMAP_SUCCESS;
954479ac375Sdm 	char		*dn = NULL;
955479ac375Sdm 	char		*oldwinname = NULL;
956479ac375Sdm 	char		*oldwindomain = NULL;
957479ac375Sdm 
958479ac375Sdm 	if (direction == IDMAP_DIRECTION_W2U) {
959479ac375Sdm 		if (!p->is_ad) {
960479ac375Sdm 			rc = IDMAP_ERR_ARG;
961c5866007SKeyur Desai 			namemap_log(
962479ac375Sdm 			    gettext("AD namemaps aren't set up."));
963479ac375Sdm 			goto cleanup;
964479ac375Sdm 		}
965479ac375Sdm 
966479ac375Sdm 		rc = winname2dn(p, winname, &is_wuser,
967479ac375Sdm 		    &dn, NULL, NULL);
968479ac375Sdm 		if (rc != IDMAP_SUCCESS)
969479ac375Sdm 			goto cleanup;
970479ac375Sdm 
971479ac375Sdm 		rc = idmap_ad_set(p, dn, is_user ? p->ad_unixuser_attr :
972479ac375Sdm 		    p->ad_unixgroup_attr, unixname);
973479ac375Sdm 		if (rc != IDMAP_SUCCESS)
974479ac375Sdm 			goto cleanup;
975479ac375Sdm 
976479ac375Sdm 	} else { /* direction == IDMAP_DIRECTION_U2W */
977479ac375Sdm 		if (!p->is_nldap) {
978479ac375Sdm 			rc = IDMAP_ERR_ARG;
979c5866007SKeyur Desai 			namemap_log(
980479ac375Sdm 			    gettext("Native ldap namemaps aren't set up."));
981479ac375Sdm 			goto cleanup;
982479ac375Sdm 		}
983479ac375Sdm 
984479ac375Sdm 		rc = unixname2dn(p, unixname, is_user, &dn, NULL, NULL);
985479ac375Sdm 		if (rc != IDMAP_SUCCESS)
986479ac375Sdm 			goto cleanup;
987479ac375Sdm 
98861b364a9Sjp 		rc = idmap_nldap_set(p, &p->nsc, dn, p->nldap_winname_attr,
98961b364a9Sjp 		    NULL, TRUE, is_user);
990479ac375Sdm 		if (rc != IDMAP_SUCCESS)
991479ac375Sdm 			goto cleanup;
992479ac375Sdm 
993479ac375Sdm 	}
994479ac375Sdm 
995479ac375Sdm cleanup:
99661b364a9Sjp 	if (oldwindomain != NULL)
99761b364a9Sjp 		free(oldwindomain);
99861b364a9Sjp 	if (oldwinname != NULL)
99961b364a9Sjp 		free(oldwinname);
100061b364a9Sjp 	if (dn != NULL)
100161b364a9Sjp 		free(dn);
1002479ac375Sdm 	return (rc);
1003479ac375Sdm }
1004479ac375Sdm 
1005479ac375Sdm 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)100661b364a9Sjp idmap_get_namemap(idmap_nm_handle_t *p, int *is_source_ad, char **winname,
100761b364a9Sjp     char **windomain, int *is_wuser, char **unixuser, char **unixgroup)
100861b364a9Sjp {
1009479ac375Sdm 	idmap_stat	rc = IDMAP_SUCCESS;
1010479ac375Sdm 	char		*dn = NULL;
1011479ac375Sdm 
1012479ac375Sdm 	*is_source_ad = IDMAP_UNKNOWN;
101361b364a9Sjp 	if (*winname != NULL) {
1014479ac375Sdm 		*is_source_ad = IDMAP_YES;
1015479ac375Sdm 
1016*ef826847SToomas Soome 		if (p->is_ad == FALSE) {
1017479ac375Sdm 			rc = IDMAP_ERR_ARG;
1018c5866007SKeyur Desai 			namemap_log(
101961b364a9Sjp 			    gettext("AD namemaps are not active."));
1020479ac375Sdm 			goto cleanup;
102161b364a9Sjp 			/* In future maybe resolve winname and try nldap? */
1022479ac375Sdm 		}
1023479ac375Sdm 
1024479ac375Sdm 		rc = winname2dn(p, *winname, is_wuser, &dn, unixuser,
1025479ac375Sdm 		    unixgroup);
102661b364a9Sjp 		if (rc != IDMAP_SUCCESS) {
1027c5866007SKeyur Desai 			namemap_log(
102861b364a9Sjp 			    gettext("Winname %s@%s not found in AD."),
102961b364a9Sjp 			    *winname, p->windomain);
103061b364a9Sjp 		}
103161b364a9Sjp 	} else if (*unixuser != NULL ||	*unixgroup != NULL) {
1032479ac375Sdm 		char *unixname;
1033479ac375Sdm 		int is_user;
1034479ac375Sdm 
1035479ac375Sdm 		*is_source_ad = IDMAP_NO;
1036479ac375Sdm 
1037*ef826847SToomas Soome 		if (p->is_nldap == FALSE) {
103861b364a9Sjp 			rc = IDMAP_ERR_ARG;
1039c5866007SKeyur Desai 			namemap_log(
104061b364a9Sjp 			    gettext("Native ldap namemaps aren't active."));
104161b364a9Sjp 			goto cleanup;
104261b364a9Sjp 			/* In future maybe resolve unixname and try AD? */
104361b364a9Sjp 		}
104461b364a9Sjp 
1045479ac375Sdm 		if (*unixuser != NULL) {
1046479ac375Sdm 			is_user = IDMAP_YES;
1047479ac375Sdm 			unixname = *unixuser;
1048479ac375Sdm 		} else if (*unixgroup != NULL) {
1049479ac375Sdm 			is_user = IDMAP_NO;
1050479ac375Sdm 			unixname = *unixgroup;
1051479ac375Sdm 		}
1052479ac375Sdm 
1053479ac375Sdm 		rc = unixname2dn(p, unixname, is_user, NULL, winname,
1054479ac375Sdm 		    windomain);
105561b364a9Sjp 		if (rc != IDMAP_SUCCESS) {
1056c5866007SKeyur Desai 			namemap_log(
105761b364a9Sjp 			    gettext("%s %s not found in native ldap."),
105861b364a9Sjp 			    is_user == IDMAP_YES ? "UNIX user" : "UNIX group",
105961b364a9Sjp 			    unixname);
1060479ac375Sdm 			goto cleanup;
106161b364a9Sjp 		}
1062479ac375Sdm 	} else {
1063479ac375Sdm 		rc = IDMAP_ERR_ARG;
1064479ac375Sdm 		goto cleanup;
1065479ac375Sdm 	}
1066479ac375Sdm 
1067479ac375Sdm cleanup:
1068479ac375Sdm 	return (rc);
1069479ac375Sdm }
1070