1 #pragma ident "%Z%%M% %I% %E% SMI" 2 3 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- 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/ 9 * 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 13 * NPL. 14 * 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 18 * Reserved. 19 */ 20 #include "ldap-int.h" 21 22 /* 23 * ldap_extended_operation - initiate an arbitrary ldapv3 extended operation. 24 * the oid and data of the extended operation are supplied. Returns an 25 * LDAP error code. 26 * 27 * Example: 28 * struct berval exdata; 29 * char *exoid; 30 * int err, msgid; 31 * ... fill in oid and data ... 32 * err = ldap_extended_operation( ld, exoid, &exdata, NULL, NULL, &msgid ); 33 */ 34 35 int 36 LDAP_CALL 37 ldap_extended_operation( 38 LDAP *ld, 39 const char *exoid, 40 const struct berval *exdata, 41 LDAPControl **serverctrls, 42 LDAPControl **clientctrls, 43 int *msgidp 44 ) 45 { 46 BerElement *ber; 47 int rc, msgid; 48 49 /* 50 * the ldapv3 extended operation request looks like this: 51 * 52 * ExtendedRequest ::= [APPLICATION 23] SEQUENCE { 53 * requestName LDAPOID, 54 * requestValue OCTET STRING 55 * } 56 * 57 * all wrapped up in an LDAPMessage sequence. 58 */ 59 60 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_extended_operation\n", 0, 0, 0 ); 61 62 if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { 63 return( LDAP_PARAM_ERROR ); 64 } 65 66 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 ); 71 return( rc ); 72 } 73 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 ); 78 return( rc ); 79 } 80 81 LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); 82 msgid = ++ld->ld_msgid; 83 LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); 84 85 #if 0 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 ); 91 return( rc ); 92 } 93 LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); 94 } 95 #endif 96 97 /* create a message to send */ 98 if (( rc = nsldapi_alloc_ber_with_options( ld, &ber )) 99 != LDAP_SUCCESS ) { 100 return( rc ); 101 } 102 103 /* fill it in */ 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 ); 109 ber_free( ber, 1 ); 110 return( rc ); 111 } 112 113 if (( rc = nsldapi_put_controls( ld, serverctrls, 1, ber )) 114 != LDAP_SUCCESS ) { 115 ber_free( ber, 1 ); 116 return( rc ); 117 } 118 119 /* send the message */ 120 rc = nsldapi_send_initial_request( ld, msgid, LDAP_REQ_EXTENDED, NULL, 121 ber ); 122 *msgidp = rc; 123 return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); 124 } 125 126 127 /* 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. 131 * 132 * Example: 133 * struct berval exdata, exretval; 134 * char *exoid; 135 * int rc; 136 * ... fill in oid and data ... 137 * rc = ldap_extended_operation_s( ld, exoid, &exdata, &exretval ); 138 */ 139 int 140 LDAP_CALL 141 ldap_extended_operation_s( 142 LDAP *ld, 143 const char *requestoid, 144 const struct berval *requestdata, 145 LDAPControl **serverctrls, 146 LDAPControl **clientctrls, 147 char **retoidp, 148 struct berval **retdatap 149 ) 150 { 151 int err, msgid; 152 LDAPMessage *result; 153 154 if (( err = ldap_extended_operation( ld, requestoid, requestdata, 155 serverctrls, clientctrls, &msgid )) != LDAP_SUCCESS ) { 156 return( err ); 157 } 158 159 if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result ) 160 == -1 ) { 161 return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); 162 } 163 164 if (( err = ldap_parse_extended_result( ld, result, retoidp, retdatap, 165 0 )) != LDAP_SUCCESS ) { 166 ldap_msgfree( result ); 167 return( err ); 168 } 169 170 return( ldap_result2error( ld, result, 1 ) ); 171 } 172 173 174 /* 175 * Pull the oid returned by the server and the data out of an extended 176 * operation result. Return an LDAP error code. 177 */ 178 int 179 LDAP_CALL 180 ldap_parse_extended_result( 181 LDAP *ld, 182 LDAPMessage *res, 183 char **retoidp, /* may be NULL */ 184 struct berval **retdatap, /* may be NULL */ 185 int freeit 186 ) 187 { 188 struct berelement ber; 189 ber_len_t len; 190 ber_int_t err; 191 char *m, *e, *roid; 192 struct berval *rdata; 193 194 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n", 0, 0, 0 ); 195 196 if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { 197 return( LDAP_PARAM_ERROR ); 198 } 199 200 if ( !NSLDAPI_VALID_LDAPMESSAGE_EXRESULT_POINTER( res )) { 201 return( LDAP_PARAM_ERROR ); 202 } 203 204 m = e = NULL; 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 ); 209 } 210 211 if ( ber_scanf( &ber, "{iaa", &err, &m, &e ) == LBER_ERROR ) { 212 goto decoding_error; 213 } 214 roid = NULL; 215 if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_EXOP_RES_OID ) { 216 if ( ber_scanf( &ber, "a", &roid ) == LBER_ERROR ) { 217 goto decoding_error; 218 } 219 } 220 if ( retoidp != NULL ) { 221 *retoidp = roid; 222 } else if ( roid != NULL ) { 223 NSLDAPI_FREE( roid ); 224 } 225 226 rdata = NULL; 227 if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_EXOP_RES_VALUE ) { 228 if ( ber_scanf( &ber, "O", &rdata ) == LBER_ERROR ) { 229 goto decoding_error; 230 } 231 } 232 if ( retdatap != NULL ) { 233 *retdatap = rdata; 234 } else if ( rdata != NULL ) { 235 ber_bvfree( rdata ); 236 } 237 238 LDAP_SET_LDERRNO( ld, err, m, e ); 239 240 if ( freeit ) { 241 ldap_msgfree( res ); 242 } 243 244 return( LDAP_SUCCESS ); 245 246 decoding_error:; 247 LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); 248 return( LDAP_DECODING_ERROR ); 249 } 250