1
votes

I have a problem where in ldap_sasl_bind_s does not work, but ldap_simple_bind_s works.

The strange thing is, ldap_sasl_bind_s works even with wrong passwords and gives user the feeling that he has entered a correct password.

PFA code snippet of the problem and suggest me if anything is wrong with my approach.

{
int rc, aReturnVal = 0;
NSString *aUserDN = [NSString stringWithFormat:@"uid=%s,cn=users,dc=example,dc=com", username];
char* userDN = (char*)[aUserDN UTF8String];
rc = ldap_simple_bind_s (
                       ld,
                       userDN,
                       password
                       );

    // TODO: ldap_simple_bind_s is a deprecated method and should not be used for long. ldap_sasl_bind_s is the right method, but is not working for now.
    // Find the reason and get this code up and running.
//  struct berval *servcred;
//  struct berval cred;
//  cred.bv_val = password; // my password
//  cred.bv_len = strlen(password);
//  rc = ldap_sasl_bind_s (
//               ld,
//               userDN,
//               "DIGEST-MD5",
//               &cred,
//               NULL,
//               NULL,
//               &servcred
//             );

if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_sasl_bind: %s\n", ldap_err2string( rc ) );
} else {
    aReturnVal = 1;
}

return aReturnVal;
}

I have initialized the LDAP using following code SNIP:

rc = ldap_initialize(&ld, HOSTNAME);
version = LDAP_VERSION3;
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
ldap_set_option( ld, LDAP_OPT_REFERRALS, 0 );

I need to be able to login with correct user name and when user tries to enter wrong user name, ldap should say so.

I have referred to following links and their related links to get to this conclusion:

LDAP - How to check a username/password combination?

How to do password authentication for a user using LDAP?

1

1 Answers

1
votes

Digest-MD5 auth is more complicated than just sending a bind DN and password. You'll need to use ldap_sasl_interactive_bind_s and provide a callback so the SASL library can combine your credentials with the server-provided nonce.

This code (adapted from this blog post) works for me against an Active Directory server:

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

typedef struct
{
  char *username;
  char *password;
} my_authdata;

int my_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *in)
{
  my_authdata *auth = (my_authdata *)defaults;
  sasl_interact_t *interact = (sasl_interact_t *)in;
  if(ld == NULL) return LDAP_PARAM_ERROR;

  while(interact->id != SASL_CB_LIST_END)
  {
    char *dflt = (char *)interact->defresult;

    switch(interact->id)
    {
      case SASL_CB_GETREALM:
        dflt = NULL;
        break;
      case SASL_CB_USER:
      case SASL_CB_AUTHNAME:
        dflt = auth->username;
        break;
      case SASL_CB_PASS:
        dflt = auth->password;
        break;
      default:
        printf("my_sasl_interact asked for unknown %ld\n",interact->id);
    }

    interact->result = (dflt && *dflt) ? dflt : (char *)"";
    interact->len = strlen((char *)interact->result);
    interact++;
  }

  return LDAP_SUCCESS;
}

int main(int argc, char *argv[])
{
  if(argc < 3)
  {
    fprintf(stderr, "Usage: dmd5-bind [username] [password]\n");
    return -1;
  }

  int rc;
  LDAP *ld = NULL;

  static my_authdata auth;
  auth.username = argv[1];
  auth.password = argv[2];

  char *sasl_mech = ber_strdup("DIGEST-MD5");
  char *ldapuri = ber_strdup("ldap://your.server.name.here");

  int protocol = LDAP_VERSION3;
  unsigned sasl_flags = LDAP_SASL_QUIET;
  char *binddn = NULL;

  rc = ldap_initialize(&ld, ldapuri);
  if(rc != LDAP_SUCCESS)
  {
    fprintf(stderr, "ldap_initialize: %s\n", ldap_err2string(rc));
    return rc;
  }


  if(ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &protocol) != LDAP_OPT_SUCCESS)
  {
    fprintf(stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", protocol);
    return -1;
  }

  rc = ldap_sasl_interactive_bind_s(ld,
                                    binddn,
                                    sasl_mech,
                                    NULL,
                                    NULL,
                                    sasl_flags,
                                    my_sasl_interact,
                                    &auth);

  if(rc != LDAP_SUCCESS)
  {
    ldap_perror(ld, "ldap_sasl_interactive_bind_s");
    ldap_unbind_ext_s(ld, NULL, NULL);
    return rc;
  }

  fprintf(stdout, "Authentication succeeded\n");

  rc = ldap_unbind_ext_s(ld, NULL, NULL);
  sasl_done();
  sasl_client_init(NULL);

  return rc;
}