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