Back to index

lightning-sunbird  0.9+nobinonly
saslbind.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_sasl_bind - authenticate to the ldap server.  The dn, mechanism,
00041  * and credentials of the entry to which to bind are supplied. An LDAP
00042  * error code is returned and if LDAP_SUCCESS is returned *msgidp is set
00043  * to the id of the request initiated.
00044  *
00045  * Example:
00046  *     struct berval creds;
00047  *     LDAPControl   **ctrls;
00048  *     int           err, msgid;
00049  *     ... fill in creds with credentials ...
00050  *     ... fill in ctrls with server controls ...
00051  *     err = ldap_sasl_bind( ld, "cn=manager, o=university of michigan, c=us",
00052  *         "mechanismname", &creds, ctrls, NULL, &msgid );
00053  */
00054 int
00055 LDAP_CALL
00056 ldap_sasl_bind(
00057     LDAP             *ld,
00058     const char              *dn,
00059     const char              *mechanism,
00060     const struct berval     *cred,
00061     LDAPControl             **serverctrls,
00062     LDAPControl             **clientctrls,
00063     int                     *msgidp
00064 )
00065 {
00066        BerElement    *ber;
00067        int           rc, simple, msgid, ldapversion;
00068 
00069        /*
00070         * The ldapv3 bind request looks like this:
00071         *     BindRequest ::= SEQUENCE {
00072         *            version              INTEGER,
00073         *            name          DistinguishedName,    -- who
00074         *            authentication       CHOICE {
00075         *                   simple        [0] OCTET STRING, -- passwd
00076         *                   sasl          [3] SaslCredentials -- v3 only
00077         *            }
00078         *     }
00079         *     SaslCredentials ::= SEQUENCE {
00080         *            mechanism     LDAPString,
00081         *            credentials   OCTET STRING
00082         *     }
00083         * all wrapped up in an LDAPMessage sequence.
00084         */
00085 
00086        LDAPDebug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 );
00087 
00088        if ( msgidp == NULL ) {
00089               LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
00090                 return( LDAP_PARAM_ERROR );
00091        }
00092 
00093        simple = ( mechanism == LDAP_SASL_SIMPLE );
00094        ldapversion = NSLDAPI_LDAP_VERSION( ld );
00095 
00096        /* only ldapv3 or higher can do sasl binds */
00097        if ( !simple && ldapversion < LDAP_VERSION3 ) {
00098               LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL );
00099               return( LDAP_NOT_SUPPORTED );
00100        }
00101 
00102        LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK );
00103        msgid = ++ld->ld_msgid;
00104        LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK );
00105 
00106        if ( dn == NULL )
00107               dn = "";
00108 
00109        if ( ld->ld_cache_on && ld->ld_cache_bind != NULL ) {
00110               LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK );
00111               if ( (rc = (ld->ld_cache_bind)( ld, msgid, LDAP_REQ_BIND, dn,
00112                   cred, LDAP_AUTH_SASL )) != 0 ) {
00113                      *msgidp = rc;
00114                      LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
00115                      return( LDAP_SUCCESS );
00116               }
00117               LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
00118        }
00119 
00120        /* create a message to send */
00121        if (( rc = nsldapi_alloc_ber_with_options( ld, &ber ))
00122            != LDAP_SUCCESS ) {
00123               return( rc );
00124        }
00125 
00126        /* fill it in */
00127        if ( simple ) {             /* simple bind; works in LDAPv2 or v3 */
00128               struct berval tmpcred;
00129 
00130               if ( cred == NULL ) {
00131                      tmpcred.bv_val = "";
00132                      tmpcred.bv_len = 0;
00133                      cred = &tmpcred;
00134               }
00135               rc = ber_printf( ber, "{it{isto}", msgid, LDAP_REQ_BIND,
00136                   ldapversion, dn, LDAP_AUTH_SIMPLE, cred->bv_val,
00137                   (int)cred->bv_len /* XXX lossy cast */ );
00138 
00139        } else {             /* SASL bind; requires LDAPv3 or better */
00140               if ( cred == NULL ) {
00141                      rc = ber_printf( ber, "{it{ist{s}}", msgid,
00142                          LDAP_REQ_BIND, ldapversion, dn, LDAP_AUTH_SASL,
00143                          mechanism );
00144               } else {
00145                      rc = ber_printf( ber, "{it{ist{so}}", msgid,
00146                          LDAP_REQ_BIND, ldapversion, dn, LDAP_AUTH_SASL,
00147                          mechanism, cred->bv_val,
00148                          (int)cred->bv_len /* XXX lossy cast */ );
00149               }
00150        }
00151 
00152        if ( rc == -1 ) {
00153               LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL );
00154               ber_free( ber, 1 );
00155               return( LDAP_ENCODING_ERROR );
00156        }
00157 
00158        if ( (rc = nsldapi_put_controls( ld, serverctrls, 1, ber ))
00159            != LDAP_SUCCESS ) {
00160               ber_free( ber, 1 );
00161               return( rc );
00162        }
00163 
00164        /* send the message */
00165        rc = nsldapi_send_initial_request( ld, msgid, LDAP_REQ_BIND,
00166               (char *)dn, ber );
00167        *msgidp = rc;
00168        return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS );
00169 }
00170 
00171 /*
00172  * ldap_sasl_bind_s - bind to the ldap server using sasl authentication
00173  * The dn, mechanism, and credentials of the entry to which to bind are
00174  * supplied.  LDAP_SUCCESS is returned upon success, the ldap error code
00175  * otherwise.
00176  *
00177  * Example:
00178  *     struct berval creds;
00179  *     ... fill in creds with credentials ...
00180  *     ldap_sasl_bind_s( ld, "cn=manager, o=university of michigan, c=us",
00181  *         "mechanismname", &creds )
00182  */
00183 int
00184 LDAP_CALL
00185 ldap_sasl_bind_s(
00186     LDAP             *ld,
00187     const char              *dn,
00188     const char              *mechanism,
00189     const struct berval     *cred,
00190     LDAPControl             **serverctrls,
00191     LDAPControl             **clientctrls,
00192     struct berval    **servercredp
00193 )
00194 {
00195        int           err, msgid;
00196        LDAPMessage   *result;
00197 
00198        LDAPDebug( LDAP_DEBUG_TRACE, "ldap_sasl_bind_s\n", 0, 0, 0 );
00199 
00200        if ( ( err = ldap_sasl_bind( ld, dn, mechanism, cred, serverctrls,
00201            clientctrls, &msgid )) != LDAP_SUCCESS )
00202               return( err );
00203 
00204        if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result ) == -1 )
00205               return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
00206 
00207        if (( err = ldap_parse_sasl_bind_result( ld, result, servercredp, 0 ))
00208            != LDAP_SUCCESS ) {
00209               ldap_msgfree( result );
00210               return( err );
00211        }
00212 
00213        return( ldap_result2error( ld, result, 1 ) );
00214 }
00215 
00216 
00217 /* returns an LDAP error code that indicates if parse succeeded or not */
00218 int
00219 LDAP_CALL
00220 ldap_parse_sasl_bind_result(
00221     LDAP             *ld,
00222     LDAPMessage             *res,
00223     struct berval    **servercredp,
00224     int                     freeit
00225 )
00226 {
00227        BerElement    ber;
00228        int           rc, err;
00229        long          along;
00230        unsigned long len;
00231        char          *m, *e;
00232 
00233        LDAPDebug( LDAP_DEBUG_TRACE, "ldap_parse_sasl_bind_result\n", 0, 0, 0 );
00234 
00235        /*
00236         * the ldapv3 SASL bind response looks like this:
00237         *
00238         *     BindResponse ::= [APPLICATION 1] SEQUENCE {
00239         *            COMPONENTS OF LDAPResult,
00240         *            serverSaslCreds [7] OCTET STRING OPTIONAL
00241         *     }
00242         *
00243         * all wrapped up in an LDAPMessage sequence.
00244         */
00245 
00246        if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) ||
00247            !NSLDAPI_VALID_LDAPMESSAGE_BINDRESULT_POINTER( res )) {
00248               return( LDAP_PARAM_ERROR );
00249        }
00250 
00251        /* only ldapv3 or higher can do sasl binds */
00252        if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) {
00253               LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL );
00254               return( LDAP_NOT_SUPPORTED );
00255        }
00256 
00257        if ( servercredp != NULL ) {
00258               *servercredp = NULL;
00259        }
00260 
00261        ber = *(res->lm_ber);       /* struct copy */
00262 
00263        /* skip past message id, matched dn, error message ... */
00264        rc = ber_scanf( &ber, "{iaa}", &along, &m, &e );
00265 
00266        if ( rc != LBER_ERROR &&
00267            ber_peek_tag( &ber, &len ) == LDAP_TAG_SASL_RES_CREDS ) {
00268               rc = ber_get_stringal( &ber, servercredp );
00269        }
00270 
00271        if ( freeit ) {
00272               ldap_msgfree( res );
00273        }
00274 
00275        if ( rc == LBER_ERROR ) {
00276               err = LDAP_DECODING_ERROR;
00277        } else {
00278               err = (int) along;
00279        }
00280 
00281        LDAP_SET_LDERRNO( ld, err, m, e );
00282        /* this is a little kludge for the 3.0 Barracuda/hammerhead relese */
00283        /* the docs state that the return is either LDAP_DECODING_ERROR */
00284        /* or LDAP_SUCCESS.  Here we match the docs...  it's cleaner in 3.1 */
00285 
00286        if ( LDAP_DECODING_ERROR == err ) {
00287               return (LDAP_DECODING_ERROR);
00288        } else {
00289               return( LDAP_SUCCESS );
00290        }
00291 }