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