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