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 16static 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 51int 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 62extern 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 74LDAP * 75ldap_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 */ 117int 118open_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 149static pthread_mutex_t ldap_thr_index_mutex = {0}; 150static pthread_t ldap_thr_table[MAX_THREAD_ID] = {0}; 151 152int 153ldap_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 */ 190LDAP * 191ldap_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 */ 251int 252open_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 340int 341establish_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 380LDAP * 381ldap_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 410LDAP * 411ldap_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