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