Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

curl with WinSSL does not enable HTTP2 against nghttp2.org #2591

Closed
fcharlie opened this issue May 21, 2018 · 13 comments
Closed

curl with WinSSL does not enable HTTP2 against nghttp2.org #2591

fcharlie opened this issue May 21, 2018 · 13 comments
Labels
HTTP/2 TLS Windows Windows-specific

Comments

@fcharlie
Copy link

I did this

I built CURL on the Windows 10 2018 April Update use WinSSL.
I used CURL to request an HTTP2 URL and found it didn't use HTTP2

CURL with OpenSSL is OK.

I expected the following

D:\Utilities\cURL>curl --http2 -I https://nghttp2.org/
HTTP/1.1 200 OK
Date: Mon, 21 May 2018 13:20:26 GMT
Content-Type: text/html
Last-Modified: Tue, 08 May 2018 13:53:22 GMT
Etag: "5af1abd2-19d8"
Accept-Ranges: bytes
Content-Length: 6616
X-Backend-Header-Rtt: 0.001094
Strict-Transport-Security: max-age=31536000
Server: nghttpx
Via: 2 nghttpx
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
x-content-type-options: nosniff

curl/libcurl version

[curl -V output]

curl 7.60.0 (Windows) libcurl/7.60.0 WinSSL zlib/1.2.11 nghttp2/1.32.0
Release-Date: 2018-05-16
Protocols: dict file ftp ftps gopher http https imap imaps ldap pop3 pop3s rtsp smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile SSPI Kerberos SPNEGO NTLM SSL libz HTTP2

Build Step

See: microsoft/WSL#3141 (comment)

curl https://curl.haxx.se/download/curl-7.60.0.tar.gz --output curl-7.60.0.tar.gz
tar -xvf curl-7.60.0.tar.gz
cd curl-7.60.0
mkdir build
cd build
cmake -GNinja -DBUILD_CURL_EXE=ON -DCMAKE_USE_WINSSL=ON -DUSE_NGHTTP2=ON -DCURL_STATICLIB=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF ..
ninja all

Nghttp2, zlib use vcpkg build.

Build Environment

C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.14.26428\ATLMFC\include
C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.14.26428\include
C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\include\um
C:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\ucrt
C:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\shared
C:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\um
C:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\winrt
C:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\cppwinrt
E:\vcpkg\installed\x64-windows-static\include
C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.14.26428\ATLMFC\lib\x64
C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.14.26428\lib\x64
C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\lib\um\x64
C:\Program Files (x86)\Windows Kits\10\lib\10.0.17134.0\ucrt\x64
C:\Program Files (x86)\Windows Kits\10\lib\10.0.17134.0\um\x64

E:\vcpkg\installed\x64-windows-static\lib

MSVC Version

PS F:\Downloads\curl-7.60.0\build2> cl -Bv
用于 x64 的 Microsoft (R) C/C++ 优化编译器 19.14.26428.1 版
版权所有(C) Microsoft Corporation。保留所有权利。

编译器扫描遍数:
 C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.14.26428\bin\HostX64\x64\cl.exe:        版本 19.14.26428.1
 C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.14.26428\bin\HostX64\x64\c1.dll:        版本 19.14.26428.1
 C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.14.26428\bin\HostX64\x64\c1xx.dll:      版本 19.14.26428.1
 C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.14.26428\bin\HostX64\x64\c2.dll:        版本 19.14.26428.1
 C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.14.26428\bin\HostX64\x64\link.exe:      版本 14.14.26428.1
 C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.14.26428\bin\HostX64\x64\mspdb140.dll:  版本 14.14.26428.1
 C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.14.26428\bin\HostX64\x64\2052\clui.dll: 版本 19.14.26428.1

operating system

Microsoft Windows [version 10.0.17134.48]
@fcharlie fcharlie changed the title Does CURL(With WinSSL) support HTTP2 ? Does CURL(With WinSSL) not support HTTP2 ? May 21, 2018
@bagder
Copy link
Member

bagder commented May 21, 2018

