I did some changes around in couple of files, so that negotiate protocol can 
deal better with kerberos or ntlm tokens generated through sspi calls. It seems 
to be working, but it's a hack fix, and may be some one can help me to make it 
a proper fix. The proper fix should be that we should take account of what 
InitializeSecurityContext function returns in the http_negotiate_sspi.c file. 
If it returns SEC_I_COMPLETE_AND_CONTINUE  or SEC_I_CONTINUE_NEEDED  , then we 
should call again InitializeSecurityContext after getting the next token from 
the server (both in ntlm and kerbeors token, although in kerberos token server 
will return 200 instead of 401). But if in kerberos we call 
again InitializeSecurityContext with server returned token, then there will be 
no more token generated by this call and output will be empty as the cycle is 
completed and it will return SEC_E_OK. But libcurl currently tries to 
call Curl_output_negotiate and try to send
 empty token again........that's why i did it in otherway... (comparing ntlm 
token....technique). Anyhow if someone have good idea how can i 
call Curl_input_negotiate to complete the cycle and not 
calling Curl_output_negotiate as the cycle is completed and auth is done???

@@ -538,7 +538,13 @@
     result = Curl_output_negotiate(conn, proxy);
     if(result)
       return result;
-    authstatus->done = TRUE;
+if ( negdata->status == SEC_I_CONTINUE_NEEDED ||
+negdata->status == SEC_I_COMPLETE_AND_CONTINUE ){
+authstatus->done = FALSE;
+}
+else
+authstatus->done = TRUE;
+
     negdata->state = GSS_AUTHSENT;
   }
   else
@@ -735,7 +741,7 @@
     *availp |= CURLAUTH_GSSNEGOTIATE;
     authp->avail |= CURLAUTH_GSSNEGOTIATE;
 
