1c5c4113dSnw /*
2c5c4113dSnw * CDDL HEADER START
3c5c4113dSnw *
4c5c4113dSnw * The contents of this file are subject to the terms of the
5c5c4113dSnw * Common Development and Distribution License (the "License").
6c5c4113dSnw * You may not use this file except in compliance with the License.
7c5c4113dSnw *
8c5c4113dSnw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c5c4113dSnw * or http://www.opensolaris.org/os/licensing.
10c5c4113dSnw * See the License for the specific language governing permissions
11c5c4113dSnw * and limitations under the License.
12c5c4113dSnw *
13c5c4113dSnw * When distributing Covered Code, include this CDDL HEADER in each
14c5c4113dSnw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c5c4113dSnw * If applicable, add the following below this CDDL HEADER, with the
16c5c4113dSnw * fields enclosed by brackets "[]" replaced with your own identifying
17c5c4113dSnw * information: Portions Copyright [yyyy] [name of copyright owner]
18c5c4113dSnw *
19c5c4113dSnw * CDDL HEADER END
20c5c4113dSnw */
21c5c4113dSnw
22c5c4113dSnw /*
23148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24a01d29c9SMatt Barden *
25a01d29c9SMatt Barden * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
26c5c4113dSnw */
27c5c4113dSnw
28c5c4113dSnw /*
29c5c4113dSnw * Processes name2sid & sid2name batched lookups for a given user or
30c5c4113dSnw * computer from an AD Directory server using GSSAPI authentication
31c5c4113dSnw */
32c5c4113dSnw
33c5c4113dSnw #include <stdio.h>
34c5c4113dSnw #include <stdlib.h>
35c5c4113dSnw #include <alloca.h>
36c5c4113dSnw #include <string.h>
37c5c4113dSnw #include <strings.h>
38c5c4113dSnw #include <lber.h>
39c5c4113dSnw #include <ldap.h>
40c5c4113dSnw #include <sasl/sasl.h>
41c5c4113dSnw #include <string.h>
42c5c4113dSnw #include <ctype.h>
43c5c4113dSnw #include <pthread.h>
44c5c4113dSnw #include <synch.h>
45c5c4113dSnw #include <atomic.h>
46c5c4113dSnw #include <errno.h>
47c5c4113dSnw #include <assert.h>
48c5c4113dSnw #include <limits.h>
492b4a7802SBaban Kenkre #include <time.h>
50cd37da74Snw #include <sys/u8_textprep.h>
512b4a7802SBaban Kenkre #include "libadutils.h"
52479ac375Sdm #include "nldaputils.h"
53c5c4113dSnw #include "idmapd.h"
54c5c4113dSnw
55c5c4113dSnw /* Attribute names and filter format strings */
56e3c2d6aaSnw #define SAN "sAMAccountName"
57e3c2d6aaSnw #define OBJSID "objectSid"
58e3c2d6aaSnw #define OBJCLASS "objectClass"
59e3f2c991SKeyur Desai #define UIDNUMBER "uidNumber"
60e3f2c991SKeyur Desai #define GIDNUMBER "gidNumber"
61e3f2c991SKeyur Desai #define UIDNUMBERFILTER "(&(objectclass=user)(uidNumber=%u))"
62e3f2c991SKeyur Desai #define GIDNUMBERFILTER "(&(objectclass=group)(gidNumber=%u))"
63e3f2c991SKeyur Desai #define SANFILTER "(sAMAccountName=%s)"
64a01d29c9SMatt Barden #define OBJSIDFILTER "(|(objectSid=%s)(sIDHistory=%s))"
65c5c4113dSnw
662b4a7802SBaban Kenkre void idmap_ldap_res_search_cb(LDAP *ld, LDAPMessage **res, int rc,
672b4a7802SBaban Kenkre int qid, void *argp);
68c5c4113dSnw
69c5c4113dSnw /*
70c5c4113dSnw * A place to put the results of a batched (async) query
71c5c4113dSnw *
72c5c4113dSnw * There is one of these for every query added to a batch object
73c5c4113dSnw * (idmap_query_state, see below).
74c5c4113dSnw */
75c5c4113dSnw typedef struct idmap_q {
76e3c2d6aaSnw /*
77e3c2d6aaSnw * data used for validating search result entries for name->SID
78e8c27ec8Sbaban * lookups
79e3c2d6aaSnw */
80cd37da74Snw char *ecanonname; /* expected canon name */
81cd37da74Snw char *edomain; /* expected domain name */
82148c5f43SAlan Wright idmap_id_type esidtype; /* expected SID type */
83e3c2d6aaSnw /* results */
84cd37da74Snw char **canonname; /* actual canon name */
85c5c4113dSnw char **domain; /* name of domain of object */
86e8c27ec8Sbaban char **sid; /* stringified SID */
87e8c27ec8Sbaban rid_t *rid; /* RID */
88148c5f43SAlan Wright idmap_id_type *sid_type; /* user or group SID? */
89e8c27ec8Sbaban char **unixname; /* unixname for name mapping */
9048258c6bSjp char **dn; /* DN of entry */
9148258c6bSjp char **attr; /* Attr for name mapping */
9248258c6bSjp char **value; /* value for name mapping */
93e3f2c991SKeyur Desai posix_id_t *pid; /* Posix ID found via IDMU */
94c5c4113dSnw idmap_retcode *rc;
952b4a7802SBaban Kenkre adutils_rc ad_rc;
962b4a7802SBaban Kenkre adutils_result_t *result;
97e3c2d6aaSnw
98bcced03bSjp /*
99bcced03bSjp * The LDAP search entry result is placed here to be processed
100bcced03bSjp * when the search done result is received.
101bcced03bSjp */
102bcced03bSjp LDAPMessage *search_res; /* The LDAP search result */
103c5c4113dSnw } idmap_q_t;
104c5c4113dSnw
105c5c4113dSnw /* Batch context structure; typedef is in header file */
106c5c4113dSnw struct idmap_query_state {
1072b4a7802SBaban Kenkre adutils_query_state_t *qs;
1084d61c878SJulian Pullen int qsize; /* Queue size */
1094d61c878SJulian Pullen uint32_t qcount; /* Number of queued requests */
110e8c27ec8Sbaban const char *ad_unixuser_attr;
111e8c27ec8Sbaban const char *ad_unixgroup_attr;
112e3f2c991SKeyur Desai int directory_based_mapping; /* enum */
113e3f2c991SKeyur Desai char *default_domain;
114c5c4113dSnw idmap_q_t queries[1]; /* array of query results */
115c5c4113dSnw };
116c5c4113dSnw
117651c0131Sbaban static pthread_t reaperid = 0;
118c5c4113dSnw
119c5c4113dSnw /*
120c5c4113dSnw * Keep connection management simple for now, extend or replace later
121c5c4113dSnw * with updated libsldap code.
122c5c4113dSnw */
123c5c4113dSnw #define ADREAPERSLEEP 60
124c5c4113dSnw
125c5c4113dSnw /*
126c5c4113dSnw * Idle connection reaping side of connection management
127c5c4113dSnw *
128c5c4113dSnw * Every minute wake up and look for connections that have been idle for
129c5c4113dSnw * five minutes or more and close them.
130c5c4113dSnw */
131c5c4113dSnw /*ARGSUSED*/
132c5c4113dSnw static
133*49160520SToomas Soome void *
adreaper(void * arg __unused)134*49160520SToomas Soome adreaper(void *arg __unused)
135c5c4113dSnw {
136c5c4113dSnw timespec_t ts;
137c5c4113dSnw
138c5c4113dSnw ts.tv_sec = ADREAPERSLEEP;
139c5c4113dSnw ts.tv_nsec = 0;
140c5c4113dSnw
141c5c4113dSnw for (;;) {
142c5c4113dSnw /*
143c5c4113dSnw * nanosleep(3RT) is thead-safe (no SIGALRM) and more
144c5c4113dSnw * portable than usleep(3C)
145c5c4113dSnw */
146c5c4113dSnw (void) nanosleep(&ts, NULL);
1472b4a7802SBaban Kenkre adutils_reap_idle_connections();
148c5c4113dSnw }
149*49160520SToomas Soome return (NULL);
150c5c4113dSnw }
151c5c4113dSnw
152c5c4113dSnw /*
153c5c4113dSnw * Take ad_host_config_t information, create a ad_host_t,
154c5c4113dSnw * populate it and add it to the list of hosts.
155c5c4113dSnw */
156c5c4113dSnw
157c5c4113dSnw int
idmap_add_ds(adutils_ad_t * ad,const char * host,int port)1582b4a7802SBaban Kenkre idmap_add_ds(adutils_ad_t *ad, const char *host, int port)
159c5c4113dSnw {
1602b4a7802SBaban Kenkre int ret = -1;
161c5c4113dSnw
1622b4a7802SBaban Kenkre if (adutils_add_ds(ad, host, port) == ADUTILS_SUCCESS)
1632b4a7802SBaban Kenkre ret = 0;
164c5c4113dSnw
165c5c4113dSnw /* Start reaper if it doesn't exist */
1662b4a7802SBaban Kenkre if (ret == 0 && reaperid == 0)
167*49160520SToomas Soome (void) pthread_create(&reaperid, NULL, adreaper, NULL);
168c5c4113dSnw return (ret);
169c5c4113dSnw }
170c5c4113dSnw
171c5c4113dSnw static
1722b4a7802SBaban Kenkre idmap_retcode
map_adrc2idmaprc(adutils_rc adrc)1732b4a7802SBaban Kenkre map_adrc2idmaprc(adutils_rc adrc)
1742b4a7802SBaban Kenkre {
1752b4a7802SBaban Kenkre switch (adrc) {
1762b4a7802SBaban Kenkre case ADUTILS_SUCCESS:
1772b4a7802SBaban Kenkre return (IDMAP_SUCCESS);
1782b4a7802SBaban Kenkre case ADUTILS_ERR_NOTFOUND:
1792b4a7802SBaban Kenkre return (IDMAP_ERR_NOTFOUND);
1802b4a7802SBaban Kenkre case ADUTILS_ERR_MEMORY:
1812b4a7802SBaban Kenkre return (IDMAP_ERR_MEMORY);
1822b4a7802SBaban Kenkre case ADUTILS_ERR_DOMAIN:
1832b4a7802SBaban Kenkre return (IDMAP_ERR_DOMAIN);
1842b4a7802SBaban Kenkre case ADUTILS_ERR_OTHER:
1852b4a7802SBaban Kenkre return (IDMAP_ERR_OTHER);
1862b4a7802SBaban Kenkre case ADUTILS_ERR_RETRIABLE_NET_ERR:
1872b4a7802SBaban Kenkre return (IDMAP_ERR_RETRIABLE_NET_ERR);
1882b4a7802SBaban Kenkre default:
1892b4a7802SBaban Kenkre return (IDMAP_ERR_INTERNAL);
190c5c4113dSnw }
1912b4a7802SBaban Kenkre /* NOTREACHED */
192c5c4113dSnw }
193c5c4113dSnw
194c5c4113dSnw idmap_retcode
idmap_lookup_batch_start(adutils_ad_t * ad,int nqueries,int directory_based_mapping,const char * default_domain,idmap_query_state_t ** state)1952b4a7802SBaban Kenkre idmap_lookup_batch_start(adutils_ad_t *ad, int nqueries,
196*49160520SToomas Soome int directory_based_mapping, const char *default_domain,
197*49160520SToomas Soome idmap_query_state_t **state)
198c5c4113dSnw {
1992b4a7802SBaban Kenkre idmap_query_state_t *new_state;
2002b4a7802SBaban Kenkre adutils_rc rc;
201c5c4113dSnw
202c5c4113dSnw *state = NULL;
203c5c4113dSnw
2044d61c878SJulian Pullen assert(ad != NULL);
205c5c4113dSnw
206c5c4113dSnw new_state = calloc(1, sizeof (idmap_query_state_t) +
207c5c4113dSnw (nqueries - 1) * sizeof (idmap_q_t));
208c5c4113dSnw if (new_state == NULL)
209c5c4113dSnw return (IDMAP_ERR_MEMORY);
210c5c4113dSnw
2112b4a7802SBaban Kenkre if ((rc = adutils_lookup_batch_start(ad, nqueries,
2122b4a7802SBaban Kenkre idmap_ldap_res_search_cb, new_state, &new_state->qs))
2132b4a7802SBaban Kenkre != ADUTILS_SUCCESS) {
214e3f2c991SKeyur Desai idmap_lookup_release_batch(&new_state);
2152b4a7802SBaban Kenkre return (map_adrc2idmaprc(rc));
2162b4a7802SBaban Kenkre }
217c5c4113dSnw
218e3f2c991SKeyur Desai new_state->default_domain = strdup(default_domain);
219e3f2c991SKeyur Desai if (new_state->default_domain == NULL) {
220e3f2c991SKeyur Desai idmap_lookup_release_batch(&new_state);
221e3f2c991SKeyur Desai return (IDMAP_ERR_MEMORY);
222e3f2c991SKeyur Desai }
223e3f2c991SKeyur Desai
224e3f2c991SKeyur Desai new_state->directory_based_mapping = directory_based_mapping;
2254d61c878SJulian Pullen new_state->qsize = nqueries;
226c5c4113dSnw *state = new_state;
227c5c4113dSnw return (IDMAP_SUCCESS);
228c5c4113dSnw }
229c5c4113dSnw
230e8c27ec8Sbaban /*
231e8c27ec8Sbaban * Set unixuser_attr and unixgroup_attr for AD-based name mapping
232e8c27ec8Sbaban */
233e8c27ec8Sbaban void
idmap_lookup_batch_set_unixattr(idmap_query_state_t * state,const char * unixuser_attr,const char * unixgroup_attr)234e8c27ec8Sbaban idmap_lookup_batch_set_unixattr(idmap_query_state_t *state,
235*49160520SToomas Soome const char *unixuser_attr, const char *unixgroup_attr)
2364edd44c5Sjp {
237e8c27ec8Sbaban state->ad_unixuser_attr = unixuser_attr;
238e8c27ec8Sbaban state->ad_unixgroup_attr = unixgroup_attr;
239e8c27ec8Sbaban }
240e8c27ec8Sbaban
241c5c4113dSnw /*
242cd37da74Snw * Take parsed attribute values from a search result entry and check if
243cd37da74Snw * it is the result that was desired and, if so, set the result fields
244cd37da74Snw * of the given idmap_q_t.
245cd37da74Snw *
246e3f2c991SKeyur Desai * Except for dn and attr, all strings are consumed, either by transferring
247e3f2c991SKeyur Desai * them over into the request results (where the caller will eventually free
248e3f2c991SKeyur Desai * them) or by freeing them here. Note that this aligns with the "const"
249e3f2c991SKeyur Desai * declarations below.
250c5c4113dSnw */
251c5c4113dSnw static
252cd37da74Snw void
idmap_setqresults(idmap_q_t * q,char * san,const char * dn,const char * attr,char * value,char * sid,rid_t rid,int sid_type,char * unixname,posix_id_t pid)253e3f2c991SKeyur Desai idmap_setqresults(
254e3f2c991SKeyur Desai idmap_q_t *q,
255e3f2c991SKeyur Desai char *san,
256e3f2c991SKeyur Desai const char *dn,
257e3f2c991SKeyur Desai const char *attr,
258e3f2c991SKeyur Desai char *value,
259e3f2c991SKeyur Desai char *sid,
260e3f2c991SKeyur Desai rid_t rid,
261e3f2c991SKeyur Desai int sid_type,
262e3f2c991SKeyur Desai char *unixname,
263e3f2c991SKeyur Desai posix_id_t pid)
264c5c4113dSnw {
265cd37da74Snw char *domain;
2661fcced4cSJordan Brown int err1;
267c5c4113dSnw
268cd37da74Snw assert(dn != NULL);
269e3c2d6aaSnw
2702b4a7802SBaban Kenkre if ((domain = adutils_dn2dns(dn)) == NULL)
271cd37da74Snw goto out;
272cd37da74Snw
273e8c27ec8Sbaban if (q->ecanonname != NULL && san != NULL) {
274e8c27ec8Sbaban /* Check that this is the canonname that we were looking for */
275cd37da74Snw if (u8_strcmp(q->ecanonname, san, 0,
276cd37da74Snw U8_STRCMP_CI_LOWER, /* no normalization, for now */
277e8c27ec8Sbaban U8_UNICODE_LATEST, &err1) != 0 || err1 != 0)
278e8c27ec8Sbaban goto out;
279e8c27ec8Sbaban }
280e8c27ec8Sbaban
281e8c27ec8Sbaban if (q->edomain != NULL) {
282e8c27ec8Sbaban /* Check that this is the domain that we were looking for */
2831fcced4cSJordan Brown if (!domain_eq(q->edomain, domain))
284cd37da74Snw goto out;
285e8c27ec8Sbaban }
286cd37da74Snw
28748258c6bSjp /* Copy the DN and attr and value */
28848258c6bSjp if (q->dn != NULL)
28948258c6bSjp *q->dn = strdup(dn);
29048258c6bSjp
29148258c6bSjp if (q->attr != NULL && attr != NULL)
29248258c6bSjp *q->attr = strdup(attr);
29348258c6bSjp
294e3f2c991SKeyur Desai if (q->value != NULL && value != NULL) {
295e3f2c991SKeyur Desai *q->value = value;
296e3f2c991SKeyur Desai value = NULL;
297e3f2c991SKeyur Desai }
29848258c6bSjp
299e8c27ec8Sbaban /* Set results */
300e8c27ec8Sbaban if (q->sid) {
301e8c27ec8Sbaban *q->sid = sid;
302e8c27ec8Sbaban sid = NULL;
303e8c27ec8Sbaban }
304e8c27ec8Sbaban if (q->rid)
305cd37da74Snw *q->rid = rid;
306e8c27ec8Sbaban if (q->sid_type)
307cd37da74Snw *q->sid_type = sid_type;
308e8c27ec8Sbaban if (q->unixname) {
309e8c27ec8Sbaban *q->unixname = unixname;
310e8c27ec8Sbaban unixname = NULL;
311e8c27ec8Sbaban }
312e8c27ec8Sbaban if (q->domain != NULL) {
313e8c27ec8Sbaban *q->domain = domain;
314e8c27ec8Sbaban domain = NULL;
315e8c27ec8Sbaban }
316e8c27ec8Sbaban if (q->canonname != NULL) {
317479ac375Sdm /*
318479ac375Sdm * The caller may be replacing the given winname by its
319479ac375Sdm * canonical name and therefore free any old name before
320479ac375Sdm * overwriting the field by the canonical name.
321479ac375Sdm */
322479ac375Sdm free(*q->canonname);
323cd37da74Snw *q->canonname = san;
324cd37da74Snw san = NULL;
325e3c2d6aaSnw }
326e3c2d6aaSnw
3279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (q->pid != NULL && pid != IDMAP_SENTINEL_PID) {
328e3f2c991SKeyur Desai *q->pid = pid;
329e3f2c991SKeyur Desai }
330e3f2c991SKeyur Desai
3312b4a7802SBaban Kenkre q->ad_rc = ADUTILS_SUCCESS;
332e3c2d6aaSnw
333cd37da74Snw out:
334cd37da74Snw /* Free unused attribute values */
335cd37da74Snw free(san);
336cd37da74Snw free(sid);
337cd37da74Snw free(domain);
338e8c27ec8Sbaban free(unixname);
339e3f2c991SKeyur Desai free(value);
340cd37da74Snw }
341c5c4113dSnw
342c5c4113dSnw #define BVAL_CASEEQ(bv, str) \
343c5c4113dSnw (((*(bv))->bv_len == (sizeof (str) - 1)) && \
344c5c4113dSnw strncasecmp((*(bv))->bv_val, str, (*(bv))->bv_len) == 0)
345c5c4113dSnw
346c5c4113dSnw /*
347cd37da74Snw * Extract the class of the result entry. Returns 1 on success, 0 on
348cd37da74Snw * failure.
349c5c4113dSnw */
350c5c4113dSnw static
351e3c2d6aaSnw int
idmap_bv_objclass2sidtype(BerValue ** bvalues,int * sid_type)352cd37da74Snw idmap_bv_objclass2sidtype(BerValue **bvalues, int *sid_type)
353c5c4113dSnw {
354c5c4113dSnw BerValue **cbval;
355c5c4113dSnw
356148c5f43SAlan Wright *sid_type = IDMAP_SID;
357c5c4113dSnw if (bvalues == NULL)
358e3c2d6aaSnw return (0);
359c5c4113dSnw
360cd37da74Snw /*
361e3f2c991SKeyur Desai * We consider Computer to be a subclass of User, so we can just
362e3f2c991SKeyur Desai * ignore Computer entries and pay attention to the accompanying
363e3f2c991SKeyur Desai * User entries.
364cd37da74Snw */
365c5c4113dSnw for (cbval = bvalues; *cbval != NULL; cbval++) {
366e3f2c991SKeyur Desai if (BVAL_CASEEQ(cbval, "group")) {
367148c5f43SAlan Wright *sid_type = IDMAP_GSID;
368cd37da74Snw break;
369e3f2c991SKeyur Desai } else if (BVAL_CASEEQ(cbval, "user")) {
370148c5f43SAlan Wright *sid_type = IDMAP_USID;
371e3f2c991SKeyur Desai break;
372cd37da74Snw }
373cd37da74Snw /*
374148c5f43SAlan Wright * "else if (*sid_type = IDMAP_USID)" then this is a
375cd37da74Snw * new sub-class of user -- what to do with it??
376cd37da74Snw */
377c5c4113dSnw }
378e3c2d6aaSnw
379e3c2d6aaSnw return (1);
380c5c4113dSnw }
381c5c4113dSnw
382c5c4113dSnw /*
383c5c4113dSnw * Handle a given search result entry
384c5c4113dSnw */
385c5c4113dSnw static
386c5c4113dSnw void
idmap_extract_object(idmap_query_state_t * state,idmap_q_t * q,LDAPMessage * res,LDAP * ld)3872b4a7802SBaban Kenkre idmap_extract_object(idmap_query_state_t *state, idmap_q_t *q,
388*49160520SToomas Soome LDAPMessage *res, LDAP *ld)
389c5c4113dSnw {
390c5c4113dSnw BerValue **bvalues;
391e3f2c991SKeyur Desai const char *attr = NULL;
392e3f2c991SKeyur Desai char *value = NULL;
393e3f2c991SKeyur Desai char *unix_name = NULL;
394e3f2c991SKeyur Desai char *dn;
395cd37da74Snw char *san = NULL;
396cd37da74Snw char *sid = NULL;
397cd37da74Snw rid_t rid = 0;
398e3f2c991SKeyur Desai int sid_type;
399e3f2c991SKeyur Desai int ok;
4009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States posix_id_t pid = IDMAP_SENTINEL_PID;
401e3c2d6aaSnw
402e8c27ec8Sbaban assert(q->rc != NULL);
403e3f2c991SKeyur Desai assert(q->domain == NULL || *q->domain == NULL);
404e8c27ec8Sbaban
4052b4a7802SBaban Kenkre if ((dn = ldap_get_dn(ld, res)) == NULL)
406c5c4113dSnw return;
407c5c4113dSnw
408e3f2c991SKeyur Desai bvalues = ldap_get_values_len(ld, res, OBJCLASS);
409e3f2c991SKeyur Desai if (bvalues == NULL) {
410e3f2c991SKeyur Desai /*
411e3f2c991SKeyur Desai * Didn't find objectclass. Something's wrong with our
412e3f2c991SKeyur Desai * AD data.
413e3f2c991SKeyur Desai */
414e3f2c991SKeyur Desai idmapdlog(LOG_ERR, "%s has no %s", dn, OBJCLASS);
415e3f2c991SKeyur Desai goto out;
416e8c27ec8Sbaban }
417e3f2c991SKeyur Desai ok = idmap_bv_objclass2sidtype(bvalues, &sid_type);
418e3f2c991SKeyur Desai ldap_value_free_len(bvalues);
419e3f2c991SKeyur Desai if (!ok) {
420c5c4113dSnw /*
421e3f2c991SKeyur Desai * Didn't understand objectclass. Something's wrong with our
422e3f2c991SKeyur Desai * AD data.
423c5c4113dSnw */
424e3f2c991SKeyur Desai idmapdlog(LOG_ERR, "%s has unexpected %s", dn, OBJCLASS);
425e3f2c991SKeyur Desai goto out;
426e3f2c991SKeyur Desai }
427e3f2c991SKeyur Desai
428e3f2c991SKeyur Desai if (state->directory_based_mapping == DIRECTORY_MAPPING_IDMU &&
429e3f2c991SKeyur Desai q->pid != NULL) {
430148c5f43SAlan Wright if (sid_type == IDMAP_USID)
431e3f2c991SKeyur Desai attr = UIDNUMBER;
432148c5f43SAlan Wright else if (sid_type == IDMAP_GSID)
433e3f2c991SKeyur Desai attr = GIDNUMBER;
434e3f2c991SKeyur Desai if (attr != NULL) {
4352b4a7802SBaban Kenkre bvalues = ldap_get_values_len(ld, res, attr);
4362b4a7802SBaban Kenkre if (bvalues != NULL) {
437e3f2c991SKeyur Desai value = adutils_bv_str(bvalues[0]);
438e3f2c991SKeyur Desai if (!adutils_bv_uint(bvalues[0], &pid)) {
439e3f2c991SKeyur Desai idmapdlog(LOG_ERR,
440e3f2c991SKeyur Desai "%s has Invalid %s value \"%s\"",
441e3f2c991SKeyur Desai dn, attr, value);
442e8c27ec8Sbaban }
443e3f2c991SKeyur Desai ldap_value_free_len(bvalues);
444e8c27ec8Sbaban }
445e3f2c991SKeyur Desai }
446e3f2c991SKeyur Desai }
447e3f2c991SKeyur Desai
448e3f2c991SKeyur Desai if (state->directory_based_mapping == DIRECTORY_MAPPING_NAME &&
449e3f2c991SKeyur Desai q->unixname != NULL) {
450e3f2c991SKeyur Desai /*
451e3f2c991SKeyur Desai * If the caller has requested unixname then determine the
452e3f2c991SKeyur Desai * AD attribute name that will have the unixname, and retrieve
453e3f2c991SKeyur Desai * its value.
454e3f2c991SKeyur Desai */
455148c5f43SAlan Wright idmap_id_type esidtype;
456e3f2c991SKeyur Desai /*
457148c5f43SAlan Wright * Determine the target type.
458e3f2c991SKeyur Desai *
459e3f2c991SKeyur Desai * If the caller specified one, use that. Otherwise, give the
460e3f2c991SKeyur Desai * same type that as we found for the Windows user.
461e3f2c991SKeyur Desai */
462148c5f43SAlan Wright esidtype = q->esidtype;
463148c5f43SAlan Wright if (esidtype == IDMAP_SID)
464148c5f43SAlan Wright esidtype = sid_type;
46548258c6bSjp
466148c5f43SAlan Wright if (esidtype == IDMAP_USID)
467e3f2c991SKeyur Desai attr = state->ad_unixuser_attr;
468148c5f43SAlan Wright else if (esidtype == IDMAP_GSID)
469e3f2c991SKeyur Desai attr = state->ad_unixgroup_attr;
470e3f2c991SKeyur Desai
471e3f2c991SKeyur Desai if (attr != NULL) {
4722b4a7802SBaban Kenkre bvalues = ldap_get_values_len(ld, res, attr);
4732b4a7802SBaban Kenkre if (bvalues != NULL) {
474e3f2c991SKeyur Desai unix_name = adutils_bv_str(bvalues[0]);
475e3f2c991SKeyur Desai ldap_value_free_len(bvalues);
476e3f2c991SKeyur Desai value = strdup(unix_name);
4772b4a7802SBaban Kenkre }
478c5c4113dSnw }
479e3f2c991SKeyur Desai }
480c5c4113dSnw
481e3f2c991SKeyur Desai bvalues = ldap_get_values_len(ld, res, SAN);
482e3f2c991SKeyur Desai if (bvalues != NULL) {
483e3f2c991SKeyur Desai san = adutils_bv_str(bvalues[0]);
484e3f2c991SKeyur Desai ldap_value_free_len(bvalues);
485c5c4113dSnw }
486c5c4113dSnw
487e3f2c991SKeyur Desai if (q->sid != NULL) {
488e3f2c991SKeyur Desai bvalues = ldap_get_values_len(ld, res, OBJSID);
489e3f2c991SKeyur Desai if (bvalues != NULL) {
490e3f2c991SKeyur Desai sid = adutils_bv_objsid2sidstr(bvalues[0], &rid);
491e3f2c991SKeyur Desai ldap_value_free_len(bvalues);
492e3f2c991SKeyur Desai }
493e8c27ec8Sbaban }
494e8c27ec8Sbaban
495e3f2c991SKeyur Desai idmap_setqresults(q, san, dn,
496e3f2c991SKeyur Desai attr, value,
497e3f2c991SKeyur Desai sid, rid, sid_type,
498e3f2c991SKeyur Desai unix_name, pid);
499c5c4113dSnw
500e3f2c991SKeyur Desai out:
501c5c4113dSnw ldap_memfree(dn);
502c5c4113dSnw }
503c5c4113dSnw
5042b4a7802SBaban Kenkre void
idmap_ldap_res_search_cb(LDAP * ld,LDAPMessage ** res,int rc,int qid,void * argp)5052b4a7802SBaban Kenkre idmap_ldap_res_search_cb(LDAP *ld, LDAPMessage **res, int rc, int qid,
506*49160520SToomas Soome void *argp)
507c5c4113dSnw {
5082b4a7802SBaban Kenkre idmap_query_state_t *state = (idmap_query_state_t *)argp;
5092b4a7802SBaban Kenkre idmap_q_t *q = &(state->queries[qid]);
510c5c4113dSnw
511c5c4113dSnw switch (rc) {
512c5c4113dSnw case LDAP_RES_SEARCH_RESULT:
5132b4a7802SBaban Kenkre if (q->search_res != NULL) {
5142b4a7802SBaban Kenkre idmap_extract_object(state, q, q->search_res, ld);
5152b4a7802SBaban Kenkre (void) ldap_msgfree(q->search_res);
5162b4a7802SBaban Kenkre q->search_res = NULL;
5172b4a7802SBaban Kenkre } else
5182b4a7802SBaban Kenkre q->ad_rc = ADUTILS_ERR_NOTFOUND;
519c5c4113dSnw break;
520c5c4113dSnw case LDAP_RES_SEARCH_ENTRY:
5212b4a7802SBaban Kenkre if (q->search_res == NULL) {
5222b4a7802SBaban Kenkre q->search_res = *res;
5232b4a7802SBaban Kenkre *res = NULL;
524c5c4113dSnw }
525c5c4113dSnw break;
526c5c4113dSnw default:
527c5c4113dSnw break;
528c5c4113dSnw }
52984decf41Sjp }
53084decf41Sjp
531e3c2d6aaSnw static
532e3c2d6aaSnw void
idmap_cleanup_batch(idmap_query_state_t * batch)533e3c2d6aaSnw idmap_cleanup_batch(idmap_query_state_t *batch)
534e3c2d6aaSnw {
535e3c2d6aaSnw int i;
536e3c2d6aaSnw
537e3c2d6aaSnw for (i = 0; i < batch->qcount; i++) {
538cd37da74Snw if (batch->queries[i].ecanonname != NULL)
539cd37da74Snw free(batch->queries[i].ecanonname);
540cd37da74Snw batch->queries[i].ecanonname = NULL;
541cd37da74Snw if (batch->queries[i].edomain != NULL)
542cd37da74Snw free(batch->queries[i].edomain);
543cd37da74Snw batch->queries[i].edomain = NULL;
544e3c2d6aaSnw }
545e3c2d6aaSnw }
546e3c2d6aaSnw
54784decf41Sjp /*
54884decf41Sjp * This routine frees the idmap_query_state_t structure
54984decf41Sjp */
550c5c4113dSnw void
idmap_lookup_release_batch(idmap_query_state_t ** state)55184decf41Sjp idmap_lookup_release_batch(idmap_query_state_t **state)
552c5c4113dSnw {
5532b4a7802SBaban Kenkre if (state == NULL || *state == NULL)
5542b4a7802SBaban Kenkre return;
5552b4a7802SBaban Kenkre adutils_lookup_batch_release(&(*state)->qs);
556e3c2d6aaSnw idmap_cleanup_batch(*state);
557e3f2c991SKeyur Desai free((*state)->default_domain);
558c5c4113dSnw free(*state);
559c5c4113dSnw *state = NULL;
560c5c4113dSnw }
561c5c4113dSnw
562c5c4113dSnw idmap_retcode
idmap_lookup_batch_end(idmap_query_state_t ** state)5630dcc7149Snw idmap_lookup_batch_end(idmap_query_state_t **state)
564c5c4113dSnw {
5652b4a7802SBaban Kenkre adutils_rc ad_rc;
5662b4a7802SBaban Kenkre int i;
5672b4a7802SBaban Kenkre idmap_query_state_t *id_qs = *state;
568c5c4113dSnw
5692b4a7802SBaban Kenkre ad_rc = adutils_lookup_batch_end(&id_qs->qs);
570c5c4113dSnw
5712b4a7802SBaban Kenkre /*
5722b4a7802SBaban Kenkre * Map adutils rc to idmap_retcode in each
5732b4a7802SBaban Kenkre * query because consumers in dbutils.c
5742b4a7802SBaban Kenkre * expects idmap_retcode.
5752b4a7802SBaban Kenkre */
5762b4a7802SBaban Kenkre for (i = 0; i < id_qs->qcount; i++) {
5772b4a7802SBaban Kenkre *id_qs->queries[i].rc =
5782b4a7802SBaban Kenkre map_adrc2idmaprc(id_qs->queries[i].ad_rc);
579c5c4113dSnw }
58084decf41Sjp idmap_lookup_release_batch(state);
5812b4a7802SBaban Kenkre return (map_adrc2idmaprc(ad_rc));
582c5c4113dSnw }
583c5c4113dSnw
584c5c4113dSnw /*
585c5c4113dSnw * Send one prepared search, queue up msgid, process what results are
586c5c4113dSnw * available
587c5c4113dSnw */
588c5c4113dSnw static
589c5c4113dSnw idmap_retcode
idmap_batch_add1(idmap_query_state_t * state,const char * filter,char * ecanonname,char * edomain,idmap_id_type esidtype,char ** dn,char ** attr,char ** value,char ** canonname,char ** dname,char ** sid,rid_t * rid,idmap_id_type * sid_type,char ** unixname,posix_id_t * pid,idmap_retcode * rc)59048258c6bSjp idmap_batch_add1(idmap_query_state_t *state, const char *filter,
591*49160520SToomas Soome char *ecanonname, char *edomain, idmap_id_type esidtype,
592*49160520SToomas Soome char **dn, char **attr, char **value,
593*49160520SToomas Soome char **canonname, char **dname,
594*49160520SToomas Soome char **sid, rid_t *rid, idmap_id_type *sid_type, char **unixname,
595*49160520SToomas Soome posix_id_t *pid,
596*49160520SToomas Soome idmap_retcode *rc)
597c5c4113dSnw {
5982b4a7802SBaban Kenkre adutils_rc ad_rc;
5992b4a7802SBaban Kenkre int qid, i;
600c5c4113dSnw idmap_q_t *q;
601e3f2c991SKeyur Desai char *attrs[20]; /* Plenty */
602c5c4113dSnw
6034d61c878SJulian Pullen qid = atomic_inc_32_nv(&state->qcount) - 1;
604c5c4113dSnw q = &(state->queries[qid]);
605c5c4113dSnw
6064d61c878SJulian Pullen assert(qid < state->qsize);
6074d61c878SJulian Pullen
608cd37da74Snw /*
6092b4a7802SBaban Kenkre * Remember the expected canonname, domainname and unix type
6102b4a7802SBaban Kenkre * so we can check the results * against it
611cd37da74Snw */
612cd37da74Snw q->ecanonname = ecanonname;
613cd37da74Snw q->edomain = edomain;
614148c5f43SAlan Wright q->esidtype = esidtype;
615e3c2d6aaSnw
616c5c4113dSnw /* Remember where to put the results */
617cd37da74Snw q->canonname = canonname;
618e8c27ec8Sbaban q->sid = sid;
619c5c4113dSnw q->domain = dname;
620c5c4113dSnw q->rid = rid;
621c5c4113dSnw q->sid_type = sid_type;
622c5c4113dSnw q->rc = rc;
623e8c27ec8Sbaban q->unixname = unixname;
62448258c6bSjp q->dn = dn;
62548258c6bSjp q->attr = attr;
62648258c6bSjp q->value = value;
627e3f2c991SKeyur Desai q->pid = pid;
628e3f2c991SKeyur Desai
629e3f2c991SKeyur Desai /* Add attributes that are not always needed */
630e3f2c991SKeyur Desai i = 0;
631e3f2c991SKeyur Desai attrs[i++] = SAN;
632e3f2c991SKeyur Desai attrs[i++] = OBJSID;
633e3f2c991SKeyur Desai attrs[i++] = OBJCLASS;
634e8c27ec8Sbaban
635e8c27ec8Sbaban if (unixname != NULL) {
636e3f2c991SKeyur Desai /* Add unixuser/unixgroup attribute names to the attrs list */
637148c5f43SAlan Wright if (esidtype != IDMAP_GSID &&
638e8c27ec8Sbaban state->ad_unixuser_attr != NULL)
639e8c27ec8Sbaban attrs[i++] = (char *)state->ad_unixuser_attr;
640148c5f43SAlan Wright if (esidtype != IDMAP_USID &&
641e8c27ec8Sbaban state->ad_unixgroup_attr != NULL)
642e3f2c991SKeyur Desai attrs[i++] = (char *)state->ad_unixgroup_attr;
643e8c27ec8Sbaban }
644c5c4113dSnw
645e3f2c991SKeyur Desai if (pid != NULL) {
646148c5f43SAlan Wright if (esidtype != IDMAP_GSID)
647e3f2c991SKeyur Desai attrs[i++] = UIDNUMBER;
648148c5f43SAlan Wright if (esidtype != IDMAP_USID)
649e3f2c991SKeyur Desai attrs[i++] = GIDNUMBER;
650e3f2c991SKeyur Desai }
651e3f2c991SKeyur Desai
652e3f2c991SKeyur Desai attrs[i] = NULL;
653e3f2c991SKeyur Desai
654c5c4113dSnw /*
655c5c4113dSnw * Provide sane defaults for the results in case we never hear
656c5c4113dSnw * back from the DS before closing the connection.
657e3c2d6aaSnw *
658e3c2d6aaSnw * In particular we default the result to indicate a retriable
659e3c2d6aaSnw * error. The first complete matching result entry will cause
660e3c2d6aaSnw * this to be set to IDMAP_SUCCESS, and the end of the results
661e3c2d6aaSnw * for this search will cause this to indicate "not found" if no
662e3c2d6aaSnw * result entries arrived or no complete ones matched the lookup
663e3c2d6aaSnw * we were doing.
664c5c4113dSnw */
665c5c4113dSnw *rc = IDMAP_ERR_RETRIABLE_NET_ERR;
666e8c27ec8Sbaban if (sid_type != NULL)
667148c5f43SAlan Wright *sid_type = IDMAP_SID;
668e8c27ec8Sbaban if (sid != NULL)
669e8c27ec8Sbaban *sid = NULL;
670c5c4113dSnw if (dname != NULL)
671c5c4113dSnw *dname = NULL;
672c5c4113dSnw if (rid != NULL)
673c5c4113dSnw *rid = 0;
67448258c6bSjp if (dn != NULL)
67548258c6bSjp *dn = NULL;
67648258c6bSjp if (attr != NULL)
67748258c6bSjp *attr = NULL;
67848258c6bSjp if (value != NULL)
67948258c6bSjp *value = NULL;
680c5c4113dSnw
681479ac375Sdm /*
682479ac375Sdm * Don't set *canonname to NULL because it may be pointing to the
683479ac375Sdm * given winname. Later on if we get a canonical name from AD the
684479ac375Sdm * old name if any will be freed before assigning the new name.
685479ac375Sdm */
686479ac375Sdm
687c5c4113dSnw /*
6882b4a7802SBaban Kenkre * Invoke the mother of all APIs i.e. the adutils API
689c5c4113dSnw */
6902b4a7802SBaban Kenkre ad_rc = adutils_lookup_batch_add(state->qs, filter,
6912b4a7802SBaban Kenkre (const char **)attrs,
6922b4a7802SBaban Kenkre edomain, &q->result, &q->ad_rc);
6932b4a7802SBaban Kenkre return (map_adrc2idmaprc(ad_rc));
694c5c4113dSnw }
695c5c4113dSnw
696c5c4113dSnw idmap_retcode
idmap_name2sid_batch_add1(idmap_query_state_t * state,const char * name,const char * dname,idmap_id_type esidtype,char ** dn,char ** attr,char ** value,char ** canonname,char ** sid,rid_t * rid,idmap_id_type * sid_type,char ** unixname,posix_id_t * pid,idmap_retcode * rc)697c5c4113dSnw idmap_name2sid_batch_add1(idmap_query_state_t *state,
698*49160520SToomas Soome const char *name, const char *dname, idmap_id_type esidtype,
699*49160520SToomas Soome char **dn, char **attr, char **value,
700*49160520SToomas Soome char **canonname, char **sid, rid_t *rid,
701*49160520SToomas Soome idmap_id_type *sid_type, char **unixname,
702*49160520SToomas Soome posix_id_t *pid, idmap_retcode *rc)
703c5c4113dSnw {
704c5c4113dSnw idmap_retcode retcode;
705e3f2c991SKeyur Desai char *filter, *s_name;
706cd37da74Snw char *ecanonname, *edomain; /* expected canonname */
707c5c4113dSnw
708c5c4113dSnw /*
709e3c2d6aaSnw * Strategy: search the global catalog for user/group by
710e3c2d6aaSnw * sAMAccountName = user/groupname with "" as the base DN and by
711e3c2d6aaSnw * userPrincipalName = user/groupname@domain. The result
712e3c2d6aaSnw * entries will be checked to conform to the name and domain
713e3c2d6aaSnw * name given here. The DN, sAMAccountName, userPrincipalName,
714e3c2d6aaSnw * objectSid and objectClass of the result entries are all we
715e3c2d6aaSnw * need to figure out which entries match the lookup, the SID of
716e3c2d6aaSnw * the user/group and whether it is a user or a group.
717c5c4113dSnw */
718c5c4113dSnw
719cd37da74Snw if ((ecanonname = strdup(name)) == NULL)
720cd37da74Snw return (IDMAP_ERR_MEMORY);
721cd37da74Snw
722d3a612caSnw if (dname == NULL || *dname == '\0') {
723e3f2c991SKeyur Desai /* 'name' not qualified and dname not given */
724e3f2c991SKeyur Desai dname = state->default_domain;
725e3f2c991SKeyur Desai edomain = strdup(dname);
726e3f2c991SKeyur Desai if (edomain == NULL) {
727e3f2c991SKeyur Desai free(ecanonname);
728e3f2c991SKeyur Desai return (IDMAP_ERR_MEMORY);
729c5c4113dSnw }
730cd37da74Snw } else {
731cd37da74Snw if ((edomain = strdup(dname)) == NULL) {
732cd37da74Snw free(ecanonname);
733e3c2d6aaSnw return (IDMAP_ERR_MEMORY);
734cd37da74Snw }
735e3c2d6aaSnw }
736c5c4113dSnw
7374d61c878SJulian Pullen if (!adutils_lookup_check_domain(state->qs, dname)) {
7384d61c878SJulian Pullen free(ecanonname);
7394d61c878SJulian Pullen free(edomain);
7404d61c878SJulian Pullen return (IDMAP_ERR_DOMAIN_NOTFOUND);
7414d61c878SJulian Pullen }
7424d61c878SJulian Pullen
743479ac375Sdm s_name = sanitize_for_ldap_filter(name);
744479ac375Sdm if (s_name == NULL) {
745479ac375Sdm free(ecanonname);
746479ac375Sdm free(edomain);
747479ac375Sdm return (IDMAP_ERR_MEMORY);
748479ac375Sdm }
749479ac375Sdm
750c5c4113dSnw /* Assemble filter */
751e3f2c991SKeyur Desai (void) asprintf(&filter, SANFILTER, s_name);
752e3f2c991SKeyur Desai if (s_name != name)
753e3f2c991SKeyur Desai free(s_name);
754e3f2c991SKeyur Desai if (filter == NULL) {
755cd37da74Snw free(ecanonname);
756479ac375Sdm free(edomain);
757c5c4113dSnw return (IDMAP_ERR_MEMORY);
758c5c4113dSnw }
759c5c4113dSnw
760cd37da74Snw retcode = idmap_batch_add1(state, filter, ecanonname, edomain,
761148c5f43SAlan Wright esidtype, dn, attr, value, canonname, NULL, sid, rid, sid_type,
762e3f2c991SKeyur Desai unixname, pid, rc);
763c5c4113dSnw
764c5c4113dSnw free(filter);
765c5c4113dSnw
766c5c4113dSnw return (retcode);
767c5c4113dSnw }
768c5c4113dSnw
769c5c4113dSnw idmap_retcode
idmap_sid2name_batch_add1(idmap_query_state_t * state,const char * sid,const rid_t * rid,idmap_id_type esidtype,char ** dn,char ** attr,char ** value,char ** name,char ** dname,idmap_id_type * sid_type,char ** unixname,posix_id_t * pid,idmap_retcode * rc)770c5c4113dSnw idmap_sid2name_batch_add1(idmap_query_state_t *state,
771*49160520SToomas Soome const char *sid, const rid_t *rid, idmap_id_type esidtype,
772*49160520SToomas Soome char **dn, char **attr, char **value,
773*49160520SToomas Soome char **name, char **dname, idmap_id_type *sid_type,
774*49160520SToomas Soome char **unixname, posix_id_t *pid, idmap_retcode *rc)
775c5c4113dSnw {
776c5c4113dSnw idmap_retcode retcode;
777e3f2c991SKeyur Desai int ret;
778e3f2c991SKeyur Desai char *filter;
7792b4a7802SBaban Kenkre char cbinsid[ADUTILS_MAXHEXBINSID + 1];
780c5c4113dSnw
781c5c4113dSnw /*
782c5c4113dSnw * Strategy: search [the global catalog] for user/group by
783c5c4113dSnw * objectSid = SID with empty base DN. The DN, sAMAccountName
784c5c4113dSnw * and objectClass of the result are all we need to figure out
785c5c4113dSnw * the name of the SID and whether it is a user, a group or a
786c5c4113dSnw * computer.
787c5c4113dSnw */
788c5c4113dSnw
7894d61c878SJulian Pullen if (!adutils_lookup_check_sid_prefix(state->qs, sid))
7904d61c878SJulian Pullen return (IDMAP_ERR_DOMAIN_NOTFOUND);
7914d61c878SJulian Pullen
7922b4a7802SBaban Kenkre ret = adutils_txtsid2hexbinsid(sid, rid, &cbinsid[0], sizeof (cbinsid));
793c5c4113dSnw if (ret != 0)
794c5c4113dSnw return (IDMAP_ERR_SID);
795c5c4113dSnw
796c5c4113dSnw /* Assemble filter */
797a01d29c9SMatt Barden (void) asprintf(&filter, OBJSIDFILTER, cbinsid, cbinsid);
798e3f2c991SKeyur Desai if (filter == NULL)
799c5c4113dSnw return (IDMAP_ERR_MEMORY);
800c5c4113dSnw
801148c5f43SAlan Wright retcode = idmap_batch_add1(state, filter, NULL, NULL, esidtype,
802e3f2c991SKeyur Desai dn, attr, value, name, dname, NULL, NULL, sid_type, unixname,
803e3f2c991SKeyur Desai pid, rc);
804e8c27ec8Sbaban
805e8c27ec8Sbaban free(filter);
806e8c27ec8Sbaban
807e8c27ec8Sbaban return (retcode);
808e8c27ec8Sbaban }
809e8c27ec8Sbaban
810e8c27ec8Sbaban idmap_retcode
idmap_unixname2sid_batch_add1(idmap_query_state_t * state,const char * unixname,int is_user,int is_wuser,char ** dn,char ** attr,char ** value,char ** sid,rid_t * rid,char ** name,char ** dname,idmap_id_type * sid_type,idmap_retcode * rc)811e8c27ec8Sbaban idmap_unixname2sid_batch_add1(idmap_query_state_t *state,
812*49160520SToomas Soome const char *unixname, int is_user, int is_wuser,
813*49160520SToomas Soome char **dn, char **attr, char **value,
814*49160520SToomas Soome char **sid, rid_t *rid, char **name,
815*49160520SToomas Soome char **dname, idmap_id_type *sid_type, idmap_retcode *rc)
816e8c27ec8Sbaban {
817e8c27ec8Sbaban idmap_retcode retcode;
818e3f2c991SKeyur Desai char *filter, *s_unixname;
819e3f2c991SKeyur Desai const char *attrname;
820e8c27ec8Sbaban
821e8c27ec8Sbaban /* Get unixuser or unixgroup AD attribute name */
822e8c27ec8Sbaban attrname = (is_user) ?
823e8c27ec8Sbaban state->ad_unixuser_attr : state->ad_unixgroup_attr;
824e8c27ec8Sbaban if (attrname == NULL)
825e8c27ec8Sbaban return (IDMAP_ERR_NOTFOUND);
826e8c27ec8Sbaban
827479ac375Sdm s_unixname = sanitize_for_ldap_filter(unixname);
828479ac375Sdm if (s_unixname == NULL)
829479ac375Sdm return (IDMAP_ERR_MEMORY);
830479ac375Sdm
831e8c27ec8Sbaban /* Assemble filter */
832e3f2c991SKeyur Desai (void) asprintf(&filter, "(&(objectclass=%s)(%s=%s))",
833e3f2c991SKeyur Desai is_wuser ? "user" : "group", attrname, s_unixname);
834479ac375Sdm if (s_unixname != unixname)
835479ac375Sdm free(s_unixname);
836e3f2c991SKeyur Desai if (filter == NULL) {
837e3f2c991SKeyur Desai return (IDMAP_ERR_MEMORY);
838e3f2c991SKeyur Desai }
839e8c27ec8Sbaban
840e8c27ec8Sbaban retcode = idmap_batch_add1(state, filter, NULL, NULL,
841148c5f43SAlan Wright IDMAP_POSIXID, dn, NULL, NULL, name, dname, sid, rid, sid_type,
842e3f2c991SKeyur Desai NULL, NULL, rc);
84348258c6bSjp
84448258c6bSjp if (retcode == IDMAP_SUCCESS && attr != NULL) {
84548258c6bSjp if ((*attr = strdup(attrname)) == NULL)
84648258c6bSjp retcode = IDMAP_ERR_MEMORY;
84748258c6bSjp }
84848258c6bSjp
84948258c6bSjp if (retcode == IDMAP_SUCCESS && value != NULL) {
850e3f2c991SKeyur Desai if ((*value = strdup(unixname)) == NULL)
851e3f2c991SKeyur Desai retcode = IDMAP_ERR_MEMORY;
852e3f2c991SKeyur Desai }
853e3f2c991SKeyur Desai
854e3f2c991SKeyur Desai free(filter);
855e3f2c991SKeyur Desai
856e3f2c991SKeyur Desai return (retcode);
857e3f2c991SKeyur Desai }
858e3f2c991SKeyur Desai
859e3f2c991SKeyur Desai idmap_retcode
idmap_pid2sid_batch_add1(idmap_query_state_t * state,posix_id_t pid,int is_user,char ** dn,char ** attr,char ** value,char ** sid,rid_t * rid,char ** name,char ** dname,idmap_id_type * sid_type,idmap_retcode * rc)860e3f2c991SKeyur Desai idmap_pid2sid_batch_add1(idmap_query_state_t *state,
861*49160520SToomas Soome posix_id_t pid, int is_user,
862*49160520SToomas Soome char **dn, char **attr, char **value,
863*49160520SToomas Soome char **sid, rid_t *rid, char **name,
864*49160520SToomas Soome char **dname, idmap_id_type *sid_type, idmap_retcode *rc)
865e3f2c991SKeyur Desai {
866e3f2c991SKeyur Desai idmap_retcode retcode;
867e3f2c991SKeyur Desai char *filter;
868e3f2c991SKeyur Desai const char *attrname;
869e3f2c991SKeyur Desai
870e3f2c991SKeyur Desai /* Assemble filter */
871e3f2c991SKeyur Desai if (is_user) {
872e3f2c991SKeyur Desai (void) asprintf(&filter, UIDNUMBERFILTER, pid);
873e3f2c991SKeyur Desai attrname = UIDNUMBER;
874e3f2c991SKeyur Desai } else {
875e3f2c991SKeyur Desai (void) asprintf(&filter, GIDNUMBERFILTER, pid);
876e3f2c991SKeyur Desai attrname = GIDNUMBER;
877e3f2c991SKeyur Desai }
878e3f2c991SKeyur Desai if (filter == NULL)
879e3f2c991SKeyur Desai return (IDMAP_ERR_MEMORY);
880e3f2c991SKeyur Desai
881e3f2c991SKeyur Desai retcode = idmap_batch_add1(state, filter, NULL, NULL,
882148c5f43SAlan Wright IDMAP_POSIXID, dn, NULL, NULL, name, dname, sid, rid, sid_type,
883e3f2c991SKeyur Desai NULL, NULL, rc);
884e3f2c991SKeyur Desai
885e3f2c991SKeyur Desai if (retcode == IDMAP_SUCCESS && attr != NULL) {
886e3f2c991SKeyur Desai if ((*attr = strdup(attrname)) == NULL)
887e3f2c991SKeyur Desai retcode = IDMAP_ERR_MEMORY;
888e3f2c991SKeyur Desai }
889e3f2c991SKeyur Desai
890e3f2c991SKeyur Desai if (retcode == IDMAP_SUCCESS && value != NULL) {
891e3f2c991SKeyur Desai (void) asprintf(value, "%u", pid);
892e3f2c991SKeyur Desai if (*value == NULL)
893e3f2c991SKeyur Desai retcode = IDMAP_ERR_MEMORY;
89448258c6bSjp }
895c5c4113dSnw
896c5c4113dSnw free(filter);
897c5c4113dSnw
898c5c4113dSnw return (retcode);
899c5c4113dSnw }
900