17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
545916cd2Sjpk * Common Development and Distribution License (the "License").
645916cd2Sjpk * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
229f2fd570SJulian Pullen * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
23*6a9f1673SMatt Barden * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include "ldap_common.h"
277c478bd9Sstevel@tonic-gate #include <malloc.h>
287c478bd9Sstevel@tonic-gate #include <synch.h>
297c478bd9Sstevel@tonic-gate #include <syslog.h>
307c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
317c478bd9Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
327c478bd9Sstevel@tonic-gate #include <thread.h>
337c478bd9Sstevel@tonic-gate #include <ctype.h>
347c478bd9Sstevel@tonic-gate #include <stdlib.h>
357c478bd9Sstevel@tonic-gate #include <signal.h>
367c478bd9Sstevel@tonic-gate #include <sys/stat.h>
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate /* getent attributes filters */
397c478bd9Sstevel@tonic-gate #define _F_GETALIASENT "(objectClass=rfc822MailGroup)"
407c478bd9Sstevel@tonic-gate #define _F_GETAUTHNAME "(objectClass=SolarisAuthAttr)"
417c478bd9Sstevel@tonic-gate #define _F_GETAUUSERNAME "(objectClass=SolarisAuditUser)"
427c478bd9Sstevel@tonic-gate #define _F_GETEXECNAME "(objectClass=SolarisExecAttr)"
437c478bd9Sstevel@tonic-gate #define _F_GETGRENT "(objectClass=posixGroup)"
447c478bd9Sstevel@tonic-gate #define _F_GETHOSTENT "(objectClass=ipHost)"
457c478bd9Sstevel@tonic-gate #define _F_GETNETENT "(objectClass=ipNetwork)"
46cb5caa98Sdjl #define _F_GETPROFNAME \
47cb5caa98Sdjl "(&(objectClass=SolarisProfAttr)(!(SolarisKernelSecurityPolicy=*)))"
487c478bd9Sstevel@tonic-gate #define _F_GETPROTOENT "(objectClass=ipProtocol)"
497c478bd9Sstevel@tonic-gate #define _F_GETPWENT "(objectClass=posixAccount)"
507c478bd9Sstevel@tonic-gate #define _F_GETPRINTERENT "(objectClass=sunPrinter)"
517c478bd9Sstevel@tonic-gate #define _F_GETRPCENT "(objectClass=oncRpc)"
527c478bd9Sstevel@tonic-gate #define _F_GETSERVENT "(objectClass=ipService)"
537c478bd9Sstevel@tonic-gate #define _F_GETSPENT "(objectclass=shadowAccount)"
547c478bd9Sstevel@tonic-gate #define _F_GETUSERNAME "(objectClass=SolarisUserAttr)"
557c478bd9Sstevel@tonic-gate #define _F_GETPROJENT "(objectClass=SolarisProject)"
5645916cd2Sjpk #define _F_GETTNRHDB "(objectClass=ipTnetHost)"
5745916cd2Sjpk #define _F_GETTNRHTP "(&(objectClass=ipTnetTemplate)"\
5845916cd2Sjpk "(SolarisAttrKeyValue=*))"
597c478bd9Sstevel@tonic-gate #define _F_GETENT_SSD "(%s)"
607c478bd9Sstevel@tonic-gate
619f2fd570SJulian Pullen /* getent sort attributes */
629f2fd570SJulian Pullen #define _A_UID "uid"
639f2fd570SJulian Pullen #define _A_GIDNUMBER "gidnumber"
649f2fd570SJulian Pullen #define _A_CN "cn"
659f2fd570SJulian Pullen #define _A_IPNETWORKNUM "ipnetworknumber"
669f2fd570SJulian Pullen #define _A_PROJECTNAM "SolarisProjectName"
679f2fd570SJulian Pullen #define _A_IPTNETNUM "ipTnetNumber"
689f2fd570SJulian Pullen #define _A_IPTNETTMPLNAM "ipTnetTemplateName"
699f2fd570SJulian Pullen
707c478bd9Sstevel@tonic-gate static struct gettablefilter {
717c478bd9Sstevel@tonic-gate char *tablename;
727c478bd9Sstevel@tonic-gate char *tablefilter;
739f2fd570SJulian Pullen char *sortattr;
747c478bd9Sstevel@tonic-gate } gettablefilterent[] = {
759f2fd570SJulian Pullen {(char *)_PASSWD, (char *)_F_GETPWENT, (char *)_A_UID},
769f2fd570SJulian Pullen {(char *)_SHADOW, (char *)_F_GETSPENT, (char *)_A_UID},
779f2fd570SJulian Pullen {(char *)_GROUP, (char *)_F_GETGRENT, (char *)_A_GIDNUMBER},
789f2fd570SJulian Pullen {(char *)_HOSTS, (char *)_F_GETHOSTENT, (char *)_A_CN},
799f2fd570SJulian Pullen {(char *)_NETWORKS, (char *)_F_GETNETENT,
809f2fd570SJulian Pullen (char *)_A_IPNETWORKNUM},
819f2fd570SJulian Pullen {(char *)_PROTOCOLS, (char *)_F_GETPROTOENT, (char *)_A_CN},
829f2fd570SJulian Pullen {(char *)_RPC, (char *)_F_GETRPCENT, (char *)_A_CN},
839f2fd570SJulian Pullen {(char *)_ALIASES, (char *)_F_GETALIASENT, (char *)_A_CN},
849f2fd570SJulian Pullen {(char *)_SERVICES, (char *)_F_GETSERVENT, (char *)_A_CN},
859f2fd570SJulian Pullen {(char *)_AUUSER, (char *)_F_GETAUUSERNAME,
869f2fd570SJulian Pullen (char *)_A_UID},
879f2fd570SJulian Pullen {(char *)_AUTHATTR, (char *)_F_GETAUTHNAME, (char *)_A_CN},
889f2fd570SJulian Pullen {(char *)_EXECATTR, (char *)_F_GETEXECNAME, (char *)_A_CN},
899f2fd570SJulian Pullen {(char *)_PROFATTR, (char *)_F_GETPROFNAME, (char *)_A_CN},
909f2fd570SJulian Pullen {(char *)_USERATTR, (char *)_F_GETUSERNAME, (char *)_A_UID},
919f2fd570SJulian Pullen {(char *)_PROJECT, (char *)_F_GETPROJENT, (char *)_A_PROJECTNAM},
929f2fd570SJulian Pullen {(char *)_PRINTERS, (char *)_F_GETPRINTERENT, (char *)_A_CN},
939f2fd570SJulian Pullen {(char *)_TNRHDB, (char *)_F_GETTNRHDB, (char *)_A_IPTNETNUM},
949f2fd570SJulian Pullen {(char *)_TNRHTP, (char *)_F_GETTNRHTP,
959f2fd570SJulian Pullen (char *)_A_IPTNETTMPLNAM},
969f2fd570SJulian Pullen {(char *)NULL, (char *)NULL, (char *)NULL}
977c478bd9Sstevel@tonic-gate };
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate
1003d047983Smichen nss_status_t
switch_err(int rc,ns_ldap_error_t * error)1017c478bd9Sstevel@tonic-gate switch_err(int rc, ns_ldap_error_t *error)
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate switch (rc) {
1043d047983Smichen case NS_LDAP_SUCCESS:
1057c478bd9Sstevel@tonic-gate return (NSS_SUCCESS);
1067c478bd9Sstevel@tonic-gate
1073d047983Smichen case NS_LDAP_NOTFOUND:
108*6a9f1673SMatt Barden errno = 0;
1097c478bd9Sstevel@tonic-gate return (NSS_NOTFOUND);
1107c478bd9Sstevel@tonic-gate
1113d047983Smichen case NS_LDAP_PARTIAL:
1127c478bd9Sstevel@tonic-gate return (NSS_TRYAGAIN);
1137c478bd9Sstevel@tonic-gate
1143d047983Smichen case NS_LDAP_INTERNAL:
1153d047983Smichen if (error && (error->status == LDAP_SERVER_DOWN ||
1163d047983Smichen error->status == LDAP_TIMEOUT))
1173d047983Smichen return (NSS_TRYAGAIN);
1183d047983Smichen else
1193d047983Smichen return (NSS_UNAVAIL);
1207c478bd9Sstevel@tonic-gate
1213d047983Smichen default:
1227c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL);
1237c478bd9Sstevel@tonic-gate }
1247c478bd9Sstevel@tonic-gate }
125cb5caa98Sdjl /* ARGSUSED */
1267c478bd9Sstevel@tonic-gate nss_status_t
_nss_ldap_lookup(ldap_backend_ptr be,nss_XbyY_args_t * argp,char * database,char * searchfilter,char * domain,int (* init_filter_cb)(const ns_ldap_search_desc_t * desc,char ** realfilter,const void * userdata),const void * userdata)1277c478bd9Sstevel@tonic-gate _nss_ldap_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
128*6a9f1673SMatt Barden char *database, char *searchfilter, char *domain,
129*6a9f1673SMatt Barden int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
130*6a9f1673SMatt Barden char **realfilter, const void *userdata),
131*6a9f1673SMatt Barden const void *userdata)
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate int callbackstat = 0;
1347c478bd9Sstevel@tonic-gate ns_ldap_error_t *error = NULL;
1357c478bd9Sstevel@tonic-gate int rc;
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate #ifdef DEBUG
1387c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_lookup]\n");
1397c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\tsearchfilter: %s\n", searchfilter);
1407c478bd9Sstevel@tonic-gate (void) fprintf(stdout,
1413d047983Smichen "\tuserdata: %s\n", userdata ? userdata : "NULL");
1427c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\tdatabase: %s\n", database);
1437c478bd9Sstevel@tonic-gate #endif /* DEBUG */
1447c478bd9Sstevel@tonic-gate
1457c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeResult(&be->result);
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate if ((rc = __ns_ldap_list(database, searchfilter, init_filter_cb,
1483d047983Smichen be->attrs, NULL, 0, &be->result, &error, NULL,
1493d047983Smichen userdata)) != NS_LDAP_SUCCESS) {
1507c478bd9Sstevel@tonic-gate argp->returnval = 0;
1517c478bd9Sstevel@tonic-gate rc = switch_err(rc, error);
1527c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeError(&error);
153cb5caa98Sdjl
1547c478bd9Sstevel@tonic-gate return (rc);
1557c478bd9Sstevel@tonic-gate }
156cb5caa98Sdjl (void) __ns_ldap_freeError(&error);
1577c478bd9Sstevel@tonic-gate /* callback function */
1587c478bd9Sstevel@tonic-gate if ((callbackstat =
1593d047983Smichen be->ldapobj2str(be, argp)) != NSS_STR_PARSE_SUCCESS) {
160cb5caa98Sdjl goto error_out;
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate
163cb5caa98Sdjl /*
164cb5caa98Sdjl * publickey does not have a front end marshaller and expects
165cb5caa98Sdjl * a string to be returned in NSS.
166cb5caa98Sdjl * No need to convert file format -> struct.
167cb5caa98Sdjl *
168cb5caa98Sdjl */
169cb5caa98Sdjl if (be->db_type == NSS_LDAP_DB_PUBLICKEY) {
170cb5caa98Sdjl argp->returnval = argp->buf.buffer;
171cb5caa98Sdjl argp->returnlen = strlen(argp->buf.buffer);
172cb5caa98Sdjl be->db_type = NSS_LDAP_DB_NONE;
173cb5caa98Sdjl return (NSS_SUCCESS);
174cb5caa98Sdjl }
175cb5caa98Sdjl /*
176cb5caa98Sdjl * Assume the switch engine wants the returned data in the file
177cb5caa98Sdjl * format when argp->buf.result == NULL.
178cb5caa98Sdjl * The front-end marshaller str2ether(ethers) uses
179cb5caa98Sdjl * ent (argp->buf.result) and buffer (argp->buf.buffer)
180cb5caa98Sdjl * for different purpose so ethers has to be treated differently.
181cb5caa98Sdjl */
182cb5caa98Sdjl if (argp->buf.result != NULL ||
1833d047983Smichen be->db_type == NSS_LDAP_DB_ETHERS) {
184cb5caa98Sdjl /* file format -> struct */
185cb5caa98Sdjl if (argp->str2ent == NULL) {
186cb5caa98Sdjl callbackstat = NSS_STR_PARSE_PARSE;
187cb5caa98Sdjl goto error_out;
188cb5caa98Sdjl }
189cb5caa98Sdjl
190cb5caa98Sdjl callbackstat = (*argp->str2ent)(be->buffer,
1913d047983Smichen be->buflen,
1923d047983Smichen argp->buf.result,
1933d047983Smichen argp->buf.buffer,
1943d047983Smichen argp->buf.buflen);
195cb5caa98Sdjl if (callbackstat == NSS_STR_PARSE_SUCCESS) {
196cb5caa98Sdjl if (be->db_type == NSS_LDAP_DB_ETHERS &&
1973d047983Smichen argp->buf.buffer != NULL) {
198cb5caa98Sdjl argp->returnval = argp->buf.buffer;
199cb5caa98Sdjl argp->returnlen = strlen(argp->buf.buffer);
200cb5caa98Sdjl } else {
201cb5caa98Sdjl argp->returnval = argp->buf.result;
202cb5caa98Sdjl argp->returnlen = 1; /* irrelevant */
203cb5caa98Sdjl }
204cb5caa98Sdjl if (be->buffer != NULL) {
205cb5caa98Sdjl free(be->buffer);
206cb5caa98Sdjl be->buffer = NULL;
207cb5caa98Sdjl be->buflen = 0;
208cb5caa98Sdjl be->db_type = NSS_LDAP_DB_NONE;
209cb5caa98Sdjl }
210cb5caa98Sdjl return ((nss_status_t)NSS_SUCCESS);
211cb5caa98Sdjl }
212cb5caa98Sdjl } else {
213cb5caa98Sdjl /* return file format in argp->buf.buffer */
214cb5caa98Sdjl argp->returnval = argp->buf.buffer;
215cb5caa98Sdjl argp->returnlen = strlen(argp->buf.buffer);
216cb5caa98Sdjl return ((nss_status_t)NSS_SUCCESS);
217cb5caa98Sdjl }
218cb5caa98Sdjl
219cb5caa98Sdjl error_out:
220cb5caa98Sdjl if (be->buffer != NULL) {
221cb5caa98Sdjl free(be->buffer);
222cb5caa98Sdjl be->buffer = NULL;
223cb5caa98Sdjl be->buflen = 0;
224cb5caa98Sdjl be->db_type = NSS_LDAP_DB_NONE;
225cb5caa98Sdjl }
2267c478bd9Sstevel@tonic-gate /* error */
2277c478bd9Sstevel@tonic-gate if (callbackstat == NSS_STR_PARSE_PARSE) {
2287c478bd9Sstevel@tonic-gate argp->returnval = 0;
2297c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
2307c478bd9Sstevel@tonic-gate }
2317c478bd9Sstevel@tonic-gate if (callbackstat == NSS_STR_PARSE_ERANGE) {
2327c478bd9Sstevel@tonic-gate argp->erange = 1;
2337c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate if (callbackstat == NSS_STR_PARSE_NO_ADDR) {
2367c478bd9Sstevel@tonic-gate /* No IPV4 address is found */
2377c478bd9Sstevel@tonic-gate argp->h_errno = HOST_NOT_FOUND;
2387c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_UNAVAIL);
2417c478bd9Sstevel@tonic-gate }
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate /*
2447c478bd9Sstevel@tonic-gate * This function is similar to _nss_ldap_lookup except it does not
2457c478bd9Sstevel@tonic-gate * do a callback. It is only used by getnetgrent.c
2467c478bd9Sstevel@tonic-gate */
2477c478bd9Sstevel@tonic-gate
248cb5caa98Sdjl /* ARGSUSED */
2497c478bd9Sstevel@tonic-gate nss_status_t
_nss_ldap_nocb_lookup(ldap_backend_ptr be,nss_XbyY_args_t * argp,char * database,char * searchfilter,const char * const * attrs,int (* init_filter_cb)(const ns_ldap_search_desc_t * desc,char ** realfilter,const void * userdata),const void * userdata)2507c478bd9Sstevel@tonic-gate _nss_ldap_nocb_lookup(ldap_backend_ptr be, nss_XbyY_args_t *argp,
251*6a9f1673SMatt Barden char *database, char *searchfilter, const char * const *attrs,
252*6a9f1673SMatt Barden int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
253*6a9f1673SMatt Barden char **realfilter, const void *userdata),
254*6a9f1673SMatt Barden const void *userdata)
2557c478bd9Sstevel@tonic-gate {
2567c478bd9Sstevel@tonic-gate ns_ldap_error_t *error = NULL;
2577c478bd9Sstevel@tonic-gate int rc;
2587c478bd9Sstevel@tonic-gate
259695ef821SGordon Ross if (attrs == NULL)
260695ef821SGordon Ross attrs = be->attrs;
261695ef821SGordon Ross
2627c478bd9Sstevel@tonic-gate #ifdef DEBUG
2637c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_nocb_lookup]\n");
2647c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\tsearchfilter: %s\n", searchfilter);
2657c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\tdatabase: %s\n", database);
2667c478bd9Sstevel@tonic-gate (void) fprintf(stdout,
2673d047983Smichen "\tuserdata: %s\n", userdata ? userdata : "NULL");
2687c478bd9Sstevel@tonic-gate #endif /* DEBUG */
2697c478bd9Sstevel@tonic-gate
2707c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeResult(&be->result);
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate if ((rc = __ns_ldap_list(database, searchfilter, init_filter_cb,
273695ef821SGordon Ross attrs, NULL, 0, &be->result, &error, NULL,
2743d047983Smichen userdata)) != NS_LDAP_SUCCESS) {
27518bdb8a7Smichen if (argp != NULL)
27618bdb8a7Smichen argp->returnval = 0;
2777c478bd9Sstevel@tonic-gate rc = switch_err(rc, error);
2787c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeError(&error);
2797c478bd9Sstevel@tonic-gate return (rc);
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate
2827c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_SUCCESS);
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate /*
2877c478bd9Sstevel@tonic-gate *
2887c478bd9Sstevel@tonic-gate */
2897c478bd9Sstevel@tonic-gate
2907c478bd9Sstevel@tonic-gate void
_clean_ldap_backend(ldap_backend_ptr be)2917c478bd9Sstevel@tonic-gate _clean_ldap_backend(ldap_backend_ptr be)
2927c478bd9Sstevel@tonic-gate {
2937c478bd9Sstevel@tonic-gate ns_ldap_error_t *error;
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate #ifdef DEBUG
2967c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _clean_ldap_backend]\n");
2977c478bd9Sstevel@tonic-gate #endif /* DEBUG */
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate if (be->tablename != NULL)
3007c478bd9Sstevel@tonic-gate free(be->tablename);
3017c478bd9Sstevel@tonic-gate if (be->result != NULL)
3027c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeResult(&be->result);
3037c478bd9Sstevel@tonic-gate if (be->enumcookie != NULL)
3047c478bd9Sstevel@tonic-gate (void) __ns_ldap_endEntry(&be->enumcookie, &error);
3057c478bd9Sstevel@tonic-gate if (be->services_cookie != NULL)
3067c478bd9Sstevel@tonic-gate _nss_services_cookie_free((void **)&be->services_cookie);
3077c478bd9Sstevel@tonic-gate if (be->toglue != NULL) {
3087c478bd9Sstevel@tonic-gate free(be->toglue);
3097c478bd9Sstevel@tonic-gate be->toglue = NULL;
3107c478bd9Sstevel@tonic-gate }
311cb5caa98Sdjl if (be->buffer != NULL) {
312cb5caa98Sdjl free(be->buffer);
313cb5caa98Sdjl be->buffer = NULL;
314cb5caa98Sdjl }
3157c478bd9Sstevel@tonic-gate free(be);
3167c478bd9Sstevel@tonic-gate }
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate /*
3207c478bd9Sstevel@tonic-gate * _nss_ldap_destr will free all smalloc'ed variable strings and structures
3217c478bd9Sstevel@tonic-gate * before exiting this nsswitch shared backend library. This function is
3227c478bd9Sstevel@tonic-gate * called before returning control back to nsswitch.
3237c478bd9Sstevel@tonic-gate */
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
3267c478bd9Sstevel@tonic-gate nss_status_t
_nss_ldap_destr(ldap_backend_ptr be,void * a)3277c478bd9Sstevel@tonic-gate _nss_ldap_destr(ldap_backend_ptr be, void *a)
3287c478bd9Sstevel@tonic-gate {
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate #ifdef DEBUG
3317c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_destr]\n");
3327c478bd9Sstevel@tonic-gate #endif /* DEBUG */
3337c478bd9Sstevel@tonic-gate
3347c478bd9Sstevel@tonic-gate (void) _clean_ldap_backend(be);
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_SUCCESS);
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate
3407c478bd9Sstevel@tonic-gate /*
3417c478bd9Sstevel@tonic-gate * _nss_ldap_setent called before _nss_ldap_getent. This function is
3427c478bd9Sstevel@tonic-gate * required by POSIX.
3437c478bd9Sstevel@tonic-gate */
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate nss_status_t
_nss_ldap_setent(ldap_backend_ptr be,void * a)3467c478bd9Sstevel@tonic-gate _nss_ldap_setent(ldap_backend_ptr be, void *a)
3477c478bd9Sstevel@tonic-gate {
3487c478bd9Sstevel@tonic-gate struct gettablefilter *gtf;
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate #ifdef DEBUG
3517c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_setent]\n");
3527c478bd9Sstevel@tonic-gate #endif /* DEBUG */
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate if (be->setcalled == 1)
3557c478bd9Sstevel@tonic-gate (void) _nss_ldap_endent(be, a);
3567c478bd9Sstevel@tonic-gate be->filter = NULL;
3579f2fd570SJulian Pullen be->sortattr = NULL;
3587c478bd9Sstevel@tonic-gate for (gtf = gettablefilterent; gtf->tablename != (char *)NULL; gtf++) {
3597c478bd9Sstevel@tonic-gate if (strcmp(gtf->tablename, be->tablename))
3607c478bd9Sstevel@tonic-gate continue;
3617c478bd9Sstevel@tonic-gate be->filter = (char *)gtf->tablefilter;
3629f2fd570SJulian Pullen be->sortattr = (char *)gtf->sortattr;
3637c478bd9Sstevel@tonic-gate break;
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate be->setcalled = 1;
3677c478bd9Sstevel@tonic-gate be->enumcookie = NULL;
3687c478bd9Sstevel@tonic-gate be->result = NULL;
3697c478bd9Sstevel@tonic-gate be->services_cookie = NULL;
370cb5caa98Sdjl be->buffer = NULL;
3717c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_SUCCESS);
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate /*
3767c478bd9Sstevel@tonic-gate * _nss_ldap_endent called after _nss_ldap_getent. This function is
3777c478bd9Sstevel@tonic-gate * required by POSIX.
3787c478bd9Sstevel@tonic-gate */
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
3817c478bd9Sstevel@tonic-gate nss_status_t
_nss_ldap_endent(ldap_backend_ptr be,void * a)3827c478bd9Sstevel@tonic-gate _nss_ldap_endent(ldap_backend_ptr be, void *a)
3837c478bd9Sstevel@tonic-gate {
3847c478bd9Sstevel@tonic-gate ns_ldap_error_t *error = NULL;
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate #ifdef DEBUG
3877c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_endent]\n");
3887c478bd9Sstevel@tonic-gate #endif /* DEBUG */
3897c478bd9Sstevel@tonic-gate
3907c478bd9Sstevel@tonic-gate be->setcalled = 0;
3917c478bd9Sstevel@tonic-gate be->filter = NULL;
3929f2fd570SJulian Pullen be->sortattr = NULL;
3937c478bd9Sstevel@tonic-gate if (be->enumcookie != NULL) {
3947c478bd9Sstevel@tonic-gate (void) __ns_ldap_endEntry(&be->enumcookie, &error);
3957c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeError(&error);
3967c478bd9Sstevel@tonic-gate }
3977c478bd9Sstevel@tonic-gate if (be->result != NULL) {
3987c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeResult(&be->result);
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate if (be->services_cookie != NULL) {
4017c478bd9Sstevel@tonic-gate _nss_services_cookie_free((void **)&be->services_cookie);
4027c478bd9Sstevel@tonic-gate }
403cb5caa98Sdjl if (be->buffer != NULL) {
404cb5caa98Sdjl free(be->buffer);
405cb5caa98Sdjl be->buffer = NULL;
406cb5caa98Sdjl }
4077c478bd9Sstevel@tonic-gate
4087c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_SUCCESS);
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate /*
4137c478bd9Sstevel@tonic-gate *
4147c478bd9Sstevel@tonic-gate */
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate nss_status_t
_nss_ldap_getent(ldap_backend_ptr be,void * a)4177c478bd9Sstevel@tonic-gate _nss_ldap_getent(ldap_backend_ptr be, void *a)
4187c478bd9Sstevel@tonic-gate {
4197c478bd9Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
4207c478bd9Sstevel@tonic-gate ns_ldap_error_t *error = NULL;
4217c478bd9Sstevel@tonic-gate int parsestat = 0;
4227c478bd9Sstevel@tonic-gate int retcode = 0;
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate #ifdef DEBUG
4257c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_getent]\n");
4267c478bd9Sstevel@tonic-gate #endif /* DEBUG */
4277c478bd9Sstevel@tonic-gate
4287c478bd9Sstevel@tonic-gate if (be->setcalled == 0)
4297c478bd9Sstevel@tonic-gate (void) _nss_ldap_setent(be, a);
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate next_entry:
4327c478bd9Sstevel@tonic-gate if (be->enumcookie == NULL) {
4337c478bd9Sstevel@tonic-gate retcode = __ns_ldap_firstEntry(be->tablename,
4349f2fd570SJulian Pullen be->filter, be->sortattr, _merge_SSD_filter, be->attrs,
4359f2fd570SJulian Pullen NULL, 0, &be->enumcookie,
4363d047983Smichen &be->result, &error, _F_GETENT_SSD);
4377c478bd9Sstevel@tonic-gate } else {
4387c478bd9Sstevel@tonic-gate if (be->services_cookie == NULL) {
4397c478bd9Sstevel@tonic-gate retcode = __ns_ldap_nextEntry(be->enumcookie,
4403d047983Smichen &be->result, &error);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate }
4437c478bd9Sstevel@tonic-gate if (retcode != NS_LDAP_SUCCESS) {
4447c478bd9Sstevel@tonic-gate retcode = switch_err(retcode, error);
4457c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeError(&error);
4467c478bd9Sstevel@tonic-gate (void) _nss_ldap_endent(be, a);
4477c478bd9Sstevel@tonic-gate return (retcode);
4489f2fd570SJulian Pullen }
4499f2fd570SJulian Pullen
4509f2fd570SJulian Pullen if (be->result == NULL) {
4519f2fd570SJulian Pullen parsestat = NSS_STR_PARSE_NO_RESULT;
4529f2fd570SJulian Pullen goto error_out;
4539f2fd570SJulian Pullen }
4549f2fd570SJulian Pullen /* ns_ldap_entry_t -> file format */
4559f2fd570SJulian Pullen if ((parsestat = be->ldapobj2str(be, argp))
4569f2fd570SJulian Pullen == NSS_STR_PARSE_SUCCESS) {
4579f2fd570SJulian Pullen if (argp->buf.result != NULL) {
4589f2fd570SJulian Pullen /* file format -> struct */
4599f2fd570SJulian Pullen if (argp->str2ent == NULL) {
4609f2fd570SJulian Pullen parsestat = NSS_STR_PARSE_NO_RESULT;
4619f2fd570SJulian Pullen goto error_out;
4629f2fd570SJulian Pullen }
4639f2fd570SJulian Pullen parsestat = (*argp->str2ent)(be->buffer,
4649f2fd570SJulian Pullen be->buflen,
4659f2fd570SJulian Pullen argp->buf.result,
4669f2fd570SJulian Pullen argp->buf.buffer,
4679f2fd570SJulian Pullen argp->buf.buflen);
4689f2fd570SJulian Pullen if (parsestat == NSS_STR_PARSE_SUCCESS) {
4699f2fd570SJulian Pullen if (be->buffer != NULL) {
4709f2fd570SJulian Pullen free(be->buffer);
4719f2fd570SJulian Pullen be->buffer = NULL;
4729f2fd570SJulian Pullen be->buflen = 0;
473cb5caa98Sdjl }
4749f2fd570SJulian Pullen be->result = NULL;
4759f2fd570SJulian Pullen argp->returnval = argp->buf.result;
4769f2fd570SJulian Pullen argp->returnlen = 1; /* irrevelant */
4779f2fd570SJulian Pullen return ((nss_status_t)NSS_SUCCESS);
478cb5caa98Sdjl }
4799f2fd570SJulian Pullen } else {
4809f2fd570SJulian Pullen /*
4819f2fd570SJulian Pullen * nscd is not caching the enumerated
4829f2fd570SJulian Pullen * entries. This code path would be dormant.
4839f2fd570SJulian Pullen * Keep this path for the future references.
4849f2fd570SJulian Pullen */
4859f2fd570SJulian Pullen argp->returnval = argp->buf.buffer;
4869f2fd570SJulian Pullen argp->returnlen =
4879f2fd570SJulian Pullen strlen(argp->buf.buffer) + 1;
488cb5caa98Sdjl }
4899f2fd570SJulian Pullen }
490cb5caa98Sdjl error_out:
4919f2fd570SJulian Pullen if (be->buffer != NULL) {
4929f2fd570SJulian Pullen free(be->buffer);
4939f2fd570SJulian Pullen be->buffer = NULL;
4949f2fd570SJulian Pullen be->buflen = 0;
4959f2fd570SJulian Pullen }
4969f2fd570SJulian Pullen be->result = NULL;
4979f2fd570SJulian Pullen if (parsestat == NSS_STR_PARSE_NO_RESULT) {
4989f2fd570SJulian Pullen argp->returnval = 0;
4999f2fd570SJulian Pullen (void) _nss_ldap_endent(be, a);
5009f2fd570SJulian Pullen return ((nss_status_t)NSS_NOTFOUND);
5019f2fd570SJulian Pullen }
5027c478bd9Sstevel@tonic-gate
5039f2fd570SJulian Pullen if (parsestat == NSS_STR_PARSE_ERANGE) {
5049f2fd570SJulian Pullen argp->erange = 1;
5059f2fd570SJulian Pullen (void) _nss_ldap_endent(be, a);
5069f2fd570SJulian Pullen return ((nss_status_t)NSS_NOTFOUND);
5077c478bd9Sstevel@tonic-gate }
5089f2fd570SJulian Pullen if (parsestat == NSS_STR_PARSE_NO_ADDR)
5099f2fd570SJulian Pullen /*
5109f2fd570SJulian Pullen * No IPV4 address is found in the current entry.
5119f2fd570SJulian Pullen * It indicates that the entry contains IPV6 addresses
5129f2fd570SJulian Pullen * only. Instead of calling _nss_ldap_endent to
5139f2fd570SJulian Pullen * terminate, get next entry to continue enumeration.
5149f2fd570SJulian Pullen * If it returned NSS_NOTFOUND here,
5159f2fd570SJulian Pullen * gethostent() would return NULL
5169f2fd570SJulian Pullen * and the enumeration would stop prematurely.
5179f2fd570SJulian Pullen */
5189f2fd570SJulian Pullen goto next_entry;
5199f2fd570SJulian Pullen
5209f2fd570SJulian Pullen if (parsestat == NSS_STR_PARSE_PARSE)
5219f2fd570SJulian Pullen /*
5229f2fd570SJulian Pullen * There has been a parse error. Most likely some
5239f2fd570SJulian Pullen * mandatory attributes are missing. Ignore the error
5249f2fd570SJulian Pullen * and get the next entry. If we returned an error the
5259f2fd570SJulian Pullen * enumeration would stop prematurely.
5269f2fd570SJulian Pullen */
5279f2fd570SJulian Pullen goto next_entry;
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_SUCCESS);
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate
5337c478bd9Sstevel@tonic-gate /*
5347c478bd9Sstevel@tonic-gate *
5357c478bd9Sstevel@tonic-gate */
5367c478bd9Sstevel@tonic-gate
5377c478bd9Sstevel@tonic-gate nss_backend_t *
_nss_ldap_constr(ldap_backend_op_t ops[],int nops,char * tablename,const char ** attrs,fnf ldapobj2str)5387c478bd9Sstevel@tonic-gate _nss_ldap_constr(ldap_backend_op_t ops[], int nops, char *tablename,
539*6a9f1673SMatt Barden const char **attrs, fnf ldapobj2str)
5407c478bd9Sstevel@tonic-gate {
5417c478bd9Sstevel@tonic-gate ldap_backend_ptr be;
5427c478bd9Sstevel@tonic-gate
5437c478bd9Sstevel@tonic-gate #ifdef DEBUG
5447c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n[ldap_common.c: _nss_ldap_constr]\n");
5457c478bd9Sstevel@tonic-gate #endif /* DEBUG */
5467c478bd9Sstevel@tonic-gate
547cb5caa98Sdjl if ((be = (ldap_backend_ptr) calloc(1, sizeof (*be))) == 0)
5487c478bd9Sstevel@tonic-gate return (0);
5497c478bd9Sstevel@tonic-gate be->ops = ops;
5507c478bd9Sstevel@tonic-gate be->nops = (nss_dbop_t)nops;
5517c478bd9Sstevel@tonic-gate be->tablename = (char *)strdup(tablename);
5527c478bd9Sstevel@tonic-gate be->attrs = attrs;
553cb5caa98Sdjl be->ldapobj2str = ldapobj2str;
5547c478bd9Sstevel@tonic-gate
5557c478bd9Sstevel@tonic-gate return ((nss_backend_t *)be);
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate
5587c478bd9Sstevel@tonic-gate
5597c478bd9Sstevel@tonic-gate /*
5607c478bd9Sstevel@tonic-gate *
5617c478bd9Sstevel@tonic-gate */
5627c478bd9Sstevel@tonic-gate int
chophostdomain(char * string,char * host,char * domain)5637c478bd9Sstevel@tonic-gate chophostdomain(char *string, char *host, char *domain)
5647c478bd9Sstevel@tonic-gate {
5657c478bd9Sstevel@tonic-gate char *dot;
5667c478bd9Sstevel@tonic-gate
5677c478bd9Sstevel@tonic-gate if (string == NULL)
5687c478bd9Sstevel@tonic-gate return (-1);
5697c478bd9Sstevel@tonic-gate
5707c478bd9Sstevel@tonic-gate if ((dot = strchr(string, '.')) == NULL) {
5717c478bd9Sstevel@tonic-gate return (0);
5727c478bd9Sstevel@tonic-gate }
5737c478bd9Sstevel@tonic-gate *dot = '\0';
574cb5caa98Sdjl (void) strcpy(host, string);
575cb5caa98Sdjl (void) strcpy(domain, ++dot);
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate return (0);
5787c478bd9Sstevel@tonic-gate }
5797c478bd9Sstevel@tonic-gate
5807c478bd9Sstevel@tonic-gate
5817c478bd9Sstevel@tonic-gate /*
5827c478bd9Sstevel@tonic-gate *
5837c478bd9Sstevel@tonic-gate */
5847c478bd9Sstevel@tonic-gate int
propersubdomain(char * domain,char * subdomain)5857c478bd9Sstevel@tonic-gate propersubdomain(char *domain, char *subdomain)
5867c478bd9Sstevel@tonic-gate {
5877c478bd9Sstevel@tonic-gate int domainlen, subdomainlen;
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate /* sanity check */
5907c478bd9Sstevel@tonic-gate if (domain == NULL || subdomain == NULL)
5917c478bd9Sstevel@tonic-gate return (-1);
5927c478bd9Sstevel@tonic-gate
5937c478bd9Sstevel@tonic-gate domainlen = strlen(domain);
5947c478bd9Sstevel@tonic-gate subdomainlen = strlen(subdomain);
5957c478bd9Sstevel@tonic-gate
5967c478bd9Sstevel@tonic-gate /* is afterdot a substring of domain? */
5977c478bd9Sstevel@tonic-gate if ((strncasecmp(domain, subdomain, subdomainlen)) != 0)
5987c478bd9Sstevel@tonic-gate return (-1);
5997c478bd9Sstevel@tonic-gate
6007c478bd9Sstevel@tonic-gate if (domainlen == subdomainlen)
6017c478bd9Sstevel@tonic-gate return (1);
6027c478bd9Sstevel@tonic-gate
6037c478bd9Sstevel@tonic-gate if (subdomainlen > domainlen)
6047c478bd9Sstevel@tonic-gate return (-1);
6057c478bd9Sstevel@tonic-gate
6067c478bd9Sstevel@tonic-gate if (*(domain + subdomainlen) != '.')
6077c478bd9Sstevel@tonic-gate return (-1);
6087c478bd9Sstevel@tonic-gate
6097c478bd9Sstevel@tonic-gate return (1);
6107c478bd9Sstevel@tonic-gate }
611