error.c 9.61 KB
Newer Older
1
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
2
/*
Kurt Zeilenga's avatar
Kurt Zeilenga committed
3
 * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
4
5
6
 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
 */

Kurt Zeilenga's avatar
Kurt Zeilenga committed
7
8
#include "portable.h"

Kurt Zeilenga's avatar
Kurt Zeilenga committed
9
#include <stdio.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
10
11

#include <ac/stdlib.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
12

Kurt Zeilenga's avatar
Kurt Zeilenga committed
13
14
15
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/time.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
16

17
#include "ldap-int.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
18
19
20

struct ldaperror {
	int	e_code;
21
	char *e_reason;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
22
23
};

24
static struct ldaperror ldap_builtin_errlist[] = {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
25
26
27
	{LDAP_SUCCESS, 					"Success" },
	{LDAP_OPERATIONS_ERROR, 		"Operations error" },
	{LDAP_PROTOCOL_ERROR, 			"Protocol error" },
28
29
	{LDAP_TIMELIMIT_EXCEEDED,		"Time limit exceeded" },
	{LDAP_SIZELIMIT_EXCEEDED, 		"Size limit exceeded" },
30
31
	{LDAP_COMPARE_FALSE, 			"Compare False" },
	{LDAP_COMPARE_TRUE, 			"Compare True" },
32
	{LDAP_STRONG_AUTH_NOT_SUPPORTED, "Authentication method not supported" },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
33
	{LDAP_STRONG_AUTH_REQUIRED, 	"Strong(er) authentication required" },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
34
	{LDAP_PARTIAL_RESULTS, 			"Partial results and referral received" },
35
36
37

	{LDAP_REFERRAL,					"Referral"},
	{LDAP_ADMINLIMIT_EXCEEDED,		"Administrative limit exceeded"},
Kurt Zeilenga's avatar
Kurt Zeilenga committed
38
	{LDAP_UNAVAILABLE_CRITICAL_EXTENSION,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
39
									"Critical extension is unavailable"},
40
41
42
	{LDAP_CONFIDENTIALITY_REQUIRED,	"Confidentiality required"},
	{LDAP_SASL_BIND_IN_PROGRESS,	"SASL bind in progress"},

Kurt Zeilenga's avatar
Kurt Zeilenga committed
43
44
45
46
47
48
	{LDAP_NO_SUCH_ATTRIBUTE, 		"No such attribute" },
	{LDAP_UNDEFINED_TYPE, 			"Undefined attribute type" },
	{LDAP_INAPPROPRIATE_MATCHING, 	"Inappropriate matching" },
	{LDAP_CONSTRAINT_VIOLATION, 	"Constraint violation" },
	{LDAP_TYPE_OR_VALUE_EXISTS, 	"Type or value exists" },
	{LDAP_INVALID_SYNTAX, 			"Invalid syntax" },
49

Kurt Zeilenga's avatar
Kurt Zeilenga committed
50
51
52
	{LDAP_NO_SUCH_OBJECT, 			"No such object" },
	{LDAP_ALIAS_PROBLEM, 			"Alias problem" },
	{LDAP_INVALID_DN_SYNTAX,		"Invalid DN syntax" },
53
	{LDAP_IS_LEAF, 					"Entry is a leaf" },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
54
	{LDAP_ALIAS_DEREF_PROBLEM,	 	"Alias dereferencing problem" },
55

Kurt Zeilenga's avatar
Kurt Zeilenga committed
56
57
58
	{LDAP_INAPPROPRIATE_AUTH, 		"Inappropriate authentication" },
	{LDAP_INVALID_CREDENTIALS, 		"Invalid credentials" },
	{LDAP_INSUFFICIENT_ACCESS, 		"Insufficient access" },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
59
60
61
	{LDAP_BUSY, 					"Server is busy" },
	{LDAP_UNAVAILABLE, 				"Server is unavailable" },
	{LDAP_UNWILLING_TO_PERFORM, 	"Server is unwilling to perform" },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
62
	{LDAP_LOOP_DETECT, 				"Loop detected" },
63

Kurt Zeilenga's avatar
Kurt Zeilenga committed
64
65
	{LDAP_NAMING_VIOLATION, 		"Naming violation" },
	{LDAP_OBJECT_CLASS_VIOLATION, 	"Object class violation" },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
66
	{LDAP_NOT_ALLOWED_ON_NONLEAF, 	"Operation not allowed on non-leaf" },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
67
68
69
70
	{LDAP_NOT_ALLOWED_ON_RDN,	 	"Operation not allowed on RDN" },
	{LDAP_ALREADY_EXISTS, 			"Already exists" },
	{LDAP_NO_OBJECT_CLASS_MODS, 	"Cannot modify object class" },
	{LDAP_RESULTS_TOO_LARGE,		"Results too large" },
71
72
	{LDAP_AFFECTS_MULTIPLE_DSAS,	"Operation affects multiple DSAs" },

Kurt Zeilenga's avatar
Kurt Zeilenga committed
73
	{LDAP_OTHER, 					"Internal (implementation specific) error" },
74
75

