]> git.sur5r.net Git - openldap/blob - libraries/libldap/extended.c
Added LDAP_LOG messages
[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         if( reqoid == NULL || *reqoid == '\0' || msgidp == NULL ) {
64                 ld->ld_errno = LDAP_PARAM_ERROR;
65                 return( ld->ld_errno );
66         }
67
68         /* create a message to send */
69         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
70                 ld->ld_errno = LDAP_NO_MEMORY;
71                 return( ld->ld_errno );
72         }
73
74         if ( reqdata != NULL ) {
75                 rc = ber_printf( ber, "{it{tstON}", /* '}' */
76                         ++ld->ld_msgid, LDAP_REQ_EXTENDED,
77                         LDAP_TAG_EXOP_REQ_OID, reqoid,
78                         LDAP_TAG_EXOP_REQ_VALUE, reqdata );
79
80         } else {
81                 rc = ber_printf( ber, "{it{tsN}", /* '}' */
82                         ++ld->ld_msgid, LDAP_REQ_EXTENDED,
83                         LDAP_TAG_EXOP_REQ_OID, reqoid );
84         }
85
86         if( rc == -1 ) {
87                 ld->ld_errno = LDAP_ENCODING_ERROR;
88                 ber_free( ber, 1 );
89                 return( ld->ld_errno );
90         }
91
92         /* Put Server Controls */
93         if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
94                 ber_free( ber, 1 );
95                 return ld->ld_errno;
96         }
97
98         if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
99                 ld->ld_errno = LDAP_ENCODING_ERROR;
100                 ber_free( ber, 1 );
101                 return( ld->ld_errno );
102         }
103
104         /* send the message */
105         *msgidp = ldap_send_initial_request( ld, LDAP_REQ_EXTENDED, NULL, ber );
106
107         return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
108 }
109
110 int
111 ldap_extended_operation_s(
112         LDAP                    *ld,
113         LDAP_CONST char *reqoid,
114         struct berval   *reqdata,
115         LDAPControl             **sctrls,
116         LDAPControl             **cctrls,
117         char                    **retoidp,
118         struct berval   **retdatap )
119 {
120     int     rc;
121     int     msgid;
122     LDAPMessage *res;
123
124 #ifdef NEW_LOGGING
125         LDAP_LOG (( "extended", LDAP_LEVEL_ENTRY, "ldap_extended_operation_s\n" ));
126 #else
127         Debug( LDAP_DEBUG_TRACE, "ldap_extended_operation_s\n", 0, 0, 0 );
128 #endif
129
130         assert( ld != NULL );
131         assert( LDAP_VALID( ld ) );
132         assert( reqoid != NULL || *reqoid == '\0' );
133         assert( retoidp != NULL || retdatap != NULL );
134
135         if( retoidp == NULL || retdatap == NULL ) {
136                 ld->ld_errno = LDAP_PARAM_ERROR;
137                 return( ld->ld_errno );
138         }
139
140     rc = ldap_extended_operation( ld, reqoid, reqdata,
141                 sctrls, cctrls, &msgid );
142         
143     if ( rc != LDAP_SUCCESS ) {
144         return( rc );
145         }
146  
147     if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 ) {
148         return( ld->ld_errno );
149         }
150
151         *retoidp = NULL;
152         *retdatap = NULL;
153
154         rc = ldap_parse_extended_result( ld, res, retoidp, retdatap, 0 );
155
156         if( rc != LDAP_SUCCESS ) {
157                 ldap_msgfree( res );
158                 return rc;
159         }
160
161     return( ldap_result2error( ld, res, 1 ) );
162 }
163
164 /* Parse an extended result */
165 int
166 ldap_parse_extended_result (
167         LDAP                    *ld,
168         LDAPMessage             *res,
169         char                    **retoidp,
170         struct berval   **retdatap,
171         int                             freeit )
172 {
173         BerElement *ber;
174         ber_tag_t rc;
175         ber_tag_t tag;
176         ber_len_t len;
177         struct berval *resdata;
178         ber_int_t errcode;
179         char *resoid;
180
181         assert( ld != NULL );
182         assert( LDAP_VALID( ld ) );
183         assert( res != NULL );
184
185 #ifdef NEW_LOGGING
186         LDAP_LOG (( "extended", LDAP_LEVEL_ENTRY, "ldap_parse_extended_result\n" ));
187 #else
188         Debug( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n", 0, 0, 0 );
189 #endif
190
191         if( ld->ld_version < LDAP_VERSION3 ) {
192                 ld->ld_errno = LDAP_NOT_SUPPORTED;
193                 return ld->ld_errno;
194         }
195
196         if( res->lm_msgtype != LDAP_RES_EXTENDED ) {
197                 ld->ld_errno = LDAP_PARAM_ERROR;
198                 return ld->ld_errno;
199         }
200
201         if( retoidp != NULL ) *retoidp = NULL;
202         if( retdatap != NULL ) *retdatap = NULL;
203
204         if ( ld->ld_error ) {
205                 LDAP_FREE( ld->ld_error );
206                 ld->ld_error = NULL;
207         }
208
209         if ( ld->ld_matched ) {
210                 LDAP_FREE( ld->ld_matched );
211                 ld->ld_matched = NULL;
212         }
213
214         ber = ber_dup( res->lm_ber );
215
216         if ( ber == NULL ) {
217                 ld->ld_errno = LDAP_NO_MEMORY;
218                 return ld->ld_errno;
219         }
220
221         rc = ber_scanf( ber, "{iaa" /*}*/, &errcode,
222                 &ld->ld_matched, &ld->ld_error );
223
224         if( rc == LBER_ERROR ) {
225                 ld->ld_errno = LDAP_DECODING_ERROR;
226                 ber_free( ber, 0 );
227                 return ld->ld_errno;
228         }
229
230         resoid = NULL;
231         resdata = NULL;
232
233         tag = ber_peek_tag( ber, &len );
234
235         if( tag == LDAP_TAG_REFERRAL ) {
236                 /* skip over referral */
237                 if( ber_scanf( ber, "x" ) == LBER_ERROR ) {
238                         ld->ld_errno = LDAP_DECODING_ERROR;
239                         ber_free( ber, 0 );
240                         return ld->ld_errno;
241                 }
242
243                 tag = ber_peek_tag( ber, &len );
244         }
245
246         if( tag == LDAP_TAG_EXOP_RES_OID ) {
247                 /* we have a resoid */
248                 if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) {
249                         ld->ld_errno = LDAP_DECODING_ERROR;
250                         ber_free( ber, 0 );
251                         return ld->ld_errno;
252                 }
253
254                 tag = ber_peek_tag( ber, &len );
255         }
256
257         if( tag == LDAP_TAG_EXOP_RES_VALUE ) {
258                 /* we have a resdata */
259                 if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) {
260                         ld->ld_errno = LDAP_DECODING_ERROR;
261                         ber_free( ber, 0 );
262                         if( resoid != NULL ) LDAP_FREE( resoid );
263                         return ld->ld_errno;
264                 }
265         }
266
267         ber_free( ber, 0 );
268
269         if( retoidp != NULL ) {
270                 *retoidp = resoid;
271         } else {
272                 LDAP_FREE( resoid );
273         }
274
275         if( retdatap != NULL ) {
276                 *retdatap = resdata;
277         } else {
278                 ber_bvfree( resdata );
279         }
280
281         ld->ld_errno = errcode;
282
283         if( freeit ) {
284                 ldap_msgfree( res );
285         }
286
287         return LDAP_SUCCESS;
288 }
289
290
291 /* Parse an extended partial */
292 int
293 ldap_parse_extended_partial (
294         LDAP                    *ld,
295         LDAPMessage             *res,
296         char                    **retoidp,
297         struct berval   **retdatap,
298         LDAPControl             ***serverctrls,
299         int                             freeit )
300 {
301         BerElement *ber;
302         ber_tag_t rc;
303         ber_tag_t tag;
304         ber_len_t len;
305         struct berval *resdata;
306         char *resoid;
307
308         assert( ld != NULL );
309         assert( LDAP_VALID( ld ) );
310         assert( res != NULL );
311
312 #ifdef NEW_LOGGING
313         LDAP_LOG (( "extended", LDAP_LEVEL_ENTRY, 
314                 "ldap_parse_extended_partial\n" ));
315 #else
316         Debug( LDAP_DEBUG_TRACE, "ldap_parse_extended_partial\n", 0, 0, 0 );
317 #endif
318
319         if( ld->ld_version < LDAP_VERSION3 ) {
320                 ld->ld_errno = LDAP_NOT_SUPPORTED;
321                 return ld->ld_errno;
322         }
323
324         if( res->lm_msgtype != LDAP_RES_EXTENDED_PARTIAL ) {
325                 ld->ld_errno = LDAP_PARAM_ERROR;
326                 return ld->ld_errno;
327         }
328
329         if( retoidp != NULL ) *retoidp = NULL;
330         if( retdatap != NULL ) *retdatap = NULL;
331
332         ber = ber_dup( res->lm_ber );
333
334         if ( ber == NULL ) {
335                 ld->ld_errno = LDAP_NO_MEMORY;
336                 return ld->ld_errno;
337         }
338
339         rc = ber_scanf( ber, "{" /*}*/ );
340
341         if( rc == LBER_ERROR ) {
342                 ld->ld_errno = LDAP_DECODING_ERROR;
343                 ber_free( ber, 0 );
344                 return ld->ld_errno;
345         }
346
347         resoid = NULL;
348         resdata = NULL;
349
350         tag = ber_peek_tag( ber, &len );
351
352         if( tag == LDAP_TAG_EXOP_RES_OID ) {
353                 /* we have a resoid */
354                 if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) {
355                         ld->ld_errno = LDAP_DECODING_ERROR;
356                         ber_free( ber, 0 );
357                         return ld->ld_errno;
358                 }
359
360                 tag = ber_peek_tag( ber, &len );
361         }
362
363         if( tag == LDAP_TAG_EXOP_RES_VALUE ) {
364                 /* we have a resdata */
365                 if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) {
366                         ld->ld_errno = LDAP_DECODING_ERROR;
367                         ber_free( ber, 0 );
368                         if( resoid != NULL ) LDAP_FREE( resoid );
369                         return ld->ld_errno;
370                 }
371         }
372
373         if ( serverctrls == NULL ) {
374                 rc = LDAP_SUCCESS;
375                 goto free_and_return;
376         }
377
378         if ( ber_scanf( ber, /*{*/ "}" ) == LBER_ERROR ) {
379                 rc = LDAP_DECODING_ERROR;
380                 goto free_and_return;
381         }
382
383         rc = ldap_int_get_controls( ber, serverctrls );
384
385 free_and_return:
386         ber_free( ber, 0 );
387
388         if( retoidp != NULL ) {
389                 *retoidp = resoid;
390         } else {
391                 LDAP_FREE( resoid );
392         }
393
394         if( retdatap != NULL ) {
395                 *retdatap = resdata;
396         } else {
397                 ber_bvfree( resdata );
398         }
399
400         if( freeit ) {
401                 ldap_msgfree( res );
402         }
403
404         return LDAP_SUCCESS;
405 }