1 /*
2 * Copyright (c) 1995-2001 by Sun Microsystems, Inc.
3 * All rights reserved.
4 */
5
6 #pragma ident "%Z%%M% %I% %E% SMI"
7
8 /*
9 * Copyright (c) 1995 Regents of the University of Michigan.
10 * All rights reserved.
11 *
12 * open.c
13 */
14
15 #ifndef lint
16 static char copyright[] = "@(#) Copyright (c) 1995 Regents of the "
17 "University of Michigan.\nAll rights reserved.\n";
18 #endif
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h> /* calloc(), free(), atoi() for Solaris */
23 #include <locale.h>
24 #include <thread.h>
25
26 #ifdef MACOS
27 #include <stdlib.h>
28 #include "macos.h"
29 #endif /* MACOS */
30
31 #if defined(DOS) || defined(_WIN32)
32 #include "msdos.h"
33 #include <stdlib.h>
34 #endif /* DOS */
35
36 #if !defined(MACOS) && !defined(DOS) && !defined(_WIN32)
37 #include <sys/time.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #ifndef VMS
41 #include <sys/param.h>
42 #endif
43 #include <netinet/in.h>
44 #endif
45 #include "lber.h"
46 #include "ldap.h"
47 #include "ldap-private.h"
48 #include "ldap-int.h"
49
50 #ifdef LDAP_DEBUG
51 int ldap_debug;
52 #endif
53
54 #ifndef INADDR_LOOPBACK
55 #define INADDR_LOOPBACK ((unsigned int) 0x7f000001)
56 #endif
57
58 #ifndef MAXHOSTNAMELEN
59 #define MAXHOSTNAMELEN 64
60 #endif
61
62 extern int thr_kill(thread_t, int);
63
64 /*
65 * ldap_open - initialize and connect to an ldap server. A magic cookie to
66 * be used for future communication is returned on success, NULL on failure.
67 * "host" may be a space-separated list of hosts or IP addresses
68 *
69 * Example:
70 * LDAP *ld;
71 * ld = ldap_open( hostname, port );
72 */
73
74 LDAP *
ldap_open(char * host,int port)75 ldap_open(char *host, int port)
76 {
77 LDAP *ld;
78 int err;
79
80 if ((ld = ldap_init(host, port)) == NULL) {
81 return (NULL);
82 }
83
84 Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 113,
85 "ldap_open (after ldap_init)\n"), 0, 0, 0);
86
87 #ifdef _REENTRANT
88 LOCK_LDAP(ld);
89 #endif
90 if ((err = open_default_ldap_connection(ld)) != LDAP_SUCCESS) {
91 #ifdef _REENTRANT
92 UNLOCK_LDAP(ld);
93 #endif
94 ldap_ld_free(ld, 0);
95 Debug(LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1275,
96 "ldap_open failed, %s\n"),
97 ldap_err2string(err), 0, 0);
98 return (NULL);
99 }
100
101 Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 194,
102 "ldap_open successful, ld_host is %s\n"),
103 (ld->ld_host == NULL) ? "(null)" : ld->ld_host, 0, 0);
104 #ifdef _REENTRANT
105 UNLOCK_LDAP(ld);
106 #endif
107 return (ld);
108
109 }
110
111 /*
112 * Open the default connection
113 * ld->ld_defconn MUST be null when calling this function,
114 * ie the connection was never established
115 * ld should be LOCKed before calling this function
116 */
117 int
open_default_ldap_connection(LDAP * ld)118 open_default_ldap_connection(LDAP *ld)
119 {
120 LDAPServer *srv;
121 int err;
122
123 if ((srv = (LDAPServer *)calloc(1, sizeof (LDAPServer))) ==
124 NULL || (ld->ld_defhost != NULL && (srv->lsrv_host =
125 strdup(ld->ld_defhost)) == NULL)) {
126 return (LDAP_NO_MEMORY);
127 }
128 srv->lsrv_port = ld->ld_defport;
129
130 if ((ld->ld_defconn = new_connection(ld, &srv, 1, 1, 0)) ==
131 NULL) {
132 err = ld->ld_errno;
133 Debug(LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1276,
134 "Default connection to ldap server %s couldn't be "
135 "opened (%d)\n"), ld->ld_defhost, err, 0);
136
137 if (ld->ld_defhost != NULL)
138 free(srv->lsrv_host);
139 free((char *)srv);
140 return (err);
141 }
142
143 /* so it never gets closed/freed */
144 ++ld->ld_defconn->lconn_refcnt;
145
146 return (LDAP_SUCCESS);
147 }
148
149 static pthread_mutex_t ldap_thr_index_mutex = {0};
150 static pthread_t ldap_thr_table[MAX_THREAD_ID] = {0};
151
152 int
ldap_thr_index()153 ldap_thr_index()
154 {
155 int i = 0;
156 int free = 0;
157 pthread_t cur = thr_self();
158 for (i = 1; i < MAX_THREAD_ID; ++i) {
159 if (ldap_thr_table[i] == cur) {
160 return (i);
161 } /* end if */
162 } /* end for */
163 /*
164 * not in the table, allocate a new entry
165 */
166 pthread_mutex_lock(&ldap_thr_index_mutex);
167 for (i = 1; i < MAX_THREAD_ID; ++i) {
168 if (ldap_thr_table[i] == 0 ||
169 thr_kill(ldap_thr_table[i], 0) != 0) {
170 ldap_thr_table[i] = cur;
171 pthread_mutex_unlock(&ldap_thr_index_mutex);
172 return (i);
173 } /* end if */
174 } /* end for */
175 pthread_mutex_unlock(&ldap_thr_index_mutex);
176 /* if table is full, return the first entry, so that it */
177 /* doesn't core dump */
178 return (0);
179 }
180
181 /*
182 * ldap_init - initialize the LDAP library. A magic cookie to be used for
183 * future communication is returned on success, NULL on failure.
184 * "defhost" may be a space-separated list of hosts or IP addresses
185 *
186 * Example:
187 * LDAP *ld;
188 * ld = ldap_init( default_hostname, default_port );
189 */
190 LDAP *
ldap_init(char * defhost,int defport)191 ldap_init(char *defhost, int defport)
192 {
193 LDAP *ld;
194 char *locale;
195
196 locale = setlocale(LC_ALL, "");
197 i18n_catopen("sdserver");
198
199 Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 195,
200 "ldap_init\n"), 0, 0, 0);
201
202
203 if ((ld = (LDAP *) calloc(1, sizeof (LDAP))) == NULL) {
204 return (NULL);
205 }
206
207 #ifdef _REENTRANT
208 pthread_mutex_init(&ld->ld_ldap_mutex, DEFAULT_TYPE);
209 pthread_mutex_init(&ld->ld_response_mutex, DEFAULT_TYPE);
210 pthread_mutex_init(&ld->ld_poll_mutex, DEFAULT_TYPE);
211 ld->ld_lockthread = 0;
212 #endif
213
214 if ((ld->ld_selectinfo = new_select_info()) == NULL) {
215 free((char *)ld);
216 return (NULL);
217 }
218 ld->ld_follow_referral = 1;
219
220 /*
221 * default to localhost when hostname is not specified
222 * or if null string is passed as hostname
223 */
224
225 if ((defhost != NULL) && (*defhost != NULL) &&
226 (ld->ld_defhost = strdup(defhost)) == NULL) {
227 free_select_info(ld->ld_selectinfo);
228 free((char *)ld);
229 return (NULL);
230 }
231
232 ld->ld_defport = (defport == 0) ? LDAP_PORT : defport;
233 ld->ld_version = LDAP_VERSION;
234 ld->ld_lberoptions = LBER_USE_DER;
235 ld->ld_refhoplimit = LDAP_DEFAULT_REFHOPLIMIT;
236 ld->ld_connect_timeout = LDAP_X_IO_TIMEOUT_NO_TIMEOUT;
237
238 #if defined(STR_TRANSLATION) && defined(LDAP_DEFAULT_CHARSET)
239 ld->ld_lberoptions |= LBER_TRANSLATE_STRINGS;
240 #if LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET
241 ldap_set_string_translators(ld, ldap_8859_to_t61,
242 ldap_t61_to_8859);
243 #endif /* LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET */
244 #endif /* STR_TRANSLATION && LDAP_DEFAULT_CHARSET */
245
246 return (ld);
247 }
248
249
250 /* ARGSUSED */
251 int
open_ldap_connection(LDAP * ld,Sockbuf * sb,char * host,int defport,char ** krbinstancep,int async)252 open_ldap_connection(LDAP *ld, Sockbuf *sb, char *host, int defport,
253 char **krbinstancep, int async)
254 {
255 int rc, port;
256 char *p, *q, *r;
257 char *curhost, hostname[ 2*MAXHOSTNAMELEN ];
258 int bindTimeout;
259
260 Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 196,
261 "open_ldap_connection\n"), 0, 0, 0);
262
263 defport = htons(defport);
264 bindTimeout = ld->ld_connect_timeout;
265
266 if (host != NULL) {
267 for (p = host; p != NULL && *p != '\0'; p = q) {
268 if ((q = strchr(p, ' ')) != NULL) {
269 (void) strncpy(hostname, p, q - p);
270 hostname[ q - p ] = '\0';
271 curhost = hostname;
272 while (*q == ' ') {
273 ++q;
274 }
275 } else {
276 /* avoid copy if possible */
277 curhost = p;
278 q = NULL;
279 }
280
281 if ((r = strchr(curhost, ':')) != NULL) {
282 if (curhost != hostname) {
283 /* now copy */
284 (void) strcpy(hostname, curhost);
285 r = hostname + (r - curhost);
286 curhost = hostname;
287 }
288 *r++ = '\0';
289 port = htons((short)atoi(r));
290 } else {
291 port = defport;
292 }
293
294 if ((rc = connect_to_host(sb, curhost, 0,
295 port, async, bindTimeout)) != -1) {
296 break;
297 }
298 }
299 } else {
300 rc = connect_to_host(sb, NULL, htonl(INADDR_LOOPBACK),
301 defport, async, bindTimeout);
302 }
303
304 if (rc == -1) {
305 return (rc);
306 }
307
308 if (krbinstancep != NULL) {
309 #ifdef KERBEROS
310 if ((*krbinstancep = host_connected_to(sb)) != NULL &&
311 (p = strchr(*krbinstancep, '.')) != NULL) {
312 *p = '\0';
313 }
314 #else /* KERBEROS */
315 krbinstancep = NULL;
316 #endif /* KERBEROS */
317 }
318
319 return (0);
320 }
321
322 /*
323 * ldap_ssl_open - initialize and connect to an ssl secured ldap
324 * server. First ldap_open() is called and then ssl is layered on top
325 * of the socket. A magic cookie to be used for future communication
326 * is returned on success, NULL on failure. "host" may be a
327 * space-separated list of hosts or IP addresses. CAfile and CApath
328 * are used first time through, subsequent calls are ignored and can
329 * be NULL.
330 *
331 * Example:
332 * LDAP *ld;
333 * ld = ldap_ssl_open( hostname, port, key );
334 */
335
336 #ifdef LDAP_SSL
337
338 #include "security/ssl.h"
339
340 int
establish_ssl_connection(LDAP * ld)341 establish_ssl_connection(LDAP *ld)
342 {
343 SSL *ssl = NULL; /* The Client's SSL connection */
344
345 /*
346 * Creates a new SSL connection. This holds information
347 * pertinent to this
348 * connection.
349 */
350 if ((ssl = SSL_new()) == NULL) {
351 Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 198,
352 "SSL_new() failed: %s\n"),
353 SSL_strerr(SSL_errno(ssl)), 0, 0);
354 return (-1);
355 }
356
357 /* if keyname is non-null, set ssl keypackage name from it */
358 if (ld->ld_ssl_key != NULL) {
359 if (SSL_set_userid(ssl, ld->ld_ssl_key, 0) == NULL) {
360 Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1,
361 199, "SSL_set_userid() failed: %s\n"),
362 SSL_strerr(SSL_errno(ssl)), 0, 0);
363 return (-1);
364 }
365 }
366
367 /* Start the SSL connection */
368 if (SSL_connect(ssl, ld->ld_sb.sb_sd) < 1) {
369 Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 200,
370 "SSL_connect() failed: %s\n"),
371 SSL_strerr(SSL_errno(ssl)), 0, 0);
372 return (-1);
373 }
374
375 ld->ld_sb.sb_ssl = ssl;
376 return (0);
377 }
378
379
380 LDAP *
ldap_ssl_open(char * host,int port,char * keyname)381 ldap_ssl_open(char *host, int port, char *keyname)
382 {
383 LDAP *ld;
384 int rval;
385
386
387 if (port == 0)
388 port = SSL_LDAP_PORT;
389
390 ld = ldap_open(host, port);
391
392 Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 197,
393 "ldap_ssl_open (after ldap_open)\n"), 0, 0, 0);
394
395 if (ld == NULL)
396 return (NULL);
397
398 ld->ld_use_ssl = 1;
399 if (keyname)
400 ld->ld_ssl_key = strdup(keyname);
401
402 if (establish_ssl_connection(ld) != 0) {
403 ldap_ld_free(ld, 1);
404 return (NULL);
405 }
406
407 return (ld);
408 }
409
410 LDAP *
ldap_ssl_init(char * defhost,int defport,char * keyname)411 ldap_ssl_init(char *defhost, int defport, char *keyname)
412 {
413 LDAP *ld;
414 int rval;
415
416
417 if (defport == 0)
418 defport = SSL_LDAP_PORT;
419
420 ld = ldap_init(defhost, defport);
421
422 Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 197,
423 "ldap_ssl_open (after ldap_open)\n"), 0, 0, 0);
424
425 if (ld == NULL)
426 return (NULL);
427 ld->ld_use_ssl = 1;
428 ld->ld_ssl_key = strdup(keyname);
429
430 return (ld);
431 }
432
433 #endif /* LDAP_SSL */
434