1 /* 2 * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 /* 9 * The contents of this file are subject to the Netscape Public 10 * License Version 1.1 (the "License"); you may not use this file 11 * except in compliance with the License. You may obtain a copy of 12 * the License at http://www.mozilla.org/NPL/ 13 * 14 * Software distributed under the License is distributed on an "AS 15 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 16 * implied. See the License for the specific language governing 17 * rights and limitations under the License. 18 * 19 * The Original Code is Mozilla Communicator client code, released 20 * March 31, 1998. 21 * 22 * The Initial Developer of the Original Code is Netscape 23 * Communications Corporation. Portions created by Netscape are 24 * Copyright (C) 1998-1999 Netscape Communications Corporation. All 25 * Rights Reserved. 26 * 27 * Contributor(s): 28 */ 29 #include "ldap-int.h" 30 31 #define LDAP_GET_BITOPT( ld, bit ) \ 32 ((ld)->ld_options & bit ) != 0 ? 1 : 0 33 34 static int nsldapi_get_api_info( LDAPAPIInfo *aip ); 35 static int nsldapi_get_feature_info( LDAPAPIFeatureInfo *fip ); 36 37 38 int 39 LDAP_CALL 40 ldap_get_option( LDAP *ld, int option, void *optdata ) 41 { 42 int rc = 0; 43 44 if ( !nsldapi_initialized ) { 45 nsldapi_initialize_defaults(); 46 } 47 48 /* 49 * optdata MUST be a valid pointer... 50 */ 51 if (NULL == optdata) 52 { 53 return(LDAP_PARAM_ERROR); 54 } 55 /* 56 * process global options (not associated with an LDAP session handle) 57 */ 58 if ( option == LDAP_OPT_MEMALLOC_FN_PTRS ) { 59 /* struct copy */ 60 *((struct ldap_memalloc_fns *)optdata) = nsldapi_memalloc_fns; 61 return( 0 ); 62 } 63 64 if ( option == LDAP_OPT_API_INFO ) { 65 rc = nsldapi_get_api_info( (LDAPAPIInfo *)optdata ); 66 if ( rc != LDAP_SUCCESS ) { 67 if ( ld != NULL ) { 68 LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); 69 } 70 return( -1 ); 71 } 72 return( 0 ); 73 } 74 /* 75 * LDAP_OPT_DEBUG_LEVEL is global 76 */ 77 if (LDAP_OPT_DEBUG_LEVEL == option) 78 { 79 #ifdef LDAP_DEBUG 80 *((int *) optdata) = ldap_debug; 81 #endif /* LDAP_DEBUG */ 82 return ( 0 ); 83 } 84 85 /* 86 * if ld is NULL, arrange to return options from our default settings 87 */ 88 if ( ld == NULL ) { 89 ld = &nsldapi_ld_defaults; 90 } 91 92 if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { 93 return( -1 ); /* punt */ 94 } 95 96 97 if (ld != &nsldapi_ld_defaults) 98 LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); 99 switch( option ) { 100 #ifdef LDAP_DNS 101 case LDAP_OPT_DNS: 102 *((int *) optdata) = LDAP_GET_BITOPT( ld, LDAP_BITOPT_DNS ); 103 break; 104 #endif 105 106 case LDAP_OPT_REFERRALS: 107 *((int *) optdata) = 108 LDAP_GET_BITOPT( ld, LDAP_BITOPT_REFERRALS ); 109 break; 110 111 #ifdef LDAP_SSLIO_HOOKS 112 case LDAP_OPT_SSL: 113 *((int *) optdata) = LDAP_GET_BITOPT( ld, LDAP_BITOPT_SSL ); 114 break; 115 #endif 116 case LDAP_OPT_RESTART: 117 *((int *) optdata) = LDAP_GET_BITOPT( ld, LDAP_BITOPT_RESTART ); 118 break; 119 120 case LDAP_OPT_RECONNECT: 121 *((int *) optdata) = 122 LDAP_GET_BITOPT( ld, LDAP_BITOPT_RECONNECT ); 123 break; 124 125 #ifdef LDAP_ASYNC_IO 126 case LDAP_OPT_ASYNC_CONNECT: 127 *((int *) optdata) = 128 LDAP_GET_BITOPT( ld, LDAP_BITOPT_ASYNC ); 129 break; 130 #endif /* LDAP_ASYNC_IO */ 131 132 /* stuff in the sockbuf */ 133 case LDAP_X_OPT_SOCKBUF: 134 *((Sockbuf **) optdata) = ld->ld_sbp; 135 break; 136 case LDAP_OPT_DESC: 137 if ( ber_sockbuf_get_option( ld->ld_sbp, 138 LBER_SOCKBUF_OPT_DESC, optdata ) != 0 ) { 139 LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL ); 140 rc = -1; 141 } 142 break; 143 144 /* fields in the LDAP structure */ 145 case LDAP_OPT_DEREF: 146 *((int *) optdata) = ld->ld_deref; 147 break; 148 case LDAP_OPT_SIZELIMIT: 149 *((int *) optdata) = ld->ld_sizelimit; 150 break; 151 case LDAP_OPT_TIMELIMIT: 152 *((int *) optdata) = ld->ld_timelimit; 153 break; 154 case LDAP_OPT_REFERRAL_HOP_LIMIT: 155 *((int *) optdata) = ld->ld_refhoplimit; 156 break; 157 case LDAP_OPT_PROTOCOL_VERSION: 158 *((int *) optdata) = ld->ld_version; 159 break; 160 case LDAP_OPT_SERVER_CONTROLS: 161 /* fall through */ 162 case LDAP_OPT_CLIENT_CONTROLS: 163 *((LDAPControl ***)optdata) = NULL; 164 /* nsldapi_dup_controls returns -1 and sets lderrno on error */ 165 rc = nsldapi_dup_controls( ld, (LDAPControl ***)optdata, 166 ( option == LDAP_OPT_SERVER_CONTROLS ) ? 167 ld->ld_servercontrols : ld->ld_clientcontrols ); 168 break; 169 170 /* rebind proc */ 171 case LDAP_OPT_REBIND_FN: 172 *((LDAP_REBINDPROC_CALLBACK **) optdata) = ld->ld_rebind_fn; 173 break; 174 case LDAP_OPT_REBIND_ARG: 175 *((void **) optdata) = ld->ld_rebind_arg; 176 break; 177 178 #ifdef LDAP_SSLIO_HOOKS 179 /* i/o function pointers */ 180 case LDAP_OPT_IO_FN_PTRS: 181 if ( ld->ld_io_fns_ptr == NULL ) { 182 memset( optdata, 0, sizeof( struct ldap_io_fns )); 183 } else { 184 /* struct copy */ 185 *((struct ldap_io_fns *)optdata) = *(ld->ld_io_fns_ptr); 186 } 187 break; 188 189 /* extended i/o function pointers */ 190 case LDAP_X_OPT_EXTIO_FN_PTRS: 191 if ( ((struct ldap_x_ext_io_fns *) optdata)->lextiof_size == LDAP_X_EXTIO_FNS_SIZE_REV0) { 192 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_close = ld->ld_extclose_fn; 193 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_connect = ld->ld_extconnect_fn; 194 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_read = ld->ld_extread_fn; 195 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_write = ld->ld_extwrite_fn; 196 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_poll = ld->ld_extpoll_fn; 197 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_newhandle = ld->ld_extnewhandle_fn; 198 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_disposehandle = ld->ld_extdisposehandle_fn; 199 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_session_arg = ld->ld_ext_session_arg; 200 } else if ( ((struct ldap_x_ext_io_fns *) optdata)->lextiof_size == 201 LDAP_X_EXTIO_FNS_SIZE ) { 202 /* struct copy */ 203 *((struct ldap_x_ext_io_fns *) optdata) = ld->ld_ext_io_fns; 204 } else { 205 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); 206 rc = -1; 207 } 208 break; 209 #endif /* LDAP_SSLIO_HOOKS */ 210 211 /* thread function pointers */ 212 case LDAP_OPT_THREAD_FN_PTRS: 213 /* struct copy */ 214 *((struct ldap_thread_fns *) optdata) = ld->ld_thread; 215 break; 216 217 /* DNS function pointers */ 218 case LDAP_OPT_DNS_FN_PTRS: 219 /* struct copy */ 220 *((struct ldap_dns_fns *) optdata) = ld->ld_dnsfn; 221 break; 222 223 /* cache function pointers */ 224 case LDAP_OPT_CACHE_FN_PTRS: 225 /* struct copy */ 226 *((struct ldap_cache_fns *) optdata) = ld->ld_cache; 227 break; 228 case LDAP_OPT_CACHE_STRATEGY: 229 *((int *) optdata) = ld->ld_cache_strategy; 230 break; 231 case LDAP_OPT_CACHE_ENABLE: 232 *((int *) optdata) = ld->ld_cache_on; 233 break; 234 235 case LDAP_OPT_ERROR_NUMBER: 236 *((int *) optdata) = LDAP_GET_LDERRNO( ld, NULL, NULL ); 237 break; 238 239 case LDAP_OPT_ERROR_STRING: 240 (void)LDAP_GET_LDERRNO( ld, NULL, (char **)optdata ); 241 *((char **) optdata) = nsldapi_strdup( *((char **) optdata )); 242 break; 243 244 case LDAP_OPT_MATCHED_DN: 245 (void)LDAP_GET_LDERRNO( ld, (char **)optdata, NULL ); 246 *((char **) optdata) = nsldapi_strdup( *((char **) optdata )); 247 break; 248 249 case LDAP_OPT_PREFERRED_LANGUAGE: 250 if ( NULL != ld->ld_preferred_language ) { 251 *((char **) optdata) = 252 nsldapi_strdup(ld->ld_preferred_language); 253 } else { 254 *((char **) optdata) = NULL; 255 } 256 break; 257 258 case LDAP_OPT_API_FEATURE_INFO: 259 rc = nsldapi_get_feature_info( (LDAPAPIFeatureInfo *)optdata ); 260 if ( rc != LDAP_SUCCESS ) { 261 LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); 262 rc = -1; 263 } 264 break; 265 266 case LDAP_OPT_HOST_NAME: 267 *((char **) optdata) = nsldapi_strdup( ld->ld_defhost ); 268 break; 269 270 case LDAP_X_OPT_CONNECT_TIMEOUT: 271 *((int *) optdata) = ld->ld_connect_timeout; 272 break; 273 274 #ifdef LDAP_SASLIO_HOOKS 275 /* SASL options */ 276 case LDAP_OPT_X_SASL_MECH: 277 *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_mech); 278 break; 279 case LDAP_OPT_X_SASL_REALM: 280 *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_realm); 281 break; 282 case LDAP_OPT_X_SASL_AUTHCID: 283 *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_authcid); 284 break; 285 case LDAP_OPT_X_SASL_AUTHZID: 286 *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_authzid); 287 break; 288 case LDAP_OPT_X_SASL_SSF: 289 { 290 int sc; 291 sasl_ssf_t *ssf; 292 sasl_conn_t *ctx; 293 if( ld->ld_defconn == NULL || 294 ld->ld_defconn->lconn_sb == NULL ) { 295 return -1; 296 } 297 ctx = (sasl_conn_t *)(ld->ld_defconn->lconn_sb->sb_sasl_ctx); 298 if ( ctx == NULL ) { 299 return -1; 300 } 301 sc = sasl_getprop( ctx, SASL_SSF, (const void **) &ssf ); 302 if ( sc != SASL_OK ) { 303 return -1; 304 } 305 *((sasl_ssf_t *) optdata) = *ssf; 306 } 307 break; 308 case LDAP_OPT_X_SASL_SSF_MIN: 309 *((sasl_ssf_t *) optdata) = ld->ld_sasl_secprops.min_ssf; 310 break; 311 case LDAP_OPT_X_SASL_SSF_MAX: 312 *((sasl_ssf_t *) optdata) = ld->ld_sasl_secprops.max_ssf; 313 break; 314 case LDAP_OPT_X_SASL_MAXBUFSIZE: 315 *((sasl_ssf_t *) optdata) = ld->ld_sasl_secprops.maxbufsize; 316 break; 317 case LDAP_OPT_X_SASL_SSF_EXTERNAL: 318 case LDAP_OPT_X_SASL_SECPROPS: 319 /* 320 * These options are write only. Making these options 321 * read/write would expose semi-private interfaces of libsasl 322 * for which there are no cross platform/standardized 323 * definitions. 324 */ 325 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); 326 rc = -1; 327 break; 328 #endif 329 330 default: 331 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); 332 rc = -1; 333 } 334 if (ld != &nsldapi_ld_defaults) 335 LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); 336 return( rc ); 337 } 338 339 340 /* 341 * Table of extended API features we support. 342 * The first field is the version of the info. strcuture itself; we do not 343 * use the ones from this table so it is okay to leave as zero. 344 */ 345 static LDAPAPIFeatureInfo nsldapi_extensions[] = { 346 { 0, "SERVER_SIDE_SORT", LDAP_API_FEATURE_SERVER_SIDE_SORT }, 347 { 0, "VIRTUAL_LIST_VIEW", LDAP_API_FEATURE_VIRTUAL_LIST_VIEW }, 348 { 0, "PERSISTENT_SEARCH", LDAP_API_FEATURE_PERSISTENT_SEARCH }, 349 { 0, "PROXY_AUTHORIZATION", LDAP_API_FEATURE_PROXY_AUTHORIZATION }, 350 { 0, "X_LDERRNO", LDAP_API_FEATURE_X_LDERRNO }, 351 { 0, "X_MEMCACHE", LDAP_API_FEATURE_X_MEMCACHE }, 352 { 0, "X_IO_FUNCTIONS", LDAP_API_FEATURE_X_IO_FUNCTIONS }, 353 { 0, "X_EXTIO_FUNCTIONS", LDAP_API_FEATURE_X_EXTIO_FUNCTIONS }, 354 { 0, "X_DNS_FUNCTIONS", LDAP_API_FEATURE_X_DNS_FUNCTIONS }, 355 { 0, "X_MEMALLOC_FUNCTIONS", LDAP_API_FEATURE_X_MEMALLOC_FUNCTIONS }, 356 { 0, "X_THREAD_FUNCTIONS", LDAP_API_FEATURE_X_THREAD_FUNCTIONS }, 357 { 0, "X_EXTHREAD_FUNCTIONS", LDAP_API_FEATURE_X_EXTHREAD_FUNCTIONS }, 358 { 0, "X_GETLANGVALUES", LDAP_API_FEATURE_X_GETLANGVALUES }, 359 { 0, "X_CLIENT_SIDE_SORT", LDAP_API_FEATURE_X_CLIENT_SIDE_SORT }, 360 { 0, "X_URL_FUNCTIONS", LDAP_API_FEATURE_X_URL_FUNCTIONS }, 361 { 0, "X_FILTER_FUNCTIONS", LDAP_API_FEATURE_X_FILTER_FUNCTIONS }, 362 }; 363 364 #define NSLDAPI_EXTENSIONS_COUNT \ 365 (sizeof(nsldapi_extensions)/sizeof(LDAPAPIFeatureInfo)) 366 367 /* 368 * Retrieve information about this implementation of the LDAP API. 369 * Returns an LDAP error code. 370 */ 371 static int 372 nsldapi_get_api_info( LDAPAPIInfo *aip ) 373 { 374 int i; 375 376 if ( aip == NULL ) { 377 return( LDAP_PARAM_ERROR ); 378 } 379 380 aip->ldapai_api_version = LDAP_API_VERSION; 381 382 if ( aip->ldapai_info_version != LDAP_API_INFO_VERSION ) { 383 aip->ldapai_info_version = LDAP_API_INFO_VERSION; 384 return( LDAP_PARAM_ERROR ); 385 } 386 387 aip->ldapai_protocol_version = LDAP_VERSION_MAX; 388 aip->ldapai_vendor_version = LDAP_VENDOR_VERSION; 389 390 if (( aip->ldapai_vendor_name = nsldapi_strdup( LDAP_VENDOR_NAME )) 391 == NULL ) { 392 return( LDAP_NO_MEMORY ); 393 } 394 395 if ( NSLDAPI_EXTENSIONS_COUNT < 1 ) { 396 aip->ldapai_extensions = NULL; 397 } else { 398 if (( aip->ldapai_extensions = NSLDAPI_CALLOC( 399 NSLDAPI_EXTENSIONS_COUNT + 1, sizeof(char *))) == NULL ) { 400 NSLDAPI_FREE( aip->ldapai_vendor_name ); 401 aip->ldapai_vendor_name = NULL; 402 return( LDAP_NO_MEMORY ); 403 } 404 405 for ( i = 0; i < NSLDAPI_EXTENSIONS_COUNT; ++i ) { 406 if (( aip->ldapai_extensions[i] = nsldapi_strdup( 407 nsldapi_extensions[i].ldapaif_name )) == NULL ) { 408 ldap_value_free( aip->ldapai_extensions ); 409 NSLDAPI_FREE( aip->ldapai_vendor_name ); 410 aip->ldapai_extensions = NULL; 411 aip->ldapai_vendor_name = NULL; 412 return( LDAP_NO_MEMORY ); 413 } 414 } 415 } 416 417 return( LDAP_SUCCESS ); 418 } 419 420 421 /* 422 * Retrieves information about a specific extended feature of the LDAP API/ 423 * Returns an LDAP error code. 424 */ 425 static int 426 nsldapi_get_feature_info( LDAPAPIFeatureInfo *fip ) 427 { 428 int i; 429 430 if ( fip == NULL || fip->ldapaif_name == NULL ) { 431 return( LDAP_PARAM_ERROR ); 432 } 433 434 if ( fip->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION ) { 435 fip->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION; 436 return( LDAP_PARAM_ERROR ); 437 } 438 439 for ( i = 0; i < NSLDAPI_EXTENSIONS_COUNT; ++i ) { 440 if ( strcmp( fip->ldapaif_name, 441 nsldapi_extensions[i].ldapaif_name ) == 0 ) { 442 fip->ldapaif_version = 443 nsldapi_extensions[i].ldapaif_version; 444 break; 445 } 446 } 447 448 return(( i < NSLDAPI_EXTENSIONS_COUNT ) ? LDAP_SUCCESS 449 : LDAP_PARAM_ERROR ); 450 } 451