14520Snw141292 /*
24520Snw141292 * CDDL HEADER START
34520Snw141292 *
44520Snw141292 * The contents of this file are subject to the terms of the
54520Snw141292 * Common Development and Distribution License (the "License").
64520Snw141292 * You may not use this file except in compliance with the License.
74520Snw141292 *
84520Snw141292 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94520Snw141292 * or http://www.opensolaris.org/os/licensing.
104520Snw141292 * See the License for the specific language governing permissions
114520Snw141292 * and limitations under the License.
124520Snw141292 *
134520Snw141292 * When distributing Covered Code, include this CDDL HEADER in each
144520Snw141292 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154520Snw141292 * If applicable, add the following below this CDDL HEADER, with the
164520Snw141292 * fields enclosed by brackets "[]" replaced with your own identifying
174520Snw141292 * information: Portions Copyright [yyyy] [name of copyright owner]
184520Snw141292 *
194520Snw141292 * CDDL HEADER END
204520Snw141292 */
214520Snw141292
224520Snw141292 /*
23*12508Samw@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
244520Snw141292 */
254520Snw141292
264520Snw141292 /*
274520Snw141292 * Processes name2sid & sid2name batched lookups for a given user or
284520Snw141292 * computer from an AD Directory server using GSSAPI authentication
294520Snw141292 */
304520Snw141292
314520Snw141292 #include <stdio.h>
324520Snw141292 #include <stdlib.h>
334520Snw141292 #include <alloca.h>
344520Snw141292 #include <string.h>
354520Snw141292 #include <strings.h>
364520Snw141292 #include <lber.h>
374520Snw141292 #include <ldap.h>
384520Snw141292 #include <sasl/sasl.h>
394520Snw141292 #include <string.h>
404520Snw141292 #include <ctype.h>
414520Snw141292 #include <pthread.h>
424520Snw141292 #include <synch.h>
434520Snw141292 #include <atomic.h>
444520Snw141292 #include <errno.h>
454520Snw141292 #include <assert.h>
464520Snw141292 #include <limits.h>
478040SBaban.Kenkre@Sun.COM #include <time.h>
485696Snw141292 #include <sys/u8_textprep.h>
498040SBaban.Kenkre@Sun.COM #include "libadutils.h"
506616Sdm199847 #include "nldaputils.h"
514520Snw141292 #include "idmapd.h"
524520Snw141292
534520Snw141292 /* Attribute names and filter format strings */
545447Snw141292 #define SAN "sAMAccountName"
555447Snw141292 #define OBJSID "objectSid"
565447Snw141292 #define OBJCLASS "objectClass"
5710504SKeyur.Desai@Sun.COM #define UIDNUMBER "uidNumber"
5810504SKeyur.Desai@Sun.COM #define GIDNUMBER "gidNumber"
5910504SKeyur.Desai@Sun.COM #define UIDNUMBERFILTER "(&(objectclass=user)(uidNumber=%u))"
6010504SKeyur.Desai@Sun.COM #define GIDNUMBERFILTER "(&(objectclass=group)(gidNumber=%u))"
6110504SKeyur.Desai@Sun.COM #define SANFILTER "(sAMAccountName=%s)"
625447Snw141292 #define OBJSIDFILTER "(objectSid=%s)"
634520Snw141292
648040SBaban.Kenkre@Sun.COM void idmap_ldap_res_search_cb(LDAP *ld, LDAPMessage **res, int rc,
658040SBaban.Kenkre@Sun.COM int qid, void *argp);
664520Snw141292
674520Snw141292 /*
684520Snw141292 * A place to put the results of a batched (async) query
694520Snw141292 *
704520Snw141292 * There is one of these for every query added to a batch object
714520Snw141292 * (idmap_query_state, see below).
724520Snw141292 */
734520Snw141292 typedef struct idmap_q {
745447Snw141292 /*
755447Snw141292 * data used for validating search result entries for name->SID
765731Sbaban * lookups
775447Snw141292 */
785696Snw141292 char *ecanonname; /* expected canon name */
795696Snw141292 char *edomain; /* expected domain name */
80*12508Samw@Sun.COM idmap_id_type esidtype; /* expected SID type */
815447Snw141292 /* results */
825696Snw141292 char **canonname; /* actual canon name */
834520Snw141292 char **domain; /* name of domain of object */
845731Sbaban char **sid; /* stringified SID */
855731Sbaban rid_t *rid; /* RID */
86*12508Samw@Sun.COM idmap_id_type *sid_type; /* user or group SID? */
875731Sbaban char **unixname; /* unixname for name mapping */
886386Sjp151216 char **dn; /* DN of entry */
896386Sjp151216 char **attr; /* Attr for name mapping */
906386Sjp151216 char **value; /* value for name mapping */
9110504SKeyur.Desai@Sun.COM posix_id_t *pid; /* Posix ID found via IDMU */
924520Snw141292 idmap_retcode *rc;
938040SBaban.Kenkre@Sun.COM adutils_rc ad_rc;
948040SBaban.Kenkre@Sun.COM adutils_result_t *result;
955447Snw141292
966531Sjp151216 /*
976531Sjp151216 * The LDAP search entry result is placed here to be processed
986531Sjp151216 * when the search done result is received.
996531Sjp151216 */
1006531Sjp151216 LDAPMessage *search_res; /* The LDAP search result */
1014520Snw141292 } idmap_q_t;
1024520Snw141292
1034520Snw141292 /* Batch context structure; typedef is in header file */
1044520Snw141292 struct idmap_query_state {
1058040SBaban.Kenkre@Sun.COM adutils_query_state_t *qs;
1068361SJulian.Pullen@Sun.COM int qsize; /* Queue size */
1078361SJulian.Pullen@Sun.COM uint32_t qcount; /* Number of queued requests */
1085731Sbaban const char *ad_unixuser_attr;
1095731Sbaban const char *ad_unixgroup_attr;
11010504SKeyur.Desai@Sun.COM int directory_based_mapping; /* enum */
11110504SKeyur.Desai@Sun.COM char *default_domain;
1124520Snw141292 idmap_q_t queries[1]; /* array of query results */
1134520Snw141292 };
1144520Snw141292
1154644Sbaban static pthread_t reaperid = 0;
1164520Snw141292
1174520Snw141292 /*
1184520Snw141292 * Keep connection management simple for now, extend or replace later
1194520Snw141292 * with updated libsldap code.
1204520Snw141292 */
1214520Snw141292 #define ADREAPERSLEEP 60
1224520Snw141292
1234520Snw141292 /*
1244520Snw141292 * Idle connection reaping side of connection management
1254520Snw141292 *
1264520Snw141292 * Every minute wake up and look for connections that have been idle for
1274520Snw141292 * five minutes or more and close them.
1284520Snw141292 */
1294520Snw141292 /*ARGSUSED*/
1304520Snw141292 static
1314520Snw141292 void
adreaper(void * arg)1324520Snw141292 adreaper(void *arg)
1334520Snw141292 {
1344520Snw141292 timespec_t ts;
1354520Snw141292
1364520Snw141292 ts.tv_sec = ADREAPERSLEEP;
1374520Snw141292 ts.tv_nsec = 0;
1384520Snw141292
1394520Snw141292 for (;;) {
1404520Snw141292 /*
1414520Snw141292 * nanosleep(3RT) is thead-safe (no SIGALRM) and more
1424520Snw141292 * portable than usleep(3C)
1434520Snw141292 */
1444520Snw141292 (void) nanosleep(&ts, NULL);
1458040SBaban.Kenkre@Sun.COM adutils_reap_idle_connections();
1464520Snw141292 }
1474520Snw141292 }
1484520Snw141292
1494520Snw141292 /*
1504520Snw141292 * Take ad_host_config_t information, create a ad_host_t,
1514520Snw141292 * populate it and add it to the list of hosts.
1524520Snw141292 */
1534520Snw141292
1544520Snw141292 int
idmap_add_ds(adutils_ad_t * ad,const char * host,int port)1558040SBaban.Kenkre@Sun.COM idmap_add_ds(adutils_ad_t *ad, const char *host, int port)
1564520Snw141292 {
1578040SBaban.Kenkre@Sun.COM int ret = -1;
1584520Snw141292
1598040SBaban.Kenkre@Sun.COM if (adutils_add_ds(ad, host, port) == ADUTILS_SUCCESS)
1608040SBaban.Kenkre@Sun.COM ret = 0;
1614520Snw141292
1624520Snw141292 /* Start reaper if it doesn't exist */
1638040SBaban.Kenkre@Sun.COM if (ret == 0 && reaperid == 0)
1644520Snw141292 (void) pthread_create(&reaperid, NULL,
1654520Snw141292 (void *(*)(void *))adreaper, (void *)NULL);
1664520Snw141292 return (ret);
1674520Snw141292 }
1684520Snw141292
1694520Snw141292 static
1708040SBaban.Kenkre@Sun.COM idmap_retcode
map_adrc2idmaprc(adutils_rc adrc)1718040SBaban.Kenkre@Sun.COM map_adrc2idmaprc(adutils_rc adrc)
1724520Snw141292 {
1738040SBaban.Kenkre@Sun.COM switch (adrc) {
1748040SBaban.Kenkre@Sun.COM case ADUTILS_SUCCESS:
1758040SBaban.Kenkre@Sun.COM return (IDMAP_SUCCESS);
1768040SBaban.Kenkre@Sun.COM case ADUTILS_ERR_NOTFOUND:
1778040SBaban.Kenkre@Sun.COM return (IDMAP_ERR_NOTFOUND);
1788040SBaban.Kenkre@Sun.COM case ADUTILS_ERR_MEMORY:
1798040SBaban.Kenkre@Sun.COM return (IDMAP_ERR_MEMORY);
1808040SBaban.Kenkre@Sun.COM case ADUTILS_ERR_DOMAIN:
1818040SBaban.Kenkre@Sun.COM return (IDMAP_ERR_DOMAIN);
1828040SBaban.Kenkre@Sun.COM case ADUTILS_ERR_OTHER:
1838040SBaban.Kenkre@Sun.COM return (IDMAP_ERR_OTHER);
1848040SBaban.Kenkre@Sun.COM case ADUTILS_ERR_RETRIABLE_NET_ERR:
1858040SBaban.Kenkre@Sun.COM return (IDMAP_ERR_RETRIABLE_NET_ERR);
1868040SBaban.Kenkre@Sun.COM default:
1878040SBaban.Kenkre@Sun.COM return (IDMAP_ERR_INTERNAL);
1884520Snw141292 }
1898040SBaban.Kenkre@Sun.COM /* NOTREACHED */
1904520Snw141292 }
1914520Snw141292
1928040SBaban.Kenkre@Sun.COM 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)1938040SBaban.Kenkre@Sun.COM idmap_lookup_batch_start(adutils_ad_t *ad, int nqueries,
19410504SKeyur.Desai@Sun.COM int directory_based_mapping, const char *default_domain,
1958040SBaban.Kenkre@Sun.COM idmap_query_state_t **state)
1964520Snw141292 {
1978040SBaban.Kenkre@Sun.COM idmap_query_state_t *new_state;
1988040SBaban.Kenkre@Sun.COM adutils_rc rc;
1994520Snw141292
2004520Snw141292 *state = NULL;
2014520Snw141292
2028361SJulian.Pullen@Sun.COM assert(ad != NULL);
2034520Snw141292
2044520Snw141292 new_state = calloc(1, sizeof (idmap_query_state_t) +
2054520Snw141292 (nqueries - 1) * sizeof (idmap_q_t));
2064520Snw141292 if (new_state == NULL)
2074520Snw141292 return (IDMAP_ERR_MEMORY);
2084520Snw141292
2098040SBaban.Kenkre@Sun.COM if ((rc = adutils_lookup_batch_start(ad, nqueries,
2108040SBaban.Kenkre@Sun.COM idmap_ldap_res_search_cb, new_state, &new_state->qs))
2118040SBaban.Kenkre@Sun.COM != ADUTILS_SUCCESS) {
21210504SKeyur.Desai@Sun.COM idmap_lookup_release_batch(&new_state);
2138040SBaban.Kenkre@Sun.COM return (map_adrc2idmaprc(rc));
2148040SBaban.Kenkre@Sun.COM }
2154520Snw141292
21610504SKeyur.Desai@Sun.COM new_state->default_domain = strdup(default_domain);
21710504SKeyur.Desai@Sun.COM if (new_state->default_domain == NULL) {
21810504SKeyur.Desai@Sun.COM idmap_lookup_release_batch(&new_state);
21910504SKeyur.Desai@Sun.COM return (IDMAP_ERR_MEMORY);
22010504SKeyur.Desai@Sun.COM }
22110504SKeyur.Desai@Sun.COM
22210504SKeyur.Desai@Sun.COM new_state->directory_based_mapping = directory_based_mapping;
2238361SJulian.Pullen@Sun.COM new_state->qsize = nqueries;
2244520Snw141292 *state = new_state;
2254520Snw141292 return (IDMAP_SUCCESS);
2264520Snw141292 }
2274520Snw141292
2284520Snw141292 /*
2295731Sbaban * Set unixuser_attr and unixgroup_attr for AD-based name mapping
2305731Sbaban */
2315731Sbaban void
idmap_lookup_batch_set_unixattr(idmap_query_state_t * state,const char * unixuser_attr,const char * unixgroup_attr)2325731Sbaban idmap_lookup_batch_set_unixattr(idmap_query_state_t *state,
2335908Sjp151216 const char *unixuser_attr, const char *unixgroup_attr)
2345908Sjp151216 {
2355731Sbaban state->ad_unixuser_attr = unixuser_attr;
2365731Sbaban state->ad_unixgroup_attr = unixgroup_attr;
2375731Sbaban }
2385731Sbaban
2395731Sbaban /*
2405696Snw141292 * Take parsed attribute values from a search result entry and check if
2415696Snw141292 * it is the result that was desired and, if so, set the result fields
2425696Snw141292 * of the given idmap_q_t.
2435696Snw141292 *
24410504SKeyur.Desai@Sun.COM * Except for dn and attr, all strings are consumed, either by transferring
24510504SKeyur.Desai@Sun.COM * them over into the request results (where the caller will eventually free
24610504SKeyur.Desai@Sun.COM * them) or by freeing them here. Note that this aligns with the "const"
24710504SKeyur.Desai@Sun.COM * declarations below.
2484520Snw141292 */
2494520Snw141292 static
2505696Snw141292 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)25110504SKeyur.Desai@Sun.COM idmap_setqresults(
25210504SKeyur.Desai@Sun.COM idmap_q_t *q,
25310504SKeyur.Desai@Sun.COM char *san,
25410504SKeyur.Desai@Sun.COM const char *dn,
25510504SKeyur.Desai@Sun.COM const char *attr,
25610504SKeyur.Desai@Sun.COM char *value,
25710504SKeyur.Desai@Sun.COM char *sid,
25810504SKeyur.Desai@Sun.COM rid_t rid,
25910504SKeyur.Desai@Sun.COM int sid_type,
26010504SKeyur.Desai@Sun.COM char *unixname,
26110504SKeyur.Desai@Sun.COM posix_id_t pid)
2624520Snw141292 {
2635696Snw141292 char *domain;
26410122SJordan.Brown@Sun.COM int err1;
2655696Snw141292
2665696Snw141292 assert(dn != NULL);
2675696Snw141292
2688040SBaban.Kenkre@Sun.COM if ((domain = adutils_dn2dns(dn)) == NULL)
2695696Snw141292 goto out;
2705696Snw141292
2715731Sbaban if (q->ecanonname != NULL && san != NULL) {
2725731Sbaban /* Check that this is the canonname that we were looking for */
2735696Snw141292 if (u8_strcmp(q->ecanonname, san, 0,
2745696Snw141292 U8_STRCMP_CI_LOWER, /* no normalization, for now */
2755731Sbaban U8_UNICODE_LATEST, &err1) != 0 || err1 != 0)
2765731Sbaban goto out;
2775731Sbaban }
2785731Sbaban
2795731Sbaban if (q->edomain != NULL) {
2805731Sbaban /* Check that this is the domain that we were looking for */
28110122SJordan.Brown@Sun.COM if (!domain_eq(q->edomain, domain))
2825696Snw141292 goto out;
2835696Snw141292 }
2845696Snw141292
2856386Sjp151216 /* Copy the DN and attr and value */
2866386Sjp151216 if (q->dn != NULL)
2876386Sjp151216 *q->dn = strdup(dn);
2886386Sjp151216
2896386Sjp151216 if (q->attr != NULL && attr != NULL)
2906386Sjp151216 *q->attr = strdup(attr);
2916386Sjp151216
29210504SKeyur.Desai@Sun.COM if (q->value != NULL && value != NULL) {
29310504SKeyur.Desai@Sun.COM *q->value = value;
29410504SKeyur.Desai@Sun.COM value = NULL;
29510504SKeyur.Desai@Sun.COM }
2966386Sjp151216
2975731Sbaban /* Set results */
2985731Sbaban if (q->sid) {
2995731Sbaban *q->sid = sid;
3005731Sbaban sid = NULL;
3015731Sbaban }
3025731Sbaban if (q->rid)
3035731Sbaban *q->rid = rid;
3045731Sbaban if (q->sid_type)
3055731Sbaban *q->sid_type = sid_type;
3065731Sbaban if (q->unixname) {
3075731Sbaban *q->unixname = unixname;
3085731Sbaban unixname = NULL;
3095731Sbaban }
3105731Sbaban if (q->domain != NULL) {
3115731Sbaban *q->domain = domain;
3125731Sbaban domain = NULL;
3135731Sbaban }
3145731Sbaban if (q->canonname != NULL) {
3156616Sdm199847 /*
3166616Sdm199847 * The caller may be replacing the given winname by its
3176616Sdm199847 * canonical name and therefore free any old name before
3186616Sdm199847 * overwriting the field by the canonical name.
3196616Sdm199847 */
3206616Sdm199847 free(*q->canonname);
3215731Sbaban *q->canonname = san;
3225731Sbaban san = NULL;
3235731Sbaban }
3245731Sbaban
32511963SAfshin.Ardakani@Sun.COM if (q->pid != NULL && pid != IDMAP_SENTINEL_PID) {
32610504SKeyur.Desai@Sun.COM *q->pid = pid;
32710504SKeyur.Desai@Sun.COM }
32810504SKeyur.Desai@Sun.COM
3298040SBaban.Kenkre@Sun.COM q->ad_rc = ADUTILS_SUCCESS;
3305696Snw141292
3315696Snw141292 out:
3325696Snw141292 /* Free unused attribute values */
3335696Snw141292 free(san);
3345696Snw141292 free(sid);
3355696Snw141292 free(domain);
3365731Sbaban free(unixname);
33710504SKeyur.Desai@Sun.COM free(value);
3384520Snw141292 }
3394520Snw141292
3404520Snw141292 #define BVAL_CASEEQ(bv, str) \
3414520Snw141292 (((*(bv))->bv_len == (sizeof (str) - 1)) && \
3424520Snw141292 strncasecmp((*(bv))->bv_val, str, (*(bv))->bv_len) == 0)
3434520Snw141292
3444520Snw141292 /*
3455696Snw141292 * Extract the class of the result entry. Returns 1 on success, 0 on
3465696Snw141292 * failure.
3474520Snw141292 */
3484520Snw141292 static
3495447Snw141292 int
idmap_bv_objclass2sidtype(BerValue ** bvalues,int * sid_type)3505696Snw141292 idmap_bv_objclass2sidtype(BerValue **bvalues, int *sid_type)
3514520Snw141292 {
3524520Snw141292 BerValue **cbval;
3534520Snw141292
354*12508Samw@Sun.COM *sid_type = IDMAP_SID;
3554520Snw141292 if (bvalues == NULL)
3565447Snw141292 return (0);
3574520Snw141292
3585696Snw141292 /*
35910504SKeyur.Desai@Sun.COM * We consider Computer to be a subclass of User, so we can just
36010504SKeyur.Desai@Sun.COM * ignore Computer entries and pay attention to the accompanying
36110504SKeyur.Desai@Sun.COM * User entries.
3625696Snw141292 */
3634520Snw141292 for (cbval = bvalues; *cbval != NULL; cbval++) {
36410504SKeyur.Desai@Sun.COM if (BVAL_CASEEQ(cbval, "group")) {
365*12508Samw@Sun.COM *sid_type = IDMAP_GSID;
3665696Snw141292 break;
36710504SKeyur.Desai@Sun.COM } else if (BVAL_CASEEQ(cbval, "user")) {
368*12508Samw@Sun.COM *sid_type = IDMAP_USID;
36910504SKeyur.Desai@Sun.COM break;
3705696Snw141292 }
3715696Snw141292 /*
372*12508Samw@Sun.COM * "else if (*sid_type = IDMAP_USID)" then this is a
3735696Snw141292 * new sub-class of user -- what to do with it??
3745696Snw141292 */
3754520Snw141292 }
3765447Snw141292
3775447Snw141292 return (1);
3784520Snw141292 }
3794520Snw141292
3804520Snw141292 /*
3814520Snw141292 * Handle a given search result entry
3824520Snw141292 */
3834520Snw141292 static
3844520Snw141292 void
idmap_extract_object(idmap_query_state_t * state,idmap_q_t * q,LDAPMessage * res,LDAP * ld)3858040SBaban.Kenkre@Sun.COM idmap_extract_object(idmap_query_state_t *state, idmap_q_t *q,
3868040SBaban.Kenkre@Sun.COM LDAPMessage *res, LDAP *ld)
3874520Snw141292 {
3884520Snw141292 BerValue **bvalues;
38910504SKeyur.Desai@Sun.COM const char *attr = NULL;
39010504SKeyur.Desai@Sun.COM char *value = NULL;
39110504SKeyur.Desai@Sun.COM char *unix_name = NULL;
39210504SKeyur.Desai@Sun.COM char *dn;
3935696Snw141292 char *san = NULL;
3945696Snw141292 char *sid = NULL;
3955696Snw141292 rid_t rid = 0;
39610504SKeyur.Desai@Sun.COM int sid_type;
39710504SKeyur.Desai@Sun.COM int ok;
39811963SAfshin.Ardakani@Sun.COM posix_id_t pid = IDMAP_SENTINEL_PID;
3995447Snw141292
4005731Sbaban assert(q->rc != NULL);
40110504SKeyur.Desai@Sun.COM assert(q->domain == NULL || *q->domain == NULL);
4025731Sbaban
4038040SBaban.Kenkre@Sun.COM if ((dn = ldap_get_dn(ld, res)) == NULL)
4044520Snw141292 return;
4054520Snw141292
40610504SKeyur.Desai@Sun.COM bvalues = ldap_get_values_len(ld, res, OBJCLASS);
40710504SKeyur.Desai@Sun.COM if (bvalues == NULL) {
4085731Sbaban /*
4095731Sbaban * Didn't find objectclass. Something's wrong with our
4105731Sbaban * AD data.
4115731Sbaban */
41210504SKeyur.Desai@Sun.COM idmapdlog(LOG_ERR, "%s has no %s", dn, OBJCLASS);
41310504SKeyur.Desai@Sun.COM goto out;
41410504SKeyur.Desai@Sun.COM }
41510504SKeyur.Desai@Sun.COM ok = idmap_bv_objclass2sidtype(bvalues, &sid_type);
41610504SKeyur.Desai@Sun.COM ldap_value_free_len(bvalues);
41710504SKeyur.Desai@Sun.COM if (!ok) {
4185731Sbaban /*
41910504SKeyur.Desai@Sun.COM * Didn't understand objectclass. Something's wrong with our
42010504SKeyur.Desai@Sun.COM * AD data.
4215731Sbaban */
42210504SKeyur.Desai@Sun.COM idmapdlog(LOG_ERR, "%s has unexpected %s", dn, OBJCLASS);
42310504SKeyur.Desai@Sun.COM goto out;
42410504SKeyur.Desai@Sun.COM }
42510504SKeyur.Desai@Sun.COM
42610504SKeyur.Desai@Sun.COM if (state->directory_based_mapping == DIRECTORY_MAPPING_IDMU &&
42710504SKeyur.Desai@Sun.COM q->pid != NULL) {
428*12508Samw@Sun.COM if (sid_type == IDMAP_USID)
42910504SKeyur.Desai@Sun.COM attr = UIDNUMBER;
430*12508Samw@Sun.COM else if (sid_type == IDMAP_GSID)
43110504SKeyur.Desai@Sun.COM attr = GIDNUMBER;
43210504SKeyur.Desai@Sun.COM if (attr != NULL) {
43310504SKeyur.Desai@Sun.COM bvalues = ldap_get_values_len(ld, res, attr);
43410504SKeyur.Desai@Sun.COM if (bvalues != NULL) {
43510504SKeyur.Desai@Sun.COM value = adutils_bv_str(bvalues[0]);
43610504SKeyur.Desai@Sun.COM if (!adutils_bv_uint(bvalues[0], &pid)) {
43710504SKeyur.Desai@Sun.COM idmapdlog(LOG_ERR,
43810504SKeyur.Desai@Sun.COM "%s has Invalid %s value \"%s\"",
43910504SKeyur.Desai@Sun.COM dn, attr, value);
44010504SKeyur.Desai@Sun.COM }
44110504SKeyur.Desai@Sun.COM ldap_value_free_len(bvalues);
44210504SKeyur.Desai@Sun.COM }
44310504SKeyur.Desai@Sun.COM }
4445731Sbaban }
4455731Sbaban
44610504SKeyur.Desai@Sun.COM if (state->directory_based_mapping == DIRECTORY_MAPPING_NAME &&
44710504SKeyur.Desai@Sun.COM q->unixname != NULL) {
44810504SKeyur.Desai@Sun.COM /*
44910504SKeyur.Desai@Sun.COM * If the caller has requested unixname then determine the
45010504SKeyur.Desai@Sun.COM * AD attribute name that will have the unixname, and retrieve
45110504SKeyur.Desai@Sun.COM * its value.
45210504SKeyur.Desai@Sun.COM */
453*12508Samw@Sun.COM idmap_id_type esidtype;
45410504SKeyur.Desai@Sun.COM /*
455*12508Samw@Sun.COM * Determine the target type.
45610504SKeyur.Desai@Sun.COM *
45710504SKeyur.Desai@Sun.COM * If the caller specified one, use that. Otherwise, give the
45810504SKeyur.Desai@Sun.COM * same type that as we found for the Windows user.
45910504SKeyur.Desai@Sun.COM */
460*12508Samw@Sun.COM esidtype = q->esidtype;
461*12508Samw@Sun.COM if (esidtype == IDMAP_SID)
462*12508Samw@Sun.COM esidtype = sid_type;
46310504SKeyur.Desai@Sun.COM
464*12508Samw@Sun.COM if (esidtype == IDMAP_USID)
46510504SKeyur.Desai@Sun.COM attr = state->ad_unixuser_attr;
466*12508Samw@Sun.COM else if (esidtype == IDMAP_GSID)
46710504SKeyur.Desai@Sun.COM attr = state->ad_unixgroup_attr;
4684520Snw141292
46910504SKeyur.Desai@Sun.COM if (attr != NULL) {
47010504SKeyur.Desai@Sun.COM bvalues = ldap_get_values_len(ld, res, attr);
47110504SKeyur.Desai@Sun.COM if (bvalues != NULL) {
47210504SKeyur.Desai@Sun.COM unix_name = adutils_bv_str(bvalues[0]);
47310504SKeyur.Desai@Sun.COM ldap_value_free_len(bvalues);
47410504SKeyur.Desai@Sun.COM value = strdup(unix_name);
47510504SKeyur.Desai@Sun.COM }
47610504SKeyur.Desai@Sun.COM }
47710504SKeyur.Desai@Sun.COM }
47810504SKeyur.Desai@Sun.COM
47910504SKeyur.Desai@Sun.COM bvalues = ldap_get_values_len(ld, res, SAN);
48010504SKeyur.Desai@Sun.COM if (bvalues != NULL) {
48110504SKeyur.Desai@Sun.COM san = adutils_bv_str(bvalues[0]);
48210504SKeyur.Desai@Sun.COM ldap_value_free_len(bvalues);
48310504SKeyur.Desai@Sun.COM }
48410504SKeyur.Desai@Sun.COM
48510504SKeyur.Desai@Sun.COM if (q->sid != NULL) {
48610504SKeyur.Desai@Sun.COM bvalues = ldap_get_values_len(ld, res, OBJSID);
48710504SKeyur.Desai@Sun.COM if (bvalues != NULL) {
48810504SKeyur.Desai@Sun.COM sid = adutils_bv_objsid2sidstr(bvalues[0], &rid);
48910504SKeyur.Desai@Sun.COM ldap_value_free_len(bvalues);
49010504SKeyur.Desai@Sun.COM }
49110504SKeyur.Desai@Sun.COM }
49210504SKeyur.Desai@Sun.COM
49310504SKeyur.Desai@Sun.COM idmap_setqresults(q, san, dn,
49410504SKeyur.Desai@Sun.COM attr, value,
49510504SKeyur.Desai@Sun.COM sid, rid, sid_type,
49610504SKeyur.Desai@Sun.COM unix_name, pid);
49710504SKeyur.Desai@Sun.COM
49810504SKeyur.Desai@Sun.COM out:
4994520Snw141292 ldap_memfree(dn);
5004520Snw141292 }
5014520Snw141292
5028040SBaban.Kenkre@Sun.COM void
idmap_ldap_res_search_cb(LDAP * ld,LDAPMessage ** res,int rc,int qid,void * argp)5038040SBaban.Kenkre@Sun.COM idmap_ldap_res_search_cb(LDAP *ld, LDAPMessage **res, int rc, int qid,
5048040SBaban.Kenkre@Sun.COM void *argp)
5054520Snw141292 {
5068040SBaban.Kenkre@Sun.COM idmap_query_state_t *state = (idmap_query_state_t *)argp;
5078040SBaban.Kenkre@Sun.COM idmap_q_t *q = &(state->queries[qid]);
5084520Snw141292
5094520Snw141292 switch (rc) {
5104520Snw141292 case LDAP_RES_SEARCH_RESULT:
5118040SBaban.Kenkre@Sun.COM if (q->search_res != NULL) {
5128040SBaban.Kenkre@Sun.COM idmap_extract_object(state, q, q->search_res, ld);
5138040SBaban.Kenkre@Sun.COM (void) ldap_msgfree(q->search_res);
5148040SBaban.Kenkre@Sun.COM q->search_res = NULL;
5158040SBaban.Kenkre@Sun.COM } else
5168040SBaban.Kenkre@Sun.COM q->ad_rc = ADUTILS_ERR_NOTFOUND;
5174520Snw141292 break;
5188040SBaban.Kenkre@Sun.COM case LDAP_RES_SEARCH_ENTRY:
5198040SBaban.Kenkre@Sun.COM if (q->search_res == NULL) {
5208040SBaban.Kenkre@Sun.COM q->search_res = *res;
5218040SBaban.Kenkre@Sun.COM *res = NULL;
5228040SBaban.Kenkre@Sun.COM }
5234520Snw141292 break;
5244520Snw141292 default:
5254520Snw141292 break;
5264520Snw141292 }
5274884Sjp151216 }
5284884Sjp151216
5295447Snw141292 static
5305447Snw141292 void
idmap_cleanup_batch(idmap_query_state_t * batch)5315447Snw141292 idmap_cleanup_batch(idmap_query_state_t *batch)
5325447Snw141292 {
5335447Snw141292 int i;
5345447Snw141292
5355447Snw141292 for (i = 0; i < batch->qcount; i++) {
5365696Snw141292 if (batch->queries[i].ecanonname != NULL)
5375696Snw141292 free(batch->queries[i].ecanonname);
5385696Snw141292 batch->queries[i].ecanonname = NULL;
5395696Snw141292 if (batch->queries[i].edomain != NULL)
5405696Snw141292 free(batch->queries[i].edomain);
5415696Snw141292 batch->queries[i].edomain = NULL;
5425447Snw141292 }
5435447Snw141292 }
5445447Snw141292
5454884Sjp151216 /*
5464884Sjp151216 * This routine frees the idmap_query_state_t structure
5474884Sjp151216 */
5484520Snw141292 void
idmap_lookup_release_batch(idmap_query_state_t ** state)5494884Sjp151216 idmap_lookup_release_batch(idmap_query_state_t **state)
5504520Snw141292 {
5518040SBaban.Kenkre@Sun.COM if (state == NULL || *state == NULL)
5528040SBaban.Kenkre@Sun.COM return;
5538040SBaban.Kenkre@Sun.COM adutils_lookup_batch_release(&(*state)->qs);
5545447Snw141292 idmap_cleanup_batch(*state);
55510504SKeyur.Desai@Sun.COM free((*state)->default_domain);
5564520Snw141292 free(*state);
5574520Snw141292 *state = NULL;
5584520Snw141292 }
5594520Snw141292
5604520Snw141292 idmap_retcode
idmap_lookup_batch_end(idmap_query_state_t ** state)5615968Snw141292 idmap_lookup_batch_end(idmap_query_state_t **state)
5624520Snw141292 {
5638040SBaban.Kenkre@Sun.COM adutils_rc ad_rc;
5648040SBaban.Kenkre@Sun.COM int i;
5658040SBaban.Kenkre@Sun.COM idmap_query_state_t *id_qs = *state;
5664520Snw141292
5678040SBaban.Kenkre@Sun.COM ad_rc = adutils_lookup_batch_end(&id_qs->qs);
5684520Snw141292
5698040SBaban.Kenkre@Sun.COM /*
5708040SBaban.Kenkre@Sun.COM * Map adutils rc to idmap_retcode in each
5718040SBaban.Kenkre@Sun.COM * query because consumers in dbutils.c
5728040SBaban.Kenkre@Sun.COM * expects idmap_retcode.
5738040SBaban.Kenkre@Sun.COM */
5748040SBaban.Kenkre@Sun.COM for (i = 0; i < id_qs->qcount; i++) {
5758040SBaban.Kenkre@Sun.COM *id_qs->queries[i].rc =
5768040SBaban.Kenkre@Sun.COM map_adrc2idmaprc(id_qs->queries[i].ad_rc);
5774520Snw141292 }
5784884Sjp151216 idmap_lookup_release_batch(state);
5798040SBaban.Kenkre@Sun.COM return (map_adrc2idmaprc(ad_rc));
5804520Snw141292 }
5814520Snw141292
5824520Snw141292 /*
5834520Snw141292 * Send one prepared search, queue up msgid, process what results are
5844520Snw141292 * available
5854520Snw141292 */
5864520Snw141292 static
5874520Snw141292 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)5886386Sjp151216 idmap_batch_add1(idmap_query_state_t *state, const char *filter,
589*12508Samw@Sun.COM char *ecanonname, char *edomain, idmap_id_type esidtype,
5906386Sjp151216 char **dn, char **attr, char **value,
5916386Sjp151216 char **canonname, char **dname,
592*12508Samw@Sun.COM char **sid, rid_t *rid, idmap_id_type *sid_type, char **unixname,
59310504SKeyur.Desai@Sun.COM posix_id_t *pid,
5946386Sjp151216 idmap_retcode *rc)
5954520Snw141292 {
5968040SBaban.Kenkre@Sun.COM adutils_rc ad_rc;
5978040SBaban.Kenkre@Sun.COM int qid, i;
5984520Snw141292 idmap_q_t *q;
59910504SKeyur.Desai@Sun.COM char *attrs[20]; /* Plenty */
6004520Snw141292
6018361SJulian.Pullen@Sun.COM qid = atomic_inc_32_nv(&state->qcount) - 1;
6024520Snw141292 q = &(state->queries[qid]);
6034520Snw141292
6048361SJulian.Pullen@Sun.COM assert(qid < state->qsize);
6058361SJulian.Pullen@Sun.COM
6065696Snw141292 /*
6078040SBaban.Kenkre@Sun.COM * Remember the expected canonname, domainname and unix type
6088040SBaban.Kenkre@Sun.COM * so we can check the results * against it
6095696Snw141292 */
6105696Snw141292 q->ecanonname = ecanonname;
6115696Snw141292 q->edomain = edomain;
612*12508Samw@Sun.COM q->esidtype = esidtype;
6135447Snw141292
6144520Snw141292 /* Remember where to put the results */
6155696Snw141292 q->canonname = canonname;
6165731Sbaban q->sid = sid;
6174520Snw141292 q->domain = dname;
6184520Snw141292 q->rid = rid;
6194520Snw141292 q->sid_type = sid_type;
6204520Snw141292 q->rc = rc;
6215731Sbaban q->unixname = unixname;
6226386Sjp151216 q->dn = dn;
6236386Sjp151216 q->attr = attr;
6246386Sjp151216 q->value = value;
62510504SKeyur.Desai@Sun.COM q->pid = pid;
6265731Sbaban
62710504SKeyur.Desai@Sun.COM /* Add attributes that are not always needed */
62810504SKeyur.Desai@Sun.COM i = 0;
62910504SKeyur.Desai@Sun.COM attrs[i++] = SAN;
63010504SKeyur.Desai@Sun.COM attrs[i++] = OBJSID;
63110504SKeyur.Desai@Sun.COM attrs[i++] = OBJCLASS;
63210504SKeyur.Desai@Sun.COM
6335731Sbaban if (unixname != NULL) {
63410504SKeyur.Desai@Sun.COM /* Add unixuser/unixgroup attribute names to the attrs list */
635*12508Samw@Sun.COM if (esidtype != IDMAP_GSID &&
6365731Sbaban state->ad_unixuser_attr != NULL)
6375731Sbaban attrs[i++] = (char *)state->ad_unixuser_attr;
638*12508Samw@Sun.COM if (esidtype != IDMAP_USID &&
6395731Sbaban state->ad_unixgroup_attr != NULL)
64010504SKeyur.Desai@Sun.COM attrs[i++] = (char *)state->ad_unixgroup_attr;
6415731Sbaban }
6424520Snw141292
64310504SKeyur.Desai@Sun.COM if (pid != NULL) {
644*12508Samw@Sun.COM if (esidtype != IDMAP_GSID)
64510504SKeyur.Desai@Sun.COM attrs[i++] = UIDNUMBER;
646*12508Samw@Sun.COM if (esidtype != IDMAP_USID)
64710504SKeyur.Desai@Sun.COM attrs[i++] = GIDNUMBER;
64810504SKeyur.Desai@Sun.COM }
64910504SKeyur.Desai@Sun.COM
65010504SKeyur.Desai@Sun.COM attrs[i] = NULL;
65110504SKeyur.Desai@Sun.COM
6524520Snw141292 /*
6534520Snw141292 * Provide sane defaults for the results in case we never hear
6544520Snw141292 * back from the DS before closing the connection.
6555447Snw141292 *
6565447Snw141292 * In particular we default the result to indicate a retriable
6575447Snw141292 * error. The first complete matching result entry will cause
6585447Snw141292 * this to be set to IDMAP_SUCCESS, and the end of the results
6595447Snw141292 * for this search will cause this to indicate "not found" if no
6605447Snw141292 * result entries arrived or no complete ones matched the lookup
6615447Snw141292 * we were doing.
6624520Snw141292 */
6634520Snw141292 *rc = IDMAP_ERR_RETRIABLE_NET_ERR;
6645731Sbaban if (sid_type != NULL)
665*12508Samw@Sun.COM *sid_type = IDMAP_SID;
6665731Sbaban if (sid != NULL)
6675731Sbaban *sid = NULL;
6684520Snw141292 if (dname != NULL)
6694520Snw141292 *dname = NULL;
6704520Snw141292 if (rid != NULL)
6714520Snw141292 *rid = 0;
6726386Sjp151216 if (dn != NULL)
6736386Sjp151216 *dn = NULL;
6746386Sjp151216 if (attr != NULL)
6756386Sjp151216 *attr = NULL;
6766386Sjp151216 if (value != NULL)
6776386Sjp151216 *value = NULL;
6784520Snw141292
6796616Sdm199847 /*
6806616Sdm199847 * Don't set *canonname to NULL because it may be pointing to the
6816616Sdm199847 * given winname. Later on if we get a canonical name from AD the
6826616Sdm199847 * old name if any will be freed before assigning the new name.
6836616Sdm199847 */
6846616Sdm199847
6854520Snw141292 /*
6868040SBaban.Kenkre@Sun.COM * Invoke the mother of all APIs i.e. the adutils API
6874520Snw141292 */
6888040SBaban.Kenkre@Sun.COM ad_rc = adutils_lookup_batch_add(state->qs, filter,
6898040SBaban.Kenkre@Sun.COM (const char **)attrs,
6908040SBaban.Kenkre@Sun.COM edomain, &q->result, &q->ad_rc);
6918040SBaban.Kenkre@Sun.COM return (map_adrc2idmaprc(ad_rc));
6924520Snw141292 }
6934520Snw141292
6944520Snw141292 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)6954520Snw141292 idmap_name2sid_batch_add1(idmap_query_state_t *state,
696*12508Samw@Sun.COM const char *name, const char *dname, idmap_id_type esidtype,
6976386Sjp151216 char **dn, char **attr, char **value,
6986386Sjp151216 char **canonname, char **sid, rid_t *rid,
699*12508Samw@Sun.COM idmap_id_type *sid_type, char **unixname,
70010504SKeyur.Desai@Sun.COM posix_id_t *pid, idmap_retcode *rc)
7014520Snw141292 {
7024520Snw141292 idmap_retcode retcode;
70310504SKeyur.Desai@Sun.COM char *filter, *s_name;
7045696Snw141292 char *ecanonname, *edomain; /* expected canonname */
7054520Snw141292
7064520Snw141292 /*
7075447Snw141292 * Strategy: search the global catalog for user/group by
7085447Snw141292 * sAMAccountName = user/groupname with "" as the base DN and by
7095447Snw141292 * userPrincipalName = user/groupname@domain. The result
7105447Snw141292 * entries will be checked to conform to the name and domain
7115447Snw141292 * name given here. The DN, sAMAccountName, userPrincipalName,
7125447Snw141292 * objectSid and objectClass of the result entries are all we
7135447Snw141292 * need to figure out which entries match the lookup, the SID of
7145447Snw141292 * the user/group and whether it is a user or a group.
7154520Snw141292 */
7164520Snw141292
7175696Snw141292 if ((ecanonname = strdup(name)) == NULL)
7185696Snw141292 return (IDMAP_ERR_MEMORY);
7194520Snw141292
7205447Snw141292 if (dname == NULL || *dname == '\0') {
72110504SKeyur.Desai@Sun.COM /* 'name' not qualified and dname not given */
72210504SKeyur.Desai@Sun.COM dname = state->default_domain;
72310504SKeyur.Desai@Sun.COM edomain = strdup(dname);
72410504SKeyur.Desai@Sun.COM if (edomain == NULL) {
72510504SKeyur.Desai@Sun.COM free(ecanonname);
72610504SKeyur.Desai@Sun.COM return (IDMAP_ERR_MEMORY);
7275696Snw141292 }
7285696Snw141292 } else {
7295696Snw141292 if ((edomain = strdup(dname)) == NULL) {
7305696Snw141292 free(ecanonname);
7315447Snw141292 return (IDMAP_ERR_MEMORY);
7325696Snw141292 }
7335447Snw141292 }
7344520Snw141292
7358361SJulian.Pullen@Sun.COM if (!adutils_lookup_check_domain(state->qs, dname)) {
7368361SJulian.Pullen@Sun.COM free(ecanonname);
7378361SJulian.Pullen@Sun.COM free(edomain);
7388361SJulian.Pullen@Sun.COM return (IDMAP_ERR_DOMAIN_NOTFOUND);
7398361SJulian.Pullen@Sun.COM }
7408361SJulian.Pullen@Sun.COM
7416616Sdm199847 s_name = sanitize_for_ldap_filter(name);
7426616Sdm199847 if (s_name == NULL) {
7436616Sdm199847 free(ecanonname);
7446616Sdm199847 free(edomain);
7456616Sdm199847 return (IDMAP_ERR_MEMORY);
7466616Sdm199847 }
7476616Sdm199847
7484520Snw141292 /* Assemble filter */
74910504SKeyur.Desai@Sun.COM (void) asprintf(&filter, SANFILTER, s_name);
75010504SKeyur.Desai@Sun.COM if (s_name != name)
75110504SKeyur.Desai@Sun.COM free(s_name);
75210504SKeyur.Desai@Sun.COM if (filter == NULL) {
7535696Snw141292 free(ecanonname);
7546616Sdm199847 free(edomain);
7554520Snw141292 return (IDMAP_ERR_MEMORY);
7564520Snw141292 }
7574520Snw141292
7585696Snw141292 retcode = idmap_batch_add1(state, filter, ecanonname, edomain,
759*12508Samw@Sun.COM esidtype, dn, attr, value, canonname, NULL, sid, rid, sid_type,
76010504SKeyur.Desai@Sun.COM unixname, pid, rc);
7614520Snw141292
7624520Snw141292 free(filter);
7634520Snw141292
7644520Snw141292 return (retcode);
7654520Snw141292 }
7664520Snw141292
7674520Snw141292 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)7684520Snw141292 idmap_sid2name_batch_add1(idmap_query_state_t *state,
769*12508Samw@Sun.COM const char *sid, const rid_t *rid, idmap_id_type esidtype,
7706386Sjp151216 char **dn, char **attr, char **value,
771*12508Samw@Sun.COM char **name, char **dname, idmap_id_type *sid_type,
77210504SKeyur.Desai@Sun.COM char **unixname, posix_id_t *pid, idmap_retcode *rc)
7734520Snw141292 {
7744520Snw141292 idmap_retcode retcode;
77510504SKeyur.Desai@Sun.COM int ret;
77610504SKeyur.Desai@Sun.COM char *filter;
7778040SBaban.Kenkre@Sun.COM char cbinsid[ADUTILS_MAXHEXBINSID + 1];
7784520Snw141292
7794520Snw141292 /*
7804520Snw141292 * Strategy: search [the global catalog] for user/group by
7814520Snw141292 * objectSid = SID with empty base DN. The DN, sAMAccountName
7824520Snw141292 * and objectClass of the result are all we need to figure out
7834520Snw141292 * the name of the SID and whether it is a user, a group or a
7844520Snw141292 * computer.
7854520Snw141292 */
7864520Snw141292
7878361SJulian.Pullen@Sun.COM if (!adutils_lookup_check_sid_prefix(state->qs, sid))
7888361SJulian.Pullen@Sun.COM return (IDMAP_ERR_DOMAIN_NOTFOUND);
7898361SJulian.Pullen@Sun.COM
7908040SBaban.Kenkre@Sun.COM ret = adutils_txtsid2hexbinsid(sid, rid, &cbinsid[0], sizeof (cbinsid));
7914520Snw141292 if (ret != 0)
7924520Snw141292 return (IDMAP_ERR_SID);
7934520Snw141292
7944520Snw141292 /* Assemble filter */
79510504SKeyur.Desai@Sun.COM (void) asprintf(&filter, OBJSIDFILTER, cbinsid);
79610504SKeyur.Desai@Sun.COM if (filter == NULL)
7974520Snw141292 return (IDMAP_ERR_MEMORY);
7984520Snw141292
799*12508Samw@Sun.COM retcode = idmap_batch_add1(state, filter, NULL, NULL, esidtype,
80010504SKeyur.Desai@Sun.COM dn, attr, value, name, dname, NULL, NULL, sid_type, unixname,
80110504SKeyur.Desai@Sun.COM pid, rc);
8024520Snw141292
8034520Snw141292 free(filter);
8044520Snw141292
8054520Snw141292 return (retcode);
8064520Snw141292 }
8075731Sbaban
8085731Sbaban 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)8095731Sbaban idmap_unixname2sid_batch_add1(idmap_query_state_t *state,
8105731Sbaban const char *unixname, int is_user, int is_wuser,
8116386Sjp151216 char **dn, char **attr, char **value,
8126386Sjp151216 char **sid, rid_t *rid, char **name,
813*12508Samw@Sun.COM char **dname, idmap_id_type *sid_type, idmap_retcode *rc)
8145731Sbaban {
8155731Sbaban idmap_retcode retcode;
81610504SKeyur.Desai@Sun.COM char *filter, *s_unixname;
81710504SKeyur.Desai@Sun.COM const char *attrname;
8185731Sbaban
8195731Sbaban /* Get unixuser or unixgroup AD attribute name */
8205731Sbaban attrname = (is_user) ?
8215731Sbaban state->ad_unixuser_attr : state->ad_unixgroup_attr;
8225731Sbaban if (attrname == NULL)
8235731Sbaban return (IDMAP_ERR_NOTFOUND);
8245731Sbaban
8256616Sdm199847 s_unixname = sanitize_for_ldap_filter(unixname);
8266616Sdm199847 if (s_unixname == NULL)
8276616Sdm199847 return (IDMAP_ERR_MEMORY);
8286616Sdm199847
8295731Sbaban /* Assemble filter */
83010504SKeyur.Desai@Sun.COM (void) asprintf(&filter, "(&(objectclass=%s)(%s=%s))",
83110504SKeyur.Desai@Sun.COM is_wuser ? "user" : "group", attrname, s_unixname);
83210504SKeyur.Desai@Sun.COM if (s_unixname != unixname)
83310504SKeyur.Desai@Sun.COM free(s_unixname);
83410504SKeyur.Desai@Sun.COM if (filter == NULL) {
8355731Sbaban return (IDMAP_ERR_MEMORY);
8366616Sdm199847 }
8375731Sbaban
8385731Sbaban retcode = idmap_batch_add1(state, filter, NULL, NULL,
839*12508Samw@Sun.COM IDMAP_POSIXID, dn, NULL, NULL, name, dname, sid, rid, sid_type,
84010504SKeyur.Desai@Sun.COM NULL, NULL, rc);
8416386Sjp151216
8426386Sjp151216 if (retcode == IDMAP_SUCCESS && attr != NULL) {
8436386Sjp151216 if ((*attr = strdup(attrname)) == NULL)
8446386Sjp151216 retcode = IDMAP_ERR_MEMORY;
8456386Sjp151216 }
8466386Sjp151216
8476386Sjp151216 if (retcode == IDMAP_SUCCESS && value != NULL) {
84810504SKeyur.Desai@Sun.COM if ((*value = strdup(unixname)) == NULL)
84910504SKeyur.Desai@Sun.COM retcode = IDMAP_ERR_MEMORY;
8506386Sjp151216 }
8515731Sbaban
8525731Sbaban free(filter);
8535731Sbaban
8545731Sbaban return (retcode);
8555731Sbaban }
85610504SKeyur.Desai@Sun.COM
85710504SKeyur.Desai@Sun.COM 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)85810504SKeyur.Desai@Sun.COM idmap_pid2sid_batch_add1(idmap_query_state_t *state,
85910504SKeyur.Desai@Sun.COM posix_id_t pid, int is_user,
86010504SKeyur.Desai@Sun.COM char **dn, char **attr, char **value,
86110504SKeyur.Desai@Sun.COM char **sid, rid_t *rid, char **name,
862*12508Samw@Sun.COM char **dname, idmap_id_type *sid_type, idmap_retcode *rc)
86310504SKeyur.Desai@Sun.COM {
86410504SKeyur.Desai@Sun.COM idmap_retcode retcode;
86510504SKeyur.Desai@Sun.COM char *filter;
86610504SKeyur.Desai@Sun.COM const char *attrname;
86710504SKeyur.Desai@Sun.COM
86810504SKeyur.Desai@Sun.COM /* Assemble filter */
86910504SKeyur.Desai@Sun.COM if (is_user) {
87010504SKeyur.Desai@Sun.COM (void) asprintf(&filter, UIDNUMBERFILTER, pid);
87110504SKeyur.Desai@Sun.COM attrname = UIDNUMBER;
87210504SKeyur.Desai@Sun.COM } else {
87310504SKeyur.Desai@Sun.COM (void) asprintf(&filter, GIDNUMBERFILTER, pid);
87410504SKeyur.Desai@Sun.COM attrname = GIDNUMBER;
87510504SKeyur.Desai@Sun.COM }
87610504SKeyur.Desai@Sun.COM if (filter == NULL)
87710504SKeyur.Desai@Sun.COM return (IDMAP_ERR_MEMORY);
87810504SKeyur.Desai@Sun.COM
87910504SKeyur.Desai@Sun.COM retcode = idmap_batch_add1(state, filter, NULL, NULL,
880*12508Samw@Sun.COM IDMAP_POSIXID, dn, NULL, NULL, name, dname, sid, rid, sid_type,
88110504SKeyur.Desai@Sun.COM NULL, NULL, rc);
88210504SKeyur.Desai@Sun.COM
88310504SKeyur.Desai@Sun.COM if (retcode == IDMAP_SUCCESS && attr != NULL) {
88410504SKeyur.Desai@Sun.COM if ((*attr = strdup(attrname)) == NULL)
88510504SKeyur.Desai@Sun.COM retcode = IDMAP_ERR_MEMORY;
88610504SKeyur.Desai@Sun.COM }
88710504SKeyur.Desai@Sun.COM
88810504SKeyur.Desai@Sun.COM if (retcode == IDMAP_SUCCESS && value != NULL) {
88910504SKeyur.Desai@Sun.COM (void) asprintf(value, "%u", pid);
89010504SKeyur.Desai@Sun.COM if (*value == NULL)
89110504SKeyur.Desai@Sun.COM retcode = IDMAP_ERR_MEMORY;
89210504SKeyur.Desai@Sun.COM }
89310504SKeyur.Desai@Sun.COM
89410504SKeyur.Desai@Sun.COM free(filter);
89510504SKeyur.Desai@Sun.COM
89610504SKeyur.Desai@Sun.COM return (retcode);
89710504SKeyur.Desai@Sun.COM }
898