HTTP/2 support (over plain HTTP) is built-in when you build with nghttp2, which you seem to have done.

HTTP/2 support over HTTPS requires that the TLS library/backend speaks ALPN properly so curl can negotiate 'h2' with the server and when built with WinSSL that is conditionally present:

#if defined(_MSC_VER) && (_MSC_VER >= 1800) && !defined(_USING_V110_SDK71_)

... and the run-time check at connection-time:

  BACKEND->use_alpn = conn->bits.tls_enable_alpn &&
                      !GetProcAddress(GetModuleHandleA("ntdll"),
                                      "wine_get_version") &&
                      Curl_verify_windows_version(6, 3, PLATFORM_WINNT,
                                                  VERSION_GREATER_THAN_EQUAL);

... if those match on your system, I think you need to debug how come HTTP/2 doesn't get used with nghttp2.org.

@bagder bagder changed the title Does CURL(With WinSSL) not support HTTP2 ? curl with WinSSL does not enable HTTP2 against nghttp2.org May 21, 2018
@fcharlie
Copy link
Author

fcharlie commented May 21, 2018

cURL use WinSSL

D:\Utilities\cURL>curl -I https://nghttp2.org --verbose
* Rebuilt URL to: https://nghttp2.org/
*   Trying 139.162.123.134...
* TCP_NODELAY set
* Connected to nghttp2.org (139.162.123.134) port 443 (#0)
* schannel: SSL/TLS connection with nghttp2.org port 443 (step 1/3)
* schannel: checking server certificate revocation
* schannel: sending initial handshake data: sending 176 bytes...
* schannel: sent initial handshake data: sent 176 bytes
* schannel: SSL/TLS connection with nghttp2.org port 443 (step 2/3)
* schannel: failed to receive handshake, need more data
* schannel: SSL/TLS connection with nghttp2.org port 443 (step 2/3)
* schannel: encrypted data got 3295
* schannel: encrypted data buffer: offset 3295 length 4096
* schannel: sending next handshake data: sending 93 bytes...
* schannel: SSL/TLS connection with nghttp2.org port 443 (step 2/3)
* schannel: encrypted data got 242
* schannel: encrypted data buffer: offset 242 length 4096
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with nghttp2.org port 443 (step 3/3)
* schannel: stored credential handle in session cache
> HEAD / HTTP/1.1
> Host: nghttp2.org
> User-Agent: curl/7.60.0
> Accept: */*
>
* schannel: client wants to read 102400 bytes
* schannel: encdata_buffer resized 103424
* schannel: encrypted data buffer: offset 0 length 103424
* schannel: encrypted data got 428
* schannel: encrypted data buffer: offset 428 length 103424
* schannel: decrypted data length: 399
* schannel: decrypted data added: 399
* schannel: decrypted data cached: offset 399 length 102400
* schannel: encrypted data buffer: offset 0 length 103424
* schannel: decrypted data buffer: offset 399 length 102400
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 399
* schannel: decrypted data buffer: offset 0 length 102400
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Date: Mon, 21 May 2018 14:02:30 GMT
Date: Mon, 21 May 2018 14:02:30 GMT
< Content-Type: text/html
Content-Type: text/html
< Last-Modified: Tue, 08 May 2018 13:53:22 GMT
Last-Modified: Tue, 08 May 2018 13:53:22 GMT
< Etag: "5af1abd2-19d8"
Etag: "5af1abd2-19d8"
< Accept-Ranges: bytes
Accept-Ranges: bytes
< Content-Length: 6616
Content-Length: 6616
< X-Backend-Header-Rtt: 0.001335
X-Backend-Header-Rtt: 0.001335
< Strict-Transport-Security: max-age=31536000
Strict-Transport-Security: max-age=31536000
< Server: nghttpx
Server: nghttpx
< Via: 2 nghttpx
Via: 2 nghttpx
< x-frame-options: SAMEORIGIN
x-frame-options: SAMEORIGIN
< x-xss-protection: 1; mode=block
x-xss-protection: 1; mode=block
< x-content-type-options: nosniff
x-content-type-options: nosniff

<
* Connection #0 to host nghttp2.org left intact

cURL use OpenSSL

D:\Utilities\cURL>curl_openssl.exe --verbose -I https://nghttp2.org
* Rebuilt URL to: https://nghttp2.org/
*   Trying 139.162.123.134...
* TCP_NODELAY set
* Connected to nghttp2.org (139.162.123.134) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: D:\Utilities\cURL\curl-ca-bundle.crt
  CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=nghttp2.org
*  start date: May 20 00:00:08 2018 GMT
*  expire date: Aug 18 00:00:08 2018 GMT
*  subjectAltName: host "nghttp2.org" matched cert's "nghttp2.org"
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x18aa3e3c7e0)
> HEAD / HTTP/2
> Host: nghttp2.org
> User-Agent: curl/7.60.0
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 200
HTTP/2 200
< date: Mon, 21 May 2018 14:03:29 GMT
date: Mon, 21 May 2018 14:03:29 GMT
< content-type: text/html
content-type: text/html
< last-modified: Tue, 08 May 2018 13:53:22 GMT
last-modified: Tue, 08 May 2018 13:53:22 GMT
< etag: "5af1abd2-19d8"
etag: "5af1abd2-19d8"
< accept-ranges: bytes
accept-ranges: bytes
< content-length: 6616
content-length: 6616
< x-backend-header-rtt: 0.028027
x-backend-header-rtt: 0.028027
< strict-transport-security: max-age=31536000
strict-transport-security: max-age=31536000
< server: nghttpx
server: nghttpx
< via: 2 nghttpx
via: 2 nghttpx
< x-frame-options: SAMEORIGIN
x-frame-options: SAMEORIGIN
< x-xss-protection: 1; mode=block
x-xss-protection: 1; mode=block
< x-content-type-options: nosniff
x-content-type-options: nosniff

<
* Connection #0 to host nghttp2.org left intact

https://http2.akamai.com/

D:\Utilities\cURL>curl -I --verbose https://http2.akamai.com/
*   Trying 23.200.218.124...
* TCP_NODELAY set
* Connected to http2.akamai.com (23.200.218.124) port 443 (#0)
* schannel: SSL/TLS connection with http2.akamai.com port 443 (step 1/3)
* schannel: checking server certificate revocation
* schannel: sending initial handshake data: sending 181 bytes...
* schannel: sent initial handshake data: sent 181 bytes
* schannel: SSL/TLS connection with http2.akamai.com port 443 (step 2/3)
* schannel: failed to receive handshake, need more data
* schannel: SSL/TLS connection with http2.akamai.com port 443 (step 2/3)
* schannel: encrypted data got 3683
* schannel: encrypted data buffer: offset 3683 length 4096
* schannel: sending next handshake data: sending 126 bytes...
* schannel: SSL/TLS connection with http2.akamai.com port 443 (step 2/3)
* schannel: encrypted data got 242
* schannel: encrypted data buffer: offset 242 length 4096
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with http2.akamai.com port 443 (step 3/3)
* schannel: stored credential handle in session cache
> HEAD / HTTP/1.1
> Host: http2.akamai.com
> User-Agent: curl/7.60.0
> Accept: */*
>
* schannel: client wants to read 102400 bytes
* schannel: encdata_buffer resized 103424
* schannel: encrypted data buffer: offset 0 length 103424
* schannel: encrypted data got 864
* schannel: encrypted data buffer: offset 864 length 103424
* schannel: decrypted data length: 835
* schannel: decrypted data added: 835
* schannel: decrypted data cached: offset 835 length 102400
* schannel: encrypted data buffer: offset 0 length 103424
* schannel: decrypted data buffer: offset 835 length 102400
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 835
* schannel: decrypted data buffer: offset 0 length 102400
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Server: Apache
Server: Apache
< ETag: "9068c20f1c727825919f58f136cdfb91:1506554442"
ETag: "9068c20f1c727825919f58f136cdfb91:1506554442"
< Last-Modified: Wed, 27 Sep 2017 23:04:38 GMT
Last-Modified: Wed, 27 Sep 2017 23:04:38 GMT
< Accept-Ranges: bytes
Accept-Ranges: bytes
< Content-Length: 11710
Content-Length: 11710
< push: true
push: true
< rtt: 331
rtt: 331
< ghost_ip: 23.200.218.124
ghost_ip: 23.200.218.124
< ghost_service_ip: 192.80.13.117
ghost_service_ip: 192.80.13.117
< client_real_ip: 113.104.216.208
client_real_ip: 113.104.216.208
< client_ip: 113.104.216.208
client_ip: 113.104.216.208
< myproto:
myproto:
< protocol_negotiation: h1
protocol_negotiation: h1
< Cache-Control: max-age=43200
Cache-Control: max-age=43200
< Expires: Tue, 22 May 2018 02:05:45 GMT
Expires: Tue, 22 May 2018 02:05:45 GMT
< Date: Mon, 21 May 2018 14:05:45 GMT
Date: Mon, 21 May 2018 14:05:45 GMT
< Connection: keep-alive
Connection: keep-alive
< Content-Type: text/html;charset=UTF-8
Content-Type: text/html;charset=UTF-8
< Accept-CH: DPR, Width, Viewport-Width, Downlink, Save-Data
Accept-CH: DPR, Width, Viewport-Width, Downlink, Save-Data
< Access-Control-Max-Age: 86400
Access-Control-Max-Age: 86400
< Access-Control-Allow-Credentials: false
Access-Control-Allow-Credentials: false
< Access-Control-Allow-Headers: *
Access-Control-Allow-Headers: *
< Access-Control-Allow-Methods: GET,HEAD,POST
Access-Control-Allow-Methods: GET,HEAD,POST
< Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *
< Strict-Transport-Security: max-age=31536000 ; includeSubDomains
Strict-Transport-Security: max-age=31536000 ; includeSubDomains

<
* Connection #0 to host http2.akamai.com left intact

D:\Utilities\cURL>curl_openssl.exe -I --verbose https://http2.akamai.com/
*   Trying 23.200.218.124...
* TCP_NODELAY set
* Connected to http2.akamai.com (23.200.218.124) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: D:\Utilities\cURL\curl-ca-bundle.crt
  CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=US; ST=Massachusetts; L=Cambridge; O=Akamai Technologies Inc.; CN=http2.akamai.com
*  start date: May  8 00:00:00 2018 GMT
*  expire date: May  8 12:00:00 2019 GMT
*  subjectAltName: host "http2.akamai.com" matched cert's "http2.akamai.com"
*  issuer: C=US; O=DigiCert Inc; CN=DigiCert SHA2 Secure Server CA
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x1b4a86bb120)
> HEAD / HTTP/2
> Host: http2.akamai.com
> User-Agent: curl/7.60.0
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 200
HTTP/2 200
< server: Apache
server: Apache
< etag: "9068c20f1c727825919f58f136cdfb91:1506554442"
etag: "9068c20f1c727825919f58f136cdfb91:1506554442"
< last-modified: Wed, 27 Sep 2017 23:04:38 GMT
last-modified: Wed, 27 Sep 2017 23:04:38 GMT
< accept-ranges: bytes
accept-ranges: bytes
< content-length: 11710
content-length: 11710
< push: true
push: true
< rtt: 451
rtt: 451
< ghost_ip: 23.200.218.124
ghost_ip: 23.200.218.124
< ghost_service_ip: 192.80.13.117
ghost_service_ip: 192.80.13.117
< client_real_ip: 113.104.216.208
client_real_ip: 113.104.216.208
< client_ip: 113.104.216.208
client_ip: 113.104.216.208
< myproto: h2
myproto: h2
< protocol_negotiation: h2
protocol_negotiation: h2
< cache-control: max-age=43200
cache-control: max-age=43200
< expires: Tue, 22 May 2018 02:06:02 GMT
expires: Tue, 22 May 2018 02:06:02 GMT
< date: Mon, 21 May 2018 14:06:02 GMT
date: Mon, 21 May 2018 14:06:02 GMT
< content-type: text/html;charset=UTF-8
content-type: text/html;charset=UTF-8
< accept-ch: DPR, Width, Viewport-Width, Downlink, Save-Data
accept-ch: DPR, Width, Viewport-Width, Downlink, Save-Data
< access-control-max-age: 86400
access-control-max-age: 86400
< access-control-allow-credentials: false
access-control-allow-credentials: false
< access-control-allow-headers: *
access-control-allow-headers: *
< access-control-allow-methods: GET,HEAD,POST
access-control-allow-methods: GET,HEAD,POST
< access-control-allow-origin: *
access-control-allow-origin: *
< strict-transport-security: max-age=31536000 ; includeSubDomains
strict-transport-security: max-age=31536000 ; includeSubDomains

