xref: /titanic_41/usr/src/lib/nsswitch/ldap/common/ldap_utils.c (revision d7ddd43c70ebe97a1118be9f663a54d0d1d89fe6)
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