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 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 26 */ 27 28 #include <sys/systeminfo.h> 29 #include "ldap_common.h" 30 31 32 #ifdef DEBUG 33 /* 34 * Debugging routine for printing the value of a result 35 * structure 36 */ 37 int 38 printresult(ns_ldap_result_t *result) 39 { 40 int i, j, k; 41 ns_ldap_entry_t *curEntry; 42 43 printf("--------------------------------------\n"); 44 printf("entries_count %d\n", result->entries_count); 45 curEntry = result->entry; 46 for (i = 0; i < result->entries_count; i++) { 47 printf("entry %d has attr_count = %d \n", 48 i, curEntry->attr_count); 49 for (j = 0; j < curEntry->attr_count; j++) { 50 printf("entry %d has attr_pair[%d] = %s \n", 51 i, j, curEntry->attr_pair[j]->attrname); 52 for (k = 0; 53 (k < curEntry->attr_pair[j]->value_count) && 54 (curEntry->attr_pair[j]->attrvalue[k]); 55 k++) 56 printf("entry %d has " 57 "attr_pair[%d]->attrvalue[%d] = %s \n", 58 i, j, k, 59 curEntry->attr_pair[j]->attrvalue[k]); 60 } 61 printf("\n--------------------------------------\n"); 62 curEntry = curEntry->next; 63 } 64 return (1); 65 } 66 #endif 67 68 69 /* 70 * 71 */ 72 73 ns_ldap_attr_t * 74 getattr(ns_ldap_result_t *result, int i) 75 { 76 ns_ldap_entry_t *entry; 77 78 #ifdef DEBUG 79 (void) fprintf(stdout, "\n[ldap_utils.c: getattr]\n"); 80 #endif /* DEBUG */ 81 82 if (result != NULL) { 83 entry = result->entry; 84 } else { 85 return (NULL); 86 } 87 if (result->entries_count == 0) { 88 return (NULL); 89 } else { 90 return (entry->attr_pair[i]); 91 } 92 } 93 94 /* 95 * _get_domain_name() passes the dn one level up from cdn, e.g., 96 * a pointer pointing to "ou= ..." for the cdn's listed below: 97 * dn: cn=hostname+ipHostNumber="109.34.54.76", ou= ... 98 * dn: echo+IpServiceProtocol=udp, ou= ... 99 * to __ns_ldap_dn2domain() to retrieve the domain name associated 100 * with cdn. 101 */ 102 103 char * 104 _get_domain_name(char *cdn) 105 { 106 char **rdns; 107 char *pdn, *domain = NULL; 108 int nrdns; 109 int len = 0; 110 const ns_cred_t *cred = NULL; 111 ns_ldap_error_t *error; 112 113 /* break the cdn into its components */ 114 rdns = ldap_explode_dn(cdn, 0); 115 if (rdns == NULL || *rdns == NULL) 116 return (NULL); 117 118 /* construct parent dn */ 119 for (nrdns = 1; rdns[nrdns]; nrdns++) 120 len += strlen(rdns[nrdns]) + 1; 121 if (len == 0) 122 len = strlen(rdns[0]); 123 pdn = (char *)malloc(len + 1); 124 if (pdn == NULL) { 125 ldap_value_free(rdns); 126 return (NULL); 127 } 128 129 *pdn = '\0'; 130 if (nrdns == 1) 131 (void) strcat(pdn, rdns[0]); 132 else { 133 for (nrdns = 1; rdns[nrdns]; nrdns++) { 134 (void) strcat(pdn, rdns[nrdns]); 135 (void) strcat(pdn, ","); 136 } 137 /* remove the last ',' */ 138 pdn[strlen(pdn) - 1] = '\0'; 139 } 140 /* get domain name */ 141 (void) __ns_ldap_dn2domain(pdn, &domain, cred, &error); 142 143 ldap_value_free(rdns); 144 free(pdn); 145 return (domain); 146 } 147 148 149 /* 150 * "109.34.54.76" -> 109.34.54.76 151 */ 152 153 const char * 154 _strip_quotes(char *ipaddress) 155 { 156 char *cp = (char *)NULL; 157 158 /* look for first " */ 159 if ((cp = strchr(ipaddress, '"')) == NULL) 160 return ((char *)ipaddress); 161 ipaddress++; 162 /* look for last " */ 163 if ((cp = strchr(ipaddress, '"')) == NULL) 164 return ((char *)ipaddress); 165 *cp++ = '\0'; 166 167 return (ipaddress); 168 } 169 170 171 /* 172 * This is a copy of a routine in libnsl/nss/netdir_inet.c. It is 173 * here because /etc/lib/nss_ldap.so.1 cannot call routines in 174 * libnsl. Care should be taken to keep the two copies in sync. 175 */ 176 177 int 178 __nss2herrno(nss_status_t nsstat) 179 { 180 switch (nsstat) { 181 case NSS_SUCCESS: 182 return (0); 183 case NSS_NOTFOUND: 184 return (HOST_NOT_FOUND); 185 case NSS_TRYAGAIN: 186 return (TRY_AGAIN); 187 case NSS_UNAVAIL: 188 default: /* keep gcc happy */ 189 return (NO_RECOVERY); 190 } 191 /* NOTREACHED */ 192 } 193 194 /* 195 * This is a generic filter call back function for 196 * merging the filter from service search descriptor with 197 * an existing search filter. This routine expects userdata 198 * contain a format string with a single %s in it, and will 199 * use the format string with sprintf() to insert the SSD filter. 200 * 201 * This routine is passed to the __ns_ldap_list() or 202 * __ns_ldap_firstEntry() APIs as the filter call back 203 * together with the userdata. For example, 204 * the gethostbyname processing may call __ns_ldap_list() with 205 * "(&(objectClass=ipHost)(cn=sys1))" as filter, this function 206 * as the filter call back, and "(&(%s)(cn=sys1))" as the 207 * userdata, this routine will in turn gets call to produce 208 * "(&(department=sds)(cn=sys1))" as the real search 209 * filter, if the input SSD contains a filter "department=sds". 210 */ 211 int 212 _merge_SSD_filter(const ns_ldap_search_desc_t *desc, 213 char **realfilter, 214 const void *userdata) 215 { 216 int len; 217 char *checker; 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 || userdata == NULL) 229 return (NS_LDAP_INVALID_PARAM); 230 231 /* Parameter check. We only want one %s here, otherwise bail. */ 232 len = 0; /* Reuse 'len' as "Number of %s hits"... */ 233 checker = (char *)userdata; 234 do { 235 checker = strchr(checker, '%'); 236 if (checker != NULL) { 237 if (len > 0 || *(checker + 1) != 's') 238 return (NS_LDAP_INVALID_PARAM); 239 len++; /* Got our %s. */ 240 checker += 2; 241 } else if (len != 1) 242 return (NS_LDAP_INVALID_PARAM); 243 } while (checker != NULL); 244 245 #ifdef DEBUG 246 (void) fprintf(stdout, "\n[userdata: %s]\n", (char *)userdata); 247 (void) fprintf(stdout, "\n[SSD filter: %s]\n", desc->filter); 248 #endif /* DEBUG */ 249 250 len = strlen(userdata) + strlen(desc->filter) + 1; 251 252 *realfilter = (char *)malloc(len); 253 if (*realfilter == NULL) 254 return (NS_LDAP_MEMORY); 255 256 (void) sprintf(*realfilter, (char *)userdata, desc->filter); 257 258 #ifdef DEBUG 259 (void) fprintf(stdout, "\n[new filter: %s]\n", *realfilter); 260 #endif /* DEBUG */ 261 262 return (NS_LDAP_SUCCESS); 263 } 264 265 static char 266 hex_char(int n) 267 { 268 return ("0123456789abcdef"[n & 0xf]); 269 } 270 271 int 272 _ldap_filter_name(char *filter_name, const char *name, int filter_name_size) 273 { 274 char *end = filter_name + filter_name_size; 275 char c; 276 277 for (; *name; name++) { 278 c = *name; 279 switch (c) { 280 case '*': 281 case '(': 282 case ')': 283 case '\\': 284 if (end <= filter_name + 3) 285 return (-1); 286 *filter_name++ = '\\'; 287 *filter_name++ = hex_char(c >> 4); 288 *filter_name++ = hex_char(c & 0xf); 289 break; 290 default: 291 if (end <= filter_name + 1) 292 return (-1); 293 *filter_name++ = c; 294 break; 295 } 296 } 297 if (end <= filter_name) 298 return (-1); 299 *filter_name = '\0'; 300 return (0); 301 } 302