1 #pragma ident "%Z%%M% %I% %E% SMI"
3 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
5 * The contents of this file are subject to the Netscape Public License
6 * Version 1.0 (the "NPL"); you may not use this file except in
7 * compliance with the NPL. You may obtain a copy of the NPL at
8 * http://www.mozilla.org/NPL/
10 * Software distributed under the NPL is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
12 * for the specific language governing rights and limitations under the
15 * The Initial Developer of this code under the NPL is Netscape
16 * Communications Corporation. Portions created by Netscape are
17 * Copyright (C) 1998 Netscape Communications Corporation. All Rights
23 * ldap_extended_operation - initiate an arbitrary ldapv3 extended operation.
24 * the oid and data of the extended operation are supplied. Returns an
28 * struct berval exdata;
31 * ... fill in oid and data ...
32 * err = ldap_extended_operation( ld, exoid, &exdata, NULL, NULL, &msgid );
37 ldap_extended_operation(
40 const struct berval
*exdata
,
41 LDAPControl
**serverctrls
,
42 LDAPControl
**clientctrls
,
50 * the ldapv3 extended operation request looks like this:
52 * ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
53 * requestName LDAPOID,
54 * requestValue OCTET STRING
57 * all wrapped up in an LDAPMessage sequence.
60 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_extended_operation\n", 0, 0, 0 );
62 if ( !NSLDAPI_VALID_LDAP_POINTER( ld
)) {
63 return( LDAP_PARAM_ERROR
);
67 /* only ldapv3 or higher can do extended operations */
68 if ( NSLDAPI_LDAP_VERSION( ld
) < LDAP_VERSION3
) {
69 rc
= LDAP_NOT_SUPPORTED
;
70 LDAP_SET_LDERRNO( ld
, rc
, NULL
, NULL
);
74 if ( msgidp
== NULL
|| exoid
== NULL
|| *exoid
== '\0' ||
75 exdata
== NULL
|| exdata
->bv_val
== NULL
) {
76 rc
= LDAP_PARAM_ERROR
;
77 LDAP_SET_LDERRNO( ld
, rc
, NULL
, NULL
);
81 LDAP_MUTEX_LOCK( ld
, LDAP_MSGID_LOCK
);
82 msgid
= ++ld
->ld_msgid
;
83 LDAP_MUTEX_UNLOCK( ld
, LDAP_MSGID_LOCK
);
86 if ( ld
->ld_cache_on
&& ld
->ld_cache_extendedop
!= NULL
) {
87 LDAP_MUTEX_LOCK( ld
, LDAP_CACHE_LOCK
);
88 if ( (rc
= (ld
->ld_cache_extendedop
)( ld
, msgid
,
89 LDAP_REQ_EXTENDED
, exoid
, cred
)) != 0 ) {
90 LDAP_MUTEX_UNLOCK( ld
, LDAP_CACHE_LOCK
);
93 LDAP_MUTEX_UNLOCK( ld
, LDAP_CACHE_LOCK
);
97 /* create a message to send */
98 if (( rc
= nsldapi_alloc_ber_with_options( ld
, &ber
))
104 if ( ber_printf( ber
, "{it{tsto}", msgid
, LDAP_REQ_EXTENDED
,
105 LDAP_TAG_EXOP_REQ_OID
, exoid
, LDAP_TAG_EXOP_REQ_VALUE
,
106 exdata
->bv_val
, (int)exdata
->bv_len
/* XXX lossy cast */ ) == -1 ) {
107 rc
= LDAP_ENCODING_ERROR
;
108 LDAP_SET_LDERRNO( ld
, rc
, NULL
, NULL
);
113 if (( rc
= nsldapi_put_controls( ld
, serverctrls
, 1, ber
))
119 /* send the message */
120 rc
= nsldapi_send_initial_request( ld
, msgid
, LDAP_REQ_EXTENDED
, NULL
,
123 return( rc
< 0 ? LDAP_GET_LDERRNO( ld
, NULL
, NULL
) : LDAP_SUCCESS
);
128 * ldap_extended_operation_s - perform an arbitrary ldapv3 extended operation.
129 * the oid and data of the extended operation are supplied. LDAP_SUCCESS
130 * is returned upon success, the ldap error code otherwise.
133 * struct berval exdata, exretval;
136 * ... fill in oid and data ...
137 * rc = ldap_extended_operation_s( ld, exoid, &exdata, &exretval );
141 ldap_extended_operation_s(
143 const char *requestoid
,
144 const struct berval
*requestdata
,
145 LDAPControl
**serverctrls
,
146 LDAPControl
**clientctrls
,
148 struct berval
**retdatap
154 if (( err
= ldap_extended_operation( ld
, requestoid
, requestdata
,
155 serverctrls
, clientctrls
, &msgid
)) != LDAP_SUCCESS
) {
159 if ( ldap_result( ld
, msgid
, 1, NULL
, &result
)
161 return( LDAP_GET_LDERRNO( ld
, NULL
, NULL
) );
164 if (( err
= ldap_parse_extended_result( ld
, result
, retoidp
, retdatap
,
165 0 )) != LDAP_SUCCESS
) {
166 ldap_msgfree( result
);
170 return( ldap_result2error( ld
, result
, 1 ) );
175 * Pull the oid returned by the server and the data out of an extended
176 * operation result. Return an LDAP error code.
180 ldap_parse_extended_result(
183 char **retoidp
, /* may be NULL */
184 struct berval
**retdatap
, /* may be NULL */
188 struct berelement ber
;
192 struct berval
*rdata
;
194 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_parse_extended_result\n", 0, 0, 0 );
196 if ( !NSLDAPI_VALID_LDAP_POINTER( ld
)) {
197 return( LDAP_PARAM_ERROR
);
200 if ( !NSLDAPI_VALID_LDAPMESSAGE_EXRESULT_POINTER( res
)) {
201 return( LDAP_PARAM_ERROR
);
205 ber
= *(res
->lm_ber
);
206 if ( NSLDAPI_LDAP_VERSION( ld
) < LDAP_VERSION3
) {
207 LDAP_SET_LDERRNO( ld
, LDAP_NOT_SUPPORTED
, NULL
, NULL
);
208 return( LDAP_NOT_SUPPORTED
);
211 if ( ber_scanf( &ber
, "{iaa", &err
, &m
, &e
) == LBER_ERROR
) {
215 if ( ber_peek_tag( &ber
, &len
) == LDAP_TAG_EXOP_RES_OID
) {
216 if ( ber_scanf( &ber
, "a", &roid
) == LBER_ERROR
) {
220 if ( retoidp
!= NULL
) {
222 } else if ( roid
!= NULL
) {
223 NSLDAPI_FREE( roid
);
227 if ( ber_peek_tag( &ber
, &len
) == LDAP_TAG_EXOP_RES_VALUE
) {
228 if ( ber_scanf( &ber
, "O", &rdata
) == LBER_ERROR
) {
232 if ( retdatap
!= NULL
) {
234 } else if ( rdata
!= NULL
) {
238 LDAP_SET_LDERRNO( ld
, err
, m
, e
);
244 return( LDAP_SUCCESS
);
247 LDAP_SET_LDERRNO( ld
, LDAP_DECODING_ERROR
, NULL
, NULL
);
248 return( LDAP_DECODING_ERROR
);