15731Sbaban /* 25731Sbaban * CDDL HEADER START 35731Sbaban * 45731Sbaban * The contents of this file are subject to the terms of the 55731Sbaban * Common Development and Distribution License (the "License"). 65731Sbaban * You may not use this file except in compliance with the License. 75731Sbaban * 85731Sbaban * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95731Sbaban * or http://www.opensolaris.org/os/licensing. 105731Sbaban * See the License for the specific language governing permissions 115731Sbaban * and limitations under the License. 125731Sbaban * 135731Sbaban * When distributing Covered Code, include this CDDL HEADER in each 145731Sbaban * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155731Sbaban * If applicable, add the following below this CDDL HEADER, with the 165731Sbaban * fields enclosed by brackets "[]" replaced with your own identifying 175731Sbaban * information: Portions Copyright [yyyy] [name of copyright owner] 185731Sbaban * 195731Sbaban * CDDL HEADER END 205731Sbaban */ 215731Sbaban 225731Sbaban /* 23*9422SAfshin.Ardakani@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 245731Sbaban * Use is subject to license terms. 255731Sbaban */ 265731Sbaban 275731Sbaban /* 285731Sbaban * native LDAP related utility routines 295731Sbaban */ 305731Sbaban 315731Sbaban #include "idmapd.h" 326616Sdm199847 #include "idmap_priv.h" 336616Sdm199847 #include "ns_sldap.h" 346616Sdm199847 #include "nldaputils.h" 356616Sdm199847 #include <assert.h> 366616Sdm199847 376616Sdm199847 /* 386616Sdm199847 * The following are format strings used to construct LDAP search filters 396616Sdm199847 * when looking up Native LDAP directory service. The _F_XXX_SSD format 406616Sdm199847 * is used by the libsldap API if a corresponding SSD is defined in 416616Sdm199847 * Native LDAP configuration. The SSD contains a string that replaces 426616Sdm199847 * the first %s in _F_XXX_SSD. If no SSD is defined then the regular 436616Sdm199847 * _F_XXX format is used. 446616Sdm199847 * 456616Sdm199847 * Note that '\\' needs to be represented as "\\5c" in LDAP filters. 466616Sdm199847 */ 476616Sdm199847 486616Sdm199847 /* Native LDAP lookup using UNIX username */ 496616Sdm199847 #define _F_GETPWNAM "(&(objectClass=posixAccount)(uid=%s))" 506616Sdm199847 #define _F_GETPWNAM_SSD "(&(%%s)(uid=%s))" 516616Sdm199847 526616Sdm199847 /* 536616Sdm199847 * Native LDAP user lookup using names of well-known SIDs 546616Sdm199847 * Note the use of 1$, 2$ in the format string which basically 556616Sdm199847 * allows snprintf to re-use its first two arguments. 566616Sdm199847 */ 576616Sdm199847 #define _F_GETPWWNAMWK \ 586616Sdm199847 "(&(objectClass=posixAccount)(|(%s=%s)(%1$s=BUILTIN\\5c%2$s)))" 596616Sdm199847 #define _F_GETPWWNAMWK_SSD "(&(%%s)(|(%s=%s)(%1$s=BUILTIN\\5c%2$s)))" 606616Sdm199847 616616Sdm199847 /* Native LDAP user lookup using winname@windomain OR windomain\winname */ 626616Sdm199847 #define _F_GETPWWNAMDOM \ 636616Sdm199847 "(&(objectClass=posixAccount)(|(%s=%s@%s)(%1$s=%3$s\\5c%2$s)))" 646616Sdm199847 #define _F_GETPWWNAMDOM_SSD "(&(%%s)(|(%s=%s@%s)(%1$s=%3$s\\5c%2$s)))" 656616Sdm199847 666616Sdm199847 /* Native LDAP lookup using UID */ 676616Sdm199847 #define _F_GETPWUID "(&(objectClass=posixAccount)(uidNumber=%u))" 686616Sdm199847 #define _F_GETPWUID_SSD "(&(%%s)(uidNumber=%u))" 696616Sdm199847 706616Sdm199847 /* Native LDAP lookup using UNIX groupname */ 716616Sdm199847 #define _F_GETGRNAM "(&(objectClass=posixGroup)(cn=%s))" 726616Sdm199847 #define _F_GETGRNAM_SSD "(&(%%s)(cn=%s))" 736616Sdm199847 746616Sdm199847 /* Native LDAP group lookup using names of well-known SIDs */ 756616Sdm199847 #define _F_GETGRWNAMWK \ 766616Sdm199847 "(&(objectClass=posixGroup)(|(%s=%s)(%1$s=BUILTIN\\5c%2$s)))" 776616Sdm199847 #define _F_GETGRWNAMWK_SSD "(&(%%s)(|(%s=%s)(%1$s=BUILTIN\\5c%2$s)))" 786616Sdm199847 796616Sdm199847 /* Native LDAP group lookup using winname@windomain OR windomain\winname */ 806616Sdm199847 #define _F_GETGRWNAMDOM \ 816616Sdm199847 "(&(objectClass=posixGroup)(|(%s=%s@%s)(%1$s=%3$s\\5c%2$s)))" 826616Sdm199847 #define _F_GETGRWNAMDOM_SSD "(&(%%s)(|(%s=%s@%s)(%1$s=%3$s\\5c%2$s)))" 836616Sdm199847 846616Sdm199847 /* Native LDAP lookup using GID */ 856616Sdm199847 #define _F_GETGRGID "(&(objectClass=posixGroup)(gidNumber=%u))" 866616Sdm199847 #define _F_GETGRGID_SSD "(&(%%s)(gidNumber=%u))" 876616Sdm199847 886616Sdm199847 /* Native LDAP attribute names */ 896616Sdm199847 #define UID "uid" 906616Sdm199847 #define CN "cn" 916616Sdm199847 #define UIDNUMBER "uidnumber" 926616Sdm199847 #define GIDNUMBER "gidnumber" 936616Sdm199847 #define DN "dn" 946616Sdm199847 956616Sdm199847 #define IS_NLDAP_RC_FATAL(x) ((x == NS_LDAP_MEMORY) ? 1 : 0) 966616Sdm199847 976616Sdm199847 typedef struct idmap_nldap_q { 986616Sdm199847 char **winname; 996616Sdm199847 char **windomain; 1006616Sdm199847 char **unixname; 1016616Sdm199847 uid_t *pid; 1026616Sdm199847 char **dn; 1036616Sdm199847 char **attr; 1046616Sdm199847 char **value; 1056616Sdm199847 int is_user; 1066616Sdm199847 idmap_retcode *rc; 1076616Sdm199847 int lrc; 1086616Sdm199847 ns_ldap_result_t *result; 1096616Sdm199847 ns_ldap_error_t *errorp; 1106616Sdm199847 char *filter; 1116616Sdm199847 char *udata; 1126616Sdm199847 } idmap_nldap_q_t; 1136616Sdm199847 1146616Sdm199847 typedef struct idmap_nldap_query_state { 1156616Sdm199847 const char *nldap_winname_attr; 1166616Sdm199847 const char *defdom; 1176616Sdm199847 int nqueries; 1186616Sdm199847 int qid; 1196616Sdm199847 int flag; 1206616Sdm199847 ns_ldap_list_batch_t *batch; 1216616Sdm199847 idmap_nldap_q_t queries[1]; 1226616Sdm199847 } idmap_nldap_query_state_t; 1236616Sdm199847 1246616Sdm199847 /* 1256616Sdm199847 * This routine has been copied from lib/nsswitch/ldap/common/ldap_utils.c 1266616Sdm199847 * after removing the debug statements. 1276616Sdm199847 * 1286616Sdm199847 * This is a generic filter callback function for merging the filter 1296616Sdm199847 * from service search descriptor with an existing search filter. This 1306616Sdm199847 * routine expects userdata to contain a format string with a single %s 1316616Sdm199847 * in it, and will use the format string with sprintf() to insert the 1326616Sdm199847 * SSD filter. 1336616Sdm199847 * 1346616Sdm199847 * This routine and userdata are passed to the __ns_ldap_list_batch_add() 1356616Sdm199847 * API. 1366616Sdm199847 * 1376616Sdm199847 * Consider an example that uses __ns_ldap_list_batch_add() to lookup 1386616Sdm199847 * native LDAP directory using a given userid 'xy12345'. In this 1396616Sdm199847 * example the userdata will contain the filter "(&(%s)(cn=xy1234))". 1406616Sdm199847 * If a SSD is defined to replace the rfc2307bis specified filter 1416616Sdm199847 * i.e. (objectClass=posixAccount) by a site-specific filter 1426616Sdm199847 * say (department=sds) then this routine when called will produce 1436616Sdm199847 * "(&(department=sds)(uid=xy1234))" as the real search filter. 1446616Sdm199847 */ 1456616Sdm199847 static 1466616Sdm199847 int 1476616Sdm199847 merge_SSD_filter(const ns_ldap_search_desc_t *desc, 1486616Sdm199847 char **realfilter, const void *userdata) 1496616Sdm199847 { 1506616Sdm199847 int len; 1516616Sdm199847 if (realfilter == NULL) 1526616Sdm199847 return (NS_LDAP_INVALID_PARAM); 1536616Sdm199847 *realfilter = NULL; 1546616Sdm199847 if (desc == NULL || desc->filter == NULL || userdata == NULL) 1556616Sdm199847 return (NS_LDAP_INVALID_PARAM); 1566616Sdm199847 len = strlen(userdata) + strlen(desc->filter) + 1; 1576616Sdm199847 *realfilter = (char *)malloc(len); 1586616Sdm199847 if (*realfilter == NULL) 1596616Sdm199847 return (NS_LDAP_MEMORY); 1606616Sdm199847 (void) sprintf(*realfilter, (char *)userdata, desc->filter); 1616616Sdm199847 return (NS_LDAP_SUCCESS); 1626616Sdm199847 } 1636616Sdm199847 1646616Sdm199847 static 1656616Sdm199847 char 1666616Sdm199847 hex_char(int n) 1676616Sdm199847 { 1686616Sdm199847 return ("0123456789abcdef"[n & 0xf]); 1696616Sdm199847 } 1706616Sdm199847 1716616Sdm199847 /* 1726616Sdm199847 * If the input string contains special characters that needs to be 1736616Sdm199847 * escaped before the string can be used in a LDAP filter then this 1746616Sdm199847 * function will return a new sanitized string. Otherwise this function 1756616Sdm199847 * returns the input string (This saves us un-necessary memory allocations 1766616Sdm199847 * especially when processing a batch of requests). The caller must free 1776616Sdm199847 * the returned string if it isn't the input string. 1786616Sdm199847 * 1796616Sdm199847 * The escape mechanism for LDAP filter is described in RFC2254 basically 1806616Sdm199847 * it's \hh where hh are the two hexadecimal digits representing the ASCII 1816616Sdm199847 * value of the encoded character (case of hh is not significant). 1826616Sdm199847 * Example: * -> \2a, ( -> \28, ) -> \29, \ -> \5c, 1836616Sdm199847 * 1846616Sdm199847 * outstring = sanitize_for_ldap_filter(instring); 1856616Sdm199847 * if (outstring == NULL) 1866616Sdm199847 * Out of memory 1876616Sdm199847 * else 1886616Sdm199847 * Use outstring 1896616Sdm199847 * if (outstring != instring) 1906616Sdm199847 * free(outstring); 1916616Sdm199847 * done 1926616Sdm199847 */ 1936616Sdm199847 char * 1946616Sdm199847 sanitize_for_ldap_filter(const char *str) 1956616Sdm199847 { 1966616Sdm199847 const char *p; 1976616Sdm199847 char *q, *s_str = NULL; 1986616Sdm199847 int n; 1996616Sdm199847 2006616Sdm199847 /* Get a count of special characters */ 2016616Sdm199847 for (p = str, n = 0; *p; p++) 2026616Sdm199847 if (*p == '*' || *p == '(' || *p == ')' || 2036616Sdm199847 *p == '\\' || *p == '%') 2046616Sdm199847 n++; 2056616Sdm199847 /* If count is zero then no need to sanitize */ 2066616Sdm199847 if (n == 0) 2076616Sdm199847 return ((char *)str); 2086616Sdm199847 /* Create output buffer that will contain the sanitized value */ 2096616Sdm199847 s_str = calloc(1, n * 2 + strlen(str) + 1); 2106616Sdm199847 if (s_str == NULL) 2116616Sdm199847 return (NULL); 2126616Sdm199847 for (p = str, q = s_str; *p; p++) { 2136616Sdm199847 if (*p == '*' || *p == '(' || *p == ')' || 2146616Sdm199847 *p == '\\' || *p == '%') { 2156616Sdm199847 *q++ = '\\'; 2166616Sdm199847 *q++ = hex_char(*p >> 4); 2176616Sdm199847 *q++ = hex_char(*p & 0xf); 2186616Sdm199847 } else 2196616Sdm199847 *q++ = *p; 2206616Sdm199847 } 2216616Sdm199847 return (s_str); 2226616Sdm199847 } 2236616Sdm199847 2246616Sdm199847 /* 2256616Sdm199847 * Map libsldap status to idmap status 2266616Sdm199847 */ 2276616Sdm199847 static 2286616Sdm199847 idmap_retcode 2296616Sdm199847 nldaprc2retcode(int rc) 2306616Sdm199847 { 2316616Sdm199847 switch (rc) { 2326616Sdm199847 case NS_LDAP_SUCCESS: 2336616Sdm199847 case NS_LDAP_SUCCESS_WITH_INFO: 2346616Sdm199847 return (IDMAP_SUCCESS); 2356616Sdm199847 case NS_LDAP_NOTFOUND: 2366616Sdm199847 return (IDMAP_ERR_NOTFOUND); 2376616Sdm199847 case NS_LDAP_MEMORY: 2386616Sdm199847 return (IDMAP_ERR_MEMORY); 2396616Sdm199847 case NS_LDAP_CONFIG: 2406616Sdm199847 return (IDMAP_ERR_NS_LDAP_CFG); 2416616Sdm199847 case NS_LDAP_OP_FAILED: 2426616Sdm199847 return (IDMAP_ERR_NS_LDAP_OP_FAILED); 2436616Sdm199847 case NS_LDAP_PARTIAL: 2446616Sdm199847 return (IDMAP_ERR_NS_LDAP_PARTIAL); 2456616Sdm199847 case NS_LDAP_INTERNAL: 2466616Sdm199847 return (IDMAP_ERR_INTERNAL); 2476616Sdm199847 case NS_LDAP_INVALID_PARAM: 2486616Sdm199847 return (IDMAP_ERR_ARG); 2496616Sdm199847 default: 2506616Sdm199847 return (IDMAP_ERR_OTHER); 2516616Sdm199847 } 2526616Sdm199847 /*NOTREACHED*/ 2536616Sdm199847 } 2546616Sdm199847 2556616Sdm199847 /* 2566616Sdm199847 * Create a batch for native LDAP lookup. 2576616Sdm199847 */ 2586616Sdm199847 static 2596616Sdm199847 idmap_retcode 2606616Sdm199847 idmap_nldap_lookup_batch_start(int nqueries, idmap_nldap_query_state_t **qs) 2616616Sdm199847 { 2626616Sdm199847 idmap_nldap_query_state_t *s; 2636616Sdm199847 2646616Sdm199847 s = calloc(1, sizeof (*s) + 2656616Sdm199847 (nqueries - 1) * sizeof (idmap_nldap_q_t)); 2666616Sdm199847 if (s == NULL) 2676616Sdm199847 return (IDMAP_ERR_MEMORY); 2686616Sdm199847 if (__ns_ldap_list_batch_start(&s->batch) != NS_LDAP_SUCCESS) { 2696616Sdm199847 free(s); 2706616Sdm199847 return (IDMAP_ERR_MEMORY); 2716616Sdm199847 } 2726616Sdm199847 s->nqueries = nqueries; 2736616Sdm199847 s->flag = NS_LDAP_KEEP_CONN; 2746616Sdm199847 *qs = s; 2756616Sdm199847 return (IDMAP_SUCCESS); 2766616Sdm199847 } 2776616Sdm199847 2786616Sdm199847 /* 2796616Sdm199847 * Add a lookup by winname request to the batch. 2806616Sdm199847 */ 2816616Sdm199847 static 2826616Sdm199847 idmap_retcode 2836616Sdm199847 idmap_nldap_bywinname_batch_add(idmap_nldap_query_state_t *qs, 2846616Sdm199847 const char *winname, const char *windomain, int is_user, 2856616Sdm199847 char **dn, char **attr, char **value, 2866616Sdm199847 char **unixname, uid_t *pid, idmap_retcode *rc) 2876616Sdm199847 { 2886616Sdm199847 idmap_nldap_q_t *q; 2896616Sdm199847 const char *db, *filter, *udata; 2906616Sdm199847 int flen, ulen, wksid = 0; 2916616Sdm199847 char *s_winname, *s_windomain; 2926616Sdm199847 const char **attrs; 2936616Sdm199847 const char *pwd_attrs[] = {UID, UIDNUMBER, NULL, NULL}; 2946616Sdm199847 const char *grp_attrs[] = {CN, GIDNUMBER, NULL, NULL}; 2956616Sdm199847 2966616Sdm199847 s_winname = s_windomain = NULL; 2976616Sdm199847 q = &(qs->queries[qs->qid++]); 2986616Sdm199847 q->unixname = unixname; 2996616Sdm199847 q->pid = pid; 3006616Sdm199847 q->rc = rc; 3016616Sdm199847 q->is_user = is_user; 3026616Sdm199847 q->dn = dn; 3036616Sdm199847 q->attr = attr; 3046616Sdm199847 q->value = value; 3056616Sdm199847 3066616Sdm199847 if (is_user) { 3076616Sdm199847 db = "passwd"; 308*9422SAfshin.Ardakani@Sun.COM if (lookup_wksids_name2sid(winname, NULL, NULL, NULL, NULL, 309*9422SAfshin.Ardakani@Sun.COM NULL, NULL) == IDMAP_SUCCESS) { 3106616Sdm199847 filter = _F_GETPWWNAMWK; 3116616Sdm199847 udata = _F_GETPWWNAMWK_SSD; 3126616Sdm199847 wksid = 1; 3136616Sdm199847 } else if (windomain != NULL) { 3146616Sdm199847 filter = _F_GETPWWNAMDOM; 3156616Sdm199847 udata = _F_GETPWWNAMDOM_SSD; 3166616Sdm199847 } else { 3176616Sdm199847 *q->rc = IDMAP_ERR_DOMAIN_NOTFOUND; 3186616Sdm199847 goto errout; 3196616Sdm199847 } 3206616Sdm199847 pwd_attrs[2] = qs->nldap_winname_attr; 3216616Sdm199847 attrs = pwd_attrs; 3226616Sdm199847 } else { 3236616Sdm199847 db = "group"; 324*9422SAfshin.Ardakani@Sun.COM if (lookup_wksids_name2sid(winname, NULL, NULL, NULL, NULL, 325*9422SAfshin.Ardakani@Sun.COM NULL, NULL) == IDMAP_SUCCESS) { 3266616Sdm199847 filter = _F_GETGRWNAMWK; 3276616Sdm199847 udata = _F_GETGRWNAMWK_SSD; 3286616Sdm199847 wksid = 1; 3296616Sdm199847 } else if (windomain != NULL) { 3306616Sdm199847 filter = _F_GETGRWNAMDOM; 3316616Sdm199847 udata = _F_GETGRWNAMDOM_SSD; 3326616Sdm199847 } else { 3336616Sdm199847 *q->rc = IDMAP_ERR_DOMAIN_NOTFOUND; 3346616Sdm199847 goto errout; 3356616Sdm199847 } 3366616Sdm199847 grp_attrs[2] = qs->nldap_winname_attr; 3376616Sdm199847 attrs = grp_attrs; 3386616Sdm199847 } 3396616Sdm199847 3406616Sdm199847 /* 3416616Sdm199847 * Sanitize names. No need to sanitize qs->nldap_winname_attr 3426616Sdm199847 * because if it contained any of the special characters then 3436616Sdm199847 * it would have been rejected by the function that reads it 3446616Sdm199847 * from the SMF config. LDAP attribute names can only contain 3456616Sdm199847 * letters, digits or hyphens. 3466616Sdm199847 */ 3476616Sdm199847 s_winname = sanitize_for_ldap_filter(winname); 3486616Sdm199847 if (s_winname == NULL) { 3496616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 3506616Sdm199847 goto errout; 3516616Sdm199847 } 3526616Sdm199847 /* windomain could be NULL for names of well-known SIDs */ 3536616Sdm199847 if (windomain != NULL) { 3546616Sdm199847 s_windomain = sanitize_for_ldap_filter(windomain); 3556616Sdm199847 if (s_windomain == NULL) { 3566616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 3576616Sdm199847 goto errout; 3586616Sdm199847 } 3596616Sdm199847 } 3606616Sdm199847 3616616Sdm199847 /* Construct the filter and udata using snprintf. */ 3626616Sdm199847 if (wksid) { 3636616Sdm199847 flen = snprintf(NULL, 0, filter, qs->nldap_winname_attr, 3646616Sdm199847 s_winname) + 1; 3656616Sdm199847 ulen = snprintf(NULL, 0, udata, qs->nldap_winname_attr, 3666616Sdm199847 s_winname) + 1; 3676616Sdm199847 } else { 3686616Sdm199847 flen = snprintf(NULL, 0, filter, qs->nldap_winname_attr, 3696616Sdm199847 s_winname, s_windomain) + 1; 3706616Sdm199847 ulen = snprintf(NULL, 0, udata, qs->nldap_winname_attr, 3716616Sdm199847 s_winname, s_windomain) + 1; 3726616Sdm199847 } 3736616Sdm199847 3746616Sdm199847 q->filter = malloc(flen); 3756616Sdm199847 if (q->filter == NULL) { 3766616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 3776616Sdm199847 goto errout; 3786616Sdm199847 } 3796616Sdm199847 q->udata = malloc(ulen); 3806616Sdm199847 if (q->udata == NULL) { 3816616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 3826616Sdm199847 goto errout; 3836616Sdm199847 } 3846616Sdm199847 3856616Sdm199847 if (wksid) { 3866616Sdm199847 (void) snprintf(q->filter, flen, filter, 3876616Sdm199847 qs->nldap_winname_attr, s_winname); 3886616Sdm199847 (void) snprintf(q->udata, ulen, udata, 3896616Sdm199847 qs->nldap_winname_attr, s_winname); 3906616Sdm199847 } else { 3916616Sdm199847 (void) snprintf(q->filter, flen, filter, 3926616Sdm199847 qs->nldap_winname_attr, s_winname, s_windomain); 3936616Sdm199847 (void) snprintf(q->udata, ulen, udata, 3946616Sdm199847 qs->nldap_winname_attr, s_winname, s_windomain); 3956616Sdm199847 } 3966616Sdm199847 3976616Sdm199847 if (s_winname != winname) 3986616Sdm199847 free(s_winname); 3996616Sdm199847 if (s_windomain != windomain) 4006616Sdm199847 free(s_windomain); 4016616Sdm199847 4026616Sdm199847 q->lrc = __ns_ldap_list_batch_add(qs->batch, db, q->filter, 4036616Sdm199847 merge_SSD_filter, attrs, NULL, qs->flag, &q->result, 4046616Sdm199847 &q->errorp, &q->lrc, NULL, q->udata); 4056616Sdm199847 4066616Sdm199847 if (IS_NLDAP_RC_FATAL(q->lrc)) 4076616Sdm199847 return (nldaprc2retcode(q->lrc)); 4086616Sdm199847 return (IDMAP_SUCCESS); 4096616Sdm199847 4106616Sdm199847 errout: 4116616Sdm199847 /* query q and its content will be freed by batch_release */ 4126616Sdm199847 if (s_winname != winname) 4136616Sdm199847 free(s_winname); 4146616Sdm199847 if (s_windomain != windomain) 4156616Sdm199847 free(s_windomain); 4166616Sdm199847 return (*q->rc); 4176616Sdm199847 } 4186616Sdm199847 4196616Sdm199847 /* 4206616Sdm199847 * Add a lookup by uid/gid request to the batch. 4216616Sdm199847 */ 4226616Sdm199847 static 4236616Sdm199847 idmap_retcode 4246616Sdm199847 idmap_nldap_bypid_batch_add(idmap_nldap_query_state_t *qs, 4256616Sdm199847 uid_t pid, int is_user, char **dn, char **attr, char **value, 4266616Sdm199847 char **winname, char **windomain, 4276616Sdm199847 char **unixname, idmap_retcode *rc) 4286616Sdm199847 { 4296616Sdm199847 idmap_nldap_q_t *q; 4306616Sdm199847 const char *db, *filter, *udata; 4316616Sdm199847 int len; 4326616Sdm199847 const char **attrs; 4336616Sdm199847 const char *pwd_attrs[] = {UID, NULL, NULL}; 4346616Sdm199847 const char *grp_attrs[] = {CN, NULL, NULL}; 4356616Sdm199847 4366616Sdm199847 q = &(qs->queries[qs->qid++]); 4376616Sdm199847 q->winname = winname; 4386616Sdm199847 q->windomain = windomain; 4396616Sdm199847 q->unixname = unixname; 4406616Sdm199847 q->rc = rc; 4416616Sdm199847 q->is_user = is_user; 4426616Sdm199847 q->dn = dn; 4436616Sdm199847 q->attr = attr; 4446616Sdm199847 q->value = value; 4456616Sdm199847 4466616Sdm199847 if (is_user) { 4476616Sdm199847 db = "passwd"; 4486616Sdm199847 filter = _F_GETPWUID; 4496616Sdm199847 udata = _F_GETPWUID_SSD; 4506616Sdm199847 pwd_attrs[1] = qs->nldap_winname_attr; 4516616Sdm199847 attrs = pwd_attrs; 4526616Sdm199847 } else { 4536616Sdm199847 db = "group"; 4546616Sdm199847 filter = _F_GETGRGID; 4556616Sdm199847 udata = _F_GETGRGID_SSD; 4566616Sdm199847 grp_attrs[1] = qs->nldap_winname_attr; 4576616Sdm199847 attrs = grp_attrs; 4586616Sdm199847 } 4596616Sdm199847 4606616Sdm199847 len = snprintf(NULL, 0, filter, pid) + 1; 4616616Sdm199847 q->filter = malloc(len); 4626616Sdm199847 if (q->filter == NULL) { 4636616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 4646616Sdm199847 return (IDMAP_ERR_MEMORY); 4656616Sdm199847 } 4666616Sdm199847 (void) snprintf(q->filter, len, filter, pid); 4676616Sdm199847 4686616Sdm199847 len = snprintf(NULL, 0, udata, pid) + 1; 4696616Sdm199847 q->udata = malloc(len); 4706616Sdm199847 if (q->udata == NULL) { 4716616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 4726616Sdm199847 return (IDMAP_ERR_MEMORY); 4736616Sdm199847 } 4746616Sdm199847 (void) snprintf(q->udata, len, udata, pid); 4756616Sdm199847 4766616Sdm199847 q->lrc = __ns_ldap_list_batch_add(qs->batch, db, q->filter, 4776616Sdm199847 merge_SSD_filter, attrs, NULL, qs->flag, &q->result, 4786616Sdm199847 &q->errorp, &q->lrc, NULL, q->udata); 4796616Sdm199847 4806616Sdm199847 if (IS_NLDAP_RC_FATAL(q->lrc)) 4816616Sdm199847 return (nldaprc2retcode(q->lrc)); 4826616Sdm199847 return (IDMAP_SUCCESS); 4836616Sdm199847 } 4846616Sdm199847 4856616Sdm199847 /* 4866616Sdm199847 * Add a lookup by user/group name request to the batch. 4876616Sdm199847 */ 4886616Sdm199847 static 4896616Sdm199847 idmap_retcode 4906616Sdm199847 idmap_nldap_byunixname_batch_add(idmap_nldap_query_state_t *qs, 4916616Sdm199847 const char *unixname, int is_user, 4926616Sdm199847 char **dn, char **attr, char **value, 4936616Sdm199847 char **winname, char **windomain, uid_t *pid, idmap_retcode *rc) 4946616Sdm199847 { 4956616Sdm199847 idmap_nldap_q_t *q; 4966616Sdm199847 const char *db, *filter, *udata; 4976616Sdm199847 int len; 4986616Sdm199847 char *s_unixname = NULL; 4996616Sdm199847 const char **attrs; 5006616Sdm199847 const char *pwd_attrs[] = {UIDNUMBER, NULL, NULL}; 5016616Sdm199847 const char *grp_attrs[] = {GIDNUMBER, NULL, NULL}; 5026616Sdm199847 5036616Sdm199847 q = &(qs->queries[qs->qid++]); 5046616Sdm199847 q->winname = winname; 5056616Sdm199847 q->windomain = windomain; 5066616Sdm199847 q->pid = pid; 5076616Sdm199847 q->rc = rc; 5086616Sdm199847 q->is_user = is_user; 5096616Sdm199847 q->dn = dn; 5106616Sdm199847 q->attr = attr; 5116616Sdm199847 q->value = value; 5126616Sdm199847 5136616Sdm199847 if (is_user) { 5146616Sdm199847 db = "passwd"; 5156616Sdm199847 filter = _F_GETPWNAM; 5166616Sdm199847 udata = _F_GETPWNAM_SSD; 5176616Sdm199847 pwd_attrs[1] = qs->nldap_winname_attr; 5186616Sdm199847 attrs = pwd_attrs; 5196616Sdm199847 } else { 5206616Sdm199847 db = "group"; 5216616Sdm199847 filter = _F_GETGRNAM; 5226616Sdm199847 udata = _F_GETGRNAM_SSD; 5236616Sdm199847 grp_attrs[1] = qs->nldap_winname_attr; 5246616Sdm199847 attrs = grp_attrs; 5256616Sdm199847 } 5266616Sdm199847 5276616Sdm199847 s_unixname = sanitize_for_ldap_filter(unixname); 5286616Sdm199847 if (s_unixname == NULL) { 5296616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 5306616Sdm199847 return (IDMAP_ERR_MEMORY); 5316616Sdm199847 } 5326616Sdm199847 5336616Sdm199847 len = snprintf(NULL, 0, filter, s_unixname) + 1; 5346616Sdm199847 q->filter = malloc(len); 5356616Sdm199847 if (q->filter == NULL) { 5366616Sdm199847 if (s_unixname != unixname) 5376616Sdm199847 free(s_unixname); 5386616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 5396616Sdm199847 return (IDMAP_ERR_MEMORY); 5406616Sdm199847 } 5416616Sdm199847 (void) snprintf(q->filter, len, filter, s_unixname); 5426616Sdm199847 5436616Sdm199847 len = snprintf(NULL, 0, udata, s_unixname) + 1; 5446616Sdm199847 q->udata = malloc(len); 5456616Sdm199847 if (q->udata == NULL) { 5466616Sdm199847 if (s_unixname != unixname) 5476616Sdm199847 free(s_unixname); 5486616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 5496616Sdm199847 return (IDMAP_ERR_MEMORY); 5506616Sdm199847 } 5516616Sdm199847 (void) snprintf(q->udata, len, udata, s_unixname); 5526616Sdm199847 5536616Sdm199847 if (s_unixname != unixname) 5546616Sdm199847 free(s_unixname); 5556616Sdm199847 5566616Sdm199847 q->lrc = __ns_ldap_list_batch_add(qs->batch, db, q->filter, 5576616Sdm199847 merge_SSD_filter, attrs, NULL, qs->flag, &q->result, 5586616Sdm199847 &q->errorp, &q->lrc, NULL, q->udata); 5596616Sdm199847 5606616Sdm199847 if (IS_NLDAP_RC_FATAL(q->lrc)) 5616616Sdm199847 return (nldaprc2retcode(q->lrc)); 5626616Sdm199847 return (IDMAP_SUCCESS); 5636616Sdm199847 } 5646616Sdm199847 5656616Sdm199847 /* 5666616Sdm199847 * Free the batch 5676616Sdm199847 */ 5686616Sdm199847 static 5696616Sdm199847 void 5706616Sdm199847 idmap_nldap_lookup_batch_release(idmap_nldap_query_state_t *qs) 5716616Sdm199847 { 5726616Sdm199847 idmap_nldap_q_t *q; 5736616Sdm199847 int i; 5746616Sdm199847 5756616Sdm199847 if (qs->batch != NULL) 5766616Sdm199847 (void) __ns_ldap_list_batch_release(qs->batch); 5776616Sdm199847 for (i = 0; i < qs->qid; i++) { 5786616Sdm199847 q = &(qs->queries[i]); 5796616Sdm199847 free(q->filter); 5806616Sdm199847 free(q->udata); 5816616Sdm199847 if (q->errorp != NULL) 5826616Sdm199847 (void) __ns_ldap_freeError(&q->errorp); 5836616Sdm199847 if (q->result != NULL) 5846616Sdm199847 (void) __ns_ldap_freeResult(&q->result); 5856616Sdm199847 } 5866616Sdm199847 free(qs); 5876616Sdm199847 } 5886616Sdm199847 5896616Sdm199847 /* 5906616Sdm199847 * Process all requests added to the batch and then free the batch. 5916616Sdm199847 * The results for individual requests will be accessible using the 5926616Sdm199847 * pointers passed during idmap_nldap_lookup_batch_end. 5936616Sdm199847 */ 5946616Sdm199847 static 5956616Sdm199847 idmap_retcode 5966616Sdm199847 idmap_nldap_lookup_batch_end(idmap_nldap_query_state_t *qs) 5976616Sdm199847 { 5986616Sdm199847 idmap_nldap_q_t *q; 5996616Sdm199847 int i; 6006616Sdm199847 ns_ldap_entry_t *entry; 6016616Sdm199847 char **val, *end, *str, *name, *dom; 6026616Sdm199847 idmap_retcode rc = IDMAP_SUCCESS; 6036616Sdm199847 6046616Sdm199847 (void) __ns_ldap_list_batch_end(qs->batch); 6056616Sdm199847 qs->batch = NULL; 6066616Sdm199847 for (i = 0; i < qs->qid; i++) { 6076616Sdm199847 q = &(qs->queries[i]); 6086616Sdm199847 *q->rc = nldaprc2retcode(q->lrc); 6096616Sdm199847 if (*q->rc != IDMAP_SUCCESS) 6106616Sdm199847 continue; 6116616Sdm199847 if (q->result == NULL || 6126616Sdm199847 !q->result->entries_count || 6136616Sdm199847 (entry = q->result->entry) == NULL || 6146616Sdm199847 !entry->attr_count) { 6156616Sdm199847 *q->rc = IDMAP_ERR_NOTFOUND; 6166616Sdm199847 continue; 6176616Sdm199847 } 6186616Sdm199847 /* Get uid/gid */ 6196616Sdm199847 if (q->pid != NULL) { 6206616Sdm199847 val = __ns_ldap_getAttr(entry, 6216616Sdm199847 (q->is_user) ? UIDNUMBER : GIDNUMBER); 6226616Sdm199847 if (val != NULL && *val != NULL) 6236616Sdm199847 *q->pid = strtoul(*val, &end, 10); 6246616Sdm199847 } 6256616Sdm199847 /* Get unixname */ 6266616Sdm199847 if (q->unixname != NULL) { 6276616Sdm199847 val = __ns_ldap_getAttr(entry, 6286616Sdm199847 (q->is_user) ? UID : CN); 6296616Sdm199847 if (val != NULL && *val != NULL) { 6306616Sdm199847 *q->unixname = strdup(*val); 6316616Sdm199847 if (*q->unixname == NULL) { 6326616Sdm199847 rc = *q->rc = IDMAP_ERR_MEMORY; 6336616Sdm199847 goto out; 6346616Sdm199847 } 6356616Sdm199847 } 6366616Sdm199847 } 6376616Sdm199847 /* Get DN for how info */ 6386616Sdm199847 if (q->dn != NULL) { 6396616Sdm199847 val = __ns_ldap_getAttr(entry, DN); 6406616Sdm199847 if (val != NULL && *val != NULL) { 6416616Sdm199847 *q->dn = strdup(*val); 6426616Sdm199847 if (*q->dn == NULL) { 6436616Sdm199847 rc = *q->rc = IDMAP_ERR_MEMORY; 6446616Sdm199847 goto out; 6456616Sdm199847 } 6466616Sdm199847 } 6476616Sdm199847 } 6486616Sdm199847 /* Get nldap name mapping attr name for how info */ 6496616Sdm199847 if (q->attr != NULL) { 6506616Sdm199847 *q->attr = strdup(qs->nldap_winname_attr); 6516616Sdm199847 if (*q->attr == NULL) { 6526616Sdm199847 rc = *q->rc = IDMAP_ERR_MEMORY; 6536616Sdm199847 goto out; 6546616Sdm199847 } 6556616Sdm199847 } 6566616Sdm199847 /* Get nldap name mapping attr value for how info */ 6576616Sdm199847 val = __ns_ldap_getAttr(entry, qs->nldap_winname_attr); 6586616Sdm199847 if (val == NULL || *val == NULL) 6596616Sdm199847 continue; 6606616Sdm199847 if (q->value != NULL) { 6616616Sdm199847 *q->value = strdup(*val); 6626616Sdm199847 if (*q->value == NULL) { 6636616Sdm199847 rc = *q->rc = IDMAP_ERR_MEMORY; 6646616Sdm199847 goto out; 6656616Sdm199847 } 6666616Sdm199847 } 6676616Sdm199847 6686616Sdm199847 /* Get winname and windomain */ 6696616Sdm199847 if (q->winname == NULL && q->windomain == NULL) 6706616Sdm199847 continue; 6716616Sdm199847 /* 6726616Sdm199847 * We need to split the value into winname and 6736616Sdm199847 * windomain. The value could be either in NT4 6746616Sdm199847 * style (i.e. dom\name) or AD-style (i.e. name@dom). 6756616Sdm199847 * We choose the first '\\' if it's in NT4 style and 6766616Sdm199847 * the last '@' if it's in AD-style for the split. 6776616Sdm199847 */ 6786616Sdm199847 name = dom = NULL; 679*9422SAfshin.Ardakani@Sun.COM if (lookup_wksids_name2sid(*val, NULL, NULL, NULL, NULL, NULL, 680*9422SAfshin.Ardakani@Sun.COM NULL) == IDMAP_SUCCESS) { 6816616Sdm199847 name = *val; 6826616Sdm199847 dom = NULL; 6836616Sdm199847 } else if ((str = strchr(*val, '\\')) != NULL) { 6846616Sdm199847 *str = '\0'; 6856616Sdm199847 name = str + 1; 6866616Sdm199847 dom = *val; 6876616Sdm199847 } else if ((str = strrchr(*val, '@')) != NULL) { 6886616Sdm199847 *str = '\0'; 6896616Sdm199847 name = *val; 6906616Sdm199847 dom = str + 1; 6916616Sdm199847 } else { 6926616Sdm199847 idmapdlog(LOG_INFO, "Domain-less " 6936616Sdm199847 "winname (%s) found in Native LDAP", *val); 6946616Sdm199847 *q->rc = IDMAP_ERR_NS_LDAP_BAD_WINNAME; 6956616Sdm199847 continue; 6966616Sdm199847 } 6976616Sdm199847 if (q->winname != NULL) { 6986616Sdm199847 *q->winname = strdup(name); 6996616Sdm199847 if (*q->winname == NULL) { 7006616Sdm199847 rc = *q->rc = IDMAP_ERR_MEMORY; 7016616Sdm199847 goto out; 7026616Sdm199847 } 7036616Sdm199847 } 7046616Sdm199847 if (q->windomain != NULL && dom != NULL) { 7056616Sdm199847 *q->windomain = strdup(dom); 7066616Sdm199847 if (*q->windomain == NULL) { 7076616Sdm199847 rc = *q->rc = IDMAP_ERR_MEMORY; 7086616Sdm199847 goto out; 7096616Sdm199847 } 7106616Sdm199847 } 7116616Sdm199847 } 7126616Sdm199847 7136616Sdm199847 out: 7146616Sdm199847 (void) idmap_nldap_lookup_batch_release(qs); 7156616Sdm199847 return (rc); 7166616Sdm199847 } 7175731Sbaban 7185731Sbaban /* ARGSUSED */ 7195731Sbaban idmap_retcode 7206616Sdm199847 nldap_lookup_one(lookup_state_t *state, idmap_mapping *req, idmap_id_res *res) 7215731Sbaban { 7226616Sdm199847 idmap_mapping_batch batch; 7236616Sdm199847 idmap_ids_res result; 7246616Sdm199847 7256616Sdm199847 /* Using nldap_lookup_batch() */ 7266616Sdm199847 7276616Sdm199847 batch.idmap_mapping_batch_len = 1; 7286616Sdm199847 batch.idmap_mapping_batch_val = req; 7296616Sdm199847 result.ids.ids_len = 1; 7306616Sdm199847 result.ids.ids_val = res; 7316616Sdm199847 return (nldap_lookup_batch(state, &batch, &result)); 7325731Sbaban } 7335731Sbaban 7345731Sbaban /* ARGSUSED */ 7355731Sbaban idmap_retcode 7365731Sbaban nldap_lookup_batch(lookup_state_t *state, idmap_mapping_batch *batch, 7375731Sbaban idmap_ids_res *result) 7385731Sbaban { 7396616Sdm199847 idmap_retcode retcode, rc1; 7406616Sdm199847 int i, add, is_wuser; 7416616Sdm199847 idmap_mapping *req; 7426616Sdm199847 idmap_id_res *res; 7436616Sdm199847 idmap_nldap_query_state_t *qs = NULL; 7446616Sdm199847 idmap_how *how; 7456616Sdm199847 7466616Sdm199847 if (state->nldap_nqueries == 0) 7476616Sdm199847 return (IDMAP_SUCCESS); 7486616Sdm199847 7496616Sdm199847 /* Create nldap lookup batch */ 7506616Sdm199847 retcode = idmap_nldap_lookup_batch_start(state->nldap_nqueries, &qs); 7516616Sdm199847 if (retcode != IDMAP_SUCCESS) { 7526616Sdm199847 idmapdlog(LOG_ERR, 7536616Sdm199847 "Failed to create batch for native LDAP lookup"); 7546616Sdm199847 goto out; 7556616Sdm199847 } 7566616Sdm199847 7576616Sdm199847 qs->nldap_winname_attr = state->nldap_winname_attr; 7586616Sdm199847 qs->defdom = state->defdom; 7596616Sdm199847 7606616Sdm199847 /* Add requests to the batch */ 7616616Sdm199847 for (i = 0, add = 0; i < batch->idmap_mapping_batch_len; i++) { 7626616Sdm199847 req = &batch->idmap_mapping_batch_val[i]; 7636616Sdm199847 res = &result->ids.ids_val[i]; 7646616Sdm199847 retcode = IDMAP_SUCCESS; 7656616Sdm199847 7666616Sdm199847 /* Skip if not marked for nldap lookup */ 7676616Sdm199847 if (!(req->direction & _IDMAP_F_LOOKUP_NLDAP)) 7686616Sdm199847 continue; 7696616Sdm199847 7706616Sdm199847 if (IS_REQUEST_SID(*req, 1)) { 7716616Sdm199847 7726616Sdm199847 /* win2unix request: */ 7736616Sdm199847 7746616Sdm199847 /* 7756616Sdm199847 * When processing a win2unix request, nldap lookup 7766616Sdm199847 * is performed after AD lookup or a successful 7776616Sdm199847 * name-cache lookup. Therefore we should already 7786616Sdm199847 * have sid, winname and sidtype. Note that 7796616Sdm199847 * windomain could be NULL e.g. well-known SIDs. 7806616Sdm199847 */ 7816616Sdm199847 assert(req->id1name != NULL && 7826616Sdm199847 (res->id.idtype == IDMAP_UID || 7836616Sdm199847 res->id.idtype == IDMAP_GID)); 7846616Sdm199847 7856616Sdm199847 /* Skip if we already have pid and unixname */ 7866616Sdm199847 if (req->id2name != NULL && 7876616Sdm199847 res->id.idmap_id_u.uid != SENTINEL_PID) { 7886616Sdm199847 res->retcode = IDMAP_SUCCESS; 7896616Sdm199847 continue; 7906616Sdm199847 } 7916616Sdm199847 7926616Sdm199847 /* Clear leftover value */ 7936616Sdm199847 free(req->id2name); 7946616Sdm199847 req->id2name = NULL; 7956616Sdm199847 7966616Sdm199847 /* Lookup nldap by winname to get pid and unixname */ 7976616Sdm199847 add = 1; 7986616Sdm199847 idmap_info_free(&res->info); 7996616Sdm199847 res->info.src = IDMAP_MAP_SRC_NEW; 8006616Sdm199847 how = &res->info.how; 8016616Sdm199847 how->map_type = IDMAP_MAP_TYPE_DS_NLDAP; 8026616Sdm199847 retcode = idmap_nldap_bywinname_batch_add( 8036616Sdm199847 qs, req->id1name, req->id1domain, 8046616Sdm199847 (res->id.idtype == IDMAP_UID) ? 1 : 0, 8056616Sdm199847 &how->idmap_how_u.nldap.dn, 8066616Sdm199847 &how->idmap_how_u.nldap.attr, 8076616Sdm199847 &how->idmap_how_u.nldap.value, 8086616Sdm199847 &req->id2name, &res->id.idmap_id_u.uid, 8096616Sdm199847 &res->retcode); 8106616Sdm199847 8116616Sdm199847 } else if (IS_REQUEST_UID(*req) || IS_REQUEST_GID(*req)) { 8126616Sdm199847 8136616Sdm199847 /* unix2win request: */ 8146616Sdm199847 8156616Sdm199847 /* Skip if we already have winname */ 8166616Sdm199847 if (req->id2name != NULL) { 8176616Sdm199847 res->retcode = IDMAP_SUCCESS; 8186616Sdm199847 continue; 8196616Sdm199847 } 8206616Sdm199847 8216616Sdm199847 /* Clear old value */ 8226616Sdm199847 free(req->id2domain); 8236616Sdm199847 req->id2domain = NULL; 8246616Sdm199847 8256616Sdm199847 /* Set how info */ 8266616Sdm199847 idmap_info_free(&res->info); 8276616Sdm199847 res->info.src = IDMAP_MAP_SRC_NEW; 8286616Sdm199847 how = &res->info.how; 8296616Sdm199847 how->map_type = IDMAP_MAP_TYPE_DS_NLDAP; 8306616Sdm199847 8316616Sdm199847 /* Lookup nldap by pid or unixname to get winname */ 8326616Sdm199847 if (req->id1.idmap_id_u.uid != SENTINEL_PID) { 8336616Sdm199847 add = 1; 8346616Sdm199847 retcode = idmap_nldap_bypid_batch_add( 8356616Sdm199847 qs, req->id1.idmap_id_u.uid, 8366616Sdm199847 (req->id1.idtype == IDMAP_UID) ? 1 : 0, 8376616Sdm199847 &how->idmap_how_u.nldap.dn, 8386616Sdm199847 &how->idmap_how_u.nldap.attr, 8396616Sdm199847 &how->idmap_how_u.nldap.value, 8406616Sdm199847 &req->id2name, &req->id2domain, 8416616Sdm199847 (req->id1name == NULL) ? 8426616Sdm199847 &req->id1name : NULL, 8436616Sdm199847 &res->retcode); 8446616Sdm199847 } else if (req->id1name != NULL) { 8456616Sdm199847 add = 1; 8466616Sdm199847 retcode = idmap_nldap_byunixname_batch_add( 8476616Sdm199847 qs, req->id1name, 8486616Sdm199847 (req->id1.idtype == IDMAP_UID) ? 1 : 0, 8496616Sdm199847 &how->idmap_how_u.nldap.dn, 8506616Sdm199847 &how->idmap_how_u.nldap.attr, 8516616Sdm199847 &how->idmap_how_u.nldap.value, 8526616Sdm199847 &req->id2name, &req->id2domain, 8536616Sdm199847 &req->id1.idmap_id_u.uid, &res->retcode); 8546616Sdm199847 } 8556616Sdm199847 8566616Sdm199847 } 8576616Sdm199847 8586616Sdm199847 /* 8596616Sdm199847 * nldap_batch_add API returns error only on fatal failures 8606616Sdm199847 * otherwise it returns success and the actual status 8616616Sdm199847 * is stored in the individual request (res->retcode). 8626616Sdm199847 * Stop adding requests to this batch on fatal failures 8636616Sdm199847 * (i.e. if retcode != success) 8646616Sdm199847 */ 8656616Sdm199847 if (retcode != IDMAP_SUCCESS) 8666616Sdm199847 break; 8676616Sdm199847 } 8686616Sdm199847 8696616Sdm199847 if (!add) 8706616Sdm199847 idmap_nldap_lookup_batch_release(qs); 8716616Sdm199847 else if (retcode != IDMAP_SUCCESS) 8726616Sdm199847 idmap_nldap_lookup_batch_release(qs); 8736616Sdm199847 else 8746616Sdm199847 retcode = idmap_nldap_lookup_batch_end(qs); 8756616Sdm199847 8766616Sdm199847 out: 8776616Sdm199847 for (i = 0; i < batch->idmap_mapping_batch_len; i++) { 8786616Sdm199847 req = &batch->idmap_mapping_batch_val[i]; 8796616Sdm199847 res = &result->ids.ids_val[i]; 8806616Sdm199847 if (!(req->direction & _IDMAP_F_LOOKUP_NLDAP)) 8816616Sdm199847 continue; 8826616Sdm199847 8836616Sdm199847 /* Reset nldap flag */ 8846616Sdm199847 req->direction &= ~(_IDMAP_F_LOOKUP_NLDAP); 8856616Sdm199847 8866616Sdm199847 /* 8876616Sdm199847 * As noted earlier retcode != success if there were fatal 8886616Sdm199847 * errors during batch_start and batch_adds. If so then set 8896616Sdm199847 * the status of each nldap request to that error. 8906616Sdm199847 */ 8916616Sdm199847 if (retcode != IDMAP_SUCCESS) { 8926616Sdm199847 res->retcode = retcode; 8936616Sdm199847 continue; 8946616Sdm199847 } 8956616Sdm199847 if (!add) 8966616Sdm199847 continue; 8976616Sdm199847 8986616Sdm199847 /* 8996616Sdm199847 * If we successfully retrieved winname from nldap entry 9006616Sdm199847 * then lookup winname2sid locally. If not found locally 9016616Sdm199847 * then mark this request for AD lookup. 9026616Sdm199847 */ 9036616Sdm199847 if (res->retcode == IDMAP_SUCCESS && 9046616Sdm199847 req->id2name != NULL && 9056616Sdm199847 res->id.idmap_id_u.sid.prefix == NULL && 9066616Sdm199847 (IS_REQUEST_UID(*req) || IS_REQUEST_GID(*req))) { 9076616Sdm199847 9086616Sdm199847 is_wuser = -1; 9096616Sdm199847 rc1 = lookup_name2sid(state->cache, 910*9422SAfshin.Ardakani@Sun.COM req->id2name, req->id2domain, &is_wuser, 911*9422SAfshin.Ardakani@Sun.COM NULL, NULL, 9126616Sdm199847 &res->id.idmap_id_u.sid.prefix, 9136616Sdm199847 &res->id.idmap_id_u.sid.rid, req, 1); 9146616Sdm199847 if (rc1 == IDMAP_SUCCESS) 9156616Sdm199847 res->id.idtype = 9166616Sdm199847 is_wuser ? IDMAP_USID : IDMAP_GSID; 9176616Sdm199847 else if (rc1 == IDMAP_ERR_NOTFOUND) { 9186616Sdm199847 req->direction |= _IDMAP_F_LOOKUP_AD; 9196616Sdm199847 state->ad_nqueries++; 9206616Sdm199847 } else 9216616Sdm199847 res->retcode = rc1; 9226616Sdm199847 } 9236616Sdm199847 9246616Sdm199847 /* 9256616Sdm199847 * Unset non-fatal errors in individual request. This allows 9266616Sdm199847 * the next pass to process other mapping mechanisms for 9276616Sdm199847 * this request. 9286616Sdm199847 */ 9296616Sdm199847 if (res->retcode != IDMAP_SUCCESS && 9306616Sdm199847 res->retcode != IDMAP_ERR_NS_LDAP_BAD_WINNAME && 9316616Sdm199847 !(IDMAP_FATAL_ERROR(res->retcode))) { 9326616Sdm199847 idmap_info_free(&res->info); 9336616Sdm199847 res->retcode = IDMAP_SUCCESS; 9346616Sdm199847 } 9356616Sdm199847 } 9366616Sdm199847 9376616Sdm199847 state->nldap_nqueries = 0; 9386616Sdm199847 return (retcode); 9395731Sbaban } 940