]> git.sur5r.net Git - openldap/blob - libraries/libldap/extended.c
9102e9ccc3d8f2134bf0847ea631043ccff85cc2
[openldap] / libraries / libldap / extended.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2003 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 #include "ldap_log.h"
34
35 int
36 ldap_extended_operation(
37         LDAP                    *ld,
38         LDAP_CONST char *reqoid,
39         struct berval   *reqdata,
40         LDAPControl             **sctrls,
41         LDAPControl             **cctrls,
42         int                             *msgidp )
43 {
44         BerElement *ber;
45         int rc;
46         ber_int_t id;
47
48 #ifdef NEW_LOGGING
49         LDAP_LOG ( OPERATION, ENTRY, "ldap_extended_operation\n", 0,0,0 );
50 #else
51         Debug( LDAP_DEBUG_TRACE, "ldap_extended_operation\n", 0, 0, 0 );
52 #endif
53
54         assert( ld != NULL );
55         assert( LDAP_VALID( ld ) );
56         assert( reqoid != NULL || *reqoid == '\0' );
57         assert( msgidp != NULL );
58
59         /* must be version 3 (or greater) */
60         if ( ld->ld_version < LDAP_VERSION3 ) {
61                 ld->ld_errno = LDAP_NOT_SUPPORTED;
62                 return( ld->ld_errno );
63         }
64
65         /* create a message to send */
66         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
67                 ld->ld_errno = LDAP_NO_MEMORY;
68                 return( ld->ld_errno );
69         }
70
71         LDAP_NEXT_MSGID( ld, id );
72         if ( reqdata != NULL ) {
73                 rc = ber_printf( ber, "{it{tstON}", /* '}' */
74                         id, LDAP_REQ_EXTENDED,
75                         LDAP_TAG_EXOP_REQ_OID, reqoid,
76                         LDAP_TAG_EXOP_REQ_VALUE, reqdata );
77
78         } else {
79                 rc = ber_printf( ber, "{it{tsN}", /* '}' */
80                         id, LDAP_REQ_EXTENDED,
81                         LDAP_TAG_EXOP_REQ_OID, reqoid );
82         }
83
84         if( rc == -1 ) {
85                 ld->ld_errno = LDAP_ENCODING_ERROR;
86                 ber_free( ber, 1 );
87                 return( ld->ld_errno );
88         }
89
90         /* Put Server Controls */
91         if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
92                 ber_free( ber, 1 );
93                 return ld->ld_errno;
94         }
95
96         if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
97                 ld->ld_errno = LDAP_ENCODING_ERROR;
98                 ber_free( ber, 1 );
99                 return( ld->ld_errno );
100         }
101
102         /* send the message */
103         *msgidp = ldap_send_initial_request( ld, LDAP_REQ_EXTENDED, NULL, ber, id );
104
105         return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
106 }
107
108 int
109 ldap_extended_operation_s(
110         LDAP                    *ld,
111         LDAP_CONST char *reqoid,
112         struct berval   *reqdata,
113         LDAPControl             **sctrls,
114         LDAPControl             **cctrls,
115         char                    **retoidp,
116         struct berval   **retdatap )
117 {
118     int     rc;
119     int     msgid;
120     LDAPMessage *res;
121
122 #ifdef NEW_LOGGING
123         LDAP_LOG ( OPERATION, ENTRY, "ldap_extended_operation_s\n", 0,0,0 );
124 #else
125         Debug( LDAP_DEBUG_TRACE, "ldap_extended_operation_s\n", 0, 0, 0 );
126 #endif
127
128         assert( ld != NULL );
129         assert( LDAP_VALID( ld ) );
130         assert( reqoid != NULL || *reqoid == '\0' );
131         assert( retoidp != NULL || retdatap != NULL );
132
133     rc = ldap_extended_operation( ld, reqoid, reqdata,
134                 sctrls, cctrls, &msgid );
135         
136     if ( rc != LDAP_SUCCESS ) {
137         return( rc );
138         }
139  
140     if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 ) {
141         return( ld->ld_errno );
142         }
143
144         if ( retoidp != NULL ) *retoidp = NULL;
145         if ( retdatap != NULL ) *retdatap = NULL;
146
147         rc = ldap_parse_extended_result( ld, res, retoidp, retdatap, 0 );
148
149         if( rc != LDAP_SUCCESS ) {
150                 ldap_msgfree( res );
151                 return rc;
152         }
153
154     return( ldap_result2error( ld, res, 1 ) );
155 }
156
157 /* Parse an extended result */
158 int
159 ldap_parse_extended_result (
160         LDAP                    *ld,
161         LDAPMessage             *res,
162         char                    **retoidp,
163         struct berval   **retdatap,
164         int                             freeit )
165 {
166         BerElement *ber;
167         ber_tag_t rc;
168         ber_tag_t tag;
169         ber_len_t len;
170         struct berval *resdata;
171         ber_int_t errcode;
172         char *resoid;
173
174         assert( ld != NULL );
175         assert( LDAP_VALID( ld ) );
176         assert( res != NULL );
177
178 #ifdef NEW_LOGGING
179         LDAP_LOG ( OPERATION, ENTRY, "ldap_parse_extended_result\n", 0,0,0 );
180 #else
181         Debug( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n", 0, 0, 0 );
182 #endif
183
184         if( ld->ld_version < LDAP_VERSION3 ) {
185                 ld->ld_errno = LDAP_NOT_SUPPORTED;
186                 return ld->ld_errno;
187         }
188
189         if( res->lm_msgtype != LDAP_RES_EXTENDED ) {
190                 ld->ld_errno = LDAP_PARAM_ERROR;
191                 return ld->ld_errno;
192         }
193
194         if( retoidp != NULL ) *retoidp = NULL;
195         if( retdatap != NULL ) *retdatap = NULL;
196
197         if ( ld->ld_error ) {
198                 LDAP_FREE( ld->ld_error );
199                 ld->ld_error = NULL;
200         }
201
202         if ( ld->ld_matched ) {
203                 LDAP_FREE( ld->ld_matched );
204                 ld->ld_matched = NULL;
205         }
206
207         ber = ber_dup( res->lm_ber );
208
209         if ( ber == NULL ) {
210                 ld->ld_errno = LDAP_NO_MEMORY;
211                 return ld->ld_errno;
212         }
213
214         rc = ber_scanf( ber, "{iaa" /*}*/, &errcode,
215                 &ld->ld_matched, &ld->ld_error );
216
217         if( rc == LBER_ERROR ) {
218                 ld->ld_errno = LDAP_DECODING_ERROR;
219                 ber_free( ber, 0 );
220                 return ld->ld_errno;
221         }
222
223         resoid = NULL;
224         resdata = NULL;
225
226         tag = ber_peek_tag( ber, &len );
227
228         if( tag == LDAP_TAG_REFERRAL ) {
229                 /* skip over referral */
230                 if( ber_scanf( ber, "x" ) == LBER_ERROR ) {
231                         ld->ld_errno = LDAP_DECODING_ERROR;
232                         ber_free( ber, 0 );
233                         return ld->ld_errno;
234                 }
235
236                 tag = ber_peek_tag( ber, &len );
237         }
238
239         if( tag == LDAP_TAG_EXOP_RES_OID ) {
240                 /* we have a resoid */
241                 if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) {
242                         ld->ld_errno = LDAP_DECODING_ERROR;
243                         ber_free( ber, 0 );
244                         return ld->ld_errno;
245                 }
246
247                 tag = ber_peek_tag( ber, &len );
248         }
249
250         if( tag == LDAP_TAG_EXOP_RES_VALUE ) {
251                 /* we have a resdata */
252                 if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) {
253                         ld->ld_errno = LDAP_DECODING_ERROR;
254                         ber_free( ber, 0 );
255                         if( resoid != NULL ) LDAP_FREE( resoid );
256                         return ld->ld_errno;
257                 }
258         }
259
260         ber_free( ber, 0 );
261
262         if( retoidp != NULL ) {
263                 *retoidp = resoid;
264         } else {
265                 LDAP_FREE( resoid );
266         }
267
268         if( retdatap != NULL ) {
269                 *retdatap = resdata;
270         } else {
271                 ber_bvfree( resdata );
272         }
273
274         ld->ld_errno = errcode;
275
276         if( freeit ) {
277                 ldap_msgfree( res );
278         }
279
280         return LDAP_SUCCESS;
281 }
282
283
284 /* Parse an extended partial */
285 int
286 ldap_parse_extended_partial (
287         LDAP                    *ld,
288         LDAPMessage             *res,
289         char                    **retoidp,
290         struct berval   **retdatap,
291         LDAPControl             ***serverctrls,
292         int                             freeit )
293 {
294         BerElement *ber;
295         ber_tag_t rc;
296         ber_tag_t tag;
297         ber_len_t len;
298         struct berval *resdata;
299         char *resoid;
300
301         assert( ld != NULL );
302         assert( LDAP_VALID( ld ) );
303         assert( res != NULL );
304
305 #ifdef NEW_LOGGING
306         LDAP_LOG ( OPERATION, ENTRY, "ldap_parse_extended_partial\n", 0,0,0 );
307 #else
308         Debug( LDAP_DEBUG_TRACE, "ldap_parse_extended_partial\n", 0, 0, 0 );
309 #endif
310
311         if( ld->ld_version < LDAP_VERSION3 ) {
312                 ld->ld_errno = LDAP_NOT_SUPPORTED;
313                 return ld->ld_errno;
314         }
315
316         if( res->lm_msgtype != LDAP_RES_EXTENDED_PARTIAL ) {
317                 ld->ld_errno = LDAP_PARAM_ERROR;
318                 return ld->ld_errno;
319         }
320
321         if( retoidp != NULL ) *retoidp = NULL;
322         if( retdatap != NULL ) *retdatap = NULL;
323
324         ber = ber_dup( res->lm_ber );
325
326         if ( ber == NULL ) {
327                 ld->ld_errno = LDAP_NO_MEMORY;
328                 return ld->ld_errno;
329         }
330
331         rc = ber_scanf( ber, "{" /*}*/ );
332
333         if( rc == LBER_ERROR ) {
334                 ld->ld_errno = LDAP_DECODING_ERROR;
335                 ber_free( ber, 0 );
336                 return ld->ld_errno;
337         }
338
339         resoid = NULL;
340         resdata = NULL;
341
342         tag = ber_peek_tag( ber, &len );
343
344         if( tag == LDAP_TAG_EXOP_RES_OID ) {
345                 /* we have a resoid */
346                 if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) {
347                         ld->ld_errno = LDAP_DECODING_ERROR;
348                         ber_free( ber, 0 );
349                         return ld->ld_errno;
350                 }
351
352                 tag = ber_peek_tag( ber, &len );
353         }
354
355         if( tag == LDAP_TAG_EXOP_RES_VALUE ) {
356                 /* we have a resdata */
357                 if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) {
358                         ld->ld_errno = LDAP_DECODING_ERROR;
359                         ber_free( ber, 0 );
360                         if( resoid != NULL ) LDAP_FREE( resoid );
361                         return ld->ld_errno;
362                 }
363         }
364
365         if ( serverctrls == NULL ) {
366                 rc = LDAP_SUCCESS;
367                 goto free_and_return;
368         }
369
370         if ( ber_scanf( ber, /*{*/ "}" ) == LBER_ERROR ) {
371                 rc = LDAP_DECODING_ERROR;
372                 goto free_and_return;
373         }
374
375         rc = ldap_int_get_controls( ber, serverctrls );
376
377 free_and_return:
378         ber_free( ber, 0 );
379
380         if( retoidp != NULL ) {
381                 *retoidp = resoid;
382         } else {
383                 LDAP_FREE( resoid );
384         }
385
386         if( retdatap != NULL ) {
387                 *retdatap = resdata;
388         } else {
389                 ber_bvfree( resdata );
390         }
391
392         if( freeit ) {
393                 ldap_msgfree( res );
394         }
395
396         return LDAP_SUCCESS;
397 }
398
399 #ifdef LDAP_RES_INTERMEDIATE_RESP
400 /* Parse an intermediate response result */
401 int
402 ldap_parse_intermediate_resp_result (
403         LDAP                    *ld,
404         LDAPMessage             *res,
405         char                    **retoidp,
406         struct berval           **retdatap,
407         int                     freeit )
408 {
409         BerElement *ber;
410         ber_tag_t rc;
411         ber_tag_t tag;
412         ber_len_t len;
413         struct berval *resdata;
414         ber_int_t errcode;
415         char *resoid;
416
417         assert( ld != NULL );
418         assert( LDAP_VALID( ld ) );
419         assert( res != NULL );
420
421 #ifdef NEW_LOGGING
422         LDAP_LOG ( OPERATION, ENTRY, "ldap_parse_intermediate_resp_result\n", 0,0,0 );
423 #else
424         Debug( LDAP_DEBUG_TRACE, "ldap_parse_intermediate_resp_result\n", 0, 0, 0 );
425 #endif
426
427         if( ld->ld_version < LDAP_VERSION3 ) {
428                 ld->ld_errno = LDAP_NOT_SUPPORTED;
429                 return ld->ld_errno;
430         }
431
432         if( res->lm_msgtype != LDAP_RES_INTERMEDIATE_RESP ) {
433                 ld->ld_errno = LDAP_PARAM_ERROR;
434                 return ld->ld_errno;
435         }
436
437         if( retoidp != NULL ) *retoidp = NULL;
438         if( retdatap != NULL ) *retdatap = NULL;
439
440         if ( ld->ld_error ) {
441                 LDAP_FREE( ld->ld_error );
442                 ld->ld_error = NULL;
443         }
444
445         if ( ld->ld_matched ) {
446                 LDAP_FREE( ld->ld_matched );
447                 ld->ld_matched = NULL;
448         }
449
450         ber = ber_dup( res->lm_ber );
451
452         if ( ber == NULL ) {
453                 ld->ld_errno = LDAP_NO_MEMORY;
454                 return ld->ld_errno;
455         }
456
457         rc = ber_scanf( ber, "{iaa" /*}*/, &errcode,
458                 &ld->ld_matched, &ld->ld_error );
459
460         if( rc == LBER_ERROR ) {
461                 ld->ld_errno = LDAP_DECODING_ERROR;
462                 ber_free( ber, 0 );
463                 return ld->ld_errno;
464         }
465
466         resoid = NULL;
467         resdata = NULL;
468
469         tag = ber_peek_tag( ber, &len );
470
471         if( tag == LDAP_TAG_EXOP_RES_OID ) {
472                 /* we have a resoid */
473                 if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) {
474                         ld->ld_errno = LDAP_DECODING_ERROR;
475                         ber_free( ber, 0 );
476                         return ld->ld_errno;
477                 }
478
479                 tag = ber_peek_tag( ber, &len );
480         }
481
482         if( tag == LDAP_TAG_EXOP_RES_VALUE ) {
483                 /* we have a resdata */
484                 if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) {
485                         ld->ld_errno = LDAP_DECODING_ERROR;
486                         ber_free( ber, 0 );
487                         if( resoid != NULL ) LDAP_FREE( resoid );
488                         return ld->ld_errno;
489                 }
490         }
491
492         ber_free( ber, 0 );
493
494         if( retoidp != NULL ) {
495                 *retoidp = resoid;
496         } else {
497                 LDAP_FREE( resoid );
498         }
499
500         if( retdatap != NULL ) {
501                 *retdatap = resdata;
502         } else {
503                 ber_bvfree( resdata );
504         }
505
506         ld->ld_errno = errcode;
507
508         if( freeit ) {
509                 ldap_msgfree( res );
510         }
511
512         return LDAP_SUCCESS;
513 }
514 #endif