12b4a7802SBaban Kenkre /* 22b4a7802SBaban Kenkre * CDDL HEADER START 32b4a7802SBaban Kenkre * 42b4a7802SBaban Kenkre * The contents of this file are subject to the terms of the 52b4a7802SBaban Kenkre * Common Development and Distribution License (the "License"). 62b4a7802SBaban Kenkre * You may not use this file except in compliance with the License. 72b4a7802SBaban Kenkre * 82b4a7802SBaban Kenkre * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92b4a7802SBaban Kenkre * or http://www.opensolaris.org/os/licensing. 102b4a7802SBaban Kenkre * See the License for the specific language governing permissions 112b4a7802SBaban Kenkre * and limitations under the License. 122b4a7802SBaban Kenkre * 132b4a7802SBaban Kenkre * When distributing Covered Code, include this CDDL HEADER in each 142b4a7802SBaban Kenkre * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152b4a7802SBaban Kenkre * If applicable, add the following below this CDDL HEADER, with the 162b4a7802SBaban Kenkre * fields enclosed by brackets "[]" replaced with your own identifying 172b4a7802SBaban Kenkre * information: Portions Copyright [yyyy] [name of copyright owner] 182b4a7802SBaban Kenkre * 192b4a7802SBaban Kenkre * CDDL HEADER END 202b4a7802SBaban Kenkre */ 212b4a7802SBaban Kenkre /* 227a8a68f5SJulian Pullen * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 232b4a7802SBaban Kenkre * Use is subject to license terms. 24*b3700b07SGordon Ross * 25*b3700b07SGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 262b4a7802SBaban Kenkre */ 272b4a7802SBaban Kenkre 282b4a7802SBaban Kenkre #include <malloc.h> 292b4a7802SBaban Kenkre #include <synch.h> 302b4a7802SBaban Kenkre #include <syslog.h> 312b4a7802SBaban Kenkre #include <rpcsvc/ypclnt.h> 322b4a7802SBaban Kenkre #include <rpcsvc/yp_prot.h> 332b4a7802SBaban Kenkre #include <pthread.h> 342b4a7802SBaban Kenkre #include <ctype.h> 352b4a7802SBaban Kenkre #include <stdlib.h> 362b4a7802SBaban Kenkre #include <stdio.h> 372b4a7802SBaban Kenkre #include <signal.h> 382b4a7802SBaban Kenkre #include <sys/stat.h> 392b4a7802SBaban Kenkre #include <assert.h> 402b4a7802SBaban Kenkre #include "ad_common.h" 412b4a7802SBaban Kenkre 422b4a7802SBaban Kenkre static pthread_mutex_t statelock = PTHREAD_MUTEX_INITIALIZER; 432b4a7802SBaban Kenkre static nssad_state_t state = {0}; 442b4a7802SBaban Kenkre 452b4a7802SBaban Kenkre static void 462b4a7802SBaban Kenkre nssad_cfg_free_props(nssad_prop_t *props) 472b4a7802SBaban Kenkre { 482b4a7802SBaban Kenkre if (props->domain_name != NULL) { 492b4a7802SBaban Kenkre free(props->domain_name); 502b4a7802SBaban Kenkre props->domain_name = NULL; 512b4a7802SBaban Kenkre } 522b4a7802SBaban Kenkre if (props->domain_controller != NULL) { 532b4a7802SBaban Kenkre free(props->domain_controller); 542b4a7802SBaban Kenkre props->domain_controller = NULL; 552b4a7802SBaban Kenkre } 562b4a7802SBaban Kenkre } 572b4a7802SBaban Kenkre 582b4a7802SBaban Kenkre static int 592b4a7802SBaban Kenkre nssad_cfg_discover_props(const char *domain, ad_disc_t ad_ctx, 602b4a7802SBaban Kenkre nssad_prop_t *props) 612b4a7802SBaban Kenkre { 622b4a7802SBaban Kenkre ad_disc_refresh(ad_ctx); 632b4a7802SBaban Kenkre if (ad_disc_set_DomainName(ad_ctx, domain) != 0) 642b4a7802SBaban Kenkre return (-1); 652b4a7802SBaban Kenkre if (props->domain_controller == NULL) 662b4a7802SBaban Kenkre props->domain_controller = 674d61c878SJulian Pullen ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE, 684d61c878SJulian Pullen NULL); 692b4a7802SBaban Kenkre return (0); 702b4a7802SBaban Kenkre } 712b4a7802SBaban Kenkre 722b4a7802SBaban Kenkre static int 732b4a7802SBaban Kenkre nssad_cfg_reload_ad(nssad_prop_t *props, adutils_ad_t **ad) 742b4a7802SBaban Kenkre { 752b4a7802SBaban Kenkre int i; 762b4a7802SBaban Kenkre adutils_ad_t *new; 772b4a7802SBaban Kenkre 782b4a7802SBaban Kenkre if (props->domain_controller == NULL || 792b4a7802SBaban Kenkre props->domain_controller[0].host[0] == '\0') 802b4a7802SBaban Kenkre return (0); 812b4a7802SBaban Kenkre if (adutils_ad_alloc(&new, props->domain_name, 822b4a7802SBaban Kenkre ADUTILS_AD_DATA) != ADUTILS_SUCCESS) 832b4a7802SBaban Kenkre return (-1); 842b4a7802SBaban Kenkre for (i = 0; props->domain_controller[i].host[0] != '\0'; i++) { 852b4a7802SBaban Kenkre if (adutils_add_ds(new, 862b4a7802SBaban Kenkre props->domain_controller[i].host, 872b4a7802SBaban Kenkre props->domain_controller[i].port) != ADUTILS_SUCCESS) { 882b4a7802SBaban Kenkre adutils_ad_free(&new); 892b4a7802SBaban Kenkre return (-1); 902b4a7802SBaban Kenkre } 912b4a7802SBaban Kenkre } 922b4a7802SBaban Kenkre 932b4a7802SBaban Kenkre if (*ad != NULL) 942b4a7802SBaban Kenkre adutils_ad_free(ad); 952b4a7802SBaban Kenkre *ad = new; 962b4a7802SBaban Kenkre return (0); 972b4a7802SBaban Kenkre } 982b4a7802SBaban Kenkre 992b4a7802SBaban Kenkre static 1002b4a7802SBaban Kenkre int 101*b3700b07SGordon Ross update_dirs(ad_disc_ds_t **value, ad_disc_ds_t **new) 1022b4a7802SBaban Kenkre { 1032b4a7802SBaban Kenkre if (*value == *new) 1042b4a7802SBaban Kenkre return (0); 1052b4a7802SBaban Kenkre 1062b4a7802SBaban Kenkre if (*value != NULL && *new != NULL && 1072b4a7802SBaban Kenkre ad_disc_compare_ds(*value, *new) == 0) { 1082b4a7802SBaban Kenkre free(*new); 1092b4a7802SBaban Kenkre *new = NULL; 1102b4a7802SBaban Kenkre return (0); 1112b4a7802SBaban Kenkre } 1122b4a7802SBaban Kenkre 1132b4a7802SBaban Kenkre if (*value) 1142b4a7802SBaban Kenkre free(*value); 1152b4a7802SBaban Kenkre *value = *new; 1162b4a7802SBaban Kenkre *new = NULL; 1172b4a7802SBaban Kenkre return (1); 1182b4a7802SBaban Kenkre } 1192b4a7802SBaban Kenkre 1202b4a7802SBaban Kenkre static 1212b4a7802SBaban Kenkre int 1222b4a7802SBaban Kenkre nssad_cfg_refresh(nssad_cfg_t *cp) 1232b4a7802SBaban Kenkre { 1242b4a7802SBaban Kenkre nssad_prop_t props; 1252b4a7802SBaban Kenkre 1262b4a7802SBaban Kenkre (void) ad_disc_SubnetChanged(cp->ad_ctx); 1272b4a7802SBaban Kenkre (void) memset(&props, 0, sizeof (props)); 1282b4a7802SBaban Kenkre if (nssad_cfg_discover_props(cp->props.domain_name, cp->ad_ctx, 1292b4a7802SBaban Kenkre &props) < 0) 1302b4a7802SBaban Kenkre return (-1); 1312b4a7802SBaban Kenkre if (update_dirs(&cp->props.domain_controller, 1322b4a7802SBaban Kenkre &props.domain_controller)) { 1332b4a7802SBaban Kenkre if (cp->props.domain_controller != NULL && 1342b4a7802SBaban Kenkre cp->props.domain_controller[0].host[0] != '\0') 1352b4a7802SBaban Kenkre (void) nssad_cfg_reload_ad(&cp->props, &cp->ad); 1362b4a7802SBaban Kenkre } 1372b4a7802SBaban Kenkre return (0); 1382b4a7802SBaban Kenkre } 1392b4a7802SBaban Kenkre 1402b4a7802SBaban Kenkre static void 1412b4a7802SBaban Kenkre nssad_cfg_destroy(nssad_cfg_t *cp) 1422b4a7802SBaban Kenkre { 1432b4a7802SBaban Kenkre if (cp != NULL) { 1442b4a7802SBaban Kenkre (void) pthread_rwlock_destroy(&cp->lock); 1452b4a7802SBaban Kenkre ad_disc_fini(cp->ad_ctx); 1462b4a7802SBaban Kenkre nssad_cfg_free_props(&cp->props); 1472b4a7802SBaban Kenkre adutils_ad_free(&cp->ad); 1482b4a7802SBaban Kenkre free(cp); 1492b4a7802SBaban Kenkre } 1502b4a7802SBaban Kenkre } 1512b4a7802SBaban Kenkre 1522b4a7802SBaban Kenkre static nssad_cfg_t * 1532b4a7802SBaban Kenkre nssad_cfg_create(const char *domain) 1542b4a7802SBaban Kenkre { 1552b4a7802SBaban Kenkre nssad_cfg_t *cp; 1562b4a7802SBaban Kenkre 1572b4a7802SBaban Kenkre if ((cp = calloc(1, sizeof (*cp))) == NULL) 1582b4a7802SBaban Kenkre return (NULL); 1592b4a7802SBaban Kenkre if (pthread_rwlock_init(&cp->lock, NULL) != 0) { 1602b4a7802SBaban Kenkre free(cp); 1612b4a7802SBaban Kenkre return (NULL); 1622b4a7802SBaban Kenkre } 1632b4a7802SBaban Kenkre if ((cp->ad_ctx = ad_disc_init()) == NULL) 1642b4a7802SBaban Kenkre goto errout; 1652b4a7802SBaban Kenkre if ((cp->props.domain_name = strdup(domain)) == NULL) 1662b4a7802SBaban Kenkre goto errout; 1672b4a7802SBaban Kenkre if (nssad_cfg_discover_props(domain, cp->ad_ctx, &cp->props) < 0) 1682b4a7802SBaban Kenkre goto errout; 1692b4a7802SBaban Kenkre if (nssad_cfg_reload_ad(&cp->props, &cp->ad) < 0) 1702b4a7802SBaban Kenkre goto errout; 1712b4a7802SBaban Kenkre return (cp); 1722b4a7802SBaban Kenkre errout: 1732b4a7802SBaban Kenkre nssad_cfg_destroy(cp); 1742b4a7802SBaban Kenkre return (NULL); 1752b4a7802SBaban Kenkre } 1762b4a7802SBaban Kenkre 1772b4a7802SBaban Kenkre #define hex_char(n) "0123456789abcdef"[n & 0xf] 1782b4a7802SBaban Kenkre 1792b4a7802SBaban Kenkre int 1802b4a7802SBaban Kenkre _ldap_filter_name(char *filter_name, const char *name, int filter_name_size) 1812b4a7802SBaban Kenkre { 1822b4a7802SBaban Kenkre char *end = filter_name + filter_name_size; 1832b4a7802SBaban Kenkre char c; 1842b4a7802SBaban Kenkre 1852b4a7802SBaban Kenkre for (; *name; name++) { 1862b4a7802SBaban Kenkre c = *name; 1872b4a7802SBaban Kenkre switch (c) { 1882b4a7802SBaban Kenkre case '*': 1892b4a7802SBaban Kenkre case '(': 1902b4a7802SBaban Kenkre case ')': 1912b4a7802SBaban Kenkre case '\\': 1922b4a7802SBaban Kenkre if (end <= filter_name + 3) 1932b4a7802SBaban Kenkre return (-1); 1942b4a7802SBaban Kenkre *filter_name++ = '\\'; 1952b4a7802SBaban Kenkre *filter_name++ = hex_char(c >> 4); 1962b4a7802SBaban Kenkre *filter_name++ = hex_char(c & 0xf); 1972b4a7802SBaban Kenkre break; 1982b4a7802SBaban Kenkre default: 1992b4a7802SBaban Kenkre if (end <= filter_name + 1) 2002b4a7802SBaban Kenkre return (-1); 2012b4a7802SBaban Kenkre *filter_name++ = c; 2022b4a7802SBaban Kenkre break; 2032b4a7802SBaban Kenkre } 2042b4a7802SBaban Kenkre } 2052b4a7802SBaban Kenkre if (end <= filter_name) 2062b4a7802SBaban Kenkre return (-1); 2072b4a7802SBaban Kenkre *filter_name = '\0'; 2082b4a7802SBaban Kenkre return (0); 2092b4a7802SBaban Kenkre } 2102b4a7802SBaban Kenkre 2112b4a7802SBaban Kenkre static 2122b4a7802SBaban Kenkre nss_status_t 2132b4a7802SBaban Kenkre map_adrc2nssrc(adutils_rc adrc) 2142b4a7802SBaban Kenkre { 2152b4a7802SBaban Kenkre if (adrc == ADUTILS_SUCCESS) 2162b4a7802SBaban Kenkre return ((nss_status_t)NSS_SUCCESS); 2172b4a7802SBaban Kenkre if (adrc == ADUTILS_ERR_NOTFOUND) 2182b4a7802SBaban Kenkre errno = 0; 2192b4a7802SBaban Kenkre return ((nss_status_t)NSS_NOTFOUND); 2202b4a7802SBaban Kenkre } 2212b4a7802SBaban Kenkre 2222b4a7802SBaban Kenkre /* ARGSUSED */ 2232b4a7802SBaban Kenkre nss_status_t 2242b4a7802SBaban Kenkre _nss_ad_marshall_data(ad_backend_ptr be, nss_XbyY_args_t *argp) 2252b4a7802SBaban Kenkre { 2262b4a7802SBaban Kenkre int stat; 2272b4a7802SBaban Kenkre 2282b4a7802SBaban Kenkre if (argp->buf.result == NULL) { 2292b4a7802SBaban Kenkre /* 2302b4a7802SBaban Kenkre * This suggests that the process (e.g. nscd) expects 2312b4a7802SBaban Kenkre * nssad to return the data in native file format in 2322b4a7802SBaban Kenkre * argp->buf.buffer i.e. no need to marshall the data. 2332b4a7802SBaban Kenkre */ 2342b4a7802SBaban Kenkre argp->returnval = argp->buf.buffer; 2352b4a7802SBaban Kenkre argp->returnlen = strlen(argp->buf.buffer); 2362b4a7802SBaban Kenkre return ((nss_status_t)NSS_STR_PARSE_SUCCESS); 2372b4a7802SBaban Kenkre } 2382b4a7802SBaban Kenkre 2392b4a7802SBaban Kenkre if (argp->str2ent == NULL) 2402b4a7802SBaban Kenkre return ((nss_status_t)NSS_STR_PARSE_PARSE); 2412b4a7802SBaban Kenkre 2422b4a7802SBaban Kenkre stat = (*argp->str2ent)(be->buffer, be->buflen, 2432b4a7802SBaban Kenkre argp->buf.result, argp->buf.buffer, argp->buf.buflen); 2442b4a7802SBaban Kenkre 2452b4a7802SBaban Kenkre if (stat == NSS_STR_PARSE_SUCCESS) { 2462b4a7802SBaban Kenkre argp->returnval = argp->buf.result; 2472b4a7802SBaban Kenkre argp->returnlen = 1; /* irrelevant */ 2482b4a7802SBaban Kenkre } 2492b4a7802SBaban Kenkre return ((nss_status_t)stat); 2502b4a7802SBaban Kenkre } 2512b4a7802SBaban Kenkre 2522b4a7802SBaban Kenkre nss_status_t 2532b4a7802SBaban Kenkre _nss_ad_sanitize_status(ad_backend_ptr be, nss_XbyY_args_t *argp, 2542b4a7802SBaban Kenkre nss_status_t stat) 2552b4a7802SBaban Kenkre { 2562b4a7802SBaban Kenkre if (be->buffer != NULL) { 2572b4a7802SBaban Kenkre free(be->buffer); 2582b4a7802SBaban Kenkre be->buffer = NULL; 2592b4a7802SBaban Kenkre be->buflen = 0; 2602b4a7802SBaban Kenkre be->db_type = NSS_AD_DB_NONE; 2612b4a7802SBaban Kenkre } 2622b4a7802SBaban Kenkre 2632b4a7802SBaban Kenkre if (stat == NSS_STR_PARSE_SUCCESS) { 2642b4a7802SBaban Kenkre return ((nss_status_t)NSS_SUCCESS); 2652b4a7802SBaban Kenkre } else if (stat == NSS_STR_PARSE_PARSE) { 2662b4a7802SBaban Kenkre argp->returnval = 0; 2672b4a7802SBaban Kenkre return ((nss_status_t)NSS_NOTFOUND); 2682b4a7802SBaban Kenkre } else if (stat == NSS_STR_PARSE_ERANGE) { 2692b4a7802SBaban Kenkre argp->erange = 1; 2702b4a7802SBaban Kenkre return ((nss_status_t)NSS_NOTFOUND); 2712b4a7802SBaban Kenkre } 2722b4a7802SBaban Kenkre return ((nss_status_t)NSS_UNAVAIL); 2732b4a7802SBaban Kenkre } 2742b4a7802SBaban Kenkre 2752b4a7802SBaban Kenkre /* ARGSUSED */ 2762b4a7802SBaban Kenkre static 2772b4a7802SBaban Kenkre nssad_cfg_t * 2782b4a7802SBaban Kenkre get_cfg(const char *domain) 2792b4a7802SBaban Kenkre { 2802b4a7802SBaban Kenkre nssad_cfg_t *cp, *lru, *prev; 2812b4a7802SBaban Kenkre 2822b4a7802SBaban Kenkre /* 2832b4a7802SBaban Kenkre * Note about the queue: 2842b4a7802SBaban Kenkre * 2852b4a7802SBaban Kenkre * The queue is used to hold our per domain 2862b4a7802SBaban Kenkre * configs. The queue is limited to CFG_QUEUE_MAX_SIZE. 2872b4a7802SBaban Kenkre * If the queue increases beyond that point we toss 2882b4a7802SBaban Kenkre * out the LRU entry. The entries are inserted into 2892b4a7802SBaban Kenkre * the queue at state.qtail and the LRU entry is 2902b4a7802SBaban Kenkre * removed from state.qhead. state.qnext points 2912b4a7802SBaban Kenkre * from the qtail to the qhead. Everytime a config 2922b4a7802SBaban Kenkre * is accessed it is moved to qtail. 2932b4a7802SBaban Kenkre */ 2942b4a7802SBaban Kenkre 2952b4a7802SBaban Kenkre (void) pthread_mutex_lock(&statelock); 2962b4a7802SBaban Kenkre 2972b4a7802SBaban Kenkre for (cp = state.qtail, prev = NULL; cp != NULL; 2982b4a7802SBaban Kenkre prev = cp, cp = cp->qnext) { 2992b4a7802SBaban Kenkre if (cp->props.domain_name == NULL || 3002b4a7802SBaban Kenkre strcasecmp(cp->props.domain_name, domain) != 0) 3012b4a7802SBaban Kenkre continue; 3022b4a7802SBaban Kenkre 3032b4a7802SBaban Kenkre /* Found config for the given domain. */ 3042b4a7802SBaban Kenkre 3052b4a7802SBaban Kenkre if (state.qtail != cp) { 3062b4a7802SBaban Kenkre /* 3072b4a7802SBaban Kenkre * Move the entry to the tail of the queue. 3082b4a7802SBaban Kenkre * This way the LRU entry can be found at 3092b4a7802SBaban Kenkre * the head of the queue. 3102b4a7802SBaban Kenkre */ 3112b4a7802SBaban Kenkre prev->qnext = cp->qnext; 3122b4a7802SBaban Kenkre if (state.qhead == cp) 3132b4a7802SBaban Kenkre state.qhead = prev; 3142b4a7802SBaban Kenkre cp->qnext = state.qtail; 3152b4a7802SBaban Kenkre state.qtail = cp; 3162b4a7802SBaban Kenkre } 3172b4a7802SBaban Kenkre 3182b4a7802SBaban Kenkre if (ad_disc_get_TTL(cp->ad_ctx) == 0) { 3192b4a7802SBaban Kenkre /* 3202b4a7802SBaban Kenkre * If there are expired items in the 3212b4a7802SBaban Kenkre * config, grab the write lock and 3222b4a7802SBaban Kenkre * refresh the config. 3232b4a7802SBaban Kenkre */ 3242b4a7802SBaban Kenkre (void) pthread_rwlock_wrlock(&cp->lock); 3252b4a7802SBaban Kenkre if (nssad_cfg_refresh(cp) < 0) { 3262b4a7802SBaban Kenkre (void) pthread_rwlock_unlock(&cp->lock); 3272b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&statelock); 3282b4a7802SBaban Kenkre return (NULL); 3292b4a7802SBaban Kenkre } 3302b4a7802SBaban Kenkre (void) pthread_rwlock_unlock(&cp->lock); 3312b4a7802SBaban Kenkre } 3322b4a7802SBaban Kenkre 3332b4a7802SBaban Kenkre /* Return the config found */ 3342b4a7802SBaban Kenkre (void) pthread_rwlock_rdlock(&cp->lock); 3352b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&statelock); 3362b4a7802SBaban Kenkre return (cp); 3372b4a7802SBaban Kenkre } 3382b4a7802SBaban Kenkre 3392b4a7802SBaban Kenkre /* Create new config entry for the domain */ 3402b4a7802SBaban Kenkre if ((cp = nssad_cfg_create(domain)) == NULL) { 3412b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&statelock); 3422b4a7802SBaban Kenkre return (NULL); 3432b4a7802SBaban Kenkre } 3442b4a7802SBaban Kenkre 3452b4a7802SBaban Kenkre /* Add it to the queue */ 3462b4a7802SBaban Kenkre state.qcount++; 3472b4a7802SBaban Kenkre if (state.qtail == NULL) { 3482b4a7802SBaban Kenkre state.qtail = state.qhead = cp; 3492b4a7802SBaban Kenkre (void) pthread_rwlock_rdlock(&cp->lock); 3502b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&statelock); 3512b4a7802SBaban Kenkre return (cp); 3522b4a7802SBaban Kenkre } 3532b4a7802SBaban Kenkre cp->qnext = state.qtail; 3542b4a7802SBaban Kenkre state.qtail = cp; 3552b4a7802SBaban Kenkre 3562b4a7802SBaban Kenkre /* If the queue has exceeded its size, remove the LRU entry */ 3572b4a7802SBaban Kenkre if (state.qcount >= CFG_QUEUE_MAX_SIZE) { 3582b4a7802SBaban Kenkre /* Detach the lru entry and destroy */ 3592b4a7802SBaban Kenkre lru = state.qhead; 3602b4a7802SBaban Kenkre if (pthread_rwlock_trywrlock(&lru->lock) == 0) { 3612b4a7802SBaban Kenkre for (prev = state.qtail; prev != NULL; 3622b4a7802SBaban Kenkre prev = prev->qnext) { 3632b4a7802SBaban Kenkre if (prev->qnext != lru) 3642b4a7802SBaban Kenkre continue; 3652b4a7802SBaban Kenkre state.qhead = prev; 3662b4a7802SBaban Kenkre prev->qnext = NULL; 3672b4a7802SBaban Kenkre state.qcount--; 3682b4a7802SBaban Kenkre (void) pthread_rwlock_unlock(&lru->lock); 3692b4a7802SBaban Kenkre nssad_cfg_destroy(lru); 3702b4a7802SBaban Kenkre break; 3712b4a7802SBaban Kenkre } 3722b4a7802SBaban Kenkre (void) assert(prev != NULL); 3732b4a7802SBaban Kenkre } 3742b4a7802SBaban Kenkre } 3752b4a7802SBaban Kenkre 3762b4a7802SBaban Kenkre (void) pthread_rwlock_rdlock(&cp->lock); 3772b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&statelock); 3782b4a7802SBaban Kenkre return (cp); 3792b4a7802SBaban Kenkre } 3802b4a7802SBaban Kenkre 3812b4a7802SBaban Kenkre 3822b4a7802SBaban Kenkre /* ARGSUSED */ 3832b4a7802SBaban Kenkre static 3842b4a7802SBaban Kenkre nss_status_t 3852b4a7802SBaban Kenkre ad_lookup(const char *filter, const char **attrs, 3862b4a7802SBaban Kenkre const char *domain, adutils_result_t **result) 3872b4a7802SBaban Kenkre { 3882b4a7802SBaban Kenkre int retries = 0; 3892b4a7802SBaban Kenkre adutils_rc rc, brc; 3902b4a7802SBaban Kenkre adutils_query_state_t *qs; 3912b4a7802SBaban Kenkre nssad_cfg_t *cp; 3922b4a7802SBaban Kenkre 3932b4a7802SBaban Kenkre retry: 3942b4a7802SBaban Kenkre if ((cp = get_cfg(domain)) == NULL) 3952b4a7802SBaban Kenkre return ((nss_status_t)NSS_NOTFOUND); 3962b4a7802SBaban Kenkre 3972b4a7802SBaban Kenkre rc = adutils_lookup_batch_start(cp->ad, 1, NULL, NULL, &qs); 3982b4a7802SBaban Kenkre (void) pthread_rwlock_unlock(&cp->lock); 3992b4a7802SBaban Kenkre if (rc != ADUTILS_SUCCESS) 4002b4a7802SBaban Kenkre goto out; 4012b4a7802SBaban Kenkre 4022b4a7802SBaban Kenkre rc = adutils_lookup_batch_add(qs, filter, attrs, domain, result, &brc); 4032b4a7802SBaban Kenkre if (rc != ADUTILS_SUCCESS) { 4042b4a7802SBaban Kenkre adutils_lookup_batch_release(&qs); 4052b4a7802SBaban Kenkre goto out; 4062b4a7802SBaban Kenkre } 4072b4a7802SBaban Kenkre 4082b4a7802SBaban Kenkre rc = adutils_lookup_batch_end(&qs); 4092b4a7802SBaban Kenkre if (rc != ADUTILS_SUCCESS) 4102b4a7802SBaban Kenkre goto out; 4112b4a7802SBaban Kenkre rc = brc; 4122b4a7802SBaban Kenkre 4132b4a7802SBaban Kenkre out: 4142b4a7802SBaban Kenkre if (rc == ADUTILS_ERR_RETRIABLE_NET_ERR && 4152b4a7802SBaban Kenkre retries++ < ADUTILS_DEF_NUM_RETRIES) 4162b4a7802SBaban Kenkre goto retry; 4172b4a7802SBaban Kenkre return (map_adrc2nssrc(rc)); 4182b4a7802SBaban Kenkre } 4192b4a7802SBaban Kenkre 4202b4a7802SBaban Kenkre 4212b4a7802SBaban Kenkre /* ARGSUSED */ 4222b4a7802SBaban Kenkre nss_status_t 4232b4a7802SBaban Kenkre _nss_ad_lookup(ad_backend_ptr be, nss_XbyY_args_t *argp, 4242b4a7802SBaban Kenkre const char *database, const char *searchfilter, 4252b4a7802SBaban Kenkre const char *dname, int *try_idmap) 4262b4a7802SBaban Kenkre { 4272b4a7802SBaban Kenkre nss_status_t stat; 4282b4a7802SBaban Kenkre 4292b4a7802SBaban Kenkre *try_idmap = 0; 4302b4a7802SBaban Kenkre 4312b4a7802SBaban Kenkre /* Clear up results if any */ 4322b4a7802SBaban Kenkre (void) adutils_freeresult(&be->result); 4332b4a7802SBaban Kenkre 4342b4a7802SBaban Kenkre /* Lookup AD */ 4352b4a7802SBaban Kenkre stat = ad_lookup(searchfilter, be->attrs, dname, &be->result); 4362b4a7802SBaban Kenkre if (stat != NSS_SUCCESS) { 4372b4a7802SBaban Kenkre argp->returnval = 0; 4382b4a7802SBaban Kenkre *try_idmap = 1; 4392b4a7802SBaban Kenkre return (stat); 4402b4a7802SBaban Kenkre } 4412b4a7802SBaban Kenkre 4422b4a7802SBaban Kenkre /* Map AD object(s) to string in native file format */ 4432b4a7802SBaban Kenkre stat = be->adobj2str(be, argp); 4442b4a7802SBaban Kenkre if (stat == NSS_STR_PARSE_SUCCESS) 4452b4a7802SBaban Kenkre stat = _nss_ad_marshall_data(be, argp); 4462b4a7802SBaban Kenkre return (_nss_ad_sanitize_status(be, argp, stat)); 4472b4a7802SBaban Kenkre } 4482b4a7802SBaban Kenkre 4492b4a7802SBaban Kenkre static 4502b4a7802SBaban Kenkre void 4512b4a7802SBaban Kenkre clean_state() 4522b4a7802SBaban Kenkre { 4532b4a7802SBaban Kenkre nssad_cfg_t *cp, *curr; 4542b4a7802SBaban Kenkre 4552b4a7802SBaban Kenkre (void) pthread_mutex_lock(&statelock); 4562b4a7802SBaban Kenkre for (cp = state.qtail; cp != NULL; ) { 4572b4a7802SBaban Kenkre curr = cp; 4582b4a7802SBaban Kenkre cp = cp->qnext; 4592b4a7802SBaban Kenkre nssad_cfg_destroy(curr); 4602b4a7802SBaban Kenkre } 4612b4a7802SBaban Kenkre (void) memset(&state, 0, sizeof (state)); 4622b4a7802SBaban Kenkre (void) pthread_mutex_unlock(&statelock); 4632b4a7802SBaban Kenkre } 4642b4a7802SBaban Kenkre 4652b4a7802SBaban Kenkre static 4662b4a7802SBaban Kenkre void 4672b4a7802SBaban Kenkre _clean_ad_backend(ad_backend_ptr be) 4682b4a7802SBaban Kenkre { 4692b4a7802SBaban Kenkre if (be->tablename != NULL) 4702b4a7802SBaban Kenkre free(be->tablename); 4712b4a7802SBaban Kenkre if (be->buffer != NULL) { 4722b4a7802SBaban Kenkre free(be->buffer); 4732b4a7802SBaban Kenkre be->buffer = NULL; 4742b4a7802SBaban Kenkre } 4752b4a7802SBaban Kenkre free(be); 4762b4a7802SBaban Kenkre } 4772b4a7802SBaban Kenkre 4782b4a7802SBaban Kenkre 4792b4a7802SBaban Kenkre /* 4802b4a7802SBaban Kenkre * _nss_ad_destr frees allocated memory before exiting this nsswitch shared 4812b4a7802SBaban Kenkre * backend library. This function is called before returning control back to 4822b4a7802SBaban Kenkre * nsswitch. 4832b4a7802SBaban Kenkre */ 4842b4a7802SBaban Kenkre /*ARGSUSED*/ 4852b4a7802SBaban Kenkre nss_status_t 4862b4a7802SBaban Kenkre _nss_ad_destr(ad_backend_ptr be, void *a) 4872b4a7802SBaban Kenkre { 4882b4a7802SBaban Kenkre (void) _clean_ad_backend(be); 4892b4a7802SBaban Kenkre clean_state(); 4902b4a7802SBaban Kenkre return ((nss_status_t)NSS_SUCCESS); 4912b4a7802SBaban Kenkre } 4922b4a7802SBaban Kenkre 4932b4a7802SBaban Kenkre 4942b4a7802SBaban Kenkre /*ARGSUSED*/ 4952b4a7802SBaban Kenkre nss_status_t 4962b4a7802SBaban Kenkre _nss_ad_setent(ad_backend_ptr be, void *a) 4972b4a7802SBaban Kenkre { 4982b4a7802SBaban Kenkre return ((nss_status_t)NSS_UNAVAIL); 4992b4a7802SBaban Kenkre } 5002b4a7802SBaban Kenkre 5012b4a7802SBaban Kenkre 5022b4a7802SBaban Kenkre /*ARGSUSED*/ 5032b4a7802SBaban Kenkre nss_status_t 5042b4a7802SBaban Kenkre _nss_ad_endent(ad_backend_ptr be, void *a) 5052b4a7802SBaban Kenkre { 5062b4a7802SBaban Kenkre return ((nss_status_t)NSS_UNAVAIL); 5072b4a7802SBaban Kenkre } 5082b4a7802SBaban Kenkre 5092b4a7802SBaban Kenkre 5102b4a7802SBaban Kenkre /*ARGSUSED*/ 5112b4a7802SBaban Kenkre nss_status_t 5122b4a7802SBaban Kenkre _nss_ad_getent(ad_backend_ptr be, void *a) 5132b4a7802SBaban Kenkre { 5142b4a7802SBaban Kenkre return ((nss_status_t)NSS_UNAVAIL); 5152b4a7802SBaban Kenkre } 5162b4a7802SBaban Kenkre 5172b4a7802SBaban Kenkre 5182b4a7802SBaban Kenkre nss_backend_t * 5192b4a7802SBaban Kenkre _nss_ad_constr(ad_backend_op_t ops[], int nops, char *tablename, 5202b4a7802SBaban Kenkre const char **attrs, fnf adobj2str) 5212b4a7802SBaban Kenkre { 5222b4a7802SBaban Kenkre ad_backend_ptr be; 5232b4a7802SBaban Kenkre 5242b4a7802SBaban Kenkre if ((be = (ad_backend_ptr) calloc(1, sizeof (*be))) == NULL) 5252b4a7802SBaban Kenkre return (NULL); 5262b4a7802SBaban Kenkre if ((be->tablename = (char *)strdup(tablename)) == NULL) { 5272b4a7802SBaban Kenkre free(be); 5282b4a7802SBaban Kenkre return (NULL); 5292b4a7802SBaban Kenkre } 5302b4a7802SBaban Kenkre be->ops = ops; 5312b4a7802SBaban Kenkre be->nops = (nss_dbop_t)nops; 5322b4a7802SBaban Kenkre be->attrs = attrs; 5332b4a7802SBaban Kenkre be->adobj2str = adobj2str; 5342b4a7802SBaban Kenkre (void) memset(&state, 0, sizeof (state)); 5352b4a7802SBaban Kenkre return ((nss_backend_t *)be); 5362b4a7802SBaban Kenkre } 537