From 5f97178a88a3c1e93f13ae531db4a9b2894fbb70 Mon Sep 17 00:00:00 2001 From: Kevin Wasserman Date: Mon, 1 Aug 2011 14:16:09 -0400 Subject: [PATCH] Windows port and Firefox 3.6 addon fixes: malloc -> PR_Malloc In 3.6, session state is deleted by firefox when ChallengeReceived() sets identityInvalid true, so allocate session state as necessary in GenerateCredentials() instead of ChallengeReceived(). Also, use continuation state instead of session state until authentication completes. If we don't do this, firefox will sometimes restart the authentication in the middle of the negotiation with a NULL username and password. Use a smart pointer for session state to avoid leaking in error cases. --- nsHttpMoonshot.cpp | 59 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/nsHttpMoonshot.cpp b/nsHttpMoonshot.cpp index 0f709ab..a09a0ce 100644 --- a/nsHttpMoonshot.cpp +++ b/nsHttpMoonshot.cpp @@ -35,6 +35,7 @@ #define FORCE_PR_LOG 1 #include +#include "nsAutoRef.h" #include "nsCOMPtr.h" #include "nsIHttpChannel.h" #include "nsIServiceManager.h" @@ -69,6 +70,14 @@ #endif #endif +NS_SPECIALIZE_TEMPLATE +class nsAutoRefTraits : public nsPointerRefTraits +{ +public: + static void Release(nsMoonshotSessionState *ptr) { ptr->Release(); } + static void AddRef(nsMoonshotSessionState *ptr) { ptr->AddRef(); } +}; + static gss_OID_desc gss_krb5_mech_oid_desc = {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}; @@ -164,25 +173,10 @@ nsHttpMoonshot::ChallengeReceived(nsIHttpChannel *httpChannel, PRBool *identityInvalid) { nsMoonshotSessionState *session = (nsMoonshotSessionState *) *sessionState; - - // - // Use this opportunity to instantiate the session object - // that gets used later when we generate the credentials. - // - if (!session) { - session = new nsMoonshotSessionState(); - if (!session) - return(NS_ERROR_OUT_OF_MEMORY); - NS_ADDREF(*sessionState = session); - LOG(("nsHttpMoonshot::A new session context established\n")); - } else { - LOG(("nsHttpMoonshot::Still using context from previous request\n")); - } - - LOG(("nsHttpMoonshot:: gss_state = %d\n", session->gss_state)); - + if (session==NULL) + session = (nsMoonshotSessionState *) *continuationState; *identityInvalid = - (session->gss_state == GSS_CTX_EMPTY) ? PR_TRUE : PR_FALSE; + ((session==NULL) || (session->gss_state == GSS_CTX_EMPTY)) ? PR_TRUE : PR_FALSE; return NS_OK; } @@ -282,8 +276,9 @@ nsHttpMoonshot::GenerateCredentials_1_9_2(nsIHttpChannel *httpChannel, gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; gss_buffer_t in_token_ptr = GSS_C_NO_BUFFER; gss_name_t server; - nsMoonshotSessionState *session = (nsMoonshotSessionState *) *sessionState; - + nsCountedRef session(static_cast(*sessionState)); + if (!session) + session = static_cast(*continuationState); nsCOMPtr uri; nsresult rv; @@ -342,6 +337,16 @@ nsHttpMoonshot::GenerateCredentials_1_9_2(nsIHttpChannel *httpChannel, return NS_ERROR_FAILURE; } + // Create session state if none added yet. + if (!session) { + session = new nsMoonshotSessionState(); + if (!session) + return(NS_ERROR_OUT_OF_MEMORY); + LOG(("nsHttpMoonshot::A new session context established\n")); + } else { + LOG(("nsHttpMoonshot::Still using context from previous request\n")); + } + // // If the "Negotiate:" header had some data associated with it, // that data should be used as the input to this call. This may @@ -487,6 +492,13 @@ nsHttpMoonshot::GenerateCredentials_1_9_2(nsIHttpChannel *httpChannel, // TEST // session->Reset(); session->gss_state = GSS_CTX_ESTABLISHED; + if (*sessionState != session) + { + NS_ADDREF(*sessionState = session); + // clean up continuation state + if (*continuationState) + NS_RELEASE(*continuationState); + } LOG(("GSS Auth done")); } else if (major_status == GSS_S_CONTINUE_NEEDED) { // @@ -499,6 +511,11 @@ nsHttpMoonshot::GenerateCredentials_1_9_2(nsIHttpChannel *httpChannel, // // TEST session->gss_state = GSS_CTX_IN_PROGRESS; + if (*continuationState != session) + { + // Assert continuationState==NULL + NS_ADDREF(*continuationState = session); + } LOG(("GSS Auth continuing")); } @@ -531,7 +548,7 @@ nsHttpMoonshot::GenerateCredentials_1_9_2(nsIHttpChannel *httpChannel, LOG(("Sending a token of length %d\n", output_token.length)); // allocate a buffer sizeof("Negotiate" + " " + b64output_token + "\0") - *creds = (char *) malloc (strlen(NEGOTIATE_AUTH) + 1 + strlen(encoded_token) + 1); + *creds = (char *) PR_Malloc (strlen(NEGOTIATE_AUTH) + 1 + strlen(encoded_token) + 1); if (!(*creds)) { PR_Free(encoded_token); (void) gss_release_buffer(&minor_status, &output_token); -- 2.1.4