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