<
* Connection #0 to host http2.akamai.com left intact

@bagder
Copy link
Member

bagder commented May 21, 2018

Given that your verbose output doesn't mention ALPN at all, I'd guess BACKEND->use_alpn is never true.

Can you verify and check that the code on

curl/lib/vtls/schannel.c

Lines 300 to 304 in d5a2df5

BACKEND->use_alpn = conn->bits.tls_enable_alpn &&
!GetProcAddress(GetModuleHandleA("ntdll"),
"wine_get_version") &&
Curl_verify_windows_version(6, 3, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL);
wants to set that to true ?

@fcharlie
Copy link
Author

Curl_verify_windows_version Unable to get correct value
See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx

https://github.com/curl/curl/blob/master/lib/system_win32.c#L126

When I modify code, Rebuid curl, It can use WinSSL support HTTP2

//#ifdef HAS_ALPN
//  /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
//     Also it doesn't seem to be supported for Wine, see curl bug #983. */
//  BACKEND->use_alpn = conn->bits.tls_enable_alpn &&
//                      !GetProcAddress(GetModuleHandleA("ntdll"),
//                                      "wine_get_version") &&
//                      Curl_verify_windows_version(6, 3, PLATFORM_WINNT,
//                                                  VERSION_GREATER_THAN_EQUAL);
//#else
//  BACKEND->use_alpn = false;
//#endif
	BACKEND->use_alpn = true;
