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
printresult(ns_ldap_result_t * result)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 *
getattr(ns_ldap_result_t * result,int i)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 *
_get_domain_name(char * cdn)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 *
_strip_quotes(char * ipaddress)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
__nss2herrno(nss_status_t nsstat)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
_merge_SSD_filter(const ns_ldap_search_desc_t * desc,char ** realfilter,const void * userdata)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
hex_char(int n)266 hex_char(int n)
267 {
268 return ("0123456789abcdef"[n & 0xf]);
269 }
270
271 int
_ldap_filter_name(char * filter_name,const char * name,int filter_name_size)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