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*6616Sdm199847 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 245731Sbaban * Use is subject to license terms. 255731Sbaban */ 265731Sbaban 275731Sbaban #pragma ident "%Z%%M% %I% %E% SMI" 285731Sbaban 295731Sbaban /* 305731Sbaban * native LDAP related utility routines 315731Sbaban */ 325731Sbaban 335731Sbaban #include "idmapd.h" 34*6616Sdm199847 #include "idmap_priv.h" 35*6616Sdm199847 #include "ns_sldap.h" 36*6616Sdm199847 #include "nldaputils.h" 37*6616Sdm199847 #include <assert.h> 38*6616Sdm199847 39*6616Sdm199847 /* 40*6616Sdm199847 * The following are format strings used to construct LDAP search filters 41*6616Sdm199847 * when looking up Native LDAP directory service. The _F_XXX_SSD format 42*6616Sdm199847 * is used by the libsldap API if a corresponding SSD is defined in 43*6616Sdm199847 * Native LDAP configuration. The SSD contains a string that replaces 44*6616Sdm199847 * the first %s in _F_XXX_SSD. If no SSD is defined then the regular 45*6616Sdm199847 * _F_XXX format is used. 46*6616Sdm199847 * 47*6616Sdm199847 * Note that '\\' needs to be represented as "\\5c" in LDAP filters. 48*6616Sdm199847 */ 49*6616Sdm199847 50*6616Sdm199847 /* Native LDAP lookup using UNIX username */ 51*6616Sdm199847 #define _F_GETPWNAM "(&(objectClass=posixAccount)(uid=%s))" 52*6616Sdm199847 #define _F_GETPWNAM_SSD "(&(%%s)(uid=%s))" 53*6616Sdm199847 54*6616Sdm199847 /* 55*6616Sdm199847 * Native LDAP user lookup using names of well-known SIDs 56*6616Sdm199847 * Note the use of 1$, 2$ in the format string which basically 57*6616Sdm199847 * allows snprintf to re-use its first two arguments. 58*6616Sdm199847 */ 59*6616Sdm199847 #define _F_GETPWWNAMWK \ 60*6616Sdm199847 "(&(objectClass=posixAccount)(|(%s=%s)(%1$s=BUILTIN\\5c%2$s)))" 61*6616Sdm199847 #define _F_GETPWWNAMWK_SSD "(&(%%s)(|(%s=%s)(%1$s=BUILTIN\\5c%2$s)))" 62*6616Sdm199847 63*6616Sdm199847 /* Native LDAP user lookup using winname@windomain OR windomain\winname */ 64*6616Sdm199847 #define _F_GETPWWNAMDOM \ 65*6616Sdm199847 "(&(objectClass=posixAccount)(|(%s=%s@%s)(%1$s=%3$s\\5c%2$s)))" 66*6616Sdm199847 #define _F_GETPWWNAMDOM_SSD "(&(%%s)(|(%s=%s@%s)(%1$s=%3$s\\5c%2$s)))" 67*6616Sdm199847 68*6616Sdm199847 /* Native LDAP lookup using UID */ 69*6616Sdm199847 #define _F_GETPWUID "(&(objectClass=posixAccount)(uidNumber=%u))" 70*6616Sdm199847 #define _F_GETPWUID_SSD "(&(%%s)(uidNumber=%u))" 71*6616Sdm199847 72*6616Sdm199847 /* Native LDAP lookup using UNIX groupname */ 73*6616Sdm199847 #define _F_GETGRNAM "(&(objectClass=posixGroup)(cn=%s))" 74*6616Sdm199847 #define _F_GETGRNAM_SSD "(&(%%s)(cn=%s))" 75*6616Sdm199847 76*6616Sdm199847 /* Native LDAP group lookup using names of well-known SIDs */ 77*6616Sdm199847 #define _F_GETGRWNAMWK \ 78*6616Sdm199847 "(&(objectClass=posixGroup)(|(%s=%s)(%1$s=BUILTIN\\5c%2$s)))" 79*6616Sdm199847 #define _F_GETGRWNAMWK_SSD "(&(%%s)(|(%s=%s)(%1$s=BUILTIN\\5c%2$s)))" 80*6616Sdm199847 81*6616Sdm199847 /* Native LDAP group lookup using winname@windomain OR windomain\winname */ 82*6616Sdm199847 #define _F_GETGRWNAMDOM \ 83*6616Sdm199847 "(&(objectClass=posixGroup)(|(%s=%s@%s)(%1$s=%3$s\\5c%2$s)))" 84*6616Sdm199847 #define _F_GETGRWNAMDOM_SSD "(&(%%s)(|(%s=%s@%s)(%1$s=%3$s\\5c%2$s)))" 85*6616Sdm199847 86*6616Sdm199847 /* Native LDAP lookup using GID */ 87*6616Sdm199847 #define _F_GETGRGID "(&(objectClass=posixGroup)(gidNumber=%u))" 88*6616Sdm199847 #define _F_GETGRGID_SSD "(&(%%s)(gidNumber=%u))" 89*6616Sdm199847 90*6616Sdm199847 /* Native LDAP attribute names */ 91*6616Sdm199847 #define UID "uid" 92*6616Sdm199847 #define CN "cn" 93*6616Sdm199847 #define UIDNUMBER "uidnumber" 94*6616Sdm199847 #define GIDNUMBER "gidnumber" 95*6616Sdm199847 #define DN "dn" 96*6616Sdm199847 97*6616Sdm199847 #define IS_NLDAP_RC_FATAL(x) ((x == NS_LDAP_MEMORY) ? 1 : 0) 98*6616Sdm199847 99*6616Sdm199847 typedef struct idmap_nldap_q { 100*6616Sdm199847 char **winname; 101*6616Sdm199847 char **windomain; 102*6616Sdm199847 char **unixname; 103*6616Sdm199847 uid_t *pid; 104*6616Sdm199847 char **dn; 105*6616Sdm199847 char **attr; 106*6616Sdm199847 char **value; 107*6616Sdm199847 int is_user; 108*6616Sdm199847 idmap_retcode *rc; 109*6616Sdm199847 int lrc; 110*6616Sdm199847 ns_ldap_result_t *result; 111*6616Sdm199847 ns_ldap_error_t *errorp; 112*6616Sdm199847 char *filter; 113*6616Sdm199847 char *udata; 114*6616Sdm199847 } idmap_nldap_q_t; 115*6616Sdm199847 116*6616Sdm199847 typedef struct idmap_nldap_query_state { 117*6616Sdm199847 const char *nldap_winname_attr; 118*6616Sdm199847 const char *defdom; 119*6616Sdm199847 int nqueries; 120*6616Sdm199847 int qid; 121*6616Sdm199847 int flag; 122*6616Sdm199847 ns_ldap_list_batch_t *batch; 123*6616Sdm199847 idmap_nldap_q_t queries[1]; 124*6616Sdm199847 } idmap_nldap_query_state_t; 125*6616Sdm199847 126*6616Sdm199847 /* 127*6616Sdm199847 * This routine has been copied from lib/nsswitch/ldap/common/ldap_utils.c 128*6616Sdm199847 * after removing the debug statements. 129*6616Sdm199847 * 130*6616Sdm199847 * This is a generic filter callback function for merging the filter 131*6616Sdm199847 * from service search descriptor with an existing search filter. This 132*6616Sdm199847 * routine expects userdata to contain a format string with a single %s 133*6616Sdm199847 * in it, and will use the format string with sprintf() to insert the 134*6616Sdm199847 * SSD filter. 135*6616Sdm199847 * 136*6616Sdm199847 * This routine and userdata are passed to the __ns_ldap_list_batch_add() 137*6616Sdm199847 * API. 138*6616Sdm199847 * 139*6616Sdm199847 * Consider an example that uses __ns_ldap_list_batch_add() to lookup 140*6616Sdm199847 * native LDAP directory using a given userid 'xy12345'. In this 141*6616Sdm199847 * example the userdata will contain the filter "(&(%s)(cn=xy1234))". 142*6616Sdm199847 * If a SSD is defined to replace the rfc2307bis specified filter 143*6616Sdm199847 * i.e. (objectClass=posixAccount) by a site-specific filter 144*6616Sdm199847 * say (department=sds) then this routine when called will produce 145*6616Sdm199847 * "(&(department=sds)(uid=xy1234))" as the real search filter. 146*6616Sdm199847 */ 147*6616Sdm199847 static 148*6616Sdm199847 int 149*6616Sdm199847 merge_SSD_filter(const ns_ldap_search_desc_t *desc, 150*6616Sdm199847 char **realfilter, const void *userdata) 151*6616Sdm199847 { 152*6616Sdm199847 int len; 153*6616Sdm199847 if (realfilter == NULL) 154*6616Sdm199847 return (NS_LDAP_INVALID_PARAM); 155*6616Sdm199847 *realfilter = NULL; 156*6616Sdm199847 if (desc == NULL || desc->filter == NULL || userdata == NULL) 157*6616Sdm199847 return (NS_LDAP_INVALID_PARAM); 158*6616Sdm199847 len = strlen(userdata) + strlen(desc->filter) + 1; 159*6616Sdm199847 *realfilter = (char *)malloc(len); 160*6616Sdm199847 if (*realfilter == NULL) 161*6616Sdm199847 return (NS_LDAP_MEMORY); 162*6616Sdm199847 (void) sprintf(*realfilter, (char *)userdata, desc->filter); 163*6616Sdm199847 return (NS_LDAP_SUCCESS); 164*6616Sdm199847 } 165*6616Sdm199847 166*6616Sdm199847 static 167*6616Sdm199847 char 168*6616Sdm199847 hex_char(int n) 169*6616Sdm199847 { 170*6616Sdm199847 return ("0123456789abcdef"[n & 0xf]); 171*6616Sdm199847 } 172*6616Sdm199847 173*6616Sdm199847 /* 174*6616Sdm199847 * If the input string contains special characters that needs to be 175*6616Sdm199847 * escaped before the string can be used in a LDAP filter then this 176*6616Sdm199847 * function will return a new sanitized string. Otherwise this function 177*6616Sdm199847 * returns the input string (This saves us un-necessary memory allocations 178*6616Sdm199847 * especially when processing a batch of requests). The caller must free 179*6616Sdm199847 * the returned string if it isn't the input string. 180*6616Sdm199847 * 181*6616Sdm199847 * The escape mechanism for LDAP filter is described in RFC2254 basically 182*6616Sdm199847 * it's \hh where hh are the two hexadecimal digits representing the ASCII 183*6616Sdm199847 * value of the encoded character (case of hh is not significant). 184*6616Sdm199847 * Example: * -> \2a, ( -> \28, ) -> \29, \ -> \5c, 185*6616Sdm199847 * 186*6616Sdm199847 * outstring = sanitize_for_ldap_filter(instring); 187*6616Sdm199847 * if (outstring == NULL) 188*6616Sdm199847 * Out of memory 189*6616Sdm199847 * else 190*6616Sdm199847 * Use outstring 191*6616Sdm199847 * if (outstring != instring) 192*6616Sdm199847 * free(outstring); 193*6616Sdm199847 * done 194*6616Sdm199847 */ 195*6616Sdm199847 char * 196*6616Sdm199847 sanitize_for_ldap_filter(const char *str) 197*6616Sdm199847 { 198*6616Sdm199847 const char *p; 199*6616Sdm199847 char *q, *s_str = NULL; 200*6616Sdm199847 int n; 201*6616Sdm199847 202*6616Sdm199847 /* Get a count of special characters */ 203*6616Sdm199847 for (p = str, n = 0; *p; p++) 204*6616Sdm199847 if (*p == '*' || *p == '(' || *p == ')' || 205*6616Sdm199847 *p == '\\' || *p == '%') 206*6616Sdm199847 n++; 207*6616Sdm199847 /* If count is zero then no need to sanitize */ 208*6616Sdm199847 if (n == 0) 209*6616Sdm199847 return ((char *)str); 210*6616Sdm199847 /* Create output buffer that will contain the sanitized value */ 211*6616Sdm199847 s_str = calloc(1, n * 2 + strlen(str) + 1); 212*6616Sdm199847 if (s_str == NULL) 213*6616Sdm199847 return (NULL); 214*6616Sdm199847 for (p = str, q = s_str; *p; p++) { 215*6616Sdm199847 if (*p == '*' || *p == '(' || *p == ')' || 216*6616Sdm199847 *p == '\\' || *p == '%') { 217*6616Sdm199847 *q++ = '\\'; 218*6616Sdm199847 *q++ = hex_char(*p >> 4); 219*6616Sdm199847 *q++ = hex_char(*p & 0xf); 220*6616Sdm199847 } else 221*6616Sdm199847 *q++ = *p; 222*6616Sdm199847 } 223*6616Sdm199847 return (s_str); 224*6616Sdm199847 } 225*6616Sdm199847 226*6616Sdm199847 /* 227*6616Sdm199847 * Map libsldap status to idmap status 228*6616Sdm199847 */ 229*6616Sdm199847 static 230*6616Sdm199847 idmap_retcode 231*6616Sdm199847 nldaprc2retcode(int rc) 232*6616Sdm199847 { 233*6616Sdm199847 switch (rc) { 234*6616Sdm199847 case NS_LDAP_SUCCESS: 235*6616Sdm199847 case NS_LDAP_SUCCESS_WITH_INFO: 236*6616Sdm199847 return (IDMAP_SUCCESS); 237*6616Sdm199847 case NS_LDAP_NOTFOUND: 238*6616Sdm199847 return (IDMAP_ERR_NOTFOUND); 239*6616Sdm199847 case NS_LDAP_MEMORY: 240*6616Sdm199847 return (IDMAP_ERR_MEMORY); 241*6616Sdm199847 case NS_LDAP_CONFIG: 242*6616Sdm199847 return (IDMAP_ERR_NS_LDAP_CFG); 243*6616Sdm199847 case NS_LDAP_OP_FAILED: 244*6616Sdm199847 return (IDMAP_ERR_NS_LDAP_OP_FAILED); 245*6616Sdm199847 case NS_LDAP_PARTIAL: 246*6616Sdm199847 return (IDMAP_ERR_NS_LDAP_PARTIAL); 247*6616Sdm199847 case NS_LDAP_INTERNAL: 248*6616Sdm199847 return (IDMAP_ERR_INTERNAL); 249*6616Sdm199847 case NS_LDAP_INVALID_PARAM: 250*6616Sdm199847 return (IDMAP_ERR_ARG); 251*6616Sdm199847 default: 252*6616Sdm199847 return (IDMAP_ERR_OTHER); 253*6616Sdm199847 } 254*6616Sdm199847 /*NOTREACHED*/ 255*6616Sdm199847 } 256*6616Sdm199847 257*6616Sdm199847 /* 258*6616Sdm199847 * Create a batch for native LDAP lookup. 259*6616Sdm199847 */ 260*6616Sdm199847 static 261*6616Sdm199847 idmap_retcode 262*6616Sdm199847 idmap_nldap_lookup_batch_start(int nqueries, idmap_nldap_query_state_t **qs) 263*6616Sdm199847 { 264*6616Sdm199847 idmap_nldap_query_state_t *s; 265*6616Sdm199847 266*6616Sdm199847 s = calloc(1, sizeof (*s) + 267*6616Sdm199847 (nqueries - 1) * sizeof (idmap_nldap_q_t)); 268*6616Sdm199847 if (s == NULL) 269*6616Sdm199847 return (IDMAP_ERR_MEMORY); 270*6616Sdm199847 if (__ns_ldap_list_batch_start(&s->batch) != NS_LDAP_SUCCESS) { 271*6616Sdm199847 free(s); 272*6616Sdm199847 return (IDMAP_ERR_MEMORY); 273*6616Sdm199847 } 274*6616Sdm199847 s->nqueries = nqueries; 275*6616Sdm199847 s->flag = NS_LDAP_KEEP_CONN; 276*6616Sdm199847 *qs = s; 277*6616Sdm199847 return (IDMAP_SUCCESS); 278*6616Sdm199847 } 279*6616Sdm199847 280*6616Sdm199847 /* 281*6616Sdm199847 * Add a lookup by winname request to the batch. 282*6616Sdm199847 */ 283*6616Sdm199847 static 284*6616Sdm199847 idmap_retcode 285*6616Sdm199847 idmap_nldap_bywinname_batch_add(idmap_nldap_query_state_t *qs, 286*6616Sdm199847 const char *winname, const char *windomain, int is_user, 287*6616Sdm199847 char **dn, char **attr, char **value, 288*6616Sdm199847 char **unixname, uid_t *pid, idmap_retcode *rc) 289*6616Sdm199847 { 290*6616Sdm199847 idmap_nldap_q_t *q; 291*6616Sdm199847 const char *db, *filter, *udata; 292*6616Sdm199847 int flen, ulen, wksid = 0; 293*6616Sdm199847 char *s_winname, *s_windomain; 294*6616Sdm199847 const char **attrs; 295*6616Sdm199847 const char *pwd_attrs[] = {UID, UIDNUMBER, NULL, NULL}; 296*6616Sdm199847 const char *grp_attrs[] = {CN, GIDNUMBER, NULL, NULL}; 297*6616Sdm199847 298*6616Sdm199847 s_winname = s_windomain = NULL; 299*6616Sdm199847 q = &(qs->queries[qs->qid++]); 300*6616Sdm199847 q->unixname = unixname; 301*6616Sdm199847 q->pid = pid; 302*6616Sdm199847 q->rc = rc; 303*6616Sdm199847 q->is_user = is_user; 304*6616Sdm199847 q->dn = dn; 305*6616Sdm199847 q->attr = attr; 306*6616Sdm199847 q->value = value; 307*6616Sdm199847 308*6616Sdm199847 if (is_user) { 309*6616Sdm199847 db = "passwd"; 310*6616Sdm199847 if (lookup_wksids_name2sid(winname, NULL, NULL, NULL, 311*6616Sdm199847 NULL) == IDMAP_SUCCESS) { 312*6616Sdm199847 filter = _F_GETPWWNAMWK; 313*6616Sdm199847 udata = _F_GETPWWNAMWK_SSD; 314*6616Sdm199847 wksid = 1; 315*6616Sdm199847 } else if (windomain != NULL) { 316*6616Sdm199847 filter = _F_GETPWWNAMDOM; 317*6616Sdm199847 udata = _F_GETPWWNAMDOM_SSD; 318*6616Sdm199847 } else { 319*6616Sdm199847 *q->rc = IDMAP_ERR_DOMAIN_NOTFOUND; 320*6616Sdm199847 goto errout; 321*6616Sdm199847 } 322*6616Sdm199847 pwd_attrs[2] = qs->nldap_winname_attr; 323*6616Sdm199847 attrs = pwd_attrs; 324*6616Sdm199847 } else { 325*6616Sdm199847 db = "group"; 326*6616Sdm199847 if (lookup_wksids_name2sid(winname, NULL, NULL, NULL, 327*6616Sdm199847 NULL) == IDMAP_SUCCESS) { 328*6616Sdm199847 filter = _F_GETGRWNAMWK; 329*6616Sdm199847 udata = _F_GETGRWNAMWK_SSD; 330*6616Sdm199847 wksid = 1; 331*6616Sdm199847 } else if (windomain != NULL) { 332*6616Sdm199847 filter = _F_GETGRWNAMDOM; 333*6616Sdm199847 udata = _F_GETGRWNAMDOM_SSD; 334*6616Sdm199847 } else { 335*6616Sdm199847 *q->rc = IDMAP_ERR_DOMAIN_NOTFOUND; 336*6616Sdm199847 goto errout; 337*6616Sdm199847 } 338*6616Sdm199847 grp_attrs[2] = qs->nldap_winname_attr; 339*6616Sdm199847 attrs = grp_attrs; 340*6616Sdm199847 } 341*6616Sdm199847 342*6616Sdm199847 /* 343*6616Sdm199847 * Sanitize names. No need to sanitize qs->nldap_winname_attr 344*6616Sdm199847 * because if it contained any of the special characters then 345*6616Sdm199847 * it would have been rejected by the function that reads it 346*6616Sdm199847 * from the SMF config. LDAP attribute names can only contain 347*6616Sdm199847 * letters, digits or hyphens. 348*6616Sdm199847 */ 349*6616Sdm199847 s_winname = sanitize_for_ldap_filter(winname); 350*6616Sdm199847 if (s_winname == NULL) { 351*6616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 352*6616Sdm199847 goto errout; 353*6616Sdm199847 } 354*6616Sdm199847 /* windomain could be NULL for names of well-known SIDs */ 355*6616Sdm199847 if (windomain != NULL) { 356*6616Sdm199847 s_windomain = sanitize_for_ldap_filter(windomain); 357*6616Sdm199847 if (s_windomain == NULL) { 358*6616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 359*6616Sdm199847 goto errout; 360*6616Sdm199847 } 361*6616Sdm199847 } 362*6616Sdm199847 363*6616Sdm199847 /* Construct the filter and udata using snprintf. */ 364*6616Sdm199847 if (wksid) { 365*6616Sdm199847 flen = snprintf(NULL, 0, filter, qs->nldap_winname_attr, 366*6616Sdm199847 s_winname) + 1; 367*6616Sdm199847 ulen = snprintf(NULL, 0, udata, qs->nldap_winname_attr, 368*6616Sdm199847 s_winname) + 1; 369*6616Sdm199847 } else { 370*6616Sdm199847 flen = snprintf(NULL, 0, filter, qs->nldap_winname_attr, 371*6616Sdm199847 s_winname, s_windomain) + 1; 372*6616Sdm199847 ulen = snprintf(NULL, 0, udata, qs->nldap_winname_attr, 373*6616Sdm199847 s_winname, s_windomain) + 1; 374*6616Sdm199847 } 375*6616Sdm199847 376*6616Sdm199847 q->filter = malloc(flen); 377*6616Sdm199847 if (q->filter == NULL) { 378*6616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 379*6616Sdm199847 goto errout; 380*6616Sdm199847 } 381*6616Sdm199847 q->udata = malloc(ulen); 382*6616Sdm199847 if (q->udata == NULL) { 383*6616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 384*6616Sdm199847 goto errout; 385*6616Sdm199847 } 386*6616Sdm199847 387*6616Sdm199847 if (wksid) { 388*6616Sdm199847 (void) snprintf(q->filter, flen, filter, 389*6616Sdm199847 qs->nldap_winname_attr, s_winname); 390*6616Sdm199847 (void) snprintf(q->udata, ulen, udata, 391*6616Sdm199847 qs->nldap_winname_attr, s_winname); 392*6616Sdm199847 } else { 393*6616Sdm199847 (void) snprintf(q->filter, flen, filter, 394*6616Sdm199847 qs->nldap_winname_attr, s_winname, s_windomain); 395*6616Sdm199847 (void) snprintf(q->udata, ulen, udata, 396*6616Sdm199847 qs->nldap_winname_attr, s_winname, s_windomain); 397*6616Sdm199847 } 398*6616Sdm199847 399*6616Sdm199847 if (s_winname != winname) 400*6616Sdm199847 free(s_winname); 401*6616Sdm199847 if (s_windomain != windomain) 402*6616Sdm199847 free(s_windomain); 403*6616Sdm199847 404*6616Sdm199847 q->lrc = __ns_ldap_list_batch_add(qs->batch, db, q->filter, 405*6616Sdm199847 merge_SSD_filter, attrs, NULL, qs->flag, &q->result, 406*6616Sdm199847 &q->errorp, &q->lrc, NULL, q->udata); 407*6616Sdm199847 408*6616Sdm199847 if (IS_NLDAP_RC_FATAL(q->lrc)) 409*6616Sdm199847 return (nldaprc2retcode(q->lrc)); 410*6616Sdm199847 return (IDMAP_SUCCESS); 411*6616Sdm199847 412*6616Sdm199847 errout: 413*6616Sdm199847 /* query q and its content will be freed by batch_release */ 414*6616Sdm199847 if (s_winname != winname) 415*6616Sdm199847 free(s_winname); 416*6616Sdm199847 if (s_windomain != windomain) 417*6616Sdm199847 free(s_windomain); 418*6616Sdm199847 return (*q->rc); 419*6616Sdm199847 } 420*6616Sdm199847 421*6616Sdm199847 /* 422*6616Sdm199847 * Add a lookup by uid/gid request to the batch. 423*6616Sdm199847 */ 424*6616Sdm199847 static 425*6616Sdm199847 idmap_retcode 426*6616Sdm199847 idmap_nldap_bypid_batch_add(idmap_nldap_query_state_t *qs, 427*6616Sdm199847 uid_t pid, int is_user, char **dn, char **attr, char **value, 428*6616Sdm199847 char **winname, char **windomain, 429*6616Sdm199847 char **unixname, idmap_retcode *rc) 430*6616Sdm199847 { 431*6616Sdm199847 idmap_nldap_q_t *q; 432*6616Sdm199847 const char *db, *filter, *udata; 433*6616Sdm199847 int len; 434*6616Sdm199847 const char **attrs; 435*6616Sdm199847 const char *pwd_attrs[] = {UID, NULL, NULL}; 436*6616Sdm199847 const char *grp_attrs[] = {CN, NULL, NULL}; 437*6616Sdm199847 438*6616Sdm199847 q = &(qs->queries[qs->qid++]); 439*6616Sdm199847 q->winname = winname; 440*6616Sdm199847 q->windomain = windomain; 441*6616Sdm199847 q->unixname = unixname; 442*6616Sdm199847 q->rc = rc; 443*6616Sdm199847 q->is_user = is_user; 444*6616Sdm199847 q->dn = dn; 445*6616Sdm199847 q->attr = attr; 446*6616Sdm199847 q->value = value; 447*6616Sdm199847 448*6616Sdm199847 if (is_user) { 449*6616Sdm199847 db = "passwd"; 450*6616Sdm199847 filter = _F_GETPWUID; 451*6616Sdm199847 udata = _F_GETPWUID_SSD; 452*6616Sdm199847 pwd_attrs[1] = qs->nldap_winname_attr; 453*6616Sdm199847 attrs = pwd_attrs; 454*6616Sdm199847 } else { 455*6616Sdm199847 db = "group"; 456*6616Sdm199847 filter = _F_GETGRGID; 457*6616Sdm199847 udata = _F_GETGRGID_SSD; 458*6616Sdm199847 grp_attrs[1] = qs->nldap_winname_attr; 459*6616Sdm199847 attrs = grp_attrs; 460*6616Sdm199847 } 461*6616Sdm199847 462*6616Sdm199847 len = snprintf(NULL, 0, filter, pid) + 1; 463*6616Sdm199847 q->filter = malloc(len); 464*6616Sdm199847 if (q->filter == NULL) { 465*6616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 466*6616Sdm199847 return (IDMAP_ERR_MEMORY); 467*6616Sdm199847 } 468*6616Sdm199847 (void) snprintf(q->filter, len, filter, pid); 469*6616Sdm199847 470*6616Sdm199847 len = snprintf(NULL, 0, udata, pid) + 1; 471*6616Sdm199847 q->udata = malloc(len); 472*6616Sdm199847 if (q->udata == NULL) { 473*6616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 474*6616Sdm199847 return (IDMAP_ERR_MEMORY); 475*6616Sdm199847 } 476*6616Sdm199847 (void) snprintf(q->udata, len, udata, pid); 477*6616Sdm199847 478*6616Sdm199847 q->lrc = __ns_ldap_list_batch_add(qs->batch, db, q->filter, 479*6616Sdm199847 merge_SSD_filter, attrs, NULL, qs->flag, &q->result, 480*6616Sdm199847 &q->errorp, &q->lrc, NULL, q->udata); 481*6616Sdm199847 482*6616Sdm199847 if (IS_NLDAP_RC_FATAL(q->lrc)) 483*6616Sdm199847 return (nldaprc2retcode(q->lrc)); 484*6616Sdm199847 return (IDMAP_SUCCESS); 485*6616Sdm199847 } 486*6616Sdm199847 487*6616Sdm199847 /* 488*6616Sdm199847 * Add a lookup by user/group name request to the batch. 489*6616Sdm199847 */ 490*6616Sdm199847 static 491*6616Sdm199847 idmap_retcode 492*6616Sdm199847 idmap_nldap_byunixname_batch_add(idmap_nldap_query_state_t *qs, 493*6616Sdm199847 const char *unixname, int is_user, 494*6616Sdm199847 char **dn, char **attr, char **value, 495*6616Sdm199847 char **winname, char **windomain, uid_t *pid, idmap_retcode *rc) 496*6616Sdm199847 { 497*6616Sdm199847 idmap_nldap_q_t *q; 498*6616Sdm199847 const char *db, *filter, *udata; 499*6616Sdm199847 int len; 500*6616Sdm199847 char *s_unixname = NULL; 501*6616Sdm199847 const char **attrs; 502*6616Sdm199847 const char *pwd_attrs[] = {UIDNUMBER, NULL, NULL}; 503*6616Sdm199847 const char *grp_attrs[] = {GIDNUMBER, NULL, NULL}; 504*6616Sdm199847 505*6616Sdm199847 q = &(qs->queries[qs->qid++]); 506*6616Sdm199847 q->winname = winname; 507*6616Sdm199847 q->windomain = windomain; 508*6616Sdm199847 q->pid = pid; 509*6616Sdm199847 q->rc = rc; 510*6616Sdm199847 q->is_user = is_user; 511*6616Sdm199847 q->dn = dn; 512*6616Sdm199847 q->attr = attr; 513*6616Sdm199847 q->value = value; 514*6616Sdm199847 515*6616Sdm199847 if (is_user) { 516*6616Sdm199847 db = "passwd"; 517*6616Sdm199847 filter = _F_GETPWNAM; 518*6616Sdm199847 udata = _F_GETPWNAM_SSD; 519*6616Sdm199847 pwd_attrs[1] = qs->nldap_winname_attr; 520*6616Sdm199847 attrs = pwd_attrs; 521*6616Sdm199847 } else { 522*6616Sdm199847 db = "group"; 523*6616Sdm199847 filter = _F_GETGRNAM; 524*6616Sdm199847 udata = _F_GETGRNAM_SSD; 525*6616Sdm199847 grp_attrs[1] = qs->nldap_winname_attr; 526*6616Sdm199847 attrs = grp_attrs; 527*6616Sdm199847 } 528*6616Sdm199847 529*6616Sdm199847 s_unixname = sanitize_for_ldap_filter(unixname); 530*6616Sdm199847 if (s_unixname == NULL) { 531*6616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 532*6616Sdm199847 return (IDMAP_ERR_MEMORY); 533*6616Sdm199847 } 534*6616Sdm199847 535*6616Sdm199847 len = snprintf(NULL, 0, filter, s_unixname) + 1; 536*6616Sdm199847 q->filter = malloc(len); 537*6616Sdm199847 if (q->filter == NULL) { 538*6616Sdm199847 if (s_unixname != unixname) 539*6616Sdm199847 free(s_unixname); 540*6616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 541*6616Sdm199847 return (IDMAP_ERR_MEMORY); 542*6616Sdm199847 } 543*6616Sdm199847 (void) snprintf(q->filter, len, filter, s_unixname); 544*6616Sdm199847 545*6616Sdm199847 len = snprintf(NULL, 0, udata, s_unixname) + 1; 546*6616Sdm199847 q->udata = malloc(len); 547*6616Sdm199847 if (q->udata == NULL) { 548*6616Sdm199847 if (s_unixname != unixname) 549*6616Sdm199847 free(s_unixname); 550*6616Sdm199847 *q->rc = IDMAP_ERR_MEMORY; 551*6616Sdm199847 return (IDMAP_ERR_MEMORY); 552*6616Sdm199847 } 553*6616Sdm199847 (void) snprintf(q->udata, len, udata, s_unixname); 554*6616Sdm199847 555*6616Sdm199847 if (s_unixname != unixname) 556*6616Sdm199847 free(s_unixname); 557*6616Sdm199847 558*6616Sdm199847 q->lrc = __ns_ldap_list_batch_add(qs->batch, db, q->filter, 559*6616Sdm199847 merge_SSD_filter, attrs, NULL, qs->flag, &q->result, 560*6616Sdm199847 &q->errorp, &q->lrc, NULL, q->udata); 561*6616Sdm199847 562*6616Sdm199847 if (IS_NLDAP_RC_FATAL(q->lrc)) 563*6616Sdm199847 return (nldaprc2retcode(q->lrc)); 564*6616Sdm199847 return (IDMAP_SUCCESS); 565*6616Sdm199847 } 566*6616Sdm199847 567*6616Sdm199847 /* 568*6616Sdm199847 * Free the batch 569*6616Sdm199847 */ 570*6616Sdm199847 static 571*6616Sdm199847 void 572*6616Sdm199847 idmap_nldap_lookup_batch_release(idmap_nldap_query_state_t *qs) 573*6616Sdm199847 { 574*6616Sdm199847 idmap_nldap_q_t *q; 575*6616Sdm199847 int i; 576*6616Sdm199847 577*6616Sdm199847 if (qs->batch != NULL) 578*6616Sdm199847 (void) __ns_ldap_list_batch_release(qs->batch); 579*6616Sdm199847 for (i = 0; i < qs->qid; i++) { 580*6616Sdm199847 q = &(qs->queries[i]); 581*6616Sdm199847 free(q->filter); 582*6616Sdm199847 free(q->udata); 583*6616Sdm199847 if (q->errorp != NULL) 584*6616Sdm199847 (void) __ns_ldap_freeError(&q->errorp); 585*6616Sdm199847 if (q->result != NULL) 586*6616Sdm199847 (void) __ns_ldap_freeResult(&q->result); 587*6616Sdm199847 } 588*6616Sdm199847 free(qs); 589*6616Sdm199847 } 590*6616Sdm199847 591*6616Sdm199847 /* 592*6616Sdm199847 * Process all requests added to the batch and then free the batch. 593*6616Sdm199847 * The results for individual requests will be accessible using the 594*6616Sdm199847 * pointers passed during idmap_nldap_lookup_batch_end. 595*6616Sdm199847 */ 596*6616Sdm199847 static 597*6616Sdm199847 idmap_retcode 598*6616Sdm199847 idmap_nldap_lookup_batch_end(idmap_nldap_query_state_t *qs) 599*6616Sdm199847 { 600*6616Sdm199847 idmap_nldap_q_t *q; 601*6616Sdm199847 int i; 602*6616Sdm199847 ns_ldap_entry_t *entry; 603*6616Sdm199847 char **val, *end, *str, *name, *dom; 604*6616Sdm199847 idmap_retcode rc = IDMAP_SUCCESS; 605*6616Sdm199847 606*6616Sdm199847 (void) __ns_ldap_list_batch_end(qs->batch); 607*6616Sdm199847 qs->batch = NULL; 608*6616Sdm199847 for (i = 0; i < qs->qid; i++) { 609*6616Sdm199847 q = &(qs->queries[i]); 610*6616Sdm199847 *q->rc = nldaprc2retcode(q->lrc); 611*6616Sdm199847 if (*q->rc != IDMAP_SUCCESS) 612*6616Sdm199847 continue; 613*6616Sdm199847 if (q->result == NULL || 614*6616Sdm199847 !q->result->entries_count || 615*6616Sdm199847 (entry = q->result->entry) == NULL || 616*6616Sdm199847 !entry->attr_count) { 617*6616Sdm199847 *q->rc = IDMAP_ERR_NOTFOUND; 618*6616Sdm199847 continue; 619*6616Sdm199847 } 620*6616Sdm199847 /* Get uid/gid */ 621*6616Sdm199847 if (q->pid != NULL) { 622*6616Sdm199847 val = __ns_ldap_getAttr(entry, 623*6616Sdm199847 (q->is_user) ? UIDNUMBER : GIDNUMBER); 624*6616Sdm199847 if (val != NULL && *val != NULL) 625*6616Sdm199847 *q->pid = strtoul(*val, &end, 10); 626*6616Sdm199847 } 627*6616Sdm199847 /* Get unixname */ 628*6616Sdm199847 if (q->unixname != NULL) { 629*6616Sdm199847 val = __ns_ldap_getAttr(entry, 630*6616Sdm199847 (q->is_user) ? UID : CN); 631*6616Sdm199847 if (val != NULL && *val != NULL) { 632*6616Sdm199847 *q->unixname = strdup(*val); 633*6616Sdm199847 if (*q->unixname == NULL) { 634*6616Sdm199847 rc = *q->rc = IDMAP_ERR_MEMORY; 635*6616Sdm199847 goto out; 636*6616Sdm199847 } 637*6616Sdm199847 } 638*6616Sdm199847 } 639*6616Sdm199847 /* Get DN for how info */ 640*6616Sdm199847 if (q->dn != NULL) { 641*6616Sdm199847 val = __ns_ldap_getAttr(entry, DN); 642*6616Sdm199847 if (val != NULL && *val != NULL) { 643*6616Sdm199847 *q->dn = strdup(*val); 644*6616Sdm199847 if (*q->dn == NULL) { 645*6616Sdm199847 rc = *q->rc = IDMAP_ERR_MEMORY; 646*6616Sdm199847 goto out; 647*6616Sdm199847 } 648*6616Sdm199847 } 649*6616Sdm199847 } 650*6616Sdm199847 /* Get nldap name mapping attr name for how info */ 651*6616Sdm199847 if (q->attr != NULL) { 652*6616Sdm199847 *q->attr = strdup(qs->nldap_winname_attr); 653*6616Sdm199847 if (*q->attr == NULL) { 654*6616Sdm199847 rc = *q->rc = IDMAP_ERR_MEMORY; 655*6616Sdm199847 goto out; 656*6616Sdm199847 } 657*6616Sdm199847 } 658*6616Sdm199847 /* Get nldap name mapping attr value for how info */ 659*6616Sdm199847 val = __ns_ldap_getAttr(entry, qs->nldap_winname_attr); 660*6616Sdm199847 if (val == NULL || *val == NULL) 661*6616Sdm199847 continue; 662*6616Sdm199847 if (q->value != NULL) { 663*6616Sdm199847 *q->value = strdup(*val); 664*6616Sdm199847 if (*q->value == NULL) { 665*6616Sdm199847 rc = *q->rc = IDMAP_ERR_MEMORY; 666*6616Sdm199847 goto out; 667*6616Sdm199847 } 668*6616Sdm199847 } 669*6616Sdm199847 670*6616Sdm199847 /* Get winname and windomain */ 671*6616Sdm199847 if (q->winname == NULL && q->windomain == NULL) 672*6616Sdm199847 continue; 673*6616Sdm199847 /* 674*6616Sdm199847 * We need to split the value into winname and 675*6616Sdm199847 * windomain. The value could be either in NT4 676*6616Sdm199847 * style (i.e. dom\name) or AD-style (i.e. name@dom). 677*6616Sdm199847 * We choose the first '\\' if it's in NT4 style and 678*6616Sdm199847 * the last '@' if it's in AD-style for the split. 679*6616Sdm199847 */ 680*6616Sdm199847 name = dom = NULL; 681*6616Sdm199847 if (lookup_wksids_name2sid(*val, NULL, NULL, NULL, NULL) == 682*6616Sdm199847 IDMAP_SUCCESS) { 683*6616Sdm199847 name = *val; 684*6616Sdm199847 dom = NULL; 685*6616Sdm199847 } else if ((str = strchr(*val, '\\')) != NULL) { 686*6616Sdm199847 *str = '\0'; 687*6616Sdm199847 name = str + 1; 688*6616Sdm199847 dom = *val; 689*6616Sdm199847 } else if ((str = strrchr(*val, '@')) != NULL) { 690*6616Sdm199847 *str = '\0'; 691*6616Sdm199847 name = *val; 692*6616Sdm199847 dom = str + 1; 693*6616Sdm199847 } else { 694*6616Sdm199847 idmapdlog(LOG_INFO, "Domain-less " 695*6616Sdm199847 "winname (%s) found in Native LDAP", *val); 696*6616Sdm199847 *q->rc = IDMAP_ERR_NS_LDAP_BAD_WINNAME; 697*6616Sdm199847 continue; 698*6616Sdm199847 } 699*6616Sdm199847 if (q->winname != NULL) { 700*6616Sdm199847 *q->winname = strdup(name); 701*6616Sdm199847 if (*q->winname == NULL) { 702*6616Sdm199847 rc = *q->rc = IDMAP_ERR_MEMORY; 703*6616Sdm199847 goto out; 704*6616Sdm199847 } 705*6616Sdm199847 } 706*6616Sdm199847 if (q->windomain != NULL && dom != NULL) { 707*6616Sdm199847 *q->windomain = strdup(dom); 708*6616Sdm199847 if (*q->windomain == NULL) { 709*6616Sdm199847 rc = *q->rc = IDMAP_ERR_MEMORY; 710*6616Sdm199847 goto out; 711*6616Sdm199847 } 712*6616Sdm199847 } 713*6616Sdm199847 } 714*6616Sdm199847 715*6616Sdm199847 out: 716*6616Sdm199847 (void) idmap_nldap_lookup_batch_release(qs); 717*6616Sdm199847 return (rc); 718*6616Sdm199847 } 7195731Sbaban 7205731Sbaban /* ARGSUSED */ 7215731Sbaban idmap_retcode 722*6616Sdm199847 nldap_lookup_one(lookup_state_t *state, idmap_mapping *req, idmap_id_res *res) 7235731Sbaban { 724*6616Sdm199847 idmap_mapping_batch batch; 725*6616Sdm199847 idmap_ids_res result; 726*6616Sdm199847 727*6616Sdm199847 /* Using nldap_lookup_batch() */ 728*6616Sdm199847 729*6616Sdm199847 batch.idmap_mapping_batch_len = 1; 730*6616Sdm199847 batch.idmap_mapping_batch_val = req; 731*6616Sdm199847 result.ids.ids_len = 1; 732*6616Sdm199847 result.ids.ids_val = res; 733*6616Sdm199847 return (nldap_lookup_batch(state, &batch, &result)); 7345731Sbaban } 7355731Sbaban 7365731Sbaban /* ARGSUSED */ 7375731Sbaban idmap_retcode 7385731Sbaban nldap_lookup_batch(lookup_state_t *state, idmap_mapping_batch *batch, 7395731Sbaban idmap_ids_res *result) 7405731Sbaban { 741*6616Sdm199847 idmap_retcode retcode, rc1; 742*6616Sdm199847 int i, add, is_wuser; 743*6616Sdm199847 idmap_mapping *req; 744*6616Sdm199847 idmap_id_res *res; 745*6616Sdm199847 idmap_nldap_query_state_t *qs = NULL; 746*6616Sdm199847 idmap_how *how; 747*6616Sdm199847 748*6616Sdm199847 if (state->nldap_nqueries == 0) 749*6616Sdm199847 return (IDMAP_SUCCESS); 750*6616Sdm199847 751*6616Sdm199847 /* Create nldap lookup batch */ 752*6616Sdm199847 retcode = idmap_nldap_lookup_batch_start(state->nldap_nqueries, &qs); 753*6616Sdm199847 if (retcode != IDMAP_SUCCESS) { 754*6616Sdm199847 idmapdlog(LOG_ERR, 755*6616Sdm199847 "Failed to create batch for native LDAP lookup"); 756*6616Sdm199847 goto out; 757*6616Sdm199847 } 758*6616Sdm199847 759*6616Sdm199847 qs->nldap_winname_attr = state->nldap_winname_attr; 760*6616Sdm199847 qs->defdom = state->defdom; 761*6616Sdm199847 762*6616Sdm199847 /* Add requests to the batch */ 763*6616Sdm199847 for (i = 0, add = 0; i < batch->idmap_mapping_batch_len; i++) { 764*6616Sdm199847 req = &batch->idmap_mapping_batch_val[i]; 765*6616Sdm199847 res = &result->ids.ids_val[i]; 766*6616Sdm199847 retcode = IDMAP_SUCCESS; 767*6616Sdm199847 768*6616Sdm199847 /* Skip if not marked for nldap lookup */ 769*6616Sdm199847 if (!(req->direction & _IDMAP_F_LOOKUP_NLDAP)) 770*6616Sdm199847 continue; 771*6616Sdm199847 772*6616Sdm199847 if (IS_REQUEST_SID(*req, 1)) { 773*6616Sdm199847 774*6616Sdm199847 /* win2unix request: */ 775*6616Sdm199847 776*6616Sdm199847 /* 777*6616Sdm199847 * When processing a win2unix request, nldap lookup 778*6616Sdm199847 * is performed after AD lookup or a successful 779*6616Sdm199847 * name-cache lookup. Therefore we should already 780*6616Sdm199847 * have sid, winname and sidtype. Note that 781*6616Sdm199847 * windomain could be NULL e.g. well-known SIDs. 782*6616Sdm199847 */ 783*6616Sdm199847 assert(req->id1name != NULL && 784*6616Sdm199847 (res->id.idtype == IDMAP_UID || 785*6616Sdm199847 res->id.idtype == IDMAP_GID)); 786*6616Sdm199847 787*6616Sdm199847 /* Skip if we already have pid and unixname */ 788*6616Sdm199847 if (req->id2name != NULL && 789*6616Sdm199847 res->id.idmap_id_u.uid != SENTINEL_PID) { 790*6616Sdm199847 res->retcode = IDMAP_SUCCESS; 791*6616Sdm199847 continue; 792*6616Sdm199847 } 793*6616Sdm199847 794*6616Sdm199847 /* Clear leftover value */ 795*6616Sdm199847 free(req->id2name); 796*6616Sdm199847 req->id2name = NULL; 797*6616Sdm199847 798*6616Sdm199847 /* Lookup nldap by winname to get pid and unixname */ 799*6616Sdm199847 add = 1; 800*6616Sdm199847 idmap_info_free(&res->info); 801*6616Sdm199847 res->info.src = IDMAP_MAP_SRC_NEW; 802*6616Sdm199847 how = &res->info.how; 803*6616Sdm199847 how->map_type = IDMAP_MAP_TYPE_DS_NLDAP; 804*6616Sdm199847 retcode = idmap_nldap_bywinname_batch_add( 805*6616Sdm199847 qs, req->id1name, req->id1domain, 806*6616Sdm199847 (res->id.idtype == IDMAP_UID) ? 1 : 0, 807*6616Sdm199847 &how->idmap_how_u.nldap.dn, 808*6616Sdm199847 &how->idmap_how_u.nldap.attr, 809*6616Sdm199847 &how->idmap_how_u.nldap.value, 810*6616Sdm199847 &req->id2name, &res->id.idmap_id_u.uid, 811*6616Sdm199847 &res->retcode); 812*6616Sdm199847 813*6616Sdm199847 } else if (IS_REQUEST_UID(*req) || IS_REQUEST_GID(*req)) { 814*6616Sdm199847 815*6616Sdm199847 /* unix2win request: */ 816*6616Sdm199847 817*6616Sdm199847 /* Skip if we already have winname */ 818*6616Sdm199847 if (req->id2name != NULL) { 819*6616Sdm199847 res->retcode = IDMAP_SUCCESS; 820*6616Sdm199847 continue; 821*6616Sdm199847 } 822*6616Sdm199847 823*6616Sdm199847 /* Clear old value */ 824*6616Sdm199847 free(req->id2domain); 825*6616Sdm199847 req->id2domain = NULL; 826*6616Sdm199847 827*6616Sdm199847 /* Set how info */ 828*6616Sdm199847 idmap_info_free(&res->info); 829*6616Sdm199847 res->info.src = IDMAP_MAP_SRC_NEW; 830*6616Sdm199847 how = &res->info.how; 831*6616Sdm199847 how->map_type = IDMAP_MAP_TYPE_DS_NLDAP; 832*6616Sdm199847 833*6616Sdm199847 /* Lookup nldap by pid or unixname to get winname */ 834*6616Sdm199847 if (req->id1.idmap_id_u.uid != SENTINEL_PID) { 835*6616Sdm199847 add = 1; 836*6616Sdm199847 retcode = idmap_nldap_bypid_batch_add( 837*6616Sdm199847 qs, req->id1.idmap_id_u.uid, 838*6616Sdm199847 (req->id1.idtype == IDMAP_UID) ? 1 : 0, 839*6616Sdm199847 &how->idmap_how_u.nldap.dn, 840*6616Sdm199847 &how->idmap_how_u.nldap.attr, 841*6616Sdm199847 &how->idmap_how_u.nldap.value, 842*6616Sdm199847 &req->id2name, &req->id2domain, 843*6616Sdm199847 (req->id1name == NULL) ? 844*6616Sdm199847 &req->id1name : NULL, 845*6616Sdm199847 &res->retcode); 846*6616Sdm199847 } else if (req->id1name != NULL) { 847*6616Sdm199847 add = 1; 848*6616Sdm199847 retcode = idmap_nldap_byunixname_batch_add( 849*6616Sdm199847 qs, req->id1name, 850*6616Sdm199847 (req->id1.idtype == IDMAP_UID) ? 1 : 0, 851*6616Sdm199847 &how->idmap_how_u.nldap.dn, 852*6616Sdm199847 &how->idmap_how_u.nldap.attr, 853*6616Sdm199847 &how->idmap_how_u.nldap.value, 854*6616Sdm199847 &req->id2name, &req->id2domain, 855*6616Sdm199847 &req->id1.idmap_id_u.uid, &res->retcode); 856*6616Sdm199847 } 857*6616Sdm199847 858*6616Sdm199847 } 859*6616Sdm199847 860*6616Sdm199847 /* 861*6616Sdm199847 * nldap_batch_add API returns error only on fatal failures 862*6616Sdm199847 * otherwise it returns success and the actual status 863*6616Sdm199847 * is stored in the individual request (res->retcode). 864*6616Sdm199847 * Stop adding requests to this batch on fatal failures 865*6616Sdm199847 * (i.e. if retcode != success) 866*6616Sdm199847 */ 867*6616Sdm199847 if (retcode != IDMAP_SUCCESS) 868*6616Sdm199847 break; 869*6616Sdm199847 } 870*6616Sdm199847 871*6616Sdm199847 if (!add) 872*6616Sdm199847 idmap_nldap_lookup_batch_release(qs); 873*6616Sdm199847 else if (retcode != IDMAP_SUCCESS) 874*6616Sdm199847 idmap_nldap_lookup_batch_release(qs); 875*6616Sdm199847 else 876*6616Sdm199847 retcode = idmap_nldap_lookup_batch_end(qs); 877*6616Sdm199847 878*6616Sdm199847 out: 879*6616Sdm199847 for (i = 0; i < batch->idmap_mapping_batch_len; i++) { 880*6616Sdm199847 req = &batch->idmap_mapping_batch_val[i]; 881*6616Sdm199847 res = &result->ids.ids_val[i]; 882*6616Sdm199847 if (!(req->direction & _IDMAP_F_LOOKUP_NLDAP)) 883*6616Sdm199847 continue; 884*6616Sdm199847 885*6616Sdm199847 /* Reset nldap flag */ 886*6616Sdm199847 req->direction &= ~(_IDMAP_F_LOOKUP_NLDAP); 887*6616Sdm199847 888*6616Sdm199847 /* 889*6616Sdm199847 * As noted earlier retcode != success if there were fatal 890*6616Sdm199847 * errors during batch_start and batch_adds. If so then set 891*6616Sdm199847 * the status of each nldap request to that error. 892*6616Sdm199847 */ 893*6616Sdm199847 if (retcode != IDMAP_SUCCESS) { 894*6616Sdm199847 res->retcode = retcode; 895*6616Sdm199847 continue; 896*6616Sdm199847 } 897*6616Sdm199847 if (!add) 898*6616Sdm199847 continue; 899*6616Sdm199847 900*6616Sdm199847 /* 901*6616Sdm199847 * If we successfully retrieved winname from nldap entry 902*6616Sdm199847 * then lookup winname2sid locally. If not found locally 903*6616Sdm199847 * then mark this request for AD lookup. 904*6616Sdm199847 */ 905*6616Sdm199847 if (res->retcode == IDMAP_SUCCESS && 906*6616Sdm199847 req->id2name != NULL && 907*6616Sdm199847 res->id.idmap_id_u.sid.prefix == NULL && 908*6616Sdm199847 (IS_REQUEST_UID(*req) || IS_REQUEST_GID(*req))) { 909*6616Sdm199847 910*6616Sdm199847 is_wuser = -1; 911*6616Sdm199847 rc1 = lookup_name2sid(state->cache, 912*6616Sdm199847 req->id2name, req->id2domain, &is_wuser, NULL, 913*6616Sdm199847 &res->id.idmap_id_u.sid.prefix, 914*6616Sdm199847 &res->id.idmap_id_u.sid.rid, req, 1); 915*6616Sdm199847 if (rc1 == IDMAP_SUCCESS) 916*6616Sdm199847 res->id.idtype = 917*6616Sdm199847 is_wuser ? IDMAP_USID : IDMAP_GSID; 918*6616Sdm199847 else if (rc1 == IDMAP_ERR_NOTFOUND) { 919*6616Sdm199847 req->direction |= _IDMAP_F_LOOKUP_AD; 920*6616Sdm199847 state->ad_nqueries++; 921*6616Sdm199847 } else 922*6616Sdm199847 res->retcode = rc1; 923*6616Sdm199847 } 924*6616Sdm199847 925*6616Sdm199847 /* 926*6616Sdm199847 * Unset non-fatal errors in individual request. This allows 927*6616Sdm199847 * the next pass to process other mapping mechanisms for 928*6616Sdm199847 * this request. 929*6616Sdm199847 */ 930*6616Sdm199847 if (res->retcode != IDMAP_SUCCESS && 931*6616Sdm199847 res->retcode != IDMAP_ERR_NS_LDAP_BAD_WINNAME && 932*6616Sdm199847 !(IDMAP_FATAL_ERROR(res->retcode))) { 933*6616Sdm199847 idmap_info_free(&res->info); 934*6616Sdm199847 res->retcode = IDMAP_SUCCESS; 935*6616Sdm199847 } 936*6616Sdm199847 } 937*6616Sdm199847 938*6616Sdm199847 state->nldap_nqueries = 0; 939*6616Sdm199847 return (retcode); 9405731Sbaban } 941