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