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