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