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 */
38int
39printresult(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
74ns_ldap_attr_t *
75getattr(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
104char *
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
154const 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
178int
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 */
212int
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
253static char
254hex_char(int n)
255{
256	return ("0123456789abcdef"[n & 0xf]);
257}
258
259int
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