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