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