[Date Prev][Date Next] [Chronological] [Thread] [Top]

ldap sasl bind programming : digest-md5 problem



hello all

I'm trying to program an sasl/digest-md5 bind with libldap
I use the following code, nearly totally pasted from ldap client tools
source code
it compiles, but when I start it I got a sasl bind in progress (tag=66)"
error in my slapd logs

somebody can help me ?

thank you very much :)

Francois


#include <stdio.h>
#include <ldap.h>
#include <sasl.h>

typedef struct lutil_sasl_defaults_s {
	char *mech;
	char *realm;
	char *authcid;
	char *passwd;
	char *authzid;
} lutilSASLdefaults;

void *lutil_sasl_defaults(LDAP *ld, char *mech, char *realm, char
*authcid, char *passwd, char *authzid);
static int interaction ( unsigned flags, sasl_interact_t *interact,
lutilSASLdefaults *defaults);
int ldap_sasl_interaction(LDAP *ld, unsigned flags, void *defaults, void
*in);

int main(int argc, char *argv[])
{
	void	*defaults;
	unsigned sasl_flags		= LDAP_SASL_QUIET;
	char	*sasl_mech		= ber_strdup("DIGEST-MD5");
	char	*sasl_realm		= NULL;
	//char 	*sasl_authc_id	= ber_strdup("francois");
	char 	*sasl_authc_id	= "francois";
	char 	*sasl_authz_id	= NULL;
	struct	berval passwd	= {0, NULL};

	int		rc;
	char	*ldaphost		= "linux-integ.enatel.local";
	int		ldapport		= 389;
	LDAP	*ld				= NULL;

    int		version			= LDAP_VERSION3;

	ld = ldap_init( ldaphost, ldapport );
	
    if (ldap_set_option(ld, 
 		LDAP_OPT_PROTOCOL_VERSION, 
 		&version) != LDAP_OPT_SUCCESS)
     	return LDAP_OPERATIONS_ERROR;
	
	defaults = lutil_sasl_defaults(ld,
			sasl_mech,
			sasl_realm,
			sasl_authc_id,
			passwd.bv_val,
			sasl_authz_id);

     rc = ldap_sasl_interactive_bind_s(ld, 
 					 NULL, 
 					 sasl_mech, 
 					 NULL, 
 					 NULL,
 					 sasl_flags, 
 					 ldap_sasl_interaction, 
 					 defaults);

	ldap_unbind (ld);
}

void *lutil_sasl_defaults(LDAP *ld, char *mech, char *realm, char
*authcid, char *passwd, char *authzid)
{
	lutilSASLdefaults *defaults;
	
	defaults = ber_memalloc( sizeof( lutilSASLdefaults ) );

	if( defaults == NULL ) return NULL;

	defaults->mech = mech;
	defaults->realm = realm;
	defaults->authcid = authcid;
	defaults->passwd = passwd;
	defaults->authzid = authzid;

	if( defaults->mech == NULL ) {
		ldap_get_option( ld, LDAP_OPT_X_SASL_MECH, &defaults->mech );
	}
	if( defaults->realm == NULL ) {
		ldap_get_option( ld, LDAP_OPT_X_SASL_REALM, &defaults->realm );
	}
	if( defaults->authcid == NULL ) {
		ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authcid );
	}
	if( defaults->authzid == NULL ) {
		ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->authzid );
	}

	return defaults;
}

 static int interaction ( unsigned flags, 
 			 sasl_interact_t *interact,
 			  lutilSASLdefaults *defaults )
 {
	const char *dflt = interact->defresult;
	char input[1024];

	int noecho=0;
	int challenge=0;

	switch( interact->id ) {
	case SASL_CB_GETREALM:
		if( defaults ) dflt = defaults->realm;
		break;
	case SASL_CB_AUTHNAME:
		if( defaults ) dflt = defaults->authcid;
		break;
	case SASL_CB_PASS:
		if( defaults ) dflt = defaults->passwd;
		noecho = 1;
		break;
	case SASL_CB_USER:
		if( defaults ) dflt = defaults->authzid;
		break;
	case SASL_CB_NOECHOPROMPT:
		noecho = 1;
		challenge = 1;
		break;
	case SASL_CB_ECHOPROMPT:
		challenge = 1;
		break;
	}

	if( dflt && !*dflt ) dflt = NULL;

	if( flags != LDAP_SASL_INTERACTIVE &&
		( dflt || interact->id == SASL_CB_USER ) )
	{
		goto use_default;
	}

	if( flags == LDAP_SASL_QUIET ) {
		/* don't prompt */
		return LDAP_OTHER;
	}

	if( challenge ) {
		if( interact->challenge ) {
			fprintf( stderr, "Challenge: %s\n", interact->challenge );
		}
	}

	if( dflt ) {
		fprintf( stderr, "Default: %s\n", dflt );
	}

	snprintf( input, sizeof input, "%s: ",
		interact->prompt ? interact->prompt : "Interact" );

	if( noecho ) {
		//interact->result = (char *) getpassphrase( input );
		interact->result = (char *) "toto";
		interact->len = interact->result
			? strlen( interact->result ) : 0;

	} else {
		/* prompt user */
		fputs( input, stderr );

		/* get input */
		interact->result = fgets( input, sizeof(input), stdin );

		if( interact->result == NULL ) {
			interact->len = 0;
			return LDAP_UNAVAILABLE;
		}

		/* len of input */
		interact->len = strlen(input); 

		if( interact->len > 0 && input[interact->len - 1] == '\n' ) {
			/* input includes '\n', trim it */
			interact->len--;
			input[interact->len] = '\0';
		}
	}


	if( interact->len > 0 ) {
		/* duplicate */
		char *p = (char *)interact->result;
		interact->result = strdup( p );

		/* zap */
		memset( p, '\0', interact->len );

	} else {
use_default:
		/* input must be empty */
		interact->result = strdup( (dflt && *dflt) ? dflt : "" );
		interact->len = interact->result
			? strlen( interact->result ) : 0;
	}

	if( defaults && defaults->passwd && interact->id == SASL_CB_PASS ) {
		/* zap password after first use */
		memset( defaults->passwd, '\0', strlen(defaults->passwd) );
		defaults->passwd = NULL;
	}

	return LDAP_SUCCESS;
}
 
 
int ldap_sasl_interaction(
	LDAP *ld,
	unsigned flags,
	void *defaults,
	void *in )
{
	sasl_interact_t *interact = in;

	if( interact->result ) {
		// we have results from a previous interaction
		free( (void *)interact->result );
		interact->result = NULL;
	}

	if( ld == NULL ) return LDAP_PARAM_ERROR;

	if( flags == LDAP_SASL_INTERACTIVE ) {
		fputs( "SASL Interaction\n", stderr );
	}

	while( interact->id != SASL_CB_LIST_END ) {
		int rc = interaction( flags, interact, defaults );

		if( rc )  return rc;
		interact++;
	}
	
	return LDAP_SUCCESS;
}