1*8040SBaban.Kenkre@Sun.COM /* 2*8040SBaban.Kenkre@Sun.COM * CDDL HEADER START 3*8040SBaban.Kenkre@Sun.COM * 4*8040SBaban.Kenkre@Sun.COM * The contents of this file are subject to the terms of the 5*8040SBaban.Kenkre@Sun.COM * Common Development and Distribution License (the "License"). 6*8040SBaban.Kenkre@Sun.COM * You may not use this file except in compliance with the License. 7*8040SBaban.Kenkre@Sun.COM * 8*8040SBaban.Kenkre@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*8040SBaban.Kenkre@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*8040SBaban.Kenkre@Sun.COM * See the License for the specific language governing permissions 11*8040SBaban.Kenkre@Sun.COM * and limitations under the License. 12*8040SBaban.Kenkre@Sun.COM * 13*8040SBaban.Kenkre@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*8040SBaban.Kenkre@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*8040SBaban.Kenkre@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*8040SBaban.Kenkre@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*8040SBaban.Kenkre@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*8040SBaban.Kenkre@Sun.COM * 19*8040SBaban.Kenkre@Sun.COM * CDDL HEADER END 20*8040SBaban.Kenkre@Sun.COM */ 21*8040SBaban.Kenkre@Sun.COM /* 22*8040SBaban.Kenkre@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*8040SBaban.Kenkre@Sun.COM * Use is subject to license terms. 24*8040SBaban.Kenkre@Sun.COM */ 25*8040SBaban.Kenkre@Sun.COM 26*8040SBaban.Kenkre@Sun.COM #include <malloc.h> 27*8040SBaban.Kenkre@Sun.COM #include <synch.h> 28*8040SBaban.Kenkre@Sun.COM #include <syslog.h> 29*8040SBaban.Kenkre@Sun.COM #include <rpcsvc/ypclnt.h> 30*8040SBaban.Kenkre@Sun.COM #include <rpcsvc/yp_prot.h> 31*8040SBaban.Kenkre@Sun.COM #include <pthread.h> 32*8040SBaban.Kenkre@Sun.COM #include <ctype.h> 33*8040SBaban.Kenkre@Sun.COM #include <stdlib.h> 34*8040SBaban.Kenkre@Sun.COM #include <stdio.h> 35*8040SBaban.Kenkre@Sun.COM #include <signal.h> 36*8040SBaban.Kenkre@Sun.COM #include <sys/stat.h> 37*8040SBaban.Kenkre@Sun.COM #include <assert.h> 38*8040SBaban.Kenkre@Sun.COM #include "ad_common.h" 39*8040SBaban.Kenkre@Sun.COM 40*8040SBaban.Kenkre@Sun.COM static pthread_mutex_t statelock = PTHREAD_MUTEX_INITIALIZER; 41*8040SBaban.Kenkre@Sun.COM static nssad_state_t state = {0}; 42*8040SBaban.Kenkre@Sun.COM 43*8040SBaban.Kenkre@Sun.COM static void 44*8040SBaban.Kenkre@Sun.COM nssad_cfg_free_props(nssad_prop_t *props) 45*8040SBaban.Kenkre@Sun.COM { 46*8040SBaban.Kenkre@Sun.COM if (props->domain_name != NULL) { 47*8040SBaban.Kenkre@Sun.COM free(props->domain_name); 48*8040SBaban.Kenkre@Sun.COM props->domain_name = NULL; 49*8040SBaban.Kenkre@Sun.COM } 50*8040SBaban.Kenkre@Sun.COM if (props->domain_controller != NULL) { 51*8040SBaban.Kenkre@Sun.COM free(props->domain_controller); 52*8040SBaban.Kenkre@Sun.COM props->domain_controller = NULL; 53*8040SBaban.Kenkre@Sun.COM } 54*8040SBaban.Kenkre@Sun.COM } 55*8040SBaban.Kenkre@Sun.COM 56*8040SBaban.Kenkre@Sun.COM static int 57*8040SBaban.Kenkre@Sun.COM nssad_cfg_discover_props(const char *domain, ad_disc_t ad_ctx, 58*8040SBaban.Kenkre@Sun.COM nssad_prop_t *props) 59*8040SBaban.Kenkre@Sun.COM { 60*8040SBaban.Kenkre@Sun.COM ad_disc_refresh(ad_ctx); 61*8040SBaban.Kenkre@Sun.COM if (ad_disc_set_DomainName(ad_ctx, domain) != 0) 62*8040SBaban.Kenkre@Sun.COM return (-1); 63*8040SBaban.Kenkre@Sun.COM if (props->domain_controller == NULL) 64*8040SBaban.Kenkre@Sun.COM props->domain_controller = 65*8040SBaban.Kenkre@Sun.COM ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE); 66*8040SBaban.Kenkre@Sun.COM return (0); 67*8040SBaban.Kenkre@Sun.COM } 68*8040SBaban.Kenkre@Sun.COM 69*8040SBaban.Kenkre@Sun.COM static int 70*8040SBaban.Kenkre@Sun.COM nssad_cfg_reload_ad(nssad_prop_t *props, adutils_ad_t **ad) 71*8040SBaban.Kenkre@Sun.COM { 72*8040SBaban.Kenkre@Sun.COM int i; 73*8040SBaban.Kenkre@Sun.COM adutils_ad_t *new; 74*8040SBaban.Kenkre@Sun.COM 75*8040SBaban.Kenkre@Sun.COM if (props->domain_controller == NULL || 76*8040SBaban.Kenkre@Sun.COM props->domain_controller[0].host[0] == '\0') 77*8040SBaban.Kenkre@Sun.COM return (0); 78*8040SBaban.Kenkre@Sun.COM if (adutils_ad_alloc(&new, props->domain_name, 79*8040SBaban.Kenkre@Sun.COM ADUTILS_AD_DATA) != ADUTILS_SUCCESS) 80*8040SBaban.Kenkre@Sun.COM return (-1); 81*8040SBaban.Kenkre@Sun.COM for (i = 0; props->domain_controller[i].host[0] != '\0'; i++) { 82*8040SBaban.Kenkre@Sun.COM if (adutils_add_ds(new, 83*8040SBaban.Kenkre@Sun.COM props->domain_controller[i].host, 84*8040SBaban.Kenkre@Sun.COM props->domain_controller[i].port) != ADUTILS_SUCCESS) { 85*8040SBaban.Kenkre@Sun.COM adutils_ad_free(&new); 86*8040SBaban.Kenkre@Sun.COM return (-1); 87*8040SBaban.Kenkre@Sun.COM } 88*8040SBaban.Kenkre@Sun.COM } 89*8040SBaban.Kenkre@Sun.COM 90*8040SBaban.Kenkre@Sun.COM if (*ad != NULL) 91*8040SBaban.Kenkre@Sun.COM adutils_ad_free(ad); 92*8040SBaban.Kenkre@Sun.COM *ad = new; 93*8040SBaban.Kenkre@Sun.COM return (0); 94*8040SBaban.Kenkre@Sun.COM } 95*8040SBaban.Kenkre@Sun.COM 96*8040SBaban.Kenkre@Sun.COM static 97*8040SBaban.Kenkre@Sun.COM int 98*8040SBaban.Kenkre@Sun.COM update_dirs(idmap_ad_disc_ds_t **value, idmap_ad_disc_ds_t **new) 99*8040SBaban.Kenkre@Sun.COM { 100*8040SBaban.Kenkre@Sun.COM if (*value == *new) 101*8040SBaban.Kenkre@Sun.COM return (0); 102*8040SBaban.Kenkre@Sun.COM 103*8040SBaban.Kenkre@Sun.COM if (*value != NULL && *new != NULL && 104*8040SBaban.Kenkre@Sun.COM ad_disc_compare_ds(*value, *new) == 0) { 105*8040SBaban.Kenkre@Sun.COM free(*new); 106*8040SBaban.Kenkre@Sun.COM *new = NULL; 107*8040SBaban.Kenkre@Sun.COM return (0); 108*8040SBaban.Kenkre@Sun.COM } 109*8040SBaban.Kenkre@Sun.COM 110*8040SBaban.Kenkre@Sun.COM if (*value) 111*8040SBaban.Kenkre@Sun.COM free(*value); 112*8040SBaban.Kenkre@Sun.COM *value = *new; 113*8040SBaban.Kenkre@Sun.COM *new = NULL; 114*8040SBaban.Kenkre@Sun.COM return (1); 115*8040SBaban.Kenkre@Sun.COM } 116*8040SBaban.Kenkre@Sun.COM 117*8040SBaban.Kenkre@Sun.COM static 118*8040SBaban.Kenkre@Sun.COM int 119*8040SBaban.Kenkre@Sun.COM nssad_cfg_refresh(nssad_cfg_t *cp) 120*8040SBaban.Kenkre@Sun.COM { 121*8040SBaban.Kenkre@Sun.COM nssad_prop_t props; 122*8040SBaban.Kenkre@Sun.COM 123*8040SBaban.Kenkre@Sun.COM (void) ad_disc_SubnetChanged(cp->ad_ctx); 124*8040SBaban.Kenkre@Sun.COM (void) memset(&props, 0, sizeof (props)); 125*8040SBaban.Kenkre@Sun.COM if (nssad_cfg_discover_props(cp->props.domain_name, cp->ad_ctx, 126*8040SBaban.Kenkre@Sun.COM &props) < 0) 127*8040SBaban.Kenkre@Sun.COM return (-1); 128*8040SBaban.Kenkre@Sun.COM if (update_dirs(&cp->props.domain_controller, 129*8040SBaban.Kenkre@Sun.COM &props.domain_controller)) { 130*8040SBaban.Kenkre@Sun.COM if (cp->props.domain_controller != NULL && 131*8040SBaban.Kenkre@Sun.COM cp->props.domain_controller[0].host[0] != '\0') 132*8040SBaban.Kenkre@Sun.COM (void) nssad_cfg_reload_ad(&cp->props, &cp->ad); 133*8040SBaban.Kenkre@Sun.COM } 134*8040SBaban.Kenkre@Sun.COM return (0); 135*8040SBaban.Kenkre@Sun.COM } 136*8040SBaban.Kenkre@Sun.COM 137*8040SBaban.Kenkre@Sun.COM static void 138*8040SBaban.Kenkre@Sun.COM nssad_cfg_destroy(nssad_cfg_t *cp) 139*8040SBaban.Kenkre@Sun.COM { 140*8040SBaban.Kenkre@Sun.COM if (cp != NULL) { 141*8040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_destroy(&cp->lock); 142*8040SBaban.Kenkre@Sun.COM ad_disc_fini(cp->ad_ctx); 143*8040SBaban.Kenkre@Sun.COM nssad_cfg_free_props(&cp->props); 144*8040SBaban.Kenkre@Sun.COM adutils_ad_free(&cp->ad); 145*8040SBaban.Kenkre@Sun.COM free(cp); 146*8040SBaban.Kenkre@Sun.COM } 147*8040SBaban.Kenkre@Sun.COM } 148*8040SBaban.Kenkre@Sun.COM 149*8040SBaban.Kenkre@Sun.COM static nssad_cfg_t * 150*8040SBaban.Kenkre@Sun.COM nssad_cfg_create(const char *domain) 151*8040SBaban.Kenkre@Sun.COM { 152*8040SBaban.Kenkre@Sun.COM nssad_cfg_t *cp; 153*8040SBaban.Kenkre@Sun.COM 154*8040SBaban.Kenkre@Sun.COM if ((cp = calloc(1, sizeof (*cp))) == NULL) 155*8040SBaban.Kenkre@Sun.COM return (NULL); 156*8040SBaban.Kenkre@Sun.COM if (pthread_rwlock_init(&cp->lock, NULL) != 0) { 157*8040SBaban.Kenkre@Sun.COM free(cp); 158*8040SBaban.Kenkre@Sun.COM return (NULL); 159*8040SBaban.Kenkre@Sun.COM } 160*8040SBaban.Kenkre@Sun.COM adutils_set_log(-1, TRUE, FALSE); 161*8040SBaban.Kenkre@Sun.COM if ((cp->ad_ctx = ad_disc_init()) == NULL) 162*8040SBaban.Kenkre@Sun.COM goto errout; 163*8040SBaban.Kenkre@Sun.COM if ((cp->props.domain_name = strdup(domain)) == NULL) 164*8040SBaban.Kenkre@Sun.COM goto errout; 165*8040SBaban.Kenkre@Sun.COM if (nssad_cfg_discover_props(domain, cp->ad_ctx, &cp->props) < 0) 166*8040SBaban.Kenkre@Sun.COM goto errout; 167*8040SBaban.Kenkre@Sun.COM if (nssad_cfg_reload_ad(&cp->props, &cp->ad) < 0) 168*8040SBaban.Kenkre@Sun.COM goto errout; 169*8040SBaban.Kenkre@Sun.COM return (cp); 170*8040SBaban.Kenkre@Sun.COM errout: 171*8040SBaban.Kenkre@Sun.COM nssad_cfg_destroy(cp); 172*8040SBaban.Kenkre@Sun.COM return (NULL); 173*8040SBaban.Kenkre@Sun.COM } 174*8040SBaban.Kenkre@Sun.COM 175*8040SBaban.Kenkre@Sun.COM #define hex_char(n) "0123456789abcdef"[n & 0xf] 176*8040SBaban.Kenkre@Sun.COM 177*8040SBaban.Kenkre@Sun.COM int 178*8040SBaban.Kenkre@Sun.COM _ldap_filter_name(char *filter_name, const char *name, int filter_name_size) 179*8040SBaban.Kenkre@Sun.COM { 180*8040SBaban.Kenkre@Sun.COM char *end = filter_name + filter_name_size; 181*8040SBaban.Kenkre@Sun.COM char c; 182*8040SBaban.Kenkre@Sun.COM 183*8040SBaban.Kenkre@Sun.COM for (; *name; name++) { 184*8040SBaban.Kenkre@Sun.COM c = *name; 185*8040SBaban.Kenkre@Sun.COM switch (c) { 186*8040SBaban.Kenkre@Sun.COM case '*': 187*8040SBaban.Kenkre@Sun.COM case '(': 188*8040SBaban.Kenkre@Sun.COM case ')': 189*8040SBaban.Kenkre@Sun.COM case '\\': 190*8040SBaban.Kenkre@Sun.COM if (end <= filter_name + 3) 191*8040SBaban.Kenkre@Sun.COM return (-1); 192*8040SBaban.Kenkre@Sun.COM *filter_name++ = '\\'; 193*8040SBaban.Kenkre@Sun.COM *filter_name++ = hex_char(c >> 4); 194*8040SBaban.Kenkre@Sun.COM *filter_name++ = hex_char(c & 0xf); 195*8040SBaban.Kenkre@Sun.COM break; 196*8040SBaban.Kenkre@Sun.COM default: 197*8040SBaban.Kenkre@Sun.COM if (end <= filter_name + 1) 198*8040SBaban.Kenkre@Sun.COM return (-1); 199*8040SBaban.Kenkre@Sun.COM *filter_name++ = c; 200*8040SBaban.Kenkre@Sun.COM break; 201*8040SBaban.Kenkre@Sun.COM } 202*8040SBaban.Kenkre@Sun.COM } 203*8040SBaban.Kenkre@Sun.COM if (end <= filter_name) 204*8040SBaban.Kenkre@Sun.COM return (-1); 205*8040SBaban.Kenkre@Sun.COM *filter_name = '\0'; 206*8040SBaban.Kenkre@Sun.COM return (0); 207*8040SBaban.Kenkre@Sun.COM } 208*8040SBaban.Kenkre@Sun.COM 209*8040SBaban.Kenkre@Sun.COM static 210*8040SBaban.Kenkre@Sun.COM nss_status_t 211*8040SBaban.Kenkre@Sun.COM map_adrc2nssrc(adutils_rc adrc) 212*8040SBaban.Kenkre@Sun.COM { 213*8040SBaban.Kenkre@Sun.COM if (adrc == ADUTILS_SUCCESS) 214*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_SUCCESS); 215*8040SBaban.Kenkre@Sun.COM if (adrc == ADUTILS_ERR_NOTFOUND) 216*8040SBaban.Kenkre@Sun.COM errno = 0; 217*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND); 218*8040SBaban.Kenkre@Sun.COM } 219*8040SBaban.Kenkre@Sun.COM 220*8040SBaban.Kenkre@Sun.COM /* ARGSUSED */ 221*8040SBaban.Kenkre@Sun.COM nss_status_t 222*8040SBaban.Kenkre@Sun.COM _nss_ad_marshall_data(ad_backend_ptr be, nss_XbyY_args_t *argp) 223*8040SBaban.Kenkre@Sun.COM { 224*8040SBaban.Kenkre@Sun.COM int stat; 225*8040SBaban.Kenkre@Sun.COM 226*8040SBaban.Kenkre@Sun.COM if (argp->buf.result == NULL) { 227*8040SBaban.Kenkre@Sun.COM /* 228*8040SBaban.Kenkre@Sun.COM * This suggests that the process (e.g. nscd) expects 229*8040SBaban.Kenkre@Sun.COM * nssad to return the data in native file format in 230*8040SBaban.Kenkre@Sun.COM * argp->buf.buffer i.e. no need to marshall the data. 231*8040SBaban.Kenkre@Sun.COM */ 232*8040SBaban.Kenkre@Sun.COM argp->returnval = argp->buf.buffer; 233*8040SBaban.Kenkre@Sun.COM argp->returnlen = strlen(argp->buf.buffer); 234*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_STR_PARSE_SUCCESS); 235*8040SBaban.Kenkre@Sun.COM } 236*8040SBaban.Kenkre@Sun.COM 237*8040SBaban.Kenkre@Sun.COM if (argp->str2ent == NULL) 238*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_STR_PARSE_PARSE); 239*8040SBaban.Kenkre@Sun.COM 240*8040SBaban.Kenkre@Sun.COM stat = (*argp->str2ent)(be->buffer, be->buflen, 241*8040SBaban.Kenkre@Sun.COM argp->buf.result, argp->buf.buffer, argp->buf.buflen); 242*8040SBaban.Kenkre@Sun.COM 243*8040SBaban.Kenkre@Sun.COM if (stat == NSS_STR_PARSE_SUCCESS) { 244*8040SBaban.Kenkre@Sun.COM argp->returnval = argp->buf.result; 245*8040SBaban.Kenkre@Sun.COM argp->returnlen = 1; /* irrelevant */ 246*8040SBaban.Kenkre@Sun.COM } 247*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)stat); 248*8040SBaban.Kenkre@Sun.COM } 249*8040SBaban.Kenkre@Sun.COM 250*8040SBaban.Kenkre@Sun.COM nss_status_t 251*8040SBaban.Kenkre@Sun.COM _nss_ad_sanitize_status(ad_backend_ptr be, nss_XbyY_args_t *argp, 252*8040SBaban.Kenkre@Sun.COM nss_status_t stat) 253*8040SBaban.Kenkre@Sun.COM { 254*8040SBaban.Kenkre@Sun.COM if (be->buffer != NULL) { 255*8040SBaban.Kenkre@Sun.COM free(be->buffer); 256*8040SBaban.Kenkre@Sun.COM be->buffer = NULL; 257*8040SBaban.Kenkre@Sun.COM be->buflen = 0; 258*8040SBaban.Kenkre@Sun.COM be->db_type = NSS_AD_DB_NONE; 259*8040SBaban.Kenkre@Sun.COM } 260*8040SBaban.Kenkre@Sun.COM 261*8040SBaban.Kenkre@Sun.COM if (stat == NSS_STR_PARSE_SUCCESS) { 262*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_SUCCESS); 263*8040SBaban.Kenkre@Sun.COM } else if (stat == NSS_STR_PARSE_PARSE) { 264*8040SBaban.Kenkre@Sun.COM argp->returnval = 0; 265*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND); 266*8040SBaban.Kenkre@Sun.COM } else if (stat == NSS_STR_PARSE_ERANGE) { 267*8040SBaban.Kenkre@Sun.COM argp->erange = 1; 268*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND); 269*8040SBaban.Kenkre@Sun.COM } 270*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_UNAVAIL); 271*8040SBaban.Kenkre@Sun.COM } 272*8040SBaban.Kenkre@Sun.COM 273*8040SBaban.Kenkre@Sun.COM /* ARGSUSED */ 274*8040SBaban.Kenkre@Sun.COM static 275*8040SBaban.Kenkre@Sun.COM nssad_cfg_t * 276*8040SBaban.Kenkre@Sun.COM get_cfg(const char *domain) 277*8040SBaban.Kenkre@Sun.COM { 278*8040SBaban.Kenkre@Sun.COM nssad_cfg_t *cp, *lru, *prev; 279*8040SBaban.Kenkre@Sun.COM 280*8040SBaban.Kenkre@Sun.COM /* 281*8040SBaban.Kenkre@Sun.COM * Note about the queue: 282*8040SBaban.Kenkre@Sun.COM * 283*8040SBaban.Kenkre@Sun.COM * The queue is used to hold our per domain 284*8040SBaban.Kenkre@Sun.COM * configs. The queue is limited to CFG_QUEUE_MAX_SIZE. 285*8040SBaban.Kenkre@Sun.COM * If the queue increases beyond that point we toss 286*8040SBaban.Kenkre@Sun.COM * out the LRU entry. The entries are inserted into 287*8040SBaban.Kenkre@Sun.COM * the queue at state.qtail and the LRU entry is 288*8040SBaban.Kenkre@Sun.COM * removed from state.qhead. state.qnext points 289*8040SBaban.Kenkre@Sun.COM * from the qtail to the qhead. Everytime a config 290*8040SBaban.Kenkre@Sun.COM * is accessed it is moved to qtail. 291*8040SBaban.Kenkre@Sun.COM */ 292*8040SBaban.Kenkre@Sun.COM 293*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&statelock); 294*8040SBaban.Kenkre@Sun.COM 295*8040SBaban.Kenkre@Sun.COM for (cp = state.qtail, prev = NULL; cp != NULL; 296*8040SBaban.Kenkre@Sun.COM prev = cp, cp = cp->qnext) { 297*8040SBaban.Kenkre@Sun.COM if (cp->props.domain_name == NULL || 298*8040SBaban.Kenkre@Sun.COM strcasecmp(cp->props.domain_name, domain) != 0) 299*8040SBaban.Kenkre@Sun.COM continue; 300*8040SBaban.Kenkre@Sun.COM 301*8040SBaban.Kenkre@Sun.COM /* Found config for the given domain. */ 302*8040SBaban.Kenkre@Sun.COM 303*8040SBaban.Kenkre@Sun.COM if (state.qtail != cp) { 304*8040SBaban.Kenkre@Sun.COM /* 305*8040SBaban.Kenkre@Sun.COM * Move the entry to the tail of the queue. 306*8040SBaban.Kenkre@Sun.COM * This way the LRU entry can be found at 307*8040SBaban.Kenkre@Sun.COM * the head of the queue. 308*8040SBaban.Kenkre@Sun.COM */ 309*8040SBaban.Kenkre@Sun.COM prev->qnext = cp->qnext; 310*8040SBaban.Kenkre@Sun.COM if (state.qhead == cp) 311*8040SBaban.Kenkre@Sun.COM state.qhead = prev; 312*8040SBaban.Kenkre@Sun.COM cp->qnext = state.qtail; 313*8040SBaban.Kenkre@Sun.COM state.qtail = cp; 314*8040SBaban.Kenkre@Sun.COM } 315*8040SBaban.Kenkre@Sun.COM 316*8040SBaban.Kenkre@Sun.COM if (ad_disc_get_TTL(cp->ad_ctx) == 0) { 317*8040SBaban.Kenkre@Sun.COM /* 318*8040SBaban.Kenkre@Sun.COM * If there are expired items in the 319*8040SBaban.Kenkre@Sun.COM * config, grab the write lock and 320*8040SBaban.Kenkre@Sun.COM * refresh the config. 321*8040SBaban.Kenkre@Sun.COM */ 322*8040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_wrlock(&cp->lock); 323*8040SBaban.Kenkre@Sun.COM if (nssad_cfg_refresh(cp) < 0) { 324*8040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_unlock(&cp->lock); 325*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&statelock); 326*8040SBaban.Kenkre@Sun.COM return (NULL); 327*8040SBaban.Kenkre@Sun.COM } 328*8040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_unlock(&cp->lock); 329*8040SBaban.Kenkre@Sun.COM } 330*8040SBaban.Kenkre@Sun.COM 331*8040SBaban.Kenkre@Sun.COM /* Return the config found */ 332*8040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_rdlock(&cp->lock); 333*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&statelock); 334*8040SBaban.Kenkre@Sun.COM return (cp); 335*8040SBaban.Kenkre@Sun.COM } 336*8040SBaban.Kenkre@Sun.COM 337*8040SBaban.Kenkre@Sun.COM /* Create new config entry for the domain */ 338*8040SBaban.Kenkre@Sun.COM if ((cp = nssad_cfg_create(domain)) == NULL) { 339*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&statelock); 340*8040SBaban.Kenkre@Sun.COM return (NULL); 341*8040SBaban.Kenkre@Sun.COM } 342*8040SBaban.Kenkre@Sun.COM 343*8040SBaban.Kenkre@Sun.COM /* Add it to the queue */ 344*8040SBaban.Kenkre@Sun.COM state.qcount++; 345*8040SBaban.Kenkre@Sun.COM if (state.qtail == NULL) { 346*8040SBaban.Kenkre@Sun.COM state.qtail = state.qhead = cp; 347*8040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_rdlock(&cp->lock); 348*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&statelock); 349*8040SBaban.Kenkre@Sun.COM return (cp); 350*8040SBaban.Kenkre@Sun.COM } 351*8040SBaban.Kenkre@Sun.COM cp->qnext = state.qtail; 352*8040SBaban.Kenkre@Sun.COM state.qtail = cp; 353*8040SBaban.Kenkre@Sun.COM 354*8040SBaban.Kenkre@Sun.COM /* If the queue has exceeded its size, remove the LRU entry */ 355*8040SBaban.Kenkre@Sun.COM if (state.qcount >= CFG_QUEUE_MAX_SIZE) { 356*8040SBaban.Kenkre@Sun.COM /* Detach the lru entry and destroy */ 357*8040SBaban.Kenkre@Sun.COM lru = state.qhead; 358*8040SBaban.Kenkre@Sun.COM if (pthread_rwlock_trywrlock(&lru->lock) == 0) { 359*8040SBaban.Kenkre@Sun.COM for (prev = state.qtail; prev != NULL; 360*8040SBaban.Kenkre@Sun.COM prev = prev->qnext) { 361*8040SBaban.Kenkre@Sun.COM if (prev->qnext != lru) 362*8040SBaban.Kenkre@Sun.COM continue; 363*8040SBaban.Kenkre@Sun.COM state.qhead = prev; 364*8040SBaban.Kenkre@Sun.COM prev->qnext = NULL; 365*8040SBaban.Kenkre@Sun.COM state.qcount--; 366*8040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_unlock(&lru->lock); 367*8040SBaban.Kenkre@Sun.COM nssad_cfg_destroy(lru); 368*8040SBaban.Kenkre@Sun.COM break; 369*8040SBaban.Kenkre@Sun.COM } 370*8040SBaban.Kenkre@Sun.COM (void) assert(prev != NULL); 371*8040SBaban.Kenkre@Sun.COM } 372*8040SBaban.Kenkre@Sun.COM } 373*8040SBaban.Kenkre@Sun.COM 374*8040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_rdlock(&cp->lock); 375*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&statelock); 376*8040SBaban.Kenkre@Sun.COM return (cp); 377*8040SBaban.Kenkre@Sun.COM } 378*8040SBaban.Kenkre@Sun.COM 379*8040SBaban.Kenkre@Sun.COM 380*8040SBaban.Kenkre@Sun.COM /* ARGSUSED */ 381*8040SBaban.Kenkre@Sun.COM static 382*8040SBaban.Kenkre@Sun.COM nss_status_t 383*8040SBaban.Kenkre@Sun.COM ad_lookup(const char *filter, const char **attrs, 384*8040SBaban.Kenkre@Sun.COM const char *domain, adutils_result_t **result) 385*8040SBaban.Kenkre@Sun.COM { 386*8040SBaban.Kenkre@Sun.COM int retries = 0; 387*8040SBaban.Kenkre@Sun.COM adutils_rc rc, brc; 388*8040SBaban.Kenkre@Sun.COM adutils_query_state_t *qs; 389*8040SBaban.Kenkre@Sun.COM nssad_cfg_t *cp; 390*8040SBaban.Kenkre@Sun.COM 391*8040SBaban.Kenkre@Sun.COM retry: 392*8040SBaban.Kenkre@Sun.COM if ((cp = get_cfg(domain)) == NULL) 393*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_NOTFOUND); 394*8040SBaban.Kenkre@Sun.COM 395*8040SBaban.Kenkre@Sun.COM rc = adutils_lookup_batch_start(cp->ad, 1, NULL, NULL, &qs); 396*8040SBaban.Kenkre@Sun.COM (void) pthread_rwlock_unlock(&cp->lock); 397*8040SBaban.Kenkre@Sun.COM if (rc != ADUTILS_SUCCESS) 398*8040SBaban.Kenkre@Sun.COM goto out; 399*8040SBaban.Kenkre@Sun.COM 400*8040SBaban.Kenkre@Sun.COM rc = adutils_lookup_batch_add(qs, filter, attrs, domain, result, &brc); 401*8040SBaban.Kenkre@Sun.COM if (rc != ADUTILS_SUCCESS) { 402*8040SBaban.Kenkre@Sun.COM adutils_lookup_batch_release(&qs); 403*8040SBaban.Kenkre@Sun.COM goto out; 404*8040SBaban.Kenkre@Sun.COM } 405*8040SBaban.Kenkre@Sun.COM 406*8040SBaban.Kenkre@Sun.COM rc = adutils_lookup_batch_end(&qs); 407*8040SBaban.Kenkre@Sun.COM if (rc != ADUTILS_SUCCESS) 408*8040SBaban.Kenkre@Sun.COM goto out; 409*8040SBaban.Kenkre@Sun.COM rc = brc; 410*8040SBaban.Kenkre@Sun.COM 411*8040SBaban.Kenkre@Sun.COM out: 412*8040SBaban.Kenkre@Sun.COM if (rc == ADUTILS_ERR_RETRIABLE_NET_ERR && 413*8040SBaban.Kenkre@Sun.COM retries++ < ADUTILS_DEF_NUM_RETRIES) 414*8040SBaban.Kenkre@Sun.COM goto retry; 415*8040SBaban.Kenkre@Sun.COM return (map_adrc2nssrc(rc)); 416*8040SBaban.Kenkre@Sun.COM } 417*8040SBaban.Kenkre@Sun.COM 418*8040SBaban.Kenkre@Sun.COM 419*8040SBaban.Kenkre@Sun.COM /* ARGSUSED */ 420*8040SBaban.Kenkre@Sun.COM nss_status_t 421*8040SBaban.Kenkre@Sun.COM _nss_ad_lookup(ad_backend_ptr be, nss_XbyY_args_t *argp, 422*8040SBaban.Kenkre@Sun.COM const char *database, const char *searchfilter, 423*8040SBaban.Kenkre@Sun.COM const char *dname, int *try_idmap) 424*8040SBaban.Kenkre@Sun.COM { 425*8040SBaban.Kenkre@Sun.COM nss_status_t stat; 426*8040SBaban.Kenkre@Sun.COM 427*8040SBaban.Kenkre@Sun.COM *try_idmap = 0; 428*8040SBaban.Kenkre@Sun.COM 429*8040SBaban.Kenkre@Sun.COM /* Clear up results if any */ 430*8040SBaban.Kenkre@Sun.COM (void) adutils_freeresult(&be->result); 431*8040SBaban.Kenkre@Sun.COM 432*8040SBaban.Kenkre@Sun.COM /* Lookup AD */ 433*8040SBaban.Kenkre@Sun.COM stat = ad_lookup(searchfilter, be->attrs, dname, &be->result); 434*8040SBaban.Kenkre@Sun.COM if (stat != NSS_SUCCESS) { 435*8040SBaban.Kenkre@Sun.COM argp->returnval = 0; 436*8040SBaban.Kenkre@Sun.COM *try_idmap = 1; 437*8040SBaban.Kenkre@Sun.COM return (stat); 438*8040SBaban.Kenkre@Sun.COM } 439*8040SBaban.Kenkre@Sun.COM 440*8040SBaban.Kenkre@Sun.COM /* Map AD object(s) to string in native file format */ 441*8040SBaban.Kenkre@Sun.COM stat = be->adobj2str(be, argp); 442*8040SBaban.Kenkre@Sun.COM if (stat == NSS_STR_PARSE_SUCCESS) 443*8040SBaban.Kenkre@Sun.COM stat = _nss_ad_marshall_data(be, argp); 444*8040SBaban.Kenkre@Sun.COM return (_nss_ad_sanitize_status(be, argp, stat)); 445*8040SBaban.Kenkre@Sun.COM } 446*8040SBaban.Kenkre@Sun.COM 447*8040SBaban.Kenkre@Sun.COM static 448*8040SBaban.Kenkre@Sun.COM void 449*8040SBaban.Kenkre@Sun.COM clean_state() 450*8040SBaban.Kenkre@Sun.COM { 451*8040SBaban.Kenkre@Sun.COM nssad_cfg_t *cp, *curr; 452*8040SBaban.Kenkre@Sun.COM 453*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_lock(&statelock); 454*8040SBaban.Kenkre@Sun.COM for (cp = state.qtail; cp != NULL; ) { 455*8040SBaban.Kenkre@Sun.COM curr = cp; 456*8040SBaban.Kenkre@Sun.COM cp = cp->qnext; 457*8040SBaban.Kenkre@Sun.COM nssad_cfg_destroy(curr); 458*8040SBaban.Kenkre@Sun.COM } 459*8040SBaban.Kenkre@Sun.COM (void) memset(&state, 0, sizeof (state)); 460*8040SBaban.Kenkre@Sun.COM (void) pthread_mutex_unlock(&statelock); 461*8040SBaban.Kenkre@Sun.COM } 462*8040SBaban.Kenkre@Sun.COM 463*8040SBaban.Kenkre@Sun.COM static 464*8040SBaban.Kenkre@Sun.COM void 465*8040SBaban.Kenkre@Sun.COM _clean_ad_backend(ad_backend_ptr be) 466*8040SBaban.Kenkre@Sun.COM { 467*8040SBaban.Kenkre@Sun.COM if (be->tablename != NULL) 468*8040SBaban.Kenkre@Sun.COM free(be->tablename); 469*8040SBaban.Kenkre@Sun.COM if (be->buffer != NULL) { 470*8040SBaban.Kenkre@Sun.COM free(be->buffer); 471*8040SBaban.Kenkre@Sun.COM be->buffer = NULL; 472*8040SBaban.Kenkre@Sun.COM } 473*8040SBaban.Kenkre@Sun.COM free(be); 474*8040SBaban.Kenkre@Sun.COM } 475*8040SBaban.Kenkre@Sun.COM 476*8040SBaban.Kenkre@Sun.COM 477*8040SBaban.Kenkre@Sun.COM /* 478*8040SBaban.Kenkre@Sun.COM * _nss_ad_destr frees allocated memory before exiting this nsswitch shared 479*8040SBaban.Kenkre@Sun.COM * backend library. This function is called before returning control back to 480*8040SBaban.Kenkre@Sun.COM * nsswitch. 481*8040SBaban.Kenkre@Sun.COM */ 482*8040SBaban.Kenkre@Sun.COM /*ARGSUSED*/ 483*8040SBaban.Kenkre@Sun.COM nss_status_t 484*8040SBaban.Kenkre@Sun.COM _nss_ad_destr(ad_backend_ptr be, void *a) 485*8040SBaban.Kenkre@Sun.COM { 486*8040SBaban.Kenkre@Sun.COM (void) _clean_ad_backend(be); 487*8040SBaban.Kenkre@Sun.COM clean_state(); 488*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_SUCCESS); 489*8040SBaban.Kenkre@Sun.COM } 490*8040SBaban.Kenkre@Sun.COM 491*8040SBaban.Kenkre@Sun.COM 492*8040SBaban.Kenkre@Sun.COM /*ARGSUSED*/ 493*8040SBaban.Kenkre@Sun.COM nss_status_t 494*8040SBaban.Kenkre@Sun.COM _nss_ad_setent(ad_backend_ptr be, void *a) 495*8040SBaban.Kenkre@Sun.COM { 496*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_UNAVAIL); 497*8040SBaban.Kenkre@Sun.COM } 498*8040SBaban.Kenkre@Sun.COM 499*8040SBaban.Kenkre@Sun.COM 500*8040SBaban.Kenkre@Sun.COM /*ARGSUSED*/ 501*8040SBaban.Kenkre@Sun.COM nss_status_t 502*8040SBaban.Kenkre@Sun.COM _nss_ad_endent(ad_backend_ptr be, void *a) 503*8040SBaban.Kenkre@Sun.COM { 504*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_UNAVAIL); 505*8040SBaban.Kenkre@Sun.COM } 506*8040SBaban.Kenkre@Sun.COM 507*8040SBaban.Kenkre@Sun.COM 508*8040SBaban.Kenkre@Sun.COM /*ARGSUSED*/ 509*8040SBaban.Kenkre@Sun.COM nss_status_t 510*8040SBaban.Kenkre@Sun.COM _nss_ad_getent(ad_backend_ptr be, void *a) 511*8040SBaban.Kenkre@Sun.COM { 512*8040SBaban.Kenkre@Sun.COM return ((nss_status_t)NSS_UNAVAIL); 513*8040SBaban.Kenkre@Sun.COM } 514*8040SBaban.Kenkre@Sun.COM 515*8040SBaban.Kenkre@Sun.COM 516*8040SBaban.Kenkre@Sun.COM nss_backend_t * 517*8040SBaban.Kenkre@Sun.COM _nss_ad_constr(ad_backend_op_t ops[], int nops, char *tablename, 518*8040SBaban.Kenkre@Sun.COM const char **attrs, fnf adobj2str) 519*8040SBaban.Kenkre@Sun.COM { 520*8040SBaban.Kenkre@Sun.COM ad_backend_ptr be; 521*8040SBaban.Kenkre@Sun.COM 522*8040SBaban.Kenkre@Sun.COM if ((be = (ad_backend_ptr) calloc(1, sizeof (*be))) == NULL) 523*8040SBaban.Kenkre@Sun.COM return (NULL); 524*8040SBaban.Kenkre@Sun.COM if ((be->tablename = (char *)strdup(tablename)) == NULL) { 525*8040SBaban.Kenkre@Sun.COM free(be); 526*8040SBaban.Kenkre@Sun.COM return (NULL); 527*8040SBaban.Kenkre@Sun.COM } 528*8040SBaban.Kenkre@Sun.COM be->ops = ops; 529*8040SBaban.Kenkre@Sun.COM be->nops = (nss_dbop_t)nops; 530*8040SBaban.Kenkre@Sun.COM be->attrs = attrs; 531*8040SBaban.Kenkre@Sun.COM be->adobj2str = adobj2str; 532*8040SBaban.Kenkre@Sun.COM (void) memset(&state, 0, sizeof (state)); 533*8040SBaban.Kenkre@Sun.COM return ((nss_backend_t *)be); 534*8040SBaban.Kenkre@Sun.COM } 535