Skip to content

Curl never completes SPNEGO security context over HTTP #5235

Description

@michael-o

While working on few issues in brandond/requests-negotiate-sspi which I haven't reported yet, I wanted to reproduce them with curl too and noticed that I can't because there is a severe bug.

I expect curl to signal me similar:

pywintypes.error: (-2146893048, 'InitializeSecurityContext', 'Das Token, das der Funktion übergeben wurde, ist ungültig.')

Which is bascially SEC_E_INVALID_TOKEN. I don't know the reason for the error yet, but this is not important for now.

Next steps: Downloaded release tarball 7.69.1 and compiled on Windows 10 with MinGW.org GCC Build-20200227-1) 9.2.0 by passing: mingw32-make mingw32-winssl-sspi.
FWIW: The backend is running Java 8 with JGSS.

Now run the curl command:

src\curl -s --negotiate -u : https://deblndw024v.ad001.siemens.net:8444/manager/html
*   Trying 147.54.65.24:8444...
* Connected to deblndw024v.ad001.siemens.net (147.54.65.24) port 8444 (#0)
* Server auth using Negotiate with user ''
> GET /manager/html HTTP/1.1
> Host: deblndw024v.ad001.siemens.net:8444
> Authorization: Negotiate YIITBwYGKwYBBQUCoIIS...fAO4Rgg
> User-Agent: curl/7.69.1
> Accept: */*
>
* schannel: failed to decrypt data, need more data
* schannel: failed to decrypt data, need more data
* schannel: failed to decrypt data, need more data
* Mark bundle as not supporting multiuse
< HTTP/1.1 200
< Cache-Control: private
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< WWW-Authenticate: Negotiate oYHzMIHwoAMKA..oGTI44w+aL6
< Content-Type: text/html;charset=utf-8
< Transfer-Encoding: chunked
< Date: Tue, 14 Apr 2020 16:21:30 GMT
<

Why doesn't this fail? So I printed right after

nego->status = s_pSecFn->InitializeSecurityContext(nego->credentials,
chlg ? nego->context :
NULL,
nego->spn,
ISC_REQ_CONFIDENTIALITY,
0, SECURITY_NATIVE_DREP,
chlg ? &chlg_desc : NULL,
0, nego->context,
&resp_desc, &attrs,
&expiry);
the context status, and see "Context status: 0x90312" (SEC_I_CONTINUE_NEEDED), but I never see the continuation.

The bug is right here:

curl/lib/http.c

Lines 4061 to 4064 in a6f7b2f

else if((checkprefix("WWW-Authenticate:", k->p) &&
(401 == k->httpcode)) ||
(checkprefix("Proxy-authenticate:", k->p) &&
(407 == k->httpcode))) {

libcurl assumes that *-Authenticate can only occur on 401/407. After removing the status code check, I see:

*   Trying 147.54.65.24:8444...
* Connected to deblndw024v.ad001.siemens.net (147.54.65.24) port 8444 (#0)
Context status: 0x90312
* Server auth using Negotiate with user ''
> GET /manager/html HTTP/1.1
> Host: deblndw024v.ad001.siemens.net:8444
> Authorization: Negotiate YIITBwYGKwYBBQUC...r/8C+h9Y3Fht1
> User-Agent: curl/7.69.1
> Accept: */*
>
* schannel: failed to decrypt data, need more data
* schannel: failed to decrypt data, need more data
* schannel: failed to decrypt data, need more data
* Mark bundle as not supporting multiuse
< HTTP/1.1 200
< Cache-Control: private
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
Context status: 0x80090308
* InitializeSecurityContext failed: SEC_E_INVALID_TOKEN (0x80090308) - Das Token, das der Funktion übergeben wurde, ist ungültig.
< WWW-Authenticate: Negotiate oYHzMIHwo...fKT+CMJ
< Content-Type: text/html;charset=utf-8
< Transfer-Encoding: chunked
< Date: Tue, 14 Apr 2020 16:26:52 GMT
<
{ [8367 bytes data]
* schannel: failed to decrypt data, need more data
{ [9000 bytes data]
* schannel: failed to decrypt data, need more data
* schannel: failed to decrypt data, need more data
{ [8775 bytes data]
* Connection #0 to host deblndw024v.ad001.siemens.net left intact

This one matches better:

    else if((checkprefix("WWW-Authenticate:", k->p) &&
             (conn->http_negotiate_state == GSS_AUTHSENT)) ||
            (checkprefix("Proxy-authenticate:", k->p) &&
             (conn->proxy_negotiate_state == GSS_AUTHSENT))) {

Unfortuntely, this does not work on Un*x, there must be some other quirk in the code as well. Doing header prefix only, I get from MIT Kerberos:

$ LD_LIBRARY_PATH=/tmp/curl/lib /tmp/curl/bin/curl --negotiate -u : https://deblndw024v.ad001.siemens.net:8444/manager/html -o /dev/null   -sq -k
Context status: 0x1
Context status: 0x0

But still authentication errors do not bubble up the chain so I never know that the authentication has failed for a severe reason.

This looks like a severe bug to me. What now?

PS: I am quite certain that the completion does not happen with MIT Kerberos too.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions