]> git.sur5r.net Git - openldap/blob - libraries/libldap/controls.c
b609b7bc5660cd0c180fe2df01663248bda74c69
[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                                 (ber_int_t) (*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(
111         BerElement *ber,
112         LDAPControl ***ctrls )
113 {
114         int nctrls;
115         ber_tag_t tag;
116         ber_len_t len;
117         char *opaque;
118
119         assert( ber != NULL );
120         assert( ctrls != NULL );
121
122         *ctrls = NULL;
123
124         len = ber_pvt_ber_remaining(ber);
125
126         if( len == 0) {
127                 /* no controls */
128                 return LDAP_SUCCESS;
129         }
130
131         if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
132                 if( tag == LBER_ERROR ) {
133                         /* decoding error */
134                         return LDAP_DECODING_ERROR;
135                 }
136
137                 /* ignore unexpected input */
138                 return LDAP_SUCCESS;
139         }
140
141         /* set through each element */
142         nctrls = 0;
143         *ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) );
144
145         if( *ctrls == NULL ) {
146                 return LDAP_NO_MEMORY;
147         }
148
149         ctrls[nctrls] = NULL;
150
151         for( tag = ber_first_element( ber, &len, &opaque );
152                 tag != LBER_ERROR;
153                 tag = ber_next_element( ber, &len, opaque ) )
154         {
155                 LDAPControl *tctrl;
156                 LDAPControl **tctrls;
157
158                 tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) );
159
160                 /* allocate pointer space for current controls (nctrls)
161                  * + this control + extra NULL
162                  */
163                 tctrls = (tctrl == NULL) ? NULL :
164                         LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
165
166                 if( tctrls == NULL ) {
167                         /* one of the above allocation failed */
168
169                         if( tctrl != NULL ) {
170                                 LDAP_FREE( tctrl );
171                         }
172
173                         ldap_controls_free(*ctrls);
174                         *ctrls = NULL;
175
176                         return LDAP_NO_MEMORY;
177                 }
178
179
180                 tctrls[nctrls++] = tctrl;
181                 tctrls[nctrls] = NULL;
182
183                 tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
184
185                 if( tag != LBER_ERROR ) {
186                         tag = ber_peek_tag( ber, &len );
187                 }
188
189                 if( tag == LBER_BOOLEAN ) {
190                         ber_int_t crit;
191                         tag = ber_scanf( ber, "b", &crit );
192                         tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
193                 }
194
195                 if( tag != LBER_ERROR ) {
196                         tag = ber_peek_tag( ber, &len );
197                 }
198
199                 if( tag == LBER_OCTETSTRING ) {
200                         tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
201
202                 } else {
203                         tctrl->ldctl_value.bv_val = NULL;
204                 }
205
206                 if( tag == LBER_ERROR ) {
207                         *ctrls = NULL;
208                         ldap_controls_free( tctrls );
209                         return LDAP_DECODING_ERROR;
210                 }
211
212                 *ctrls = tctrls;
213         }
214                 
215         return LDAP_SUCCESS;
216 }
217
218 /*
219  * Free a LDAPControl
220  */
221 void
222 ldap_control_free( LDAPControl *c )
223 {
224         assert( c != NULL );
225
226         if ( c != NULL ) {
227                 if( c->ldctl_oid != NULL) {
228                         LDAP_FREE( c->ldctl_oid );
229                 }
230
231                 if( c->ldctl_value.bv_val != NULL ) {
232                         LDAP_FREE( c->ldctl_value.bv_val );
233                 }
234
235                 LDAP_FREE( c );
236         }
237 }
238
239 /*
240  * Free an array of LDAPControl's
241  */
242 void
243 ldap_controls_free( LDAPControl **controls )
244 {
245         assert( controls != NULL );
246
247         if ( controls != NULL ) {
248                 LDAPControl *c;
249
250                 for(c = *controls; c != NULL; c++) {
251                         ldap_control_free( c );
252                 }
253
254                 LDAP_FREE( controls );
255         }
256 }
257
258 /*
259  * Duplicate an array of LDAPControl
260  */
261 LDAPControl **ldap_controls_dup( LDAPControl **controls )
262 {
263         LDAPControl **new;
264         int i;
265
266         if ( controls == NULL ) {
267                 return NULL;
268         }
269
270         /* count the controls */
271         for(i=0; controls[i] != NULL; i++) /* empty */ ;
272
273         if( i < 1 ) {
274                 /* no controls to duplicate */
275                 return NULL;
276         }
277
278         new = (LDAPControl **) LDAP_MALLOC( i * sizeof(LDAPControl *) );
279
280         if( new == NULL ) {
281                 /* memory allocation failure */
282                 return NULL;
283         }
284
285         /* duplicate the controls */
286         for(i=0; controls[i] != NULL; i++) {
287                 new[i] = ldap_control_dup( controls[i] );
288
289                 if( new[i] == NULL ) {
290                         ldap_controls_free( new );
291                         return NULL;
292                 }
293         }
294
295         new[i] = NULL;
296
297         return new;
298 }
299
300 /*
301  * Duplicate a LDAPControl
302  */
303 LDAPControl *ldap_control_dup( LDAPControl *c )
304 {
305         LDAPControl *new;
306
307         if ( c == NULL ) {
308                 return NULL;
309         }
310
311         new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
312
313         if( new == NULL ) {
314                 return NULL;
315         }
316
317         if( c->ldctl_oid != NULL ) {
318                 new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
319
320                 if(new->ldctl_oid == NULL) {
321                         LDAP_FREE( new );
322                         return NULL;
323                 }
324
325         } else {
326                 new->ldctl_oid = NULL;
327         }
328
329         if( c->ldctl_value.bv_len > 0 ) {
330                 new->ldctl_value.bv_val = (char *) LDAP_MALLOC( c->ldctl_value.bv_len );
331
332                 if(new->ldctl_value.bv_val == NULL) {
333                         if(new->ldctl_oid != NULL) {
334                                 LDAP_FREE( new->ldctl_oid );
335                         }
336                         LDAP_FREE( new );
337                         return NULL;
338                 }
339                 
340                 SAFEMEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, 
341                         c->ldctl_value.bv_len );
342
343                 new->ldctl_value.bv_len = c->ldctl_value.bv_len;
344
345         } else {
346                 new->ldctl_value.bv_len = 0;
347                 new->ldctl_value.bv_val = NULL;
348         }
349
350         new->ldctl_iscritical = c->ldctl_iscritical;
351         return new;
352 }