libmicrohttpd
[Top][All Lists]
Advanced

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

Re: [libmicrohttpd] Upgrade to digest authentication


From: Christian Grothoff
Subject: Re: [libmicrohttpd] Upgrade to digest authentication
Date: Sun, 8 Nov 2020 18:20:51 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.12.0

On 11/7/20 2: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().

Well, the key question is why the nonce keeps changing. There are two
reasons I can see:

1) bug on your end (like change in inputs: realm, random data source)
2) time passing (nonces have a timestamp). For the timeout, you are
responsible for giving a sane lifetime (in seconds).

> 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.

Well, if you immediately queue a reply, then the access handler is only
called once per request, so it would be normal for the next request to
get a non-NULL value.

Use MHD_OPTION_NOTIFY_COMPLETED to register a function that is called
when a request is 'finished', and MHD_OPTION_URI_LOG_CALLBACK to
register a function that is called when a new request starts. That way
you can maybe more easily see what is going on.

Happy hacking!

Christian

> 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");
>>  }
>> }
>>



reply via email to

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