1c5c4113dSnw141292 /* 2c5c4113dSnw141292 * CDDL HEADER START 3c5c4113dSnw141292 * 4c5c4113dSnw141292 * The contents of this file are subject to the terms of the 5c5c4113dSnw141292 * Common Development and Distribution License (the "License"). 6c5c4113dSnw141292 * You may not use this file except in compliance with the License. 7c5c4113dSnw141292 * 8c5c4113dSnw141292 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9c5c4113dSnw141292 * or http://www.opensolaris.org/os/licensing. 10c5c4113dSnw141292 * See the License for the specific language governing permissions 11c5c4113dSnw141292 * and limitations under the License. 12c5c4113dSnw141292 * 13c5c4113dSnw141292 * When distributing Covered Code, include this CDDL HEADER in each 14c5c4113dSnw141292 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15c5c4113dSnw141292 * If applicable, add the following below this CDDL HEADER, with the 16c5c4113dSnw141292 * fields enclosed by brackets "[]" replaced with your own identifying 17c5c4113dSnw141292 * information: Portions Copyright [yyyy] [name of copyright owner] 18c5c4113dSnw141292 * 19c5c4113dSnw141292 * CDDL HEADER END 20c5c4113dSnw141292 */ 21c5c4113dSnw141292 22c5c4113dSnw141292 /* 231fcced4cSJordan Brown * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24c5c4113dSnw141292 * Use is subject to license terms. 25c5c4113dSnw141292 */ 26c5c4113dSnw141292 27c5c4113dSnw141292 /* 28c5c4113dSnw141292 * Processes name2sid & sid2name batched lookups for a given user or 29c5c4113dSnw141292 * computer from an AD Directory server using GSSAPI authentication 30c5c4113dSnw141292 */ 31c5c4113dSnw141292 32c5c4113dSnw141292 #include <stdio.h> 33c5c4113dSnw141292 #include <stdlib.h> 34c5c4113dSnw141292 #include <alloca.h> 35c5c4113dSnw141292 #include <string.h> 36c5c4113dSnw141292 #include <strings.h> 37c5c4113dSnw141292 #include <lber.h> 38c5c4113dSnw141292 #include <ldap.h> 39c5c4113dSnw141292 #include <sasl/sasl.h> 40c5c4113dSnw141292 #include <string.h> 41c5c4113dSnw141292 #include <ctype.h> 42c5c4113dSnw141292 #include <pthread.h> 43c5c4113dSnw141292 #include <synch.h> 44c5c4113dSnw141292 #include <atomic.h> 45c5c4113dSnw141292 #include <errno.h> 46c5c4113dSnw141292 #include <assert.h> 47c5c4113dSnw141292 #include <limits.h> 482b4a7802SBaban Kenkre #include <time.h> 49cd37da74Snw141292 #include <sys/u8_textprep.h> 502b4a7802SBaban Kenkre #include "libadutils.h" 51479ac375Sdm199847 #include "nldaputils.h" 52c5c4113dSnw141292 #include "idmapd.h" 53c5c4113dSnw141292 54c5c4113dSnw141292 /* Attribute names and filter format strings */ 55e3c2d6aaSnw141292 #define SAN "sAMAccountName" 56e3c2d6aaSnw141292 #define OBJSID "objectSid" 57e3c2d6aaSnw141292 #define OBJCLASS "objectClass" 58*e3f2c991SKeyur Desai #define UIDNUMBER "uidNumber" 59*e3f2c991SKeyur Desai #define GIDNUMBER "gidNumber" 60*e3f2c991SKeyur Desai #define UIDNUMBERFILTER "(&(objectclass=user)(uidNumber=%u))" 61*e3f2c991SKeyur Desai #define GIDNUMBERFILTER "(&(objectclass=group)(gidNumber=%u))" 62*e3f2c991SKeyur Desai #define SANFILTER "(sAMAccountName=%s)" 63e3c2d6aaSnw141292 #define OBJSIDFILTER "(objectSid=%s)" 64c5c4113dSnw141292 652b4a7802SBaban Kenkre void idmap_ldap_res_search_cb(LDAP *ld, LDAPMessage **res, int rc, 662b4a7802SBaban Kenkre int qid, void *argp); 67c5c4113dSnw141292 68c5c4113dSnw141292 /* 69c5c4113dSnw141292 * A place to put the results of a batched (async) query 70c5c4113dSnw141292 * 71c5c4113dSnw141292 * There is one of these for every query added to a batch object 72c5c4113dSnw141292 * (idmap_query_state, see below). 73c5c4113dSnw141292 */ 74c5c4113dSnw141292 typedef struct idmap_q { 75e3c2d6aaSnw141292 /* 76e3c2d6aaSnw141292 * data used for validating search result entries for name->SID 77e8c27ec8Sbaban * lookups 78e3c2d6aaSnw141292 */ 79cd37da74Snw141292 char *ecanonname; /* expected canon name */ 80cd37da74Snw141292 char *edomain; /* expected domain name */ 81e8c27ec8Sbaban int eunixtype; /* expected unix type */ 82e3c2d6aaSnw141292 /* results */ 83cd37da74Snw141292 char **canonname; /* actual canon name */ 84c5c4113dSnw141292 char **domain; /* name of domain of object */ 85e8c27ec8Sbaban char **sid; /* stringified SID */ 86e8c27ec8Sbaban rid_t *rid; /* RID */ 87e8c27ec8Sbaban int *sid_type; /* user or group SID? */ 88e8c27ec8Sbaban char **unixname; /* unixname for name mapping */ 8948258c6bSjp151216 char **dn; /* DN of entry */ 9048258c6bSjp151216 char **attr; /* Attr for name mapping */ 9148258c6bSjp151216 char **value; /* value for name mapping */ 92*e3f2c991SKeyur Desai posix_id_t *pid; /* Posix ID found via IDMU */ 93c5c4113dSnw141292 idmap_retcode *rc; 942b4a7802SBaban Kenkre adutils_rc ad_rc; 952b4a7802SBaban Kenkre adutils_result_t *result; 96e3c2d6aaSnw141292 97bcced03bSjp151216 /* 98bcced03bSjp151216 * The LDAP search entry result is placed here to be processed 99bcced03bSjp151216 * when the search done result is received. 100bcced03bSjp151216 */ 101bcced03bSjp151216 LDAPMessage *search_res; /* The LDAP search result */ 102c5c4113dSnw141292 } idmap_q_t; 103c5c4113dSnw141292 104c5c4113dSnw141292 /* Batch context structure; typedef is in header file */ 105c5c4113dSnw141292 struct idmap_query_state { 1062b4a7802SBaban Kenkre adutils_query_state_t *qs; 1074d61c878SJulian Pullen int qsize; /* Queue size */ 1084d61c878SJulian Pullen uint32_t qcount; /* Number of queued requests */ 109e8c27ec8Sbaban const char *ad_unixuser_attr; 110e8c27ec8Sbaban const char *ad_unixgroup_attr; 111*e3f2c991SKeyur Desai int directory_based_mapping; /* enum */ 112*e3f2c991SKeyur Desai char *default_domain; 113c5c4113dSnw141292 idmap_q_t queries[1]; /* array of query results */ 114c5c4113dSnw141292 }; 115c5c4113dSnw141292 116651c0131Sbaban static pthread_t reaperid = 0; 117c5c4113dSnw141292 118c5c4113dSnw141292 /* 119c5c4113dSnw141292 * Keep connection management simple for now, extend or replace later 120c5c4113dSnw141292 * with updated libsldap code. 121c5c4113dSnw141292 */ 122c5c4113dSnw141292 #define ADREAPERSLEEP 60 123c5c4113dSnw141292 124c5c4113dSnw141292 /* 125c5c4113dSnw141292 * Idle connection reaping side of connection management 126c5c4113dSnw141292 * 127c5c4113dSnw141292 * Every minute wake up and look for connections that have been idle for 128c5c4113dSnw141292 * five minutes or more and close them. 129c5c4113dSnw141292 */ 130c5c4113dSnw141292 /*ARGSUSED*/ 131c5c4113dSnw141292 static 132c5c4113dSnw141292 void 133c5c4113dSnw141292 adreaper(void *arg) 134c5c4113dSnw141292 { 135c5c4113dSnw141292 timespec_t ts; 136c5c4113dSnw141292 137c5c4113dSnw141292 ts.tv_sec = ADREAPERSLEEP; 138c5c4113dSnw141292 ts.tv_nsec = 0; 139c5c4113dSnw141292 140c5c4113dSnw141292 for (;;) { 141c5c4113dSnw141292 /* 142c5c4113dSnw141292 * nanosleep(3RT) is thead-safe (no SIGALRM) and more 143c5c4113dSnw141292 * portable than usleep(3C) 144c5c4113dSnw141292 */ 145c5c4113dSnw141292 (void) nanosleep(&ts, NULL); 1462b4a7802SBaban Kenkre adutils_reap_idle_connections(); 147c5c4113dSnw141292 } 148c5c4113dSnw141292 } 149c5c4113dSnw141292 150c5c4113dSnw141292 /* 151c5c4113dSnw141292 * Take ad_host_config_t information, create a ad_host_t, 152c5c4113dSnw141292 * populate it and add it to the list of hosts. 153c5c4113dSnw141292 */ 154c5c4113dSnw141292 155c5c4113dSnw141292 int 1562b4a7802SBaban Kenkre idmap_add_ds(adutils_ad_t *ad, const char *host, int port) 157c5c4113dSnw141292 { 158c5c4113dSnw141292 int ret = -1; 159c5c4113dSnw141292 1602b4a7802SBaban Kenkre if (adutils_add_ds(ad, host, port) == ADUTILS_SUCCESS) 161c8e26105Sjp151216 ret = 0; 162c5c4113dSnw141292 163c5c4113dSnw141292 /* Start reaper if it doesn't exist */ 1642b4a7802SBaban Kenkre if (ret == 0 && reaperid == 0) 165c5c4113dSnw141292 (void) pthread_create(&reaperid, NULL, 166c5c4113dSnw141292 (void *(*)(void *))adreaper, (void *)NULL); 167c5c4113dSnw141292 return (ret); 168c5c4113dSnw141292 } 169c5c4113dSnw141292 170c5c4113dSnw141292 static 1712b4a7802SBaban Kenkre idmap_retcode 1722b4a7802SBaban Kenkre map_adrc2idmaprc(adutils_rc adrc) 173c5c4113dSnw141292 { 1742b4a7802SBaban Kenkre switch (adrc) { 1752b4a7802SBaban Kenkre case ADUTILS_SUCCESS: 1762b4a7802SBaban Kenkre return (IDMAP_SUCCESS); 1772b4a7802SBaban Kenkre case ADUTILS_ERR_NOTFOUND: 1782b4a7802SBaban Kenkre return (IDMAP_ERR_NOTFOUND); 1792b4a7802SBaban Kenkre case ADUTILS_ERR_MEMORY: 1802b4a7802SBaban Kenkre return (IDMAP_ERR_MEMORY); 1812b4a7802SBaban Kenkre case ADUTILS_ERR_DOMAIN: 1822b4a7802SBaban Kenkre return (IDMAP_ERR_DOMAIN); 1832b4a7802SBaban Kenkre case ADUTILS_ERR_OTHER: 1842b4a7802SBaban Kenkre return (IDMAP_ERR_OTHER); 1852b4a7802SBaban Kenkre case ADUTILS_ERR_RETRIABLE_NET_ERR: 1862b4a7802SBaban Kenkre return (IDMAP_ERR_RETRIABLE_NET_ERR); 1872b4a7802SBaban Kenkre default: 1882b4a7802SBaban Kenkre return (IDMAP_ERR_INTERNAL); 189c5c4113dSnw141292 } 1902b4a7802SBaban Kenkre /* NOTREACHED */ 191c5c4113dSnw141292 } 192c5c4113dSnw141292 193c5c4113dSnw141292 idmap_retcode 1942b4a7802SBaban Kenkre idmap_lookup_batch_start(adutils_ad_t *ad, int nqueries, 195*e3f2c991SKeyur Desai int directory_based_mapping, const char *default_domain, 1962b4a7802SBaban Kenkre idmap_query_state_t **state) 197c5c4113dSnw141292 { 198c5c4113dSnw141292 idmap_query_state_t *new_state; 1992b4a7802SBaban Kenkre adutils_rc rc; 200c5c4113dSnw141292 201c5c4113dSnw141292 *state = NULL; 202c5c4113dSnw141292 2034d61c878SJulian Pullen assert(ad != NULL); 204c5c4113dSnw141292 205c5c4113dSnw141292 new_state = calloc(1, sizeof (idmap_query_state_t) + 206c5c4113dSnw141292 (nqueries - 1) * sizeof (idmap_q_t)); 207c5c4113dSnw141292 if (new_state == NULL) 208c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 209c5c4113dSnw141292 2102b4a7802SBaban Kenkre if ((rc = adutils_lookup_batch_start(ad, nqueries, 2112b4a7802SBaban Kenkre idmap_ldap_res_search_cb, new_state, &new_state->qs)) 2122b4a7802SBaban Kenkre != ADUTILS_SUCCESS) { 213*e3f2c991SKeyur Desai idmap_lookup_release_batch(&new_state); 2142b4a7802SBaban Kenkre return (map_adrc2idmaprc(rc)); 2152b4a7802SBaban Kenkre } 2162b4a7802SBaban Kenkre 217*e3f2c991SKeyur Desai new_state->default_domain = strdup(default_domain); 218*e3f2c991SKeyur Desai if (new_state->default_domain == NULL) { 219*e3f2c991SKeyur Desai idmap_lookup_release_batch(&new_state); 220*e3f2c991SKeyur Desai return (IDMAP_ERR_MEMORY); 221*e3f2c991SKeyur Desai } 222*e3f2c991SKeyur Desai 223*e3f2c991SKeyur Desai new_state->directory_based_mapping = directory_based_mapping; 2244d61c878SJulian Pullen new_state->qsize = nqueries; 225c5c4113dSnw141292 *state = new_state; 226c5c4113dSnw141292 return (IDMAP_SUCCESS); 227c5c4113dSnw141292 } 228c5c4113dSnw141292 229c5c4113dSnw141292 /* 230e8c27ec8Sbaban * Set unixuser_attr and unixgroup_attr for AD-based name mapping 231e8c27ec8Sbaban */ 232e8c27ec8Sbaban void 233e8c27ec8Sbaban idmap_lookup_batch_set_unixattr(idmap_query_state_t *state, 2344edd44c5Sjp151216 const char *unixuser_attr, const char *unixgroup_attr) 2354edd44c5Sjp151216 { 236e8c27ec8Sbaban state->ad_unixuser_attr = unixuser_attr; 237e8c27ec8Sbaban state->ad_unixgroup_attr = unixgroup_attr; 238e8c27ec8Sbaban } 239e8c27ec8Sbaban 240e8c27ec8Sbaban /* 241cd37da74Snw141292 * Take parsed attribute values from a search result entry and check if 242cd37da74Snw141292 * it is the result that was desired and, if so, set the result fields 243cd37da74Snw141292 * of the given idmap_q_t. 244cd37da74Snw141292 * 245*e3f2c991SKeyur Desai * Except for dn and attr, all strings are consumed, either by transferring 246*e3f2c991SKeyur Desai * them over into the request results (where the caller will eventually free 247*e3f2c991SKeyur Desai * them) or by freeing them here. Note that this aligns with the "const" 248*e3f2c991SKeyur Desai * declarations below. 249c5c4113dSnw141292 */ 250c5c4113dSnw141292 static 251cd37da74Snw141292 void 252*e3f2c991SKeyur Desai idmap_setqresults( 253*e3f2c991SKeyur Desai idmap_q_t *q, 254*e3f2c991SKeyur Desai char *san, 255*e3f2c991SKeyur Desai const char *dn, 256*e3f2c991SKeyur Desai const char *attr, 257*e3f2c991SKeyur Desai char *value, 258*e3f2c991SKeyur Desai char *sid, 259*e3f2c991SKeyur Desai rid_t rid, 260*e3f2c991SKeyur Desai int sid_type, 261*e3f2c991SKeyur Desai char *unixname, 262*e3f2c991SKeyur Desai posix_id_t pid) 263c5c4113dSnw141292 { 264cd37da74Snw141292 char *domain; 2651fcced4cSJordan Brown int err1; 266cd37da74Snw141292 267cd37da74Snw141292 assert(dn != NULL); 268cd37da74Snw141292 2692b4a7802SBaban Kenkre if ((domain = adutils_dn2dns(dn)) == NULL) 270cd37da74Snw141292 goto out; 271cd37da74Snw141292 272e8c27ec8Sbaban if (q->ecanonname != NULL && san != NULL) { 273e8c27ec8Sbaban /* Check that this is the canonname that we were looking for */ 274cd37da74Snw141292 if (u8_strcmp(q->ecanonname, san, 0, 275cd37da74Snw141292 U8_STRCMP_CI_LOWER, /* no normalization, for now */ 276e8c27ec8Sbaban U8_UNICODE_LATEST, &err1) != 0 || err1 != 0) 277e8c27ec8Sbaban goto out; 278e8c27ec8Sbaban } 279e8c27ec8Sbaban 280e8c27ec8Sbaban if (q->edomain != NULL) { 281e8c27ec8Sbaban /* Check that this is the domain that we were looking for */ 2821fcced4cSJordan Brown if (!domain_eq(q->edomain, domain)) 283cd37da74Snw141292 goto out; 284e8c27ec8Sbaban } 285cd37da74Snw141292 28648258c6bSjp151216 /* Copy the DN and attr and value */ 28748258c6bSjp151216 if (q->dn != NULL) 28848258c6bSjp151216 *q->dn = strdup(dn); 28948258c6bSjp151216 29048258c6bSjp151216 if (q->attr != NULL && attr != NULL) 29148258c6bSjp151216 *q->attr = strdup(attr); 29248258c6bSjp151216 293*e3f2c991SKeyur Desai if (q->value != NULL && value != NULL) { 294*e3f2c991SKeyur Desai *q->value = value; 295*e3f2c991SKeyur Desai value = NULL; 296*e3f2c991SKeyur Desai } 29748258c6bSjp151216 298e8c27ec8Sbaban /* Set results */ 299e8c27ec8Sbaban if (q->sid) { 300e8c27ec8Sbaban *q->sid = sid; 301cd37da74Snw141292 sid = NULL; 302e8c27ec8Sbaban } 303e8c27ec8Sbaban if (q->rid) 304e8c27ec8Sbaban *q->rid = rid; 305e8c27ec8Sbaban if (q->sid_type) 306cd37da74Snw141292 *q->sid_type = sid_type; 307e8c27ec8Sbaban if (q->unixname) { 308e8c27ec8Sbaban *q->unixname = unixname; 309e8c27ec8Sbaban unixname = NULL; 310e8c27ec8Sbaban } 311cd37da74Snw141292 if (q->domain != NULL) { 312cd37da74Snw141292 *q->domain = domain; 313cd37da74Snw141292 domain = NULL; 314e8c27ec8Sbaban } 315e8c27ec8Sbaban if (q->canonname != NULL) { 316479ac375Sdm199847 /* 317479ac375Sdm199847 * The caller may be replacing the given winname by its 318479ac375Sdm199847 * canonical name and therefore free any old name before 319479ac375Sdm199847 * overwriting the field by the canonical name. 320479ac375Sdm199847 */ 321479ac375Sdm199847 free(*q->canonname); 322e8c27ec8Sbaban *q->canonname = san; 323cd37da74Snw141292 san = NULL; 324cd37da74Snw141292 } 325cd37da74Snw141292 326*e3f2c991SKeyur Desai if (q->pid != NULL && pid != SENTINEL_PID) { 327*e3f2c991SKeyur Desai *q->pid = pid; 328*e3f2c991SKeyur Desai } 329*e3f2c991SKeyur Desai 3302b4a7802SBaban Kenkre q->ad_rc = ADUTILS_SUCCESS; 331cd37da74Snw141292 332cd37da74Snw141292 out: 333cd37da74Snw141292 /* Free unused attribute values */ 334cd37da74Snw141292 free(san); 335cd37da74Snw141292 free(sid); 336cd37da74Snw141292 free(domain); 337e8c27ec8Sbaban free(unixname); 338*e3f2c991SKeyur Desai free(value); 339c5c4113dSnw141292 } 340c5c4113dSnw141292 341c5c4113dSnw141292 #define BVAL_CASEEQ(bv, str) \ 342c5c4113dSnw141292 (((*(bv))->bv_len == (sizeof (str) - 1)) && \ 343c5c4113dSnw141292 strncasecmp((*(bv))->bv_val, str, (*(bv))->bv_len) == 0) 344c5c4113dSnw141292 345c5c4113dSnw141292 /* 346cd37da74Snw141292 * Extract the class of the result entry. Returns 1 on success, 0 on 347cd37da74Snw141292 * failure. 348c5c4113dSnw141292 */ 349c5c4113dSnw141292 static 350e3c2d6aaSnw141292 int 351cd37da74Snw141292 idmap_bv_objclass2sidtype(BerValue **bvalues, int *sid_type) 352c5c4113dSnw141292 { 353c5c4113dSnw141292 BerValue **cbval; 354c5c4113dSnw141292 355cd37da74Snw141292 *sid_type = _IDMAP_T_OTHER; 356c5c4113dSnw141292 if (bvalues == NULL) 357e3c2d6aaSnw141292 return (0); 358c5c4113dSnw141292 359cd37da74Snw141292 /* 360*e3f2c991SKeyur Desai * We consider Computer to be a subclass of User, so we can just 361*e3f2c991SKeyur Desai * ignore Computer entries and pay attention to the accompanying 362*e3f2c991SKeyur Desai * User entries. 363cd37da74Snw141292 */ 364c5c4113dSnw141292 for (cbval = bvalues; *cbval != NULL; cbval++) { 365*e3f2c991SKeyur Desai if (BVAL_CASEEQ(cbval, "group")) { 366cd37da74Snw141292 *sid_type = _IDMAP_T_GROUP; 367cd37da74Snw141292 break; 368*e3f2c991SKeyur Desai } else if (BVAL_CASEEQ(cbval, "user")) { 369cd37da74Snw141292 *sid_type = _IDMAP_T_USER; 370*e3f2c991SKeyur Desai break; 371cd37da74Snw141292 } 372cd37da74Snw141292 /* 373cd37da74Snw141292 * "else if (*sid_type = _IDMAP_T_USER)" then this is a 374cd37da74Snw141292 * new sub-class of user -- what to do with it?? 375cd37da74Snw141292 */ 376c5c4113dSnw141292 } 377e3c2d6aaSnw141292 378e3c2d6aaSnw141292 return (1); 379c5c4113dSnw141292 } 380c5c4113dSnw141292 381c5c4113dSnw141292 /* 382c5c4113dSnw141292 * Handle a given search result entry 383c5c4113dSnw141292 */ 384c5c4113dSnw141292 static 385c5c4113dSnw141292 void 3862b4a7802SBaban Kenkre idmap_extract_object(idmap_query_state_t *state, idmap_q_t *q, 3872b4a7802SBaban Kenkre LDAPMessage *res, LDAP *ld) 388c5c4113dSnw141292 { 389c5c4113dSnw141292 BerValue **bvalues; 390*e3f2c991SKeyur Desai const char *attr = NULL; 391*e3f2c991SKeyur Desai char *value = NULL; 392*e3f2c991SKeyur Desai char *unix_name = NULL; 393*e3f2c991SKeyur Desai char *dn; 394cd37da74Snw141292 char *san = NULL; 395cd37da74Snw141292 char *sid = NULL; 396cd37da74Snw141292 rid_t rid = 0; 397*e3f2c991SKeyur Desai int sid_type; 398*e3f2c991SKeyur Desai int ok; 399*e3f2c991SKeyur Desai posix_id_t pid = SENTINEL_PID; 400e3c2d6aaSnw141292 401e8c27ec8Sbaban assert(q->rc != NULL); 402*e3f2c991SKeyur Desai assert(q->domain == NULL || *q->domain == NULL); 403e8c27ec8Sbaban 4042b4a7802SBaban Kenkre if ((dn = ldap_get_dn(ld, res)) == NULL) 405c5c4113dSnw141292 return; 406c5c4113dSnw141292 407*e3f2c991SKeyur Desai bvalues = ldap_get_values_len(ld, res, OBJCLASS); 408*e3f2c991SKeyur Desai if (bvalues == NULL) { 409e8c27ec8Sbaban /* 410e8c27ec8Sbaban * Didn't find objectclass. Something's wrong with our 411e8c27ec8Sbaban * AD data. 412e8c27ec8Sbaban */ 413*e3f2c991SKeyur Desai idmapdlog(LOG_ERR, "%s has no %s", dn, OBJCLASS); 414*e3f2c991SKeyur Desai goto out; 415*e3f2c991SKeyur Desai } 416*e3f2c991SKeyur Desai ok = idmap_bv_objclass2sidtype(bvalues, &sid_type); 417*e3f2c991SKeyur Desai ldap_value_free_len(bvalues); 418*e3f2c991SKeyur Desai if (!ok) { 419e8c27ec8Sbaban /* 420*e3f2c991SKeyur Desai * Didn't understand objectclass. Something's wrong with our 421*e3f2c991SKeyur Desai * AD data. 422e8c27ec8Sbaban */ 423*e3f2c991SKeyur Desai idmapdlog(LOG_ERR, "%s has unexpected %s", dn, OBJCLASS); 424*e3f2c991SKeyur Desai goto out; 425e8c27ec8Sbaban } 426e8c27ec8Sbaban 427*e3f2c991SKeyur Desai if (state->directory_based_mapping == DIRECTORY_MAPPING_IDMU && 428*e3f2c991SKeyur Desai q->pid != NULL) { 429*e3f2c991SKeyur Desai if (sid_type == _IDMAP_T_USER) 430*e3f2c991SKeyur Desai attr = UIDNUMBER; 431*e3f2c991SKeyur Desai else if (sid_type == _IDMAP_T_GROUP) 432*e3f2c991SKeyur Desai attr = GIDNUMBER; 433*e3f2c991SKeyur Desai if (attr != NULL) { 434*e3f2c991SKeyur Desai bvalues = ldap_get_values_len(ld, res, attr); 435*e3f2c991SKeyur Desai if (bvalues != NULL) { 436*e3f2c991SKeyur Desai value = adutils_bv_str(bvalues[0]); 437*e3f2c991SKeyur Desai if (!adutils_bv_uint(bvalues[0], &pid)) { 438*e3f2c991SKeyur Desai idmapdlog(LOG_ERR, 439*e3f2c991SKeyur Desai "%s has Invalid %s value \"%s\"", 440*e3f2c991SKeyur Desai dn, attr, value); 441*e3f2c991SKeyur Desai } 442*e3f2c991SKeyur Desai ldap_value_free_len(bvalues); 443*e3f2c991SKeyur Desai } 444*e3f2c991SKeyur Desai } 445*e3f2c991SKeyur Desai } 446c5c4113dSnw141292 447*e3f2c991SKeyur Desai if (state->directory_based_mapping == DIRECTORY_MAPPING_NAME && 448*e3f2c991SKeyur Desai q->unixname != NULL) { 449*e3f2c991SKeyur Desai /* 450*e3f2c991SKeyur Desai * If the caller has requested unixname then determine the 451*e3f2c991SKeyur Desai * AD attribute name that will have the unixname, and retrieve 452*e3f2c991SKeyur Desai * its value. 453*e3f2c991SKeyur Desai */ 454*e3f2c991SKeyur Desai int unix_type; 455*e3f2c991SKeyur Desai /* 456*e3f2c991SKeyur Desai * Determine the target UNIX type. 457*e3f2c991SKeyur Desai * 458*e3f2c991SKeyur Desai * If the caller specified one, use that. Otherwise, give the 459*e3f2c991SKeyur Desai * same type that as we found for the Windows user. 460*e3f2c991SKeyur Desai */ 461*e3f2c991SKeyur Desai unix_type = q->eunixtype; 462*e3f2c991SKeyur Desai if (unix_type == _IDMAP_T_UNDEF) { 463*e3f2c991SKeyur Desai if (sid_type == _IDMAP_T_USER) 464*e3f2c991SKeyur Desai unix_type = _IDMAP_T_USER; 465*e3f2c991SKeyur Desai else if (sid_type == _IDMAP_T_GROUP) 466*e3f2c991SKeyur Desai unix_type = _IDMAP_T_GROUP; 467*e3f2c991SKeyur Desai } 468*e3f2c991SKeyur Desai 469*e3f2c991SKeyur Desai if (unix_type == _IDMAP_T_USER) 470*e3f2c991SKeyur Desai attr = state->ad_unixuser_attr; 471*e3f2c991SKeyur Desai else if (unix_type == _IDMAP_T_GROUP) 472*e3f2c991SKeyur Desai attr = state->ad_unixgroup_attr; 473*e3f2c991SKeyur Desai 474*e3f2c991SKeyur Desai if (attr != NULL) { 475*e3f2c991SKeyur Desai bvalues = ldap_get_values_len(ld, res, attr); 476*e3f2c991SKeyur Desai if (bvalues != NULL) { 477*e3f2c991SKeyur Desai unix_name = adutils_bv_str(bvalues[0]); 478*e3f2c991SKeyur Desai ldap_value_free_len(bvalues); 479*e3f2c991SKeyur Desai value = strdup(unix_name); 480*e3f2c991SKeyur Desai } 481*e3f2c991SKeyur Desai } 482*e3f2c991SKeyur Desai } 483*e3f2c991SKeyur Desai 484*e3f2c991SKeyur Desai bvalues = ldap_get_values_len(ld, res, SAN); 485*e3f2c991SKeyur Desai if (bvalues != NULL) { 486*e3f2c991SKeyur Desai san = adutils_bv_str(bvalues[0]); 487*e3f2c991SKeyur Desai ldap_value_free_len(bvalues); 488*e3f2c991SKeyur Desai } 489*e3f2c991SKeyur Desai 490*e3f2c991SKeyur Desai if (q->sid != NULL) { 491*e3f2c991SKeyur Desai bvalues = ldap_get_values_len(ld, res, OBJSID); 492*e3f2c991SKeyur Desai if (bvalues != NULL) { 493*e3f2c991SKeyur Desai sid = adutils_bv_objsid2sidstr(bvalues[0], &rid); 494*e3f2c991SKeyur Desai ldap_value_free_len(bvalues); 495*e3f2c991SKeyur Desai } 496*e3f2c991SKeyur Desai } 497*e3f2c991SKeyur Desai 498*e3f2c991SKeyur Desai idmap_setqresults(q, san, dn, 499*e3f2c991SKeyur Desai attr, value, 500*e3f2c991SKeyur Desai sid, rid, sid_type, 501*e3f2c991SKeyur Desai unix_name, pid); 502*e3f2c991SKeyur Desai 503*e3f2c991SKeyur Desai out: 504c5c4113dSnw141292 ldap_memfree(dn); 505c5c4113dSnw141292 } 506c5c4113dSnw141292 5072b4a7802SBaban Kenkre void 5082b4a7802SBaban Kenkre idmap_ldap_res_search_cb(LDAP *ld, LDAPMessage **res, int rc, int qid, 5092b4a7802SBaban Kenkre void *argp) 510c5c4113dSnw141292 { 5112b4a7802SBaban Kenkre idmap_query_state_t *state = (idmap_query_state_t *)argp; 5122b4a7802SBaban Kenkre idmap_q_t *q = &(state->queries[qid]); 513c5c4113dSnw141292 514c5c4113dSnw141292 switch (rc) { 515c5c4113dSnw141292 case LDAP_RES_SEARCH_RESULT: 5162b4a7802SBaban Kenkre if (q->search_res != NULL) { 5172b4a7802SBaban Kenkre idmap_extract_object(state, q, q->search_res, ld); 5182b4a7802SBaban Kenkre (void) ldap_msgfree(q->search_res); 5192b4a7802SBaban Kenkre q->search_res = NULL; 520bcced03bSjp151216 } else 5212b4a7802SBaban Kenkre q->ad_rc = ADUTILS_ERR_NOTFOUND; 522c5c4113dSnw141292 break; 523c5c4113dSnw141292 case LDAP_RES_SEARCH_ENTRY: 5242b4a7802SBaban Kenkre if (q->search_res == NULL) { 5252b4a7802SBaban Kenkre q->search_res = *res; 5262b4a7802SBaban Kenkre *res = NULL; 527bcced03bSjp151216 } 528c5c4113dSnw141292 break; 529c5c4113dSnw141292 default: 530c5c4113dSnw141292 break; 531c5c4113dSnw141292 } 53284decf41Sjp151216 } 53384decf41Sjp151216 534e3c2d6aaSnw141292 static 535e3c2d6aaSnw141292 void 536e3c2d6aaSnw141292 idmap_cleanup_batch(idmap_query_state_t *batch) 537e3c2d6aaSnw141292 { 538e3c2d6aaSnw141292 int i; 539e3c2d6aaSnw141292 540e3c2d6aaSnw141292 for (i = 0; i < batch->qcount; i++) { 541cd37da74Snw141292 if (batch->queries[i].ecanonname != NULL) 542cd37da74Snw141292 free(batch->queries[i].ecanonname); 543cd37da74Snw141292 batch->queries[i].ecanonname = NULL; 544cd37da74Snw141292 if (batch->queries[i].edomain != NULL) 545cd37da74Snw141292 free(batch->queries[i].edomain); 546cd37da74Snw141292 batch->queries[i].edomain = NULL; 547e3c2d6aaSnw141292 } 548e3c2d6aaSnw141292 } 549e3c2d6aaSnw141292 55084decf41Sjp151216 /* 55184decf41Sjp151216 * This routine frees the idmap_query_state_t structure 55284decf41Sjp151216 */ 553c5c4113dSnw141292 void 55484decf41Sjp151216 idmap_lookup_release_batch(idmap_query_state_t **state) 555c5c4113dSnw141292 { 5562b4a7802SBaban Kenkre if (state == NULL || *state == NULL) 5572b4a7802SBaban Kenkre return; 5582b4a7802SBaban Kenkre adutils_lookup_batch_release(&(*state)->qs); 559e3c2d6aaSnw141292 idmap_cleanup_batch(*state); 560*e3f2c991SKeyur Desai free((*state)->default_domain); 561c5c4113dSnw141292 free(*state); 562c5c4113dSnw141292 *state = NULL; 563c5c4113dSnw141292 } 564c5c4113dSnw141292 565c5c4113dSnw141292 idmap_retcode 5660dcc7149Snw141292 idmap_lookup_batch_end(idmap_query_state_t **state) 567c5c4113dSnw141292 { 5682b4a7802SBaban Kenkre adutils_rc ad_rc; 5692b4a7802SBaban Kenkre int i; 5702b4a7802SBaban Kenkre idmap_query_state_t *id_qs = *state; 571c5c4113dSnw141292 5722b4a7802SBaban Kenkre ad_rc = adutils_lookup_batch_end(&id_qs->qs); 573c5c4113dSnw141292 5742b4a7802SBaban Kenkre /* 5752b4a7802SBaban Kenkre * Map adutils rc to idmap_retcode in each 5762b4a7802SBaban Kenkre * query because consumers in dbutils.c 5772b4a7802SBaban Kenkre * expects idmap_retcode. 5782b4a7802SBaban Kenkre */ 5792b4a7802SBaban Kenkre for (i = 0; i < id_qs->qcount; i++) { 5802b4a7802SBaban Kenkre *id_qs->queries[i].rc = 5812b4a7802SBaban Kenkre map_adrc2idmaprc(id_qs->queries[i].ad_rc); 582c5c4113dSnw141292 } 58384decf41Sjp151216 idmap_lookup_release_batch(state); 5842b4a7802SBaban Kenkre return (map_adrc2idmaprc(ad_rc)); 585c5c4113dSnw141292 } 586c5c4113dSnw141292 587c5c4113dSnw141292 /* 588c5c4113dSnw141292 * Send one prepared search, queue up msgid, process what results are 589c5c4113dSnw141292 * available 590c5c4113dSnw141292 */ 591c5c4113dSnw141292 static 592c5c4113dSnw141292 idmap_retcode 59348258c6bSjp151216 idmap_batch_add1(idmap_query_state_t *state, const char *filter, 59448258c6bSjp151216 char *ecanonname, char *edomain, int eunixtype, 59548258c6bSjp151216 char **dn, char **attr, char **value, 59648258c6bSjp151216 char **canonname, char **dname, 59748258c6bSjp151216 char **sid, rid_t *rid, int *sid_type, char **unixname, 598*e3f2c991SKeyur Desai posix_id_t *pid, 59948258c6bSjp151216 idmap_retcode *rc) 600c5c4113dSnw141292 { 6012b4a7802SBaban Kenkre adutils_rc ad_rc; 6022b4a7802SBaban Kenkre int qid, i; 603c5c4113dSnw141292 idmap_q_t *q; 604*e3f2c991SKeyur Desai char *attrs[20]; /* Plenty */ 605c5c4113dSnw141292 6064d61c878SJulian Pullen qid = atomic_inc_32_nv(&state->qcount) - 1; 607c5c4113dSnw141292 q = &(state->queries[qid]); 608c5c4113dSnw141292 6094d61c878SJulian Pullen assert(qid < state->qsize); 6104d61c878SJulian Pullen 611cd37da74Snw141292 /* 6122b4a7802SBaban Kenkre * Remember the expected canonname, domainname and unix type 6132b4a7802SBaban Kenkre * so we can check the results * against it 614cd37da74Snw141292 */ 615cd37da74Snw141292 q->ecanonname = ecanonname; 616cd37da74Snw141292 q->edomain = edomain; 617e8c27ec8Sbaban q->eunixtype = eunixtype; 618e3c2d6aaSnw141292 619c5c4113dSnw141292 /* Remember where to put the results */ 620cd37da74Snw141292 q->canonname = canonname; 621e8c27ec8Sbaban q->sid = sid; 622c5c4113dSnw141292 q->domain = dname; 623c5c4113dSnw141292 q->rid = rid; 624c5c4113dSnw141292 q->sid_type = sid_type; 625c5c4113dSnw141292 q->rc = rc; 626e8c27ec8Sbaban q->unixname = unixname; 62748258c6bSjp151216 q->dn = dn; 62848258c6bSjp151216 q->attr = attr; 62948258c6bSjp151216 q->value = value; 630*e3f2c991SKeyur Desai q->pid = pid; 631e8c27ec8Sbaban 632*e3f2c991SKeyur Desai /* Add attributes that are not always needed */ 633*e3f2c991SKeyur Desai i = 0; 634*e3f2c991SKeyur Desai attrs[i++] = SAN; 635*e3f2c991SKeyur Desai attrs[i++] = OBJSID; 636*e3f2c991SKeyur Desai attrs[i++] = OBJCLASS; 637*e3f2c991SKeyur Desai 638e8c27ec8Sbaban if (unixname != NULL) { 639*e3f2c991SKeyur Desai /* Add unixuser/unixgroup attribute names to the attrs list */ 640e8c27ec8Sbaban if (eunixtype != _IDMAP_T_GROUP && 641e8c27ec8Sbaban state->ad_unixuser_attr != NULL) 642e8c27ec8Sbaban attrs[i++] = (char *)state->ad_unixuser_attr; 643e8c27ec8Sbaban if (eunixtype != _IDMAP_T_USER && 644e8c27ec8Sbaban state->ad_unixgroup_attr != NULL) 645*e3f2c991SKeyur Desai attrs[i++] = (char *)state->ad_unixgroup_attr; 646e8c27ec8Sbaban } 647c5c4113dSnw141292 648*e3f2c991SKeyur Desai if (pid != NULL) { 649*e3f2c991SKeyur Desai if (eunixtype != _IDMAP_T_GROUP) 650*e3f2c991SKeyur Desai attrs[i++] = UIDNUMBER; 651*e3f2c991SKeyur Desai if (eunixtype != _IDMAP_T_USER) 652*e3f2c991SKeyur Desai attrs[i++] = GIDNUMBER; 653*e3f2c991SKeyur Desai } 654*e3f2c991SKeyur Desai 655*e3f2c991SKeyur Desai attrs[i] = NULL; 656*e3f2c991SKeyur Desai 657c5c4113dSnw141292 /* 658c5c4113dSnw141292 * Provide sane defaults for the results in case we never hear 659c5c4113dSnw141292 * back from the DS before closing the connection. 660e3c2d6aaSnw141292 * 661e3c2d6aaSnw141292 * In particular we default the result to indicate a retriable 662e3c2d6aaSnw141292 * error. The first complete matching result entry will cause 663e3c2d6aaSnw141292 * this to be set to IDMAP_SUCCESS, and the end of the results 664e3c2d6aaSnw141292 * for this search will cause this to indicate "not found" if no 665e3c2d6aaSnw141292 * result entries arrived or no complete ones matched the lookup 666e3c2d6aaSnw141292 * we were doing. 667c5c4113dSnw141292 */ 668c5c4113dSnw141292 *rc = IDMAP_ERR_RETRIABLE_NET_ERR; 669e8c27ec8Sbaban if (sid_type != NULL) 670c5c4113dSnw141292 *sid_type = _IDMAP_T_OTHER; 671e8c27ec8Sbaban if (sid != NULL) 672e8c27ec8Sbaban *sid = NULL; 673c5c4113dSnw141292 if (dname != NULL) 674c5c4113dSnw141292 *dname = NULL; 675c5c4113dSnw141292 if (rid != NULL) 676c5c4113dSnw141292 *rid = 0; 67748258c6bSjp151216 if (dn != NULL) 67848258c6bSjp151216 *dn = NULL; 67948258c6bSjp151216 if (attr != NULL) 68048258c6bSjp151216 *attr = NULL; 68148258c6bSjp151216 if (value != NULL) 68248258c6bSjp151216 *value = NULL; 683c5c4113dSnw141292 684479ac375Sdm199847 /* 685479ac375Sdm199847 * Don't set *canonname to NULL because it may be pointing to the 686479ac375Sdm199847 * given winname. Later on if we get a canonical name from AD the 687479ac375Sdm199847 * old name if any will be freed before assigning the new name. 688479ac375Sdm199847 */ 689479ac375Sdm199847 690c5c4113dSnw141292 /* 6912b4a7802SBaban Kenkre * Invoke the mother of all APIs i.e. the adutils API 692c5c4113dSnw141292 */ 6932b4a7802SBaban Kenkre ad_rc = adutils_lookup_batch_add(state->qs, filter, 6942b4a7802SBaban Kenkre (const char **)attrs, 6952b4a7802SBaban Kenkre edomain, &q->result, &q->ad_rc); 6962b4a7802SBaban Kenkre return (map_adrc2idmaprc(ad_rc)); 697c5c4113dSnw141292 } 698c5c4113dSnw141292 699c5c4113dSnw141292 idmap_retcode 700c5c4113dSnw141292 idmap_name2sid_batch_add1(idmap_query_state_t *state, 701e8c27ec8Sbaban const char *name, const char *dname, int eunixtype, 70248258c6bSjp151216 char **dn, char **attr, char **value, 70348258c6bSjp151216 char **canonname, char **sid, rid_t *rid, 704*e3f2c991SKeyur Desai int *sid_type, char **unixname, 705*e3f2c991SKeyur Desai posix_id_t *pid, idmap_retcode *rc) 706c5c4113dSnw141292 { 707c5c4113dSnw141292 idmap_retcode retcode; 708*e3f2c991SKeyur Desai char *filter, *s_name; 709cd37da74Snw141292 char *ecanonname, *edomain; /* expected canonname */ 710c5c4113dSnw141292 711c5c4113dSnw141292 /* 712e3c2d6aaSnw141292 * Strategy: search the global catalog for user/group by 713e3c2d6aaSnw141292 * sAMAccountName = user/groupname with "" as the base DN and by 714e3c2d6aaSnw141292 * userPrincipalName = user/groupname@domain. The result 715e3c2d6aaSnw141292 * entries will be checked to conform to the name and domain 716e3c2d6aaSnw141292 * name given here. The DN, sAMAccountName, userPrincipalName, 717e3c2d6aaSnw141292 * objectSid and objectClass of the result entries are all we 718e3c2d6aaSnw141292 * need to figure out which entries match the lookup, the SID of 719e3c2d6aaSnw141292 * the user/group and whether it is a user or a group. 720c5c4113dSnw141292 */ 721c5c4113dSnw141292 722cd37da74Snw141292 if ((ecanonname = strdup(name)) == NULL) 723e3c2d6aaSnw141292 return (IDMAP_ERR_MEMORY); 724cd37da74Snw141292 725cd37da74Snw141292 if (dname == NULL || *dname == '\0') { 7262b4a7802SBaban Kenkre /* 'name' not qualified and dname not given */ 727*e3f2c991SKeyur Desai dname = state->default_domain; 7282b4a7802SBaban Kenkre edomain = strdup(dname); 729cd37da74Snw141292 if (edomain == NULL) { 730cd37da74Snw141292 free(ecanonname); 731e3c2d6aaSnw141292 return (IDMAP_ERR_MEMORY); 732cd37da74Snw141292 } 733cd37da74Snw141292 } else { 734cd37da74Snw141292 if ((edomain = strdup(dname)) == NULL) { 735cd37da74Snw141292 free(ecanonname); 736cd37da74Snw141292 return (IDMAP_ERR_MEMORY); 737cd37da74Snw141292 } 738e3c2d6aaSnw141292 } 739c5c4113dSnw141292 7404d61c878SJulian Pullen if (!adutils_lookup_check_domain(state->qs, dname)) { 7414d61c878SJulian Pullen free(ecanonname); 7424d61c878SJulian Pullen free(edomain); 7434d61c878SJulian Pullen return (IDMAP_ERR_DOMAIN_NOTFOUND); 7444d61c878SJulian Pullen } 7454d61c878SJulian Pullen 746479ac375Sdm199847 s_name = sanitize_for_ldap_filter(name); 747479ac375Sdm199847 if (s_name == NULL) { 748cd37da74Snw141292 free(ecanonname); 749479ac375Sdm199847 free(edomain); 750c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 751c5c4113dSnw141292 } 752479ac375Sdm199847 753479ac375Sdm199847 /* Assemble filter */ 754*e3f2c991SKeyur Desai (void) asprintf(&filter, SANFILTER, s_name); 755*e3f2c991SKeyur Desai if (s_name != name) 756*e3f2c991SKeyur Desai free(s_name); 757*e3f2c991SKeyur Desai if (filter == NULL) { 758479ac375Sdm199847 free(ecanonname); 759479ac375Sdm199847 free(edomain); 760479ac375Sdm199847 return (IDMAP_ERR_MEMORY); 761479ac375Sdm199847 } 762c5c4113dSnw141292 763cd37da74Snw141292 retcode = idmap_batch_add1(state, filter, ecanonname, edomain, 76448258c6bSjp151216 eunixtype, dn, attr, value, canonname, NULL, sid, rid, sid_type, 765*e3f2c991SKeyur Desai unixname, pid, rc); 766c5c4113dSnw141292 767c5c4113dSnw141292 free(filter); 768c5c4113dSnw141292 769c5c4113dSnw141292 return (retcode); 770c5c4113dSnw141292 } 771c5c4113dSnw141292 772c5c4113dSnw141292 idmap_retcode 773c5c4113dSnw141292 idmap_sid2name_batch_add1(idmap_query_state_t *state, 774e8c27ec8Sbaban const char *sid, const rid_t *rid, int eunixtype, 77548258c6bSjp151216 char **dn, char **attr, char **value, 77648258c6bSjp151216 char **name, char **dname, int *sid_type, 777*e3f2c991SKeyur Desai char **unixname, posix_id_t *pid, idmap_retcode *rc) 778c5c4113dSnw141292 { 779c5c4113dSnw141292 idmap_retcode retcode; 780*e3f2c991SKeyur Desai int ret; 781*e3f2c991SKeyur Desai char *filter; 7822b4a7802SBaban Kenkre char cbinsid[ADUTILS_MAXHEXBINSID + 1]; 783c5c4113dSnw141292 784c5c4113dSnw141292 /* 785c5c4113dSnw141292 * Strategy: search [the global catalog] for user/group by 786c5c4113dSnw141292 * objectSid = SID with empty base DN. The DN, sAMAccountName 787c5c4113dSnw141292 * and objectClass of the result are all we need to figure out 788c5c4113dSnw141292 * the name of the SID and whether it is a user, a group or a 789c5c4113dSnw141292 * computer. 790c5c4113dSnw141292 */ 791c5c4113dSnw141292 7924d61c878SJulian Pullen if (!adutils_lookup_check_sid_prefix(state->qs, sid)) 7934d61c878SJulian Pullen return (IDMAP_ERR_DOMAIN_NOTFOUND); 7944d61c878SJulian Pullen 7952b4a7802SBaban Kenkre ret = adutils_txtsid2hexbinsid(sid, rid, &cbinsid[0], sizeof (cbinsid)); 796c5c4113dSnw141292 if (ret != 0) 797c5c4113dSnw141292 return (IDMAP_ERR_SID); 798c5c4113dSnw141292 799c5c4113dSnw141292 /* Assemble filter */ 800*e3f2c991SKeyur Desai (void) asprintf(&filter, OBJSIDFILTER, cbinsid); 801*e3f2c991SKeyur Desai if (filter == NULL) 802c5c4113dSnw141292 return (IDMAP_ERR_MEMORY); 803c5c4113dSnw141292 804e8c27ec8Sbaban retcode = idmap_batch_add1(state, filter, NULL, NULL, eunixtype, 805*e3f2c991SKeyur Desai dn, attr, value, name, dname, NULL, NULL, sid_type, unixname, 806*e3f2c991SKeyur Desai pid, rc); 807e8c27ec8Sbaban 808e8c27ec8Sbaban free(filter); 809e8c27ec8Sbaban 810e8c27ec8Sbaban return (retcode); 811e8c27ec8Sbaban } 812e8c27ec8Sbaban 813e8c27ec8Sbaban idmap_retcode 814e8c27ec8Sbaban idmap_unixname2sid_batch_add1(idmap_query_state_t *state, 815e8c27ec8Sbaban const char *unixname, int is_user, int is_wuser, 81648258c6bSjp151216 char **dn, char **attr, char **value, 81748258c6bSjp151216 char **sid, rid_t *rid, char **name, 81848258c6bSjp151216 char **dname, int *sid_type, idmap_retcode *rc) 819e8c27ec8Sbaban { 820e8c27ec8Sbaban idmap_retcode retcode; 821*e3f2c991SKeyur Desai char *filter, *s_unixname; 822*e3f2c991SKeyur Desai const char *attrname; 823e8c27ec8Sbaban 824e8c27ec8Sbaban /* Get unixuser or unixgroup AD attribute name */ 825e8c27ec8Sbaban attrname = (is_user) ? 826e8c27ec8Sbaban state->ad_unixuser_attr : state->ad_unixgroup_attr; 827e8c27ec8Sbaban if (attrname == NULL) 828e8c27ec8Sbaban return (IDMAP_ERR_NOTFOUND); 829e8c27ec8Sbaban 830479ac375Sdm199847 s_unixname = sanitize_for_ldap_filter(unixname); 831479ac375Sdm199847 if (s_unixname == NULL) 832479ac375Sdm199847 return (IDMAP_ERR_MEMORY); 833479ac375Sdm199847 834e8c27ec8Sbaban /* Assemble filter */ 835*e3f2c991SKeyur Desai (void) asprintf(&filter, "(&(objectclass=%s)(%s=%s))", 836*e3f2c991SKeyur Desai is_wuser ? "user" : "group", attrname, s_unixname); 837479ac375Sdm199847 if (s_unixname != unixname) 838479ac375Sdm199847 free(s_unixname); 839*e3f2c991SKeyur Desai if (filter == NULL) { 840e8c27ec8Sbaban return (IDMAP_ERR_MEMORY); 841479ac375Sdm199847 } 842e8c27ec8Sbaban 843e8c27ec8Sbaban retcode = idmap_batch_add1(state, filter, NULL, NULL, 84448258c6bSjp151216 _IDMAP_T_UNDEF, dn, NULL, NULL, name, dname, sid, rid, sid_type, 845*e3f2c991SKeyur Desai NULL, NULL, rc); 84648258c6bSjp151216 84748258c6bSjp151216 if (retcode == IDMAP_SUCCESS && attr != NULL) { 84848258c6bSjp151216 if ((*attr = strdup(attrname)) == NULL) 84948258c6bSjp151216 retcode = IDMAP_ERR_MEMORY; 85048258c6bSjp151216 } 85148258c6bSjp151216 85248258c6bSjp151216 if (retcode == IDMAP_SUCCESS && value != NULL) { 85348258c6bSjp151216 if ((*value = strdup(unixname)) == NULL) 85448258c6bSjp151216 retcode = IDMAP_ERR_MEMORY; 85548258c6bSjp151216 } 856*e3f2c991SKeyur Desai 857*e3f2c991SKeyur Desai free(filter); 858*e3f2c991SKeyur Desai 859*e3f2c991SKeyur Desai return (retcode); 860*e3f2c991SKeyur Desai } 861*e3f2c991SKeyur Desai 862*e3f2c991SKeyur Desai idmap_retcode 863*e3f2c991SKeyur Desai idmap_pid2sid_batch_add1(idmap_query_state_t *state, 864*e3f2c991SKeyur Desai posix_id_t pid, int is_user, 865*e3f2c991SKeyur Desai char **dn, char **attr, char **value, 866*e3f2c991SKeyur Desai char **sid, rid_t *rid, char **name, 867*e3f2c991SKeyur Desai char **dname, int *sid_type, idmap_retcode *rc) 868*e3f2c991SKeyur Desai { 869*e3f2c991SKeyur Desai idmap_retcode retcode; 870*e3f2c991SKeyur Desai char *filter; 871*e3f2c991SKeyur Desai const char *attrname; 872*e3f2c991SKeyur Desai 873*e3f2c991SKeyur Desai /* Assemble filter */ 874*e3f2c991SKeyur Desai if (is_user) { 875*e3f2c991SKeyur Desai (void) asprintf(&filter, UIDNUMBERFILTER, pid); 876*e3f2c991SKeyur Desai attrname = UIDNUMBER; 877*e3f2c991SKeyur Desai } else { 878*e3f2c991SKeyur Desai (void) asprintf(&filter, GIDNUMBERFILTER, pid); 879*e3f2c991SKeyur Desai attrname = GIDNUMBER; 880*e3f2c991SKeyur Desai } 881*e3f2c991SKeyur Desai if (filter == NULL) 882*e3f2c991SKeyur Desai return (IDMAP_ERR_MEMORY); 883*e3f2c991SKeyur Desai 884*e3f2c991SKeyur Desai retcode = idmap_batch_add1(state, filter, NULL, NULL, 885*e3f2c991SKeyur Desai _IDMAP_T_UNDEF, dn, NULL, NULL, name, dname, sid, rid, sid_type, 886*e3f2c991SKeyur Desai NULL, NULL, rc); 887*e3f2c991SKeyur Desai 888*e3f2c991SKeyur Desai if (retcode == IDMAP_SUCCESS && attr != NULL) { 889*e3f2c991SKeyur Desai if ((*attr = strdup(attrname)) == NULL) 890*e3f2c991SKeyur Desai retcode = IDMAP_ERR_MEMORY; 891*e3f2c991SKeyur Desai } 892*e3f2c991SKeyur Desai 893*e3f2c991SKeyur Desai if (retcode == IDMAP_SUCCESS && value != NULL) { 894*e3f2c991SKeyur Desai (void) asprintf(value, "%u", pid); 895*e3f2c991SKeyur Desai if (*value == NULL) 896*e3f2c991SKeyur Desai retcode = IDMAP_ERR_MEMORY; 89748258c6bSjp151216 } 898c5c4113dSnw141292 899c5c4113dSnw141292 free(filter); 900c5c4113dSnw141292 901c5c4113dSnw141292 return (retcode); 902c5c4113dSnw141292 } 903