	/* API ResultCodes */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
76
77
78
79
80
81
82
83
84
85
	{LDAP_SERVER_DOWN,				"Can't contact LDAP server" },
	{LDAP_LOCAL_ERROR,				"Local error" },
	{LDAP_ENCODING_ERROR,			"Encoding error" },
	{LDAP_DECODING_ERROR,			"Decoding error" },
	{LDAP_TIMEOUT,					"Timed out" },
	{LDAP_AUTH_UNKNOWN,				"Unknown authentication method" },
	{LDAP_FILTER_ERROR,				"Bad search filter" },
	{LDAP_USER_CANCELLED,			"User cancelled operation" },
	{LDAP_PARAM_ERROR,				"Bad parameter to an ldap routine" },
	{LDAP_NO_MEMORY,				"Out of memory" },
86
87
88
89
90
91
92
93
94

	{LDAP_CONNECT_ERROR,			"Connect error" },
	{LDAP_NOT_SUPPORTED,			"Not Supported" },
	{LDAP_CONTROL_NOT_FOUND,		"Control not found" },
	{LDAP_NO_RESULTS_RETURNED,		"No results returned" },
	{LDAP_MORE_RESULTS_TO_RETURN,	"More results to return" },
	{LDAP_CLIENT_LOOP,				"Client Loop" },
	{LDAP_REFERRAL_LIMIT_EXCEEDED,	"Referral Limit Exceeded" },

95
	{-1, NULL}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
96
97
};

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
static struct ldaperror *ldap_errlist = ldap_builtin_errlist; 

void ldap_int_error_init( void ) {
#ifdef LDAP_NLS
#define LDAP_NLS_SDK_CAT "openldap_sdk"
#define LDAP_NLS_LIBLDAP_SET (0)

	int	i;
	nl_catd catd = catopen( LDAP_NLS_SDK_CAT, NL_CAT_LOCALE );

	if( catd == -1 ) {
		return;
	}

	for ( i=0; ldap_errlist[i].e_reason != NULL; i++ ) {
		char *msg = catgets( catd,
			LDAP_NLS_LIBLDAP_SET,
			ldap_errlist[i].e_code, NULL );

		if( msg != NULL ) {
			msg = LDAP_STRDUP( msg );

			if( msg != NULL ) {
				ldap_errlist[i].e_reason = msg;
			}
		}
	}

	catclose( catd );
#endif
}

