xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/deref.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: deref.c,v 1.1.1.1 2010/03/08 02:14:20 lukem Exp $	*/
2 
3 /* OpenLDAP: pkg/ldap/libraries/libldap/deref.c,v 1.2.2.2 2009/01/22 00:00:54 kurt Exp */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1998-2009 The OpenLDAP Foundation.
7  * Portions Copyright 2008 Pierangelo Masarati.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* ACKNOWLEDGEMENTS:
19  * This work was initially developed by Pierangelo Masarati
20  * for inclusion in OpenLDAP Software.
21  */
22 
23 #include "portable.h"
24 
25 #include <stdio.h>
26 #include <ac/stdlib.h>
27 #include <ac/string.h>
28 #include <ac/time.h>
29 
30 #include "ldap-int.h"
31 
32 int
33 ldap_create_deref_control_value(
34 	LDAP		*ld,
35 	LDAPDerefSpec	*ds,
36 	struct berval	*value )
37 {
38 	BerElement	*ber = NULL;
39 	ber_tag_t	tag;
40 	int		i;
41 
42 	if ( ld == NULL || value == NULL || ds == NULL )
43 	{
44 		if ( ld )
45 			ld->ld_errno = LDAP_PARAM_ERROR;
46 		return LDAP_PARAM_ERROR;
47 	}
48 
49 	assert( LDAP_VALID( ld ) );
50 
51 	value->bv_val = NULL;
52 	value->bv_len = 0;
53 	ld->ld_errno = LDAP_SUCCESS;
54 
55 	ber = ldap_alloc_ber_with_options( ld );
56 	if ( ber == NULL ) {
57 		ld->ld_errno = LDAP_NO_MEMORY;
58 		return ld->ld_errno;
59 	}
60 
61 	tag = ber_printf( ber, "{" /*}*/ );
62 	if ( tag == LBER_ERROR ) {
63 		ld->ld_errno = LDAP_ENCODING_ERROR;
64 		goto done;
65 	}
66 
67 	for ( i = 0; ds[i].derefAttr != NULL; i++ ) {
68 		int j;
69 
70 		tag = ber_printf( ber, "{s{" /*}}*/ , ds[i].derefAttr );
71 		if ( tag == LBER_ERROR ) {
72 			ld->ld_errno = LDAP_ENCODING_ERROR;
73 			goto done;
74 		}
75 
76 		for ( j = 0; ds[i].attributes[j] != NULL; j++ ) {
77 			tag = ber_printf( ber, "s", ds[i].attributes[ j ] );
78 			if ( tag == LBER_ERROR ) {
79 				ld->ld_errno = LDAP_ENCODING_ERROR;
80 				goto done;
81 			}
82 		}
83 
84 		tag = ber_printf( ber, /*{{*/ "}N}" );
85 		if ( tag == LBER_ERROR ) {
86 			ld->ld_errno = LDAP_ENCODING_ERROR;
87 			goto done;
88 		}
89 	}
90 
91 	tag = ber_printf( ber, /*{*/ "}" );
92 	if ( tag == LBER_ERROR ) {
93 		ld->ld_errno = LDAP_ENCODING_ERROR;
94 		goto done;
95 	}
96 
97 	if ( ber_flatten2( ber, value, 1 ) == -1 ) {
98 		ld->ld_errno = LDAP_NO_MEMORY;
99 	}
100 
101 done:;
102 	if ( ber != NULL ) {
103 		ber_free( ber, 1 );
104 	}
105 
106 	return ld->ld_errno;
107 }
108 
109 int
110 ldap_create_deref_control(
111 	LDAP		*ld,
112 	LDAPDerefSpec	*ds,
113 	int		iscritical,
114 	LDAPControl	**ctrlp )
115 {
116 	struct berval	value;
117 
118 	if ( ctrlp == NULL ) {
119 		ld->ld_errno = LDAP_PARAM_ERROR;
120 		return ld->ld_errno;
121 	}
122 
123 	ld->ld_errno = ldap_create_deref_control_value( ld, ds, &value );
124 	if ( ld->ld_errno == LDAP_SUCCESS ) {
125 		ld->ld_errno = ldap_control_create( LDAP_CONTROL_PAGEDRESULTS,
126 			iscritical, &value, 0, ctrlp );
127 		if ( ld->ld_errno != LDAP_SUCCESS ) {
128 			LDAP_FREE( value.bv_val );
129 		}
130 	}
131 
132 	return ld->ld_errno;
133 }
134 
135 void
136 ldap_derefresponse_free( LDAPDerefRes *dr )
137 {
138 	for ( ; dr; ) {
139 		LDAPDerefRes *drnext = dr->next;
140 		LDAPDerefVal *dv;
141 
142 		LDAP_FREE( dr->derefAttr );
143 		LDAP_FREE( dr->derefVal.bv_val );
144 
145 		for ( dv = dr->attrVals; dv; ) {
146 			LDAPDerefVal *dvnext = dv->next;
147 			LDAP_FREE( dv->type );
148 			ber_bvarray_free( dv->vals );
149 			LDAP_FREE( dv );
150 			dv = dvnext;
151 		}
152 
153 		LDAP_FREE( dr );
154 
155 		dr = drnext;
156 	}
157 }
158 
159 int
160 ldap_parse_derefresponse_control(
161 	LDAP		*ld,
162 	LDAPControl	*ctrl,
163 	LDAPDerefRes	**drp2 )
164 {
165 	BerElement *ber;
166 	ber_tag_t tag;
167 	ber_len_t len;
168 	char *last;
169 	LDAPDerefRes *drhead = NULL, **drp;
170 
171 	if ( ld == NULL || ctrl == NULL || drp2 == NULL ) {
172 		if ( ld )
173 			ld->ld_errno = LDAP_PARAM_ERROR;
174 		return LDAP_PARAM_ERROR;
175 	}
176 
177 	/* Create a BerElement from the berval returned in the control. */
178 	ber = ber_init( &ctrl->ldctl_value );
179 
180 	if ( ber == NULL ) {
181 		ld->ld_errno = LDAP_NO_MEMORY;
182 		return ld->ld_errno;
183 	}
184 
185 	/* Extract the count and cookie from the control. */
186 	drp = &drhead;
187 	for ( tag = ber_first_element( ber, &len, &last );
188 		tag != LBER_DEFAULT;
189 		tag = ber_next_element( ber, &len, last ) )
190 	{
191 		LDAPDerefRes *dr;
192 		LDAPDerefVal **dvp;
193 		char *last2;
194 
195 		dr = LDAP_CALLOC( 1, sizeof(LDAPDerefRes) );
196 		dvp = &dr->attrVals;
197 
198 		tag = ber_scanf( ber, "{ao", &dr->derefAttr, &dr->derefVal );
199 		if ( tag == LBER_ERROR ) {
200 			goto done;
201 		}
202 
203 		tag = ber_peek_tag( ber, &len );
204 		if ( tag == (LBER_CONSTRUCTED|LBER_CLASS_CONTEXT) ) {
205 			for ( tag = ber_first_element( ber, &len, &last2 );
206 				tag != LBER_DEFAULT;
207 				tag = ber_next_element( ber, &len, last2 ) )
208 			{
209 				LDAPDerefVal *dv;
210 
211 				dv = LDAP_CALLOC( 1, sizeof(LDAPDerefVal) );
212 
213 				tag = ber_scanf( ber, "{a[W]}", &dv->type, &dv->vals );
214 				if ( tag == LBER_ERROR ) {
215 					goto done;
216 				}
217 
218 				*dvp = dv;
219 				dvp = &dv->next;
220 			}
221 		}
222 
223 		tag = ber_scanf( ber, "}" );
224 		if ( tag == LBER_ERROR ) {
225 			goto done;
226 		}
227 
228 		*drp = dr;
229 		drp = &dr->next;
230 	}
231 
232 	tag = 0;
233 
234 done:;
235         ber_free( ber, 1 );
236 
237 	if ( tag == LBER_ERROR ) {
238 		if ( drhead != NULL ) {
239 			ldap_derefresponse_free( drhead );
240 		}
241 
242 		*drp2 = NULL;
243 		ld->ld_errno = LDAP_DECODING_ERROR;
244 
245 	} else {
246 		*drp2 = drhead;
247 		ld->ld_errno = LDAP_SUCCESS;
248 	}
249 
250 	return ld->ld_errno;
251 }
252 
253 int
254 ldap_parse_deref_control(
255 	LDAP		*ld,
256 	LDAPControl	**ctrls,
257 	LDAPDerefRes	**drp )
258 {
259 	LDAPControl *c;
260 
261 	if ( drp == NULL ) {
262 		ld->ld_errno = LDAP_PARAM_ERROR;
263 		return ld->ld_errno;
264 	}
265 
266 	*drp = NULL;
267 
268 	if ( ctrls == NULL ) {
269 		ld->ld_errno =  LDAP_CONTROL_NOT_FOUND;
270 		return ld->ld_errno;
271 	}
272 
273 	c = ldap_control_find( LDAP_CONTROL_X_DEREF, ctrls, NULL );
274 	if ( c == NULL ) {
275 		/* No deref control was found. */
276 		ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
277 		return ld->ld_errno;
278 	}
279 
280 	ld->ld_errno = ldap_parse_derefresponse_control( ld, c, drp );
281 
282 	return ld->ld_errno;
283 }
284 
285