--- libraries/libldap/sasl.c 2000/01/16 00:29:15 1.9 +++ libraries/libldap/sasl.c 2000/05/10 23:40:02 1.18 @@ -1,4 +1,4 @@ -/* $OpenLDAP: pkg/ldap/libraries/libldap/sasl.c,v 1.8 2000/01/08 17:42:18 kdz Exp $ */ +/* $OpenLDAP: pkg/ldap/libraries/libldap/sasl.c,v 1.17 2000/05/03 16:59:58 kurt Exp $ */ /* * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file @@ -37,13 +37,14 @@ /* - * ldap_sasl_bind - bind to the ldap server (and X.500). The dn, mechanism, and - * credentials of the entry to which to bind are supplied. The message id - * of the request initiated is provided upon successful (LDAP_SUCCESS) return. + * ldap_sasl_bind - bind to the ldap server (and X.500). + * The dn (usually NULL), mechanism, and credentials are provided. + * The message id of the request initiated is provided upon successful + * (LDAP_SUCCESS) return. * * Example: - * ldap_sasl_bind( ld, "cn=manager, o=university of michigan, c=us", - * "mechanism", "secret", NULL, NULL, &msgid ) + * ldap_sasl_bind( ld, NULL, "mechanism", + * cred, NULL, NULL, &msgid ) */ int @@ -190,19 +191,21 @@ ldap_sasl_bind_s( rc = ldap_parse_sasl_bind_result( ld, result, &scredp, 0 ); } - if( rc != LDAP_SUCCESS ) { + if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) { ldap_msgfree( result ); return( rc ); } rc = ldap_result2error( ld, result, 1 ); - if( rc == LDAP_SUCCESS ) { + if ( rc == LDAP_SUCCESS || rc == LDAP_SASL_BIND_IN_PROGRESS ) { if( servercredp != NULL ) { *servercredp = scredp; + scredp = NULL; } + } - } else if (scredp != NULL ) { + if ( scredp != NULL ) { ber_bvfree(scredp); } @@ -496,42 +499,43 @@ static int sasl_close( Sockbuf *sb ) (ber_pvt_sb_io_tcp.sbi_close)( sb ); } -int -ldap_pvt_sasl_err2ldap( int saslerr ) +static int +sasl_err2ldap( int saslerr ) { int rc; switch (saslerr) { case SASL_CONTINUE: - rc = LDAP_SASL_BIND_IN_PROGRESS; + rc = LDAP_MORE_RESULTS_TO_RETURN; break; case SASL_OK: rc = LDAP_SUCCESS; break; case SASL_FAIL: - rc = LDAP_OPERATIONS_ERROR; + rc = LDAP_LOCAL_ERROR; break; case SASL_NOMEM: rc = LDAP_NO_MEMORY; break; case SASL_NOMECH: - rc = LDAP_AUTH_METHOD_NOT_SUPPORTED; + rc = LDAP_AUTH_UNKNOWN; break; case SASL_BADAUTH: - rc = LDAP_INVALID_CREDENTIALS; + rc = LDAP_AUTH_UNKNOWN; break; case SASL_NOAUTHZ: - rc = LDAP_INSUFFICIENT_ACCESS; + rc = LDAP_PARAM_ERROR; break; case SASL_TOOWEAK: case SASL_ENCRYPT: - rc = LDAP_INAPPROPRIATE_AUTH; + rc = LDAP_AUTH_UNKNOWN; break; default: - rc = LDAP_OPERATIONS_ERROR; + rc = LDAP_LOCAL_ERROR; break; } + assert( rc == LDAP_SUCCESS || LDAP_API_ERROR( rc ) ); return rc; } @@ -545,7 +549,7 @@ ldap_pvt_sasl_getmechs ( LDAP *ld, LDAP_ int rc; rc = ldap_search_s( ld, NULL, LDAP_SCOPE_BASE, - "(objectclass=*)", attrs, 0, &res ); + NULL, attrs, 0, &res ); if ( rc != LDAP_SUCCESS ) { return ld->ld_errno; @@ -570,7 +574,7 @@ ldap_pvt_sasl_getmechs ( LDAP *ld, LDAP_ rc = LDAP_INAPPROPRIATE_AUTH; for ( p = values; *p != NULL; p++ ) { - if ( !strcmp( *p, desired ) == 0 ) { + if ( strcmp( *p, desired ) == 0 ) { rc = LDAP_SUCCESS; break; } @@ -655,7 +659,7 @@ ldap_pvt_sasl_bind( if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { LDAP_FREE( mechlist ); - ld->ld_errno = ldap_pvt_sasl_err2ldap( rc ); + ld->ld_errno = sasl_err2ldap( rc ); sasl_dispose( &ld->ld_sasl_context ); return ld->ld_errno; } @@ -674,7 +678,7 @@ ldap_pvt_sasl_bind( LDAP_FREE( mechlist ); if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { - ld->ld_errno = ldap_pvt_sasl_err2ldap( saslrc ); + ld->ld_errno = sasl_err2ldap( saslrc ); sasl_dispose( &ld->ld_sasl_context ); return ld->ld_errno; } @@ -710,7 +714,7 @@ ldap_pvt_sasl_bind( ber_bvfree( scred ); if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { - ld->ld_errno = ldap_pvt_sasl_err2ldap( saslrc ); + ld->ld_errno = sasl_err2ldap( saslrc ); sasl_dispose( &ld->ld_sasl_context ); return ld->ld_errno; } @@ -781,44 +785,128 @@ ldap_pvt_sasl_getsimple(void *context, i return SASL_OK; } +int +ldap_pvt_sasl_get_option( LDAP *ld, int option, void *arg ) +{ + sasl_ssf_t *ssf; + + if ( ld == NULL ) + return -1; + + switch ( option ) { + case LDAP_OPT_X_SASL_MINSSF: + *(int *)arg = ld->ld_options.ldo_sasl_minssf; + break; + case LDAP_OPT_X_SASL_MAXSSF: + *(int *)arg = ld->ld_options.ldo_sasl_maxssf; + break; + case LDAP_OPT_X_SASL_ACTSSF: + if ( ld->ld_sasl_context == NULL ) { + *(int *)arg = -1; + break; + } + if ( sasl_getprop( ld->ld_sasl_context, SASL_SSF, &ssf ) + != SASL_OK ) + return -1; + *(int *)arg = *ssf; + break; + default: + return -1; + } + return 0; +} + +int +ldap_pvt_sasl_set_option( LDAP *ld, int option, void *arg ) +{ + if ( ld == NULL ) + return -1; + + switch ( option ) { + case LDAP_OPT_X_SASL_MINSSF: + ld->ld_options.ldo_sasl_minssf = *(int *)arg; + break; + case LDAP_OPT_X_SASL_MAXSSF: + ld->ld_options.ldo_sasl_maxssf = *(int *)arg; + break; + case LDAP_OPT_X_SASL_ACTSSF: + /* This option is read-only */ + default: + return -1; + } + return 0; +} + /* - * ldap_negotiated_sasl_bind_s - bind to the ldap server (and X.500) using SASL - * authentication. The dn and password of the entry to which to bind are - * supplied. LDAP_SUCCESS is returned upon success, the ldap error code + * ldap_negotiated_sasl_bind_s - bind to the ldap server (and X.500) + * using SASL authentication. + * + * This routine attempts to authenticate the user referred by the + * authentication id using the provided password. An optional + * authorization identity may be provided. An DN is generally not + * provided [see AuthMethod]. + * + * If the mechanism negotiated does not require a password, the + * passwd field is ignored. [A callback mechanism should really + * be used]. + * + * LDAP_SUCCESS is returned upon success, the ldap error code * otherwise. * - * Example: + * Examples: + * ldap_negotiated_sasl_bind_s( ld, NULL, + * "user@OPENLDAP.ORG", NULL, NULL, + * "GSSAPI", NULL, NULL, NULL ); + * + * ldap_negotiated_sasl_bind_s( ld, NULL, + * "manager", "cn=user,dc=openldap,dc=org", NULL, + * "DIGEST-MD5", NULL, NULL, NULL ); + * + * ldap_negotiated_sasl_bind_s( ld, NULL, + * "root@OPENLDAP.ORG", "u:user@OPENLDAP.ORG", NULL, + * "GSSAPI", NULL, NULL, NULL ); + * * ldap_negotiated_sasl_bind_s( ld, NULL, - * "dn:cn=manager", NULL, "GSSAPI", NULL, NULL, NULL ); + * "manager", "dn:cn=user,dc=openldap,dc=org", NULL, + * "DIGEST-MD5", NULL, NULL, NULL ); */ int ldap_negotiated_sasl_bind_s( - LDAP *ld, + LDAP *ld, LDAP_CONST char *dn, /* usually NULL */ - LDAP_CONST char *authorizationId, - LDAP_CONST char *authenticationId, - LDAP_CONST char *saslMechanism, - struct berval *passPhrase, - LDAPControl **serverControls, - LDAPControl **clientControls) + LDAP_CONST char *authenticationId, + LDAP_CONST char *authorizationId, /* commonly NULL */ + LDAP_CONST char *saslMechanism, + struct berval *passPhrase, + LDAPControl **serverControls, + LDAPControl **clientControls) { + int n; sasl_callback_t callbacks[4]; int rc; - callbacks[0].id = SASL_CB_USER; - callbacks[0].proc = ldap_pvt_sasl_getsimple; - callbacks[0].context = (void *)authorizationId; - callbacks[1].id = SASL_CB_AUTHNAME; - callbacks[1].proc = ldap_pvt_sasl_getsimple; - callbacks[1].context = (void *)authenticationId; - callbacks[2].id = SASL_CB_PASS; - callbacks[2].proc = ldap_pvt_sasl_getsecret; - callbacks[2].context = (void *)passPhrase; - callbacks[3].id = SASL_CB_LIST_END; - callbacks[3].proc = NULL; - callbacks[3].context = NULL; + /* SASL Authentication Identity */ + callbacks[n=0].id = SASL_CB_AUTHNAME; + callbacks[n].proc = ldap_pvt_sasl_getsimple; + callbacks[n].context = (void *)authenticationId; + + /* SASL Authorization Identity (userid) */ + if( authorizationId != NULL ) { + callbacks[++n].id = SASL_CB_USER; + callbacks[n].proc = ldap_pvt_sasl_getsimple; + callbacks[n].context = (void *)authorizationId; + } + + callbacks[++n].id = SASL_CB_PASS; + callbacks[n].proc = ldap_pvt_sasl_getsecret; + callbacks[n].context = (void *)passPhrase; + + callbacks[++n].id = SASL_CB_LIST_END; + callbacks[n].proc = NULL; + callbacks[n].context = NULL; - rc = ldap_pvt_sasl_bind(ld, dn, saslMechanism, callbacks, serverControls, clientControls); + rc = ldap_pvt_sasl_bind(ld, dn, saslMechanism, callbacks, + serverControls, clientControls); return rc; }