diff options
Diffstat (limited to 'ldap/c-sdk/libraries/libldap/saslbind.c')
-rw-r--r-- | ldap/c-sdk/libraries/libldap/saslbind.c | 877 |
1 files changed, 0 insertions, 877 deletions
diff --git a/ldap/c-sdk/libraries/libldap/saslbind.c b/ldap/c-sdk/libraries/libldap/saslbind.c deleted file mode 100644 index 5cbe73bbf..000000000 --- a/ldap/c-sdk/libraries/libldap/saslbind.c +++ /dev/null @@ -1,877 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "ldap-int.h" - -#ifdef LDAP_SASLIO_HOOKS -/* - * Global SASL Init data - */ - -static int -nsldapi_sasl_fail() -{ - return( SASL_FAIL ); -} - -sasl_callback_t client_callbacks[] = { - { SASL_CB_GETOPT, nsldapi_sasl_fail, NULL }, - { SASL_CB_GETREALM, NULL, NULL }, - { SASL_CB_USER, NULL, NULL }, - { SASL_CB_CANON_USER, NULL, NULL }, - { SASL_CB_AUTHNAME, NULL, NULL }, - { SASL_CB_PASS, NULL, NULL }, - { SASL_CB_ECHOPROMPT, NULL, NULL }, - { SASL_CB_NOECHOPROMPT, NULL, NULL }, - { SASL_CB_LIST_END, NULL, NULL } -}; - -int -nsldapi_sasl_cvterrno( LDAP *ld, int err, char *msg ) -{ - int rc = LDAP_LOCAL_ERROR; - - switch (err) { - case SASL_OK: - rc = LDAP_SUCCESS; - break; - case SASL_NOMECH: - rc = LDAP_AUTH_UNKNOWN; - break; - case SASL_BADSERV: - rc = LDAP_CONNECT_ERROR; - break; - case SASL_DISABLED: - case SASL_ENCRYPT: - case SASL_EXPIRED: - case SASL_NOUSERPASS: - case SASL_NOVERIFY: - case SASL_PWLOCK: - case SASL_TOOWEAK: - case SASL_UNAVAIL: - case SASL_WEAKPASS: - rc = LDAP_INAPPROPRIATE_AUTH; - break; - case SASL_BADAUTH: - case SASL_NOAUTHZ: - rc = LDAP_INVALID_CREDENTIALS; - break; - case SASL_NOMEM: - rc = LDAP_NO_MEMORY; - break; - case SASL_NOUSER: - rc = LDAP_NO_SUCH_OBJECT; - break; - case SASL_CONTINUE: - case SASL_FAIL: - case SASL_INTERACT: - default: - rc = LDAP_LOCAL_ERROR; - break; - } - - LDAP_SET_LDERRNO( ld, rc, NULL, msg ); - return( rc ); -} - -#ifdef LDAP_SASLIO_GET_MECHS_FROM_SERVER -/* - * Get available SASL Mechanisms supported by the server - */ - -static int -nsldapi_get_sasl_mechs ( LDAP *ld, char **pmech ) -{ - char *attr[] = { "supportedSASLMechanisms", NULL }; - char **values, **v, *mech, *m; - LDAPMessage *res, *e; - struct timeval timeout; - int slen, rc; - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - timeout.tv_sec = SEARCH_TIMEOUT_SECS; - timeout.tv_usec = 0; - - rc = ldap_search_st( ld, "", LDAP_SCOPE_BASE, - "objectclass=*", attr, 0, &timeout, &res ); - - if ( rc != LDAP_SUCCESS ) { - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - e = ldap_first_entry( ld, res ); - if ( e == NULL ) { - ldap_msgfree( res ); - if ( ld->ld_errno == LDAP_SUCCESS ) { - LDAP_SET_LDERRNO( ld, LDAP_NO_SUCH_OBJECT, NULL, NULL ); - } - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - } - - values = ldap_get_values( ld, e, "supportedSASLMechanisms" ); - if ( values == NULL ) { - ldap_msgfree( res ); - LDAP_SET_LDERRNO( ld, LDAP_NO_SUCH_ATTRIBUTE, NULL, NULL ); - return( LDAP_NO_SUCH_ATTRIBUTE ); - } - - slen = 0; - for(v = values; *v != NULL; v++ ) { - slen += strlen(*v) + 1; - } - if ( (mech = NSLDAPI_CALLOC(1, slen)) == NULL) { - ldap_value_free( values ); - ldap_msgfree( res ); - LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); - return( LDAP_NO_MEMORY ); - } - m = mech; - for(v = values; *v; v++) { - if (v != values) { - *m++ = ' '; - } - slen = strlen(*v); - strncpy(m, *v, slen); - m += slen; - } - *m = '\0'; - - ldap_value_free( values ); - ldap_msgfree( res ); - - *pmech = mech; - - return( LDAP_SUCCESS ); -} -#endif /* LDAP_SASLIO_GET_MECHS_FROM_SERVER */ - -int -nsldapi_sasl_secprops( - const char *in, - sasl_security_properties_t *secprops ) -{ - int i; - char **props = NULL; - char *inp; - unsigned sflags = 0; - sasl_ssf_t max_ssf = 0; - sasl_ssf_t min_ssf = 0; - unsigned maxbufsize = 0; - int got_sflags = 0; - int got_max_ssf = 0; - int got_min_ssf = 0; - int got_maxbufsize = 0; - - if (in == NULL) { - return LDAP_PARAM_ERROR; - } - inp = nsldapi_strdup(in); - if (inp == NULL) { - return LDAP_PARAM_ERROR; - } - props = ldap_str2charray( inp, "," ); - NSLDAPI_FREE( inp ); - - if( props == NULL || secprops == NULL ) { - return LDAP_PARAM_ERROR; - } - - for( i=0; props[i]; i++ ) { - if( strcasecmp(props[i], "none") == 0 ) { - got_sflags++; - - } else if( strcasecmp(props[i], "noactive") == 0 ) { - got_sflags++; - sflags |= SASL_SEC_NOACTIVE; - - } else if( strcasecmp(props[i], "noanonymous") == 0 ) { - got_sflags++; - sflags |= SASL_SEC_NOANONYMOUS; - - } else if( strcasecmp(props[i], "nodict") == 0 ) { - got_sflags++; - sflags |= SASL_SEC_NODICTIONARY; - - } else if( strcasecmp(props[i], "noplain") == 0 ) { - got_sflags++; - sflags |= SASL_SEC_NOPLAINTEXT; - - } else if( strcasecmp(props[i], "forwardsec") == 0 ) { - got_sflags++; - sflags |= SASL_SEC_FORWARD_SECRECY; - - } else if( strcasecmp(props[i], "passcred") == 0 ) { - got_sflags++; - sflags |= SASL_SEC_PASS_CREDENTIALS; - - } else if( strncasecmp(props[i], - "minssf=", sizeof("minssf")) == 0 ) { - if( isdigit( props[i][sizeof("minssf")] ) ) { - got_min_ssf++; - min_ssf = atoi( &props[i][sizeof("minssf")] ); - } else { - return LDAP_NOT_SUPPORTED; - } - - } else if( strncasecmp(props[i], - "maxssf=", sizeof("maxssf")) == 0 ) { - if( isdigit( props[i][sizeof("maxssf")] ) ) { - got_max_ssf++; - max_ssf = atoi( &props[i][sizeof("maxssf")] ); - } else { - return LDAP_NOT_SUPPORTED; - } - - } else if( strncasecmp(props[i], - "maxbufsize=", sizeof("maxbufsize")) == 0 ) { - if( isdigit( props[i][sizeof("maxbufsize")] ) ) { - got_maxbufsize++; - maxbufsize = atoi( &props[i][sizeof("maxbufsize")] ); - if( maxbufsize && - (( maxbufsize < SASL_MIN_BUFF_SIZE ) - || (maxbufsize > SASL_MAX_BUFF_SIZE ))) { - return( LDAP_PARAM_ERROR ); - } - } else { - return( LDAP_NOT_SUPPORTED ); - } - } else { - return( LDAP_NOT_SUPPORTED ); - } - } - - if(got_sflags) { - secprops->security_flags = sflags; - } - if(got_min_ssf) { - secprops->min_ssf = min_ssf; - } - if(got_max_ssf) { - secprops->max_ssf = max_ssf; - } - if(got_maxbufsize) { - secprops->maxbufsize = maxbufsize; - } - - ldap_charray_free( props ); - return( LDAP_SUCCESS ); -} -#endif /* LDAP_SASLIO_HOOKS */ - -static int -nsldapi_sasl_bind_s( - LDAP *ld, - const char *dn, - const char *mechanism, - const struct berval *cred, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - struct berval **servercredp, - LDAPControl ***responsectrls -) -{ - int err, msgid; - LDAPMessage *result; - - LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_sasl_bind_s\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { - LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); - return( LDAP_NOT_SUPPORTED ); - } - - if ( ( err = ldap_sasl_bind( ld, dn, mechanism, cred, serverctrls, - clientctrls, &msgid )) != LDAP_SUCCESS ) - return( err ); - - if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result ) == -1 ) - return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); - - /* Get the controls sent by the server if requested */ - if ( responsectrls ) { - if ( ( err = ldap_parse_result( ld, result, &err, NULL, NULL, - NULL, responsectrls, 0 )) != LDAP_SUCCESS ) - return( err ); - } - - err = ldap_parse_sasl_bind_result( ld, result, servercredp, 0 ); - if (err != LDAP_SUCCESS && err != LDAP_SASL_BIND_IN_PROGRESS) { - ldap_msgfree( result ); - return( err ); - } - - return( ldap_result2error( ld, result, 1 ) ); -} - -#ifdef LDAP_SASLIO_HOOKS -static int -nsldapi_sasl_do_bind( LDAP *ld, const char *dn, - const char *mechs, unsigned flags, - LDAP_SASL_INTERACT_PROC *callback, void *defaults, - LDAPControl **sctrl, LDAPControl **cctrl, LDAPControl ***rctrl ) -{ - sasl_interact_t *prompts = NULL; - sasl_conn_t *ctx = NULL; - sasl_ssf_t *ssf = NULL; - const char *mech = NULL; - int saslrc, rc; - struct berval ccred; - unsigned credlen; - int stepnum = 1; - char *sasl_username = NULL; - - if (rctrl) { - /* init to NULL so we can call ldap_controls_free below */ - *rctrl = NULL; - } - - if (NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3) { - LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); - return( LDAP_NOT_SUPPORTED ); - } - - /* shouldn't happen */ - if (callback == NULL) { - return( LDAP_LOCAL_ERROR ); - } - - if ( (rc = nsldapi_sasl_open(ld, NULL, &ctx, 0)) != LDAP_SUCCESS ) { - return( rc ); - } - - ccred.bv_val = NULL; - ccred.bv_len = 0; - - LDAPDebug(LDAP_DEBUG_TRACE, "Starting SASL/%s authentication\n", - (mechs ? mechs : ""), 0, 0 ); - - do { - saslrc = sasl_client_start( ctx, - mechs, - &prompts, - (const char **)&ccred.bv_val, - &credlen, - &mech ); - - LDAPDebug(LDAP_DEBUG_TRACE, "Doing step %d of client start for SASL/%s authentication\n", - stepnum, (mech ? mech : ""), 0 ); - stepnum++; - - if( saslrc == SASL_INTERACT && - (callback)(ld, flags, defaults, prompts) != LDAP_SUCCESS ) { - break; - } - } while ( saslrc == SASL_INTERACT ); - - ccred.bv_len = credlen; - - if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { - return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) ); - } - - stepnum = 1; - - do { - struct berval *scred; - int clientstepnum = 1; - - scred = NULL; - - if (rctrl) { - /* if we're looping again, we need to free any controls set - during the previous loop */ - /* NOTE that this assumes we only care about the controls - returned by the last call to nsldapi_sasl_bind_s - if - we care about _all_ controls, we will have to figure out - some way to append them each loop go round */ - ldap_controls_free(*rctrl); - *rctrl = NULL; - } - - LDAPDebug(LDAP_DEBUG_TRACE, "Doing step %d of bind for SASL/%s authentication\n", - stepnum, (mech ? mech : ""), 0 ); - stepnum++; - - /* notify server of a sasl bind step */ - rc = nsldapi_sasl_bind_s(ld, dn, mech, &ccred, - sctrl, cctrl, &scred, rctrl); - - if ( ccred.bv_val != NULL ) { - ccred.bv_val = NULL; - } - - if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) { - ber_bvfree( scred ); - return( rc ); - } - - if( rc == LDAP_SUCCESS && saslrc == SASL_OK ) { - /* we're done, no need to step */ - if( scred ) { - if ( scred->bv_len == 0 ) { /* MS AD sends back empty screds */ - LDAPDebug(LDAP_DEBUG_ANY, - "SASL BIND complete - ignoring empty credential response\n", - 0, 0, 0); - ber_bvfree( scred ); - } else { - /* but server provided us with data! */ - LDAPDebug(LDAP_DEBUG_TRACE, - "SASL BIND complete but invalid because server responded with credentials - length [%u]\n", - scred->bv_len, 0, 0); - ber_bvfree( scred ); - LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, - NULL, "Error during SASL handshake - invalid server credential response" ); - return( LDAP_LOCAL_ERROR ); - } - } - break; - } - - /* perform the next step of the sasl bind */ - do { - LDAPDebug(LDAP_DEBUG_TRACE, "Doing client step %d of bind step %d for SASL/%s authentication\n", - clientstepnum, stepnum, (mech ? mech : "") ); - clientstepnum++; - saslrc = sasl_client_step( ctx, - (scred == NULL) ? NULL : scred->bv_val, - (scred == NULL) ? 0 : scred->bv_len, - &prompts, - (const char **)&ccred.bv_val, - &credlen ); - - if( saslrc == SASL_INTERACT && - (callback)(ld, flags, defaults, prompts) - != LDAP_SUCCESS ) { - break; - } - } while ( saslrc == SASL_INTERACT ); - - ccred.bv_len = credlen; - ber_bvfree( scred ); - - if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { - return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) ); - } - } while ( rc == LDAP_SASL_BIND_IN_PROGRESS ); - - if ( rc != LDAP_SUCCESS ) { - return( rc ); - } - - if ( saslrc != SASL_OK ) { - return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) ); - } - - saslrc = sasl_getprop( ctx, SASL_USERNAME, (const void **) &sasl_username ); - if ( (saslrc == SASL_OK) && sasl_username ) { - LDAPDebug(LDAP_DEBUG_TRACE, "SASL identity: %s\n", sasl_username, 0, 0); - } - - saslrc = sasl_getprop( ctx, SASL_SSF, (const void **) &ssf ); - if( saslrc == SASL_OK ) { - if( ssf && *ssf ) { - LDAPDebug(LDAP_DEBUG_TRACE, - "SASL install encryption, for SSF: %lu\n", - (unsigned long) *ssf, 0, 0 ); - nsldapi_sasl_install( ld, NULL ); - } - } - - return( rc ); -} -#endif /* LDAP_SASLIO_HOOKS */ - - -/* - * ldap_sasl_bind - authenticate to the ldap server. The dn, mechanism, - * and credentials of the entry to which to bind are supplied. An LDAP - * error code is returned and if LDAP_SUCCESS is returned *msgidp is set - * to the id of the request initiated. - * - * Example: - * struct berval creds; - * LDAPControl **ctrls; - * int err, msgid; - * ... fill in creds with credentials ... - * ... fill in ctrls with server controls ... - * err = ldap_sasl_bind( ld, "cn=manager, o=university of michigan, c=us", - * "mechanismname", &creds, ctrls, NULL, &msgid ); - */ -int -LDAP_CALL -ldap_sasl_bind( - LDAP *ld, - const char *dn, - const char *mechanism, - const struct berval *cred, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - int *msgidp -) -{ - BerElement *ber; - int rc, simple, msgid, ldapversion; - - /* - * The ldapv3 bind request looks like this: - * BindRequest ::= SEQUENCE { - * version INTEGER, - * name DistinguishedName, -- who - * authentication CHOICE { - * simple [0] OCTET STRING, -- passwd - * sasl [3] SaslCredentials -- v3 only - * } - * } - * SaslCredentials ::= SEQUENCE { - * mechanism LDAPString, - * credentials OCTET STRING - * } - * all wrapped up in an LDAPMessage sequence. - */ - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ( msgidp == NULL ) { - LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); - return( LDAP_PARAM_ERROR ); - } - - if ( ( ld->ld_options & LDAP_BITOPT_RECONNECT ) != 0 ) { - nsldapi_handle_reconnect( ld ); - } - - simple = ( mechanism == LDAP_SASL_SIMPLE ); - ldapversion = NSLDAPI_LDAP_VERSION( ld ); - - /* only ldapv3 or higher can do sasl binds */ - if ( !simple && ldapversion < LDAP_VERSION3 ) { - LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); - return( LDAP_NOT_SUPPORTED ); - } - - LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); - msgid = ++ld->ld_msgid; - LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); - - if ( dn == NULL ) - dn = ""; - - if ( ld->ld_cache_on && ld->ld_cache_bind != NULL ) { - LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); - if ( (rc = (ld->ld_cache_bind)( ld, msgid, LDAP_REQ_BIND, dn, - cred, LDAP_AUTH_SASL )) != 0 ) { - *msgidp = rc; - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - return( LDAP_SUCCESS ); - } - LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); - } - - /* create a message to send */ - if (( rc = nsldapi_alloc_ber_with_options( ld, &ber )) - != LDAP_SUCCESS ) { - return( rc ); - } - - /* fill it in */ - if ( simple ) { /* simple bind; works in LDAPv2 or v3 */ - struct berval tmpcred; - - if ( cred == NULL ) { - tmpcred.bv_val = ""; - tmpcred.bv_len = 0; - cred = &tmpcred; - } - rc = ber_printf( ber, "{it{isto}", msgid, LDAP_REQ_BIND, - ldapversion, dn, LDAP_AUTH_SIMPLE, cred->bv_val, - cred->bv_len ); - - } else { /* SASL bind; requires LDAPv3 or better */ - if ( cred == NULL || cred->bv_val == NULL || cred->bv_len == 0) { - rc = ber_printf( ber, "{it{ist{s}}", msgid, - LDAP_REQ_BIND, ldapversion, dn, LDAP_AUTH_SASL, - mechanism ); - } else { - rc = ber_printf( ber, "{it{ist{so}}", msgid, - LDAP_REQ_BIND, ldapversion, dn, LDAP_AUTH_SASL, - mechanism, cred->bv_val, - cred->bv_len ); - } - } - - if ( rc == -1 ) { - LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); - ber_free( ber, 1 ); - return( LDAP_ENCODING_ERROR ); - } - - if ( (rc = nsldapi_put_controls( ld, serverctrls, 1, ber )) - != LDAP_SUCCESS ) { - ber_free( ber, 1 ); - return( rc ); - } - - /* send the message */ - rc = nsldapi_send_initial_request( ld, msgid, LDAP_REQ_BIND, - (char *)dn, ber ); - *msgidp = rc; - return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); -} - -/* - * ldap_sasl_bind_s - bind to the ldap server using sasl authentication - * The dn, mechanism, and credentials of the entry to which to bind are - * supplied. LDAP_SUCCESS is returned upon success, the ldap error code - * otherwise. - * - * Example: - * struct berval creds; - * ... fill in creds with credentials ... - * ldap_sasl_bind_s( ld, "cn=manager, o=university of michigan, c=us", - * "mechanismname", &creds ) - */ -int -LDAP_CALL -ldap_sasl_bind_s( - LDAP *ld, - const char *dn, - const char *mechanism, - const struct berval *cred, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - struct berval **servercredp -) -{ - return ( nsldapi_sasl_bind_s( ld, dn, mechanism, cred, - serverctrls, clientctrls, servercredp, NULL ) ); -} - -#ifdef LDAP_SASLIO_HOOKS -/* - * SASL Authentication Interface: ldap_sasl_interactive_bind_s - * - * This routine takes a DN, SASL mech list, and a SASL callback - * and performs the necessary sequencing to complete a SASL bind - * to the LDAP connection ld. The user provided callback can - * use an optionally provided set of default values to complete - * any necessary interactions. - * - * Currently imposes the following restrictions: - * A mech list must be provided - * LDAP_SASL_INTERACTIVE mode requires a callback - */ -int -LDAP_CALL -ldap_sasl_interactive_bind_s( LDAP *ld, const char *dn, - const char *saslMechanism, - LDAPControl **sctrl, LDAPControl **cctrl, unsigned flags, - LDAP_SASL_INTERACT_PROC *callback, void *defaults ) -{ - return ldap_sasl_interactive_bind_ext_s( ld, dn, - saslMechanism, sctrl, cctrl, flags, callback, - defaults, NULL ); -} - -/* - * ldap_sasl_interactive_bind_ext_s - * - * This function extends ldap_sasl_interactive_bind_s by allowing - * controls received from the server to be returned as rctrl. The - * caller must pass in a valid LDAPControl** pointer and free the - * array of controls when finished with them e.g. - * LDAPControl **retctrls = NULL; - * ... - * ldap_sasl_interactive_bind_ext_s(ld, ...., &retctrls); - * ... - * ldap_controls_free(retctrls); - * Only the controls from the server during the last bind step are returned - - * intermediate controls (if any, usually not) are discarded. - */ -int -LDAP_CALL -ldap_sasl_interactive_bind_ext_s( LDAP *ld, const char *dn, - const char *saslMechanism, - LDAPControl **sctrl, LDAPControl **cctrl, unsigned flags, - LDAP_SASL_INTERACT_PROC *callback, void *defaults, LDAPControl ***rctrl ) -{ -#ifdef LDAP_SASLIO_GET_MECHS_FROM_SERVER - char *smechs; -#endif - int rc; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_sasl_interactive_bind_s\n", 0, 0, 0 ); - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { - return( LDAP_PARAM_ERROR ); - } - - if ((flags == LDAP_SASL_INTERACTIVE) && (callback == NULL)) { - return( LDAP_PARAM_ERROR ); - } - - LDAP_MUTEX_LOCK(ld, LDAP_SASL_LOCK ); - - if( saslMechanism == NULL || *saslMechanism == '\0' ) { -#ifdef LDAP_SASLIO_GET_MECHS_FROM_SERVER - rc = nsldapi_get_sasl_mechs( ld, &smechs ); - if( rc != LDAP_SUCCESS ) { - LDAP_MUTEX_UNLOCK(ld, LDAP_SASL_LOCK ); - return( rc ); - } - saslMechanism = smechs; -#else - LDAP_MUTEX_UNLOCK(ld, LDAP_SASL_LOCK ); - return( LDAP_PARAM_ERROR ); -#endif /* LDAP_SASLIO_GET_MECHS_FROM_SERVER */ - } - - rc = nsldapi_sasl_do_bind( ld, dn, saslMechanism, - flags, callback, defaults, sctrl, cctrl, rctrl); - - LDAP_MUTEX_UNLOCK(ld, LDAP_SASL_LOCK ); - return( rc ); -} -#else /* LDAP_SASLIO_HOOKS */ -/* stubs for platforms that do not support SASL */ -int -LDAP_CALL -ldap_sasl_interactive_bind_s( LDAP *ld, const char *dn, - const char *saslMechanism, - LDAPControl **sctrl, LDAPControl **cctrl, unsigned flags, - LDAP_SASL_INTERACT_PROC *callback, void *defaults ) -{ - return LDAP_SUCCESS; -} - -int -LDAP_CALL -ldap_sasl_interactive_bind_ext_s( LDAP *ld, const char *dn, - const char *saslMechanism, - LDAPControl **sctrl, LDAPControl **cctrl, unsigned flags, - LDAP_SASL_INTERACT_PROC *callback, void *defaults, LDAPControl ***rctrl ) -{ - return LDAP_SUCCESS; -} -#endif /* LDAP_SASLIO_HOOKS */ - - -/* returns an LDAP error code that indicates if parse succeeded or not */ -int -LDAP_CALL -ldap_parse_sasl_bind_result( - LDAP *ld, - LDAPMessage *res, - struct berval **servercredp, - int freeit -) -{ - BerElement ber; - int rc, err; - ber_int_t along; - ber_len_t len; - char *m, *e; - - LDAPDebug( LDAP_DEBUG_TRACE, "ldap_parse_sasl_bind_result\n", 0, 0, 0 ); - - /* - * the ldapv3 SASL bind response looks like this: - * - * BindResponse ::= [APPLICATION 1] SEQUENCE { - * COMPONENTS OF LDAPResult, - * serverSaslCreds [7] OCTET STRING OPTIONAL - * } - * - * all wrapped up in an LDAPMessage sequence. - */ - - if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || - !NSLDAPI_VALID_LDAPMESSAGE_BINDRESULT_POINTER( res )) { - return( LDAP_PARAM_ERROR ); - } - - /* only ldapv3 or higher can do sasl binds */ - if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { - LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); - return( LDAP_NOT_SUPPORTED ); - } - - if ( servercredp != NULL ) { - *servercredp = NULL; - } - - ber = *(res->lm_ber); /* struct copy */ - - /* skip past message id, matched dn, error message ... */ - rc = ber_scanf( &ber, "{iaa}", &along, &m, &e ); - - if ( rc != LBER_ERROR && - ber_peek_tag( &ber, &len ) == LDAP_TAG_SASL_RES_CREDS ) { - rc = ber_get_stringal( &ber, servercredp ); - } - - if ( freeit ) { - ldap_msgfree( res ); - } - - if ( rc == LBER_ERROR ) { - err = LDAP_DECODING_ERROR; - } else { - err = (int) along; - } - - LDAP_SET_LDERRNO( ld, err, m, e ); - /* this is a little kludge for the 3.0 Barracuda/hammerhead relese */ - /* the docs state that the return is either LDAP_DECODING_ERROR */ - /* or LDAP_SUCCESS. Here we match the docs... it's cleaner in 3.1 */ - - if ( LDAP_DECODING_ERROR == err ) { - return (LDAP_DECODING_ERROR); - } else { - return( LDAP_SUCCESS ); - } -} - |