F:\Downloads\curl-7.60.0\build2\src>curl -I https://nghttp2.org
HTTP/2 200
date: Mon, 21 May 2018 14:16:53 GMT
content-type: text/html
last-modified: Tue, 08 May 2018 13:53:22 GMT
etag: "5af1abd2-19d8"
accept-ranges: bytes
content-length: 6616
x-backend-header-rtt: 0.001479
strict-transport-security: max-age=31536000
server: nghttpx
via: 2 nghttpx
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
x-content-type-options: nosniff


F:\Downloads\curl-7.60.0\build2\src>curl -I https://nghttp2.org

F:\Downloads\curl-7.60.0\build2\src>curl -V
curl 7.60.0 (Windows) libcurl/7.60.0 WinSSL zlib/1.2.11 nghttp2/1.32.0
Release-Date: 2018-05-16
Protocols: dict file ftp ftps gopher http https imap imaps ldap pop3 pop3s rtsp smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile SSPI Kerberos SPNEGO NTLM SSL libz HTTP2

* Rebuilt URL to: https://nghttp2.org/
*   Trying 139.162.123.134...
* TCP_NODELAY set
* Connected to nghttp2.org (139.162.123.134) port 443 (#0)
* schannel: SSL/TLS connection with nghttp2.org port 443 (step 1/3)
* schannel: checking server certificate revocation
* schannel: ALPN, offering h2
* schannel: ALPN, offering http/1.1
* schannel: sending initial handshake data: sending 194 bytes...
* schannel: sent initial handshake data: sent 194 bytes
* schannel: SSL/TLS connection with nghttp2.org port 443 (step 2/3)
* schannel: failed to receive handshake, need more data
* schannel: SSL/TLS connection with nghttp2.org port 443 (step 2/3)
* schannel: encrypted data got 3306
* schannel: encrypted data buffer: offset 3306 length 4096
* schannel: sending next handshake data: sending 93 bytes...
* schannel: SSL/TLS connection with nghttp2.org port 443 (step 2/3)
* schannel: encrypted data got 298
* schannel: encrypted data buffer: offset 298 length 4096
* schannel: encrypted data length: 56
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with nghttp2.org port 443 (step 3/3)
* schannel: ALPN, server accepted to use h2
* schannel: stored credential handle in session cache
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x167d07f9010)
> HEAD / HTTP/2
> Host: nghttp2.org
> User-Agent: curl/7.60.0
> Accept: */*
>
* schannel: client wants to read 32768 bytes
* schannel: encdata_buffer resized 33792
* schannel: encrypted data buffer: offset 56 length 33792
* schannel: encrypted data got 297
* schannel: encrypted data buffer: offset 353 length 33792
* schannel: decrypted data length: 27
* schannel: decrypted data added: 27
* schannel: decrypted data cached: offset 27 length 32768
* schannel: encrypted data length: 297
* schannel: encrypted data cached: offset 297 length 33792
* schannel: decrypted data length: 9
* schannel: decrypted data added: 9
* schannel: decrypted data cached: offset 36 length 32768
* schannel: encrypted data length: 259
* schannel: encrypted data cached: offset 259 length 33792
* schannel: decrypted data length: 230
* schannel: decrypted data added: 230
* schannel: decrypted data cached: offset 266 length 32768
* schannel: encrypted data buffer: offset 0 length 33792
* schannel: decrypted data buffer: offset 266 length 32768
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 266
* schannel: decrypted data buffer: offset 0 length 32768
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 200
HTTP/2 200
< date: Mon, 21 May 2018 14:19:35 GMT
date: Mon, 21 May 2018 14:19:35 GMT
< content-type: text/html
content-type: text/html
< last-modified: Tue, 08 May 2018 13:53:22 GMT
last-modified: Tue, 08 May 2018 13:53:22 GMT
< etag: "5af1abd2-19d8"
etag: "5af1abd2-19d8"
< accept-ranges: bytes
accept-ranges: bytes
< content-length: 6616
content-length: 6616
< x-backend-header-rtt: 0.001597
x-backend-header-rtt: 0.001597
< strict-transport-security: max-age=31536000
strict-transport-security: max-age=31536000
< server: nghttpx
server: nghttpx
< via: 2 nghttpx
via: 2 nghttpx
< x-frame-options: SAMEORIGIN
x-frame-options: SAMEORIGIN
< x-xss-protection: 1; mode=block
x-xss-protection: 1; mode=block
< x-content-type-options: nosniff
x-content-type-options: nosniff

<
* Connection #0 to host nghttp2.org left intact

@bagder
Copy link
Member

bagder commented May 21, 2018

Good, then you've identified the bug. Now we only need a proper fix...

@fcharlie
Copy link
Author

Great Thanks. I love curl.

@fcharlie
Copy link
Author

fcharlie commented May 21, 2018

Test code:

#ifdef HAS_ALPN
  /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
     Also it doesn't seem to be supported for Wine, see curl bug #983. */
  if(!Curl_verify_windows_version(6, 3, PLATFORM_WINNT,
  VERSION_GREATER_THAN_EQUAL)){
	  fprintf(stderr,"OS not support ALPN\n");
  }
  BACKEND->use_alpn = conn->bits.tls_enable_alpn &&
                      !GetProcAddress(GetModuleHandleA("ntdll"),
                                      "wine_get_version") &&
                      Curl_verify_windows_version(6, 3, PLATFORM_WINNT,
                                                  VERSION_GREATER_THAN_EQUAL);
