]> git.sur5r.net Git - openldap/blob - libraries/libldap/controls.c
Initial implementation of ldap_int_get_controls()... EXPERIMENTAL.
[openldap] / libraries / libldap / controls.c
1 /*
2  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5 /*
6  * LDAP controls
7  */
8
9 #include "portable.h"
10
11 #include <stdlib.h>
12
13 #include <ac/time.h>
14 #include <ac/string.h>
15
16 #include "ldap-int.h"
17
18
19 /*
20  * ldap_int_put_controls
21  */
22
23 int ldap_int_put_controls(
24         LDAP *ld,
25         LDAPControl **ctrls,
26         BerElement *ber )
27 {
28         LDAPControl **c;
29
30         assert( ld != NULL );
31         assert( ber != NULL );
32
33         if( ctrls == NULL ) {
34                 /* use default server controls */
35                 ctrls = ld->ld_sctrls;
36         }
37
38         if( ctrls == NULL || *ctrls == NULL ) {
39                 return LDAP_SUCCESS;
40         }
41
42         if ( ld->ld_version < LDAP_VERSION3 ) {
43                 /* LDAPv2 doesn't support controls,
44                  * error if any control is critical
45                  */
46                 for( c = ctrls ; *c != NULL; c++ ) {
47                         if( (*c)->ldctl_iscritical ) {
48                                 ld->ld_errno = LDAP_NOT_SUPPORTED;
49                                 return ld->ld_errno;
50                         }
51                 }
52
53                 return LDAP_SUCCESS;
54         }
55
56         /* Controls are encoded as a sequence of sequences */
57         if( ber_printf( ber, "t{", LDAP_TAG_CONTROLS ) == -1 ) {
58                 ld->ld_errno = LDAP_ENCODING_ERROR;
59                 return ld->ld_errno;
60         }
61
62         for( c = ctrls ; *c != NULL; c++ ) {
63                 if ( ber_printf( ber, "{s",
64                         (*c)->ldctl_oid ) == -1 )
65                 {
66                         ld->ld_errno = LDAP_ENCODING_ERROR;
67                         return ld->ld_errno;
68                 }
69
70                 if( (*c)->ldctl_iscritical /* only if true */
71                         &&  ( ber_printf( ber, "b",
72                                 (*c)->ldctl_iscritical ) == -1 ) )
73                 {
74                         ld->ld_errno = LDAP_ENCODING_ERROR;
75                         return ld->ld_errno;
76                 }
77
78                 if( (*c)->ldctl_value.bv_val != NULL /* only if we have a value */
79                         &&  ( ber_printf( ber, "O",
80                                 &((*c)->ldctl_value) ) == -1 ) )
81                 {
82                         ld->ld_errno = LDAP_ENCODING_ERROR;
83                         return ld->ld_errno;
84                 }
85
86
87                 if( ber_printf( ber, "}" ) == -1 ) {
88                         ld->ld_errno = LDAP_ENCODING_ERROR;
89                         return ld->ld_errno;
90                 }
91         }
92
93
94         if( ber_printf( ber, "}" ) == -1 ) {
95                 ld->ld_errno = LDAP_ENCODING_ERROR;
96                 return ld->ld_errno;
97         }
98
99         return LDAP_SUCCESS;
100 }
101
102 int ldap_int_get_controls LDAP_P((
103         BerElement *ber,
104         LDAPControl ***ctrls ))
105 {
106         int nctrls;
107         unsigned long tag, len;
108         char *opaque;
109
110         assert( ber != NULL );
111         assert( ctrls != NULL );
112
113         *ctrls = NULL;
114
115         len = ber->ber_end - ber->ber_ptr;
116
117         if( len == 0) {
118                 /* no controls */
119                 return LDAP_SUCCESS;
120         }
121
122         if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
123                 if( tag == LBER_ERROR ) {
124                         /* decoding error */
125                         return LDAP_DECODING_ERROR;
126                 }
127
128                 /* ignore unexpected input */
129                 return LDAP_SUCCESS;
130         }
131
132         /* set through each element */
133         nctrls = 0;
134         *ctrls = malloc( 1 * sizeof(LDAPControl *) );
135
136         if( *ctrls == NULL ) {
137                 return LDAP_NO_MEMORY;
138         }
139
140         ctrls[nctrls] = NULL;
141
142         for( tag = ber_first_element( ber, &len, &opaque );
143                 (
144                         tag != LBER_ERROR
145 #ifdef LDAP_END_SEQORSET
146                         && tag != LBER_END_OF_SEQORSET
147 #endif
148                 );
149                 tag = ber_next_element( ber, &len, opaque ) )
150         {
151                 LDAPControl *tctrl;
152                 LDAPControl **tctrls;
153
154                 tctrl = calloc( 1, sizeof(LDAPControl) );
155
156                 /* allocate pointer space for current controls (nctrls)
157                  * + this control + extra NULL
158                  */
159                 tctrls = (tctrl == NULL) ? NULL :
160                         realloc(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
161
162                 if( tctrls == NULL ) {
163                         /* one of the above allocation failed */
164
165                         if( tctrl != NULL ) {
166                                 free( tctrl );
167                         }
168
169                         ldap_controls_free(*ctrls);
170                         *ctrls = NULL;
171
172                         return LDAP_NO_MEMORY;
173                 }
174
175
176                 tctrls[nctrls++] = tctrl;
177                 tctrls[nctrls] = NULL;
178
179                 tag = ber_scanf( ber, "{a", &tctrl->ldctl_oid );
180
181                 if( tag != LBER_ERROR ) {
182                         tag = ber_peek_tag( ber, &len );
183                 }
184
185                 if( tag == LBER_BOOLEAN ) {
186                         tag = ber_scanf( ber, "b", &tctrl->ldctl_iscritical );
187                 }
188
189                 if( tag != LBER_ERROR ) {
190                         tag = ber_peek_tag( ber, &len );
191                 }
192
193                 if( tag == LBER_OCTETSTRING ) {
194                         tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
195
196                 } else {
197                         tctrl->ldctl_value.bv_val = NULL;
198                 }
199
200                 if( tag == LBER_ERROR ) {
201                         *ctrls = NULL;
202                         ldap_controls_free( tctrls );
203                         return LDAP_DECODING_ERROR;
204                 }
205
206                 *ctrls = tctrls;
207         }
208                 
209         return LDAP_SUCCESS;
210 }
211
212 /*
213  * Free a LDAPControl
214  */
215 void
216 ldap_control_free( LDAPControl *c )
217 {
218         if ( c != NULL ) {
219                 if( c->ldctl_oid != NULL) {
220                         free( c->ldctl_oid );
221                 }
222
223                 if( c->ldctl_value.bv_val != NULL ) {
224                         free( c->ldctl_value.bv_val );
225                 }
226
227                 free( c );
228         }
229 }
230
231 /*
232  * Free an array of LDAPControl's
233  */
234 void
235 ldap_controls_free( LDAPControl **controls )
236 {
237         if ( controls != NULL ) {
238                 LDAPControl *c;
239
240                 for(c = *controls; c != NULL; c++) {
241                         ldap_control_free( c );
242                 }
243
244                 free( controls );
245         }
246 }
247
248 /*
249  * Duplicate an array of LDAPControl
250  */
251 LDAPControl **ldap_controls_dup( const LDAPControl **controls )
252 {
253         LDAPControl **new;
254         int i;
255
256         if ( controls == NULL ) {
257                 return NULL;
258         }
259
260         /* count the controls */
261         for(i=0; controls[i] != NULL; i++) /* empty */ ;
262
263         if( i < 1 ) {
264                 /* no controls to duplicate */
265                 return NULL;
266         }
267
268         new = (LDAPControl **) malloc( i * sizeof(LDAPControl *) );
269
270         if( new == NULL ) {
271                 /* memory allocation failure */
272                 return NULL;
273         }
274
275         /* duplicate the controls */
276         for(i=0; controls[i] != NULL; i++) {
277                 new[i] = ldap_control_dup( controls[i] );
278
279                 if( new[i] == NULL ) {
280                         ldap_controls_free( new );
281                         return NULL;
282                 }
283         }
284
285         new[i] = NULL;
286
287         return new;
288 }
289
290 /*
291  * Duplicate a LDAPControl
292  */
293 LDAPControl *ldap_control_dup( const LDAPControl *c )
294 {
295         LDAPControl *new;
296
297         if ( c == NULL ) {
298                 return NULL;
299         }
300
301         new = (LDAPControl *) malloc( sizeof(LDAPControl) );
302
303         if( new == NULL ) {
304                 return NULL;
305         }
306
307         if( c->ldctl_oid != NULL ) {
308                 new->ldctl_oid = strdup( c->ldctl_oid );
309
310                 if(new->ldctl_oid == NULL) {
311                         free( new );
312                         return NULL;
313                 }
314
315         } else {
316                 new->ldctl_oid = NULL;
317         }
318
319         if( c->ldctl_value.bv_len > 0 ) {
320                 new->ldctl_value.bv_val = (char *) malloc( c->ldctl_value.bv_len );
321
322                 if(new->ldctl_value.bv_val == NULL) {
323                         if(new->ldctl_oid != NULL) {
324                                 free( new->ldctl_oid );
325                         }
326                         free( new );
327                         return NULL;
328                 }
329                 
330                 SAFEMEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, 
331                         c->ldctl_value.bv_len );
332
333                 new->ldctl_value.bv_len = c->ldctl_value.bv_len;
334
335         } else {
336                 new->ldctl_value.bv_len = 0;
337                 new->ldctl_value.bv_val = NULL;
338         }
339
340         new->ldctl_iscritical = c->ldctl_iscritical;
341         return new;
342 }