xref: /titanic_52/usr/src/lib/nsswitch/ldap/common/ldap_utils.c (revision 528b7d8ba791f2da280ff1ddd45c61eb47a2744e)
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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*528b7d8bSRichard Lowe  * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
297c478bd9Sstevel@tonic-gate #include "ldap_common.h"
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #ifdef DEBUG
337c478bd9Sstevel@tonic-gate /*
347c478bd9Sstevel@tonic-gate  * Debugging routine for printing the value of a result
357c478bd9Sstevel@tonic-gate  * structure
367c478bd9Sstevel@tonic-gate  */
377c478bd9Sstevel@tonic-gate int
387c478bd9Sstevel@tonic-gate printresult(ns_ldap_result_t *result)
397c478bd9Sstevel@tonic-gate {
407c478bd9Sstevel@tonic-gate 	int		i, j, k;
417c478bd9Sstevel@tonic-gate 	ns_ldap_entry_t	*curEntry;
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate 	printf("--------------------------------------\n");
447c478bd9Sstevel@tonic-gate 	printf("entries_count %d\n", result->entries_count);
457c478bd9Sstevel@tonic-gate 	curEntry = result->entry;
467c478bd9Sstevel@tonic-gate 	for (i = 0; i < result->entries_count; i++) {
477c478bd9Sstevel@tonic-gate 		printf("entry %d has attr_count = %d \n",
487c478bd9Sstevel@tonic-gate 		    i, curEntry->attr_count);
497c478bd9Sstevel@tonic-gate 		for (j = 0; j < curEntry->attr_count; j++) {
507c478bd9Sstevel@tonic-gate 			printf("entry %d has attr_pair[%d] = %s \n",
517c478bd9Sstevel@tonic-gate 			    i, j, curEntry->attr_pair[j]->attrname);
527c478bd9Sstevel@tonic-gate 			for (k = 0;
537c478bd9Sstevel@tonic-gate 			    (k < curEntry->attr_pair[j]->value_count) &&
547c478bd9Sstevel@tonic-gate 			    (curEntry->attr_pair[j]->attrvalue[k]);
557c478bd9Sstevel@tonic-gate 			    k++)
567c478bd9Sstevel@tonic-gate 				printf("entry %d has "
577c478bd9Sstevel@tonic-gate 				    "attr_pair[%d]->attrvalue[%d] = %s \n",
587c478bd9Sstevel@tonic-gate 				    i, j, k,
597c478bd9Sstevel@tonic-gate 				    curEntry->attr_pair[j]->attrvalue[k]);
607c478bd9Sstevel@tonic-gate 		}
617c478bd9Sstevel@tonic-gate 		printf("\n--------------------------------------\n");
627c478bd9Sstevel@tonic-gate 		curEntry = curEntry->next;
637c478bd9Sstevel@tonic-gate 	}
647c478bd9Sstevel@tonic-gate 	return (1);
657c478bd9Sstevel@tonic-gate }
667c478bd9Sstevel@tonic-gate #endif
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate  *
717c478bd9Sstevel@tonic-gate  */
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate ns_ldap_attr_t *
747c478bd9Sstevel@tonic-gate getattr(ns_ldap_result_t *result, int i)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate 	ns_ldap_entry_t	*entry;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate #ifdef DEBUG
797c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_utils.c: getattr]\n");
807c478bd9Sstevel@tonic-gate #endif /* DEBUG */
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 	if (result != NULL) {
837c478bd9Sstevel@tonic-gate 		entry = result->entry;
847c478bd9Sstevel@tonic-gate 	} else {
857c478bd9Sstevel@tonic-gate 		return (NULL);
867c478bd9Sstevel@tonic-gate 	}
877c478bd9Sstevel@tonic-gate 	if (result->entries_count == 0) {
887c478bd9Sstevel@tonic-gate 		return (NULL);
897c478bd9Sstevel@tonic-gate 	} else {
907c478bd9Sstevel@tonic-gate 		return (entry->attr_pair[i]);
917c478bd9Sstevel@tonic-gate 	}
927c478bd9Sstevel@tonic-gate }
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate /*
957c478bd9Sstevel@tonic-gate  * _get_domain_name() passes the dn one level up from cdn, e.g.,
967c478bd9Sstevel@tonic-gate  * a pointer pointing to "ou= ..." for the cdn's listed below:
977c478bd9Sstevel@tonic-gate  * 	dn: cn=hostname+ipHostNumber="109.34.54.76", ou= ...
987c478bd9Sstevel@tonic-gate  *	dn: echo+IpServiceProtocol=udp, ou= ...
997c478bd9Sstevel@tonic-gate  * to __ns_ldap_dn2domain() to retrieve the domain name associated
1007c478bd9Sstevel@tonic-gate  * with cdn.
1017c478bd9Sstevel@tonic-gate  */
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate char *
1047c478bd9Sstevel@tonic-gate _get_domain_name(char *cdn)
1057c478bd9Sstevel@tonic-gate {
1067c478bd9Sstevel@tonic-gate 	char			**rdns;
1077c478bd9Sstevel@tonic-gate 	char			*pdn, *domain = NULL;
1087c478bd9Sstevel@tonic-gate 	int			nrdns;
1097c478bd9Sstevel@tonic-gate 	int			len = 0;
1107c478bd9Sstevel@tonic-gate 	const ns_cred_t		*cred = NULL;
1117c478bd9Sstevel@tonic-gate 	ns_ldap_error_t		*error;
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	/* break the cdn into its components */
1147c478bd9Sstevel@tonic-gate 	rdns = ldap_explode_dn(cdn, 0);
1157c478bd9Sstevel@tonic-gate 	if (rdns == NULL || *rdns == NULL)
1167c478bd9Sstevel@tonic-gate 		return (NULL);
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	/* construct parent dn */
1197c478bd9Sstevel@tonic-gate 	for (nrdns = 1; rdns[nrdns]; nrdns++)
1207c478bd9Sstevel@tonic-gate 		len += strlen(rdns[nrdns]) + 1;
1217c478bd9Sstevel@tonic-gate 	if (len == 0)
1227c478bd9Sstevel@tonic-gate 		len = strlen(rdns[0]);
1237c478bd9Sstevel@tonic-gate 	pdn = (char *)malloc(len + 1);
1247c478bd9Sstevel@tonic-gate 	if (pdn == NULL) {
1257c478bd9Sstevel@tonic-gate 		ldap_value_free(rdns);
1267c478bd9Sstevel@tonic-gate 		return (NULL);
1277c478bd9Sstevel@tonic-gate 	}
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	*pdn = '\0';
1307c478bd9Sstevel@tonic-gate 	if (nrdns == 1)
1317c478bd9Sstevel@tonic-gate 		(void) strcat(pdn, rdns[0]);
1327c478bd9Sstevel@tonic-gate 	else {
1337c478bd9Sstevel@tonic-gate 		for (nrdns = 1; rdns[nrdns]; nrdns++) {
1347c478bd9Sstevel@tonic-gate 			(void) strcat(pdn, rdns[nrdns]);
1357c478bd9Sstevel@tonic-gate 			(void) strcat(pdn, ",");
1367c478bd9Sstevel@tonic-gate 		}
1377c478bd9Sstevel@tonic-gate 		/* remove the last ',' */
1387c478bd9Sstevel@tonic-gate 		pdn[strlen(pdn) - 1] = '\0';
1397c478bd9Sstevel@tonic-gate 	}
1407c478bd9Sstevel@tonic-gate 	/* get domain name */
1417c478bd9Sstevel@tonic-gate 	(void) __ns_ldap_dn2domain(pdn, &domain, cred, &error);
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	ldap_value_free(rdns);
1447c478bd9Sstevel@tonic-gate 	free(pdn);
1457c478bd9Sstevel@tonic-gate 	return (domain);
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate /*
1507c478bd9Sstevel@tonic-gate  * 	"109.34.54.76" -> 109.34.54.76
1517c478bd9Sstevel@tonic-gate  */
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate const char *
1547c478bd9Sstevel@tonic-gate _strip_quotes(char *ipaddress)
1557c478bd9Sstevel@tonic-gate {
1567c478bd9Sstevel@tonic-gate 	char	*cp = (char *)NULL;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	/* look for first " */
1597c478bd9Sstevel@tonic-gate 	if ((cp = strchr(ipaddress, '"')) == NULL)
1607c478bd9Sstevel@tonic-gate 		return ((char *)ipaddress);
1617c478bd9Sstevel@tonic-gate 	ipaddress++;
1627c478bd9Sstevel@tonic-gate 	/* look for last " */
1637c478bd9Sstevel@tonic-gate 	if ((cp = strchr(ipaddress, '"')) == NULL)
1647c478bd9Sstevel@tonic-gate 		return ((char *)ipaddress);
1657c478bd9Sstevel@tonic-gate 	*cp++ = '\0';
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	return (ipaddress);
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate /*
1727c478bd9Sstevel@tonic-gate  * This is a copy of a routine in libnsl/nss/netdir_inet.c.  It is
1737c478bd9Sstevel@tonic-gate  * here because /etc/lib/nss_ldap.so.1 cannot call routines in
1747c478bd9Sstevel@tonic-gate  * libnsl.  Care should be taken to keep the two copies in sync.
1757c478bd9Sstevel@tonic-gate  */
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate int
1787c478bd9Sstevel@tonic-gate __nss2herrno(nss_status_t nsstat)
1797c478bd9Sstevel@tonic-gate {
1807c478bd9Sstevel@tonic-gate 	switch (nsstat) {
1817c478bd9Sstevel@tonic-gate 		case NSS_SUCCESS:
1827c478bd9Sstevel@tonic-gate 			return (0);
1837c478bd9Sstevel@tonic-gate 		case NSS_NOTFOUND:
1847c478bd9Sstevel@tonic-gate 			return (HOST_NOT_FOUND);
1857c478bd9Sstevel@tonic-gate 		case NSS_TRYAGAIN:
1867c478bd9Sstevel@tonic-gate 			return (TRY_AGAIN);
1877c478bd9Sstevel@tonic-gate 		case NSS_UNAVAIL:
1887c478bd9Sstevel@tonic-gate 		default:	/* keep gcc happy */
1897c478bd9Sstevel@tonic-gate 			return (NO_RECOVERY);
1907c478bd9Sstevel@tonic-gate 	}
1917c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate /*
1957c478bd9Sstevel@tonic-gate  * This is a generic filter call back function for
1967c478bd9Sstevel@tonic-gate  * merging the filter from service search descriptor with
1977c478bd9Sstevel@tonic-gate  * an existing search filter. This routine expects userdata
1987c478bd9Sstevel@tonic-gate  * contain a format string with a single %s in it, and will
1997c478bd9Sstevel@tonic-gate  * use the format string with sprintf() to insert the SSD filter.
2007c478bd9Sstevel@tonic-gate  *
2017c478bd9Sstevel@tonic-gate  * This routine is passed to the __ns_ldap_list() or
2027c478bd9Sstevel@tonic-gate  * __ns_ldap_firstEntry() APIs as the filter call back
2037c478bd9Sstevel@tonic-gate  * together with the userdata. For example,
2047c478bd9Sstevel@tonic-gate  * the gethostbyname processing may call __ns_ldap_list() with
2057c478bd9Sstevel@tonic-gate  * "(&(objectClass=ipHost)(cn=sys1))" as filter, this function
2067c478bd9Sstevel@tonic-gate  * as the filter call back, and "(&(%s)(cn=sys1))" as the
2077c478bd9Sstevel@tonic-gate  * userdata, this routine will in turn gets call to produce
2087c478bd9Sstevel@tonic-gate  * "(&(department=sds)(cn=sys1))" as the real search
2097c478bd9Sstevel@tonic-gate  * filter, if the input SSD contains a filter "department=sds".
2107c478bd9Sstevel@tonic-gate  */
2117c478bd9Sstevel@tonic-gate int
2127c478bd9Sstevel@tonic-gate _merge_SSD_filter(const ns_ldap_search_desc_t *desc,
2137c478bd9Sstevel@tonic-gate 			char **realfilter,
2147c478bd9Sstevel@tonic-gate 			const void *userdata)
2157c478bd9Sstevel@tonic-gate {
2167c478bd9Sstevel@tonic-gate 	int	len;
217*528b7d8bSRichard Lowe 	char *checker;
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate #ifdef DEBUG
2207c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[ldap_utils.c: _merge_SSD_filter]\n");
2217c478bd9Sstevel@tonic-gate #endif /* DEBUG */
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	/* sanity check */
2247c478bd9Sstevel@tonic-gate 	if (realfilter == NULL)
2257c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
2267c478bd9Sstevel@tonic-gate 	*realfilter = NULL;
2277c478bd9Sstevel@tonic-gate 
228*528b7d8bSRichard Lowe 	if (desc == NULL || desc->filter == NULL || userdata == NULL)
2297c478bd9Sstevel@tonic-gate 		return (NS_LDAP_INVALID_PARAM);
2307c478bd9Sstevel@tonic-gate 
231*528b7d8bSRichard Lowe 	/* Parameter check.  We only want one %s here, otherwise bail. */
232*528b7d8bSRichard Lowe 	len = 0;	/* Reuse 'len' as "Number of %s hits"... */
233*528b7d8bSRichard Lowe 	checker = (char *)userdata;
234*528b7d8bSRichard Lowe 	do {
235*528b7d8bSRichard Lowe 		checker = strchr(checker, '%');
236*528b7d8bSRichard Lowe 		if (checker != NULL) {
237*528b7d8bSRichard Lowe 			if (len > 0 || *(checker + 1) != 's')
238*528b7d8bSRichard Lowe 				return (NS_LDAP_INVALID_PARAM);
239*528b7d8bSRichard Lowe 			len++;	/* Got our %s. */
240*528b7d8bSRichard Lowe 			checker += 2;
241*528b7d8bSRichard Lowe 		} else if (len != 1)
242*528b7d8bSRichard Lowe 			return (NS_LDAP_INVALID_PARAM);
243*528b7d8bSRichard Lowe 	} while (checker != NULL);
244*528b7d8bSRichard Lowe 
2457c478bd9Sstevel@tonic-gate #ifdef DEBUG
2467c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[userdata: %s]\n", (char *)userdata);
2477c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[SSD filter: %s]\n", desc->filter);
2487c478bd9Sstevel@tonic-gate #endif /* DEBUG */
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	len = strlen(userdata) + strlen(desc->filter) + 1;
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	*realfilter = (char *)malloc(len);
2537c478bd9Sstevel@tonic-gate 	if (*realfilter == NULL)
2547c478bd9Sstevel@tonic-gate 		return (NS_LDAP_MEMORY);
2557c478bd9Sstevel@tonic-gate 
256*528b7d8bSRichard Lowe 	(void) sprintf(*realfilter, (char *)userdata, desc->filter);
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate #ifdef DEBUG
2597c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[new filter: %s]\n", *realfilter);
2607c478bd9Sstevel@tonic-gate #endif /* DEBUG */
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	return (NS_LDAP_SUCCESS);
2637c478bd9Sstevel@tonic-gate }
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate static char
2667c478bd9Sstevel@tonic-gate hex_char(int n)
2677c478bd9Sstevel@tonic-gate {
2687c478bd9Sstevel@tonic-gate 	return ("0123456789abcdef"[n & 0xf]);
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate int
2727c478bd9Sstevel@tonic-gate _ldap_filter_name(char *filter_name, const char *name, int filter_name_size)
2737c478bd9Sstevel@tonic-gate {
2747c478bd9Sstevel@tonic-gate 	char *end = filter_name + filter_name_size;
2757c478bd9Sstevel@tonic-gate 	char c;
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	for (; *name; name++) {
2787c478bd9Sstevel@tonic-gate 		c = *name;
2797c478bd9Sstevel@tonic-gate 		switch (c) {
2807c478bd9Sstevel@tonic-gate 			case '*':
2817c478bd9Sstevel@tonic-gate 			case '(':
2827c478bd9Sstevel@tonic-gate 			case ')':
2837c478bd9Sstevel@tonic-gate 			case '\\':
2847c478bd9Sstevel@tonic-gate 				if (end <= filter_name + 3)
2857c478bd9Sstevel@tonic-gate 					return (-1);
2867c478bd9Sstevel@tonic-gate 				*filter_name++ = '\\';
2877c478bd9Sstevel@tonic-gate 				*filter_name++ = hex_char(c >> 4);
2887c478bd9Sstevel@tonic-gate 				*filter_name++ = hex_char(c & 0xf);
2897c478bd9Sstevel@tonic-gate 				break;
2907c478bd9Sstevel@tonic-gate 			default:
2917c478bd9Sstevel@tonic-gate 				if (end <= filter_name + 1)
2927c478bd9Sstevel@tonic-gate 					return (-1);
2937c478bd9Sstevel@tonic-gate 				*filter_name++ = c;
2947c478bd9Sstevel@tonic-gate 				break;
2957c478bd9Sstevel@tonic-gate 		}
2967c478bd9Sstevel@tonic-gate 	}
2977c478bd9Sstevel@tonic-gate 	if (end <= filter_name)
2987c478bd9Sstevel@tonic-gate 		return (-1);
2997c478bd9Sstevel@tonic-gate 	*filter_name = '\0';
3007c478bd9Sstevel@tonic-gate 	return (0);
3017c478bd9Sstevel@tonic-gate }
302