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