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