-    if(data->state.negotiate.state == GSS_AUTHSENT) {
+if(data->state.negotiate.state == GSS_AUTHSENT && 
data->state.negotiate.status!=SEC_I_CONTINUE_NEEDED && 
data->state.negotiate.status!=SEC_I_COMPLETE_AND_CONTINUE) {
       /* if we sent GSS authentication in the outgoing request and we get this
          back, we're in trouble */
       infof(data, "Authentication problem. Ignoring this.\n");
@@ -744,7 +750,7 @@
     else {
       neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start);
       if(neg == 0) {
-        DEBUGASSERT(!data->req.newurl);
+  DEBUGASSERT(!data->req.newurl);
         data->req.newurl = strdup(data->change.url);
         if(!data->req.newurl)
           return CURLE_OUT_OF_MEMORY;
@@ -3289,9 +3295,10 @@
         data->info.filetime = (long)k->timeofdoc;
     }
     else if((checkprefix("WWW-Authenticate:", k->p) &&
-             (401 == k->httpcode)) ||
+(401 == k->httpcode /*|| 
conn->data->state.negotiate.status==SEC_I_CONTINUE_NEEDED || 
conn->data->state.negotiate.status==SEC_I_COMPLETE_AND_CONTINUE*/)) ||
             (checkprefix("Proxy-authenticate:", k->p) &&
              (407 == k->httpcode))) {
+ //if we deal properly the return codes from negotiate context, then we can 
uncomment above.
       result = Curl_http_input_auth(conn, k->httpcode, k->p);
       if(result)
         return result;





@@ -91,7 +91,6 @@
   SecBuffer         in_sec_buff;
   ULONG             context_attributes;
   TimeStamp         lifetime;
-
   int ret;
   size_t len = 0, input_token_len = 0;
   bool gss = FALSE;
@@ -121,6 +120,13 @@
     neg_ctx->gss = gss;
   }
 
+   if(neg_ctx->output_token) {
+  free(neg_ctx->output_token);
+  neg_ctx->output_token = 0;
+  neg_ctx->output_token_length = 0;
+  neg_ctx->max_token_length = 0;
+  }
+
   if(neg_ctx->context && neg_ctx->status == SEC_E_OK) {
     /* We finished successfully our part of authentication, but server
      * rejected it (since we're again here). Exit with an error since we
@@ -196,7 +202,7 @@
   if (input_token) {
     in_buff_desc.ulVersion = 0;
     in_buff_desc.cBuffers  = 1;
-    in_buff_desc.pBuffers  = &out_sec_buff;
+    in_buff_desc.pBuffers  = &in_sec_buff;
 
     in_sec_buff.cbBuffer   = input_token_len;
     in_sec_buff.BufferType = SECBUFFER_TOKEN;
@@ -222,10 +228,33 @@
 
   if ( neg_ctx->status == SEC_I_COMPLETE_NEEDED ||
        neg_ctx->status == SEC_I_COMPLETE_AND_CONTINUE ) {
-    neg_ctx->status = s_pSecFn->CompleteAuthToken(neg_ctx->context,
+   neg_ctx->status = s_pSecFn->CompleteAuthToken(neg_ctx->context,
                                                   &out_buff_desc);
     if ( GSS_ERROR(neg_ctx->status) )
       return -1;
+
+  }
+  //else if(neg_ctx->status == SEC_E_OK && out_sec_buff.cbBuffer==0)
+  //{
+ //  //means we are done so no need to continue...
+  //Curl_cleanup_negotiate (conn->data);
+  //conn->data->state.authhost.done = TRUE;  
+  //}
+  if ( neg_ctx->status == SEC_I_CONTINUE_NEEDED ||
+       neg_ctx->status == SEC_I_COMPLETE_AND_CONTINUE ) {
+if(out_sec_buff.cbBuffer>0)
+{
+   if(!(checkprefix("NTLM",out_sec_buff.pvBuffer)))
+   {
+neg_ctx->status = SEC_E_OK;
+//means we are doing kerberos auth, so we can skipp next cycle.
+   }
+}
+   //   
+//   /////we need to continue...not end.
+  //  if ( GSS_ERROR(neg_ctx->status) )
+  //    return -1;
+
   }
 
   neg_ctx->output_token_length = out_sec_buff.cbBuffer;
@@ -258,30 +287,35 @@
   else
     conn->allocptr.userpwd = userp;
   free(encoded);
+  
   Curl_cleanup_negotiate (conn->data);
+
   return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
 }
 
 static void cleanup(struct negotiatedata *neg_ctx)
 {
-  if(neg_ctx->context) {
-    s_pSecFn->DeleteSecurityContext(neg_ctx->context);
-    free(neg_ctx->context);
-    neg_ctx->context = 0;
-  }
+if ( neg_ctx->status != SEC_I_CONTINUE_NEEDED &&
+neg_ctx->status != SEC_I_COMPLETE_AND_CONTINUE ) {
+//delete the context and handle if we are done.
+if(neg_ctx->context) {
+s_pSecFn->DeleteSecurityContext(neg_ctx->context);
+free(neg_ctx->context);
+neg_ctx->context = 0;
+}
 
-  if(neg_ctx->credentials) {
-    s_pSecFn->FreeCredentialsHandle(neg_ctx->credentials);
-    free(neg_ctx->credentials);
-    neg_ctx->credentials = 0;
-  }
-
-  if(neg_ctx->output_token) {
-    free(neg_ctx->output_token);
-    neg_ctx->output_token = 0;
-neg_ctx->output_token_length = 0;
-neg_ctx->max_token_length = 0;
-  }
+if(neg_ctx->credentials) {
+s_pSecFn->FreeCredentialsHandle(neg_ctx->credentials);
+free(neg_ctx->credentials);
+neg_ctx->credentials = 0;
+}
+if(neg_ctx->output_token) {
+free(neg_ctx->output_token);
+neg_ctx->output_token = 0;
+neg_ctx->output_token_length = 0;
+neg_ctx->max_token_length = 0;
+}
+}
 }
 
 void Curl_cleanup_negotiate(struct SessionHandle *data)
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Reply via email to