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
fill_ldap_errlist()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
ldap_err2string(int err)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 *
nsldapi_safe_strerror(int e)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
ldap_perror(LDAP * ld,const char * s)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
ldap_result2error(LDAP * ld,LDAPMessage * r,int freeit)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
ldap_get_lderrno(LDAP * ld,char ** m,char ** s)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
ldap_set_lderrno(LDAP * ld,int e,char * m,char * s)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
ldap_parse_result(LDAP * ld,LDAPMessage * res,int * errcodep,char ** matchednp,char ** errmsgp,char *** referralsp,LDAPControl *** serverctrlsp,int freeit)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
nsldapi_parse_result(LDAP * ld,int msgtype,BerElement * rber,int * errcodep,char ** matchednp,char ** errmsgp,char *** referralsp,LDAPControl *** serverctrlsp)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