libmicrohttpd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [libmicrohttpd] Upgrade to digest authentication


From: DJM-Avalesta
Subject: Re: [libmicrohttpd] Upgrade to digest authentication
Date: Wed, 11 Nov 2020 14:02:36 +0000
User-agent: Roundcube Webmail/1.4-rc2

Hi,

I spoke too soon, I still have issues authenticating with certain clients.

The attached wireshark shows, at the very end, it fails to authenticate an HTTP GET of an image file (/mjpg/image.cgi) when the username, nonce and realm all seem to be correct.

It actually fails in digestauth.c with the message "Authentication failed, arguments do no match".

Any ideas?

Regards

David


On 2020-11-09 2:51 pm, DJM-Avalesta wrote:

Many thanks, Christian,

As you say, I had the rnd array allocated on the stack. I moved it to global storage and voila, it works. I should have read the manual more closely.

On the con_cls issue, I guess I'm completing each request so the handler never gets called with a non-zero value.

Best regards

David


On 2020-11-08 5:14 pm, Christian Grothoff wrote:

Hi David,

Looking at the pcap, it seems the 'nonce' of the server keeps changing,
which it must not. I don't know what you are doing, maybe you called
MHD_OPTION_DIGEST_AUTH_RANDOM with a pointer to a location in RAM that
keeps changing.

Anyway, to debug this, I would begin by looking
at the digestauth.c::calculate_nonce() function. Check in particular if
the arguments 'rnd'/rnd_size, or 'uri' or 'realm' change between calls,
they should not (at least not for the same page!).

Again, without reference code from you exhibiting the problematic
behavior, diagnosis help is difficult...

Happy hacking!

-Christian

On 2020-11-07 1:24 pm, DJM-Avalesta wrote:

Hi,

I desperately need to solve issue this for a Client, I attach a wireshark capture of the problem but basically, I have two problems:-

1. Around 50% of the calls to MHD_digest_auth_check() fail returning INVALID_NONCE. This seems to be random, sometimes it passes and sometimes not. Some clients (eg ONVIF Conformance Tool) don't seem to re-send the response with a different nonce when they receive a MHD_queue_auth_fail_response().

2. The *con_cls parameter to the access handler is always null, even though I change it when I get an authentication pass. This means that I'm authenticating every call into the access handler which does not seem right.

I must be doing something wrong as I'm sure this has been tested many times over.

Best regards

David


On 2020-10-31 5:36 pm, Christian Grothoff wrote:

Hi David,

I don't see anything _obviously_ wrong with the snippet you provided. I
would suggest you to use wireshark to log a transcript of the
interaction and/or to provide a stand-alone minimal C implementation
based on your code for testing by others.

Happy hacking!

Christian
 

On 2020-10-29 4:10 pm, DJM-Avalesta wrote:

Hi,

I'm trying to update my 8 year old code to use digest authentication where previously it only supported basic.

I'm trying to use *con_cls (*ptr in my code) to determine when to authenticate but it's not working, *con_cls always seems to be null, even after I've set it, so it's authenticating every time.

I mostly get MHD_digest_auth_check() failures returning INVALID_NONCE and the Client never stops asking for credentials even when the authentication passes, which it does occasionally.

I'm missing something crucial but I can't see it.

The authentication part of my access_handler is shown below

Many thanks

David


static int aptr;
if (bDigestAuth)
{
 printf("URL:%s, con_cls:%p\r\n", url, *ptr);
 //HACK to see if digest authentication works and allows ONVIF snapshorUri test to pass
 //Only works for Admin-Admin
 if (&aptr != *ptr)
 {
  /* Only authenticate on first call of session*/
  char *username;
  const char *password = "Admin";

  g_CameraData->GetRealmName(g_szRealm, sizeof(g_szRealm));

  username = MHD_digest_auth_get_username(connection);
  if (username == NULL)
  {
    response = MHD_create_response_from_data (strlen (NOTAUTH_RESPONSE),
    (void *) NOTAUTH_RESPONSE,
    MHD_NO, MHD_NO);
    ret = MHD_queue_auth_fail_response(connection, g_szRealm,
      OPAQUE,
      response,
      MHD_NO);
    MHD_destroy_response(response);
    pthread_mutex_unlock (&m_AuthMutex); //unlock after authorization
    // printf("Failed digest auth, no username\r\n");
    return ret;
  }
  printf("Applying digest auth to user: %s, realm:%s, con_cls:%p\r\n", username, g_szRealm, *ptr);
  *ptr = &aptr; //set this for session
  ret = MHD_digest_auth_check(connection, g_szRealm,
    username,
    password,
    300);
  printf("Checking digest auth for username: %s, password: %s, realm:%s\r\n", username, password, g_szRealm);
  free(username);
  if ( (ret == MHD_INVALID_NONCE) ||
    (ret == MHD_NO) )
  {
    printf("Failed digest auth, invalid nonce, ret:%d\r\n", ret);
    response = MHD_create_response_from_data (strlen (NOTAUTH_RESPONSE),
      (void *) NOTAUTH_RESPONSE,
      MHD_NO, MHD_NO);
    if (NULL == response)
      return MHD_NO;
    ret = MHD_queue_auth_fail_response(connection, g_szRealm,
      OPAQUE,
      response,
      (ret == MHD_INVALID_NONCE) ? MHD_YES : MHD_NO);
    MHD_destroy_response(response);
    pthread_mutex_unlock (&m_AuthMutex); //unlock after authorization
    return ret;
  }
  //PASSED
  printf("PASSED digest auth\r\n");
 }
 else
 {
   printf("No digest auth required\r\n");
 }
}

Attachment: ODM-SnapshotURI-fail-01.pcapng
Description: Binary data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]