#else
  BACKEND->use_alpn = false;
#endif
OS not support ALPN
HTTP/1.1 200 OK
Date: Mon, 21 May 2018 14:42:38 GMT
Content-Type: text/html
Last-Modified: Tue, 08 May 2018 13:53:22 GMT
Etag: "5af1abd2-19d8"
Accept-Ranges: bytes
Content-Length: 6616
X-Backend-Header-Rtt: 0.001399
Strict-Transport-Security: max-age=31536000
Server: nghttpx
Via: 2 nghttpx
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
x-content-type-options: nosniff

https://social.msdn.microsoft.com/Forums/windowsdesktop/en-us/298a1817-0af5-4efc-9663-db9a841a233b/verifyversioninfo-and-windows-10

Update curl manifest is work !!!

mt  -inputresource:curl.exe -manifest curl.manifest -outputresource:curl.exe
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
  <assemblyIdentity version="1.0.0.0" name="curl.app"/>
  <description>curl</description>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
            level="asInvoker"
            uiAccess="false"
                />
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency optional="yes">
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.1.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="*"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- Windows 10 -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
      <!-- Windows 8.1 -->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
      <!-- Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
      <!-- Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <!-- Windows 8 -->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
    </application>
  </compatibility>
</assembly>

@bagder
Copy link
Member

