I spoke too soon, I still have issues authenticating with certainclients.
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, nonceand realm all seem to be correct.
It actually fails in digestauth.c with the message "Authenticationfailed, 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 DavidOn 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! -ChristianOn 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 Davidstatic 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"); } }
ODM-SnapshotURI-fail-01.pcapng
Description: Binary data