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