diff --git a/lib/http.c b/lib/http.c
index d65acac..3169cf1 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -560,10 +560,6 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
   }
 
   if(pickhost || pickproxy) {
-    /* In case this is GSS auth, the newurl field is already allocated so
-       we must make sure to free it before allocating a new one. As figured
-       out in bug #2284386 */
-    Curl_safefree(data->req.newurl);
     data->req.newurl = strdup(data->change.url); /* clone URL */
     if(!data->req.newurl)
       return CURLE_OUT_OF_MEMORY;
@@ -630,8 +626,7 @@ output_auth_headers(struct connectdata *conn,
 
 #ifdef USE_SPNEGO
   negdata->state = GSS_AUTHNONE;
-  if((authstatus->picked == CURLAUTH_NEGOTIATE) &&
-     negdata->context && !GSS_ERROR(negdata->status)) {
+  if(authstatus->picked == CURLAUTH_NEGOTIATE) {
     auth="Negotiate";
     result = Curl_output_negotiate(conn, proxy);
     if(result)
@@ -841,10 +836,6 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
         if(negdata->state == GSS_AUTHSENT || negdata->state == GSS_AUTHNONE) {
           CURLcode result = Curl_input_negotiate(conn, proxy, auth);
           if(!result) {
-            DEBUGASSERT(!data->req.newurl);
-            data->req.newurl = strdup(data->change.url);
-            if(!data->req.newurl)
-              return CURLE_OUT_OF_MEMORY;
             data->state.authproblem = FALSE;
             /* we received a GSS auth token and we dealt with it fine */
             negdata->state = GSS_AUTHRECV;
diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c
index ecdd4e1..1dc3c6a 100644
--- a/lib/http_negotiate.c
+++ b/lib/http_negotiate.c
@@ -46,11 +46,8 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
   struct SessionHandle *data = conn->data;
   struct negotiatedata *neg_ctx = proxy?&data->state.proxyneg:
     &data->state.negotiate;
-  OM_uint32 major_status, minor_status, discard_st;
-  gss_buffer_desc spn_token = GSS_C_EMPTY_BUFFER;
   gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
-  gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
-  size_t len;
+  size_t len = 0;
   size_t rawlen = 0;
   CURLcode result;
 
@@ -62,6 +59,49 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     return CURLE_LOGIN_DENIED;
   }
 
+  header += strlen("Negotiate");
+  while(*header && ISSPACE(*header))
+    header++;
+
+  len = strlen(header);
+  if(len > 0) {
+    result = Curl_base64_decode(header, (unsigned char **)&input_token.value,
+                                &rawlen);
+    if(result)
+      return result;
+
+    if(!rawlen) {
+      infof(data, "Negotiate handshake failure (empty challenge message)\n");
+
+      return CURLE_BAD_CONTENT_ENCODING;
+    }
+
+    input_token.length = rawlen;
+
+    DEBUGASSERT(input_token.value != NULL);
+  }
+
+  neg_ctx->input_token = input_token;
+
+  return CURLE_OK;
+}
+
+CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
+{
+  struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
+    &conn->data->state.negotiate;
+  OM_uint32 major_status, minor_status, discard_st;
+  gss_buffer_desc spn_token = GSS_C_EMPTY_BUFFER;
+  gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
+  gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
+  char *encoded = NULL;
+  size_t len = 0;
+  char *userp;
+  CURLcode result;
+
+  if(neg_ctx->context && neg_ctx->input_token.value)
+    input_token = neg_ctx->input_token;
+
   if(!neg_ctx->server_name) {
     /* Generate our SPN */
     char *spn = Curl_sasl_build_gssapi_spn("HTTP", proxy ? conn->proxy.name :
@@ -71,14 +111,16 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
 
     /* Populate the SPN structure */
     spn_token.value = spn;
-    spn_token.length = strlen(spn);
+    spn_token.length = strlen(spn) +1;
 
     /* Import the SPN */
-    major_status = gss_import_name(&minor_status, &spn_token,
+    major_status = gss_import_name(&minor_status,
+                                   &spn_token,
                                    GSS_C_NT_HOSTBASED_SERVICE,
                                    &neg_ctx->server_name);
     if(GSS_ERROR(major_status)) {
-      Curl_gss_log_error(data, minor_status, "gss_import_name() failed: ");
+      Curl_gss_log_error(conn->data, minor_status,
+                         "gss_import_name() failed: ");
 
       Curl_safefree(spn);
 
@@ -88,29 +130,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
       Curl_safefree(spn);
   }
 
-  header += strlen("Negotiate");
-  while(*header && ISSPACE(*header))
-    header++;
-
-  len = strlen(header);
-  if(len > 0) {
-    result = Curl_base64_decode(header, (unsigned char **)&input_token.value,
-                                &rawlen);
-    if(result)
-      return result;
-
-    if(!rawlen) {
-      infof(data, "Negotiate handshake failure (empty challenge message)\n");
-
-      return CURLE_BAD_CONTENT_ENCODING;
-    }
-
-    input_token.length = rawlen;
-
-    DEBUGASSERT(input_token.value != NULL);
-  }
-
-  major_status = Curl_gss_init_sec_context(data,
+  major_status = Curl_gss_init_sec_context(conn->data,
                                            &minor_status,
                                            &neg_ctx->context,
                                            neg_ctx->server_name,
@@ -121,6 +141,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
                                            TRUE,
                                            NULL);
   Curl_safefree(input_token.value);
+  input_token.value = NULL;
 
   neg_ctx->status = major_status;
   if(GSS_ERROR(major_status)) {
@@ -137,37 +158,14 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     return CURLE_OUT_OF_MEMORY;
   }
 
-  neg_ctx->output_token = output_token;
-
-  return CURLE_OK;
-}
-
-CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
-{
-  struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
-    &conn->data->state.negotiate;
-  char *encoded = NULL;
-  size_t len = 0;
-  char *userp;
-  CURLcode result;
-  OM_uint32 discard_st;
-
   result = Curl_base64_encode(conn->data,
-                              neg_ctx->output_token.value,
-                              neg_ctx->output_token.length,
+                              output_token.value,
+                              output_token.length,
                               &encoded, &len);
-  if(result) {
-    gss_release_buffer(&discard_st, &neg_ctx->output_token);
-    neg_ctx->output_token.value = NULL;
-    neg_ctx->output_token.length = 0;
-    return result;
-  }
 
-  if(!encoded || !len) {
-    gss_release_buffer(&discard_st, &neg_ctx->output_token);
-    neg_ctx->output_token.value = NULL;
-    neg_ctx->output_token.length = 0;
-    return CURLE_REMOTE_ACCESS_DENIED;
+  if(result || !encoded || !len) {
+    gss_release_buffer(&discard_st, &output_token);
+    return result ? result : CURLE_REMOTE_ACCESS_DENIED;
   }
 
   userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
@@ -181,6 +179,8 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
     conn->allocptr.userpwd = userp;
   }
 
+  if(output_token.value)
+      gss_release_buffer(&discard_st, &output_token);
   Curl_safefree(encoded);
 
   return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
@@ -192,9 +192,6 @@ static void cleanup(struct negotiatedata *neg_ctx)
   if(neg_ctx->context != GSS_C_NO_CONTEXT)
     gss_delete_sec_context(&minor_status, &neg_ctx->context, GSS_C_NO_BUFFER);
 
-  if(neg_ctx->output_token.value)
-    gss_release_buffer(&minor_status, &neg_ctx->output_token);
-
   if(neg_ctx->server_name != GSS_C_NO_NAME)
     gss_release_name(&minor_status, &neg_ctx->server_name);
 
diff --git a/lib/urldata.h b/lib/urldata.h
index 50a745f..4289889 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -480,7 +480,7 @@ struct negotiatedata {
   OM_uint32 status;
   gss_ctx_id_t context;
   gss_name_t server_name;
-  gss_buffer_desc output_token;
+  gss_buffer_desc input_token;
 #else
 #ifdef USE_WINDOWS_SSPI
   DWORD status;
