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
namemap_log(char * fmt,...)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
string2auth(const char * from,ns_auth_t * na)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
strings2cred(ns_cred_t * nsc,char * user,char * passwd,char * auth)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
idmap_saslcallback(LDAP * ld,unsigned flags,void * defaults,void * prompts)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
idmap_open_ad_conn(idmap_nm_handle_t * adh)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
idmap_init_nldap(idmap_nm_handle_t * p)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
idmap_init_ad(idmap_nm_handle_t * p)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
idmap_fini_namemaps(idmap_nm_handle_t * p)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
idmap_init_namemaps(idmap_nm_handle_t ** adh,char * user,char * passwd,char * auth,char * windomain,int direction)354 idmap_init_namemaps(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(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(rc));
371 goto cleanup;
372 }
373
374 rc = idmap_get_prop_str(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(rc));
380 goto cleanup;
381 }
382
383 rc = idmap_get_prop_str(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(rc));
389 goto cleanup;
390 }
391
392
393 rc = idmap_get_prop_str(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(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 *
dns2dn(const char * dns,const char * prefix)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
extract_attribute(idmap_nm_handle_t * p,LDAPMessage * entry,char * name,char ** value)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
split_fqwn(char * fqwn,char ** name,char ** domain)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
unixname2dn(idmap_nm_handle_t * p,char * unixname,int is_user,char ** dn,char ** winname,char ** windomain)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
winname2dn(idmap_nm_handle_t * p,char * winname,int * is_wuser,char ** dn,char ** unixuser,char ** unixgroup)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
idmap_ad_set(idmap_nm_handle_t * p,char * dn,char * attr,char * value)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 */
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)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
idmap_set_namemap(idmap_nm_handle_t * p,char * winname,char * unixname,int is_user,int is_wuser,int direction)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
idmap_unset_namemap(idmap_nm_handle_t * p,char * winname,char * unixname,int is_user,int is_wuser,int direction)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
idmap_get_namemap(idmap_nm_handle_t * p,int * is_source_ad,char ** winname,char ** windomain,int * is_wuser,char ** unixuser,char ** unixgroup)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