18040SBaban.Kenkre@Sun.COM /* 28040SBaban.Kenkre@Sun.COM * CDDL HEADER START 38040SBaban.Kenkre@Sun.COM * 48040SBaban.Kenkre@Sun.COM * The contents of this file are subject to the terms of the 58040SBaban.Kenkre@Sun.COM * Common Development and Distribution License (the "License"). 68040SBaban.Kenkre@Sun.COM * You may not use this file except in compliance with the License. 78040SBaban.Kenkre@Sun.COM * 88040SBaban.Kenkre@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 98040SBaban.Kenkre@Sun.COM * or http://www.opensolaris.org/os/licensing. 108040SBaban.Kenkre@Sun.COM * See the License for the specific language governing permissions 118040SBaban.Kenkre@Sun.COM * and limitations under the License. 128040SBaban.Kenkre@Sun.COM * 138040SBaban.Kenkre@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 148040SBaban.Kenkre@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 158040SBaban.Kenkre@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 168040SBaban.Kenkre@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 178040SBaban.Kenkre@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 188040SBaban.Kenkre@Sun.COM * 198040SBaban.Kenkre@Sun.COM * CDDL HEADER END 208040SBaban.Kenkre@Sun.COM */ 218040SBaban.Kenkre@Sun.COM /* 228040SBaban.Kenkre@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 238040SBaban.Kenkre@Sun.COM * Use is subject to license terms. 248040SBaban.Kenkre@Sun.COM */ 258040SBaban.Kenkre@Sun.COM 268040SBaban.Kenkre@Sun.COM #include <malloc.h> 278040SBaban.Kenkre@Sun.COM #include <synch.h> 288040SBaban.Kenkre@Sun.COM #include <syslog.h> 298040SBaban.Kenkre@Sun.COM #include <rpcsvc/ypclnt.h> 308040SBaban.Kenkre@Sun.COM #include <rpcsvc/yp_prot.h> 318040SBaban.Kenkre@Sun.COM #include <pthread.h> 328040SBaban.Kenkre@Sun.COM #include <ctype.h> 338040SBaban.Kenkre@Sun.COM #include <stdlib.h> 348040SBaban.Kenkre@Sun.COM #include <stdio.h> 358040SBaban.Kenkre@Sun.COM #include <signal.h> 368040SBaban.Kenkre@Sun.COM #include <sys/stat.h> 378040SBaban.Kenkre@Sun.COM #include <assert.h> 388040SBaban.Kenkre@Sun.COM #include "ad_common.h" 398040SBaban.Kenkre@Sun.COM 408040SBaban.Kenkre@Sun.COM static pthread_mutex_t statelock = PTHREAD_MUTEX_INITIALIZER; 418040SBaban.Kenkre@Sun.COM static nssad_state_t state = {0}; 428040SBaban.Kenkre@Sun.COM 438040SBaban.Kenkre@Sun.COM static void 448040SBaban.Kenkre@Sun.COM nssad_cfg_free_props(nssad_prop_t *props) 458040SBaban.Kenkre@Sun.COM { 468040SBaban.Kenkre@Sun.COM if (props->domain_name != NULL) { 478040SBaban.Kenkre@Sun.COM free(props->domain_name); 488040SBaban.Kenkre@Sun.COM props->domain_name = NULL; 498040SBaban.Kenkre@Sun.COM } 508040SBaban.Kenkre@Sun.COM if (props->domain_controller != NULL) { 518040SBaban.Kenkre@Sun.COM free(props->domain_controller); 528040SBaban.Kenkre@Sun.COM props->domain_controller = NULL; 538040SBaban.Kenkre@Sun.COM } 548040SBaban.Kenkre@Sun.COM } 558040SBaban.Kenkre@Sun.COM 568040SBaban.Kenkre@Sun.COM static int 578040SBaban.Kenkre@Sun.COM nssad_cfg_discover_props(const char *domain, ad_disc_t ad_ctx, 588040SBaban.Kenkre@Sun.COM nssad_prop_t *props) 598040SBaban.Kenkre@Sun.COM { 608040SBaban.Kenkre@Sun.COM ad_disc_refresh(ad_ctx); 618040SBaban.Kenkre@Sun.COM if (ad_disc_set_DomainName(ad_ctx, domain) != 0) 628040SBaban.Kenkre@Sun.COM return (-1); 638040SBaban.Kenkre@Sun.COM if (props->domain_controller == NULL) 648040SBaban.Kenkre@Sun.COM props->domain_controller = 65*8361SJulian.Pullen@Sun.COM ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE, 66*8361SJulian.Pullen@Sun.COM NULL); 678040SBaban.Kenkre@Sun.COM return (0); 688040SBaban.Kenkre@Sun.COM } 698040SBaban.Kenkre@Sun.COM 708040SBaban.Kenkre@Sun.COM static int 718040SBaban.Kenkre@Sun.COM nssad_cfg_reload_ad(nssad_prop_t *props, adutils_ad_t **ad) 728040SBaban.Kenkre@Sun.COM { 738040SBaban.Kenkre@Sun.COM int i; 748040SBaban.Kenkre@Sun.COM adutils_ad_t *new; 758040SBaban.Kenkre@Sun.COM 768040SBaban.Kenkre@Sun.COM if (props->domain_controller == NULL || 778040SBaban.Kenkre@Sun.COM props->domain_controller[0].host[0] == '\0') 788040SBaban.Kenkre@Sun.COM return (0); 798040SBaban.Kenkre@Sun.COM if (adutils_ad_alloc(&new, props->domain_name, 808040SBaban.Kenkre@Sun.COM ADUTILS_AD_DATA) != ADUTILS_SUCCESS) 818040SBaban.Kenkre@Sun.COM return (-1); 828040SBaban.Kenkre@Sun.COM for (i = 0; props->domain_controller[i].host[0] != '\0'; i++) { 838040SBaban.Kenkre@Sun.COM if (adutils_add_ds(new, 848040SBaban.Kenkre@Sun.COM props->domain_controller[i].host, 858040SBaban.Kenkre@Sun.COM props->domain_controller[i].port) != ADUTILS_SUCCESS) { 868040SBaban.Kenkre@Sun.COM adutils_ad_free(&new); 878040SBaban.Kenkre@Sun.COM return (-1); 888040SBaban.Kenkre@Sun.COM } 898040SBaban.Kenkre@Sun.COM } 908040SBaban.Kenkre@Sun.COM 918040SBaban.Kenkre@Sun.COM if (*ad != NULL) 928040SBaban.Kenkre@Sun.COM adutils_ad_free(ad); 938040SBaban.Kenkre@Sun.COM *ad = new; 948040SBaban.Kenkre@Sun.COM return (0); 958040SBaban.Kenkre@Sun.COM } 968040SBaban.Kenkre@Sun.COM 978040SBaban.Kenkre@Sun.COM static 988040SBaban.Kenkre@Sun.COM int 998040SBaban.Kenkre@Sun.COM update_dirs(idmap_ad_disc_ds_t **value, idmap_ad_disc_ds_t **new) 1008040SBaban.Kenkre@Sun.COM { 1018040SBaban.Kenkre@Sun.COM if (*value == *new) 1028040SBaban.Kenkre@Sun.COM return (0); 1038040SBaban.Kenkre@Sun.COM 1048040SBaban.Kenkre@Sun.COM if (*value != NULL && *new != NULL && 1058040SBaban.Kenkre@Sun.COM ad_disc_compare_ds(*value, *new) == 0) { 1068040SBaban.Kenkre@Sun.COM free(*new); 1078040SBaban.Kenkre@Sun.COM *new = NULL; 1088040SBaban.Kenkre@Sun.COM return (0); 1098040SBaban.Kenkre@Sun.COM } 1108040SBaban.Kenkre@Sun.COM 1118040SBaban.Kenkre@Sun.COM if (*value) 1128040SBaban.Kenkre@Sun.COM free(*value); 1138040SBaban.Kenkre@Sun.COM *value = *new; 1148040SBaban.Kenkre@Sun.COM *new = NULL; 1158040SBaban.Kenkre@Sun.COM return (1); 1168040SBaban.Kenkre@Sun.COM } 1178040SBaban.Kenkre@Sun.COM 1188040SBaban.Kenkre@Sun.COM static 1198040SBaban.Kenkre@Sun.COM int 1208040SBaban.Kenkre@Sun.COM nssad_cfg_refresh(nssad_cfg_t *cp) 1218040SBaban.Kenkre@Sun.COM { 1228040SBaban.Kenkre@Sun.COM nssad_prop_t props; 1238040SBaban.Kenkre@Sun.COM 1248040SBaban.Kenkre@Sun.COM (void) ad_disc_SubnetChanged(cp->ad_ctx); 1258040SBaban.Kenkre@Sun.COM (void) memset(&props, 0, sizeof (props)); 1268040SBaban.Kenkre@Sun.COM if (nssad_cfg_discover_props(cp->props.domain_name, cp->ad_ctx, 1278040SBaban.Kenkre@Sun.COM &props) < 0) 1288040SBaban.Kenkre@Sun.COM return (-1); 1298040SBaban.Kenkre@Sun.COM if (update_dirs(&cp->props.domain_controller, 1308040SBaban.Kenkre@Sun.COM &props.domain_controller)) { 1318040SBaban.Kenkre@Sun.COM if (cp->props.domain_controller != NULL && 1328040SBaban.Kenkre@Sun.COM cp->props.domain_controller[0].host[0] != '\0') 1338040SBaban.Kenkre@Sun.COM (void) nssad_cfg_reload_ad(&cp->props, &cp->ad); 1348040SBaban.Kenkre@Sun.COM } 1358040SBaban.Kenkre@Sun.COM return (0); 1368040SBaban.Kenkre@Sun.COM } 1378040SBaban.Kenkre@Sun.COM 1388040SBaban.Kenkre@Sun.COM static void 1398040SBaban.Kenkre@Sun.COM nssad_cfg_destroy(nssad_cfg_t *cp) 1408040SBaban.Kenkre@Sun.COM { 1418040SBaban.Kenkre@Sun.COM if (cp != NULL) { 1428040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_destroy(&cp->lock); 1438040SBaban.Kenkre@Sun.COM ad_disc_fini(cp->ad_ctx); 1448040SBaban.Kenkre@Sun.COM nssad_cfg_free_props(&cp->props); 1458040SBaban.Kenkre@Sun.COM adutils_ad_free(&cp->ad); 1468040SBaban.Kenkre@Sun.COM free(cp); 1478040SBaban.Kenkre@Sun.COM } 1488040SBaban.Kenkre@Sun.COM } 1498040SBaban.Kenkre@Sun.COM 1508040SBaban.Kenkre@Sun.COM static nssad_cfg_t * 1518040SBaban.Kenkre@Sun.COM nssad_cfg_create(const char *domain) 1528040SBaban.Kenkre@Sun.COM { 1538040SBaban.Kenkre@Sun.COM nssad_cfg_t *cp; 1548040SBaban.Kenkre@Sun.COM 1558040SBaban.Kenkre@Sun.COM if ((cp = calloc(1, sizeof (*cp))) == NULL) 1568040SBaban.Kenkre@Sun.COM return (NULL); 1578040SBaban.Kenkre@Sun.COM if (pthread_rwlock_init(&cp->lock, NULL) != 0) { 1588040SBaban.Kenkre@Sun.COM free(cp); 1598040SBaban.Kenkre@Sun.COM return (NULL); 1608040SBaban.Kenkre@Sun.COM } 1618040SBaban.Kenkre@Sun.COM adutils_set_log(-1, TRUE, FALSE); 1628040SBaban.Kenkre@Sun.COM if ((cp->ad_ctx = ad_disc_init()) == NULL) 1638040SBaban.Kenkre@Sun.COM goto errout; 1648040SBaban.Kenkre@Sun.COM if ((cp->props.domain_name = strdup(domain)) == NULL) 1658040SBaban.Kenkre@Sun.COM goto errout; 1668040SBaban.Kenkre@Sun.COM if (nssad_cfg_discover_props(domain, cp->ad_ctx, &cp->props) < 0) 1678040SBaban.Kenkre@Sun.COM goto errout; 1688040SBaban.Kenkre@Sun.COM if (nssad_cfg_reload_ad(&cp->props, &cp->ad) < 0) 1698040SBaban.Kenkre@Sun.COM goto errout; 1708040SBaban.Kenkre@Sun.COM return (cp); 1718040SBaban.Kenkre@Sun.COM errout: 1728040SBaban.Kenkre@Sun.COM nssad_cfg_destroy(cp); 1738040SBaban.Kenkre@Sun.COM return (NULL); 1748040SBaban.Kenkre@Sun.COM } 1758040SBaban.Kenkre@Sun.COM 1768040SBaban.Kenkre@Sun.COM #define hex_char(n) "0123456789abcdef"[n & 0xf] 1778040SBaban.Kenkre@Sun.COM 1788040SBaban.Kenkre@Sun.COM int 1798040SBaban.Kenkre@Sun.COM _ldap_filter_name(char *filter_name, const char *name, int filter_name_size) 1808040SBaban.Kenkre@Sun.COM { 1818040SBaban.Kenkre@Sun.COM char *end = filter_name + filter_name_size; 1828040SBaban.Kenkre@Sun.COM char c; 1838040SBaban.Kenkre@Sun.COM 1848040SBaban.Kenkre@Sun.COM for (; *name; name++) { 1858040SBaban.Kenkre@Sun.COM c = *name; 1868040SBaban.Kenkre@Sun.COM switch (c) { 1878040SBaban.Kenkre@Sun.COM case '*': 1888040SBaban.Kenkre@Sun.COM case '(': 1898040SBaban.Kenkre@Sun.COM case ')': 1908040SBaban.Kenkre@Sun.COM case '\\': 1918040SBaban.Kenkre@Sun.COM if (end <= filter_name + 3) 1928040SBaban.Kenkre@Sun.COM return (-1); 1938040SBaban.Kenkre@Sun.COM *filter_name++ = '\\'; 1948040SBaban.Kenkre@Sun.COM *filter_name++ = hex_char(c >> 4); 1958040SBaban.Kenkre@Sun.COM *filter_name++ = hex_char(c & 0xf); 1968040SBaban.Kenkre@Sun.COM break; 1978040SBaban.Kenkre@Sun.COM default: 1988040SBaban.Kenkre@Sun.COM if (end <= filter_name + 1) 1998040SBaban.Kenkre@Sun.COM return (-1); 2008040SBaban.Kenkre@Sun.COM *filter_name++ = c; 2018040SBaban.Kenkre@Sun.COM break; 2028040SBaban.Kenkre@Sun.COM } 2038040SBaban.Kenkre@Sun.COM } 2048040SBaban.Kenkre@Sun.COM if (end <= filter_name) 2058040SBaban.Kenkre@Sun.COM return (-1); 2068040SBaban.Kenkre@Sun.COM *filter_name = '\0'; 2078040SBaban.Kenkre@Sun.COM return (0); 2088040SBaban.Kenkre@Sun.COM } 2098040SBaban.Kenkre@Sun.COM 2108040SBaban.Kenkre@Sun.COM static 2118040SBaban.Kenkre@Sun.COM nss_status_t 2128040SBaban.Kenkre@Sun.COM map_adrc2nssrc(adutils_rc adrc) 2138040SBaban.Kenkre@Sun.COM { 2148040SBaban.Kenkre@Sun.COM if (adrc == ADUTILS_SUCCESS) 2158040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_SUCCESS); 2168040SBaban.Kenkre@Sun.COM if (adrc == ADUTILS_ERR_NOTFOUND) 2178040SBaban.Kenkre@Sun.COM errno = 0; 2188040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND); 2198040SBaban.Kenkre@Sun.COM } 2208040SBaban.Kenkre@Sun.COM 2218040SBaban.Kenkre@Sun.COM /* ARGSUSED */ 2228040SBaban.Kenkre@Sun.COM nss_status_t 2238040SBaban.Kenkre@Sun.COM _nss_ad_marshall_data(ad_backend_ptr be, nss_XbyY_args_t *argp) 2248040SBaban.Kenkre@Sun.COM { 2258040SBaban.Kenkre@Sun.COM int stat; 2268040SBaban.Kenkre@Sun.COM 2278040SBaban.Kenkre@Sun.COM if (argp->buf.result == NULL) { 2288040SBaban.Kenkre@Sun.COM /* 2298040SBaban.Kenkre@Sun.COM * This suggests that the process (e.g. nscd) expects 2308040SBaban.Kenkre@Sun.COM * nssad to return the data in native file format in 2318040SBaban.Kenkre@Sun.COM * argp->buf.buffer i.e. no need to marshall the data. 2328040SBaban.Kenkre@Sun.COM */ 2338040SBaban.Kenkre@Sun.COM argp->returnval = argp->buf.buffer; 2348040SBaban.Kenkre@Sun.COM argp->returnlen = strlen(argp->buf.buffer); 2358040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_STR_PARSE_SUCCESS); 2368040SBaban.Kenkre@Sun.COM } 2378040SBaban.Kenkre@Sun.COM 2388040SBaban.Kenkre@Sun.COM if (argp->str2ent == NULL) 2398040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_STR_PARSE_PARSE); 2408040SBaban.Kenkre@Sun.COM 2418040SBaban.Kenkre@Sun.COM stat = (*argp->str2ent)(be->buffer, be->buflen, 2428040SBaban.Kenkre@Sun.COM argp->buf.result, argp->buf.buffer, argp->buf.buflen); 2438040SBaban.Kenkre@Sun.COM 2448040SBaban.Kenkre@Sun.COM if (stat == NSS_STR_PARSE_SUCCESS) { 2458040SBaban.Kenkre@Sun.COM argp->returnval = argp->buf.result; 2468040SBaban.Kenkre@Sun.COM argp->returnlen = 1; /* irrelevant */ 2478040SBaban.Kenkre@Sun.COM } 2488040SBaban.Kenkre@Sun.COM return ((nss_status_t)stat); 2498040SBaban.Kenkre@Sun.COM } 2508040SBaban.Kenkre@Sun.COM 2518040SBaban.Kenkre@Sun.COM nss_status_t 2528040SBaban.Kenkre@Sun.COM _nss_ad_sanitize_status(ad_backend_ptr be, nss_XbyY_args_t *argp, 2538040SBaban.Kenkre@Sun.COM nss_status_t stat) 2548040SBaban.Kenkre@Sun.COM { 2558040SBaban.Kenkre@Sun.COM if (be->buffer != NULL) { 2568040SBaban.Kenkre@Sun.COM free(be->buffer); 2578040SBaban.Kenkre@Sun.COM be->buffer = NULL; 2588040SBaban.Kenkre@Sun.COM be->buflen = 0; 2598040SBaban.Kenkre@Sun.COM be->db_type = NSS_AD_DB_NONE; 2608040SBaban.Kenkre@Sun.COM } 2618040SBaban.Kenkre@Sun.COM 2628040SBaban.Kenkre@Sun.COM if (stat == NSS_STR_PARSE_SUCCESS) { 2638040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_SUCCESS); 2648040SBaban.Kenkre@Sun.COM } else if (stat == NSS_STR_PARSE_PARSE) { 2658040SBaban.Kenkre@Sun.COM argp->returnval = 0; 2668040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND); 2678040SBaban.Kenkre@Sun.COM } else if (stat == NSS_STR_PARSE_ERANGE) { 2688040SBaban.Kenkre@Sun.COM argp->erange = 1; 2698040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND); 2708040SBaban.Kenkre@Sun.COM } 2718040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_UNAVAIL); 2728040SBaban.Kenkre@Sun.COM } 2738040SBaban.Kenkre@Sun.COM 2748040SBaban.Kenkre@Sun.COM /* ARGSUSED */ 2758040SBaban.Kenkre@Sun.COM static 2768040SBaban.Kenkre@Sun.COM nssad_cfg_t * 2778040SBaban.Kenkre@Sun.COM get_cfg(const char *domain) 2788040SBaban.Kenkre@Sun.COM { 2798040SBaban.Kenkre@Sun.COM nssad_cfg_t *cp, *lru, *prev; 2808040SBaban.Kenkre@Sun.COM 2818040SBaban.Kenkre@Sun.COM /* 2828040SBaban.Kenkre@Sun.COM * Note about the queue: 2838040SBaban.Kenkre@Sun.COM * 2848040SBaban.Kenkre@Sun.COM * The queue is used to hold our per domain 2858040SBaban.Kenkre@Sun.COM * configs. The queue is limited to CFG_QUEUE_MAX_SIZE. 2868040SBaban.Kenkre@Sun.COM * If the queue increases beyond that point we toss 2878040SBaban.Kenkre@Sun.COM * out the LRU entry. The entries are inserted into 2888040SBaban.Kenkre@Sun.COM * the queue at state.qtail and the LRU entry is 2898040SBaban.Kenkre@Sun.COM * removed from state.qhead. state.qnext points 2908040SBaban.Kenkre@Sun.COM * from the qtail to the qhead. Everytime a config 2918040SBaban.Kenkre@Sun.COM * is accessed it is moved to qtail. 2928040SBaban.Kenkre@Sun.COM */ 2938040SBaban.Kenkre@Sun.COM 2948040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&statelock); 2958040SBaban.Kenkre@Sun.COM 2968040SBaban.Kenkre@Sun.COM for (cp = state.qtail, prev = NULL; cp != NULL; 2978040SBaban.Kenkre@Sun.COM prev = cp, cp = cp->qnext) { 2988040SBaban.Kenkre@Sun.COM if (cp->props.domain_name == NULL || 2998040SBaban.Kenkre@Sun.COM strcasecmp(cp->props.domain_name, domain) != 0) 3008040SBaban.Kenkre@Sun.COM continue; 3018040SBaban.Kenkre@Sun.COM 3028040SBaban.Kenkre@Sun.COM /* Found config for the given domain. */ 3038040SBaban.Kenkre@Sun.COM 3048040SBaban.Kenkre@Sun.COM if (state.qtail != cp) { 3058040SBaban.Kenkre@Sun.COM /* 3068040SBaban.Kenkre@Sun.COM * Move the entry to the tail of the queue. 3078040SBaban.Kenkre@Sun.COM * This way the LRU entry can be found at 3088040SBaban.Kenkre@Sun.COM * the head of the queue. 3098040SBaban.Kenkre@Sun.COM */ 3108040SBaban.Kenkre@Sun.COM prev->qnext = cp->qnext; 3118040SBaban.Kenkre@Sun.COM if (state.qhead == cp) 3128040SBaban.Kenkre@Sun.COM state.qhead = prev; 3138040SBaban.Kenkre@Sun.COM cp->qnext = state.qtail; 3148040SBaban.Kenkre@Sun.COM state.qtail = cp; 3158040SBaban.Kenkre@Sun.COM } 3168040SBaban.Kenkre@Sun.COM 3178040SBaban.Kenkre@Sun.COM if (ad_disc_get_TTL(cp->ad_ctx) == 0) { 3188040SBaban.Kenkre@Sun.COM /* 3198040SBaban.Kenkre@Sun.COM * If there are expired items in the 3208040SBaban.Kenkre@Sun.COM * config, grab the write lock and 3218040SBaban.Kenkre@Sun.COM * refresh the config. 3228040SBaban.Kenkre@Sun.COM */ 3238040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_wrlock(&cp->lock); 3248040SBaban.Kenkre@Sun.COM if (nssad_cfg_refresh(cp) < 0) { 3258040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_unlock(&cp->lock); 3268040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&statelock); 3278040SBaban.Kenkre@Sun.COM return (NULL); 3288040SBaban.Kenkre@Sun.COM } 3298040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_unlock(&cp->lock); 3308040SBaban.Kenkre@Sun.COM } 3318040SBaban.Kenkre@Sun.COM 3328040SBaban.Kenkre@Sun.COM /* Return the config found */ 3338040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_rdlock(&cp->lock); 3348040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&statelock); 3358040SBaban.Kenkre@Sun.COM return (cp); 3368040SBaban.Kenkre@Sun.COM } 3378040SBaban.Kenkre@Sun.COM 3388040SBaban.Kenkre@Sun.COM /* Create new config entry for the domain */ 3398040SBaban.Kenkre@Sun.COM if ((cp = nssad_cfg_create(domain)) == NULL) { 3408040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&statelock); 3418040SBaban.Kenkre@Sun.COM return (NULL); 3428040SBaban.Kenkre@Sun.COM } 3438040SBaban.Kenkre@Sun.COM 3448040SBaban.Kenkre@Sun.COM /* Add it to the queue */ 3458040SBaban.Kenkre@Sun.COM state.qcount++; 3468040SBaban.Kenkre@Sun.COM if (state.qtail == NULL) { 3478040SBaban.Kenkre@Sun.COM state.qtail = state.qhead = cp; 3488040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_rdlock(&cp->lock); 3498040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&statelock); 3508040SBaban.Kenkre@Sun.COM return (cp); 3518040SBaban.Kenkre@Sun.COM } 3528040SBaban.Kenkre@Sun.COM cp->qnext = state.qtail; 3538040SBaban.Kenkre@Sun.COM state.qtail = cp; 3548040SBaban.Kenkre@Sun.COM 3558040SBaban.Kenkre@Sun.COM /* If the queue has exceeded its size, remove the LRU entry */ 3568040SBaban.Kenkre@Sun.COM if (state.qcount >= CFG_QUEUE_MAX_SIZE) { 3578040SBaban.Kenkre@Sun.COM /* Detach the lru entry and destroy */ 3588040SBaban.Kenkre@Sun.COM lru = state.qhead; 3598040SBaban.Kenkre@Sun.COM if (pthread_rwlock_trywrlock(&lru->lock) == 0) { 3608040SBaban.Kenkre@Sun.COM for (prev = state.qtail; prev != NULL; 3618040SBaban.Kenkre@Sun.COM prev = prev->qnext) { 3628040SBaban.Kenkre@Sun.COM if (prev->qnext != lru) 3638040SBaban.Kenkre@Sun.COM continue; 3648040SBaban.Kenkre@Sun.COM state.qhead = prev; 3658040SBaban.Kenkre@Sun.COM prev->qnext = NULL; 3668040SBaban.Kenkre@Sun.COM state.qcount--; 3678040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_unlock(&lru->lock); 3688040SBaban.Kenkre@Sun.COM nssad_cfg_destroy(lru); 3698040SBaban.Kenkre@Sun.COM break; 3708040SBaban.Kenkre@Sun.COM } 3718040SBaban.Kenkre@Sun.COM (void) assert(prev != NULL); 3728040SBaban.Kenkre@Sun.COM } 3738040SBaban.Kenkre@Sun.COM } 3748040SBaban.Kenkre@Sun.COM 3758040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_rdlock(&cp->lock); 3768040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&statelock); 3778040SBaban.Kenkre@Sun.COM return (cp); 3788040SBaban.Kenkre@Sun.COM } 3798040SBaban.Kenkre@Sun.COM 3808040SBaban.Kenkre@Sun.COM 3818040SBaban.Kenkre@Sun.COM /* ARGSUSED */ 3828040SBaban.Kenkre@Sun.COM static 3838040SBaban.Kenkre@Sun.COM nss_status_t 3848040SBaban.Kenkre@Sun.COM ad_lookup(const char *filter, const char **attrs, 3858040SBaban.Kenkre@Sun.COM const char *domain, adutils_result_t **result) 3868040SBaban.Kenkre@Sun.COM { 3878040SBaban.Kenkre@Sun.COM int retries = 0; 3888040SBaban.Kenkre@Sun.COM adutils_rc rc, brc; 3898040SBaban.Kenkre@Sun.COM adutils_query_state_t *qs; 3908040SBaban.Kenkre@Sun.COM nssad_cfg_t *cp; 3918040SBaban.Kenkre@Sun.COM 3928040SBaban.Kenkre@Sun.COM retry: 3938040SBaban.Kenkre@Sun.COM if ((cp = get_cfg(domain)) == NULL) 3948040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND); 3958040SBaban.Kenkre@Sun.COM 3968040SBaban.Kenkre@Sun.COM rc = adutils_lookup_batch_start(cp->ad, 1, NULL, NULL, &qs); 3978040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_unlock(&cp->lock); 3988040SBaban.Kenkre@Sun.COM if (rc != ADUTILS_SUCCESS) 3998040SBaban.Kenkre@Sun.COM goto out; 4008040SBaban.Kenkre@Sun.COM 4018040SBaban.Kenkre@Sun.COM rc = adutils_lookup_batch_add(qs, filter, attrs, domain, result, &brc); 4028040SBaban.Kenkre@Sun.COM if (rc != ADUTILS_SUCCESS) { 4038040SBaban.Kenkre@Sun.COM adutils_lookup_batch_release(&qs); 4048040SBaban.Kenkre@Sun.COM goto out; 4058040SBaban.Kenkre@Sun.COM } 4068040SBaban.Kenkre@Sun.COM 4078040SBaban.Kenkre@Sun.COM rc = adutils_lookup_batch_end(&qs); 4088040SBaban.Kenkre@Sun.COM if (rc != ADUTILS_SUCCESS) 4098040SBaban.Kenkre@Sun.COM goto out; 4108040SBaban.Kenkre@Sun.COM rc = brc; 4118040SBaban.Kenkre@Sun.COM 4128040SBaban.Kenkre@Sun.COM out: 4138040SBaban.Kenkre@Sun.COM if (rc == ADUTILS_ERR_RETRIABLE_NET_ERR && 4148040SBaban.Kenkre@Sun.COM retries++ < ADUTILS_DEF_NUM_RETRIES) 4158040SBaban.Kenkre@Sun.COM goto retry; 4168040SBaban.Kenkre@Sun.COM return (map_adrc2nssrc(rc)); 4178040SBaban.Kenkre@Sun.COM } 4188040SBaban.Kenkre@Sun.COM 4198040SBaban.Kenkre@Sun.COM 4208040SBaban.Kenkre@Sun.COM /* ARGSUSED */ 4218040SBaban.Kenkre@Sun.COM nss_status_t 4228040SBaban.Kenkre@Sun.COM _nss_ad_lookup(ad_backend_ptr be, nss_XbyY_args_t *argp, 4238040SBaban.Kenkre@Sun.COM const char *database, const char *searchfilter, 4248040SBaban.Kenkre@Sun.COM const char *dname, int *try_idmap) 4258040SBaban.Kenkre@Sun.COM { 4268040SBaban.Kenkre@Sun.COM nss_status_t stat; 4278040SBaban.Kenkre@Sun.COM 4288040SBaban.Kenkre@Sun.COM *try_idmap = 0; 4298040SBaban.Kenkre@Sun.COM 4308040SBaban.Kenkre@Sun.COM /* Clear up results if any */ 4318040SBaban.Kenkre@Sun.COM (void) adutils_freeresult(&be->result); 4328040SBaban.Kenkre@Sun.COM 4338040SBaban.Kenkre@Sun.COM /* Lookup AD */ 4348040SBaban.Kenkre@Sun.COM stat = ad_lookup(searchfilter, be->attrs, dname, &be->result); 4358040SBaban.Kenkre@Sun.COM if (stat != NSS_SUCCESS) { 4368040SBaban.Kenkre@Sun.COM argp->returnval = 0; 4378040SBaban.Kenkre@Sun.COM *try_idmap = 1; 4388040SBaban.Kenkre@Sun.COM return (stat); 4398040SBaban.Kenkre@Sun.COM } 4408040SBaban.Kenkre@Sun.COM 4418040SBaban.Kenkre@Sun.COM /* Map AD object(s) to string in native file format */ 4428040SBaban.Kenkre@Sun.COM stat = be->adobj2str(be, argp); 4438040SBaban.Kenkre@Sun.COM if (stat == NSS_STR_PARSE_SUCCESS) 4448040SBaban.Kenkre@Sun.COM stat = _nss_ad_marshall_data(be, argp); 4458040SBaban.Kenkre@Sun.COM return (_nss_ad_sanitize_status(be, argp, stat)); 4468040SBaban.Kenkre@Sun.COM } 4478040SBaban.Kenkre@Sun.COM 4488040SBaban.Kenkre@Sun.COM static 4498040SBaban.Kenkre@Sun.COM void 4508040SBaban.Kenkre@Sun.COM clean_state() 4518040SBaban.Kenkre@Sun.COM { 4528040SBaban.Kenkre@Sun.COM nssad_cfg_t *cp, *curr; 4538040SBaban.Kenkre@Sun.COM 4548040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&statelock); 4558040SBaban.Kenkre@Sun.COM for (cp = state.qtail; cp != NULL; ) { 4568040SBaban.Kenkre@Sun.COM curr = cp; 4578040SBaban.Kenkre@Sun.COM cp = cp->qnext; 4588040SBaban.Kenkre@Sun.COM nssad_cfg_destroy(curr); 4598040SBaban.Kenkre@Sun.COM } 4608040SBaban.Kenkre@Sun.COM (void) memset(&state, 0, sizeof (state)); 4618040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&statelock); 4628040SBaban.Kenkre@Sun.COM } 4638040SBaban.Kenkre@Sun.COM 4648040SBaban.Kenkre@Sun.COM static 4658040SBaban.Kenkre@Sun.COM void 4668040SBaban.Kenkre@Sun.COM _clean_ad_backend(ad_backend_ptr be) 4678040SBaban.Kenkre@Sun.COM { 4688040SBaban.Kenkre@Sun.COM if (be->tablename != NULL) 4698040SBaban.Kenkre@Sun.COM free(be->tablename); 4708040SBaban.Kenkre@Sun.COM if (be->buffer != NULL) { 4718040SBaban.Kenkre@Sun.COM free(be->buffer); 4728040SBaban.Kenkre@Sun.COM be->buffer = NULL; 4738040SBaban.Kenkre@Sun.COM } 4748040SBaban.Kenkre@Sun.COM free(be); 4758040SBaban.Kenkre@Sun.COM } 4768040SBaban.Kenkre@Sun.COM 4778040SBaban.Kenkre@Sun.COM 4788040SBaban.Kenkre@Sun.COM /* 4798040SBaban.Kenkre@Sun.COM * _nss_ad_destr frees allocated memory before exiting this nsswitch shared 4808040SBaban.Kenkre@Sun.COM * backend library. This function is called before returning control back to 4818040SBaban.Kenkre@Sun.COM * nsswitch. 4828040SBaban.Kenkre@Sun.COM */ 4838040SBaban.Kenkre@Sun.COM /*ARGSUSED*/ 4848040SBaban.Kenkre@Sun.COM nss_status_t 4858040SBaban.Kenkre@Sun.COM _nss_ad_destr(ad_backend_ptr be, void *a) 4868040SBaban.Kenkre@Sun.COM { 4878040SBaban.Kenkre@Sun.COM (void) _clean_ad_backend(be); 4888040SBaban.Kenkre@Sun.COM clean_state(); 4898040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_SUCCESS); 4908040SBaban.Kenkre@Sun.COM } 4918040SBaban.Kenkre@Sun.COM 4928040SBaban.Kenkre@Sun.COM 4938040SBaban.Kenkre@Sun.COM /*ARGSUSED*/ 4948040SBaban.Kenkre@Sun.COM nss_status_t 4958040SBaban.Kenkre@Sun.COM _nss_ad_setent(ad_backend_ptr be, void *a) 4968040SBaban.Kenkre@Sun.COM { 4978040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_UNAVAIL); 4988040SBaban.Kenkre@Sun.COM } 4998040SBaban.Kenkre@Sun.COM 5008040SBaban.Kenkre@Sun.COM 5018040SBaban.Kenkre@Sun.COM /*ARGSUSED*/ 5028040SBaban.Kenkre@Sun.COM nss_status_t 5038040SBaban.Kenkre@Sun.COM _nss_ad_endent(ad_backend_ptr be, void *a) 5048040SBaban.Kenkre@Sun.COM { 5058040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_UNAVAIL); 5068040SBaban.Kenkre@Sun.COM } 5078040SBaban.Kenkre@Sun.COM 5088040SBaban.Kenkre@Sun.COM 5098040SBaban.Kenkre@Sun.COM /*ARGSUSED*/ 5108040SBaban.Kenkre@Sun.COM nss_status_t 5118040SBaban.Kenkre@Sun.COM _nss_ad_getent(ad_backend_ptr be, void *a) 5128040SBaban.Kenkre@Sun.COM { 5138040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_UNAVAIL); 5148040SBaban.Kenkre@Sun.COM } 5158040SBaban.Kenkre@Sun.COM 5168040SBaban.Kenkre@Sun.COM 5178040SBaban.Kenkre@Sun.COM nss_backend_t * 5188040SBaban.Kenkre@Sun.COM _nss_ad_constr(ad_backend_op_t ops[], int nops, char *tablename, 5198040SBaban.Kenkre@Sun.COM const char **attrs, fnf adobj2str) 5208040SBaban.Kenkre@Sun.COM { 5218040SBaban.Kenkre@Sun.COM ad_backend_ptr be; 5228040SBaban.Kenkre@Sun.COM 5238040SBaban.Kenkre@Sun.COM if ((be = (ad_backend_ptr) calloc(1, sizeof (*be))) == NULL) 5248040SBaban.Kenkre@Sun.COM return (NULL); 5258040SBaban.Kenkre@Sun.COM if ((be->tablename = (char *)strdup(tablename)) == NULL) { 5268040SBaban.Kenkre@Sun.COM free(be); 5278040SBaban.Kenkre@Sun.COM return (NULL); 5288040SBaban.Kenkre@Sun.COM } 5298040SBaban.Kenkre@Sun.COM be->ops = ops; 5308040SBaban.Kenkre@Sun.COM be->nops = (nss_dbop_t)nops; 5318040SBaban.Kenkre@Sun.COM be->attrs = attrs; 5328040SBaban.Kenkre@Sun.COM be->adobj2str = adobj2str; 5338040SBaban.Kenkre@Sun.COM (void) memset(&state, 0, sizeof (state)); 5348040SBaban.Kenkre@Sun.COM return ((nss_backend_t *)be); 5358040SBaban.Kenkre@Sun.COM } 536