Back to index

lightning-sunbird  0.9+nobinonly
extendop.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla Communicator client code, released
00015  * March 31, 1998.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 #include "ldap-int.h"
00038 
00039 /*
00040  * ldap_extended_operation - initiate an arbitrary ldapv3 extended operation.
00041  * the oid and data of the extended operation are supplied. Returns an
00042  * LDAP error code.
00043  *
00044  * Example:
00045  *     struct berval exdata;
00046  *     char          *exoid;
00047  *     int           err, msgid;
00048  *     ... fill in oid and data ...
00049  *     err = ldap_extended_operation( ld, exoid, &exdata, NULL, NULL, &msgid );
00050  */
00051 
00052 int
00053 LDAP_CALL
00054 ldap_extended_operation(
00055     LDAP             *ld,
00056     const char              *exoid,
00057     const struct berval     *exdata,
00058     LDAPControl             **serverctrls,
00059     LDAPControl             **clientctrls,
00060     int                     *msgidp
00061 )
00062 {
00063        BerElement    *ber;
00064        int           rc, msgid;
00065 
00066        /*
00067         * the ldapv3 extended operation request looks like this:
00068         *
00069         *     ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
00070         *            requestName   LDAPOID,
00071         *            requestValue  OCTET STRING
00072         *     }
00073         *
00074         * all wrapped up in an LDAPMessage sequence.
00075         */
00076 
00077        LDAPDebug( LDAP_DEBUG_TRACE, "ldap_extended_operation\n", 0, 0, 0 );
00078 
00079        if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
00080               return( LDAP_PARAM_ERROR );
00081        }
00082 
00083 
00084        /* only ldapv3 or higher can do extended operations */
00085        if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) {
00086               rc = LDAP_NOT_SUPPORTED;
00087               LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
00088               return( rc );
00089        }
00090 
00091        if ( msgidp == NULL || exoid == NULL || *exoid == '\0' ) {
00092               rc = LDAP_PARAM_ERROR;
00093               LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
00094               return( rc );
00095        }
00096 
00097        LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK );
00098        msgid = ++ld->ld_msgid;
00099        LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK );
00100 
00101 #if 0
00102        if ( ld->ld_cache_on && ld->ld_cache_extendedop != NULL ) {
00103               LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK );
00104               if ( (rc = (ld->ld_cache_extendedop)( ld, msgid,
00105                   LDAP_REQ_EXTENDED, exoid, cred )) != 0 ) {
00106                      LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
00107                      return( rc );
00108               }
00109               LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
00110        }
00111 #endif
00112 
00113        /* create a message to send */
00114        if (( rc = nsldapi_alloc_ber_with_options( ld, &ber ))
00115            != LDAP_SUCCESS ) {
00116               return( rc );
00117        }
00118 
00119        /* fill it in */
00120        if ( ber_printf( ber, "{it{tsto}", msgid, LDAP_REQ_EXTENDED,
00121            LDAP_TAG_EXOP_REQ_OID, exoid, LDAP_TAG_EXOP_REQ_VALUE,
00122            exdata->bv_val, (int)exdata->bv_len /* XXX lossy cast */ ) == -1 ) {
00123               rc = LDAP_ENCODING_ERROR;
00124               LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
00125               ber_free( ber, 1 );
00126               return( rc );
00127        }
00128 
00129        if (( rc = nsldapi_put_controls( ld, serverctrls, 1, ber ))
00130            != LDAP_SUCCESS ) {
00131               ber_free( ber, 1 );
00132               return( rc );
00133        }
00134 
00135        /* send the message */
00136        rc = nsldapi_send_initial_request( ld, msgid, LDAP_REQ_EXTENDED, NULL,
00137               ber );
00138        *msgidp = rc;
00139        return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS );
00140 }
00141 
00142 
00143 /*
00144  * ldap_extended_operation_s - perform an arbitrary ldapv3 extended operation.
00145  * the oid and data of the extended operation are supplied. LDAP_SUCCESS
00146  * is returned upon success, the ldap error code otherwise.
00147  *
00148  * Example:
00149  *     struct berval exdata, exretval;
00150  *     char          *exoid;
00151  *     int           rc;
00152  *     ... fill in oid and data ...
00153  *     rc = ldap_extended_operation_s( ld, exoid, &exdata, &exretval );
00154  */
00155 int
00156 LDAP_CALL
00157 ldap_extended_operation_s(
00158     LDAP             *ld,
00159     const char              *requestoid,
00160     const struct berval     *requestdata,
00161     LDAPControl             **serverctrls,
00162     LDAPControl             **clientctrls,
00163     char             **retoidp,
00164     struct berval    **retdatap
00165 )
00166 {
00167        int           err, msgid;
00168        LDAPMessage   *result;
00169 
00170        if (( err = ldap_extended_operation( ld, requestoid, requestdata,
00171            serverctrls, clientctrls, &msgid )) != LDAP_SUCCESS ) {
00172               return( err );
00173        }
00174 
00175        if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result )
00176            == -1 ) {
00177               return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
00178        }
00179 
00180        if (( err = ldap_parse_extended_result( ld, result, retoidp, retdatap,
00181               0 )) != LDAP_SUCCESS ) {
00182            ldap_msgfree( result );
00183            return( err );
00184        }
00185 
00186        return( ldap_result2error( ld, result, 1 ) );
00187 }
00188 
00189 
00190 /*
00191  * Pull the oid returned by the server and the data out of an extended
00192  * operation result.  Return an LDAP error code.
00193  */
00194 int
00195 LDAP_CALL
00196 ldap_parse_extended_result(
00197     LDAP             *ld,
00198     LDAPMessage             *res,
00199     char             **retoidp,    /* may be NULL */
00200     struct berval    **retdatap,   /* may be NULL */
00201     int                     freeit
00202 )
00203 {
00204        struct berelement    ber;
00205        unsigned long        len;
00206        long                 err;
00207        char                 *m, *e, *roid;
00208        struct berval        *rdata;
00209 
00210        LDAPDebug( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n", 0, 0, 0 );
00211 
00212        if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
00213               return( LDAP_PARAM_ERROR );
00214        }
00215 
00216         if ( !NSLDAPI_VALID_LDAPMESSAGE_EXRESULT_POINTER( res )) {
00217               return( LDAP_PARAM_ERROR );
00218        }
00219 
00220        m = e = NULL;
00221        ber = *(res->lm_ber);
00222        if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) {
00223               LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL );
00224               return( LDAP_NOT_SUPPORTED );
00225        }
00226 
00227        if ( ber_scanf( &ber, "{iaa", &err, &m, &e ) == LBER_ERROR ) {
00228               goto decoding_error;
00229        }
00230        roid = NULL;
00231        if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_EXOP_RES_OID ) {
00232               if ( ber_scanf( &ber, "a", &roid ) == LBER_ERROR ) {
00233                      goto decoding_error;
00234               }
00235        }
00236        if ( retoidp != NULL ) {
00237               *retoidp = roid;
00238        } else if ( roid != NULL ) {
00239               NSLDAPI_FREE( roid );
00240        }
00241 
00242        rdata = NULL;
00243        if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_EXOP_RES_VALUE ) {
00244               if ( ber_scanf( &ber, "O", &rdata ) == LBER_ERROR ) {
00245                      goto decoding_error;
00246               }
00247        }
00248        if ( retdatap != NULL ) {
00249               *retdatap = rdata;
00250        } else if ( rdata != NULL ) {
00251               ber_bvfree( rdata );
00252        }
00253 
00254        LDAP_SET_LDERRNO( ld, err, m, e );
00255 
00256        if ( freeit ) {
00257               ldap_msgfree( res );
00258        }
00259 
00260        return( LDAP_SUCCESS );
00261 
00262 decoding_error:;
00263        LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
00264        return( LDAP_DECODING_ERROR );
00265 }