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