xref: /onnv-gate/usr/src/lib/nsswitch/ldap/common/ldap_utils.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/systeminfo.h>
30*0Sstevel@tonic-gate #include "ldap_common.h"
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate #ifdef DEBUG
34*0Sstevel@tonic-gate /*
35*0Sstevel@tonic-gate  * Debugging routine for printing the value of a result
36*0Sstevel@tonic-gate  * structure
37*0Sstevel@tonic-gate  */
38*0Sstevel@tonic-gate int
printresult(ns_ldap_result_t * result)39*0Sstevel@tonic-gate printresult(ns_ldap_result_t *result)
40*0Sstevel@tonic-gate {
41*0Sstevel@tonic-gate 	int		i, j, k;
42*0Sstevel@tonic-gate 	ns_ldap_entry_t	*curEntry;
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate 	printf("--------------------------------------\n");
45*0Sstevel@tonic-gate 	printf("entries_count %d\n", result->entries_count);
46*0Sstevel@tonic-gate 	curEntry = result->entry;
47*0Sstevel@tonic-gate 	for (i = 0; i < result->entries_count; i++) {
48*0Sstevel@tonic-gate 		printf("entry %d has attr_count = %d \n",
49*0Sstevel@tonic-gate 		    i, curEntry->attr_count);
50*0Sstevel@tonic-gate 		for (j = 0; j < curEntry->attr_count; j++) {
51*0Sstevel@tonic-gate 			printf("entry %d has attr_pair[%d] = %s \n",
52*0Sstevel@tonic-gate 			    i, j, curEntry->attr_pair[j]->attrname);
53*0Sstevel@tonic-gate 			for (k = 0;
54*0Sstevel@tonic-gate 			    (k < curEntry->attr_pair[j]->value_count) &&
55*0Sstevel@tonic-gate 			    (curEntry->attr_pair[j]->attrvalue[k]);
56*0Sstevel@tonic-gate 			    k++)
57*0Sstevel@tonic-gate 				printf("entry %d has "
58*0Sstevel@tonic-gate 				    "attr_pair[%d]->attrvalue[%d] = %s \n",
59*0Sstevel@tonic-gate 				    i, j, k,
60*0Sstevel@tonic-gate 				    curEntry->attr_pair[j]->attrvalue[k]);
61*0Sstevel@tonic-gate 		}
62*0Sstevel@tonic-gate 		printf("\n--------------------------------------\n");
63*0Sstevel@tonic-gate 		curEntry = curEntry->next;
64*0Sstevel@tonic-gate 	}
65*0Sstevel@tonic-gate 	return (1);
66*0Sstevel@tonic-gate }
67*0Sstevel@tonic-gate #endif
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate /*
71*0Sstevel@tonic-gate  *
72*0Sstevel@tonic-gate  */
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate ns_ldap_attr_t *
getattr(ns_ldap_result_t * result,int i)75*0Sstevel@tonic-gate getattr(ns_ldap_result_t *result, int i)
76*0Sstevel@tonic-gate {
77*0Sstevel@tonic-gate 	ns_ldap_entry_t	*entry;
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate #ifdef DEBUG
80*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_utils.c: getattr]\n");
81*0Sstevel@tonic-gate #endif /* DEBUG */
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate 	if (result != NULL) {
84*0Sstevel@tonic-gate 		entry = result->entry;
85*0Sstevel@tonic-gate 	} else {
86*0Sstevel@tonic-gate 		return (NULL);
87*0Sstevel@tonic-gate 	}
88*0Sstevel@tonic-gate 	if (result->entries_count == 0) {
89*0Sstevel@tonic-gate 		return (NULL);
90*0Sstevel@tonic-gate 	} else {
91*0Sstevel@tonic-gate 		return (entry->attr_pair[i]);
92*0Sstevel@tonic-gate 	}
93*0Sstevel@tonic-gate }
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate /*
96*0Sstevel@tonic-gate  * _get_domain_name() passes the dn one level up from cdn, e.g.,
97*0Sstevel@tonic-gate  * a pointer pointing to "ou= ..." for the cdn's listed below:
98*0Sstevel@tonic-gate  * 	dn: cn=hostname+ipHostNumber="109.34.54.76", ou= ...
99*0Sstevel@tonic-gate  *	dn: echo+IpServiceProtocol=udp, ou= ...
100*0Sstevel@tonic-gate  * to __ns_ldap_dn2domain() to retrieve the domain name associated
101*0Sstevel@tonic-gate  * with cdn.
102*0Sstevel@tonic-gate  */
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate char *
_get_domain_name(char * cdn)105*0Sstevel@tonic-gate _get_domain_name(char *cdn)
106*0Sstevel@tonic-gate {
107*0Sstevel@tonic-gate 	char			**rdns;
108*0Sstevel@tonic-gate 	char			*pdn, *domain = NULL;
109*0Sstevel@tonic-gate 	int			nrdns;
110*0Sstevel@tonic-gate 	int			len = 0;
111*0Sstevel@tonic-gate 	const ns_cred_t		*cred = NULL;
112*0Sstevel@tonic-gate 	ns_ldap_error_t		*error;
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate 	/* break the cdn into its components */
115*0Sstevel@tonic-gate 	rdns = ldap_explode_dn(cdn, 0);
116*0Sstevel@tonic-gate 	if (rdns == NULL || *rdns == NULL)
117*0Sstevel@tonic-gate 		return (NULL);
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate 	/* construct parent dn */
120*0Sstevel@tonic-gate 	for (nrdns = 1; rdns[nrdns]; nrdns++)
121*0Sstevel@tonic-gate 		len += strlen(rdns[nrdns]) + 1;
122*0Sstevel@tonic-gate 	if (len == 0)
123*0Sstevel@tonic-gate 		len = strlen(rdns[0]);
124*0Sstevel@tonic-gate 	pdn = (char *)malloc(len + 1);
125*0Sstevel@tonic-gate 	if (pdn == NULL) {
126*0Sstevel@tonic-gate 		ldap_value_free(rdns);
127*0Sstevel@tonic-gate 		return (NULL);
128*0Sstevel@tonic-gate 	}
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 	*pdn = '\0';
131*0Sstevel@tonic-gate 	if (nrdns == 1)
132*0Sstevel@tonic-gate 		(void) strcat(pdn, rdns[0]);
133*0Sstevel@tonic-gate 	else {
134*0Sstevel@tonic-gate 		for (nrdns = 1; rdns[nrdns]; nrdns++) {
135*0Sstevel@tonic-gate 			(void) strcat(pdn, rdns[nrdns]);
136*0Sstevel@tonic-gate 			(void) strcat(pdn, ",");
137*0Sstevel@tonic-gate 		}
138*0Sstevel@tonic-gate 		/* remove the last ',' */
139*0Sstevel@tonic-gate 		pdn[strlen(pdn) - 1] = '\0';
140*0Sstevel@tonic-gate 	}
141*0Sstevel@tonic-gate 	/* get domain name */
142*0Sstevel@tonic-gate 	(void) __ns_ldap_dn2domain(pdn, &domain, cred, &error);
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate 	ldap_value_free(rdns);
145*0Sstevel@tonic-gate 	free(pdn);
146*0Sstevel@tonic-gate 	return (domain);
147*0Sstevel@tonic-gate }
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate 
150*0Sstevel@tonic-gate /*
151*0Sstevel@tonic-gate  * 	"109.34.54.76" -> 109.34.54.76
152*0Sstevel@tonic-gate  */
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate const char *
_strip_quotes(char * ipaddress)155*0Sstevel@tonic-gate _strip_quotes(char *ipaddress)
156*0Sstevel@tonic-gate {
157*0Sstevel@tonic-gate 	char	*cp = (char *)NULL;
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate 	/* look for first " */
160*0Sstevel@tonic-gate 	if ((cp = strchr(ipaddress, '"')) == NULL)
161*0Sstevel@tonic-gate 		return ((char *)ipaddress);
162*0Sstevel@tonic-gate 	ipaddress++;
163*0Sstevel@tonic-gate 	/* look for last " */
164*0Sstevel@tonic-gate 	if ((cp = strchr(ipaddress, '"')) == NULL)
165*0Sstevel@tonic-gate 		return ((char *)ipaddress);
166*0Sstevel@tonic-gate 	*cp++ = '\0';
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate 	return (ipaddress);
169*0Sstevel@tonic-gate }
170*0Sstevel@tonic-gate 
171*0Sstevel@tonic-gate 
172*0Sstevel@tonic-gate /*
173*0Sstevel@tonic-gate  * This is a copy of a routine in libnsl/nss/netdir_inet.c.  It is
174*0Sstevel@tonic-gate  * here because /etc/lib/nss_ldap.so.1 cannot call routines in
175*0Sstevel@tonic-gate  * libnsl.  Care should be taken to keep the two copies in sync.
176*0Sstevel@tonic-gate  */
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate int
__nss2herrno(nss_status_t nsstat)179*0Sstevel@tonic-gate __nss2herrno(nss_status_t nsstat)
180*0Sstevel@tonic-gate {
181*0Sstevel@tonic-gate 	switch (nsstat) {
182*0Sstevel@tonic-gate 		case NSS_SUCCESS:
183*0Sstevel@tonic-gate 			return (0);
184*0Sstevel@tonic-gate 		case NSS_NOTFOUND:
185*0Sstevel@tonic-gate 			return (HOST_NOT_FOUND);
186*0Sstevel@tonic-gate 		case NSS_TRYAGAIN:
187*0Sstevel@tonic-gate 			return (TRY_AGAIN);
188*0Sstevel@tonic-gate 		case NSS_UNAVAIL:
189*0Sstevel@tonic-gate 		default:	/* keep gcc happy */
190*0Sstevel@tonic-gate 			return (NO_RECOVERY);
191*0Sstevel@tonic-gate 	}
192*0Sstevel@tonic-gate 	/* NOTREACHED */
193*0Sstevel@tonic-gate }
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate /*
196*0Sstevel@tonic-gate  * This is a generic filter call back function for
197*0Sstevel@tonic-gate  * merging the filter from service search descriptor with
198*0Sstevel@tonic-gate  * an existing search filter. This routine expects userdata
199*0Sstevel@tonic-gate  * contain a format string with a single %s in it, and will
200*0Sstevel@tonic-gate  * use the format string with sprintf() to insert the SSD filter.
201*0Sstevel@tonic-gate  *
202*0Sstevel@tonic-gate  * This routine is passed to the __ns_ldap_list() or
203*0Sstevel@tonic-gate  * __ns_ldap_firstEntry() APIs as the filter call back
204*0Sstevel@tonic-gate  * together with the userdata. For example,
205*0Sstevel@tonic-gate  * the gethostbyname processing may call __ns_ldap_list() with
206*0Sstevel@tonic-gate  * "(&(objectClass=ipHost)(cn=sys1))" as filter, this function
207*0Sstevel@tonic-gate  * as the filter call back, and "(&(%s)(cn=sys1))" as the
208*0Sstevel@tonic-gate  * userdata, this routine will in turn gets call to produce
209*0Sstevel@tonic-gate  * "(&(department=sds)(cn=sys1))" as the real search
210*0Sstevel@tonic-gate  * filter, if the input SSD contains a filter "department=sds".
211*0Sstevel@tonic-gate  */
212*0Sstevel@tonic-gate int
_merge_SSD_filter(const ns_ldap_search_desc_t * desc,char ** realfilter,const void * userdata)213*0Sstevel@tonic-gate _merge_SSD_filter(const ns_ldap_search_desc_t *desc,
214*0Sstevel@tonic-gate 			char **realfilter,
215*0Sstevel@tonic-gate 			const void *userdata)
216*0Sstevel@tonic-gate {
217*0Sstevel@tonic-gate 	int	len;
218*0Sstevel@tonic-gate 
219*0Sstevel@tonic-gate #ifdef DEBUG
220*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_utils.c: _merge_SSD_filter]\n");
221*0Sstevel@tonic-gate #endif /* DEBUG */
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate 	/* sanity check */
224*0Sstevel@tonic-gate 	if (realfilter == NULL)
225*0Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
226*0Sstevel@tonic-gate 	*realfilter = NULL;
227*0Sstevel@tonic-gate 
228*0Sstevel@tonic-gate 	if (desc == NULL || desc->filter == NULL ||
229*0Sstevel@tonic-gate 			userdata == NULL)
230*0Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate #ifdef DEBUG
233*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[userdata: %s]\n", (char *)userdata);
234*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[SSD filter: %s]\n", desc->filter);
235*0Sstevel@tonic-gate #endif /* DEBUG */
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate 	len = strlen(userdata) + strlen(desc->filter) + 1;
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 	*realfilter = (char *)malloc(len);
240*0Sstevel@tonic-gate 	if (*realfilter == NULL)
241*0Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate 	(void) sprintf(*realfilter, (char *)userdata,
244*0Sstevel@tonic-gate 			desc->filter);
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate #ifdef DEBUG
247*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[new filter: %s]\n", *realfilter);
248*0Sstevel@tonic-gate #endif /* DEBUG */
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
251*0Sstevel@tonic-gate }
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate static char
hex_char(int n)254*0Sstevel@tonic-gate hex_char(int n)
255*0Sstevel@tonic-gate {
256*0Sstevel@tonic-gate 	return ("0123456789abcdef"[n & 0xf]);
257*0Sstevel@tonic-gate }
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate int
_ldap_filter_name(char * filter_name,const char * name,int filter_name_size)260*0Sstevel@tonic-gate _ldap_filter_name(char *filter_name, const char *name, int filter_name_size)
261*0Sstevel@tonic-gate {
262*0Sstevel@tonic-gate 	char *end = filter_name + filter_name_size;
263*0Sstevel@tonic-gate 	char c;
264*0Sstevel@tonic-gate 
265*0Sstevel@tonic-gate 	for (; *name; name++) {
266*0Sstevel@tonic-gate 		c = *name;
267*0Sstevel@tonic-gate 		switch (c) {
268*0Sstevel@tonic-gate 			case '*':
269*0Sstevel@tonic-gate 			case '(':
270*0Sstevel@tonic-gate 			case ')':
271*0Sstevel@tonic-gate 			case '\\':
272*0Sstevel@tonic-gate 				if (end <= filter_name + 3)
273*0Sstevel@tonic-gate 					return (-1);
274*0Sstevel@tonic-gate 				*filter_name++ = '\\';
275*0Sstevel@tonic-gate 				*filter_name++ = hex_char(c >> 4);
276*0Sstevel@tonic-gate 				*filter_name++ = hex_char(c & 0xf);
277*0Sstevel@tonic-gate 				break;
278*0Sstevel@tonic-gate 			default:
279*0Sstevel@tonic-gate 				if (end <= filter_name + 1)
280*0Sstevel@tonic-gate 					return (-1);
281*0Sstevel@tonic-gate 				*filter_name++ = c;
282*0Sstevel@tonic-gate 				break;
283*0Sstevel@tonic-gate 		}
284*0Sstevel@tonic-gate 	}
285*0Sstevel@tonic-gate 	if (end <= filter_name)
286*0Sstevel@tonic-gate 		return (-1);
287*0Sstevel@tonic-gate 	*filter_name = '\0';
288*0Sstevel@tonic-gate 	return (0);
289*0Sstevel@tonic-gate }
290