10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51676Sjpk * Common Development and Distribution License (the "License"). 61676Sjpk * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 221676Sjpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include "ldap_common.h" 290Sstevel@tonic-gate #include <malloc.h> 300Sstevel@tonic-gate #include <synch.h> 310Sstevel@tonic-gate #include <syslog.h> 320Sstevel@tonic-gate #include <rpcsvc/ypclnt.h> 330Sstevel@tonic-gate #include <rpcsvc/yp_prot.h> 340Sstevel@tonic-gate #include <thread.h> 350Sstevel@tonic-gate #include <ctype.h> 360Sstevel@tonic-gate #include <stdlib.h> 370Sstevel@tonic-gate #include <signal.h> 380Sstevel@tonic-gate #include <sys/stat.h> 390Sstevel@tonic-gate 400Sstevel@tonic-gate /* getent attributes filters */ 410Sstevel@tonic-gate #define _F_GETALIASENT "(objectClass=rfc822MailGroup)" 420Sstevel@tonic-gate #define _F_GETAUTHNAME "(objectClass=SolarisAuthAttr)" 430Sstevel@tonic-gate #define _F_GETAUUSERNAME "(objectClass=SolarisAuditUser)" 440Sstevel@tonic-gate #define _F_GETEXECNAME "(objectClass=SolarisExecAttr)" 450Sstevel@tonic-gate #define _F_GETGRENT "(objectClass=posixGroup)" 460Sstevel@tonic-gate #define _F_GETHOSTENT "(objectClass=ipHost)" 470Sstevel@tonic-gate #define _F_GETNETENT "(objectClass=ipNetwork)" 48*2830Sdjl #define _F_GETPROFNAME \ 49*2830Sdjl "(&(objectClass=SolarisProfAttr)(!(SolarisKernelSecurityPolicy=*)))" 500Sstevel@tonic-gate #define _F_GETPROTOENT "(objectClass=ipProtocol)" 510Sstevel@tonic-gate #define _F_GETPWENT "(objectClass=posixAccount)" 520Sstevel@tonic-gate #define _F_GETPRINTERENT "(objectClass=sunPrinter)" 530Sstevel@tonic-gate #define _F_GETRPCENT "(objectClass=oncRpc)" 540Sstevel@tonic-gate #define _F_GETSERVENT "(objectClass=ipService)" 550Sstevel@tonic-gate #define _F_GETSPENT "(objectclass=shadowAccount)" 560Sstevel@tonic-gate #define _F_GETUSERNAME "(objectClass=SolarisUserAttr)" 570Sstevel@tonic-gate #define _F_GETPROJENT "(objectClass=SolarisProject)" 581676Sjpk #define _F_GETTNRHDB "(objectClass=ipTnetHost)" 591676Sjpk #define _F_GETTNRHTP "(&(objectClass=ipTnetTemplate)"\ 601676Sjpk "(SolarisAttrKeyValue=*))" 610Sstevel@tonic-gate #define _F_GETENT_SSD "(%s)" 620Sstevel@tonic-gate 630Sstevel@tonic-gate static struct gettablefilter { 640Sstevel@tonic-gate char *tablename; 650Sstevel@tonic-gate char *tablefilter; 660Sstevel@tonic-gate } gettablefilterent[] = { 670Sstevel@tonic-gate {(char *)_PASSWD, (char *)_F_GETPWENT}, 680Sstevel@tonic-gate {(char *)_SHADOW, (char *)_F_GETSPENT}, 690Sstevel@tonic-gate {(char *)_GROUP, (char *)_F_GETGRENT}, 700Sstevel@tonic-gate {(char *)_HOSTS, (char *)_F_GETHOSTENT}, 710Sstevel@tonic-gate {(char *)_NETWORKS, (char *)_F_GETNETENT}, 720Sstevel@tonic-gate {(char *)_PROTOCOLS, (char *)_F_GETPROTOENT}, 730Sstevel@tonic-gate {(char *)_RPC, (char *)_F_GETRPCENT}, 740Sstevel@tonic-gate {(char *)_ALIASES, (char *)_F_GETALIASENT}, 750Sstevel@tonic-gate {(char *)_SERVICES, (char *)_F_GETSERVENT}, 760Sstevel@tonic-gate {(char *)_AUUSER, (char *)_F_GETAUUSERNAME}, 770Sstevel@tonic-gate {(char *)_AUTHATTR, (char *)_F_GETAUTHNAME}, 780Sstevel@tonic-gate {(char *)_EXECATTR, (char *)_F_GETEXECNAME}, 790Sstevel@tonic-gate {(char *)_PROFATTR, (char *)_F_GETPROFNAME}, 800Sstevel@tonic-gate {(char *)_USERATTR, (char *)_F_GETUSERNAME}, 810Sstevel@tonic-gate {(char *)_PROJECT, (char *)_F_GETPROJENT}, 820Sstevel@tonic-gate {(char *)_PRINTERS, (char *)_F_GETPRINTERENT}, 831676Sjpk {(char *)_TNRHDB, (char *)_F_GETTNRHDB}, 841676Sjpk {(char *)_TNRHTP, (char *)_F_GETTNRHTP}, 850Sstevel@tonic-gate {(char *)NULL, (char *)NULL} 860Sstevel@tonic-gate }; 870Sstevel@tonic-gate 880Sstevel@tonic-gate 89*2830Sdjl static nss_status_t 900Sstevel@tonic-gate switch_err(int rc, ns_ldap_error_t *error) 910Sstevel@tonic-gate { 920Sstevel@tonic-gate switch (rc) { 930Sstevel@tonic-gate case NS_LDAP_SUCCESS: 940Sstevel@tonic-gate return (NSS_SUCCESS); 950Sstevel@tonic-gate 960Sstevel@tonic-gate case NS_LDAP_NOTFOUND: 970Sstevel@tonic-gate return (NSS_NOTFOUND); 980Sstevel@tonic-gate 990Sstevel@tonic-gate case NS_LDAP_PARTIAL: 1000Sstevel@tonic-gate return (NSS_TRYAGAIN); 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate case NS_LDAP_INTERNAL: 1030Sstevel@tonic-gate if (error && (error->status == LDAP_SERVER_DOWN || 1040Sstevel@tonic-gate error->status == LDAP_TIMEOUT)) 1050Sstevel@tonic-gate return (NSS_TRYAGAIN); 1060Sstevel@tonic-gate else 1070Sstevel@tonic-gate return (NSS_UNAVAIL); 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate default: 1100Sstevel@tonic-gate return (NSS_UNAVAIL); 1110Sstevel@tonic-gate } 1120Sstevel@tonic-gate } 113*2830Sdjl /* ARGSUSED */ 1140Sstevel@tonic-gate nss_status_t 1150Sstevel@tonic-gate _nss_ldap_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp, 1160Sstevel@tonic-gate char *database, char *searchfilter, char *domain, 1170Sstevel@tonic-gate int (*init_filter_cb)(const ns_ldap_search_desc_t *desc, 1180Sstevel@tonic-gate char **realfilter, const void *userdata), 1190Sstevel@tonic-gate const void *userdata) 1200Sstevel@tonic-gate { 1210Sstevel@tonic-gate int callbackstat = 0; 1220Sstevel@tonic-gate ns_ldap_error_t *error = NULL; 1230Sstevel@tonic-gate int rc; 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate #ifdef DEBUG 1260Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_lookup]\n"); 1270Sstevel@tonic-gate (void) fprintf(stdout, "\tsearchfilter: %s\n", searchfilter); 1280Sstevel@tonic-gate (void) fprintf(stdout, 1290Sstevel@tonic-gate "\tuserdata: %s\n", userdata ? userdata : "NULL"); 1300Sstevel@tonic-gate (void) fprintf(stdout, "\tdatabase: %s\n", database); 1310Sstevel@tonic-gate #endif /* DEBUG */ 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate (void) __ns_ldap_freeResult(&be->result); 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate if ((rc = __ns_ldap_list(database, searchfilter, init_filter_cb, 1360Sstevel@tonic-gate be->attrs, NULL, 0, &be->result, &error, NULL, 1370Sstevel@tonic-gate userdata)) != NS_LDAP_SUCCESS) { 1380Sstevel@tonic-gate argp->returnval = 0; 1390Sstevel@tonic-gate rc = switch_err(rc, error); 1400Sstevel@tonic-gate (void) __ns_ldap_freeError(&error); 141*2830Sdjl 1420Sstevel@tonic-gate return (rc); 1430Sstevel@tonic-gate } 144*2830Sdjl (void) __ns_ldap_freeError(&error); 1450Sstevel@tonic-gate /* callback function */ 1460Sstevel@tonic-gate if ((callbackstat = 147*2830Sdjl be->ldapobj2str(be, argp)) != NSS_STR_PARSE_SUCCESS) { 148*2830Sdjl goto error_out; 149*2830Sdjl } 150*2830Sdjl 151*2830Sdjl /* 152*2830Sdjl * publickey does not have a front end marshaller and expects 153*2830Sdjl * a string to be returned in NSS. 154*2830Sdjl * No need to convert file format -> struct. 155*2830Sdjl * 156*2830Sdjl */ 157*2830Sdjl if (be->db_type == NSS_LDAP_DB_PUBLICKEY) { 158*2830Sdjl argp->returnval = argp->buf.buffer; 159*2830Sdjl argp->returnlen = strlen(argp->buf.buffer); 160*2830Sdjl be->db_type = NSS_LDAP_DB_NONE; 161*2830Sdjl return (NSS_SUCCESS); 1620Sstevel@tonic-gate } 163*2830Sdjl /* 164*2830Sdjl * Assume the switch engine wants the returned data in the file 165*2830Sdjl * format when argp->buf.result == NULL. 166*2830Sdjl * The front-end marshaller str2ether(ethers) uses 167*2830Sdjl * ent (argp->buf.result) and buffer (argp->buf.buffer) 168*2830Sdjl * for different purpose so ethers has to be treated differently. 169*2830Sdjl */ 170*2830Sdjl if (argp->buf.result != NULL || 171*2830Sdjl be->db_type == NSS_LDAP_DB_ETHERS) { 172*2830Sdjl /* file format -> struct */ 173*2830Sdjl if (argp->str2ent == NULL) { 174*2830Sdjl callbackstat = NSS_STR_PARSE_PARSE; 175*2830Sdjl goto error_out; 176*2830Sdjl } 1770Sstevel@tonic-gate 178*2830Sdjl callbackstat = (*argp->str2ent)(be->buffer, 179*2830Sdjl be->buflen, 180*2830Sdjl argp->buf.result, 181*2830Sdjl argp->buf.buffer, 182*2830Sdjl argp->buf.buflen); 183*2830Sdjl if (callbackstat == NSS_STR_PARSE_SUCCESS) { 184*2830Sdjl if (be->db_type == NSS_LDAP_DB_ETHERS && 185*2830Sdjl argp->buf.buffer != NULL) { 186*2830Sdjl argp->returnval = argp->buf.buffer; 187*2830Sdjl argp->returnlen = strlen(argp->buf.buffer); 188*2830Sdjl } else { 189*2830Sdjl argp->returnval = argp->buf.result; 190*2830Sdjl argp->returnlen = 1; /* irrelevant */ 191*2830Sdjl } 192*2830Sdjl if (be->buffer != NULL) { 193*2830Sdjl free(be->buffer); 194*2830Sdjl be->buffer = NULL; 195*2830Sdjl be->buflen = 0; 196*2830Sdjl be->db_type = NSS_LDAP_DB_NONE; 197*2830Sdjl } 198*2830Sdjl return ((nss_status_t)NSS_SUCCESS); 199*2830Sdjl } 200*2830Sdjl } else { 201*2830Sdjl /* return file format in argp->buf.buffer */ 202*2830Sdjl argp->returnval = argp->buf.buffer; 203*2830Sdjl argp->returnlen = strlen(argp->buf.buffer); 204*2830Sdjl return ((nss_status_t)NSS_SUCCESS); 205*2830Sdjl } 206*2830Sdjl 207*2830Sdjl error_out: 208*2830Sdjl if (be->buffer != NULL) { 209*2830Sdjl free(be->buffer); 210*2830Sdjl be->buffer = NULL; 211*2830Sdjl be->buflen = 0; 212*2830Sdjl be->db_type = NSS_LDAP_DB_NONE; 213*2830Sdjl } 2140Sstevel@tonic-gate /* error */ 2150Sstevel@tonic-gate if (callbackstat == NSS_STR_PARSE_PARSE) { 2160Sstevel@tonic-gate argp->returnval = 0; 2170Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 2180Sstevel@tonic-gate } 2190Sstevel@tonic-gate if (callbackstat == NSS_STR_PARSE_ERANGE) { 2200Sstevel@tonic-gate argp->erange = 1; 2210Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 2220Sstevel@tonic-gate } 2230Sstevel@tonic-gate if (callbackstat == NSS_STR_PARSE_NO_ADDR) { 2240Sstevel@tonic-gate /* No IPV4 address is found */ 2250Sstevel@tonic-gate argp->h_errno = HOST_NOT_FOUND; 2260Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 2270Sstevel@tonic-gate } 2280Sstevel@tonic-gate return ((nss_status_t)NSS_UNAVAIL); 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate /* 2320Sstevel@tonic-gate * This function is similar to _nss_ldap_lookup except it does not 2330Sstevel@tonic-gate * do a callback. It is only used by getnetgrent.c 2340Sstevel@tonic-gate */ 2350Sstevel@tonic-gate 236*2830Sdjl /* ARGSUSED */ 2370Sstevel@tonic-gate nss_status_t 2380Sstevel@tonic-gate _nss_ldap_nocb_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp, 2390Sstevel@tonic-gate char *database, char *searchfilter, char *domain, 2400Sstevel@tonic-gate int (*init_filter_cb)(const ns_ldap_search_desc_t *desc, 2410Sstevel@tonic-gate char **realfilter, const void *userdata), 2420Sstevel@tonic-gate const void *userdata) 2430Sstevel@tonic-gate { 2440Sstevel@tonic-gate ns_ldap_error_t *error = NULL; 2450Sstevel@tonic-gate int rc; 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate #ifdef DEBUG 2480Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_nocb_lookup]\n"); 2490Sstevel@tonic-gate (void) fprintf(stdout, "\tsearchfilter: %s\n", searchfilter); 2500Sstevel@tonic-gate (void) fprintf(stdout, "\tdatabase: %s\n", database); 2510Sstevel@tonic-gate (void) fprintf(stdout, 2520Sstevel@tonic-gate "\tuserdata: %s\n", userdata ? userdata : "NULL"); 2530Sstevel@tonic-gate #endif /* DEBUG */ 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate (void) __ns_ldap_freeResult(&be->result); 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate if ((rc = __ns_ldap_list(database, searchfilter, init_filter_cb, 2580Sstevel@tonic-gate be->attrs, NULL, 0, &be->result, &error, NULL, 2590Sstevel@tonic-gate userdata)) != NS_LDAP_SUCCESS) { 2600Sstevel@tonic-gate argp->returnval = 0; 2610Sstevel@tonic-gate rc = switch_err(rc, error); 2620Sstevel@tonic-gate (void) __ns_ldap_freeError(&error); 2630Sstevel@tonic-gate return (rc); 2640Sstevel@tonic-gate } 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate return ((nss_status_t)NSS_SUCCESS); 2670Sstevel@tonic-gate } 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate /* 2710Sstevel@tonic-gate * 2720Sstevel@tonic-gate */ 2730Sstevel@tonic-gate 2740Sstevel@tonic-gate void 2750Sstevel@tonic-gate _clean_ldap_backend(ldap_backend_ptr be) 2760Sstevel@tonic-gate { 2770Sstevel@tonic-gate ns_ldap_error_t *error; 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate #ifdef DEBUG 2800Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _clean_ldap_backend]\n"); 2810Sstevel@tonic-gate #endif /* DEBUG */ 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate if (be->tablename != NULL) 2840Sstevel@tonic-gate free(be->tablename); 2850Sstevel@tonic-gate if (be->result != NULL) 2860Sstevel@tonic-gate (void) __ns_ldap_freeResult(&be->result); 2870Sstevel@tonic-gate if (be->enumcookie != NULL) 2880Sstevel@tonic-gate (void) __ns_ldap_endEntry(&be->enumcookie, &error); 2890Sstevel@tonic-gate if (be->services_cookie != NULL) 2900Sstevel@tonic-gate _nss_services_cookie_free((void **)&be->services_cookie); 2910Sstevel@tonic-gate if (be->toglue != NULL) { 2920Sstevel@tonic-gate free(be->toglue); 2930Sstevel@tonic-gate be->toglue = NULL; 2940Sstevel@tonic-gate } 295*2830Sdjl if (be->buffer != NULL) { 296*2830Sdjl free(be->buffer); 297*2830Sdjl be->buffer = NULL; 298*2830Sdjl } 2990Sstevel@tonic-gate free(be); 3000Sstevel@tonic-gate } 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate /* 3040Sstevel@tonic-gate * _nss_ldap_destr will free all smalloc'ed variable strings and structures 3050Sstevel@tonic-gate * before exiting this nsswitch shared backend library. This function is 3060Sstevel@tonic-gate * called before returning control back to nsswitch. 3070Sstevel@tonic-gate */ 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate /*ARGSUSED1*/ 3100Sstevel@tonic-gate nss_status_t 3110Sstevel@tonic-gate _nss_ldap_destr(ldap_backend_ptr be, void *a) 3120Sstevel@tonic-gate { 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate #ifdef DEBUG 3150Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_destr]\n"); 3160Sstevel@tonic-gate #endif /* DEBUG */ 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate (void) _clean_ldap_backend(be); 3190Sstevel@tonic-gate 3200Sstevel@tonic-gate return ((nss_status_t)NSS_SUCCESS); 3210Sstevel@tonic-gate } 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate 3240Sstevel@tonic-gate /* 3250Sstevel@tonic-gate * _nss_ldap_setent called before _nss_ldap_getent. This function is 3260Sstevel@tonic-gate * required by POSIX. 3270Sstevel@tonic-gate */ 3280Sstevel@tonic-gate 3290Sstevel@tonic-gate nss_status_t 3300Sstevel@tonic-gate _nss_ldap_setent(ldap_backend_ptr be, void *a) 3310Sstevel@tonic-gate { 3320Sstevel@tonic-gate struct gettablefilter *gtf; 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate #ifdef DEBUG 3350Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_setent]\n"); 3360Sstevel@tonic-gate #endif /* DEBUG */ 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate if (be->setcalled == 1) 3390Sstevel@tonic-gate (void) _nss_ldap_endent(be, a); 3400Sstevel@tonic-gate be->filter = NULL; 3410Sstevel@tonic-gate for (gtf = gettablefilterent; gtf->tablename != (char *)NULL; gtf++) { 3420Sstevel@tonic-gate if (strcmp(gtf->tablename, be->tablename)) 3430Sstevel@tonic-gate continue; 3440Sstevel@tonic-gate be->filter = (char *)gtf->tablefilter; 3450Sstevel@tonic-gate break; 3460Sstevel@tonic-gate } 3470Sstevel@tonic-gate 3480Sstevel@tonic-gate be->setcalled = 1; 3490Sstevel@tonic-gate be->enumcookie = NULL; 3500Sstevel@tonic-gate be->result = NULL; 3510Sstevel@tonic-gate be->services_cookie = NULL; 352*2830Sdjl be->buffer = NULL; 3530Sstevel@tonic-gate return ((nss_status_t)NSS_SUCCESS); 3540Sstevel@tonic-gate } 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate /* 3580Sstevel@tonic-gate * _nss_ldap_endent called after _nss_ldap_getent. This function is 3590Sstevel@tonic-gate * required by POSIX. 3600Sstevel@tonic-gate */ 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate /*ARGSUSED1*/ 3630Sstevel@tonic-gate nss_status_t 3640Sstevel@tonic-gate _nss_ldap_endent(ldap_backend_ptr be, void *a) 3650Sstevel@tonic-gate { 3660Sstevel@tonic-gate ns_ldap_error_t *error = NULL; 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate #ifdef DEBUG 3690Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_endent]\n"); 3700Sstevel@tonic-gate #endif /* DEBUG */ 3710Sstevel@tonic-gate 3720Sstevel@tonic-gate be->setcalled = 0; 3730Sstevel@tonic-gate be->filter = NULL; 3740Sstevel@tonic-gate if (be->enumcookie != NULL) { 3750Sstevel@tonic-gate (void) __ns_ldap_endEntry(&be->enumcookie, &error); 3760Sstevel@tonic-gate (void) __ns_ldap_freeError(&error); 3770Sstevel@tonic-gate } 3780Sstevel@tonic-gate if (be->result != NULL) { 3790Sstevel@tonic-gate (void) __ns_ldap_freeResult(&be->result); 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate if (be->services_cookie != NULL) { 3820Sstevel@tonic-gate _nss_services_cookie_free((void **)&be->services_cookie); 3830Sstevel@tonic-gate } 384*2830Sdjl if (be->buffer != NULL) { 385*2830Sdjl free(be->buffer); 386*2830Sdjl be->buffer = NULL; 387*2830Sdjl } 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate return ((nss_status_t)NSS_SUCCESS); 3900Sstevel@tonic-gate } 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate /* 3940Sstevel@tonic-gate * 3950Sstevel@tonic-gate */ 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate nss_status_t 3980Sstevel@tonic-gate _nss_ldap_getent(ldap_backend_ptr be, void *a) 3990Sstevel@tonic-gate { 4000Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 4010Sstevel@tonic-gate ns_ldap_error_t *error = NULL; 4020Sstevel@tonic-gate int parsestat = 0; 4030Sstevel@tonic-gate int retcode = 0; 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate #ifdef DEBUG 4060Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_getent]\n"); 4070Sstevel@tonic-gate #endif /* DEBUG */ 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate if (be->setcalled == 0) 4100Sstevel@tonic-gate (void) _nss_ldap_setent(be, a); 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate next_entry: 4130Sstevel@tonic-gate if (be->enumcookie == NULL) { 4140Sstevel@tonic-gate retcode = __ns_ldap_firstEntry(be->tablename, 4150Sstevel@tonic-gate be->filter, _merge_SSD_filter, be->attrs, NULL, 4160Sstevel@tonic-gate 0, &be->enumcookie, 4170Sstevel@tonic-gate &be->result, &error, _F_GETENT_SSD); 4180Sstevel@tonic-gate } else { 4190Sstevel@tonic-gate if (be->services_cookie == NULL) { 4200Sstevel@tonic-gate retcode = __ns_ldap_nextEntry(be->enumcookie, 4210Sstevel@tonic-gate &be->result, &error); 4220Sstevel@tonic-gate } 4230Sstevel@tonic-gate } 4240Sstevel@tonic-gate if (retcode != NS_LDAP_SUCCESS) { 4250Sstevel@tonic-gate retcode = switch_err(retcode, error); 4260Sstevel@tonic-gate (void) __ns_ldap_freeError(&error); 4270Sstevel@tonic-gate (void) _nss_ldap_endent(be, a); 4280Sstevel@tonic-gate return (retcode); 4290Sstevel@tonic-gate } else { 430*2830Sdjl /* ns_ldap_entry_t -> file format */ 431*2830Sdjl if ((parsestat = be->ldapobj2str(be, argp)) 4320Sstevel@tonic-gate == NSS_STR_PARSE_SUCCESS) { 433*2830Sdjl if (argp->buf.result != NULL) { 434*2830Sdjl /* file format -> struct */ 435*2830Sdjl if (argp->str2ent == NULL) { 436*2830Sdjl parsestat = NSS_STR_PARSE_PARSE; 437*2830Sdjl goto error_out; 438*2830Sdjl } 439*2830Sdjl parsestat = (*argp->str2ent)(be->buffer, 440*2830Sdjl be->buflen, 441*2830Sdjl argp->buf.result, 442*2830Sdjl argp->buf.buffer, 443*2830Sdjl argp->buf.buflen); 444*2830Sdjl if (parsestat == NSS_STR_PARSE_SUCCESS) { 445*2830Sdjl if (be->buffer != NULL) { 446*2830Sdjl free(be->buffer); 447*2830Sdjl be->buffer = NULL; 448*2830Sdjl be->buflen = 0; 449*2830Sdjl } 450*2830Sdjl be->result = NULL; 451*2830Sdjl argp->returnval = argp->buf.result; 452*2830Sdjl argp->returnlen = 1; /* irrevelant */ 453*2830Sdjl return ((nss_status_t)NSS_SUCCESS); 454*2830Sdjl } 455*2830Sdjl } else { 456*2830Sdjl /* 457*2830Sdjl * nscd is not caching the enumerated 458*2830Sdjl * entries. This code path would be dormant. 459*2830Sdjl * Keep this path for the future references. 460*2830Sdjl */ 461*2830Sdjl argp->returnval = argp->buf.buffer; 462*2830Sdjl argp->returnlen = 463*2830Sdjl strlen(argp->buf.buffer) + 1; 464*2830Sdjl } 465*2830Sdjl } 466*2830Sdjl error_out: 467*2830Sdjl if (be->buffer != NULL) { 468*2830Sdjl free(be->buffer); 469*2830Sdjl be->buffer = NULL; 470*2830Sdjl be->buflen = 0; 4710Sstevel@tonic-gate } 4720Sstevel@tonic-gate be->result = NULL; 4730Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_PARSE) { 4740Sstevel@tonic-gate argp->returnval = 0; 4750Sstevel@tonic-gate (void) _nss_ldap_endent(be, a); 4760Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 4770Sstevel@tonic-gate } 4780Sstevel@tonic-gate 4790Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_ERANGE) { 4800Sstevel@tonic-gate argp->erange = 1; 4810Sstevel@tonic-gate (void) _nss_ldap_endent(be, a); 4820Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 4830Sstevel@tonic-gate } 4840Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_NO_ADDR) 4850Sstevel@tonic-gate /* 4860Sstevel@tonic-gate * No IPV4 address is found in the current entry. 4870Sstevel@tonic-gate * It indicates that the entry contains IPV6 addresses 4880Sstevel@tonic-gate * only. Instead of calling _nss_ldap_endent to 4890Sstevel@tonic-gate * terminate, get next entry to continue enumeration. 4900Sstevel@tonic-gate * If it returned NSS_NOTFOUND here, 4910Sstevel@tonic-gate * gethostent() would return NULL 4920Sstevel@tonic-gate * and the enumeration would stop prematurely. 4930Sstevel@tonic-gate */ 4940Sstevel@tonic-gate goto next_entry; 4950Sstevel@tonic-gate } 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate return ((nss_status_t)NSS_SUCCESS); 4980Sstevel@tonic-gate } 4990Sstevel@tonic-gate 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate /* 5020Sstevel@tonic-gate * 5030Sstevel@tonic-gate */ 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate nss_backend_t * 5060Sstevel@tonic-gate _nss_ldap_constr(ldap_backend_op_t ops[], int nops, char *tablename, 507*2830Sdjl const char **attrs, fnf ldapobj2str) 5080Sstevel@tonic-gate { 5090Sstevel@tonic-gate ldap_backend_ptr be; 5100Sstevel@tonic-gate 5110Sstevel@tonic-gate #ifdef DEBUG 5120Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_constr]\n"); 5130Sstevel@tonic-gate #endif /* DEBUG */ 5140Sstevel@tonic-gate 515*2830Sdjl if ((be = (ldap_backend_ptr) calloc(1, sizeof (*be))) == 0) 5160Sstevel@tonic-gate return (0); 5170Sstevel@tonic-gate be->ops = ops; 5180Sstevel@tonic-gate be->nops = (nss_dbop_t)nops; 5190Sstevel@tonic-gate be->tablename = (char *)strdup(tablename); 5200Sstevel@tonic-gate be->attrs = attrs; 521*2830Sdjl be->ldapobj2str = ldapobj2str; 5220Sstevel@tonic-gate 5230Sstevel@tonic-gate return ((nss_backend_t *)be); 5240Sstevel@tonic-gate } 5250Sstevel@tonic-gate 5260Sstevel@tonic-gate 5270Sstevel@tonic-gate /* 5280Sstevel@tonic-gate * 5290Sstevel@tonic-gate */ 5300Sstevel@tonic-gate int 5310Sstevel@tonic-gate chophostdomain(char *string, char *host, char *domain) 5320Sstevel@tonic-gate { 5330Sstevel@tonic-gate char *dot; 5340Sstevel@tonic-gate 5350Sstevel@tonic-gate if (string == NULL) 5360Sstevel@tonic-gate return (-1); 5370Sstevel@tonic-gate 5380Sstevel@tonic-gate if ((dot = strchr(string, '.')) == NULL) { 5390Sstevel@tonic-gate return (0); 5400Sstevel@tonic-gate } 5410Sstevel@tonic-gate *dot = '\0'; 542*2830Sdjl (void) strcpy(host, string); 543*2830Sdjl (void) strcpy(domain, ++dot); 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate return (0); 5460Sstevel@tonic-gate } 5470Sstevel@tonic-gate 5480Sstevel@tonic-gate 5490Sstevel@tonic-gate /* 5500Sstevel@tonic-gate * 5510Sstevel@tonic-gate */ 5520Sstevel@tonic-gate int 5530Sstevel@tonic-gate propersubdomain(char *domain, char *subdomain) 5540Sstevel@tonic-gate { 5550Sstevel@tonic-gate int domainlen, subdomainlen; 5560Sstevel@tonic-gate 5570Sstevel@tonic-gate /* sanity check */ 5580Sstevel@tonic-gate if (domain == NULL || subdomain == NULL) 5590Sstevel@tonic-gate return (-1); 5600Sstevel@tonic-gate 5610Sstevel@tonic-gate domainlen = strlen(domain); 5620Sstevel@tonic-gate subdomainlen = strlen(subdomain); 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate /* is afterdot a substring of domain? */ 5650Sstevel@tonic-gate if ((strncasecmp(domain, subdomain, subdomainlen)) != 0) 5660Sstevel@tonic-gate return (-1); 5670Sstevel@tonic-gate 5680Sstevel@tonic-gate if (domainlen == subdomainlen) 5690Sstevel@tonic-gate return (1); 5700Sstevel@tonic-gate 5710Sstevel@tonic-gate if (subdomainlen > domainlen) 5720Sstevel@tonic-gate return (-1); 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate if (*(domain + subdomainlen) != '.') 5750Sstevel@tonic-gate return (-1); 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate return (1); 5780Sstevel@tonic-gate } 579