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