]> git.sur5r.net Git - openldap/blob - libraries/libldap/controls.c
6a814b80fe053a3082e29928689ef832f8a55f79
[openldap] / libraries / libldap / controls.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2000 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, /*{*/"N}" ) == -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 #ifdef LDAP_MEMORY_DEBUG
230         assert( c != NULL );
231 #endif
232
233         if ( c != NULL ) {
234                 if( c->ldctl_oid != NULL) {
235                         LDAP_FREE( c->ldctl_oid );
236                 }
237
238                 if( c->ldctl_value.bv_val != NULL ) {
239                         LDAP_FREE( c->ldctl_value.bv_val );
240                 }
241
242                 LDAP_FREE( c );
243         }
244 }
245
246 /*
247  * Free an array of LDAPControl's
248  */
249 void
250 ldap_controls_free( LDAPControl **controls )
251 {
252 #ifdef LDAP_MEMORY_DEBUG
253         assert( controls != NULL );
254 #endif
255
256         if ( controls != NULL ) {
257                 int i;
258
259                 for( i=0; controls[i] != NULL; i++) {
260                         ldap_control_free( controls[i] );
261                 }
262
263                 LDAP_FREE( controls );
264         }
265 }
266
267 /*
268  * Duplicate an array of LDAPControl
269  */
270 LDAPControl **
271 ldap_controls_dup( LDAPControl *const *controls )
272 {
273         LDAPControl **new;
274         int i;
275
276         if ( controls == NULL ) {
277                 return NULL;
278         }
279
280         /* count the controls */
281         for(i=0; controls[i] != NULL; i++) /* empty */ ;
282
283         if( i < 1 ) {
284                 /* no controls to duplicate */
285                 return NULL;
286         }
287
288         new = (LDAPControl **) LDAP_MALLOC( i * sizeof(LDAPControl *) );
289
290         if( new == NULL ) {
291                 /* memory allocation failure */
292                 return NULL;
293         }
294
295         /* duplicate the controls */
296         for(i=0; controls[i] != NULL; i++) {
297                 new[i] = ldap_control_dup( controls[i] );
298
299                 if( new[i] == NULL ) {
300                         ldap_controls_free( new );
301                         return NULL;
302                 }
303         }
304
305         new[i] = NULL;
306
307         return new;
308 }
309
310 /*
311  * Duplicate a LDAPControl
312  */
313 LDAPControl *
314 ldap_control_dup( const LDAPControl *c )
315 {
316         LDAPControl *new;
317
318         if ( c == NULL ) {
319                 return NULL;
320         }
321
322         new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
323
324         if( new == NULL ) {
325                 return NULL;
326         }
327
328         if( c->ldctl_oid != NULL ) {
329                 new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
330
331                 if(new->ldctl_oid == NULL) {
332                         LDAP_FREE( new );
333                         return NULL;
334                 }
335
336         } else {
337                 new->ldctl_oid = NULL;
338         }
339
340         if( c->ldctl_value.bv_len > 0 ) {
341                 new->ldctl_value.bv_val = (char *) LDAP_MALLOC( c->ldctl_value.bv_len );
342
343                 if(new->ldctl_value.bv_val == NULL) {
344                         if(new->ldctl_oid != NULL) {
345                                 LDAP_FREE( new->ldctl_oid );
346                         }
347                         LDAP_FREE( new );
348                         return NULL;
349                 }
350                 
351                 AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val, 
352                         c->ldctl_value.bv_len );
353
354                 new->ldctl_value.bv_len = c->ldctl_value.bv_len;
355
356         } else {
357                 new->ldctl_value.bv_len = 0;
358                 new->ldctl_value.bv_val = NULL;
359         }
360
361         new->ldctl_iscritical = c->ldctl_iscritical;
362         return new;
363 }
364
365 /*
366  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
367  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
368  */
369 /* Adapted for inclusion into OpenLDAP by Kurt D. Zeilenga */
370 /*---
371  * This notice applies to changes, created by or for Novell, Inc.,
372  * to preexisting works for which notices appear elsewhere in this file.
373  *
374  * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
375  *
376  * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
377  * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION
378  * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT
379  * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE
380  * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS
381  * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC
382  * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE
383  * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. 
384  *---
385  * Modification to OpenLDAP source by Novell, Inc.
386  * June 2000 sfs  Added control utilities
387  */
388 /*---
389    ldap_create_control
390    
391    Internal function to create an LDAP control from the encoded BerElement.
392
393    requestOID  (IN) The OID to use in creating the control.
394    
395    ber         (IN) The encoded BerElement to use in creating the control.
396    
397    iscritical  (IN) 0 - Indicates the control is not critical to the operation.
398                                         non-zero - The control is critical to the operation.
399                                   
400    ctrlp      (OUT) Returns a pointer to the LDAPControl created.  This control
401                                         SHOULD be freed by calling ldap_control_free() when done.
402 ---*/
403
404 int
405 ldap_create_control(
406         LDAP_CONST char *requestOID,
407         BerElement *ber,
408         int iscritical,
409         LDAPControl **ctrlp )
410 {
411         LDAPControl *ctrl;
412         struct berval *bvalp;
413
414         if ( requestOID == NULL || ber == NULL || ctrlp == NULL ) {
415                 return LDAP_PARAM_ERROR;
416         }
417
418         ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
419         if ( ctrl == NULL ) {
420                 return LDAP_NO_MEMORY;
421         }
422
423         if ( ber_flatten( ber, &bvalp ) == LBER_ERROR ) {
424                 LDAP_FREE( ctrl );
425                 return LDAP_NO_MEMORY;
426         }
427
428         ctrl->ldctl_value = *bvalp;
429         ber_memfree( bvalp );
430
431         ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
432         ctrl->ldctl_iscritical = iscritical;
433
434         if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
435                 ldap_control_free( ctrl );
436                 return LDAP_NO_MEMORY;
437         }
438
439         *ctrlp = ctrl;
440         return LDAP_SUCCESS;
441 }