]> git.sur5r.net Git - openldap/blob - libraries/libldap/extended.c
VLV clean
[openldap] / libraries / libldap / extended.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 /*
8  * LDAPv3 Extended Operation Request
9  *      ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
10  *              requestName      [0] LDAPOID,
11  *              requestValue     [1] OCTET STRING OPTIONAL
12  *      }
13  *
14  * LDAPv3 Extended Operation Response
15  *      ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
16  *              COMPONENTS OF LDAPResult,
17  *              responseName     [10] LDAPOID OPTIONAL,
18  *              response         [11] OCTET STRING OPTIONAL
19  *      }
20  *
21  */
22
23 #include "portable.h"
24
25 #include <stdio.h>
26 #include <ac/stdlib.h>
27
28 #include <ac/socket.h>
29 #include <ac/string.h>
30 #include <ac/time.h>
31
32 #include "ldap-int.h"
33
34 int
35 ldap_extended_operation(
36         LDAP                    *ld,
37         LDAP_CONST char *reqoid,
38         struct berval   *reqdata,
39         LDAPControl             **sctrls,
40         LDAPControl             **cctrls,
41         int                             *msgidp )
42 {
43         BerElement *ber;
44         int rc;
45
46 #ifdef NEW_LOGGING
47         LDAP_LOG (( "extended", LDAP_LEVEL_ENTRY, "ldap_extended_operation\n" ));
48 #else
49         Debug( LDAP_DEBUG_TRACE, "ldap_extended_operation\n", 0, 0, 0 );
50 #endif
51
52         assert( ld != NULL );
53         assert( LDAP_VALID( ld ) );
54         assert( reqoid != NULL || *reqoid == '\0' );
55         assert( msgidp != NULL );
56
57         /* must be version 3 (or greater) */
58         if ( ld->ld_version < LDAP_VERSION3 ) {
59                 ld->ld_errno = LDAP_NOT_SUPPORTED;
60                 return( ld->ld_errno );
61         }
62
63         /* create a message to send */
64         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
65                 ld->ld_errno = LDAP_NO_MEMORY;
66                 return( ld->ld_errno );
67         }
68
69         if ( reqdata != NULL ) {
70                 rc = ber_printf( ber, "{it{tstON}", /* '}' */
71                         ++ld->ld_msgid, LDAP_REQ_EXTENDED,
72                         LDAP_TAG_EXOP_REQ_OID, reqoid,
73                         LDAP_TAG_EXOP_REQ_VALUE, reqdata );
74
75         } else {
76                 rc = ber_printf( ber, "{it{tsN}", /* '}' */
77                         ++ld->ld_msgid, LDAP_REQ_EXTENDED,
78                         LDAP_TAG_EXOP_REQ_OID, reqoid );
79         }
80
81         if( rc == -1 ) {
82                 ld->ld_errno = LDAP_ENCODING_ERROR;
83                 ber_free( ber, 1 );
84                 return( ld->ld_errno );
85         }
86
87         /* Put Server Controls */
88         if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
89                 ber_free( ber, 1 );
90                 return ld->ld_errno;
91         }
92
93         if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
94                 ld->ld_errno = LDAP_ENCODING_ERROR;
95                 ber_free( ber, 1 );
96                 return( ld->ld_errno );
97         }
98
99         /* send the message */
100         *msgidp = ldap_send_initial_request( ld, LDAP_REQ_EXTENDED, NULL, ber );
101
102         return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
103 }
104
105 int
106 ldap_extended_operation_s(
107         LDAP                    *ld,
108         LDAP_CONST char *reqoid,
109         struct berval   *reqdata,
110         LDAPControl             **sctrls,
111         LDAPControl             **cctrls,
112         char                    **retoidp,
113         struct berval   **retdatap )
114 {
115     int     rc;
116     int     msgid;
117     LDAPMessage *res;
118
119 #ifdef NEW_LOGGING
120         LDAP_LOG (( "extended", LDAP_LEVEL_ENTRY, "ldap_extended_operation_s\n" ));
121 #else
122         Debug( LDAP_DEBUG_TRACE, "ldap_extended_operation_s\n", 0, 0, 0 );
123 #endif
124
125         assert( ld != NULL );
126         assert( LDAP_VALID( ld ) );
127         assert( reqoid != NULL || *reqoid == '\0' );
128         assert( retoidp != NULL || retdatap != NULL );
129
130     rc = ldap_extended_operation( ld, reqoid, reqdata,
131                 sctrls, cctrls, &msgid );
132         
133     if ( rc != LDAP_SUCCESS ) {
134         return( rc );
135         }
136  
137     if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 ) {
138         return( ld->ld_errno );
139         }
140
141         *retoidp = NULL;
142         *retdatap = NULL;
143
144         rc = ldap_parse_extended_result( ld, res, retoidp, retdatap, 0 );
145
146         if( rc != LDAP_SUCCESS ) {
147                 ldap_msgfree( res );
148                 return rc;
149         }
150
151     return( ldap_result2error( ld, res, 1 ) );
152 }
153
154 /* Parse an extended result */
155 int
156 ldap_parse_extended_result (
157         LDAP                    *ld,
158         LDAPMessage             *res,
159         char                    **retoidp,
160         struct berval   **retdatap,
161         int                             freeit )
162 {
163         BerElement *ber;
164         ber_tag_t rc;
165         ber_tag_t tag;
166         ber_len_t len;
167         struct berval *resdata;
168         ber_int_t errcode;
169         char *resoid;
170
171         assert( ld != NULL );
172         assert( LDAP_VALID( ld ) );
173         assert( res != NULL );
174
175 #ifdef NEW_LOGGING
176         LDAP_LOG (( "extended", LDAP_LEVEL_ENTRY, "ldap_parse_extended_result\n" ));
177 #else
178         Debug( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n", 0, 0, 0 );
179 #endif
180
181         if( ld->ld_version < LDAP_VERSION3 ) {
182                 ld->ld_errno = LDAP_NOT_SUPPORTED;
183                 return ld->ld_errno;
184         }
185
186         if( res->lm_msgtype != LDAP_RES_EXTENDED ) {
187                 ld->ld_errno = LDAP_PARAM_ERROR;
188                 return ld->ld_errno;
189         }
190
191         if( retoidp != NULL ) *retoidp = NULL;
192         if( retdatap != NULL ) *retdatap = NULL;
193
194         if ( ld->ld_error ) {
195                 LDAP_FREE( ld->ld_error );
196                 ld->ld_error = NULL;
197         }
198
199         if ( ld->ld_matched ) {
200                 LDAP_FREE( ld->ld_matched );
201                 ld->ld_matched = NULL;
202         }
203
204         ber = ber_dup( res->lm_ber );
205
206         if ( ber == NULL ) {
207                 ld->ld_errno = LDAP_NO_MEMORY;
208                 return ld->ld_errno;
209         }
210
211         rc = ber_scanf( ber, "{iaa" /*}*/, &errcode,
212                 &ld->ld_matched, &ld->ld_error );
213
214         if( rc == LBER_ERROR ) {
215                 ld->ld_errno = LDAP_DECODING_ERROR;
216                 ber_free( ber, 0 );
217                 return ld->ld_errno;
218         }
219
220         resoid = NULL;
221         resdata = NULL;
222
223         tag = ber_peek_tag( ber, &len );
224
225         if( tag == LDAP_TAG_REFERRAL ) {
226                 /* skip over referral */
227                 if( ber_scanf( ber, "x" ) == LBER_ERROR ) {
228                         ld->ld_errno = LDAP_DECODING_ERROR;
229                         ber_free( ber, 0 );
230                         return ld->ld_errno;
231                 }
232
233                 tag = ber_peek_tag( ber, &len );
234         }
235
236         if( tag == LDAP_TAG_EXOP_RES_OID ) {
237                 /* we have a resoid */
238                 if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) {
239                         ld->ld_errno = LDAP_DECODING_ERROR;
240                         ber_free( ber, 0 );
241                         return ld->ld_errno;
242                 }
243
244                 tag = ber_peek_tag( ber, &len );
245         }
246
247         if( tag == LDAP_TAG_EXOP_RES_VALUE ) {
248                 /* we have a resdata */
249                 if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) {
250                         ld->ld_errno = LDAP_DECODING_ERROR;
251                         ber_free( ber, 0 );
252                         if( resoid != NULL ) LDAP_FREE( resoid );
253                         return ld->ld_errno;
254                 }
255         }
256
257         ber_free( ber, 0 );
258
259         if( retoidp != NULL ) {
260                 *retoidp = resoid;
261         } else {
262                 LDAP_FREE( resoid );
263         }
264
265         if( retdatap != NULL ) {
266                 *retdatap = resdata;
267         } else {
268                 ber_bvfree( resdata );
269         }
270
271         ld->ld_errno = errcode;
272
273         if( freeit ) {
274                 ldap_msgfree( res );
275         }
276
277         return LDAP_SUCCESS;
278 }
279
280
281 /* Parse an extended partial */
282 int
283 ldap_parse_extended_partial (
284         LDAP                    *ld,
285         LDAPMessage             *res,
286         char                    **retoidp,
287         struct berval   **retdatap,
288         LDAPControl             ***serverctrls,
289         int                             freeit )
290 {
291         BerElement *ber;
292         ber_tag_t rc;
293         ber_tag_t tag;
294         ber_len_t len;
295         struct berval *resdata;
296         char *resoid;
297
298         assert( ld != NULL );
299         assert( LDAP_VALID( ld ) );
300         assert( res != NULL );
301
302 #ifdef NEW_LOGGING
303         LDAP_LOG (( "extended", LDAP_LEVEL_ENTRY, 
304                 "ldap_parse_extended_partial\n" ));
305 #else
306         Debug( LDAP_DEBUG_TRACE, "ldap_parse_extended_partial\n", 0, 0, 0 );
307 #endif
308
309         if( ld->ld_version < LDAP_VERSION3 ) {
310                 ld->ld_errno = LDAP_NOT_SUPPORTED;
311                 return ld->ld_errno;
312         }
313
314         if( res->lm_msgtype != LDAP_RES_EXTENDED_PARTIAL ) {
315                 ld->ld_errno = LDAP_PARAM_ERROR;
316                 return ld->ld_errno;
317         }
318
319         if( retoidp != NULL ) *retoidp = NULL;
320         if( retdatap != NULL ) *retdatap = NULL;
321
322         ber = ber_dup( res->lm_ber );
323
324         if ( ber == NULL ) {
325                 ld->ld_errno = LDAP_NO_MEMORY;
326                 return ld->ld_errno;
327         }
328
329         rc = ber_scanf( ber, "{" /*}*/ );
330
331         if( rc == LBER_ERROR ) {
332                 ld->ld_errno = LDAP_DECODING_ERROR;
333                 ber_free( ber, 0 );
334                 return ld->ld_errno;
335         }
336
337         resoid = NULL;
338         resdata = NULL;
339
340         tag = ber_peek_tag( ber, &len );
341
342         if( tag == LDAP_TAG_EXOP_RES_OID ) {
343                 /* we have a resoid */
344                 if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) {
345                         ld->ld_errno = LDAP_DECODING_ERROR;
346                         ber_free( ber, 0 );
347                         return ld->ld_errno;
348                 }
349
350                 tag = ber_peek_tag( ber, &len );
351         }
352
353         if( tag == LDAP_TAG_EXOP_RES_VALUE ) {
354                 /* we have a resdata */
355                 if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) {
356                         ld->ld_errno = LDAP_DECODING_ERROR;
357                         ber_free( ber, 0 );
358                         if( resoid != NULL ) LDAP_FREE( resoid );
359                         return ld->ld_errno;
360                 }
361         }
362
363         if ( serverctrls == NULL ) {
364                 rc = LDAP_SUCCESS;
365                 goto free_and_return;
366         }
367
368         if ( ber_scanf( ber, /*{*/ "}" ) == LBER_ERROR ) {
369                 rc = LDAP_DECODING_ERROR;
370                 goto free_and_return;
371         }
372
373         rc = ldap_int_get_controls( ber, serverctrls );
374
375 free_and_return:
376         ber_free( ber, 0 );
377
378         if( retoidp != NULL ) {
379                 *retoidp = resoid;
380         } else {
381                 LDAP_FREE( resoid );
382         }
383
384         if( retdatap != NULL ) {
385                 *retdatap = resdata;
386         } else {
387                 ber_bvfree( resdata );
388         }
389
390         if( freeit ) {
391                 ldap_msgfree( res );
392         }
393
394         return LDAP_SUCCESS;
395 }