{"action":"created","issue":{"url":"https://api.github.com/repos/curl/curl/issues/2452","repository_url":"https://api.github.com/repos/curl/curl","labels_url":"https://api.github.com/repos/curl/curl/issues/2452/labels{/name}","comments_url":"https://api.github.com/repos/curl/curl/issues/2452/comments","events_url":"https://api.github.com/repos/curl/curl/issues/2452/events","html_url":"https://github.com/curl/curl/pull/2452","id":310827819,"number":2452,"title":"optimize negotiate and ntlm auth in first and reused connections.","user":{"login":"DarovskikhAndrei","id":10544047,"avatar_url":"https://avatars3.githubusercontent.com/u/10544047?v=4","gravatar_id":"","url":"https://api.github.com/users/DarovskikhAndrei","html_url":"https://github.com/DarovskikhAndrei","followers_url":"https://api.github.com/users/DarovskikhAndrei/followers","following_url":"https://api.github.com/users/DarovskikhAndrei/following{/other_user}","gists_url":"https://api.github.com/users/DarovskikhAndrei/gists{/gist_id}","starred_url":"https://api.github.com/users/DarovskikhAndrei/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DarovskikhAndrei/subscriptions","organizations_url":"https://api.github.com/users/DarovskikhAndrei/orgs","repos_url":"https://api.github.com/users/DarovskikhAndrei/repos","events_url":"https://api.github.com/users/DarovskikhAndrei/events{/privacy}","received_events_url":"https://api.github.com/users/DarovskikhAndrei/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":6,"created_at":"2018-04-03T13:03:49Z","updated_at":"2018-04-13T08:39:28Z","closed_at":null,"author_association":"NONE","pull_request":{"url":"https://api.github.com/repos/curl/curl/pulls/2452","html_url":"https://github.com/curl/curl/pull/2452","diff_url":"https://github.com/curl/curl/pull/2452.diff","patch_url":"https://github.com/curl/curl/pull/2452.patch"},"body":"now curl send 4 requests for new connection with negotiate auth (kerberos):\r\nrequest 1: no authenticate headers\r\nresponse: authenticate headers\r\nrequest 2: no authecticate headers\r\nresponse: authenticate headers\r\nrequest 3: authenticate headers with first token\r\nresponse: authenticate headers with token\r\nrequest 4: authenticate headers with second token\r\nresponse: authenticate headers with token, status 200 and response body\r\n\r\nthis PR remove second request without auth headers and requests will be like this:\r\nrequest 1: no authecticate headers\r\nresponse: authenticate headers\r\nrequest 2: authenticate headers with first token\r\nresponse: authenticate headers with token\r\nrequest 3: authenticate headers with second token\r\nresponse: authenticate headers with token, status 200 and response body\r\n\r\nFor reused connections forced using last selected authentication protocol:\r\nrequest 1: authenticate headers with first token\r\nresponse: authenticate headers with token\r\nrequest 2: authenticate headers with second token\r\nresponse: authenticate headers with token, status 200 and response body\r\n"},"comment":{"url":"https://api.github.com/repos/curl/curl/issues/comments/381066656","html_url":"https://github.com/curl/curl/pull/2452#issuecomment-381066656","issue_url":"https://api.github.com/repos/curl/curl/issues/2452","id":381066656,"user":{"login":"dhoelzl","id":25737508,"avatar_url":"https://avatars2.githubusercontent.com/u/25737508?v=4","gravatar_id":"","url":"https://api.github.com/users/dhoelzl","html_url":"https://github.com/dhoelzl","followers_url":"https://api.github.com/users/dhoelzl/followers","following_url":"https://api.github.com/users/dhoelzl/following{/other_user}","gists_url":"https://api.github.com/users/dhoelzl/gists{/gist_id}","starred_url":"https://api.github.com/users/dhoelzl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dhoelzl/subscriptions","organizations_url":"https://api.github.com/users/dhoelzl/orgs","repos_url":"https://api.github.com/users/dhoelzl/repos","events_url":"https://api.github.com/users/dhoelzl/events{/privacy}","received_events_url":"https://api.github.com/users/dhoelzl/received_events","type":"User","site_admin":false},"created_at":"2018-04-13T08:39:28Z","updated_at":"2018-04-13T08:39:28Z","author_association":"NONE","body":"Please have a look at my last updates to #1975 \r\n\r\nI had to consider following issues:\r\n * `Persistent-Auth` header (IIS-Configuration: authPersistNonNTLM): Some servers send this header to indicate if the authentication needs to be re-issued on every request (and the security context needs to be reset), or if the authentication can be re-used on a connection for multiple requests and no more challenge requests are required. If the server does not send this header, it needs to be detected if to persist authentication or not. I did this by checking if there was a challenging with multiple requests on the connection. If not, the authentication is not persisted. I am not sure if this is correct, but I did not find a way to ask the security context for that or if this can be detected in an other way. If not detecting this, one extra (unauthenticated) request would be sent to the server on every request which theoretically \"works\" but in practice the server rejected any further authentication attempt on a connection where authentication failed in a request before.\r\n* The `\"100 continue\"` mechanism seems not to work while the challenge requests take place. So I had to disable it in this case by setting an emtpy \"Expect:\"-header (and setting cURL to keep sending also in case of errors with CURLOPT_KEEP_SENDING_ON_ERROR to send the complete request body to the server even if the server already answered with 401/407 while negotiation). This \"fix\" is not part of my pull request as cURL has to/can be configured to do so. I got it only working to completely transfer the whole request with body included to the server on every negotiation challenge request. Otherwise the requests hang up as the server seems to wait for the request body even if the \"Expect: 100-continue\" header is present). After a successful authentication, the \"expect 100\" mechanism works as expected.\r\n* `GSS_S_CONTINUE_NEEDED/SEC_I_CONTINUE_NEEDED` does not reliable indicate that the authentication is not already accepted by the server. I had cases (e.g. connecting to a negotiate-enabled IIS via localhost) where the API returned SEC_I_CONTINUE_NEEDED on the response, but the server already accepted the authentication and processed the request. In this case the request body must already be sent to the server.\r\n\r\nOne more issue I ran into: If the call to `InitializeSecurityContext `fails for any reason (e.g. the network became unavailable while this call and it could not contact the principal server), cURL returns CURLE_OUT_OF_MEMORY (see https://github.com/curl/curl/blob/master/lib/vauth/spnego_sspi.c#L230)\r\n\r\nRegards,\r\nDominik"}}
{"actor":{"display_login":"dhoelzl"}}