bagder commented May 21, 2018

Curl_verify_windows_version() clearly does not work as intended there...

@fcharlie
Copy link
Author

fcharlie commented May 21, 2018

I use Register check OS version.

struct RegKeyHelper {
  ~RegKeyHelper() {
    if (hKey != nullptr) {
      RegCloseKey(hKey);
    }
  }
  HKEY hKey{nullptr};
};

bool IsWindowsVersionOrGreaterEx(WORD wMajorVersion, WORD wMinorVersion,
                                 DWORD buildNumber) {
  const wchar_t *currentVersion =
      LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)";
  RegKeyHelper key;
  if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, currentVersion, 0, KEY_READ,
                    &(key.hKey)) != ERROR_SUCCESS) {
    ErrorMessage err(GetLastError());
    fwprintf(stderr, L"error: %s\n", err.message());
    return false;
  }
  DWORD wMajor, wMinor;
  DWORD type = 0;
  DWORD dwSizeM = sizeof(DWORD);
  if (RegGetValueW(key.hKey, nullptr, L"CurrentMajorVersionNumber",
                   RRF_RT_DWORD, &type, &wMajor, &dwSizeM) != ERROR_SUCCESS) {
    ErrorMessage err(GetLastError());
    fwprintf(stderr, L"error: %s\n", err.message());
    return false;
  }
  dwSizeM = sizeof(DWORD);
  if (RegGetValueW(key.hKey, nullptr, L"CurrentMinorVersionNumber",
                   RRF_RT_DWORD, &type, &wMinor, &dwSizeM) != ERROR_SUCCESS) {
    ErrorMessage err(GetLastError());
    fwprintf(stderr, L"error: %s\n", err.message());
    return false;
  }
  WCHAR buffer[32];
  DWORD dwSize = sizeof(buffer);
  if (RegGetValueW(key.hKey, nullptr, L"CurrentBuildNumber", RRF_RT_REG_SZ,
                   &type, buffer, &dwSize) != ERROR_SUCCESS) {
    ErrorMessage err(GetLastError());
    fwprintf(stderr, L"error: %s\n", err.message());
    return false;
  }
  wchar_t *w;
  auto bn = wcstol(buffer, &w, 10);
  if (wMajor < wMajorVersion) {
    return false;
  }
  if (wMajor > wMajorVersion) {
    return true;
  }
  if (wMinor > wMinorVersion) {
    return true;
  }
  if (wMinor < wMinorVersion) {
    return false;
  }
  return ((DWORD)bn >= buildNumber);
}

