]> git.sur5r.net Git - openldap/blob - libraries/libldap/controls.c
Add OpenLDAP RCSid to *.[ch] in clients, libraries, and servers.
[openldap] / libraries / libldap / controls.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-1999 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         assert( c != NULL );
230
231         if ( c != NULL ) {
232                 if( c->ldctl_oid != NULL) {
233                         LDAP_FREE( c->ldctl_oid );
234                 }
235
236                 if( c->ldctl_value.bv_val != NULL ) {
237                         LDAP_FREE( c->ldctl_value.bv_val );
238                 }
239
240                 LDAP_FREE( c );
241         }
242 }
243
244 /*
245  * Free an array of LDAPControl's
246  */
247 void
248 ldap_controls_free( LDAPControl **controls )
249 {
250         assert( controls != NULL );
251
252         if ( controls != NULL ) {
253                 int i;
254
255                 for( i=0; controls[i] != NULL; i++) {
256                         ldap_control_free( controls[i] );
257                 }
258
259                 LDAP_FREE( controls );
260         }
261 }
262
263 /*
264  * Duplicate an array of LDAPControl
265  */
266 LDAPControl **
267 ldap_controls_dup( LDAPControl *const *controls )
268 {
269         LDAPControl **new;
270         int i;
271
272         if ( controls == NULL ) {
273                 return NULL;
274         }
275
276         /* count the controls */
277         for(i=0; controls[i] != NULL; i++) /* empty */ ;
278
279         if( i < 1 ) {
280                 /* no controls to duplicate */
281                 return NULL;
282         }
283
284         new = (LDAPControl **) LDAP_MALLOC( i * sizeof(LDAPControl *) );
285
286         if( new == NULL ) {
287                 /* memory allocation failure */
288                 return NULL;
289         }
290
291         /* duplicate the controls */
292         for(i=0; controls[i] != NULL; i++) {
293                 new[i] = ldap_control_dup( controls[i] );
294
295                 if( new[i] == NULL ) {
296                         ldap_controls_free( new );
297                         return NULL;
298                 }
299         }
300
301         new[i] = NULL;
302
303         return new;
304 }
305
306 /*
307  * Duplicate a LDAPControl
308  */
309 LDAPControl *
310 ldap_control_dup( const LDAPControl *c )
311 {
312         LDAPControl *new;
313
314         if ( c == NULL ) {
315                 return NULL;
316         }
317
318         new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
319
320         if( new == NULL ) {
321                 return NULL;
322         }
323
324         if( c->ldctl_oid != NULL ) {
325                 new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
326
327                 if(new->ldctl_oid == NULL) {
328                         LDAP_FREE( new );
329                         return NULL;
330                 }
331
332         } else {
333                 new->ldctl_oid = NULL;
334         }
335
336         if( c->ldctl_value.bv_len > 0 ) {
337                 new->ldctl_value.bv_val = (char *) LDAP_MALLOC( c->ldctl_value.bv_len );
338
339                 if(new->ldctl_value.bv_val == NULL) {
340                         if(new->ldctl_oid != NULL) {
341                                 LDAP_FREE( new->ldctl_oid );
342                         }
343                         LDAP_FREE( new );
344                         return NULL;
345                 }
346                 
347                 SAFEMEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, 
348                         c->ldctl_value.bv_len );
349
350                 new->ldctl_value.bv_len = c->ldctl_value.bv_len;
351
352         } else {
353                 new->ldctl_value.bv_len = 0;
354                 new->ldctl_value.bv_val = NULL;
355         }
356
357         new->ldctl_iscritical = c->ldctl_iscritical;
358         return new;
359 }