1*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
2*7c478bd9Sstevel@tonic-gate
3*7c478bd9Sstevel@tonic-gate /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
4*7c478bd9Sstevel@tonic-gate *
5*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public License
6*7c478bd9Sstevel@tonic-gate * Version 1.0 (the "NPL"); you may not use this file except in
7*7c478bd9Sstevel@tonic-gate * compliance with the NPL. You may obtain a copy of the NPL at
8*7c478bd9Sstevel@tonic-gate * http://www.mozilla.org/NPL/
9*7c478bd9Sstevel@tonic-gate *
10*7c478bd9Sstevel@tonic-gate * Software distributed under the NPL is distributed on an "AS IS" basis,
11*7c478bd9Sstevel@tonic-gate * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
12*7c478bd9Sstevel@tonic-gate * for the specific language governing rights and limitations under the
13*7c478bd9Sstevel@tonic-gate * NPL.
14*7c478bd9Sstevel@tonic-gate *
15*7c478bd9Sstevel@tonic-gate * The Initial Developer of this code under the NPL is Netscape
16*7c478bd9Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are
17*7c478bd9Sstevel@tonic-gate * Copyright (C) 1998 Netscape Communications Corporation. All Rights
18*7c478bd9Sstevel@tonic-gate * Reserved.
19*7c478bd9Sstevel@tonic-gate */
20*7c478bd9Sstevel@tonic-gate #include "ldap-int.h"
21*7c478bd9Sstevel@tonic-gate
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * ldap_extended_operation - initiate an arbitrary ldapv3 extended operation.
24*7c478bd9Sstevel@tonic-gate * the oid and data of the extended operation are supplied. Returns an
25*7c478bd9Sstevel@tonic-gate * LDAP error code.
26*7c478bd9Sstevel@tonic-gate *
27*7c478bd9Sstevel@tonic-gate * Example:
28*7c478bd9Sstevel@tonic-gate * struct berval exdata;
29*7c478bd9Sstevel@tonic-gate * char *exoid;
30*7c478bd9Sstevel@tonic-gate * int err, msgid;
31*7c478bd9Sstevel@tonic-gate * ... fill in oid and data ...
32*7c478bd9Sstevel@tonic-gate * err = ldap_extended_operation( ld, exoid, &exdata, NULL, NULL, &msgid );
33*7c478bd9Sstevel@tonic-gate */
34*7c478bd9Sstevel@tonic-gate
35*7c478bd9Sstevel@tonic-gate int
36*7c478bd9Sstevel@tonic-gate LDAP_CALL
ldap_extended_operation(LDAP * ld,const char * exoid,const struct berval * exdata,LDAPControl ** serverctrls,LDAPControl ** clientctrls,int * msgidp)37*7c478bd9Sstevel@tonic-gate ldap_extended_operation(
38*7c478bd9Sstevel@tonic-gate LDAP *ld,
39*7c478bd9Sstevel@tonic-gate const char *exoid,
40*7c478bd9Sstevel@tonic-gate const struct berval *exdata,
41*7c478bd9Sstevel@tonic-gate LDAPControl **serverctrls,
42*7c478bd9Sstevel@tonic-gate LDAPControl **clientctrls,
43*7c478bd9Sstevel@tonic-gate int *msgidp
44*7c478bd9Sstevel@tonic-gate )
45*7c478bd9Sstevel@tonic-gate {
46*7c478bd9Sstevel@tonic-gate BerElement *ber;
47*7c478bd9Sstevel@tonic-gate int rc, msgid;
48*7c478bd9Sstevel@tonic-gate
49*7c478bd9Sstevel@tonic-gate /*
50*7c478bd9Sstevel@tonic-gate * the ldapv3 extended operation request looks like this:
51*7c478bd9Sstevel@tonic-gate *
52*7c478bd9Sstevel@tonic-gate * ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
53*7c478bd9Sstevel@tonic-gate * requestName LDAPOID,
54*7c478bd9Sstevel@tonic-gate * requestValue OCTET STRING
55*7c478bd9Sstevel@tonic-gate * }
56*7c478bd9Sstevel@tonic-gate *
57*7c478bd9Sstevel@tonic-gate * all wrapped up in an LDAPMessage sequence.
58*7c478bd9Sstevel@tonic-gate */
59*7c478bd9Sstevel@tonic-gate
60*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "ldap_extended_operation\n", 0, 0, 0 );
61*7c478bd9Sstevel@tonic-gate
62*7c478bd9Sstevel@tonic-gate if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
63*7c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
64*7c478bd9Sstevel@tonic-gate }
65*7c478bd9Sstevel@tonic-gate
66*7c478bd9Sstevel@tonic-gate
67*7c478bd9Sstevel@tonic-gate /* only ldapv3 or higher can do extended operations */
68*7c478bd9Sstevel@tonic-gate if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) {
69*7c478bd9Sstevel@tonic-gate rc = LDAP_NOT_SUPPORTED;
70*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
71*7c478bd9Sstevel@tonic-gate return( rc );
72*7c478bd9Sstevel@tonic-gate }
73*7c478bd9Sstevel@tonic-gate
74*7c478bd9Sstevel@tonic-gate if ( msgidp == NULL || exoid == NULL || *exoid == '\0' ||
75*7c478bd9Sstevel@tonic-gate exdata == NULL || exdata->bv_val == NULL ) {
76*7c478bd9Sstevel@tonic-gate rc = LDAP_PARAM_ERROR;
77*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
78*7c478bd9Sstevel@tonic-gate return( rc );
79*7c478bd9Sstevel@tonic-gate }
80*7c478bd9Sstevel@tonic-gate
81*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK );
82*7c478bd9Sstevel@tonic-gate msgid = ++ld->ld_msgid;
83*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK );
84*7c478bd9Sstevel@tonic-gate
85*7c478bd9Sstevel@tonic-gate #if 0
86*7c478bd9Sstevel@tonic-gate if ( ld->ld_cache_on && ld->ld_cache_extendedop != NULL ) {
87*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK );
88*7c478bd9Sstevel@tonic-gate if ( (rc = (ld->ld_cache_extendedop)( ld, msgid,
89*7c478bd9Sstevel@tonic-gate LDAP_REQ_EXTENDED, exoid, cred )) != 0 ) {
90*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
91*7c478bd9Sstevel@tonic-gate return( rc );
92*7c478bd9Sstevel@tonic-gate }
93*7c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
94*7c478bd9Sstevel@tonic-gate }
95*7c478bd9Sstevel@tonic-gate #endif
96*7c478bd9Sstevel@tonic-gate
97*7c478bd9Sstevel@tonic-gate /* create a message to send */
98*7c478bd9Sstevel@tonic-gate if (( rc = nsldapi_alloc_ber_with_options( ld, &ber ))
99*7c478bd9Sstevel@tonic-gate != LDAP_SUCCESS ) {
100*7c478bd9Sstevel@tonic-gate return( rc );
101*7c478bd9Sstevel@tonic-gate }
102*7c478bd9Sstevel@tonic-gate
103*7c478bd9Sstevel@tonic-gate /* fill it in */
104*7c478bd9Sstevel@tonic-gate if ( ber_printf( ber, "{it{tsto}", msgid, LDAP_REQ_EXTENDED,
105*7c478bd9Sstevel@tonic-gate LDAP_TAG_EXOP_REQ_OID, exoid, LDAP_TAG_EXOP_REQ_VALUE,
106*7c478bd9Sstevel@tonic-gate exdata->bv_val, (int)exdata->bv_len /* XXX lossy cast */ ) == -1 ) {
107*7c478bd9Sstevel@tonic-gate rc = LDAP_ENCODING_ERROR;
108*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
109*7c478bd9Sstevel@tonic-gate ber_free( ber, 1 );
110*7c478bd9Sstevel@tonic-gate return( rc );
111*7c478bd9Sstevel@tonic-gate }
112*7c478bd9Sstevel@tonic-gate
113*7c478bd9Sstevel@tonic-gate if (( rc = nsldapi_put_controls( ld, serverctrls, 1, ber ))
114*7c478bd9Sstevel@tonic-gate != LDAP_SUCCESS ) {
115*7c478bd9Sstevel@tonic-gate ber_free( ber, 1 );
116*7c478bd9Sstevel@tonic-gate return( rc );
117*7c478bd9Sstevel@tonic-gate }
118*7c478bd9Sstevel@tonic-gate
119*7c478bd9Sstevel@tonic-gate /* send the message */
120*7c478bd9Sstevel@tonic-gate rc = nsldapi_send_initial_request( ld, msgid, LDAP_REQ_EXTENDED, NULL,
121*7c478bd9Sstevel@tonic-gate ber );
122*7c478bd9Sstevel@tonic-gate *msgidp = rc;
123*7c478bd9Sstevel@tonic-gate return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS );
124*7c478bd9Sstevel@tonic-gate }
125*7c478bd9Sstevel@tonic-gate
126*7c478bd9Sstevel@tonic-gate
127*7c478bd9Sstevel@tonic-gate /*
128*7c478bd9Sstevel@tonic-gate * ldap_extended_operation_s - perform an arbitrary ldapv3 extended operation.
129*7c478bd9Sstevel@tonic-gate * the oid and data of the extended operation are supplied. LDAP_SUCCESS
130*7c478bd9Sstevel@tonic-gate * is returned upon success, the ldap error code otherwise.
131*7c478bd9Sstevel@tonic-gate *
132*7c478bd9Sstevel@tonic-gate * Example:
133*7c478bd9Sstevel@tonic-gate * struct berval exdata, exretval;
134*7c478bd9Sstevel@tonic-gate * char *exoid;
135*7c478bd9Sstevel@tonic-gate * int rc;
136*7c478bd9Sstevel@tonic-gate * ... fill in oid and data ...
137*7c478bd9Sstevel@tonic-gate * rc = ldap_extended_operation_s( ld, exoid, &exdata, &exretval );
138*7c478bd9Sstevel@tonic-gate */
139*7c478bd9Sstevel@tonic-gate int
140*7c478bd9Sstevel@tonic-gate LDAP_CALL
ldap_extended_operation_s(LDAP * ld,const char * requestoid,const struct berval * requestdata,LDAPControl ** serverctrls,LDAPControl ** clientctrls,char ** retoidp,struct berval ** retdatap)141*7c478bd9Sstevel@tonic-gate ldap_extended_operation_s(
142*7c478bd9Sstevel@tonic-gate LDAP *ld,
143*7c478bd9Sstevel@tonic-gate const char *requestoid,
144*7c478bd9Sstevel@tonic-gate const struct berval *requestdata,
145*7c478bd9Sstevel@tonic-gate LDAPControl **serverctrls,
146*7c478bd9Sstevel@tonic-gate LDAPControl **clientctrls,
147*7c478bd9Sstevel@tonic-gate char **retoidp,
148*7c478bd9Sstevel@tonic-gate struct berval **retdatap
149*7c478bd9Sstevel@tonic-gate )
150*7c478bd9Sstevel@tonic-gate {
151*7c478bd9Sstevel@tonic-gate int err, msgid;
152*7c478bd9Sstevel@tonic-gate LDAPMessage *result;
153*7c478bd9Sstevel@tonic-gate
154*7c478bd9Sstevel@tonic-gate if (( err = ldap_extended_operation( ld, requestoid, requestdata,
155*7c478bd9Sstevel@tonic-gate serverctrls, clientctrls, &msgid )) != LDAP_SUCCESS ) {
156*7c478bd9Sstevel@tonic-gate return( err );
157*7c478bd9Sstevel@tonic-gate }
158*7c478bd9Sstevel@tonic-gate
159*7c478bd9Sstevel@tonic-gate if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result )
160*7c478bd9Sstevel@tonic-gate == -1 ) {
161*7c478bd9Sstevel@tonic-gate return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
162*7c478bd9Sstevel@tonic-gate }
163*7c478bd9Sstevel@tonic-gate
164*7c478bd9Sstevel@tonic-gate if (( err = ldap_parse_extended_result( ld, result, retoidp, retdatap,
165*7c478bd9Sstevel@tonic-gate 0 )) != LDAP_SUCCESS ) {
166*7c478bd9Sstevel@tonic-gate ldap_msgfree( result );
167*7c478bd9Sstevel@tonic-gate return( err );
168*7c478bd9Sstevel@tonic-gate }
169*7c478bd9Sstevel@tonic-gate
170*7c478bd9Sstevel@tonic-gate return( ldap_result2error( ld, result, 1 ) );
171*7c478bd9Sstevel@tonic-gate }
172*7c478bd9Sstevel@tonic-gate
173*7c478bd9Sstevel@tonic-gate
174*7c478bd9Sstevel@tonic-gate /*
175*7c478bd9Sstevel@tonic-gate * Pull the oid returned by the server and the data out of an extended
176*7c478bd9Sstevel@tonic-gate * operation result. Return an LDAP error code.
177*7c478bd9Sstevel@tonic-gate */
178*7c478bd9Sstevel@tonic-gate int
179*7c478bd9Sstevel@tonic-gate LDAP_CALL
ldap_parse_extended_result(LDAP * ld,LDAPMessage * res,char ** retoidp,struct berval ** retdatap,int freeit)180*7c478bd9Sstevel@tonic-gate ldap_parse_extended_result(
181*7c478bd9Sstevel@tonic-gate LDAP *ld,
182*7c478bd9Sstevel@tonic-gate LDAPMessage *res,
183*7c478bd9Sstevel@tonic-gate char **retoidp, /* may be NULL */
184*7c478bd9Sstevel@tonic-gate struct berval **retdatap, /* may be NULL */
185*7c478bd9Sstevel@tonic-gate int freeit
186*7c478bd9Sstevel@tonic-gate )
187*7c478bd9Sstevel@tonic-gate {
188*7c478bd9Sstevel@tonic-gate struct berelement ber;
189*7c478bd9Sstevel@tonic-gate ber_len_t len;
190*7c478bd9Sstevel@tonic-gate ber_int_t err;
191*7c478bd9Sstevel@tonic-gate char *m, *e, *roid;
192*7c478bd9Sstevel@tonic-gate struct berval *rdata;
193*7c478bd9Sstevel@tonic-gate
194*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n", 0, 0, 0 );
195*7c478bd9Sstevel@tonic-gate
196*7c478bd9Sstevel@tonic-gate if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
197*7c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
198*7c478bd9Sstevel@tonic-gate }
199*7c478bd9Sstevel@tonic-gate
200*7c478bd9Sstevel@tonic-gate if ( !NSLDAPI_VALID_LDAPMESSAGE_EXRESULT_POINTER( res )) {
201*7c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
202*7c478bd9Sstevel@tonic-gate }
203*7c478bd9Sstevel@tonic-gate
204*7c478bd9Sstevel@tonic-gate m = e = NULL;
205*7c478bd9Sstevel@tonic-gate ber = *(res->lm_ber);
206*7c478bd9Sstevel@tonic-gate if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) {
207*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL );
208*7c478bd9Sstevel@tonic-gate return( LDAP_NOT_SUPPORTED );
209*7c478bd9Sstevel@tonic-gate }
210*7c478bd9Sstevel@tonic-gate
211*7c478bd9Sstevel@tonic-gate if ( ber_scanf( &ber, "{iaa", &err, &m, &e ) == LBER_ERROR ) {
212*7c478bd9Sstevel@tonic-gate goto decoding_error;
213*7c478bd9Sstevel@tonic-gate }
214*7c478bd9Sstevel@tonic-gate roid = NULL;
215*7c478bd9Sstevel@tonic-gate if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_EXOP_RES_OID ) {
216*7c478bd9Sstevel@tonic-gate if ( ber_scanf( &ber, "a", &roid ) == LBER_ERROR ) {
217*7c478bd9Sstevel@tonic-gate goto decoding_error;
218*7c478bd9Sstevel@tonic-gate }
219*7c478bd9Sstevel@tonic-gate }
220*7c478bd9Sstevel@tonic-gate if ( retoidp != NULL ) {
221*7c478bd9Sstevel@tonic-gate *retoidp = roid;
222*7c478bd9Sstevel@tonic-gate } else if ( roid != NULL ) {
223*7c478bd9Sstevel@tonic-gate NSLDAPI_FREE( roid );
224*7c478bd9Sstevel@tonic-gate }
225*7c478bd9Sstevel@tonic-gate
226*7c478bd9Sstevel@tonic-gate rdata = NULL;
227*7c478bd9Sstevel@tonic-gate if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_EXOP_RES_VALUE ) {
228*7c478bd9Sstevel@tonic-gate if ( ber_scanf( &ber, "O", &rdata ) == LBER_ERROR ) {
229*7c478bd9Sstevel@tonic-gate goto decoding_error;
230*7c478bd9Sstevel@tonic-gate }
231*7c478bd9Sstevel@tonic-gate }
232*7c478bd9Sstevel@tonic-gate if ( retdatap != NULL ) {
233*7c478bd9Sstevel@tonic-gate *retdatap = rdata;
234*7c478bd9Sstevel@tonic-gate } else if ( rdata != NULL ) {
235*7c478bd9Sstevel@tonic-gate ber_bvfree( rdata );
236*7c478bd9Sstevel@tonic-gate }
237*7c478bd9Sstevel@tonic-gate
238*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, err, m, e );
239*7c478bd9Sstevel@tonic-gate
240*7c478bd9Sstevel@tonic-gate if ( freeit ) {
241*7c478bd9Sstevel@tonic-gate ldap_msgfree( res );
242*7c478bd9Sstevel@tonic-gate }
243*7c478bd9Sstevel@tonic-gate
244*7c478bd9Sstevel@tonic-gate return( LDAP_SUCCESS );
245*7c478bd9Sstevel@tonic-gate
246*7c478bd9Sstevel@tonic-gate decoding_error:;
247*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
248*7c478bd9Sstevel@tonic-gate return( LDAP_DECODING_ERROR );
249*7c478bd9Sstevel@tonic-gate }
250