@vszakats
Copy link
Member

vszakats commented May 21, 2018

Curl_verify_windows_version() is the correct (and the canonical/official) way to retrieve Windows version, but it requires a Manifest to return the expected values.

@vszakats
Copy link
Member

I've reopened #1221 to add a manifest to curl.exe. It's enabled with the src/Makefile.m32 build method at the moment.

@vszakats
Copy link
Member

I've added CMake builds into the mix having a correct manifest enabled. Testers wanted.

@fcharlie
Copy link
Author

@vszakats OK.

*   Trying 139.162.123.134...
* TCP_NODELAY set
* Connected to nghttp2.org (139.162.123.134) port 443 (#0)
* schannel: SSL/TLS connection with nghttp2.org port 443 (step 1/3)
* schannel: checking server certificate revocation
* schannel: ALPN, offering h2
* schannel: ALPN, offering http/1.1
* schannel: sending initial handshake data: sending 194 bytes...
* schannel: sent initial handshake data: sent 194 bytes
* schannel: SSL/TLS connection with nghttp2.org port 443 (step 2/3)
* schannel: failed to receive handshake, need more data
* schannel: SSL/TLS connection with nghttp2.org port 443 (step 2/3)
* schannel: encrypted data got 3305
* schannel: encrypted data buffer: offset 3305 length 4096
* schannel: sending next handshake data: sending 93 bytes...
* schannel: SSL/TLS connection with nghttp2.org port 443 (step 2/3)
* schannel: encrypted data got 298
* schannel: encrypted data buffer: offset 298 length 4096
* schannel: encrypted data length: 56
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with nghttp2.org port 443 (step 3/3)
* schannel: ALPN, server accepted to use h2
* schannel: stored credential handle in session cache
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x1fa7b5b7770)
> HEAD / HTTP/2
> Host: nghttp2.org
> User-Agent: curl/7.60.0
> Accept: */*
>
* schannel: client wants to read 32768 bytes
* schannel: encdata_buffer resized 33792
* schannel: encrypted data buffer: offset 56 length 33792
* schannel: encrypted data got 297
* schannel: encrypted data buffer: offset 353 length 33792
* schannel: decrypted data length: 27
* schannel: decrypted data added: 27
* schannel: decrypted data cached: offset 27 length 32768
* schannel: encrypted data length: 297
* schannel: encrypted data cached: offset 297 length 33792
* schannel: decrypted data length: 9
* schannel: decrypted data added: 9
* schannel: decrypted data cached: offset 36 length 32768
* schannel: encrypted data length: 259
* schannel: encrypted data cached: offset 259 length 33792
* schannel: decrypted data length: 230
* schannel: decrypted data added: 230
* schannel: decrypted data cached: offset 266 length 32768
* schannel: encrypted data buffer: offset 0 length 33792
* schannel: decrypted data buffer: offset 266 length 32768
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 266
* schannel: decrypted data buffer: offset 0 length 32768
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 200
HTTP/2 200
< date: Tue, 29 May 2018 20:59:17 GMT
date: Tue, 29 May 2018 20:59:17 GMT
< content-type: text/html
content-type: text/html
< last-modified: Tue, 08 May 2018 13:53:22 GMT
last-modified: Tue, 08 May 2018 13:53:22 GMT
< etag: "5af1abd2-19d8"
etag: "5af1abd2-19d8"
< accept-ranges: bytes
accept-ranges: bytes
< content-length: 6616
content-length: 6616
< x-backend-header-rtt: 0.001095
x-backend-header-rtt: 0.001095
< strict-transport-security: max-age=31536000
strict-transport-security: max-age=31536000
< server: nghttpx
server: nghttpx
< via: 2 nghttpx
via: 2 nghttpx
< x-frame-options: SAMEORIGIN
x-frame-options: SAMEORIGIN
< x-xss-protection: 1; mode=block
x-xss-protection: 1; mode=block
< x-content-type-options: nosniff
x-content-type-options: nosniff

<
* Connection #0 to host nghttp2.org left intact

Manifest is OK:

image

pravic added a commit to pravic/vcpkg that referenced this issue Jul 14, 2018
ras0219-msft pushed a commit to microsoft/vcpkg that referenced this issue Jul 18, 2018
* [curl] update to 7.61.0

* [curl] Fix wrong checksum.

* [curl] Remove winssl-http2 patch which is not needed anymore.

per curl/curl#2591.
dirkvdb pushed a commit to dirkvdb/vcpkg that referenced this issue Jul 19, 2018
* [curl] update to 7.61.0

* [curl] Fix wrong checksum.

* [curl] Remove winssl-http2 patch which is not needed anymore.

per curl/curl#2591.
@lock lock bot locked as resolved and limited conversation to collaborators Aug 28, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
HTTP/2 TLS Windows Windows-specific
Development

No branches or pull requests

3 participants