]> git.sur5r.net Git - openldap/blob - libraries/libldap/extended.c
72657c3476a84cd4af62f66bc2c765fa06cd2017
[openldap] / libraries / libldap / extended.c
1 /*
2  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5
6 /*
7  * LDAPv3 Extended Operation Request
8  *      ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
9  *              requestName      [0] LDAPOID,
10  *              requestValue     [1] OCTET STRING OPTIONAL
11  *      }
12  *
13  * LDAPv3 Extended Operation Response
14  *      ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
15  *              COMPONENTS OF LDAPResult,
16  *              responseName     [10] LDAPOID OPTIONAL,
17  *              response         [11] OCTET STRING OPTIONAL
18  *      }
19  *
20  */
21
22 #include "portable.h"
23
24 #include <stdio.h>
25 #include <ac/stdlib.h>
26
27 #include <ac/socket.h>
28 #include <ac/string.h>
29 #include <ac/time.h>
30
31 #include "ldap-int.h"
32
33 int
34 ldap_extended_operation(
35         LDAP                    *ld,
36         LDAP_CONST char *reqoid,
37         struct berval   *reqdata,
38         LDAPControl             **sctrls,
39         LDAPControl             **cctrls,
40         int                             *msgidp )
41 {
42         BerElement *ber;
43
44         Debug( LDAP_DEBUG_TRACE, "ldap_extended_operation\n", 0, 0, 0 );
45
46         assert( ld != NULL );
47         assert( LDAP_VALID( ld ) );
48         assert( reqoid != NULL || *reqoid == '\0' );
49         assert( msgidp != NULL );
50
51         /* must be version 3 (or greater) */
52         if ( ld->ld_version == 0 ) {
53                 ld->ld_version = LDAP_VERSION3;
54         }
55
56         if ( ld->ld_version < LDAP_VERSION3 ) {
57                 ld->ld_errno = LDAP_NOT_SUPPORTED;
58                 return( ld->ld_errno );
59         }
60
61         if( reqoid == NULL || *reqoid == '\0' || msgidp == NULL ) {
62                 ld->ld_errno = LDAP_PARAM_ERROR;
63                 return( ld->ld_errno );
64         }
65
66         /* create a message to send */
67         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULLBER ) {
68                 ld->ld_errno = LDAP_NO_MEMORY;
69                 return( ld->ld_errno );
70         }
71
72         if ( ber_printf( ber, "{it{tstO}", /* leave '}' for later */
73                 ++ld->ld_msgid, LDAP_REQ_EXTENDED, LDAP_TAG_EXOP_REQ_OID,
74                         reqoid, LDAP_TAG_EXOP_REQ_VALUE, reqdata ) == -1 )
75         {
76                 ld->ld_errno = LDAP_ENCODING_ERROR;
77                 ber_free( ber, 1 );
78                 return( ld->ld_errno );
79         }
80
81         /* Put Server Controls */
82         if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
83                 ber_free( ber, 1 );
84                 return ld->ld_errno;
85         }
86
87         if ( ber_printf( ber, /*{*/ "}" ) == -1 ) {
88                 ld->ld_errno = LDAP_ENCODING_ERROR;
89                 ber_free( ber, 1 );
90                 return( ld->ld_errno );
91         }
92
93         /* send the message */
94         *msgidp = ldap_send_initial_request( ld, LDAP_REQ_EXTENDED, NULL, ber );
95
96         return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
97 }
98
99 int
100 ldap_extended_operation_s(
101         LDAP                    *ld,
102         LDAP_CONST char *reqoid,
103         struct berval   *reqdata,
104         LDAPControl             **sctrls,
105         LDAPControl             **cctrls,
106         char                    **retoidp,
107         struct berval   **retdatap )
108 {
109     int     rc;
110     int     msgid;
111     LDAPMessage *res;
112
113         Debug( LDAP_DEBUG_TRACE, "ldap_extended_operation_s\n", 0, 0, 0 );
114
115         assert( ld != NULL );
116         assert( LDAP_VALID( ld ) );
117         assert( reqoid != NULL || *reqoid == '\0' );
118         assert( retoidp != NULL || retdatap != NULL );
119
120         if( retoidp == NULL || retdatap == NULL ) {
121                 ld->ld_errno = LDAP_PARAM_ERROR;
122                 return( ld->ld_errno );
123         }
124
125     rc = ldap_extended_operation( ld, reqoid, reqdata,
126                 sctrls, cctrls, &msgid );
127         
128     if ( rc != LDAP_SUCCESS ) {
129         return( rc );
130         }
131  
132     if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 ) {
133         return( ld->ld_errno );
134         }
135
136         *retoidp = NULL;
137         *retdatap = NULL;
138
139         rc = ldap_parse_extended_result( ld, res, retoidp, retdatap, 0 );
140
141         if( rc != LDAP_SUCCESS ) {
142                 ldap_msgfree( res );
143                 return rc;
144         }
145
146     return( ldap_result2error( ld, res, 1 ) );
147 }
148
149 /* Parse an extended result */
150 int
151 ldap_parse_extended_result (
152         LDAP                    *ld,
153         LDAPMessage             *res,
154         char                    **retoidp,
155         struct berval   **retdatap,
156         int                             freeit )
157 {
158         BerElement *ber;
159         int rc;
160         unsigned long tag, len;
161         struct berval *resdata;
162         long errcode;
163         char *resoid;
164
165         assert( ld != NULL );
166         assert( LDAP_VALID( ld ) );
167         assert( res != NULL );
168
169         Debug( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n", 0, 0, 0 );
170
171         if( ld->ld_version < LDAP_VERSION3 ) {
172                 ld->ld_errno = LDAP_NOT_SUPPORTED;
173                 return ld->ld_errno;
174         }
175
176         if( retoidp != NULL ) *retoidp = NULL;
177         if( retdatap != NULL ) *retdatap = NULL;
178
179         ber = ber_dup( res->lm_ber );
180
181         if ( ld->ld_error ) {
182                 LDAP_FREE( ld->ld_error );
183                 ld->ld_error = NULL;
184         }
185
186         if ( ld->ld_matched ) {
187                 LDAP_FREE( ld->ld_matched );
188                 ld->ld_matched = NULL;
189         }
190
191         rc = ber_scanf( ber, "{iaa", &errcode,
192                 &ld->ld_matched, &ld->ld_matched );
193
194         if( rc == LBER_ERROR ) {
195                 ld->ld_errno = LDAP_DECODING_ERROR;
196                 ber_free( ber, 0 );
197                 return ld->ld_errno;
198         }
199
200         resoid = NULL;
201         resdata = NULL;
202
203         tag = ber_peek_tag( ber, &len );
204
205         if( tag == LDAP_TAG_EXOP_RES_OID ) {
206                 /* we have a resoid */
207                 if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) {
208                         ld->ld_errno = LDAP_DECODING_ERROR;
209                         ber_free( ber, 0 );
210                         return ld->ld_errno;
211                 }
212
213                 tag = ber_peek_tag( ber, &len );
214         }
215
216         if( tag == LDAP_TAG_EXOP_RES_VALUE ) {
217                 /* we have a resdata */
218                 if( ber_scanf( ber, "O", &resoid ) == LBER_ERROR ) {
219                         ld->ld_errno = LDAP_DECODING_ERROR;
220                         ber_free( ber, 0 );
221                         if( resoid != NULL ) LDAP_FREE( resoid );
222                         return ld->ld_errno;
223                 }
224         }
225
226         if( retoidp != NULL ) {
227                 *retoidp = resoid;
228         } else {
229                 LDAP_FREE( resoid );
230         }
231
232         if( retdatap != NULL ) {
233                 *retdatap = resdata;
234         } else {
235                 ber_bvfree( resdata );
236         }
237
238         ld->ld_errno = errcode;
239
240         if( freeit ) {
241                 ldap_msgfree( res );
242         }
243
244         return LDAP_SUCCESS;
245 }