130
131
static const struct ldaperror *
ldap_int_error( int err )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
132
133
134
{
	int	i;

135
	for ( i=0; ldap_errlist[i].e_reason != NULL; i++ ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
136
		if ( err == ldap_errlist[i].e_code ) {
137
			return &ldap_errlist[i];
Kurt Zeilenga's avatar
Kurt Zeilenga committed
138
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
139
140
	}

141
	return NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
142
143
}

144
145
char *
ldap_err2string( int err )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
146
{
147
	const struct ldaperror *e;
148
	
Julius Enarusai's avatar
   
Julius Enarusai committed
149
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
150
	LDAP_LOG ( OPERATION, ENTRY, "ldap_err2string\n", 0,0,0 );
Julius Enarusai's avatar
   
Julius Enarusai committed
151
#else
152
	Debug( LDAP_DEBUG_TRACE, "ldap_err2string\n", 0, 0, 0 );
Julius Enarusai's avatar
   
Julius Enarusai committed
153
#endif
154
155
156

	e = ldap_int_error( err );

Kurt Zeilenga's avatar
Kurt Zeilenga committed
157
	return e ? e->e_reason : "Unknown error";
158
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
159

160
161
162
163
/* deprecated */
void
ldap_perror( LDAP *ld, LDAP_CONST char *str )
{
164
	const struct ldaperror *e;
Julius Enarusai's avatar
   
Julius Enarusai committed
165
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
166
	LDAP_LOG ( OPERATION, ENTRY, "ldap_perror\n", 0,0,0 );
Julius Enarusai's avatar
   
Julius Enarusai committed
167
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
168
	Debug( LDAP_DEBUG_TRACE, "ldap_perror\n", 0, 0, 0 );
Julius Enarusai's avatar
   
Julius Enarusai committed
169
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
170

171
172
	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
173
	assert( str );
174
175
176

	e = ldap_int_error( ld->ld_errno );

Kurt Zeilenga's avatar
Kurt Zeilenga committed
177
178
179
180
	fprintf( stderr, "%s: %s (%d)\n",
		str ? str : "ldap_perror",
		e ? e->e_reason : "unknown LDAP result code",
		ld->ld_errno );
181

182
	if ( ld->ld_matched != NULL && ld->ld_matched[0] != '\0' ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
183
		fprintf( stderr, "\tmatched DN: %s\n", ld->ld_matched );
184
185
	}

186
	if ( ld->ld_error != NULL && ld->ld_error[0] != '\0' ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
187
		fprintf( stderr, "\tadditional info: %s\n", ld->ld_error );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
188
189
190
	}

	fflush( stderr );
191
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
192

193
/* deprecated */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
194
195
int
ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit )
196
197
198
199
200
201
{
	int rc, err;

	rc = ldap_parse_result( ld, r, &err,
		NULL, NULL, NULL, NULL, freeit );

202
	return err != LDAP_SUCCESS ? err : rc;
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
}

/*
 * Parse LDAPResult Messages:
 *
 *   LDAPResult ::= SEQUENCE {
 *     resultCode      ENUMERATED,
 *     matchedDN       LDAPDN,
 *     errorMessage    LDAPString,
 *     referral        [3] Referral OPTIONAL }
 *
 * including Bind results:
 *
 *   BindResponse ::= [APPLICATION 1] SEQUENCE {
 *     COMPONENTS OF LDAPResult,
 *     serverSaslCreds  [7] OCTET STRING OPTIONAL }
 * 
 * and ExtendedOp results:
 *
 *   ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
 *     COMPONENTS OF LDAPResult,
 *     responseName     [10] LDAPOID OPTIONAL,
 *     response         [11] OCTET STRING OPTIONAL }
 *
 */
int
ldap_parse_result(
	LDAP			*ld,
	LDAPMessage		*r,
	int				*errcodep,
	char			**matcheddnp,
	char			**errmsgp,
	char			***referralsp,
	LDAPControl		***serverctrls,
	int				freeit )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
238
239
{
	LDAPMessage	*lm;
240
	ber_int_t errcode = LDAP_SUCCESS;
241
242
243

	ber_tag_t tag;
	BerElement	*ber;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
244

Julius Enarusai's avatar
   
Julius Enarusai committed
245
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
246
	LDAP_LOG ( OPERATION, ENTRY, "ldap_parse_result\n", 0,0,0 );
Julius Enarusai's avatar
   
Julius Enarusai committed
247
#else
248
	Debug( LDAP_DEBUG_TRACE, "ldap_parse_result\n", 0, 0, 0 );
Julius Enarusai's avatar
   
Julius Enarusai committed
249
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
250

251
252
253
254
	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( r != NULL );

255
	if(errcodep != NULL) *errcodep = LDAP_SUCCESS;
256
257
258
259
260
261
	if(matcheddnp != NULL) *matcheddnp = NULL;
	if(errmsgp != NULL) *errmsgp = NULL;
	if(referralsp != NULL) *referralsp = NULL;
	if(serverctrls != NULL) *serverctrls = NULL;

	/* Find the next result... */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
262
	for ( lm = r; lm != NULL; lm = lm->lm_chain ) {
263
264
		/* skip over entries and references */
		if( lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY &&
265
266
			lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE &&
			lm->lm_msgtype != LDAP_RES_EXTENDED_PARTIAL )
267
268
269
270
271
272
273
274
275
276
		{
			break;
		}
	}

	if( lm == NULL ) {
		ld->ld_errno = LDAP_NO_RESULTS_RETURNED;
		return ld->ld_errno;
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
277
	if ( ld->ld_error ) {
278
		LDAP_FREE( ld->ld_error );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
279
280
281
		ld->ld_error = NULL;
	}
	if ( ld->ld_matched ) {
282
		LDAP_FREE( ld->ld_matched );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
283
284
285
		ld->ld_matched = NULL;
	}

286
287
288
	/* parse results */

	ber = ber_dup( lm->lm_ber );
289
290

	if ( ld->ld_version < LDAP_VERSION2 ) {
291
		tag = ber_scanf( ber, "{ia}",
292
			&ld->ld_errno, &ld->ld_error );
293
	} else {
294
295
		ber_len_t len;
		tag = ber_scanf( ber, "{iaa" /*}*/,
296
			&ld->ld_errno, &ld->ld_matched, &ld->ld_error );
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336

		if( tag != LBER_ERROR ) {
			/* peek for referrals */
			if( ber_peek_tag(ber, &len) == LDAP_TAG_REFERRAL ) {
				if( referralsp != NULL ) {
					tag = ber_scanf( ber, "v", referralsp );

				} else {
					/* no place to put them so skip 'em */
					tag = ber_scanf( ber, "x" );
				}
			}
		}

		/* need to clean out misc items */
		if( tag != LBER_ERROR ) {
			if( lm->lm_msgtype == LDAP_RES_BIND ) {
				/* look for sasl result creditials */
				if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SASL_RES_CREDS ) {
					/* skip 'em */
					tag = ber_scanf( ber, "x" );
				}

			} else if( lm->lm_msgtype == LDAP_RES_EXTENDED ) {
				/* look for exop result oid or value */
				if ( ber_peek_tag( ber, &len ) == LDAP_TAG_EXOP_RES_OID ) {
					/* skip 'em */
					tag = ber_scanf( ber, "x" );
				}

				if ( tag != LBER_ERROR &&
					ber_peek_tag( ber, &len ) == LDAP_TAG_EXOP_RES_VALUE )
				{
					/* skip 'em */
					tag = ber_scanf( ber, "x" );
				}
			}
		}

		if( tag != LBER_ERROR ) {
337
			int rc = ldap_int_get_controls( ber, serverctrls );
338
339
340
341
342
343
344
345
346

			if( rc != LDAP_SUCCESS ) {
				tag = LBER_ERROR;
			}
		}

		if( tag != LBER_ERROR ) {
			tag = ber_scanf( ber, /*{*/"}" );
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
347
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
348

349
	if ( tag == LBER_ERROR ) {
350
		ld->ld_errno = errcode = LDAP_DECODING_ERROR;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
351
352
	}

353
354
355
356
357
	if( ber != NULL ) {
		ber_free( ber, 0 );
	}

	/* return */
358
359
360
	if( errcodep != NULL ) {
		*errcodep = ld->ld_errno;
	}
361
362
363
364
365
366
367
368
369
370
371
372
	if ( errcode == LDAP_SUCCESS ) {
		if( matcheddnp != NULL ) {
			*matcheddnp = LDAP_STRDUP( ld->ld_matched );
		}
		if( errmsgp != NULL ) {
			*errmsgp = LDAP_STRDUP( ld->ld_error );
		}

		/* Find the next result... */
		for ( lm = lm->lm_chain; lm != NULL; lm = lm->lm_chain ) {
			/* skip over entries and references */
			if( lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY &&
373
374
				lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE &&
				lm->lm_msgtype != LDAP_RES_EXTENDED_PARTIAL )
375
376
377
378
379
380
381
382
383
			{
				/* more results to return */
				errcode = LDAP_MORE_RESULTS_TO_RETURN;
				break;
			}
		}
	}

	if ( freeit ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
384
		ldap_msgfree( r );
385
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
386

387
	return( errcode );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
388
}