1 /* 2 * Copyright 2004 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 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- 9 * 10 * The contents of this file are subject to the Netscape Public License 11 * Version 1.0 (the "NPL"); you may not use this file except in 12 * compliance with the NPL. You may obtain a copy of the NPL at 13 * http://www.mozilla.org/NPL/ 14 * 15 * Software distributed under the NPL is distributed on an "AS IS" basis, 16 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL 17 * for the specific language governing rights and limitations under the 18 * NPL. 19 * 20 * The Initial Developer of this code under the NPL is Netscape 21 * Communications Corporation. Portions created by Netscape are 22 * Copyright (C) 1998 Netscape Communications Corporation. All Rights 23 * Reserved. 24 */ 25 #include "ldap-int.h" 26 27 struct ldaperror { 28 int e_code; 29 char *e_reason; 30 }; 31 32 #ifdef _SOLARIS_SDK 33 #include <synch.h> 34 static struct ldaperror ldap_errlist[] = { 35 { LDAP_SUCCESS, 0 }, 36 { LDAP_OPERATIONS_ERROR, 0 }, 37 { LDAP_PROTOCOL_ERROR, 0 }, 38 { LDAP_TIMELIMIT_EXCEEDED, 0 }, 39 { LDAP_SIZELIMIT_EXCEEDED, 0 }, 40 { LDAP_COMPARE_FALSE, 0 }, 41 { LDAP_COMPARE_TRUE, 0 }, 42 { LDAP_STRONG_AUTH_NOT_SUPPORTED, 0 }, 43 { LDAP_STRONG_AUTH_REQUIRED, 0 }, 44 { LDAP_PARTIAL_RESULTS, 0 }, 45 { LDAP_REFERRAL, 0 }, 46 { LDAP_ADMINLIMIT_EXCEEDED, 0 }, 47 { LDAP_UNAVAILABLE_CRITICAL_EXTENSION, 0 }, 48 { LDAP_CONFIDENTIALITY_REQUIRED, 0 }, 49 { LDAP_SASL_BIND_IN_PROGRESS, 0 }, 50 51 { LDAP_NO_SUCH_ATTRIBUTE, 0 }, 52 { LDAP_UNDEFINED_TYPE, 0 }, 53 { LDAP_INAPPROPRIATE_MATCHING, 0 }, 54 { LDAP_CONSTRAINT_VIOLATION, 0 }, 55 { LDAP_TYPE_OR_VALUE_EXISTS, 0 }, 56 { LDAP_INVALID_SYNTAX, 0 }, 57 58 { LDAP_NO_SUCH_OBJECT, 0 }, 59 { LDAP_ALIAS_PROBLEM, 0 }, 60 { LDAP_INVALID_DN_SYNTAX, 0 }, 61 { LDAP_IS_LEAF, 0 }, 62 { LDAP_ALIAS_DEREF_PROBLEM, 0 }, 63 64 { LDAP_INAPPROPRIATE_AUTH, 0 }, 65 { LDAP_INVALID_CREDENTIALS, 0 }, 66 { LDAP_INSUFFICIENT_ACCESS, 0 }, 67 { LDAP_BUSY, 0 }, 68 { LDAP_UNAVAILABLE, 0 }, 69 { LDAP_UNWILLING_TO_PERFORM, 0 }, 70 { LDAP_LOOP_DETECT, 0 }, 71 { LDAP_SORT_CONTROL_MISSING, 0 }, 72 { LDAP_INDEX_RANGE_ERROR, 0 }, 73 74 { LDAP_NAMING_VIOLATION, 0 }, 75 { LDAP_OBJECT_CLASS_VIOLATION, 0 }, 76 { LDAP_NOT_ALLOWED_ON_NONLEAF, 0 }, 77 { LDAP_NOT_ALLOWED_ON_RDN, 0 }, 78 { LDAP_ALREADY_EXISTS, 0 }, 79 { LDAP_NO_OBJECT_CLASS_MODS, 0 }, 80 { LDAP_RESULTS_TOO_LARGE, 0 }, 81 { LDAP_AFFECTS_MULTIPLE_DSAS, 0 }, 82 83 { LDAP_OTHER, 0 }, 84 { LDAP_SERVER_DOWN, 0 }, 85 { LDAP_LOCAL_ERROR, 0 }, 86 { LDAP_ENCODING_ERROR, 0 }, 87 { LDAP_DECODING_ERROR, 0 }, 88 { LDAP_TIMEOUT, 0 }, 89 { LDAP_AUTH_UNKNOWN, 0 }, 90 { LDAP_FILTER_ERROR, 0 }, 91 { LDAP_USER_CANCELLED, 0 }, 92 { LDAP_PARAM_ERROR, 0 }, 93 { LDAP_NO_MEMORY, 0 }, 94 { LDAP_CONNECT_ERROR, 0 }, 95 { LDAP_NOT_SUPPORTED, 0 }, 96 { LDAP_CONTROL_NOT_FOUND, 0 }, 97 { LDAP_NO_RESULTS_RETURNED, 0 }, 98 { LDAP_MORE_RESULTS_TO_RETURN, 0 }, 99 { LDAP_CLIENT_LOOP, 0 }, 100 { LDAP_REFERRAL_LIMIT_EXCEEDED, 0 }, 101 { -1, 0 } 102 }; 103 const int last_index = sizeof(ldap_errlist)/sizeof(ldap_errlist[0]) - 2; 104 #else 105 static struct ldaperror ldap_errlist[] = { 106 { LDAP_SUCCESS, "Success" }, 107 { LDAP_OPERATIONS_ERROR, "Operations error" }, 108 { LDAP_PROTOCOL_ERROR, "Protocol error" }, 109 { LDAP_TIMELIMIT_EXCEEDED, "Timelimit exceeded" }, 110 { LDAP_SIZELIMIT_EXCEEDED, "Sizelimit exceeded" }, 111 { LDAP_COMPARE_FALSE, "Compare false" }, 112 { LDAP_COMPARE_TRUE, "Compare true" }, 113 { LDAP_STRONG_AUTH_NOT_SUPPORTED, "Authentication method not supported" }, 114 { LDAP_STRONG_AUTH_REQUIRED, "Strong authentication required" }, 115 { LDAP_PARTIAL_RESULTS, "Partial results and referral received" }, 116 { LDAP_REFERRAL, "Referral received" }, 117 { LDAP_ADMINLIMIT_EXCEEDED, "Administrative limit exceeded" }, 118 { LDAP_UNAVAILABLE_CRITICAL_EXTENSION, "Unavailable critical extension" }, 119 { LDAP_CONFIDENTIALITY_REQUIRED, "Confidentiality required" }, 120 { LDAP_SASL_BIND_IN_PROGRESS, "SASL bind in progress" }, 121 122 { LDAP_NO_SUCH_ATTRIBUTE, "No such attribute" }, 123 { LDAP_UNDEFINED_TYPE, "Undefined attribute type" }, 124 { LDAP_INAPPROPRIATE_MATCHING, "Inappropriate matching" }, 125 { LDAP_CONSTRAINT_VIOLATION, "Constraint violation" }, 126 { LDAP_TYPE_OR_VALUE_EXISTS, "Type or value exists" }, 127 { LDAP_INVALID_SYNTAX, "Invalid syntax" }, 128 129 { LDAP_NO_SUCH_OBJECT, "No such object" }, 130 { LDAP_ALIAS_PROBLEM, "Alias problem" }, 131 { LDAP_INVALID_DN_SYNTAX, "Invalid DN syntax" }, 132 { LDAP_IS_LEAF, "Object is a leaf" }, 133 { LDAP_ALIAS_DEREF_PROBLEM, "Alias dereferencing problem" }, 134 135 { LDAP_INAPPROPRIATE_AUTH, "Inappropriate authentication" }, 136 { LDAP_INVALID_CREDENTIALS, "Invalid credentials" }, 137 { LDAP_INSUFFICIENT_ACCESS, "Insufficient access" }, 138 { LDAP_BUSY, "DSA is busy" }, 139 { LDAP_UNAVAILABLE, "DSA is unavailable" }, 140 { LDAP_UNWILLING_TO_PERFORM, "DSA is unwilling to perform" }, 141 { LDAP_LOOP_DETECT, "Loop detected" }, 142 { LDAP_SORT_CONTROL_MISSING, "Sort Control is missing" }, 143 { LDAP_INDEX_RANGE_ERROR, "Search results exceed the range specified by the offsets" }, 144 145 { LDAP_NAMING_VIOLATION, "Naming violation" }, 146 { LDAP_OBJECT_CLASS_VIOLATION, "Object class violation" }, 147 { LDAP_NOT_ALLOWED_ON_NONLEAF, "Operation not allowed on nonleaf" }, 148 { LDAP_NOT_ALLOWED_ON_RDN, "Operation not allowed on RDN" }, 149 { LDAP_ALREADY_EXISTS, "Already exists" }, 150 { LDAP_NO_OBJECT_CLASS_MODS, "Cannot modify object class" }, 151 { LDAP_RESULTS_TOO_LARGE, "Results too large" }, 152 { LDAP_AFFECTS_MULTIPLE_DSAS, "Affects multiple servers" }, 153 154 { LDAP_OTHER, "Unknown error" }, 155 { LDAP_SERVER_DOWN, "Can't contact LDAP server" }, 156 { LDAP_LOCAL_ERROR, "Local error" }, 157 { LDAP_ENCODING_ERROR, "Encoding error" }, 158 { LDAP_DECODING_ERROR, "Decoding error" }, 159 { LDAP_TIMEOUT, "Timed out" }, 160 { LDAP_AUTH_UNKNOWN, "Unknown authentication method" }, 161 { LDAP_FILTER_ERROR, "Bad search filter" }, 162 { LDAP_USER_CANCELLED, "User cancelled operation" }, 163 { LDAP_PARAM_ERROR, "Bad parameter to an ldap routine" }, 164 { LDAP_NO_MEMORY, "Out of memory" }, 165 { LDAP_CONNECT_ERROR, "Can't connect to the LDAP server" }, 166 { LDAP_NOT_SUPPORTED, "Not supported by this version of the LDAP protocol" }, 167 { LDAP_CONTROL_NOT_FOUND, "Requested LDAP control not found" }, 168 { LDAP_NO_RESULTS_RETURNED, "No results returned" }, 169 { LDAP_MORE_RESULTS_TO_RETURN, "More results to return" }, 170 { LDAP_CLIENT_LOOP, "Client detected loop" }, 171 { LDAP_REFERRAL_LIMIT_EXCEEDED, "Referral hop limit exceeded" }, 172 { -1, 0 } 173 }; 174 #endif 175 176 #ifdef _SOLARIS_SDK 177 static mutex_t err_mutex = DEFAULTMUTEX; 178 179 static void fill_ldap_errlist() 180 { 181 int i=0; 182 mutex_lock(&err_mutex); 183 184 LDAPDebug(LDAP_DEBUG_TRACE, "fill_ldap_errlist\n", 0, 0, 0 ); 185 186 if (ldap_errlist[last_index].e_reason != NULL) { 187 mutex_unlock(&err_mutex); 188 return; 189 } 190 191 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Success"); 192 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Operations error"); 193 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Protocol error"); 194 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 195 "Timelimit exceeded"); 196 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 197 "Sizelimit exceeded"); 198 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Compare false"); 199 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Compare true"); 200 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 201 "Authentication method not supported"); 202 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 203 "Strong authentication required"); 204 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 205 "Partial results and referral received"); 206 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 207 "Referral received"); 208 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 209 "Administrative limit exceeded"); 210 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 211 "Unavailable critical extension"); 212 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 213 "Confidentiality required"); 214 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 215 "SASL bind in progress"); 216 217 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 218 "No such attribute"); 219 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 220 "Undefined attribute type"); 221 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 222 "Inappropriate matching"); 223 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 224 "Constraint violation"); 225 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 226 "Type or value exists"); 227 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Invalid syntax"); 228 229 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "No such object"); 230 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Alias problem"); 231 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 232 "Invalid DN syntax"); 233 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Object is a leaf"); 234 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 235 "Alias dereferencing problem"); 236 237 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 238 "Inappropriate authentication"); 239 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 240 "Invalid credentials"); 241 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 242 "Insufficient access"); 243 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "DSA is busy"); 244 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 245 "DSA is unavailable"); 246 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 247 "DSA is unwilling to perform"); 248 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Loop detected"); 249 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 250 "Sort Control is missing"); 251 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 252 "Search results exceed the range specified by the offsets"); 253 254 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Naming violation"); 255 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 256 "Object class violation"); 257 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 258 "Operation not allowed on nonleaf"); 259 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 260 "Operation not allowed on RDN"); 261 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Already exists"); 262 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 263 "Cannot modify object class"); 264 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 265 "Results too large"); 266 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 267 "Affects multiple servers"); 268 269 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Unknown error"); 270 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 271 "Can't contact LDAP server"); 272 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Local error"); 273 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Encoding error"); 274 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Decoding error"); 275 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Timed out"); 276 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 277 "Unknown authentication method"); 278 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 279 "Bad search filter"); 280 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 281 "User cancelled operation"); 282 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 283 "Bad parameter to an ldap routine"); 284 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, "Out of memory"); 285 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 286 "Can't connect to the LDAP server"); 287 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 288 "Not supported by this version of the LDAP protocol"); 289 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 290 "Requested LDAP control not found"); 291 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 292 "No results returned"); 293 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 294 "More results to return"); 295 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 296 "Client detected loop"); 297 ldap_errlist[i++].e_reason = dgettext(TEXT_DOMAIN, 298 "Referral hop limit exceeded"); 299 mutex_unlock(&err_mutex); 300 } 301 #endif 302 303 char * 304 LDAP_CALL 305 ldap_err2string( int err ) 306 { 307 int i; 308 309 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_err2string\n", 0, 0, 0 ); 310 311 #ifdef _SOLARIS_SDK 312 /* Make sure errlist is initialized before referencing err string */ 313 if (ldap_errlist[last_index].e_reason == NULL) 314 fill_ldap_errlist(); 315 #endif 316 317 for ( i = 0; ldap_errlist[i].e_code != -1; i++ ) { 318 if ( err == ldap_errlist[i].e_code ) 319 return( ldap_errlist[i].e_reason ); 320 } 321 322 return( dgettext(TEXT_DOMAIN, "Unknown error") ); 323 } 324 325 326 static char * 327 nsldapi_safe_strerror( int e ) 328 { 329 char *s; 330 331 if (( s = strerror( e )) == NULL ) { 332 s = dgettext(TEXT_DOMAIN, "unknown error"); 333 } 334 335 return( s ); 336 } 337 338 339 void 340 LDAP_CALL 341 ldap_perror( LDAP *ld, const char *s ) 342 { 343 int i, err; 344 char *matched, *errmsg, *separator; 345 char msg[1024]; 346 347 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_perror\n", 0, 0, 0 ); 348 349 #ifdef _SOLARIS_SDK 350 /* Make sure errlist is initialized before referencing err string */ 351 if (ldap_errlist[last_index].e_reason == NULL) 352 fill_ldap_errlist(); 353 #endif 354 355 if ( s == NULL ) { 356 s = separator = ""; 357 } else { 358 separator = ": "; 359 } 360 361 if ( ld == NULL ) { 362 sprintf( msg, "%s%s%s", s, separator, 363 nsldapi_safe_strerror( errno ) ); 364 ber_err_print( msg ); 365 return; 366 } 367 368 LDAP_MUTEX_LOCK( ld, LDAP_ERR_LOCK ); 369 err = LDAP_GET_LDERRNO( ld, &matched, &errmsg ); 370 for ( i = 0; ldap_errlist[i].e_code != -1; i++ ) { 371 if ( err == ldap_errlist[i].e_code ) { 372 sprintf( msg, "%s%s%s", s, separator, 373 ldap_errlist[i].e_reason ); 374 ber_err_print( msg ); 375 if ( err == LDAP_CONNECT_ERROR ) { 376 ber_err_print( " - " ); 377 ber_err_print( nsldapi_safe_strerror( 378 LDAP_GET_ERRNO( ld ))); 379 } 380 ber_err_print( "\n" ); 381 if ( matched != NULL && *matched != '\0' ) { 382 sprintf( msg, dgettext(TEXT_DOMAIN, 383 "%s%smatched: %s\n"), 384 s, separator, matched ); 385 ber_err_print( msg ); 386 } 387 if ( errmsg != NULL && *errmsg != '\0' ) { 388 sprintf( msg, dgettext(TEXT_DOMAIN, 389 "%s%sadditional info: %s\n"), 390 s, separator, errmsg ); 391 ber_err_print( msg ); 392 } 393 LDAP_MUTEX_UNLOCK( ld, LDAP_ERR_LOCK ); 394 return; 395 } 396 } 397 sprintf( msg, dgettext(TEXT_DOMAIN, "%s%sNot an LDAP errno %d\n"), 398 s, separator, err ); 399 ber_err_print( msg ); 400 LDAP_MUTEX_UNLOCK( ld, LDAP_ERR_LOCK ); 401 } 402 403 int 404 LDAP_CALL 405 ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit ) 406 { 407 int lderr_parse, lderr; 408 409 lderr_parse = ldap_parse_result( ld, r, &lderr, NULL, NULL, NULL, 410 NULL, freeit ); 411 412 if ( lderr_parse != LDAP_SUCCESS ) { 413 return( lderr_parse ); 414 } 415 416 return( lderr ); 417 } 418 419 int 420 LDAP_CALL 421 ldap_get_lderrno( LDAP *ld, char **m, char **s ) 422 { 423 if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { 424 return( LDAP_PARAM_ERROR ); /* punt */ 425 } 426 427 if ( ld->ld_get_lderrno_fn == NULL ) { 428 if ( m != NULL ) { 429 *m = ld->ld_matched; 430 } 431 if ( s != NULL ) { 432 *s = ld->ld_error; 433 } 434 return( ld->ld_errno ); 435 } else { 436 return( ld->ld_get_lderrno_fn( m, s, ld->ld_lderrno_arg ) ); 437 } 438 } 439 440 441 /* 442 * Note: there is no need for callers of ldap_set_lderrno() to lock the 443 * ld mutex. If applications intend to share an LDAP session handle 444 * between threads they *must* perform their own locking around the 445 * session handle or they must install a "set lderrno" thread callback 446 * function. 447 * 448 */ 449 int 450 LDAP_CALL 451 ldap_set_lderrno( LDAP *ld, int e, char *m, char *s ) 452 { 453 if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { 454 return( LDAP_PARAM_ERROR ); 455 } 456 457 if ( ld->ld_set_lderrno_fn != NULL ) { 458 ld->ld_set_lderrno_fn( e, m, s, ld->ld_lderrno_arg ); 459 } else { 460 LDAP_MUTEX_LOCK( ld, LDAP_ERR_LOCK ); 461 ld->ld_errno = e; 462 if ( ld->ld_matched ) { 463 NSLDAPI_FREE( ld->ld_matched ); 464 } 465 ld->ld_matched = m; 466 if ( ld->ld_error ) { 467 NSLDAPI_FREE( ld->ld_error ); 468 } 469 ld->ld_error = s; 470 LDAP_MUTEX_UNLOCK( ld, LDAP_ERR_LOCK ); 471 } 472 473 return( LDAP_SUCCESS ); 474 } 475 476 477 /* 478 * Returns an LDAP error that says whether parse succeeded. The error code 479 * from the LDAP result itself is returned in the errcodep result parameter. 480 * If any of the result params. (errcodep, matchednp, errmsgp, referralsp, 481 * or serverctrlsp) are NULL we don't return that info. 482 */ 483 int 484 LDAP_CALL 485 ldap_parse_result( LDAP *ld, LDAPMessage *res, int *errcodep, char **matchednp, 486 char **errmsgp, char ***referralsp, LDAPControl ***serverctrlsp, 487 int freeit ) 488 { 489 LDAPMessage *lm; 490 int err, errcode; 491 char *m, *e; 492 493 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_parse_result\n", 0, 0, 0 ); 494 495 if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || 496 !NSLDAPI_VALID_LDAPMESSAGE_POINTER( res )) { 497 return( LDAP_PARAM_ERROR ); 498 } 499 500 /* skip over entries and references to find next result in this chain */ 501 for ( lm = res; lm != NULL; lm = lm->lm_chain ) { 502 if ( lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY && 503 lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) { 504 break; 505 } 506 } 507 508 if ( lm == NULL ) { 509 err = LDAP_NO_RESULTS_RETURNED; 510 LDAP_SET_LDERRNO( ld, err, NULL, NULL ); 511 return( err ); 512 } 513 514 err = nsldapi_parse_result( ld, lm->lm_msgtype, lm->lm_ber, &errcode, 515 &m, &e, referralsp, serverctrlsp ); 516 517 if ( err == LDAP_SUCCESS ) { 518 if ( errcodep != NULL ) { 519 *errcodep = errcode; 520 } 521 if ( matchednp != NULL ) { 522 *matchednp = nsldapi_strdup( m ); 523 } 524 if ( errmsgp != NULL ) { 525 *errmsgp = nsldapi_strdup( e ); 526 } 527 528 /* 529 * if there are more result messages in the chain, arrange to 530 * return the special LDAP_MORE_RESULTS_TO_RETURN "error" code. 531 */ 532 for ( lm = lm->lm_chain; lm != NULL; lm = lm->lm_chain ) { 533 if ( lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY && 534 lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) { 535 err = LDAP_MORE_RESULTS_TO_RETURN; 536 break; 537 } 538 } 539 } else { 540 m = e = NULL; 541 } 542 543 if ( freeit ) { 544 ldap_msgfree( res ); 545 } 546 547 LDAP_SET_LDERRNO( ld, ( err == LDAP_SUCCESS ) ? errcode : err, m, e ); 548 549 return( err ); 550 } 551 552 553 /* 554 * returns an LDAP error code indicating success or failure of parsing 555 * does NOT set any error information inside "ld" 556 */ 557 int 558 nsldapi_parse_result( LDAP *ld, int msgtype, BerElement *rber, int *errcodep, 559 char **matchednp, char **errmsgp, char ***referralsp, 560 LDAPControl ***serverctrlsp ) 561 { 562 BerElement ber; 563 ber_len_t len; 564 int berrc, err, errcode; 565 ber_int_t along; 566 char *m, *e; 567 568 /* 569 * Parse the result message. LDAPv3 result messages look like this: 570 * 571 * LDAPResult ::= SEQUENCE { 572 * resultCode ENUMERATED { ... }, 573 * matchedDN LDAPDN, 574 * errorMessage LDAPString, 575 * referral [3] Referral OPTIONAL 576 * opSpecificStuff OPTIONAL 577 * } 578 * 579 * all wrapped up in an LDAPMessage sequence which looks like this: 580 * LDAPMessage ::= SEQUENCE { 581 * messageID MessageID, 582 * LDAPResult CHOICE { ... }, // message type 583 * controls [0] Controls OPTIONAL 584 * } 585 * 586 * LDAPv2 messages don't include referrals or controls. 587 * LDAPv1 messages don't include matchedDN, referrals, or controls. 588 * 589 * ldap_result() pulls out the message id, so by the time a result 590 * message gets here we are sitting at the start of the LDAPResult. 591 */ 592 593 err = LDAP_SUCCESS; /* optimistic */ 594 m = e = NULL; 595 if ( matchednp != NULL ) { 596 *matchednp = NULL; 597 } 598 if ( errmsgp != NULL ) { 599 *errmsgp = NULL; 600 } 601 if ( referralsp != NULL ) { 602 *referralsp = NULL; 603 } 604 if ( serverctrlsp != NULL ) { 605 *serverctrlsp = NULL; 606 } 607 ber = *rber; /* struct copy */ 608 609 if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION2 ) { 610 berrc = ber_scanf( &ber, "{ia}", &along, &e ); 611 errcode = (int)along; /* XXX lossy cast */ 612 } else { 613 if (( berrc = ber_scanf( &ber, "{iaa", &along, &m, &e )) 614 != LBER_ERROR ) { 615 errcode = (int)along; /* XXX lossy cast */ 616 /* check for optional referrals */ 617 if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_REFERRAL ) { 618 if ( referralsp == NULL ) { 619 /* skip referrals */ 620 berrc = ber_scanf( &ber, "x" ); 621 } else { 622 /* suck out referrals */ 623 berrc = ber_scanf( &ber, "v", 624 referralsp ); 625 } 626 } else if ( referralsp != NULL ) { 627 *referralsp = NULL; 628 } 629 } 630 631 if ( berrc != LBER_ERROR ) { 632 /* 633 * skip past optional operation-specific elements: 634 * bind results - serverSASLcreds 635 * extendedop results - OID plus value 636 */ 637 if ( msgtype == LDAP_RES_BIND ) { 638 if ( ber_peek_tag( &ber, &len ) == 639 LDAP_TAG_SASL_RES_CREDS ) { 640 berrc = ber_scanf( &ber, "x" ); 641 } 642 } else if ( msgtype == LDAP_RES_EXTENDED ) { 643 if ( ber_peek_tag( &ber, &len ) == 644 LDAP_TAG_EXOP_RES_OID ) { 645 berrc = ber_scanf( &ber, "x" ); 646 } 647 if ( berrc != LBER_ERROR && 648 ber_peek_tag( &ber, &len ) == 649 LDAP_TAG_EXOP_RES_VALUE ) { 650 berrc = ber_scanf( &ber, "x" ); 651 } 652 } 653 } 654 655 /* pull out controls (if requested and any are present) */ 656 if ( berrc != LBER_ERROR && serverctrlsp != NULL && 657 ( berrc = ber_scanf( &ber, "}" )) != LBER_ERROR ) { 658 err = nsldapi_get_controls( &ber, serverctrlsp ); 659 } 660 } 661 662 if ( berrc == LBER_ERROR && err == LDAP_SUCCESS ) { 663 err = LDAP_DECODING_ERROR; 664 } 665 666 if ( errcodep != NULL ) { 667 *errcodep = errcode; 668 } 669 if ( matchednp != NULL ) { 670 *matchednp = m; 671 } else if ( m != NULL ) { 672 NSLDAPI_FREE( m ); 673 } 674 if ( errmsgp != NULL ) { 675 *errmsgp = e; 676 } else if ( e != NULL ) { 677 NSLDAPI_FREE( e ); 678 } 679 680 return( err ); 681 } 682