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.
#define FORCE_PR_LOG 1
#include <stdlib.h>
#define FORCE_PR_LOG 1
#include <stdlib.h>
#include "nsCOMPtr.h"
#include "nsIHttpChannel.h"
#include "nsIServiceManager.h"
#include "nsCOMPtr.h"
#include "nsIHttpChannel.h"
#include "nsIServiceManager.h"
+NS_SPECIALIZE_TEMPLATE
+class nsAutoRefTraits<nsMoonshotSessionState> : public nsPointerRefTraits<nsMoonshotSessionState>
+{
+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"};
static gss_OID_desc gss_krb5_mech_oid_desc =
{9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"};
PRBool *identityInvalid)
{
nsMoonshotSessionState *session = (nsMoonshotSessionState *) *sessionState;
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;
- (session->gss_state == GSS_CTX_EMPTY) ? PR_TRUE : PR_FALSE;
+ ((session==NULL) || (session->gss_state == GSS_CTX_EMPTY)) ? PR_TRUE : PR_FALSE;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
gss_buffer_t in_token_ptr = GSS_C_NO_BUFFER;
gss_name_t server;
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<nsMoonshotSessionState> session(static_cast<nsMoonshotSessionState *>(*sessionState));
+ if (!session)
+ session = static_cast<nsMoonshotSessionState *>(*continuationState);
nsCOMPtr<nsIURI> uri;
nsresult rv;
nsCOMPtr<nsIURI> uri;
nsresult rv;
return NS_ERROR_FAILURE;
}
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
//
// If the "Negotiate:" header had some data associated with it,
// that data should be used as the input to this call. This may
// TEST
// session->Reset();
session->gss_state = GSS_CTX_ESTABLISHED;
// 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) {
//
LOG(("GSS Auth done"));
} else if (major_status == GSS_S_CONTINUE_NEEDED) {
//
//
// TEST
session->gss_state = GSS_CTX_IN_PROGRESS;
//
// TEST
session->gss_state = GSS_CTX_IN_PROGRESS;
+ if (*continuationState != session)
+ {
+ // Assert continuationState==NULL
+ NS_ADDREF(*continuationState = session);
+ }
LOG(("GSS Auth continuing"));
}
LOG(("GSS Auth continuing"));
}
LOG(("Sending a token of length %d\n", output_token.length));
// allocate a buffer sizeof("Negotiate" + " " + b64output_token + "\0")
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);
if (!(*creds)) {
PR_Free(encoded_token);
(void) gss_release_buffer(&minor_status, &output_token);