aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/CONTRIBUTING.md4
-rw-r--r--.travis.yml2
-rw-r--r--Android.bp4
-rw-r--r--CMake/CurlSymbolHiding.cmake61
-rw-r--r--CMake/FindNGHTTP2.cmake18
-rw-r--r--CMake/OtherTests.cmake25
-rw-r--r--CMakeLists.txt104
-rw-r--r--GIT-INFO14
-rw-r--r--Makefile.am11
-rw-r--r--README.md1
-rw-r--r--README.version6
-rw-r--r--RELEASE-NOTES103
-rw-r--r--acinclude.m459
-rw-r--r--configure.ac126
-rw-r--r--docs/BINDINGS260
-rw-r--r--docs/BINDINGS.md106
-rw-r--r--docs/CHECKSRC.md4
-rw-r--r--docs/CODE_STYLE.md66
-rw-r--r--docs/CONTRIBUTE261
-rw-r--r--docs/CONTRIBUTE.md247
-rw-r--r--docs/FAQ20
-rw-r--r--docs/FEATURES4
-rw-r--r--docs/HISTORY.md (renamed from docs/HISTORY)12
-rw-r--r--docs/HTTP2.md29
-rw-r--r--docs/INSTALL1108
-rw-r--r--docs/INSTALL.devcpp302
-rw-r--r--docs/INSTALL.md513
-rw-r--r--docs/INTERNALS.md (renamed from docs/INTERNALS)167
-rw-r--r--docs/KNOWN_BUGS133
-rw-r--r--docs/LICENSE-MIXING130
-rw-r--r--docs/LICENSE-MIXING.md127
-rw-r--r--docs/MAIL-ETIQUETTE9
-rw-r--r--docs/MANUAL8
-rw-r--r--docs/Makefile.am12
-rw-r--r--docs/RELEASE-PROCEDURE8
-rw-r--r--docs/SECURITY.md (renamed from docs/SECURITY)28
-rw-r--r--docs/SSL-PROBLEMS.md (renamed from docs/SSL-PROBLEMS)14
-rw-r--r--docs/SSLCERTS.md (renamed from docs/SSLCERTS)0
-rw-r--r--docs/THANKS46
-rw-r--r--docs/THANKS-filter2
-rw-r--r--docs/TODO423
-rw-r--r--docs/TheArtOfHttpScripting2
-rw-r--r--docs/cmdline-opts/MANPAGE.md53
-rw-r--r--docs/cmdline-opts/anyauth.d17
-rw-r--r--docs/cmdline-opts/append.d8
-rw-r--r--docs/cmdline-opts/basic.d11
-rw-r--r--docs/cmdline-opts/cacert.d28
-rw-r--r--docs/cmdline-opts/capath.d15
-rw-r--r--docs/cmdline-opts/cert-status.d13
-rw-r--r--docs/cmdline-opts/cert-type.d10
-rw-r--r--docs/cmdline-opts/cert.d32
-rw-r--r--docs/cmdline-opts/ciphers.d16
-rw-r--r--docs/cmdline-opts/compressed.d7
-rw-r--r--docs/cmdline-opts/config.d60
-rw-r--r--docs/cmdline-opts/connect-timeout.d11
-rw-r--r--docs/cmdline-opts/connect-to.d18
-rw-r--r--docs/cmdline-opts/continue-at.d15
-rw-r--r--docs/cmdline-opts/cookie-jar.d24
-rw-r--r--docs/cmdline-opts/cookie.d36
-rw-r--r--docs/cmdline-opts/create-dirs.d9
-rw-r--r--docs/cmdline-opts/crlf.d7
-rw-r--r--docs/cmdline-opts/crlfile.d10
-rw-r--r--docs/cmdline-opts/data-ascii.d5
-rw-r--r--docs/cmdline-opts/data-binary.d13
-rw-r--r--docs/cmdline-opts/data-raw.d9
-rw-r--r--docs/cmdline-opts/data-urlencode.d33
-rw-r--r--docs/cmdline-opts/data.d30
-rw-r--r--docs/cmdline-opts/delegation.d16
-rw-r--r--docs/cmdline-opts/digest.d11
-rw-r--r--docs/cmdline-opts/disable-eprt.d19
-rw-r--r--docs/cmdline-opts/dns-interface.d11
-rw-r--r--docs/cmdline-opts/dns-ipv4-addr.d11
-rw-r--r--docs/cmdline-opts/dns-ipv6-addr.d11
-rw-r--r--docs/cmdline-opts/dns-servers.d10
-rw-r--r--docs/cmdline-opts/dump-header.d18
-rw-r--r--docs/cmdline-opts/egd-file.d7
-rw-r--r--docs/cmdline-opts/engine.d8
-rw-r--r--docs/cmdline-opts/environment.d7
-rw-r--r--docs/cmdline-opts/expect100-timeout.d11
-rw-r--r--docs/cmdline-opts/fail-early.d18
-rw-r--r--docs/cmdline-opts/fail.d14
-rw-r--r--docs/cmdline-opts/false-start.d12
-rw-r--r--docs/cmdline-opts/form-string.d10
-rw-r--r--docs/cmdline-opts/form.d54
-rw-r--r--docs/cmdline-opts/ftp-account.d10
-rw-r--r--docs/cmdline-opts/ftp-alternative-to-user.d10
-rw-r--r--docs/cmdline-opts/ftp-create-dirs.d8
-rw-r--r--docs/cmdline-opts/ftp-method.d21
-rw-r--r--docs/cmdline-opts/ftp-pasv.d16
-rw-r--r--docs/cmdline-opts/ftp-port.d32
-rw-r--r--docs/cmdline-opts/ftp-pret.d8
-rw-r--r--docs/cmdline-opts/ftp-skip-pasv-ip.d12
-rw-r--r--docs/cmdline-opts/ftp-ssl-ccc-mode.d11
-rw-r--r--docs/cmdline-opts/ftp-ssl-ccc.d10
-rw-r--r--docs/cmdline-opts/ftp-ssl-control.d8
-rw-r--r--docs/cmdline-opts/ftp-ssl-reqd.d3
-rw-r--r--docs/cmdline-opts/ftp-ssl.d3
-rwxr-xr-xdocs/cmdline-opts/gen.pl374
-rw-r--r--docs/cmdline-opts/get.d15
-rw-r--r--docs/cmdline-opts/globoff.d8
-rw-r--r--docs/cmdline-opts/head.d8
-rw-r--r--docs/cmdline-opts/header.d39
-rw-r--r--docs/cmdline-opts/hostpubmd5.d9
-rw-r--r--docs/cmdline-opts/http1.0.d10
-rw-r--r--docs/cmdline-opts/http1.1.d8
-rw-r--r--docs/cmdline-opts/http2-prior-knowledge.d12
-rw-r--r--docs/cmdline-opts/http2.d10
-rw-r--r--docs/cmdline-opts/ignore-content-length.d10
-rw-r--r--docs/cmdline-opts/include.d7
-rw-r--r--docs/cmdline-opts/insecure.d12
-rw-r--r--docs/cmdline-opts/interface.d12
-rw-r--r--docs/cmdline-opts/ipv4.d12
-rw-r--r--docs/cmdline-opts/ipv6.d12
-rw-r--r--docs/cmdline-opts/junk-session-cookies.d10
-rw-r--r--docs/cmdline-opts/keepalive-time.d13
-rw-r--r--docs/cmdline-opts/key-type.d9
-rw-r--r--docs/cmdline-opts/key.d10
-rw-r--r--docs/cmdline-opts/krb.d11
-rw-r--r--docs/cmdline-opts/krb4.d2
-rw-r--r--docs/cmdline-opts/libcurl.d11
-rw-r--r--docs/cmdline-opts/limit-rate.d18
-rw-r--r--docs/cmdline-opts/list-only.d24
-rw-r--r--docs/cmdline-opts/local-port.d9
-rw-r--r--docs/cmdline-opts/location-trusted.d9
-rw-r--r--docs/cmdline-opts/location.d23
-rw-r--r--docs/cmdline-opts/login-options.d13
-rw-r--r--docs/cmdline-opts/mail-auth.d10
-rw-r--r--docs/cmdline-opts/mail-from.d8
-rw-r--r--docs/cmdline-opts/mail-rcpt.d19
-rw-r--r--docs/cmdline-opts/max-filesize.d12
-rw-r--r--docs/cmdline-opts/max-redirs.d11
-rw-r--r--docs/cmdline-opts/max-time.d13
-rw-r--r--docs/cmdline-opts/metalink.d27
-rw-r--r--docs/cmdline-opts/negotiate.d15
-rw-r--r--docs/cmdline-opts/netrc-file.d12
-rw-r--r--docs/cmdline-opts/netrc-optional.d7
-rw-r--r--docs/cmdline-opts/netrc.d17
-rw-r--r--docs/cmdline-opts/next.d20
-rw-r--r--docs/cmdline-opts/no-alpn.d11
-rw-r--r--docs/cmdline-opts/no-buffer.d11
-rw-r--r--docs/cmdline-opts/no-keepalive.d8
-rw-r--r--docs/cmdline-opts/no-npn.d12
-rw-r--r--docs/cmdline-opts/no-sessionid.d13
-rw-r--r--docs/cmdline-opts/noproxy.d11
-rw-r--r--docs/cmdline-opts/ntlm-wb.d7
-rw-r--r--docs/cmdline-opts/ntlm.d18
-rw-r--r--docs/cmdline-opts/oauth2-bearer.d11
-rw-r--r--docs/cmdline-opts/output.d32
-rw-r--r--docs/cmdline-opts/page-header138
-rw-r--r--docs/cmdline-opts/pass.d8
-rw-r--r--docs/cmdline-opts/path-as-is.d7
-rw-r--r--docs/cmdline-opts/pinnedpubkey.d27
-rw-r--r--docs/cmdline-opts/post301.d11
-rw-r--r--docs/cmdline-opts/post302.d11
-rw-r--r--docs/cmdline-opts/post303.d11
-rw-r--r--docs/cmdline-opts/progress-bar.d11
-rw-r--r--docs/cmdline-opts/proto-default.d18
-rw-r--r--docs/cmdline-opts/proto-redir.d17
-rw-r--r--docs/cmdline-opts/proto.d43
-rw-r--r--docs/cmdline-opts/proxy-header.d20
-rw-r--r--docs/cmdline-opts/proxytunnel.d9
-rw-r--r--docs/cmdline-opts/referer.d12
-rw-r--r--docs/cmdline-opts/remote-header-name.d19
-rw-r--r--docs/cmdline-opts/remote-name.d21
-rw-r--r--docs/cmdline-opts/sslv2.d13
-rw-r--r--docs/cmdline-opts/sslv3.d13
-rw-r--r--docs/cmdline-opts/tlsv1.d14
-rw-r--r--docs/cmdline-opts/use-ascii.d8
-rw-r--r--docs/cmdline-opts/user-agent.d12
-rw-r--r--docs/cmdline-opts/verbose.d19
-rw-r--r--docs/curl.1133
-rw-r--r--docs/examples/10-at-a-time.c2
-rw-r--r--docs/examples/Makefile.netware2
-rw-r--r--docs/examples/anyauthput.c4
-rw-r--r--docs/examples/cacertinmem.c12
-rw-r--r--docs/examples/curlx.c42
-rw-r--r--docs/examples/evhiperfifo.c5
-rw-r--r--docs/examples/fileupload.c11
-rw-r--r--docs/examples/fopen.c2
-rw-r--r--docs/examples/ftpuploadresume.c6
-rw-r--r--docs/examples/ghiper.c6
-rw-r--r--docs/examples/hiperfifo.c5
-rw-r--r--docs/examples/imap-append.c8
-rw-r--r--docs/examples/multi-uv.c63
-rw-r--r--docs/examples/opensslthreadlock.c2
-rw-r--r--docs/examples/rtsp.c4
-rw-r--r--docs/examples/sessioninfo.c2
-rw-r--r--docs/libcurl/Makefile.am4
-rw-r--r--docs/libcurl/curl_easy_getinfo.39
-rw-r--r--docs/libcurl/curl_easy_setopt.338
-rw-r--r--docs/libcurl/curl_easy_unescape.37
-rw-r--r--docs/libcurl/curl_formadd.34
-rw-r--r--docs/libcurl/curl_global_cleanup.310
-rw-r--r--docs/libcurl/libcurl-errors.35
-rw-r--r--docs/libcurl/opts/CURLINFO_COOKIELIST.32
-rw-r--r--docs/libcurl/opts/CURLINFO_PROTOCOL.355
-rw-r--r--docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.344
-rw-r--r--docs/libcurl/opts/CURLINFO_SCHEME.359
-rw-r--r--docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.34
-rw-r--r--docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.34
-rw-r--r--docs/libcurl/opts/CURLMOPT_PIPELINING.340
-rw-r--r--docs/libcurl/opts/CURLOPT_CAINFO.36
-rw-r--r--docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.31
-rw-r--r--docs/libcurl/opts/CURLOPT_FAILONERROR.32
-rw-r--r--docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.352
-rw-r--r--docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.35
-rw-r--r--docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.36
-rw-r--r--docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.313
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY.38
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_CAINFO.364
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_CAPATH.354
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.359
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.346
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.356
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.349
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.351
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.351
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.381
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.366
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.362
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.388
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.382
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.348
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.353
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.346
-rw-r--r--docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.33
-rw-r--r--docs/libcurl/opts/CURLOPT_SOCKS_PROXY.388
-rw-r--r--docs/libcurl/opts/CURLOPT_SOCKS_PROXYTYPE.355
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLVERSION.32
-rw-r--r--docs/libcurl/opts/CURLOPT_TCP_NODELAY.312
-rw-r--r--docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.36
-rw-r--r--docs/libcurl/opts/Makefile.am24
-rw-r--r--docs/libcurl/symbols-in-versions26
-rw-r--r--docs/mk-ca-bundle.123
-rw-r--r--include/README2
-rw-r--r--include/curl/curl.h89
-rw-r--r--include/curl/curlver.h8
-rw-r--r--include/curl/easy.h4
-rw-r--r--include/curl/typecheck-gcc.h51
-rw-r--r--lib/CMakeLists.txt5
-rw-r--r--lib/Makefile.inc12
-rw-r--r--lib/Makefile.netware2
-rw-r--r--lib/Makefile.vc64
-rw-r--r--lib/amigaos.c2
-rw-r--r--lib/asyn-thread.c12
-rw-r--r--lib/base64.c5
-rwxr-xr-xlib/checksrc.pl30
-rw-r--r--lib/config-symbian.h6
-rw-r--r--lib/conncache.c7
-rw-r--r--lib/connect.c69
-rw-r--r--lib/connect.h46
-rw-r--r--lib/content_encoding.c9
-rw-r--r--lib/cookie.c134
-rw-r--r--lib/cookie.h4
-rw-r--r--lib/curl_config.h.cmake11
-rw-r--r--lib/curl_endian.c18
-rw-r--r--lib/curl_endian.h18
-rw-r--r--lib/curl_gethostname.c8
-rw-r--r--lib/curl_gssapi.c2
-rw-r--r--lib/curl_hmac.h26
-rw-r--r--lib/curl_ntlm_core.c37
-rw-r--r--lib/curl_ntlm_wb.c10
-rw-r--r--lib/curl_sasl.c32
-rw-r--r--lib/curl_sec.h6
-rw-r--r--lib/curl_setup.h28
-rw-r--r--lib/curl_sspi.c20
-rw-r--r--lib/curl_threads.c4
-rw-r--r--lib/curl_threads.h4
-rw-r--r--lib/curlx.h13
-rw-r--r--lib/dict.c25
-rw-r--r--lib/easy.c42
-rw-r--r--lib/escape.c41
-rw-r--r--lib/file.c13
-rw-r--r--lib/formdata.c92
-rw-r--r--lib/formdata.h3
-rw-r--r--lib/ftp.c251
-rw-r--r--lib/ftp.h6
-rw-r--r--lib/ftplistparser.c3
-rw-r--r--lib/getenv.c3
-rw-r--r--lib/getinfo.c37
-rw-r--r--lib/gopher.c37
-rw-r--r--lib/hash.c4
-rw-r--r--lib/hash.h15
-rw-r--r--lib/hmac.c10
-rw-r--r--lib/hostcheck.c14
-rw-r--r--lib/hostip.c9
-rw-r--r--lib/hostip.h6
-rw-r--r--lib/hostip4.c2
-rw-r--r--lib/http.c339
-rw-r--r--lib/http.h1
-rw-r--r--lib/http2.c298
-rw-r--r--lib/http2.h6
-rw-r--r--lib/http_digest.c6
-rw-r--r--lib/http_negotiate.c17
-rw-r--r--lib/http_ntlm.c6
-rw-r--r--lib/http_proxy.c71
-rw-r--r--lib/http_proxy.h4
-rw-r--r--lib/if2ip.c10
-rw-r--r--lib/imap.c31
-rw-r--r--lib/inet_ntop.c4
-rw-r--r--lib/krb5.c14
-rw-r--r--lib/ldap.c69
-rw-r--r--lib/libcurl.rc6
-rw-r--r--lib/md5.c6
-rw-r--r--lib/memdebug.c2
-rwxr-xr-xlib/mk-ca-bundle.pl173
-rwxr-xr-xlib/mk-ca-bundle.vbs261
-rw-r--r--lib/mprintf.c27
-rw-r--r--lib/multi.c315
-rw-r--r--lib/multihandle.h4
-rw-r--r--lib/multiif.h5
-rw-r--r--lib/netrc.c18
-rw-r--r--lib/non-ascii.c4
-rw-r--r--lib/parsedate.c20
-rw-r--r--lib/pingpong.c17
-rw-r--r--lib/pingpong.h2
-rw-r--r--lib/pipeline.c12
-rw-r--r--lib/pop3.c18
-rw-r--r--lib/progress.c87
-rw-r--r--lib/progress.h6
-rw-r--r--lib/rand.c130
-rw-r--r--lib/rand.h43
-rw-r--r--lib/rtsp.c27
-rw-r--r--lib/security.c24
-rw-r--r--lib/select.c37
-rw-r--r--lib/select.h11
-rw-r--r--lib/sendf.c2
-rw-r--r--lib/setup-os400.h52
-rw-r--r--lib/setup-vms.h139
-rw-r--r--lib/smb.c24
-rw-r--r--lib/smtp.c14
-rw-r--r--lib/socks.c165
-rw-r--r--lib/socks.h5
-rw-r--r--lib/socks_gssapi.c18
-rw-r--r--lib/socks_sspi.c11
-rw-r--r--lib/speedcheck.c6
-rw-r--r--lib/ssh.c64
-rw-r--r--lib/strcase.c (renamed from lib/rawstr.c)36
-rw-r--r--lib/strcase.h (renamed from lib/rawstr.h)26
-rw-r--r--lib/strdup.c27
-rw-r--r--lib/strdup.h5
-rw-r--r--lib/strequal.c79
-rw-r--r--lib/strerror.c87
-rw-r--r--lib/strerror.h4
-rw-r--r--lib/strtoofft.c4
-rw-r--r--lib/system_win32.c39
-rw-r--r--lib/telnet.c19
-rw-r--r--lib/tftp.c35
-rw-r--r--lib/timeval.c6
-rw-r--r--lib/timeval.h6
-rw-r--r--lib/transfer.c107
-rw-r--r--lib/transfer.h8
-rw-r--r--lib/url.c1045
-rw-r--r--lib/url.h11
-rw-r--r--lib/urldata.h150
-rw-r--r--lib/vauth/cleartext.c26
-rw-r--r--lib/vauth/digest.c65
-rw-r--r--lib/vauth/digest_sspi.c27
-rw-r--r--lib/vauth/krb5_gssapi.c14
-rw-r--r--lib/vauth/krb5_sspi.c22
-rw-r--r--lib/vauth/ntlm.c26
-rw-r--r--lib/vauth/ntlm_sspi.c21
-rw-r--r--lib/vauth/spnego_gssapi.c14
-rw-r--r--lib/vauth/spnego_sspi.c28
-rw-r--r--lib/vauth/vauth.c41
-rw-r--r--lib/vauth/vauth.h15
-rw-r--r--lib/version.c14
-rw-r--r--lib/vtls/axtls.c72
-rw-r--r--lib/vtls/cyassl.c99
-rw-r--r--lib/vtls/darwinssl.c422
-rw-r--r--lib/vtls/gskit.c341
-rw-r--r--lib/vtls/gskit.h4
-rw-r--r--lib/vtls/gtls.c285
-rw-r--r--lib/vtls/gtls.h4
-rw-r--r--lib/vtls/mbedtls.c96
-rw-r--r--lib/vtls/nss.c284
-rw-r--r--lib/vtls/openssl.c484
-rw-r--r--lib/vtls/polarssl.c153
-rw-r--r--lib/vtls/polarssl_threadlock.c4
-rw-r--r--lib/vtls/schannel.c121
-rw-r--r--lib/vtls/vtls.c315
-rw-r--r--lib/vtls/vtls.h48
-rw-r--r--lib/x509asn1.c192
-rw-r--r--lib/x509asn1.h26
-rw-r--r--m4/curl-compilers.m42
-rw-r--r--m4/curl-functions.m427
-rwxr-xr-xmaketgz51
-rw-r--r--packages/AIX/RPM/README2
-rw-r--r--packages/DOS/common.dj2
-rw-r--r--packages/OS400/README.OS40020
-rw-r--r--packages/OS400/ccsidcurl.c23
-rw-r--r--packages/OS400/curl.inc.in50
-rw-r--r--packages/Symbian/group/curl.mmp4
-rw-r--r--packages/Symbian/group/libcurl.mmp4
-rw-r--r--packages/Win32/cygwin/README10
-rw-r--r--packages/vms/curlmsg.h3
-rw-r--r--packages/vms/curlmsg.msg2
-rw-r--r--packages/vms/curlmsg.sdl1
-rw-r--r--packages/vms/curlmsg_vms.h2
-rw-r--r--packages/vms/gnv_link_curl.com8
-rw-r--r--packages/vms/readme10
-rw-r--r--packages/vms/vms_eco_level.h2
-rw-r--r--projects/README16
-rw-r--r--projects/generate.bat3
-rw-r--r--src/CMakeLists.txt8
-rw-r--r--src/Makefile.Watcom4
-rw-r--r--src/Makefile.inc2
-rw-r--r--src/Makefile.netware2
-rw-r--r--src/Makefile.vc612
-rw-r--r--src/curl.rc8
-rw-r--r--src/macos/MACINSTALL.TXT2
-rw-r--r--src/makefile.amiga6
-rw-r--r--src/makefile.dj2
-rw-r--r--src/tool_cb_dbg.c6
-rw-r--r--src/tool_cb_hdr.c6
-rw-r--r--src/tool_cfgable.c15
-rw-r--r--src/tool_cfgable.h21
-rw-r--r--src/tool_dirhie.c19
-rw-r--r--src/tool_doswin.c4
-rw-r--r--src/tool_formparse.c2
-rw-r--r--src/tool_getparam.c187
-rw-r--r--src/tool_getpass.h4
-rw-r--r--src/tool_help.c31
-rw-r--r--src/tool_helpers.c6
-rw-r--r--src/tool_libinfo.c6
-rw-r--r--src/tool_metalink.c36
-rw-r--r--src/tool_operate.c97
-rw-r--r--src/tool_operhlp.c8
-rw-r--r--src/tool_paramhlp.c26
-rw-r--r--src/tool_setopt.c15
-rw-r--r--src/tool_setopt.h3
-rw-r--r--src/tool_urlglob.c69
-rw-r--r--src/tool_urlglob.h6
-rw-r--r--src/tool_writeenv.c6
-rw-r--r--src/tool_writeout.c30
-rw-r--r--tests/README5
-rw-r--r--tests/data/Makefile.inc13
-rw-r--r--tests/data/test10012
-rw-r--r--tests/data/test10023
-rw-r--r--tests/data/test10082
-rw-r--r--tests/data/test10213
-rw-r--r--tests/data/test10341
-rw-r--r--tests/data/test10351
-rw-r--r--tests/data/test10591
-rw-r--r--tests/data/test10602
-rw-r--r--tests/data/test10612
-rw-r--r--tests/data/test10773
-rw-r--r--tests/data/test10781
-rw-r--r--tests/data/test10873
-rw-r--r--tests/data/test10883
-rw-r--r--tests/data/test10921
-rw-r--r--tests/data/test10971
-rw-r--r--tests/data/test10982
-rw-r--r--tests/data/test11042
-rw-r--r--tests/data/test11061
-rw-r--r--tests/data/test11352
-rw-r--r--tests/data/test11412
-rw-r--r--tests/data/test11421
-rw-r--r--tests/data/test114469
-rw-r--r--tests/data/test12131
-rw-r--r--tests/data/test12141
-rw-r--r--tests/data/test12152
-rw-r--r--tests/data/test12162
-rw-r--r--tests/data/test12183
-rw-r--r--tests/data/test12282
-rw-r--r--tests/data/test12301
-rw-r--r--tests/data/test12322
-rw-r--r--tests/data/test12412
-rw-r--r--tests/data/test12441
-rw-r--r--tests/data/test124563
-rw-r--r--tests/data/test124664
-rw-r--r--tests/data/test124738
-rw-r--r--tests/data/test128058
-rw-r--r--tests/data/test13014
-rw-r--r--tests/data/test13142
-rw-r--r--tests/data/test13191
-rw-r--r--tests/data/test13201
-rw-r--r--tests/data/test13211
-rw-r--r--tests/data/test13312
-rw-r--r--tests/data/test14001
-rw-r--r--tests/data/test14011
-rw-r--r--tests/data/test14021
-rw-r--r--tests/data/test14031
-rw-r--r--tests/data/test14041
-rw-r--r--tests/data/test14051
-rw-r--r--tests/data/test14061
-rw-r--r--tests/data/test14071
-rw-r--r--tests/data/test14151
-rw-r--r--tests/data/test14201
-rw-r--r--tests/data/test14212
-rw-r--r--tests/data/test14281
-rw-r--r--tests/data/test15091
-rw-r--r--tests/data/test15251
-rw-r--r--tests/data/test15261
-rw-r--r--tests/data/test15271
-rw-r--r--tests/data/test15281
-rw-r--r--tests/data/test153249
-rw-r--r--tests/data/test153374
-rw-r--r--tests/data/test153450
-rw-r--r--tests/data/test161
-rw-r--r--tests/data/test160525
-rw-r--r--tests/data/test1616
-rw-r--r--tests/data/test1621
-rw-r--r--tests/data/test16511
-rw-r--r--tests/data/test1672
-rw-r--r--tests/data/test1683
-rw-r--r--tests/data/test1693
-rw-r--r--tests/data/test1701
-rw-r--r--tests/data/test1711
-rw-r--r--tests/data/test1791
-rw-r--r--tests/data/test18002
-rw-r--r--tests/data/test18012
-rw-r--r--tests/data/test1832
-rw-r--r--tests/data/test1842
-rw-r--r--tests/data/test1852
-rw-r--r--tests/data/test20454
-rw-r--r--tests/data/test20472
-rw-r--r--tests/data/test20482
-rw-r--r--tests/data/test20501
-rw-r--r--tests/data/test2062
-rw-r--r--tests/data/test2081
-rw-r--r--tests/data/test2092
-rw-r--r--tests/data/test2132
-rw-r--r--tests/data/test2171
-rw-r--r--tests/data/test21937
-rw-r--r--tests/data/test2332
-rw-r--r--tests/data/test2342
-rw-r--r--tests/data/test2392
-rw-r--r--tests/data/test2433
-rw-r--r--tests/data/test2561
-rw-r--r--tests/data/test2573
-rw-r--r--tests/data/test2584
-rw-r--r--tests/data/test2592
-rw-r--r--tests/data/test2631
-rw-r--r--tests/data/test2641
-rw-r--r--tests/data/test2652
-rw-r--r--tests/data/test2751
-rw-r--r--tests/data/test2781
-rw-r--r--tests/data/test2791
-rw-r--r--tests/data/test2871
-rw-r--r--tests/data/test2991
-rw-r--r--tests/data/test432
-rw-r--r--tests/data/test51
-rw-r--r--tests/data/test5031
-rw-r--r--tests/data/test50654
-rw-r--r--tests/data/test5176
-rw-r--r--tests/data/test5231
-rw-r--r--tests/data/test5403
-rw-r--r--tests/data/test5473
-rw-r--r--tests/data/test5483
-rw-r--r--tests/data/test5491
-rw-r--r--tests/data/test5501
-rw-r--r--tests/data/test5512
-rw-r--r--tests/data/test552bin142925 -> 142985 bytes
-rw-r--r--tests/data/test5553
-rw-r--r--tests/data/test5584
-rw-r--r--tests/data/test5611
-rw-r--r--tests/data/test5631
-rw-r--r--tests/data/test5903
-rw-r--r--tests/data/test631
-rw-r--r--tests/data/test791
-rw-r--r--tests/data/test801
-rw-r--r--tests/data/test812
-rw-r--r--tests/data/test821
-rw-r--r--tests/data/test831
-rw-r--r--tests/data/test841
-rw-r--r--tests/data/test851
-rw-r--r--tests/data/test8642
-rw-r--r--tests/data/test931
-rw-r--r--tests/data/test941
-rw-r--r--tests/data/test951
-rwxr-xr-xtests/ftpserver.pl10
-rw-r--r--tests/libtest/CMakeLists.txt4
-rw-r--r--tests/libtest/Makefile.inc15
-rw-r--r--tests/libtest/lib1500.c4
-rw-r--r--tests/libtest/lib1502.c4
-rw-r--r--tests/libtest/lib1507.c2
-rw-r--r--tests/libtest/lib1511.c4
-rw-r--r--tests/libtest/lib1515.c2
-rw-r--r--tests/libtest/lib1532.c80
-rw-r--r--tests/libtest/lib1533.c199
-rw-r--r--tests/libtest/lib1534.c129
-rw-r--r--tests/libtest/lib507.c6
-rw-r--r--tests/libtest/lib517.c8
-rw-r--r--tests/libtest/lib539.c4
-rw-r--r--tests/libtest/lib540.c4
-rw-r--r--tests/libtest/lib543.c2
-rw-r--r--tests/libtest/lib552.c2
-rw-r--r--tests/libtest/lib557.c104
-rw-r--r--tests/libtest/lib571.c3
-rw-r--r--tests/libtest/lib582.c4
-rw-r--r--tests/libtest/lib583.c6
-rw-r--r--tests/libtest/libauthretry.c9
-rw-r--r--tests/libtest/libntlmconnect.c4
-rw-r--r--tests/libtest/test.h2
-rw-r--r--tests/pathhelp.pm2
-rw-r--r--tests/server/Makefile.inc2
-rw-r--r--tests/server/rtspd.c6
-rw-r--r--tests/server/sws.c12
-rw-r--r--tests/server/tftpd.c18
-rw-r--r--tests/server/util.c84
-rw-r--r--tests/server/util.h4
-rw-r--r--tests/testcurl.110
-rw-r--r--tests/unit/CMakeLists.txt14
-rw-r--r--tests/unit/Makefile.am2
-rw-r--r--tests/unit/Makefile.inc4
-rw-r--r--tests/unit/unit1301.c2
-rw-r--r--tests/unit/unit1303.c41
-rw-r--r--tests/unit/unit1304.c2
-rw-r--r--tests/unit/unit1308.c6
-rw-r--r--tests/unit/unit1602.c2
-rw-r--r--tests/unit/unit1604.c6
-rw-r--r--tests/unit/unit1605.c (renamed from lib/strequal.h)32
-rw-r--r--winbuild/Makefile.vc47
-rw-r--r--winbuild/MakefileBuild.vc52
615 files changed, 13909 insertions, 6537 deletions
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index d4f580bd..bce89b44 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -8,7 +8,7 @@ Join the community
2. Subscribe to the suitable [mailing lists](https://curl.haxx.se/mail/)
-Read [CONTRIBUTE](../docs/CONTRIBUTE)
+Read [CONTRIBUTE](../docs/CONTRIBUTE.md)
---------------------------------------
Send your suggestions using one of these methods:
@@ -20,4 +20,4 @@ Send your suggestions using one of these methods:
3. as an [issue](https://github.com/curl/curl/issues)
-/ The cURL team!
+/ The curl team!
diff --git a/.travis.yml b/.travis.yml
index 49e3f15a..bdd21b09 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,7 +8,7 @@ language: c
install:
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update > /dev/null; fi
- - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew reinstall -s libtool > /dev/null; fi
+ - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew reinstall libtool > /dev/null; fi
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install openssl libidn rtmpdump libssh2 c-ares libmetalink libressl nghttp2; fi
before_script:
diff --git a/Android.bp b/Android.bp
index 7b791852..29426a7d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -40,6 +40,7 @@ cc_library {
"-DBUILDING_LIBCURL",
],
srcs:[
+ "lib/rand.c",
"lib/file.c",
"lib/timeval.c",
"lib/base64.c",
@@ -63,7 +64,6 @@ cc_library {
"lib/netrc.c",
"lib/getinfo.c",
"lib/transfer.c",
- "lib/strequal.c",
"lib/easy.c",
"lib/security.c",
"lib/curl_fnmatch.c",
@@ -97,10 +97,10 @@ cc_library {
"lib/select.c",
"lib/tftp.c",
"lib/splay.c",
+ "lib/strcase.c",
"lib/strdup.c",
"lib/socks.c",
"lib/ssh.c",
- "lib/rawstr.c",
"lib/curl_addrinfo.c",
"lib/socks_gssapi.c",
"lib/socks_sspi.c",
diff --git a/CMake/CurlSymbolHiding.cmake b/CMake/CurlSymbolHiding.cmake
new file mode 100644
index 00000000..9f7d2963
--- /dev/null
+++ b/CMake/CurlSymbolHiding.cmake
@@ -0,0 +1,61 @@
+include(CheckCSourceCompiles)
+
+option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide all symbols that aren't officially external)." ON)
+mark_as_advanced(CURL_HIDDEN_SYMBOLS)
+
+if(CURL_HIDDEN_SYMBOLS)
+ set(SUPPORTS_SYMBOL_HIDING FALSE)
+
+ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ set(SUPPORTS_SYMBOL_HIDING TRUE)
+ set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
+ set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
+ elseif(CMAKE_COMPILER_IS_GNUCC)
+ if(NOT CMAKE_VERSION VERSION_LESS 2.8.10)
+ set(GCC_VERSION ${CMAKE_C_COMPILER_VERSION})
+ else()
+ execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
+ OUTPUT_VARIABLE GCC_VERSION)
+ endif()
+ if(NOT GCC_VERSION VERSION_LESS 3.4)
+ # note: this is considered buggy prior to 4.0 but the autotools don't care, so let's ignore that fact
+ set(SUPPORTS_SYMBOL_HIDING TRUE)
+ set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
+ set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
+ endif()
+ elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.0)
+ set(SUPPORTS_SYMBOL_HIDING TRUE)
+ set(_SYMBOL_EXTERN "__global")
+ set(_CFLAG_SYMBOLS_HIDE "-xldscope=hidden")
+ elseif(CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.0)
+ # note: this should probably just check for version 9.1.045 but I'm not 100% sure
+ # so let's to it the same way autotools do.
+ set(SUPPORTS_SYMBOL_HIDING TRUE)
+ set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
+ set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
+ check_c_source_compiles("#include <stdio.h>
+ int main (void) { printf(\"icc fvisibility bug test\"); return 0; }" _no_bug)
+ if(NOT _no_bug)
+ set(SUPPORTS_SYMBOL_HIDING FALSE)
+ set(_SYMBOL_EXTERN "")
+ set(_CFLAG_SYMBOLS_HIDE "")
+ endif()
+ elseif(MSVC)
+ set(SUPPORTS_SYMBOL_HIDING TRUE)
+ endif()
+
+ set(HIDES_CURL_PRIVATE_SYMBOLS ${SUPPORTS_SYMBOL_HIDING})
+elseif(MSVC)
+ if(NOT CMAKE_VERSION VERSION_LESS 3.7)
+ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) #present since 3.4.3 but broken
+ set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
+ else()
+ message(WARNING "Hiding private symbols regardless CURL_HIDDEN_SYMBOLS being disabled.")
+ set(HIDES_CURL_PRIVATE_SYMBOLS TRUE)
+ endif()
+elseif()
+ set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
+endif()
+
+set(CURL_CFLAG_SYMBOLS_HIDE ${_CFLAG_SYMBOLS_HIDE})
+set(CURL_EXTERN_SYMBOL ${_SYMBOL_EXTERN})
diff --git a/CMake/FindNGHTTP2.cmake b/CMake/FindNGHTTP2.cmake
new file mode 100644
index 00000000..4e566cf0
--- /dev/null
+++ b/CMake/FindNGHTTP2.cmake
@@ -0,0 +1,18 @@
+include(FindPackageHandleStandardArgs)
+
+find_path(NGHTTP2_INCLUDE_DIR "nghttp2/nghttp2.h")
+
+find_library(NGHTTP2_LIBRARY NAMES nghttp2)
+
+find_package_handle_standard_args(NGHTTP2
+ FOUND_VAR
+ NGHTTP2_FOUND
+ REQUIRED_VARS
+ NGHTTP2_LIBRARY
+ NGHTTP2_INCLUDE_DIR
+ FAIL_MESSAGE
+ "Could NOT find NGHTTP2"
+)
+
+set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR} )
+set(NGHTTP2_LIBRARIES ${NGHTTP2_LIBRARY})
diff --git a/CMake/OtherTests.cmake b/CMake/OtherTests.cmake
index d5994987..3b203c53 100644
--- a/CMake/OtherTests.cmake
+++ b/CMake/OtherTests.cmake
@@ -179,17 +179,20 @@ int main(void) {
include(CheckCSourceRuns)
-set(CMAKE_REQUIRED_FLAGS)
-if(HAVE_SYS_POLL_H)
- set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
-endif(HAVE_SYS_POLL_H)
-check_c_source_runs("
- #ifdef HAVE_SYS_POLL_H
- # include <sys/poll.h>
- #endif
- int main(void) {
- return poll((void *)0, 0, 10 /*ms*/);
- }" HAVE_POLL_FINE)
+# See HAVE_POLL in CMakeLists.txt for why poll is disabled on macOS
+if(NOT APPLE)
+ set(CMAKE_REQUIRED_FLAGS)
+ if(HAVE_SYS_POLL_H)
+ set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
+ endif(HAVE_SYS_POLL_H)
+ check_c_source_runs("
+ #ifdef HAVE_SYS_POLL_H
+ # include <sys/poll.h>
+ #endif
+ int main(void) {
+ return poll((void *)0, 0, 10 /*ms*/);
+ }" HAVE_POLL_FINE)
+endif()
set(HAVE_SIG_ATOMIC_T 1)
set(CMAKE_REQUIRED_FLAGS)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7f7c4d6d..a6a73689 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -19,7 +19,7 @@
# KIND, either express or implied.
#
###########################################################################
-# cURL/libcurl CMake script
+# curl/libcurl CMake script
# by Tetetest and Sukender (Benoit Neil)
# TODO:
@@ -42,6 +42,7 @@ cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
include(Utilities)
include(Macros)
+include(CMakeDependentOption)
project( CURL C )
@@ -71,11 +72,17 @@ set(OS "\"${CMAKE_SYSTEM_NAME}\"")
include_directories(${PROJECT_BINARY_DIR}/include/curl)
include_directories( ${CURL_SOURCE_DIR}/include )
-option(BUILD_CURL_EXE "Set to ON to build cURL executable." ON)
+option(BUILD_CURL_EXE "Set to ON to build curl executable." ON)
option(CURL_STATICLIB "Set to ON to build libcurl with static linking." OFF)
option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
-option(ENABLE_THREADED_RESOLVER "Set to ON to enable POSIX threaded DNS lookup" OFF)
-
+if(WIN32)
+ CMAKE_DEPENDENT_OPTION(ENABLE_THREADED_RESOLVER
+ "Set to ON to enable threaded DNS lookup"
+ ON "NOT ENABLE_ARES"
+ OFF)
+else()
+ option(ENABLE_THREADED_RESOLVER "Set to ON to enable POSIX threaded DNS lookup" OFF)
+endif()
option(ENABLE_DEBUG "Set to ON to enable curl debug features" OFF)
option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" OFF)
@@ -112,8 +119,7 @@ if(MSVC)
mark_as_advanced(BUILD_RELEASE_DEBUG_DIRS)
endif()
-option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide all symbols that aren't officially external)." ON)
-mark_as_advanced(CURL_HIDDEN_SYMBOLS)
+include(CurlSymbolHiding)
option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" OFF)
mark_as_advanced(HTTP_ONLY)
@@ -250,13 +256,17 @@ if(WIN32)
endif(WIN32)
if(ENABLE_THREADED_RESOLVER)
- check_include_file_concat("pthread.h" HAVE_PTHREAD_H)
- if(HAVE_PTHREAD_H)
- set(CMAKE_THREAD_PREFER_PTHREAD 1)
- find_package(Threads)
- if(CMAKE_USE_PTHREADS_INIT)
- set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
- set(USE_THREADS_POSIX 1)
+ if(WIN32)
+ set(USE_THREADS_WIN32 ON)
+ else()
+ check_include_file_concat("pthread.h" HAVE_PTHREAD_H)
+ if(HAVE_PTHREAD_H)
+ set(CMAKE_THREAD_PREFER_PTHREAD 1)
+ find_package(Threads)
+ if(CMAKE_USE_PTHREADS_INIT)
+ set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
+ set(USE_THREADS_POSIX 1)
+ endif()
endif()
endif()
endif()
@@ -322,6 +332,13 @@ if(CMAKE_USE_OPENSSL)
endif()
endif()
+option(USE_NGHTTP2 "Use Nghttp2 library" OFF)
+if(USE_NGHTTP2)
+ find_package(NGHTTP2 REQUIRED)
+ include_directories(${NGHTTP2_INCLUDE_DIRS})
+ list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES})
+endif()
+
if(NOT CURL_DISABLE_LDAP)
if(WIN32)
option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON)
@@ -432,12 +449,12 @@ if(NOT CURL_DISABLE_LDAPS)
endif()
# Check for idn
-check_library_exists_concat("idn" idna_to_ascii_lz HAVE_LIBIDN)
+check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2)
# Check for symbol dlopen (same as HAVE_LIBDL)
check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN)
-option(CURL_ZLIB "Set to ON to enable building cURL with zlib support." ON)
+option(CURL_ZLIB "Set to ON to enable building curl with zlib support." ON)
set(HAVE_LIBZ OFF)
set(HAVE_ZLIB_H OFF)
set(HAVE_ZLIB OFF)
@@ -601,7 +618,7 @@ check_include_file_concat("des.h" HAVE_DES_H)
check_include_file_concat("err.h" HAVE_ERR_H)
check_include_file_concat("errno.h" HAVE_ERRNO_H)
check_include_file_concat("fcntl.h" HAVE_FCNTL_H)
-check_include_file_concat("idn-free.h" HAVE_IDN_FREE_H)
+check_include_file_concat("idn2.h" HAVE_IDN2_H)
check_include_file_concat("ifaddrs.h" HAVE_IFADDRS_H)
check_include_file_concat("io.h" HAVE_IO_H)
check_include_file_concat("krb.h" HAVE_KRB_H)
@@ -631,7 +648,6 @@ check_include_file_concat("stropts.h" HAVE_STROPTS_H)
check_include_file_concat("termio.h" HAVE_TERMIO_H)
check_include_file_concat("termios.h" HAVE_TERMIOS_H)
check_include_file_concat("time.h" HAVE_TIME_H)
-check_include_file_concat("tld.h" HAVE_TLD_H)
check_include_file_concat("unistd.h" HAVE_UNISTD_H)
check_include_file_concat("utime.h" HAVE_UTIME_H)
check_include_file_concat("x509.h" HAVE_X509_H)
@@ -645,9 +661,6 @@ check_include_file_concat("netinet/if_ether.h" HAVE_NETINET_IF_ETHER_H)
check_include_file_concat("stdint.h" HAVE_STDINT_H)
check_include_file_concat("sockio.h" HAVE_SOCKIO_H)
check_include_file_concat("sys/utsname.h" HAVE_SYS_UTSNAME_H)
-check_include_file_concat("idna.h" HAVE_IDNA_H)
-
-
check_type_size(size_t SIZEOF_SIZE_T)
check_type_size(ssize_t SIZEOF_SSIZE_T)
@@ -666,6 +679,7 @@ if(NOT HAVE_SIZEOF_SSIZE_T)
set(ssize_t __int64)
endif(NOT ssize_t AND SIZEOF___INT64 EQUAL SIZEOF_SIZE_T)
endif(NOT HAVE_SIZEOF_SSIZE_T)
+# off_t is sized later, after the HAVE_FILE_OFFSET_BITS test
# Different sizeofs, etc.
@@ -728,7 +742,11 @@ endif()
check_symbol_exists(basename "${CURL_INCLUDES}" HAVE_BASENAME)
check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET)
-check_symbol_exists(poll "${CURL_INCLUDES}" HAVE_POLL)
+# poll on macOS is unreliable, it first did not exist, then was broken until
+# fixed in 10.9 only to break again in 10.12.
+if(NOT APPLE)
+ check_symbol_exists(poll "${CURL_INCLUDES}" HAVE_POLL)
+endif()
check_symbol_exists(select "${CURL_INCLUDES}" HAVE_SELECT)
check_symbol_exists(strdup "${CURL_INCLUDES}" HAVE_STRDUP)
check_symbol_exists(strstr "${CURL_INCLUDES}" HAVE_STRSTR)
@@ -764,8 +782,6 @@ if(CMAKE_USE_OPENSSL)
check_symbol_exists(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS)
check_symbol_exists(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN)
check_symbol_exists(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD)
- check_symbol_exists(CRYPTO_cleanup_all_ex_data "${CURL_INCLUDES}"
- HAVE_CRYPTO_CLEANUP_ALL_EX_DATA)
if(HAVE_LIBCRYPTO AND HAVE_LIBSSL)
set(USE_OPENSSL 1)
endif(HAVE_LIBCRYPTO AND HAVE_LIBSSL)
@@ -795,9 +811,6 @@ check_symbol_exists(pipe "${CURL_INCLUDES}" HAVE_PIPE)
check_symbol_exists(ftruncate "${CURL_INCLUDES}" HAVE_FTRUNCATE)
check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME)
check_symbol_exists(getrlimit "${CURL_INCLUDES}" HAVE_GETRLIMIT)
-check_symbol_exists(idn_free "${CURL_INCLUDES}" HAVE_IDN_FREE)
-check_symbol_exists(idna_strerror "${CURL_INCLUDES}" HAVE_IDNA_STRERROR)
-check_symbol_exists(tld_strerror "${CURL_INCLUDES}" HAVE_TLD_STRERROR)
check_symbol_exists(setlocale "${CURL_INCLUDES}" HAVE_SETLOCALE)
check_symbol_exists(setrlimit "${CURL_INCLUDES}" HAVE_SETRLIMIT)
check_symbol_exists(fcntl "${CURL_INCLUDES}" HAVE_FCNTL)
@@ -864,9 +877,14 @@ foreach(CURL_TEST
)
curl_internal_test(${CURL_TEST})
endforeach(CURL_TEST)
+
if(HAVE_FILE_OFFSET_BITS)
set(_FILE_OFFSET_BITS 64)
+ set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64")
endif(HAVE_FILE_OFFSET_BITS)
+check_type_size("off_t" SIZEOF_OFF_T)
+set(CMAKE_REQUIRED_FLAGS)
+
foreach(CURL_TEST
HAVE_GLIBC_STRERROR_R
HAVE_POSIX_STRERROR_R
@@ -928,16 +946,6 @@ if(NOT CURL_SPECIAL_LIBZ)
endif(NOT HAVE_ZLIB_H)
endif(NOT CURL_SPECIAL_LIBZ)
-if(_FILE_OFFSET_BITS)
- set(_FILE_OFFSET_BITS 64)
-endif(_FILE_OFFSET_BITS)
-set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64")
-set(CMAKE_EXTRA_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/curl/curl.h")
-check_type_size("curl_off_t" SIZEOF_CURL_OFF_T)
-set(CMAKE_EXTRA_INCLUDE_FILES)
-set(CMAKE_REQUIRED_FLAGS)
-
-
# Check for nonblocking
set(HAVE_DISABLED_NONBLOCKING 1)
if(HAVE_FIONBIO OR
@@ -1010,6 +1018,11 @@ if(WIN32)
add_definitions(-D_WIN32_WINNT=0x0501)
endif(WIN32)
+# For windows, all compilers used by cmake should support large files
+if(WIN32)
+ set(USE_WIN32_LARGE_FILES ON)
+endif(WIN32)
+
if(MSVC)
add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
endif(MSVC)
@@ -1061,8 +1074,10 @@ _add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL)
_add_if("IPv6" ENABLE_IPV6)
_add_if("unix-sockets" USE_UNIX_SOCKETS)
_add_if("libz" HAVE_LIBZ)
-_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX)
-_add_if("IDN" HAVE_LIBIDN)
+_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32)
+_add_if("IDN" HAVE_LIBIDN2)
+_add_if("Largefile" (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND
+ ((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES))
# TODO SSP1 (WinSSL) check is missing
_add_if("SSPI" USE_WINDOWS_SSPI)
_add_if("GSS-API" HAVE_GSSAPI)
@@ -1128,9 +1143,7 @@ set(CURL_CA_BUNDLE "")
set(CURLVERSION "${CURL_VERSION}")
set(ENABLE_SHARED "yes")
if(CURL_STATICLIB)
- # Broken: LIBCURL_LIBS below; .a lib is not built
- message(WARNING "Static linking is broken!")
- set(ENABLE_STATIC "no")
+ set(ENABLE_STATIC "yes")
else()
set(ENABLE_STATIC "no")
endif()
@@ -1139,9 +1152,12 @@ set(includedir "\${prefix}/include")
set(LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
set(LIBCURL_LIBS "")
set(libdir "${CMAKE_INSTALL_PREFIX}/lib")
-# TODO CURL_LIBS also contains absolute paths which don't work with static -l...
foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS})
- set(LIBCURL_LIBS "${LIBCURL_LIBS} -l${_lib}")
+ if(_lib MATCHES ".*/.*")
+ set(LIBCURL_LIBS "${LIBCURL_LIBS} ${_lib}")
+ else()
+ set(LIBCURL_LIBS "${LIBCURL_LIBS} -l${_lib}")
+ endif()
endforeach()
# "a" (Linux) or "lib" (Windows)
string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}")
diff --git a/GIT-INFO b/GIT-INFO
index 16f4a220..6b703fef 100644
--- a/GIT-INFO
+++ b/GIT-INFO
@@ -51,17 +51,3 @@ installed:
install them, you can rename the source file src/tool_hugehelp.c.cvs to
src/tool_hugehelp.c and avoid having to generate this file. This will
give you a stubbed version of the file that doesn't contain actual content.
-
-MAC OS X
-
- With Mac OS X 10.2 and the associated Developer Tools, the installed versions
- of the build tools are adequate. For Mac OS X 10.1 users, Guido Neitzer
- wrote the following step-by-step guide:
-
- 1. Install fink (http://fink.sourceforge.net)
- 2. Update fink to the newest version (with the installed fink)
- 3. Install the latest version of autoconf, automake and m4 with fink
- 4. Install version 1.4.1 of libtool - you find it in the "unstable" section
- (read the manual to see how to get unstable versions)
- 5. Get cURL from git
- 6. Build cURL with "./buildconf", "./configure", "make", "sudo make install"
diff --git a/Makefile.am b/Makefile.am
index 2986acf6..f86ffbca 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,10 +24,13 @@ AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4
-CMAKE_DIST = CMakeLists.txt CMake/CMakeConfigurableFile.in \
- CMake/CurlTests.c CMake/FindGSS.cmake CMake/OtherTests.cmake \
- CMake/Platforms/WindowsCache.cmake CMake/Utilities.cmake \
- include/curl/curlbuild.h.cmake CMake/Macros.cmake
+CMAKE_DIST = CMakeLists.txt CMake/CMakeConfigurableFile.in \
+ CMake/CurlTests.c CMake/FindGSS.cmake CMake/OtherTests.cmake \
+ CMake/Platforms/WindowsCache.cmake CMake/Utilities.cmake \
+ include/curl/curlbuild.h.cmake CMake/Macros.cmake \
+ CMake/CurlSymbolHiding.cmake CMake/FindCARES.cmake \
+ CMake/FindLibSSH2.cmake CMake/FindNGHTTP2.cmake
+
VC6_LIBTMPL = projects/Windows/VC6/lib/libcurl.tmpl
VC6_LIBDSP = projects/Windows/VC6/lib/libcurl.dsp.dist
diff --git a/README.md b/README.md
index 64883dc9..567d6d1d 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
![curl logo](https://cdn.rawgit.com/curl/curl-www/master/logo/curl-logo.svg)
+[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/63/badge)](https://bestpractices.coreinfrastructure.org/projects/63)
Curl is a command-line tool for transferring data specified with URL
syntax. Find out how to use curl by reading [the curl.1 man
diff --git a/README.version b/README.version
index 41ae42b1..9c2568fd 100644
--- a/README.version
+++ b/README.version
@@ -1,6 +1,6 @@
-URL: https://curl.haxx.se/download/curl-7.50.1.tar.gz
-Version: 7.50.1
-Upstream commit: f2cb3a01192d36395d16acec6cdb93446ca6fd45
+URL: https://curl.haxx.se/download/curl-7.54.1.tar.gz
+Version: 7.54.1
+Upstream commit: 54b636f14546d3fde9f9c67c3b32701d78563161
License: MIT
License File: NOTICE
BugComponent: 31714
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 163ceb1a..f5d172f7 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -1,26 +1,52 @@
-Curl and libcurl 7.50.1
+Curl and libcurl 7.52.0
- Public curl releases: 157
- Command line options: 185
- curl_easy_setopt() options: 224
+ Public curl releases: 161
+ Command line options: 205
+ curl_easy_setopt() options: 243
Public functions in libcurl: 61
- Contributors: 1418
+ Contributors: 1467
+
+This release includes the following changes:
+
+ o nss: map CURL_SSLVERSION_DEFAULT to NSS default
+ o vtls: support TLS 1.3 via CURL_SSLVERSION_TLSv1_3
+ o curl: introduce the --tlsv1.3 option to force TLS 1.3
+ o curl: Add --retry-connrefused [11]
+ o proxy: Support HTTPS proxy and SOCKS+HTTP(s)
This release includes the following bugfixes:
- o TLS: switch off SSL session id when client cert is used [7]
- o TLS: only reuse connections with the same client cert [8]
- o curl_multi_cleanup: clear connection pointer for easy handles [9]
- o include the CURLINFO_HTTP_VERSION(3) man page into the release tarball
- o include the http2-server.pl script in the release tarball
- o test558: fix test by stripping file paths from FD lines
- o spnego: Corrected miss-placed * in Curl_auth_spnego_cleanup() declaration
- o tests: Fix for http/2 feature [1]
- o cmake: Fix for schannel support [2]
- o curl.h: make public types void * again [3]
- o win32: fix a potential memory leak in Curl_load_library [4]
- o travis: fix OSX build by re-installing libtool [5]
- o mbedtls: Fix debug function name [6]
+ o msvc: removed a straggling reference to strequal.c
+ o winbuild: remove strcase.obj from curl build [1]
+ o examples: bugfixed multi-uv.c
+ o configure: verify that compiler groks -Werror=partial-availability [2]
+ o mbedtls: fix build with mbedtls versions < 2.4.0 [3]
+ o dist: add unit test CMakeLists.txt to the tarball
+ o curl -w: added more decimal digits to timing counters [4]
+ o easy: Initialize info variables on easy init and duphandle [5]
+ o cmake: disable poll for macOS [6]
+ o http2: Don't send header fields prohibited by HTTP/2 spec [7]
+ o ssh: check md5 fingerprints case insensitively (regression) [8]
+ o openssl: initial TLS 1.3 adaptions
+ o curl_formadd.3: *_FILECONTENT and *_FILE need the file to be kept
+ o printf: fix ".*f" handling [9]
+ o examples/fileupload.c: fclose the file as well
+ o SPNEGO: Fix memory leak when authentication fails [10]
+ o realloc: use Curl_saferealloc to avoid common mistakes [12]
+ o openssl: make sure to fail in the unlikely event that PRNG seeding fails
+ o URL-parser: for file://[host]/ URLs, the [host] must be localhost [13]
+ o timeval: prefer time_t to hold seconds instead of long
+ o Curl_rand: fixed and moved to rand.c [14]
+ o curl: add --fail-early [15]
+ o glob: fix [a-c] globbing regression [16]
+ o darwinssl: fix SSL client certificate not found on MacOS Sierra [17]
+ o curl.1: Clarify --dump-header only writes received headers
+ o http2: Fix address sanitizer memcpy warning
+ o http2: Use huge HTTP/2 windows [18]
+ o connects: Don't mix unix domain sockets with regular ones
+ o url: Fix conn reuse for local ports and interfaces [19]
+ o x509: Limit ASN.1 structure sizes to 256K
+ o checksrc: add more checks
This release includes the following known bugs:
@@ -29,22 +55,35 @@ This release includes the following known bugs:
This release would not have looked like this without help, code, reports and
advice from friends like these:
- Alain Danteny, Bru Rom, Dan Fandrich, Daniel Stenberg, Eric Rescorla,
- Fernando Muñoz, Kamil Dudka, Marcelo Echeverria, Martin Vejnár,
- Patrick Monnerat, Paul Howarth, Peter Frühberger, Ray Satiro, Sergei Nikulov,
- Steve Holme, Thomas Glanzmann, Viktor Szakáts, Yonggang Luo,
- (18 contributors)
+ Adam Piggott, afrind on github, Alex Chan, Alex Rousskov, Andrei Sedoi,
+ Bruce Stephens, Dan Fandrich, Daniel Hwang, Daniel Stenberg, Dave Reisner,
+ David Schweikert, Dmitry Kurochkin, Frank Gevaerts, Isaac Boukris,
+ Jakub Zakrzewski, Kamil Dudka, Marcel Raad, Mauro Rappa, Mike Crowe,
+ Neal Poole, Nick Zitzmann, Okhin Vasilij, Patrick Monnerat, Peter Wu,
+ Ray Satiro, Ricki Hirner, Tatsuhiro Tsujikawa, Thomas Glanzmann, Tony Kelman,
+ Vasy Okhin,
+ (30 contributors)
Thanks! (and sorry if I forgot to mention someone)
References to bug reports and discussions on issues:
- [1] = https://curl.haxx.se/mail/lib-2016-07/0070.html
- [2] = https://curl.haxx.se/bug/?i=917
- [3] = https://curl.haxx.se/bug/?i=926
- [4] = https://curl.haxx.se/bug/?i=938
- [5] = https://curl.haxx.se/bug/?i=939
- [6] = https://curl.haxx.se/mail/lib-2016-08/0001.html
- [7] = https://curl.haxx.se/docs/adv_20160803A.html
- [8] = https://curl.haxx.se/docs/adv_20160803B.html
- [9] = https://curl.haxx.se/docs/adv_20160803C.html
+ [1] = https://curl.haxx.se/bug/?i=1098
+ [2] = https://curl.haxx.se/bug/?i=1104
+ [3] = https://curl.haxx.se/bug/?i=1087
+ [4] = https://curl.haxx.se/bug/?i=1106
+ [5] = https://curl.haxx.se/bug/?i=1103
+ [6] = https://curl.haxx.se/bug/?i=1089
+ [7] = https://curl.haxx.se/bug/?i=1092
+ [8] = https://github.com/curl/curl/commit/ce8d09483eea2fcb1b50e323e1a8ed1f3613b2e3#commitcomment-19666146
+ [9] = https://curl.haxx.se/bug/?i=1113
+ [10] = https://curl.haxx.se/bug/?i=1115
+ [11] = https://curl.haxx.se/bug/?i=1064
+ [12] = https://curl.haxx.se/mail/lib-2016-11/0087.html
+ [13] = https://curl.haxx.se/mail/lib-2016-11/0104.html
+ [14] = https://curl.haxx.se/mail/lib-2016-11/0119.html
+ [15] = https://curl.haxx.se/mail/archive-2016-11/0038.html
+ [16] = https://github.com/curl/curl/commit/ee4f76606cfa4ee068bf28edd37c8dae7e8db317#commitcomment-19823146
+ [17] = https://curl.haxx.se/bug/?i=1105
+ [18] = https://curl.haxx.se/bug/?i=1102
+ [19] = https://curl.haxx.se/mail/lib-2016-11/0137.html
diff --git a/acinclude.m4 b/acinclude.m4
index fa621b5b..2abae8d8 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -32,8 +32,8 @@ dnl actually be a single double-quoted string concatenating all them.
AC_DEFUN([CURL_CHECK_DEF], [
AC_REQUIRE([CURL_CPP_P])dnl
OLDCPPFLAGS=$CPPFLAGS
- # CPPPFLAGS comes from CURL_CPP_P
- CPPFLAGS="$CPPPFLAGS"
+ # CPPPFLAG comes from CURL_CPP_P
+ CPPFLAGS="$CPPFLAGS $CPPPFLAG"
AS_VAR_PUSHDEF([ac_HaveDef], [curl_cv_have_def_$1])dnl
AS_VAR_PUSHDEF([ac_Def], [curl_cv_def_$1])dnl
if test -z "$SED"; then
@@ -1856,7 +1856,7 @@ AC_DEFUN([CURL_CHECK_FUNC_CLOCK_GETTIME_MONOTONIC], [
AC_CHECK_HEADERS(sys/types.h sys/time.h time.h)
AC_MSG_CHECKING([for monotonic clock_gettime])
#
- if test "x$dontwant_rt" == "xno" ; then
+ if test "x$dontwant_rt" = "xno" ; then
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
#ifdef HAVE_SYS_TYPES_H
@@ -3187,12 +3187,59 @@ TEST EINVAL TEST
if test "x$cpp_p" = "xno"; then
AC_MSG_WARN([failed to figure out cpp -P alternative])
# without -P
- CPPPFLAGS=$OLDCPPFLAGS
+ CPPPFLAG=""
else
# with -P
- CPPPFLAGS=$CPPFLAGS
+ CPPPFLAG="-P"
fi
dnl restore CPPFLAGS
CPPFLAGS=$OLDCPPFLAGS
+ else
+ # without -P
+ CPPPFLAG=""
+ fi
+])
+
+
+dnl CURL_MAC_CFLAGS
+dnl
+dnl Check if -mmacosx-version-min, -miphoneos-version-min or any
+dnl similar are set manually, otherwise do. And set
+dnl -Werror=partial-availability.
+dnl
+
+AC_DEFUN([CURL_MAC_CFLAGS], [
+
+ tst_cflags="no"
+ case $host_os in
+ darwin*)
+ tst_cflags="yes"
+ ;;
+ esac
+
+ AC_MSG_CHECKING([for good-to-use Mac CFLAGS])
+ AC_MSG_RESULT([$tst_cflags]);
+
+ if test "$tst_cflags" = "yes"; then
+ AC_MSG_CHECKING([for *version-min in CFLAGS])
+ min=""
+ if test -z "$(echo $CFLAGS | grep m.*os.*-version-min)"; then
+ min="-mmacosx-version-min=10.8"
+ CFLAGS="$CFLAGS $min"
+ fi
+ if test -z "$min"; then
+ AC_MSG_RESULT([set by user])
+ else
+ AC_MSG_RESULT([$min set])
+ fi
+
+ old_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS -Werror=partial-availability"
+ AC_MSG_CHECKING([whether $CC accepts -Werror=partial-availability])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])
+ CFLAGS=$old_CFLAGS])
fi
+
])
diff --git a/configure.ac b/configure.ac
index ec3d22a4..e2ef8020 100644
--- a/configure.ac
+++ b/configure.ac
@@ -141,7 +141,7 @@ AC_SUBST(VERSIONNUM)
dnl Solaris pkgadd support definitions
PKGADD_PKG="HAXXcurl"
-PKGADD_NAME="cURL - a client that groks URLs"
+PKGADD_NAME="curl - a client that groks URLs"
PKGADD_VENDOR="curl.haxx.se"
AC_SUBST(PKGADD_PKG)
AC_SUBST(PKGADD_NAME)
@@ -157,7 +157,7 @@ curl_tls_srp_msg="no (--enable-tls-srp)"
curl_res_msg="default (--enable-ares / --enable-threaded-resolver)"
curl_ipv6_msg="no (--enable-ipv6)"
curl_unix_sockets_msg="no (--enable-unix-sockets)"
- curl_idn_msg="no (--with-{libidn,winidn})"
+ curl_idn_msg="no (--with-{libidn2,winidn})"
curl_manual_msg="no (--enable-manual)"
curl_libcurl_msg="enabled (--disable-libcurl-option)"
curl_verbose_msg="enabled (--disable-verbose)"
@@ -349,6 +349,8 @@ case X-"$curl_cv_native_windows" in
esac
CURL_CHECK_WIN32_LARGEFILE
+CURL_MAC_CFLAGS
+
dnl ************************************************************
dnl switch off particular protocols
dnl
@@ -883,17 +885,30 @@ else
OPT_ZLIB=""
fi
+ CURL_CHECK_PKGCONFIG(zlib)
+
+ if test "$PKGCONFIG" != "no" ; then
+ LIBS="`$PKGCONFIG --libs-only-l zlib` $LIBS"
+ LDFLAGS="`$PKGCONFIG --libs-only-L zlib` $LDFLAGS"
+ CPPFLAGS="`$PKGCONFIG --cflags-only-I zlib` $CPPFLAGS"
+ OPT_ZLIB=""
+ HAVE_LIBZ="1"
+ fi
+
if test -z "$OPT_ZLIB" ; then
- dnl check for the lib first without setting any new path, since many
- dnl people have it in the default path
- AC_CHECK_LIB(z, inflateEnd,
+ if test -z "$HAVE_LIBZ"; then
+
+ dnl Check for the lib without setting any new path, since many
+ dnl people have it in the default path
+
+ AC_CHECK_LIB(z, inflateEnd,
dnl libz found, set the variable
[HAVE_LIBZ="1"
LIBS="-lz $LIBS"],
dnl if no lib found, try /usr/local
[OPT_ZLIB="/usr/local"])
-
+ fi
fi
dnl Add a nonempty path to the compiler flags
@@ -1350,18 +1365,18 @@ fi
OPT_DARWINSSL=no
AC_ARG_WITH(darwinssl,dnl
-AC_HELP_STRING([--with-darwinssl],[enable iOS/Mac OS X native SSL/TLS])
-AC_HELP_STRING([--without-darwinssl], [disable iOS/Mac OS X native SSL/TLS]),
+AC_HELP_STRING([--with-darwinssl],[enable Apple OS native SSL/TLS])
+AC_HELP_STRING([--without-darwinssl], [disable Apple OS native SSL/TLS]),
OPT_DARWINSSL=$withval)
-AC_MSG_CHECKING([whether to enable iOS/Mac OS X native SSL/TLS])
+AC_MSG_CHECKING([whether to enable Apple OS native SSL/TLS])
if test "$curl_ssl_msg" = "$init_ssl_msg"; then
if test "x$OPT_DARWINSSL" != "xno" &&
test -d "/System/Library/Frameworks/Security.framework"; then
AC_MSG_RESULT(yes)
- AC_DEFINE(USE_DARWINSSL, 1, [to enable iOS/Mac OS X native SSL/TLS support])
+ AC_DEFINE(USE_DARWINSSL, 1, [to enable Apple OS native SSL/TLS support])
AC_SUBST(USE_DARWINSSL, [1])
- curl_ssl_msg="enabled (iOS/Mac OS X-native)"
+ curl_ssl_msg="enabled (Apple OS-native)"
DARWINSSL_ENABLED=1
LDFLAGS="$LDFLAGS -framework CoreFoundation -framework Security"
else
@@ -1614,11 +1629,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg" && test X"$OPT_SSL" != Xno; then
dnl SSL_get_shutdown (but this check won't actually detect it there
dnl as it's a macro that needs the header files be included)
- AC_CHECK_FUNCS( RAND_status \
- RAND_screen \
- RAND_egd \
+ AC_CHECK_FUNCS( RAND_egd \
ENGINE_cleanup \
- CRYPTO_cleanup_all_ex_data \
SSL_get_shutdown \
SSLv2_client_method )
@@ -2561,7 +2573,7 @@ if test X"$OPT_LIBSSH2" != Xno; then
DIR_SSH2=${PREFIX_SSH2}/lib$libsuff
fi
- LDFLAGS="$LDFLAGS $LD_SSH2"
+ LDFLAGS="$LD_SSH2 $LDFLAGS"
CPPFLAGS="$CPPFLAGS $CPP_SSH2"
LIBS="$LIB_SSH2 $LIBS"
@@ -2808,15 +2820,15 @@ dnl **********************************************************************
dnl Check for the presence of IDN libraries and headers
dnl **********************************************************************
-AC_MSG_CHECKING([whether to build with libidn])
+AC_MSG_CHECKING([whether to build with libidn2])
OPT_IDN="default"
AC_ARG_WITH(libidn,
-AC_HELP_STRING([--with-libidn=PATH],[Enable libidn usage])
-AC_HELP_STRING([--without-libidn],[Disable libidn usage]),
+AC_HELP_STRING([--with-libidn2=PATH],[Enable libidn2 usage])
+AC_HELP_STRING([--without-libidn2],[Disable libidn2 usage]),
[OPT_IDN=$withval])
case "$OPT_IDN" in
no)
- dnl --without-libidn option used
+ dnl --without-libidn2 option used
want_idn="no"
AC_MSG_RESULT([no])
;;
@@ -2827,13 +2839,13 @@ case "$OPT_IDN" in
AC_MSG_RESULT([(assumed) yes])
;;
yes)
- dnl --with-libidn option used without path
+ dnl --with-libidn2 option used without path
want_idn="yes"
want_idn_path="default"
AC_MSG_RESULT([yes])
;;
*)
- dnl --with-libidn option used with path
+ dnl --with-libidn2 option used with path
want_idn="yes"
want_idn_path="$withval"
AC_MSG_RESULT([yes ($withval)])
@@ -2850,33 +2862,33 @@ if test "$want_idn" = "yes"; then
if test "$want_idn_path" != "default"; then
dnl path has been specified
IDN_PCDIR="$want_idn_path/lib$libsuff/pkgconfig"
- CURL_CHECK_PKGCONFIG(libidn, [$IDN_PCDIR])
+ CURL_CHECK_PKGCONFIG(libidn2, [$IDN_PCDIR])
if test "$PKGCONFIG" != "no"; then
IDN_LIBS=`CURL_EXPORT_PCDIR([$IDN_PCDIR]) dnl
- $PKGCONFIG --libs-only-l libidn 2>/dev/null`
+ $PKGCONFIG --libs-only-l libidn2 2>/dev/null`
IDN_LDFLAGS=`CURL_EXPORT_PCDIR([$IDN_PCDIR]) dnl
- $PKGCONFIG --libs-only-L libidn 2>/dev/null`
+ $PKGCONFIG --libs-only-L libidn2 2>/dev/null`
IDN_CPPFLAGS=`CURL_EXPORT_PCDIR([$IDN_PCDIR]) dnl
- $PKGCONFIG --cflags-only-I libidn 2>/dev/null`
+ $PKGCONFIG --cflags-only-I libidn2 2>/dev/null`
IDN_DIR=`echo $IDN_LDFLAGS | $SED -e 's/-L//'`
else
dnl pkg-config not available or provides no info
- IDN_LIBS="-lidn"
+ IDN_LIBS="-lidn2"
IDN_LDFLAGS="-L$want_idn_path/lib$libsuff"
IDN_CPPFLAGS="-I$want_idn_path/include"
IDN_DIR="$want_idn_path/lib$libsuff"
fi
else
dnl path not specified
- CURL_CHECK_PKGCONFIG(libidn)
+ CURL_CHECK_PKGCONFIG(libidn2)
if test "$PKGCONFIG" != "no"; then
- IDN_LIBS=`$PKGCONFIG --libs-only-l libidn 2>/dev/null`
- IDN_LDFLAGS=`$PKGCONFIG --libs-only-L libidn 2>/dev/null`
- IDN_CPPFLAGS=`$PKGCONFIG --cflags-only-I libidn 2>/dev/null`
+ IDN_LIBS=`$PKGCONFIG --libs-only-l libidn2 2>/dev/null`
+ IDN_LDFLAGS=`$PKGCONFIG --libs-only-L libidn2 2>/dev/null`
+ IDN_CPPFLAGS=`$PKGCONFIG --cflags-only-I libidn2 2>/dev/null`
IDN_DIR=`echo $IDN_LDFLAGS | $SED -e 's/-L//'`
else
dnl pkg-config not available or provides no info
- IDN_LIBS="-lidn"
+ IDN_LIBS="-lidn2"
fi
fi
#
@@ -2896,9 +2908,9 @@ if test "$want_idn" = "yes"; then
LDFLAGS="$IDN_LDFLAGS $LDFLAGS"
LIBS="$IDN_LIBS $LIBS"
#
- AC_MSG_CHECKING([if idna_to_ascii_4i can be linked])
+ AC_MSG_CHECKING([if idn2_lookup_ul can be linked])
AC_LINK_IFELSE([
- AC_LANG_FUNC_LINK_TRY([idna_to_ascii_4i])
+ AC_LANG_FUNC_LINK_TRY([idn2_lookup_ul])
],[
AC_MSG_RESULT([yes])
tst_links_libidn="yes"
@@ -2906,37 +2918,19 @@ if test "$want_idn" = "yes"; then
AC_MSG_RESULT([no])
tst_links_libidn="no"
])
- if test "$tst_links_libidn" = "no"; then
- AC_MSG_CHECKING([if idna_to_ascii_lz can be linked])
- AC_LINK_IFELSE([
- AC_LANG_FUNC_LINK_TRY([idna_to_ascii_lz])
- ],[
- AC_MSG_RESULT([yes])
- tst_links_libidn="yes"
- ],[
- AC_MSG_RESULT([no])
- tst_links_libidn="no"
- ])
- fi
#
+ AC_CHECK_HEADERS( idn2.h )
+
if test "$tst_links_libidn" = "yes"; then
- AC_DEFINE(HAVE_LIBIDN, 1, [Define to 1 if you have the `idn' library (-lidn).])
+ AC_DEFINE(HAVE_LIBIDN2, 1, [Define to 1 if you have the `idn2' library (-lidn2).])
dnl different versions of libidn have different setups of these:
- AC_CHECK_FUNCS( idn_free idna_strerror tld_strerror )
- AC_CHECK_HEADERS( idn-free.h tld.h )
- if test "x$ac_cv_header_tld_h" = "xyes"; then
- AC_SUBST([IDN_ENABLED], [1])
- curl_idn_msg="enabled"
- if test -n "$IDN_DIR" -a "x$cross_compiling" != "xyes"; then
- LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$IDN_DIR"
- export LD_LIBRARY_PATH
- AC_MSG_NOTICE([Added $IDN_DIR to LD_LIBRARY_PATH])
- fi
- else
- AC_MSG_WARN([Libraries for IDN support too old: IDN disabled])
- CPPFLAGS="$clean_CPPFLAGS"
- LDFLAGS="$clean_LDFLAGS"
- LIBS="$clean_LIBS"
+
+ AC_SUBST([IDN_ENABLED], [1])
+ curl_idn_msg="enabled (libidn2)"
+ if test -n "$IDN_DIR" -a "x$cross_compiling" != "xyes"; then
+ LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$IDN_DIR"
+ export LD_LIBRARY_PATH
+ AC_MSG_NOTICE([Added $IDN_DIR to LD_LIBRARY_PATH])
fi
else
AC_MSG_WARN([Cannot find libraries for IDN support: IDN disabled])
@@ -3683,8 +3677,8 @@ fi
if test "x$CURL_DISABLE_CRYPTO_AUTH" != "x1"; then
if test "x$OPENSSL_ENABLED" = "x1" -o "x$USE_WINDOWS_SSPI" = "x1" \
- -o "x$GNUTLS_ENABLED" = "x1" -o "x$NSS_ENABLED" = "x1" \
- -o "x$DARWINSSL_ENABLED" = "x1"; then
+ -o "x$GNUTLS_ENABLED" = "x1" -o "x$MBEDTLS_ENABLED" = "x1" \
+ -o "x$NSS_ENABLED" = "x1" -o "x$DARWINSSL_ENABLED" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES NTLM"
if test "x$CURL_DISABLE_HTTP" != "x1" -a \
@@ -3756,8 +3750,8 @@ fi
if test "x$CURL_DISABLE_SMB" != "x1" \
-a "x$CURL_DISABLE_CRYPTO_AUTH" != "x1" \
-a \( "x$OPENSSL_ENABLED" = "x1" -o "x$USE_WINDOWS_SSPI" = "x1" \
- -o "x$GNUTLS_ENABLED" = "x1" -o "x$NSS_ENABLED" = "x1" \
- -o "x$DARWINSSL_ENABLED" = "x1" \); then
+ -o "x$GNUTLS_ENABLED" = "x1" -o "x$MBEDTLS_ENABLED" = "x1" \
+ -o "x$NSS_ENABLED" = "x1" -o "x$DARWINSSL_ENABLED" = "x1" \); then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SMB"
if test "x$SSL_ENABLED" = "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SMBS"
diff --git a/docs/BINDINGS b/docs/BINDINGS
deleted file mode 100644
index eb67c3d6..00000000
--- a/docs/BINDINGS
+++ /dev/null
@@ -1,260 +0,0 @@
- _ _ ____ _
- ___| | | | _ \| |
- / __| | | | |_) | |
- | (__| |_| | _ <| |___
- \___|\___/|_| \_\_____|
-
- libcurl bindings
-
- Creative people have written bindings or interfaces for various environments
- and programming languages. Using one of these allows you to take advantage of
- curl powers from within your favourite language or system.
-
- This is a list of all known interfaces as of this writing.
-
- The bindings listed below are not part of the curl/libcurl distribution
- archives, but must be downloaded and installed separately.
-
-Ada95
-
- Writtten by Andreas Almroth
- http://www.almroth.com/adacurl/index.html
-
-Basic
-
- ScriptBasic bindings to libcurl. Writtten by Peter Verhas
- http://scriptbasic.com/
-
-C
- libcurl is a C library in itself!
- https://curl.haxx.se/libcurl/
-
-C++
-
- Written by Jean-Philippe Barrette-LaPierre
- http://curlpp.org/
-
-Ch
-
- Written by Stephen Nestinger and Jonathan Rogado
- http://chcurl.sourceforge.net/
-
-Cocoa
-
- BBHTTP: written by Bruno de Carvalho
- https://github.com/brunodecarvalho/BBHTTP
-
- curlhandle: Written by Dan Wood
- http://curlhandle.sourceforge.net/
-
-D
-
- Written by Kenneth Bogert
- http://dlang.org/library/std/net/curl.html
-
-Dylan
-
- Written by Chris Double
- http://dylanlibs.sourceforge.net/
-
-Eiffel
-
- Written by Eiffel Software
- https://room.eiffel.com/library/curl
-
-Euphoria
-
- Written by Ray Smith
- http://rays-web.com/eulibcurl.htm
-
-Falcon
-
- http://www.falconpl.org/index.ftd?page_id=prjs&prj_id=curl
-
-Ferite
-
- Written by Paul Querna
- http://www.ferite.org/
-
-Gambas
-
- http://gambas.sourceforge.net/
-
-glib/GTK+
-
- Written by Richard Atterer
- http://atterer.net/glibcurl/
-
-Guile:
-
- Written by Michael L. Gran
- http://www.lonelycactus.com/guile-curl.html
-
-Harbour
-
- Written by Viktor Szakáts
- https://github.com/vszakats/harbour-core/tree/master/contrib/hbcurl
-
-Haskell
-
- Written by Galois, Inc
- http://hackage.haskell.org/cgi-bin/hackage-scripts/package/curl
-
-Java
-
- https://github.com/pjlegato/curl-java
-
-Julia
-
- Written by Paul Howe
- https://github.com/forio/Curl.jl
-
-Lisp
-
- Written by Liam Healy
- http://common-lisp.net/project/cl-curl/
-
-Lua
-
- luacurl by Alexander Marinov
- http://luacurl.luaforge.net/
-
- Lua-cURL by Jürgen Hötzel
- http://luaforge.net/projects/lua-curl/
-
-Mono
-
- Written by Jeffrey Phillips
- http://forge.novell.com/modules/xfmod/project/?libcurl-mono
-
-.NET
-
- libcurl-net by Jeffrey Phillips
- https://sourceforge.net/projects/libcurl-net/
-
-node.js
-
- node-libcurl by Jonathan Cardoso Machado
- https://github.com/JCMais/node-libcurl
-
-Object-Pascal
-
- Free Pascal, Delphi and Kylix binding written by Christophe Espern.
- http://www.tekool.com/opcurl
-
-O'Caml
-
- Written by Lars Nilsson
- https://sourceforge.net/projects/ocurl/
-
-Pascal
-
- Free Pascal, Delphi and Kylix binding written by Jeffrey Pohlmeyer.
- http://houston.quik.com/jkp/curlpas/
-
-Perl
-
- Maintained by Cris Bailiff and Bálint Szilakszi
- https://github.com/szbalint/WWW--Curl
-
-PHP
-
- Written by Sterling Hughes
- https://php.net/curl
-
-PostgreSQL
-
- Written by Gian Paolo Ciceri
- http://gborg.postgresql.org/project/pgcurl/projdisplay.php
-
-Python
-
- PycURL by Kjetil Jacobsen
- http://pycurl.sourceforge.net/
-
-R
-
- http://cran.r-project.org/package=curl
-
-Rexx
-
- Written Mark Hessling
- http://rexxcurl.sourceforge.net/
-
-RPG
-
- Support for ILE/RPG on OS/400 is included in source distribution
- https://curl.haxx.se/libcurl/
- See packages/OS400/README.OS400 and packages/OS400/curl.inc.in
-
-Ruby
-
- curb - written by Ross Bamford
- http://curb.rubyforge.org/
-
- ruby-curl-multi - written by Kristjan Petursson and Keith Rarick
- http://curl-multi.rubyforge.org/
-
-Rust
-
- curl-rust - by Carl Lerche
- https://github.com/carllerche/curl-rust
-
-Scheme
-
- Bigloo binding by Kirill Lisovsky
- http://www.metapaper.net/lisovsky/web/curl/
-
-S-Lang
-
- S-Lang binding by John E Davis
- http://www.jedsoft.org/slang/modules/curl.html
-
-Smalltalk
-
- Smalltalk binding by Danil Osipchuk
- http://www.squeaksource.com/CurlPlugin/
-
-SP-Forth
-
- SP-Forth binding by ygrek
- http://www.forth.org.ru/~ac/lib/lin/curl/
-
-SPL
-
- SPL binding by Clifford Wolf
- http://www.clifford.at/spl/
-
-Tcl
-
- Tclcurl by Andrés García
- http://mirror.yellow5.com/tclcurl/
-
-Visual Basic
-
- libcurl-vb by Jeffrey Phillips
- https://sourceforge.net/projects/libcurl-vb/
-
-Visual Foxpro
-
- by Carlos Alloatti
- http://www.ctl32.com.ar/libcurl.asp
-
-Q
- The libcurl module is part of the default install
- http://q-lang.sourceforge.net/
-
-wxWidgets
-
- Written by Casey O'Donnell
- http://wxcode.sourceforge.net/components/wxcurl/
-
-XBLite
-
- Written by David Szafranski
- http://perso.wanadoo.fr/xblite/libraries.html
-
-Xojo
-
- Written by Andrew Lambert
- https://github.com/charonn0/RB-libcURL
diff --git a/docs/BINDINGS.md b/docs/BINDINGS.md
new file mode 100644
index 00000000..a59a94f3
--- /dev/null
+++ b/docs/BINDINGS.md
@@ -0,0 +1,106 @@
+libcurl bindings
+================
+
+ Creative people have written bindings or interfaces for various environments
+ and programming languages. Using one of these allows you to take advantage of
+ curl powers from within your favourite language or system.
+
+ This is a list of all known interfaces as of this writing.
+
+ The bindings listed below are not part of the curl/libcurl distribution
+ archives, but must be downloaded and installed separately.
+
+[Ada95](http://www.almroth.com/adacurl/index.html) Written by Andreas Almroth
+
+[Basic](http://scriptbasic.com/) ScriptBasic bindings written by Peter Verhas
+
+[C++](http://curlpp.org/) Written by Jean-Philippe Barrette-LaPierre
+
+[Ch](http://chcurl.sourceforge.net/) Written by Stephen Nestinger and Jonathan Rogado
+
+Cocoa: [BBHTTP](https://github.com/brunodecarvalho/BBHTTP) written by Bruno de Carvalho
+[curlhandle](http://curlhandle.sourceforge.net/) Written by Dan Wood
+
+[D](http://dlang.org/library/std/net/curl.html) Written by Kenneth Bogert
+
+[Dylan](http://dylanlibs.sourceforge.net/) Written by Chris Double
+
+[Eiffel](https://room.eiffel.com/library/curl) Written by Eiffel Software
+
+[Euphoria](http://rays-web.com/eulibcurl.htm) Written by Ray Smith
+
+[Falcon](http://www.falconpl.org/index.ftd?page_id=prjs&prj_id=curl)
+
+[Ferite](http://www.ferite.org/) Written by Paul Querna
+
+[Gambas](http://gambas.sourceforge.net/)
+
+[glib/GTK+](http://atterer.net/glibcurl/) Written by Richard Atterer
+
+[Guile](http://www.lonelycactus.com/guile-curl.html) Written by Michael L. Gran
+
+[Harbour](https://github.com/vszakats/harbour-core/tree/master/contrib/hbcurl) Written by Viktor Szakáts
+
+[Haskell](http://hackage.haskell.org/cgi-bin/hackage-scripts/package/curl) Written by Galois, Inc
+
+[Java](https://github.com/pjlegato/curl-java)
+
+[Julia](https://github.com/forio/Curl.jl) Written by Paul Howe
+
+[Lisp](http://common-lisp.net/project/cl-curl/) Written by Liam Healy
+
+Lua: [luacurl](http://luacurl.luaforge.net/) by Alexander Marinov, [Lua-cURL](http://luaforge.net/projects/lua-curl/) by Jürgen Hötzel
+
+[Mono](http://forge.novell.com/modules/xfmod/project/?libcurl-mono) Written by Jeffrey Phillips
+
+[.NET](https://sourceforge.net/projects/libcurl-net/) libcurl-net by Jeffrey Phillips
+
+[node.js](https://github.com/JCMais/node-libcurl) node-libcurl by Jonathan Cardoso Machado
+
+[Object-Pascal](http://www.tekool.com/opcurl) Free Pascal, Delphi and Kylix binding written by Christophe Espern.
+
+[O'Caml](https://sourceforge.net/projects/ocurl/) Written by Lars Nilsson
+
+[Pascal](http://houston.quik.com/jkp/curlpas/) Free Pascal, Delphi and Kylix binding written by Jeffrey Pohlmeyer.
+
+[Perl](https://github.com/szbalint/WWW--Curl) Maintained by Cris Bailiff and Bálint Szilakszi
+
+[PHP](https://php.net/curl) Originally written by Sterling Hughes
+
+[PostgreSQL](http://gborg.postgresql.org/project/pgcurl/projdisplay.php) Written by Gian Paolo Ciceri
+
+[Python](http://pycurl.sourceforge.net/) PycURL by Kjetil Jacobsen
+
+[R](http://cran.r-project.org/package=curl)
+
+[Rexx](http://rexxcurl.sourceforge.net/) Written Mark Hessling
+
+RPG, support for ILE/RPG on OS/400 is included in source distribution
+
+Ruby: [curb](http://curb.rubyforge.org/) written by Ross Bamford, [ruby-curl-multi](http://curl-multi.rubyforge.org/) written by Kristjan Petursson and Keith Rarick
+
+[Rust](https://github.com/carllerche/curl-rust) curl-rust - by Carl Lerche
+
+[Scheme](http://www.metapaper.net/lisovsky/web/curl/) Bigloo binding by Kirill Lisovsky
+
+[S-Lang](http://www.jedsoft.org/slang/modules/curl.html) by John E Davis
+
+[Smalltalk](http://www.squeaksource.com/CurlPlugin/) Written by Danil Osipchuk
+
+[SP-Forth](http://www.forth.org.ru/~ac/lib/lin/curl/) Written by ygrek
+
+[SPL](http://www.clifford.at/spl/) Written by Clifford Wolf
+
+[Tcl](http://mirror.yellow5.com/tclcurl/) Tclcurl by Andrés García
+
+[Visual Basic](https://sourceforge.net/projects/libcurl-vb/) libcurl-vb by Jeffrey Phillips
+
+[Visual Foxpro](http://www.ctl32.com.ar/libcurl.asp) by Carlos Alloatti
+
+[Q](http://q-lang.sourceforge.net/) The libcurl module is part of the default install
+
+[wxWidgets](http://wxcode.sourceforge.net/components/wxcurl/) Written by Casey O'Donnell
+
+[XBLite](http://perso.wanadoo.fr/xblite/libraries.html) Written by David Szafranski
+
+[Xojo](https://github.com/charonn0/RB-libcURL) Written by Andrew Lambert
diff --git a/docs/CHECKSRC.md b/docs/CHECKSRC.md
index 591e066f..b42de847 100644
--- a/docs/CHECKSRC.md
+++ b/docs/CHECKSRC.md
@@ -20,7 +20,7 @@ when, for example, one of the files is generated.
checksrc does not check and verify the code against the entire style guide,
but the script is instead an effort to detect the most common mistakes and
-syntax mistakes that contributers make before they get accustomed to our code
+syntax mistakes that contributors make before they get accustomed to our code
style. Heck, many of us regulars do the mistakes too and this script helps us
keep the code in shape.
@@ -33,7 +33,7 @@ warnings are:
- `BADCOMMAND`: There's a bad !checksrc! instruction in the code. See the
**Ignore certain warnings** section below for details.
-- `BANNEDFUNC`: A banned function was used. The funtions sprintf, vsprintf,
+- `BANNEDFUNC`: A banned function was used. The functions sprintf, vsprintf,
strcat, strncat, gets are **never** allowed in curl source code.
- `BRACEELSE`: '} else' on the same line. The else is supposed to be on the
diff --git a/docs/CODE_STYLE.md b/docs/CODE_STYLE.md
index 73a4d94b..ba5f7102 100644
--- a/docs/CODE_STYLE.md
+++ b/docs/CODE_STYLE.md
@@ -1,4 +1,4 @@
-# cURL C code style
+# curl C code style
Source code that has a common style is easier to read than code that uses
different styles in different places. It helps making the code feel like one
@@ -9,8 +9,8 @@ style is more important than individual contributors having their own personal
tastes satisfied.
Our C code has a few style rules. Most of them are verified and upheld by the
-lib/checksrc.pl script. Invoked with `make checksrc` or even by default by the
-build system when built after `./configure --enable-debug` has been used.
+`lib/checksrc.pl` script. Invoked with `make checksrc` or even by default by
+the build system when built after `./configure --enable-debug` has been used.
It is normally not a problem for anyone to follow the guidelines, as you just
need to copy the style already used in the source code and there are no
@@ -28,7 +28,8 @@ other places of the code, just that the names should be logical,
understandable and be named according to what they're used for. File-local
functions should be made static. We like lower case names.
-See the INTERNALS document on how we name non-exported library-global symbols.
+See the [INTERNALS](INTERNALS.md) document on how we name non-exported
+library-global symbols.
## Indenting
@@ -50,7 +51,7 @@ introduced in the C standard until C99. We use only `/*` and `*/` comments:
## Long lines
-Source code in curl may never be wider than 80 columns and there are two
+Source code in curl may never be wider than 79 columns and there are two
reasons for maintaining this even in the modern era of very large and high
resolution screens:
@@ -72,8 +73,12 @@ the initial keyword. Like this:
/* clearly a youngster */
}
-When we write functions however, the opening brace should be in the first
-column of the first line:
+You may omit the braces if they would contain only a one-line statement:
+
+ if(!x)
+ continue;
+
+For functions the opening brace should be on a separate line:
int main(int argc, char **argv)
{
@@ -162,6 +167,53 @@ Examples:
complement = ~bits;
empty = (!*string) ? TRUE : FALSE;
+## Column alignment
+
+Some statements cannot be completed on a single line because the line would
+be too long, the statement too hard to read, or due to other style guidelines
+above. In such a case the statement will span multiple lines.
+
+If a continuation line is part of an expression or sub-expression then you
+should align on the appropriate column so that it's easy to tell what part of
+the statement it is. Operators should not start continuation lines. In other
+cases follow the 2-space indent guideline. Here are some examples from libcurl:
+
+~~~c
+ if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
+ (handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
+ (handle->set.httpreq == HTTPREQ_GET ||
+ handle->set.httpreq == HTTPREQ_HEAD))
+ /* didn't ask for HTTP/1.0 and a GET or HEAD */
+ return TRUE;
+~~~
+
+~~~c
+ case CURLOPT_KEEP_SENDING_ON_ERROR:
+ data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
+ break;
+~~~
+
+~~~c
+ data->set.http_disable_hostname_check_before_authentication =
+ (0 != va_arg(param, long)) ? TRUE : FALSE;
+~~~
+
+~~~c
+ if(option) {
+ result = parse_login_details(option, strlen(option),
+ (userp ? &user : NULL),
+ (passwdp ? &passwd : NULL),
+ NULL);
+ }
+~~~
+
+~~~c
+ DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
+ "server response left\n",
+ (int)clipamount));
+~~~
+
## Platform dependent code
Use `#ifdef HAVE_FEATURE` to do conditional code. We avoid checking for
diff --git a/docs/CONTRIBUTE b/docs/CONTRIBUTE
deleted file mode 100644
index 9e84175b..00000000
--- a/docs/CONTRIBUTE
+++ /dev/null
@@ -1,261 +0,0 @@
- _ _ ____ _
- ___| | | | _ \| |
- / __| | | | |_) | |
- | (__| |_| | _ <| |___
- \___|\___/|_| \_\_____|
-
- When Contributing Source Code
-
- This document is intended to offer guidelines that can be useful to keep in
- mind when you decide to contribute to the project. This concerns new features
- as well as corrections to existing flaws or bugs.
-
- 1. Learning cURL
- 1.1 Join the Community
- 1.2 License
- 1.3 What To Read
-
- 2. Write a good patch
- 2.1 Follow code style
- 2.2 Non-clobbering All Over
- 2.3 Write Separate Patches
- 2.4 Patch Against Recent Sources
- 2.5 Document
- 2.6 Test Cases
-
- 3. Pushing Out Your Changes
- 3.1 Write Access to git Repository
- 3.2 How To Make a Patch with git
- 3.3 How To Make a Patch without git
- 3.4 How to get your changes into the main sources
- 3.5 Write good commit messages
- 3.6 About pull requests
-
-==============================================================================
-
-1. Learning cURL
-
-1.1 Join the Community
-
- Skip over to https://curl.haxx.se/mail/ and join the appropriate mailing
- list(s). Read up on details before you post questions. Read this file before
- you start sending patches! We prefer patches and discussions being held on
- the mailing list(s), not sent to individuals.
-
- Before posting to one of the curl mailing lists, please read up on the mailing
- list etiquette: https://curl.haxx.se/mail/etiquette.html
-
- We also hang out on IRC in #curl on irc.freenode.net
-
- If you're at all interested in the code side of things, consider clicking
- 'watch' on the curl repo at github to get notified on pull requests and new
- issues posted there.
-
-1.2. License
-
- When contributing with code, you agree to put your changes and new code under
- the same license curl and libcurl is already using unless stated and agreed
- otherwise.
-
- If you add a larger piece of code, you can opt to make that file or set of
- files to use a different license as long as they don't enforce any changes to
- the rest of the package and they make sense. Such "separate parts" can not be
- GPL licensed (as we don't want copyleft to affect users of libcurl) but they
- must use "GPL compatible" licenses (as we want to allow users to use libcurl
- properly in GPL licensed environments).
-
- When changing existing source code, you do not alter the copyright of the
- original file(s). The copyright will still be owned by the original
- creator(s) or those who have been assigned copyright by the original
- author(s).
-
- By submitting a patch to the curl project, you are assumed to have the right
- to the code and to be allowed by your employer or whatever to hand over that
- patch/code to us. We will credit you for your changes as far as possible, to
- give credit but also to keep a trace back to who made what changes. Please
- always provide us with your full real name when contributing!
-
-1.3 What To Read
-
- Source code, the man pages, the INTERNALS document, TODO, KNOWN_BUGS and the
- most recent changes in the git log. Just lurking on the curl-library mailing
- list is gonna give you a lot of insights on what's going on right now. Asking
- there is a good idea too.
-
-2. Write a good patch
-
-2.1 Follow code style
-
- When writing C code, follow the CODE_STYLE already established in the
- project. Consistent style makes code easier to read and mistakes less likely
- to happen.
-
-2.2 Non-clobbering All Over
-
- When you write new functionality or fix bugs, it is important that you don't
- fiddle all over the source files and functions. Remember that it is likely
- that other people have done changes in the same source files as you have and
- possibly even in the same functions. If you bring completely new
- functionality, try writing it in a new source file. If you fix bugs, try to
- fix one bug at a time and send them as separate patches.
-
-2.3 Write Separate Patches
-
- It is annoying when you get a huge patch from someone that is said to fix 511
- odd problems, but discussions and opinions don't agree with 510 of them - or
- 509 of them were already fixed in a different way. Then the patcher needs to
- extract the single interesting patch from somewhere within the huge pile of
- source, and that gives a lot of extra work. Preferably, all fixes that
- correct different problems should be in their own patch with an attached
- description exactly what they correct so that all patches can be selectively
- applied by the maintainer or other interested parties.
-
- Also, separate patches enable bisecting much better when we track problems in
- the future.
-
-2.4 Patch Against Recent Sources
-
- Please try to get the latest available sources to make your patches
- against. It makes the life of the developers so much easier. The very best is
- if you get the most up-to-date sources from the git repository, but the
- latest release archive is quite OK as well!
-
-2.5 Document
-
- Writing docs is dead boring and one of the big problems with many open source
- projects. Someone's gotta do it. It makes it a lot easier if you submit a
- small description of your fix or your new features with every contribution so
- that it can be swiftly added to the package documentation.
-
- The documentation is always made in man pages (nroff formatted) or plain
- ASCII files. All HTML files on the web site and in the release archives are
- generated from the nroff/ASCII versions.
-
-2.6 Test Cases
-
- Since the introduction of the test suite, we can quickly verify that the main
- features are working as they're supposed to. To maintain this situation and
- improve it, all new features and functions that are added need to be tested
- in the test suite. Every feature that is added should get at least one valid
- test case that verifies that it works as documented. If every submitter also
- posts a few test cases, it won't end up as a heavy burden on a single person!
-
- If you don't have test cases or perhaps you have done something that is very
- hard to write tests for, do explain exactly how you have otherwise tested and
- verified your changes.
-
-3. Pushing Out Your Changes
-
-3.1 Write Access to git Repository
-
- If you are a frequent contributor, or have another good reason, you can of
- course get write access to the git repository and then you'll be able to push
- your changes straight into the git repo instead of sending changes by mail as
- patches. Just ask if this is what you'd want. You will be required to have
- posted a few quality patches first, before you can be granted push access.
-
-3.2 How To Make a Patch with git
-
- You need to first checkout the repository:
-
- git clone https://github.com/curl/curl.git
-
- You then proceed and edit all the files you like and you commit them to your
- local repository:
-
- git commit [file]
-
- As usual, group your commits so that you commit all changes that at once that
- constitutes a logical change. See also section "3.5 Write good commit
- messages".
-
- Once you have done all your commits and you're happy with what you see, you
- can make patches out of your changes that are suitable for mailing:
-
- git format-patch remotes/origin/master
-
- This creates files in your local directory named NNNN-[name].patch for each
- commit.
-
- Now send those patches off to the curl-library list. You can of course opt to
- do that with the 'git send-email' command.
-
-3.3 How To Make a Patch without git
-
- Keep a copy of the unmodified curl sources. Make your changes in a separate
- source tree. When you think you have something that you want to offer the
- curl community, use GNU diff to generate patches.
-
- If you have modified a single file, try something like:
-
- diff -u unmodified-file.c my-changed-one.c > my-fixes.diff
-
- If you have modified several files, possibly in different directories, you
- can use diff recursively:
-
- diff -ur curl-original-dir curl-modified-sources-dir > my-fixes.diff
-
- The GNU diff and GNU patch tools exist for virtually all platforms, including
- all kinds of Unixes and Windows:
-
- For unix-like operating systems:
-
- https://savannah.gnu.org/projects/patch/
- https://www.gnu.org/software/diffutils/
-
- For Windows:
-
- http://gnuwin32.sourceforge.net/packages/patch.htm
- http://gnuwin32.sourceforge.net/packages/diffutils.htm
-
-3.4 How to get your changes into the main sources
-
- Submit your patch to the curl-library mailing list.
-
- Make the patch against as recent sources as possible.
-
- Make sure your patch adheres to the source indent and coding style of already
- existing source code. Failing to do so just adds more work for me.
-
- Respond to replies on the list about the patch and answer questions and/or
- fix nits/flaws. This is very important. I will take lack of replies as a sign
- that you're not very anxious to get your patch accepted and I tend to simply
- drop such patches from my TODO list.
-
- If you've followed the above paragraphs and your patch still hasn't been
- incorporated after some weeks, consider resubmitting it to the list.
-
-3.5 Write good commit messages
-
- A short guide to how to do fine commit messages in the curl project.
-
- ---- start ----
- [area]: [short line describing the main effect]
-
- [separate the above single line from the rest with an empty line]
-
- [full description, no wider than 72 columns that describe as much as
- possible as to why this change is made, and possibly what things
- it fixes and everything else that is related]
-
- [Bug: link to source of the report or more related discussion]
- [Reported-by: John Doe - credit the reporter]
- [whatever-else-by: credit all helpers, finders, doers]
- ---- stop ----
-
- Don't forget to use commit --author="" if you commit someone else's work,
- and make sure that you have your own user and email setup correctly in git
- before you commit
-
-3.6 About pull requests
-
- With git (and especially github) it is easy and tempting to send a pull
- request to the curl project to have changes merged this way instead of
- mailing patches to the curl-library mailing list.
-
- We used to dislike this but we're trying to change that and accept that this
- is a frictionless way for people to contribute to the project. We now welcome
- pull requests!
-
- We will continue to avoid using github's merge tools to make the history
- linear and to make sure commits follow our style guidelines.
diff --git a/docs/CONTRIBUTE.md b/docs/CONTRIBUTE.md
new file mode 100644
index 00000000..b0b0f6cc
--- /dev/null
+++ b/docs/CONTRIBUTE.md
@@ -0,0 +1,247 @@
+# Contributing to the curl project
+
+This document is intended to offer guidelines on how to best contribute to the
+curl project. This concerns new features as well as corrections to existing
+flaws or bugs.
+
+## Learning curl
+
+### Join the Community
+
+Skip over to [https://curl.haxx.se/mail/](https://curl.haxx.se/mail/) and join
+the appropriate mailing list(s). Read up on details before you post
+questions. Read this file before you start sending patches! We prefer
+questions sent to and discussions being held on the mailing list(s), not sent
+to individuals.
+
+Before posting to one of the curl mailing lists, please read up on the
+[mailing list etiquette](https://curl.haxx.se/mail/etiquette.html).
+
+We also hang out on IRC in #curl on irc.freenode.net
+
+If you're at all interested in the code side of things, consider clicking
+'watch' on the [curl repo on github](https://github.com/curl/curl) to get
+notified on pull requests and new issues posted there.
+
+### License and copyright
+
+When contributing with code, you agree to put your changes and new code under
+the same license curl and libcurl is already using unless stated and agreed
+otherwise.
+
+If you add a larger piece of code, you can opt to make that file or set of
+files to use a different license as long as they don't enforce any changes to
+the rest of the package and they make sense. Such "separate parts" can not be
+GPL licensed (as we don't want copyleft to affect users of libcurl) but they
+must use "GPL compatible" licenses (as we want to allow users to use libcurl
+properly in GPL licensed environments).
+
+When changing existing source code, you do not alter the copyright of the
+original file(s). The copyright will still be owned by the original creator(s)
+or those who have been assigned copyright by the original author(s).
+
+By submitting a patch to the curl project, you are assumed to have the right
+to the code and to be allowed by your employer or whatever to hand over that
+patch/code to us. We will credit you for your changes as far as possible, to
+give credit but also to keep a trace back to who made what changes. Please
+always provide us with your full real name when contributing!
+
+### What To Read
+
+Source code, the man pages, the [INTERNALS
+document](https://curl.haxx.se/dev/internals.html),
+[TODO](https://curl.haxx.se/docs/todo.html),
+[KNOWN_BUGS](https://curl.haxx.se/docs/knownbugs.html) and the [most recent
+changes](https://curl.haxx.se/dev/sourceactivity.html) in git. Just lurking on
+the [curl-library mailing
+list](https://curl.haxx.se/mail/list.cgi?list=curl-library) will give you a
+lot of insights on what's going on right now. Asking there is a good idea too.
+
+## Write a good patch
+
+### Follow code style
+
+When writing C code, follow the
+[CODE_STYLE](https://curl.haxx.se/dev/code-style.html) already established in
+the project. Consistent style makes code easier to read and mistakes less
+likely to happen. Run `make checksrc` before you submit anything, to make sure
+you follow the basic style. That script doesn't verify everything, but if it
+complains you know you have work to do.
+
+### Non-clobbering All Over
+
+When you write new functionality or fix bugs, it is important that you don't
+fiddle all over the source files and functions. Remember that it is likely
+that other people have done changes in the same source files as you have and
+possibly even in the same functions. If you bring completely new
+functionality, try writing it in a new source file. If you fix bugs, try to
+fix one bug at a time and send them as separate patches.
+
+### Write Separate Changes
+
+It is annoying when you get a huge patch from someone that is said to fix 511
+odd problems, but discussions and opinions don't agree with 510 of them - or
+509 of them were already fixed in a different way. Then the person merging
+this change needs to extract the single interesting patch from somewhere
+within the huge pile of source, and that gives a lot of extra work.
+
+Preferably, each fix that correct a problem should be in its own patch/commit
+with its own description/commit message stating exactly what they correct so
+that all changes can be selectively applied by the maintainer or other
+interested parties.
+
+Also, separate changes enable bisecting much better when we track problems
+and regression in the future.
+
+### Patch Against Recent Sources
+
+Please try to get the latest available sources to make your patches against.
+It makes the lives of the developers so much easier. The very best is if you
+get the most up-to-date sources from the git repository, but the latest
+release archive is quite OK as well!
+
+### Documentation
+
+Writing docs is dead boring and one of the big problems with many open source
+projects. Someone's gotta do it. It makes it a lot easier if you submit a
+small description of your fix or your new features with every contribution so
+that it can be swiftly added to the package documentation.
+
+The documentation is always made in man pages (nroff formatted) or plain
+ASCII files. All HTML files on the web site and in the release archives are
+generated from the nroff/ASCII versions.
+
+### Test Cases
+
+Since the introduction of the test suite, we can quickly verify that the main
+features are working as they're supposed to. To maintain this situation and
+improve it, all new features and functions that are added need to be tested
+in the test suite. Every feature that is added should get at least one valid
+test case that verifies that it works as documented. If every submitter also
+posts a few test cases, it won't end up as a heavy burden on a single person!
+
+If you don't have test cases or perhaps you have done something that is very
+hard to write tests for, do explain exactly how you have otherwise tested and
+verified your changes.
+
+## Sharing Your Changes
+
+### How to get your changes into the main sources
+
+Ideally you file a [pull request on
+github](https://github.com/curl/curl/pulls), but you can also send your plain
+patch to [the curl-library mailing
+list](https://curl.haxx.se/mail/list.cgi?list=curl-library).
+
+Either way, your change will be reviewed and discussed there and you will be
+expected to correct flaws pointed out and update accordingly, or the change
+risk stalling and eventually just get deleted without action. As a submitter
+of a change, you are the owner of that change until it has been merged.
+
+Respond on the list or on github about the change and answer questions and/or
+fix nits/flaws. This is very important. We will take lack of replies as a
+sign that you're not very anxious to get your patch accepted and we tend to
+simply drop such changes.
+
+### About pull requests
+
+With github it is easy to send a [pull
+request](https://github.com/curl/curl/pulls) to the curl project to have
+changes merged.
+
+We prefer pull requests to mailed patches, as it makes it a proper git commit
+that is easy to merge and they are easy to track and not that easy to loose
+in a flood of many emails, like they sometimes do on the mailing lists.
+
+When you adjust your pull requests after review, consider squashing the
+commits so that we can review the full updated version more easily.
+
+### Making quality patches
+
+Make the patch against as recent sources as possible.
+
+If you've followed the tips in this document and your patch still hasn't been
+incorporated or responded to after some weeks, consider resubmitting it to
+the list or better yet: change it to a pull request.
+
+### Write good commit messages
+
+A short guide to how to write commit messages in the curl project.
+
+ ---- start ----
+ [area]: [short line describing the main effect]
+ -- empty line --
+ [full description, no wider than 72 columns that describe as much as
+ possible as to why this change is made, and possibly what things
+ it fixes and everything else that is related]
+ -- empty line --
+ [Bug: URL to source of the report or more related discussion]
+ [Reported-by: John Doe - credit the reporter]
+ [whatever-else-by: credit all helpers, finders, doers]
+ ---- stop ----
+
+Don't forget to use commit --author="" if you commit someone else's work,
+and make sure that you have your own user and email setup correctly in git
+before you commit
+
+### Write Access to git Repository
+
+If you are a very frequent contributor, you may be given push access to the
+git repository and then you'll be able to push your changes straight into the
+git repo instead of sending changes as pull requests or by mail as patches.
+
+Just ask if this is what you'd want. You will be required to have posted
+several high quality patches first, before you can be granted push access.
+
+### How To Make a Patch with git
+
+You need to first checkout the repository:
+
+ git clone https://github.com/curl/curl.git
+
+You then proceed and edit all the files you like and you commit them to your
+local repository:
+
+ git commit [file]
+
+As usual, group your commits so that you commit all changes that at once that
+constitutes a logical change.
+
+Once you have done all your commits and you're happy with what you see, you
+can make patches out of your changes that are suitable for mailing:
+
+ git format-patch remotes/origin/master
+
+This creates files in your local directory named NNNN-[name].patch for each
+commit.
+
+Now send those patches off to the curl-library list. You can of course opt to
+do that with the 'git send-email' command.
+
+### How To Make a Patch without git
+
+Keep a copy of the unmodified curl sources. Make your changes in a separate
+source tree. When you think you have something that you want to offer the
+curl community, use GNU diff to generate patches.
+
+If you have modified a single file, try something like:
+
+ diff -u unmodified-file.c my-changed-one.c > my-fixes.diff
+
+If you have modified several files, possibly in different directories, you
+can use diff recursively:
+
+ diff -ur curl-original-dir curl-modified-sources-dir > my-fixes.diff
+
+The GNU diff and GNU patch tools exist for virtually all platforms, including
+all kinds of Unixes and Windows:
+
+For unix-like operating systems:
+
+ - [https://savannah.gnu.org/projects/patch/](https://savannah.gnu.org/projects/patch/)
+ - [https://www.gnu.org/software/diffutils/](https://www.gnu.org/software/diffutils/)
+
+For Windows:
+
+ - [http://gnuwin32.sourceforge.net/packages/patch.htm](http://gnuwin32.sourceforge.net/packages/patch.htm)
+ - [http://gnuwin32.sourceforge.net/packages/diffutils.htm](http://gnuwin32.sourceforge.net/packages/diffutils.htm)
diff --git a/docs/FAQ b/docs/FAQ
index 681ce292..d663811a 100644
--- a/docs/FAQ
+++ b/docs/FAQ
@@ -81,7 +81,7 @@ FAQ
4.16 My HTTP POST or PUT requests are slow!
4.17 Non-functional connect timeouts on Windows
4.18 file:// URLs containing drive letters (Windows, NetWare)
- 4.19 Why doesn't cURL return an error when the network cable is unplugged?
+ 4.19 Why doesn't curl return an error when the network cable is unplugged?
4.20 curl doesn't return error for HTTP non-200 responses!
4.21 Why is there a HTTP/1.1 in my HTTP/2 request?
@@ -968,8 +968,8 @@ FAQ
4.9 Curl can't authenticate to the server that requires NTLM?
- NTLM support requires OpenSSL, GnuTLS, NSS, Secure Transport, or Microsoft
- Windows libraries at build-time to provide this functionality.
+ NTLM support requires OpenSSL, GnuTLS, mbedTLS, NSS, Secure Transport, or
+ Microsoft Windows libraries at build-time to provide this functionality.
NTLM is a Microsoft proprietary protocol. Proprietary formats are evil. You
should not use such ones.
@@ -1083,18 +1083,18 @@ FAQ
4.18 file:// URLs containing drive letters (Windows, NetWare)
- When using cURL to try to download a local file, one might use a URL
+ When using curl to try to download a local file, one might use a URL
in this format:
file://D:/blah.txt
- You'll find that even if D:\blah.txt does exist, cURL returns a 'file
+ You'll find that even if D:\blah.txt does exist, curl returns a 'file
not found' error.
According to RFC 1738 (https://www.ietf.org/rfc/rfc1738.txt),
file:// URLs must contain a host component, but it is ignored by
most implementations. In the above example, 'D:' is treated as the
- host component, and is taken away. Thus, cURL tries to open '/blah.txt'.
+ host component, and is taken away. Thus, curl tries to open '/blah.txt'.
If your system is installed to drive C:, that will resolve to 'C:\blah.txt',
and if that doesn't exist you will get the not found error.
@@ -1107,9 +1107,9 @@ FAQ
file://localhost/D:/blah.txt
- In either case, cURL should now be looking for the correct file.
+ In either case, curl should now be looking for the correct file.
- 4.19 Why doesn't cURL return an error when the network cable is unplugged?
+ 4.19 Why doesn't curl return an error when the network cable is unplugged?
Unplugging a cable is not an error situation. The TCP/IP protocol stack
was designed to be fault tolerant, so even though there may be a physical
@@ -1385,14 +1385,14 @@ FAQ
member function that is passed a pointer to the class:
// f is the pointer to your object.
- static YourClass::func(void *buffer, size_t sz, size_t n, void *f)
+ static size_t YourClass::func(void *buffer, size_t sz, size_t n, void *f)
{
// Call non-static member function.
static_cast<YourClass*>(f)->nonStaticFunction();
}
// This is how you pass pointer to the static function:
- curl_easy_setopt(hcurl, CURLOPT_WRITEFUNCTION, YourClass:func);
+ curl_easy_setopt(hcurl, CURLOPT_WRITEFUNCTION, YourClass::func);
curl_easy_setopt(hcurl, CURLOPT_WRITEDATA, this);
5.15 How do I get an FTP directory listing?
diff --git a/docs/FEATURES b/docs/FEATURES
index 10fbdd57..24fa56dd 100644
--- a/docs/FEATURES
+++ b/docs/FEATURES
@@ -195,8 +195,8 @@ FOOTNOTES
*7 = requires OpenSSL, NSS, GSKit, WinSSL or Secure Transport; GnuTLS, for
example, only supports SSLv3 and TLSv1
*8 = requires libssh2
- *9 = requires OpenSSL, GnuTLS, NSS, yassl, Secure Transport or SSPI (native
- Windows)
+ *9 = requires OpenSSL, GnuTLS, mbedTLS, NSS, yassl, Secure Transport or SSPI
+ (native Windows)
*10 = requires any of the SSL libraries in (*1) above other than axTLS, which
does not support SSLv3
*11 = requires libidn or Windows
diff --git a/docs/HISTORY b/docs/HISTORY.md
index f878ee10..ac93b674 100644
--- a/docs/HISTORY
+++ b/docs/HISTORY.md
@@ -1,10 +1,4 @@
- _ _ ____ _
- ___| | | | _ \| |
- / __| | | | |_) | |
- | (__| |_| | _ <| |___
- \___|\___/|_| \_\_____|
-
-How cURL Became Like This
+How curl Became Like This
=========================
Towards the end of 1996, Daniel Stenberg was spending time writing an IRC bot
@@ -178,6 +172,8 @@ August: Curl and libcurl 7.12.1
April. GnuTLS can now optionally be used for the secure layer when curl is
built.
+April: Added the multi_socket() API
+
September: TFTP support was added.
More than 100,000 unique visitors of the curl web site. 25 mirrors.
@@ -193,8 +189,6 @@ nobody had found out in all this time we removed it instead of fixing it.
March: security vulnerability: libcurl TFTP Packet Buffer Overflow
-April: Added the multi_socket() API
-
September: The major SONAME number for libcurl was bumped to 4 due to the
removal of ftp third party transfer support.
diff --git a/docs/HTTP2.md b/docs/HTTP2.md
index cc5a5b33..efbe6999 100644
--- a/docs/HTTP2.md
+++ b/docs/HTTP2.md
@@ -96,18 +96,31 @@ curl tool
curl offers the `--http2` command line option to enable use of HTTP/2.
-curl offers the `--http2-prior-knowledge` command line option to enable use of
+curl offers the `--http2-prior-knowledge` command line option to enable use of
HTTP/2 without HTTP/1.1 Upgrade.
Since 7.47.0, the curl tool enables HTTP/2 by default for HTTPS connections.
+curl tool limitations
+---------------------
+
+The command line tool won't do any HTTP/2 multiplexing even though libcurl
+supports it, simply because the curl tool is not written to take advantage of
+the libcurl API that's necessary for this (the multi interface). We have an
+outstanding TODO item for this and **you** can help us make it happen.
+
+The command line tool also doesn't support HTTP/2 server push for the same
+reason it doesn't do multiplexing: it needs to use the multi interface for
+that so that multiplexing is supported.
+
HTTP Alternative Services
-------------------------
-Alt-Svc is a suggested extension with a corresponding frame (ALTSVC) in HTTP/2
-that tells the client about an alternative "route" to the same content for the
-same origin server that you get the response from. A browser or long-living
-client can use that hint to create a new connection asynchronously. For
-libcurl, we may introduce a way to bring such clues to the applicaton and/or
-let a subsequent request use the alternate route
-automatically. [Spec](https://tools.ietf.org/html/draft-ietf-httpbis-alt-svc-14)
+Alt-Svc is an extension with a corresponding frame (ALTSVC) in HTTP/2 that
+tells the client about an alternative "route" to the same content for the same
+origin server that you get the response from. A browser or long-living client
+can use that hint to create a new connection asynchronously. For libcurl, we
+may introduce a way to bring such clues to the application and/or let a
+subsequent request use the alternate route automatically.
+
+[Detailed in RFC 7838](https://tools.ietf.org/html/rfc7838)
diff --git a/docs/INSTALL b/docs/INSTALL
index 2e1075ba..ff260b1b 100644
--- a/docs/INSTALL
+++ b/docs/INSTALL
@@ -6,1110 +6,4 @@
How To Compile
-Installing Binary Packages
-==========================
-
- Lots of people download binary distributions of curl and libcurl. This
- document does not describe how to install curl or libcurl using such a
- binary package. This document describes how to compile, build and install
- curl and libcurl from source code.
-
-Building from git
-=================
-
- If you get your code off a git repository, see the GIT-INFO file in the
- root directory for specific instructions on how to proceed.
-
-Unix
-====
-
- A normal Unix installation is made in three or four steps (after you've
- unpacked the source archive):
-
- ./configure
- make
- make test (optional)
- make install
-
- You probably need to be root when doing the last command.
-
- If you have checked out the sources from the git repository, read the
- GIT-INFO on how to proceed.
-
- Get a full listing of all available configure options by invoking it like:
-
- ./configure --help
-
- If you want to install curl in a different file hierarchy than /usr/local,
- you need to specify that already when running configure:
-
- ./configure --prefix=/path/to/curl/tree
-
- If you happen to have write permission in that directory, you can do 'make
- install' without being root. An example of this would be to make a local
- install in your own home directory:
-
- ./configure --prefix=$HOME
- make
- make install
-
- The configure script always tries to find a working SSL library unless
- explicitly told not to. If you have OpenSSL installed in the default search
- path for your compiler/linker, you don't need to do anything special. If
- you have OpenSSL installed in /usr/local/ssl, you can run configure like:
-
- ./configure --with-ssl
-
- If you have OpenSSL installed somewhere else (for example, /opt/OpenSSL)
- and you have pkg-config installed, set the pkg-config path first, like this:
-
- env PKG_CONFIG_PATH=/opt/OpenSSL/lib/pkgconfig ./configure --with-ssl
-
- Without pkg-config installed, use this:
-
- ./configure --with-ssl=/opt/OpenSSL
-
- If you insist on forcing a build without SSL support, even though you may
- have OpenSSL installed in your system, you can run configure like this:
-
- ./configure --without-ssl
-
- If you have OpenSSL installed, but with the libraries in one place and the
- header files somewhere else, you have to set the LDFLAGS and CPPFLAGS
- environment variables prior to running configure. Something like this
- should work:
-
- (with the Bourne shell and its clones):
-
- CPPFLAGS="-I/path/to/ssl/include" LDFLAGS="-L/path/to/ssl/lib" \
- ./configure
-
- (with csh, tcsh and their clones):
-
- env CPPFLAGS="-I/path/to/ssl/include" LDFLAGS="-L/path/to/ssl/lib" \
- ./configure
-
- If you have shared SSL libs installed in a directory where your run-time
- linker doesn't find them (which usually causes configure failures), you can
- provide the -R option to ld on some operating systems to set a hard-coded
- path to the run-time linker:
-
- env LDFLAGS=-R/usr/local/ssl/lib ./configure --with-ssl
-
- MORE OPTIONS
- ------------
-
- To force configure to use the standard cc compiler if both cc and gcc are
- present, run configure like
-
- CC=cc ./configure
- or
- env CC=cc ./configure
-
- To force a static library compile, disable the shared library creation
- by running configure like:
-
- ./configure --disable-shared
-
- To tell the configure script to skip searching for thread-safe functions,
- add an option like:
-
- ./configure --disable-thread
-
- If you're a curl developer and use gcc, you might want to enable more
- debug options with the --enable-debug option.
-
- curl can be built to use a whole range of libraries to provide various
- useful services, and configure will try to auto-detect a decent
- default. But if you want to alter it, you can select how to deal with
- each individual library.
-
- To build with GnuTLS for SSL/TLS, use both --without-ssl and
- --with-gnutls.
-
- To build with Cyassl for SSL/TLS, use both --without-ssl and
- --with-cyassl.
-
- To build with NSS for SSL/TLS, use both --without-ssl and --with-nss.
-
- To build with PolarSSL for SSL/TLS, use both --without-ssl and
- --with-polarssl.
-
- To build with axTLS for SSL/TLS, use both --without-ssl and --with-axtls.
-
- To build with GSS-API support, use --with-gssapi and have the MIT Kerberos
- or Heimdal packages installed.
-
- To get support for SCP and SFTP, build with --with-libssh2 and have
- libssh2 0.16 or later installed.
-
- To get Metalink support, build with --with-libmetalink and have the
- libmetalink packages installed.
-
- SPECIAL CASES
- -------------
-
- Some versions of uClibc require configuring with CPPFLAGS=-D_GNU_SOURCE=1
- to get correct large file support.
-
- The Open Watcom C compiler on Linux requires configuring with the variables:
-
- ./configure CC=owcc AR="$WATCOM/binl/wlib" AR_FLAGS=-q \
- RANLIB=/bin/true STRIP="$WATCOM/binl/wstrip" CFLAGS=-Wextra
-
-Win32
-=====
-
- Building Windows DLLs and C run-time (CRT) linkage issues
- ---------------------------------------------------------
-
- As a general rule, building a DLL with static CRT linkage is highly
- discouraged, and intermixing CRTs in the same app is something to
- avoid at any cost.
-
- Reading and comprehension of Microsoft Knowledge Base articles
- KB94248 and KB140584 is a must for any Windows developer. Especially
- important is full understanding if you are not going to follow the
- advice given above.
-
- KB94248 - How To Use the C Run-Time
- https://support.microsoft.com/kb/94248/en-us
-
- KB140584 - How to link with the correct C Run-Time (CRT) library
- https://support.microsoft.com/kb/140584/en-us
-
- KB190799 - Potential Errors Passing CRT Objects Across DLL Boundaries
- https://msdn.microsoft.com/en-us/library/ms235460
-
- If your app is misbehaving in some strange way, or it is suffering
- from memory corruption, before asking for further help, please try
- first to rebuild every single library your app uses as well as your
- app using the debug multithreaded dynamic C runtime.
-
- If you get linkage errors read section 5.7 of the FAQ document.
-
- MingW32
- -------
-
- Make sure that MinGW32's bin dir is in the search path, for example:
-
- set PATH=c:\mingw32\bin;%PATH%
-
- then run 'mingw32-make mingw32' in the root dir. There are other
- make targets available to build libcurl with more features, use:
- 'mingw32-make mingw32-zlib' to build with Zlib support;
- 'mingw32-make mingw32-ssl-zlib' to build with SSL and Zlib enabled;
- 'mingw32-make mingw32-ssh2-ssl-zlib' to build with SSH2, SSL, Zlib;
- 'mingw32-make mingw32-ssh2-ssl-sspi-zlib' to build with SSH2, SSL, Zlib
- and SSPI support.
-
- If you have any problems linking libraries or finding header files, be sure
- to verify that the provided "Makefile.m32" files use the proper paths, and
- adjust as necessary. It is also possible to override these paths with
- environment variables, for example:
-
- set ZLIB_PATH=c:\zlib-1.2.8
- set OPENSSL_PATH=c:\openssl-1.0.2c
- set LIBSSH2_PATH=c:\libssh2-1.6.0
-
- ATTENTION: if you want to build with libssh2 support you have to use latest
- version 0.17 - previous versions will NOT work with 7.17.0 and later!
- Use 'mingw32-make mingw32-ssh2-ssl-zlib' to build with SSH2 and SSL enabled.
-
- It is now also possible to build with other LDAP SDKs than MS LDAP;
- currently it is possible to build with native Win32 OpenLDAP, or with the
- Novell CLDAP SDK. If you want to use these you need to set these vars:
-
- set LDAP_SDK=c:\openldap
- set USE_LDAP_OPENLDAP=1
-
- or for using the Novell SDK:
-
- set USE_LDAP_NOVELL=1
-
- If you want to enable LDAPS support then set LDAPS=1.
-
- - optional MingW32-built OpenLDAP SDK available from:
- http://www.gknw.net/mirror/openldap/
- - optional recent Novell CLDAP SDK available from:
- https://www.novell.com/developer/ndk/ldap_libraries_for_c.html
-
- Cygwin
- ------
-
- Almost identical to the unix installation. Run the configure script in the
- curl root with 'sh configure'. Make sure you have the sh executable in
- /bin/ or you'll see the configure fail toward the end.
-
- Run 'make'
-
- Dev-Cpp
- -------
-
- See the separate INSTALL.devcpp file for details.
-
- MSVC 6 caveats
- --------------
-
- If you use MSVC 6 it is required that you use the February 2003 edition of
- the 'Platform SDK' which can be downloaded from:
-
- https://www.microsoft.com/en-us/download/details.aspx?id=12261
-
- Building any software with MSVC 6 without having PSDK installed is just
- asking for trouble down the road once you have released it, you might notice
- the problems in the first corner or ten miles ahead, depending mostly on your
- choice of static vs dynamic runtime and third party libraries. Anyone using
- software built in such way will at some point regret having done so.
-
- If the compiler has been updated with the installation of a service pack as
- those mentioned in https://support.microsoft.com/kb/194022 the compiler can be
- safely used to read source code, translate and make it object code.
-
- But, even with the service packs mentioned above installed, the resulting
- software generated in such an environment will be using outdated system
- header files and libraries with bugs and security issues which have already
- been addressed and fixed long time ago.
-
- So, building curl and libcurl with MSVC 6 without PSDK is absolutely
- discouraged for the benefit of anyone using software built in such
- environment. And it will not be supported in any way, as we could just
- be hunting bugs which have already been fixed way back in 2003.
-
- When building with MSVC 6 we attempt to detect if PSDK is not being used,
- and if this is the case the build process will fail hard with an error
- message stating that the February 2003 PSDK is required. This is done to
- protect the unsuspecting and avoid PEBKAC issues.
-
- Additionally it might happen that a die hard MSVC hacker still wants to
- build curl and libcurl with MSVC 6 without PSDK installed, even knowing
- that this is a highly discouraged and unsupported build environment. In
- this case the brave of heart will be able to build in such an environment
- with the requisite of defining preprocessor symbol ALLOW_MSVC6_WITHOUT_PSDK
- in lib/config-win32.h and knowing that LDAP and IPv6 support will be missing.
-
- MSVC from command line
- ----------------------
-
- Run the 'vcvars32.bat' file to get a proper environment. The
- vcvars32.bat file is part of the Microsoft development environment and
- you may find it in 'C:\Program Files\Microsoft Visual Studio\vc98\bin'
- provided that you installed Visual C/C++ 6 in the default directory.
-
- Then run 'nmake vc' in curl's root directory.
-
- If you want to compile with zlib support, you will need to build
- zlib (http://www.zlib.net/) as well. Please read the zlib
- documentation on how to compile zlib. Define the ZLIB_PATH environment
- variable to the location of zlib.h and zlib.lib, for example:
-
- set ZLIB_PATH=c:\zlib-1.2.8
-
- Then run 'nmake vc-zlib' in curl's root directory.
-
- If you want to compile with SSL support you need the OpenSSL package.
- Please read the OpenSSL documentation on how to compile and install
- the OpenSSL libraries. The build process of OpenSSL generates the
- libeay32.dll and ssleay32.dll files in the out32dll subdirectory in
- the OpenSSL home directory. OpenSSL static libraries (libeay32.lib,
- ssleay32.lib, RSAglue.lib) are created in the out32 subdirectory.
-
- Before running nmake define the OPENSSL_PATH environment variable with
- the root/base directory of OpenSSL, for example:
-
- set OPENSSL_PATH=c:\openssl-0.9.8zc
-
- Then run 'nmake vc-ssl' or 'nmake vc-ssl-dll' in curl's root
- directory. 'nmake vc-ssl' will create a libcurl static and dynamic
- libraries in the lib subdirectory, as well as a statically linked
- version of curl.exe in the src subdirectory. This statically linked
- version is a standalone executable not requiring any DLL at
- runtime. This make method requires that you have the static OpenSSL
- libraries available in OpenSSL's out32 subdirectory.
- 'nmake vc-ssl-dll' creates the libcurl dynamic library and
- links curl.exe against libcurl and OpenSSL dynamically.
- This executable requires libcurl.dll and the OpenSSL DLLs
- at runtime.
- Run 'nmake vc-ssl-zlib' to build with both ssl and zlib support.
-
- MSVC IDE
- --------
-
- A fairly comprehensive set of Visual Studio project files are available for
- v6.0 through v12.0 and are located in the projects folder to allow proper
- building of both the libcurl library as well as the curl tool.
-
- For more information about these projects and building via Visual Studio
- please see the README file located in the projects folder.
-
- Borland C++ compiler
- --------------------
-
- Ensure that your build environment is properly set up to use the compiler
- and associated tools. PATH environment variable must include the path to
- bin subdirectory of your compiler installation, eg: c:\Borland\BCC55\bin
-
- It is advisable to set environment variable BCCDIR to the base path of
- the compiler installation.
-
- set BCCDIR=c:\Borland\BCC55
-
- In order to build a plain vanilla version of curl and libcurl run the
- following command from curl's root directory:
-
- make borland
-
- To build curl and libcurl with zlib and OpenSSL support set environment
- variables ZLIB_PATH and OPENSSL_PATH to the base subdirectories of the
- already built zlib and OpenSSL libraries and from curl's root directory
- run command:
-
- make borland-ssl-zlib
-
- libcurl library will be built in 'lib' subdirectory while curl tool
- is built in 'src' subdirectory. In order to use libcurl library it is
- advisable to modify compiler's configuration file bcc32.cfg located
- in c:\Borland\BCC55\bin to reflect the location of libraries include
- paths for example the '-I' line could result in something like:
-
- -I"c:\Borland\BCC55\include;c:\curl\include;c:\openssl\inc32"
-
- bcc3.cfg '-L' line could also be modified to reflect the location of
- of libcurl library resulting for example:
-
- -L"c:\Borland\BCC55\lib;c:\curl\lib;c:\openssl\out32"
-
- In order to build sample program 'simple.c' from the docs\examples
- subdirectory run following command from mentioned subdirectory:
-
- bcc32 simple.c libcurl.lib cw32mt.lib
-
- In order to build sample program simplessl.c an SSL enabled libcurl
- is required, as well as the OpenSSL libeay32.lib and ssleay32.lib
- libraries.
-
- OTHER MSVC IDEs
- ---------------
-
- If you use VC++, Borland or similar compilers. Include all lib source
- files in a static lib "project" (all .c and .h files that is).
- (you should name it libcurl or similar)
-
- Make the sources in the src/ drawer be a "win32 console application"
- project. Name it curl.
-
- Disabling Specific Protocols in Win32 builds
- --------------------------------------------
-
- The configure utility, unfortunately, is not available for the Windows
- environment, therefore, you cannot use the various disable-protocol
- options of the configure utility on this platform.
-
- However, you can use the following defines to disable specific
- protocols:
-
- HTTP_ONLY disables all protocols except HTTP
- CURL_DISABLE_FTP disables FTP
- CURL_DISABLE_LDAP disables LDAP
- CURL_DISABLE_TELNET disables TELNET
- CURL_DISABLE_DICT disables DICT
- CURL_DISABLE_FILE disables FILE
- CURL_DISABLE_TFTP disables TFTP
- CURL_DISABLE_HTTP disables HTTP
- CURL_DISABLE_IMAP disables IMAP
- CURL_DISABLE_POP3 disables POP3
- CURL_DISABLE_SMTP disables SMTP
-
- If you want to set any of these defines you have the following options:
-
- - Modify lib/config-win32.h
- - Modify lib/curl_setup.h
- - Modify lib/Makefile.vc6
- - Modify the "Preprocessor Definitions" in the libcurl project
-
- Note: The pre-processor settings can be found using the Visual Studio IDE
- under "Project -> Settings -> C/C++ -> General" in VC6 and "Project ->
- Properties -> Configuration Properties -> C/C++ -> Preprocessor" in later
- versions.
-
- Using BSD-style lwIP instead of Winsock TCP/IP stack in Win32 builds
- --------------------------------------------------------------------
-
- In order to compile libcurl and curl using BSD-style lwIP TCP/IP stack
- it is necessary to make definition of preprocessor symbol USE_LWIPSOCK
- visible to libcurl and curl compilation processes. To set this definition
- you have the following alternatives:
-
- - Modify lib/config-win32.h and src/config-win32.h
- - Modify lib/Makefile.vc6
- - Modify the "Preprocessor Definitions" in the libcurl project
-
- Note: The pre-processor settings can be found using the Visual Studio IDE
- under "Project -> Settings -> C/C++ -> General" in VC6 and "Project ->
- Properties -> Configuration Properties -> C/C++ -> Preprocessor" in later
- versions.
-
- Once that libcurl has been built with BSD-style lwIP TCP/IP stack support,
- in order to use it with your program it is mandatory that your program
- includes lwIP header file <lwip/opt.h> (or another lwIP header that includes
- this) before including any libcurl header. Your program does not need the
- USE_LWIPSOCK preprocessor definition which is for libcurl internals only.
-
- Compilation has been verified with lwIP 1.4.0 and contrib-1.4.0 from:
-
- http://download.savannah.gnu.org/releases/lwip/lwip-1.4.0.zip
- http://download.savannah.gnu.org/releases/lwip/contrib-1.4.0.zip
-
- This BSD-style lwIP TCP/IP stack support must be considered experimental
- given that it has been verified that lwIP 1.4.0 still needs some polish,
- and libcurl might yet need some additional adjustment, caveat emptor.
-
- Important static libcurl usage note
- -----------------------------------
-
- When building an application that uses the static libcurl library, you must
- add '-DCURL_STATICLIB' to your CFLAGS. Otherwise the linker will look for
- dynamic import symbols.
-
- Legacy Windows and SSL
- ----------------------
-
- WinSSL (specifically SChannel from Windows SSPI), is the native SSL library
- in Windows. However, WinSSL in Windows <= XP is unable to connect to servers
- that no longer support the legacy handshakes and algorithms used by those
- versions. If you will be using curl in one of those earlier versions of
- Windows you should choose another SSL backend such as OpenSSL.
-
-Apple iOS and Mac OS X
-======================
-
- On recent Apple operating systems, curl can be built to use Apple's
- SSL/TLS implementation, Secure Transport, instead of OpenSSL. To build with
- Secure Transport for SSL/TLS, use the configure option --with-darwinssl. (It
- is not necessary to use the option --without-ssl.) This feature requires iOS
- 5.0 or later, or OS X 10.5 ("Leopard") or later.
-
- When Secure Transport is in use, the curl options --cacert and --capath and
- their libcurl equivalents, will be ignored, because Secure Transport uses
- the certificates stored in the Keychain to evaluate whether or not to trust
- the server. This, of course, includes the root certificates that ship with
- the OS. The --cert and --engine options, and their libcurl equivalents, are
- currently unimplemented in curl with Secure Transport.
-
- For OS X users: In OS X 10.8 ("Mountain Lion"), Apple made a major
- overhaul to the Secure Transport API that, among other things, added
- support for the newer TLS 1.1 and 1.2 protocols. To get curl to support
- TLS 1.1 and 1.2, you must build curl on Mountain Lion or later, or by
- using the equivalent SDK. If you set the MACOSX_DEPLOYMENT_TARGET
- environmental variable to an earlier version of OS X prior to building curl,
- then curl will use the new Secure Transport API on Mountain Lion and later,
- and fall back on the older API when the same curl binary is executed on
- older cats. For example, running these commands in curl's directory in the
- shell will build the code such that it will run on cats as old as OS X 10.6
- ("Snow Leopard") (using bash):
-
- export MACOSX_DEPLOYMENT_TARGET="10.6"
- ./configure --with-darwinssl
- make
-
-IBM OS/2
-========
-
- Building under OS/2 is not much different from building under unix.
- You need:
-
- - emx 0.9d
- - GNU make
- - GNU patch
- - ksh
- - GNU bison
- - GNU file utilities
- - GNU sed
- - autoconf 2.13
-
- If you want to build with OpenSSL or OpenLDAP support, you'll need to
- download those libraries, too. Dirk Ohme has done some work to port SSL
- libraries under OS/2, but it looks like he doesn't care about emx. You'll
- find his patches on: http://come.to/Dirk_Ohme
-
- If during the linking you get an error about _errno being an undefined
- symbol referenced from the text segment, you need to add -D__ST_MT_ERRNO__
- in your definitions.
-
- If everything seems to work fine but there's no curl.exe, you need to add
- -Zexe to your linker flags.
-
- If you're getting huge binaries, probably your makefiles have the -g in
- CFLAGS.
-
-VMS
-===
-
- (The VMS section is in whole contributed by the friendly Nico Baggus)
-
- Curl seems to work with FTP & HTTP other protocols are not tested. (the
- perl http/ftp testing server supplied as testing too cannot work on VMS
- because vms has no concept of fork(). [ I tried to give it a whack, but
- that's of no use.
-
- SSL stuff has not been ported.
-
- Telnet has about the same issues as for Win32. When the changes for Win32
- are clear maybe they'll work for VMS too. The basic problem is that select
- ONLY works for sockets.
-
- Marked instances of fopen/[f]stat that might become a problem, especially
- for non stream files. In this regard, the files opened for writing will be
- created stream/lf and will thus be safe. Just keep in mind that non-binary
- read/wring from/to files will have a records size limit of 32767 bytes
- imposed.
-
- Stat to get the size of the files is again only safe for stream files &
- fixed record files without implied CC.
-
- -- My guess is that only allowing access to stream files is the quickest
- way to get around the most issues. Therefore all files need to to be
- checked to be sure they will be stream/lf before processing them. This is
- the easiest way out, I know. The reason for this is that code that needs to
- report the filesize will become a pain in the ass otherwise.
-
- Exit status.... Well we needed something done here,
-
- VMS has a structured exist status:
- | 3 | 2 | 1 | 0|
- |1098|765432109876|5432109876543|210|
- +----+------------+-------------+---+
- |Ctrl| Facility | Error code |sev|
- +----+------------+-------------+---+
-
- With the Ctrl-bits an application can tell if part or the whole message has
- already been printed from the program, DCL doesn't need to print it again.
-
- Facility - basically the program ID. A code assigned to the program
- the name can be fetched from external or internal message libraries
- Error code - the err codes assigned by the application
- Sev. - severity: Even = error, off = non error
-
- 0 = Warning
- 1 = Success
- 2 = Error
- 3 = Information
- 4 = Fatal
- <5-7> reserved.
-
- This all presents itself with:
- %<FACILITY>-<Sev>-<Errorname>, <Error message>
-
- See also the src/curlmsg.msg file, it has the source for the messages In
- src/main.c a section is devoted to message status values, the globalvalues
- create symbols with certain values, referenced from a compiled message
- file. Have all exit function use a exit status derived from a translation
- table with the compiled message codes.
-
- This was all compiled with:
-
- Compaq C V6.2-003 on OpenVMS Alpha V7.1-1H2
-
- So far for porting notes as of:
-
- 13-jul-2001
- N. Baggus
-
-QNX
-===
-
- (This section was graciously brought to us by David Bentham)
-
- As QNX is targeted for resource constrained environments, the QNX headers
- set conservative limits. This includes the FD_SETSIZE macro, set by default
- to 32. Socket descriptors returned within the CURL library may exceed this,
- resulting in memory faults/SIGSEGV crashes when passed into select(..)
- calls using fd_set macros.
-
- A good all-round solution to this is to override the default when building
- libcurl, by overriding CFLAGS during configure, example
-
- # configure CFLAGS='-DFD_SETSIZE=64 -g -O2'
-
-RISC OS
-=======
-
- The library can be cross-compiled using gccsdk as follows:
-
- CC=riscos-gcc AR=riscos-ar RANLIB='riscos-ar -s' ./configure \
- --host=arm-riscos-aof --without-random --disable-shared
- make
-
- where riscos-gcc and riscos-ar are links to the gccsdk tools.
- You can then link your program with curl/lib/.libs/libcurl.a
-
-AmigaOS
-=======
-
- (This section was graciously brought to us by Diego Casorran)
-
- To build cURL/libcurl on AmigaOS just type 'make amiga' ...
-
- What you need is: (not tested with others versions)
-
- GeekGadgets / gcc 2.95.3 (http://www.geekgadgets.org/)
-
- AmiTCP SDK v4.3 (http://www.aminet.net/comm/tcp/AmiTCP-SDK-4.3.lha)
-
- Native Developer Kit (http://www.amiga.com/3.9/download/NDK3.9.lha)
-
- As no ixemul.library is required you will be able to build it for
- WarpOS/PowerPC (not tested by me), as well a MorphOS version should be
- possible with no problems.
-
- To enable SSL support, you need a OpenSSL native version (without ixemul),
- you can find a precompiled package at http://amiga.sourceforge.net/OpenSSL/
-
-NetWare
-=======
-
- To compile curl.nlm / libcurl.nlm you need:
-
- - either any gcc / nlmconv, or CodeWarrior 7 PDK 4 or later.
- - gnu make and awk running on the platform you compile on;
- native Win32 versions can be downloaded from:
- http://www.gknw.net/development/prgtools/
- - recent Novell LibC or Novell CLib SDK available from:
- https://www.novell.com/developer/ndk/
- - optional recent Novell CLDAP SDK available from:
- https://www.novell.com/developer/ndk/ldap_libraries_for_c.html
- - optional zlib sources (static or dynamic linking with zlib.imp);
- sources with NetWare Makefile can be obtained from:
- http://www.gknw.net/mirror/zlib/
- - optional OpenSSL sources (version 0.9.8 or later build with BSD sockets);
- you can find precompiled packages at:
- http://www.gknw.net/development/ossl/netware/
- for CLIB-based builds OpenSSL 0.9.8h or later is required - earlier versions
- don't support building with CLIB BSD sockets.
- - optional SSH2 sources (version 0.17 or later);
-
- Set a search path to your compiler, linker and tools; on Linux make
- sure that the var OSTYPE contains the string 'linux'; set the var
- NDKBASE to point to the base of your Novell NDK; and then type
- 'make netware' from the top source directory; other targets available
- are 'netware-ssl', 'netware-ssl-zlib', 'netware-zlib' and 'netware-ares';
- if you need other combinations you can control the build with the
- environment variables WITH_SSL, WITH_ZLIB, WITH_ARES, WITH_SSH2, and
- ENABLE_IPV6; you can set LINK_STATIC=1 to link curl.nlm statically.
- By default LDAP support is enabled, however currently you will need a patch
- in order to use the CLDAP NDK with BSD sockets (Novell Bug 300237):
- http://www.gknw.net/test/curl/cldap_ndk/ldap_ndk.diff
- I found on some Linux systems (RH9) that OS detection didn't work although
- a 'set | grep OSTYPE' shows the var present and set; I simply overwrote it
- with 'OSTYPE=linux-rh9-gnu' and the detection in the Makefile worked...
- Any help in testing appreciated!
- Builds automatically created 8 times a day from current git are here:
- http://www.gknw.net/mirror/curl/autobuilds/
- the status of these builds can be viewed at the autobuild table:
- https://curl.haxx.se/dev/builds.html
-
-eCos
-====
-
- curl does not use the eCos build system, so you must first build eCos
- separately, then link curl to the resulting eCos library. Here's a sample
- configure line to do so on an x86 Linux box targeting x86:
-
- GCCLIB=`gcc -print-libgcc-file-name` && \
- CFLAGS="-D__ECOS=1 -nostdinc -I$ECOS_INSTALL/include \
- -I`dirname $GCCLIB`/include" \
- LDFLAGS="-nostdlib -Wl,--gc-sections -Wl,-static \
- -L$ECOS_INSTALL/lib -Ttarget.ld -ltarget" \
- ./configure --host=i386 --disable-shared \
- --without-ssl --without-zlib --disable-manual --disable-ldap
-
- In most cases, eCos users will be using libcurl from within a custom
- embedded application. Using the standard 'curl' executable from
- within eCos means facing the limitation of the standard eCos C
- startup code which does not allow passing arguments in main(). To
- run 'curl' from eCos and have it do something useful, you will need
- to either modify the eCos startup code to pass in some arguments, or
- modify the curl application itself to retrieve its arguments from
- some location set by the bootloader or hard-code them.
-
- Something like the following patch could be used to hard-code some
- arguments. The MTAB_ENTRY line mounts a RAM disk as the root filesystem
- (without mounting some kind of filesystem, eCos errors out all file
- operations which curl does not take to well). The next section synthesizes
- some command-line arguments for curl to use, in this case to direct curl
- to read further arguments from a file. It then creates that file on the
- RAM disk and places within it a URL to download: a file: URL that
- just happens to point to the configuration file itself. The results
- of running curl in this way is the contents of the configuration file
- printed to the console.
-
---- src/main.c 19 Jul 2006 19:09:56 -0000 1.363
-+++ src/main.c 24 Jul 2006 21:37:23 -0000
-@@ -4286,11 +4286,31 @@
- }
-
-
-+#ifdef __ECOS
-+#include <cyg/fileio/fileio.h>
-+MTAB_ENTRY( testfs_mte1,
-+ "/",
-+ "ramfs",
-+ "",
-+ 0);
-+#endif
-
- int main(int argc, char *argv[])
- {
- int res;
- struct Configurable config;
-+#ifdef __ECOS
-+ char *args[] = {"ecos-curl", "-K", "curlconf.txt"};
-+ FILE *f;
-+ argc = sizeof(args)/sizeof(args[0]);
-+ argv = args;
-+
-+ f = fopen("curlconf.txt", "w");
-+ if (f) {
-+ fprintf(f, "--url file:curlconf.txt");
-+ fclose(f);
-+ }
-+#endif
- memset(&config, 0, sizeof(struct Configurable));
-
- config.errors = stderr; /* default errors to stderr */
-
-Minix
-=====
-
- curl can be compiled on Minix 3 using gcc or ACK (starting with
- ver. 3.1.3). Ensure that GNU gawk and bash are both installed and
- available in the PATH.
-
- ACK
- ---
- Increase the heap sizes of the compiler with the command:
-
- binsizes xxl
-
- then configure and compile curl with:
-
- ./configure CC=cc LD=cc AR=/usr/bin/aal GREP=grep \
- CPPFLAGS='-D_POSIX_SOURCE=1 -I/usr/local/include'
- make
- chmem =256000 src/curl
-
- GCC
- ---
- Make sure gcc is in your PATH with the command:
-
- export PATH=/usr/gnu/bin:$PATH
-
- then configure and compile curl with:
-
- ./configure CC=gcc AR=/usr/gnu/bin/gar GREP=grep
- make
- chmem =256000 src/curl
-
-Symbian OS
-==========
-
- The Symbian OS port uses the Symbian build system to compile. From the
- packages/Symbian/group/ directory, run:
-
- bldmake bldfiles
- abld build
-
- to compile and install curl and libcurl using SBSv1. If your Symbian
- SDK doesn't include support for P.I.P.S., you will need to contact
- your SDK vendor to obtain that first.
-
-VxWorks
-========
-
- Build for VxWorks is performed using cross compilation.
- That means you build on Windows machine using VxWorks tools and
- run the built image on the VxWorks device.
-
- To build libcurl for VxWorks you need:
-
- - CYGWIN (free, https://cygwin.com/)
- - Wind River Workbench (commercial)
-
- If you have CYGWIN and Workbench installed on you machine
- follow after next steps:
-
- 1. Open the Command Prompt window and change directory ('cd')
- to the libcurl 'lib' folder.
- 2. Add CYGWIN 'bin' folder to the PATH environment variable.
- For example, type 'set PATH=C:/embedded/cygwin/bin;%PATH%'.
- 3. Adjust environment variables defined in 'Environment' section
- of the Makefile.vxworks file to point to your software folders.
- 4. Build the libcurl by typing 'make -f ./Makefile.vxworks'
-
- As a result the libcurl.a library should be created in the 'lib' folder.
- To clean the build results type 'make -f ./Makefile.vxworks clean'.
-
-Android
-=======
-
- Method using the static makefile:
-
- - see the build notes in the packages/Android/Android.mk file.
-
- Method using a configure cross-compile (tested with Android NDK r7c, r8):
-
- - prepare the toolchain of the Android NDK for standalone use; this can
- be done by invoking the script:
- ./build/tools/make-standalone-toolchain.sh
- which creates a usual cross-compile toolchain. Lets assume that you put
- this toolchain below /opt then invoke configure with something like:
- export PATH=/opt/arm-linux-androideabi-4.4.3/bin:$PATH
- ./configure --host=arm-linux-androideabi [more configure options]
- make
- - if you want to compile directly from our GIT repo you might run into
- this issue with older automake stuff:
- checking host system type...
- Invalid configuration `arm-linux-androideabi':
- system `androideabi' not recognized
- configure: error: /bin/sh ./config.sub arm-linux-androideabi failed
- this issue can be fixed with using more recent versions of config.sub
- and config.guess which can be obtained here:
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=tree
- you need to replace your system-own versions which usually can be
- found in your automake folder:
- find /usr -name config.sub
-
- Wrapper for pkg-config:
-
- - In order to make proper use of pkg-config so that configure is able to
- find all dependencies you should create a wrapper script for pkg-config;
- file /opt/arm-linux-androideabi-4.4.3/bin/arm-linux-androideabi-pkg-config:
-
- #!/bin/sh
- SYSROOT=$(dirname ${0%/*})/sysroot
- export PKG_CONFIG_DIR=
- export PKG_CONFIG_LIBDIR=${SYSROOT}/usr/local/lib/pkgconfig:${SYSROOT}/usr/share/pkgconfig
- export PKG_CONFIG_SYSROOT_DIR=${SYSROOT}
- exec pkg-config "$@"
-
- also create a copy or symlink with name arm-unknown-linux-androideabi-pkg-config.
-
-CROSS COMPILE
-=============
-
- (This section was graciously brought to us by Jim Duey, with additions by
- Dan Fandrich)
-
- Download and unpack the cURL package.
-
- 'cd' to the new directory. (e.g. cd curl-7.12.3)
-
- Set environment variables to point to the cross-compile toolchain and call
- configure with any options you need. Be sure and specify the '--host' and
- '--build' parameters at configuration time. The following script is an
- example of cross-compiling for the IBM 405GP PowerPC processor using the
- toolchain from MonteVista for Hardhat Linux.
-
- (begin script)
-
- #! /bin/sh
-
- export PATH=$PATH:/opt/hardhat/devkit/ppc/405/bin
- export CPPFLAGS="-I/opt/hardhat/devkit/ppc/405/target/usr/include"
- export AR=ppc_405-ar
- export AS=ppc_405-as
- export LD=ppc_405-ld
- export RANLIB=ppc_405-ranlib
- export CC=ppc_405-gcc
- export NM=ppc_405-nm
-
- ./configure --target=powerpc-hardhat-linux \
- --host=powerpc-hardhat-linux \
- --build=i586-pc-linux-gnu \
- --prefix=/opt/hardhat/devkit/ppc/405/target/usr/local \
- --exec-prefix=/usr/local
-
- (end script)
-
- You may also need to provide a parameter like '--with-random=/dev/urandom'
- to configure as it cannot detect the presence of a random number
- generating device for a target system. The '--prefix' parameter
- specifies where cURL will be installed. If 'configure' completes
- successfully, do 'make' and 'make install' as usual.
-
- In some cases, you may be able to simplify the above commands to as
- little as:
-
- ./configure --host=ARCH-OS
-
-REDUCING SIZE
-=============
-
- There are a number of configure options that can be used to reduce the
- size of libcurl for embedded applications where binary size is an
- important factor. First, be sure to set the CFLAGS variable when
- configuring with any relevant compiler optimization flags to reduce the
- size of the binary. For gcc, this would mean at minimum the -Os option,
- and potentially the -march=X, -mdynamic-no-pic and -flto options as well,
- e.g.
-
- ./configure CFLAGS='-Os' LDFLAGS='-Wl,-Bsymbolic'...
-
- Note that newer compilers often produce smaller code than older versions
- due to improved optimization.
-
- Be sure to specify as many --disable- and --without- flags on the configure
- command-line as you can to disable all the libcurl features that you
- know your application is not going to need. Besides specifying the
- --disable-PROTOCOL flags for all the types of URLs your application
- will not use, here are some other flags that can reduce the size of the
- library:
-
- --disable-ares (disables support for the C-ARES DNS library)
- --disable-cookies (disables support for HTTP cookies)
- --disable-crypto-auth (disables HTTP cryptographic authentication)
- --disable-ipv6 (disables support for IPv6)
- --disable-manual (disables support for the built-in documentation)
- --disable-proxy (disables support for HTTP and SOCKS proxies)
- --disable-unix-sockets (disables support for UNIX sockets)
- --disable-verbose (eliminates debugging strings and error code strings)
- --disable-versioned-symbols (disables support for versioned symbols)
- --enable-hidden-symbols (eliminates unneeded symbols in the shared library)
- --without-libidn (disables support for the libidn DNS library)
- --without-librtmp (disables support for RTMP)
- --without-ssl (disables support for SSL/TLS)
- --without-zlib (disables support for on-the-fly decompression)
-
- The GNU compiler and linker have a number of options that can reduce the
- size of the libcurl dynamic libraries on some platforms even further.
- Specify them by providing appropriate CFLAGS and LDFLAGS variables on the
- configure command-line, e.g.
-
- CFLAGS="-Os -ffunction-sections -fdata-sections \
- -fno-unwind-tables -fno-asynchronous-unwind-tables -flto" \
- LDFLAGS="-Wl,-s -Wl,-Bsymbolic -Wl,--gc-sections"
-
- Be sure also to strip debugging symbols from your binaries after
- compiling using 'strip' (or the appropriate variant if cross-compiling).
- If space is really tight, you may be able to remove some unneeded
- sections of the shared library using the -R option to objcopy (e.g. the
- .comment section).
-
- Using these techniques it is possible to create a basic HTTP-only shared
- libcurl library for i386 Linux platforms that is only 109 KiB in size, and
- an FTP-only library that is 109 KiB in size (as of libcurl version 7.45.0,
- using gcc 4.9.2).
-
- You may find that statically linking libcurl to your application will
- result in a lower total size than dynamically linking.
-
- Note that the curl test harness can detect the use of some, but not all, of
- the --disable statements suggested above. Use will cause tests relying on
- those features to fail. The test harness can be manually forced to skip
- the relevant tests by specifying certain key words on the runtests.pl
- command line. Following is a list of appropriate key words:
-
- --disable-cookies !cookies
- --disable-manual !--manual
- --disable-proxy !HTTP\ proxy !proxytunnel !SOCKS4 !SOCKS5
-
-PORTS
-=====
-
- This is a probably incomplete list of known hardware and operating systems
- that curl has been compiled for. If you know a system curl compiles and
- runs on, that isn't listed, please let us know!
-
- - Alpha DEC OSF 4
- - Alpha Digital UNIX v3.2
- - Alpha FreeBSD 4.1, 4.5
- - Alpha Linux 2.2, 2.4
- - Alpha NetBSD 1.5.2
- - Alpha OpenBSD 3.0
- - Alpha OpenVMS V7.1-1H2
- - Alpha Tru64 v5.0 5.1
- - AVR32 Linux
- - ARM Android 1.5, 2.1, 2.3, 3.2, 4.x
- - ARM INTEGRITY
- - ARM iOS
- - Cell Linux
- - Cell Cell OS
- - HP-PA HP-UX 9.X 10.X 11.X
- - HP-PA Linux
- - HP3000 MPE/iX
- - MicroBlaze uClinux
- - MIPS IRIX 6.2, 6.5
- - MIPS Linux
- - OS/400
- - Pocket PC/Win CE 3.0
- - Power AIX 3.2.5, 4.2, 4.3.1, 4.3.2, 5.1, 5.2
- - PowerPC Darwin 1.0
- - PowerPC INTEGRITY
- - PowerPC Linux
- - PowerPC Mac OS 9
- - PowerPC Mac OS X
- - SH4 Linux 2.6.X
- - SH4 OS21
- - SINIX-Z v5
- - Sparc Linux
- - Sparc Solaris 2.4, 2.5, 2.5.1, 2.6, 7, 8, 9, 10
- - Sparc SunOS 4.1.X
- - StrongARM (and other ARM) RISC OS 3.1, 4.02
- - StrongARM/ARM7/ARM9 Linux 2.4, 2.6
- - StrongARM NetBSD 1.4.1
- - Symbian OS (P.I.P.S.) 9.x
- - TPF
- - Ultrix 4.3a
- - UNICOS 9.0
- - i386 BeOS
- - i386 DOS
- - i386 eCos 1.3.1
- - i386 Esix 4.1
- - i386 FreeBSD
- - i386 HURD
- - i386 Haiku OS
- - i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4, 2.6
- - i386 Mac OS X
- - i386 MINIX 3.1
- - i386 NetBSD
- - i386 Novell NetWare
- - i386 OS/2
- - i386 OpenBSD
- - i386 QNX 6
- - i386 SCO unix
- - i386 Solaris 2.7
- - i386 Windows 95, 98, ME, NT, 2000, XP, 2003
- - i486 ncr-sysv4.3.03 (NCR MP-RAS)
- - ia64 Linux 2.3.99
- - m68k AmigaOS 3
- - m68k Linux
- - m68k uClinux
- - m68k OpenBSD
- - m88k dg-dgux5.4R3.00
- - s390 Linux
- - x86_64 Linux
- - XScale/PXA250 Linux 2.4
- - Nios II uClinux
-
-Useful URLs
-===========
-
-axTLS http://axtls.sourceforge.net/
-c-ares http://c-ares.haxx.se/
-GNU GSS https://www.gnu.org/software/gss/
-GnuTLS https://www.gnu.org/software/gnutls/
-Heimdal http://www.h5l.org/
-libidn https://www.gnu.org/software/libidn/
-libmetalink https://launchpad.net/libmetalink/
-libssh2 https://www.libssh2.org/
-MIT Kerberos http://web.mit.edu/kerberos/www/dist/
-NSS https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS
-OpenLDAP http://www.openldap.org/
-OpenSSL https://www.openssl.org/
-PolarSSL https://tls.mbed.org/
-wolfSSL https://www.wolfssl.com/wolfSSL/
-Zlib http://www.zlib.net/
-
-MingW http://www.mingw.org/
-MinGW-w64 http://mingw-w64.sourceforge.net/
-OpenWatcom http://www.openwatcom.org/
+see INSTALL.md
diff --git a/docs/INSTALL.devcpp b/docs/INSTALL.devcpp
deleted file mode 100644
index f989d529..00000000
--- a/docs/INSTALL.devcpp
+++ /dev/null
@@ -1,302 +0,0 @@
-DevCpp-Mingw Install & Compilation Sept 2005
-==================================
-
-Reference Emails available at curl@haxx.se:
-
- Libcurl Install and Use Issues
- Awaiting an Answer for Win 32 Install
- res = curl_easy_perform(curl); Error
- Makefile Issues
-
-
-Having previously done a thorough review of what was available that met my
-requirements under GPL, I settled for Libcurl as the software of choice for
-many reasons not the least of which was the support.
-
-Background
-----------
-
-This quest started when I innocently tried to incorporate the libcurl library
-into my simple source code. I figured that a few easy steps would accomplish
-this without major headaches. I had no idea that I would be facing an almost
-insurmountable challenge.
-
-The main problem lies in two areas. First the bulk of support for libcurl
-exists for a Unix/linux command line environments. This is of little help when
-it comes to Windows O/S.
-
-Secondly the help that does exist for the Windows O/S focused around mingw
-through a command line argument environment.
-
-You may ask "Why is this a problem?"
-
-I'm using a Windows O/S with DevCpp. For those of you who are unfamiliar with
-DevCpp, it is a window shell GUI that replaces the command line environment
-for gcc. A definite improvement that I am unwilling to give up. However using
-DevCpp presented its own set of issues. Inadvertently I also made some
-careless errors such as compiling the 7.14 version of Makefile with an older
-version of source code. Thanks to Dan Fandrich for picking this up.
-
-I did eventually with the help of Daniel, Phillipe and others manage to
-implement successfully (the only mingw available version)
-curl-7.13.0-win32-ssl-devel-mingw32 into the DevCpp environment. Only the
-dynamic libcurl.dll libcurldll.a libraries worked. The static library which I
-was interested in did not. Furthermore when I tried to implement one of the
-examples included with the curl package (get info.c) it caused the executable
-to crash. Tracing the bug I found it in the code and function res =
-curl_easy_perform(curl);.
-
-At this point I had to make a choice as to whether invest my limited
-time-energy resource to fixing the bug or to compile the new version
-available. After searching the archives I found a very similar or the same bug
-reported from version 7.12x on. Daniel did inform me that he thought that this
-bug had been fixed with the latest version. So I proceeded to compile the
-latest SSL version where I faced other challenges.
-
-In order to make this process unremarkable for others using the same
-environment I decided to document the process so that others will find it
-routine. It would be a shame if newbies could not implement this excellent
-package for their use.
-
-I would like to thank the many others in this forum and in the DevCpp forum
-for their help. Without your help I may either have given up or it would have
-taken me many times longer to achieve success.
-
-The Cookbook Approach
----------------------
-
-This discussion will be confined to a SSL static library compilation and
-installation. Limited mention and comments will be inserted where appropriate
-to help with non-SSL, dynamic libraries and executables.
-
-
- Using Makefile from DevCpp to compile Libcurl libraries
-
-Preamble
---------
-
-Using the latest version release - curl-7.14.0.tar.gz. Curl source code is
-platform independent. This simply means that the source code can be compiled
-for any Operating System (Linux/Unix Windows etc. and variations of thereof).
-
-The first thing to note is that inside curl-7.14.0 you will find two folders
-lib and src. Both contain Makefile.m32 (required for win mingw library or exe
-compilation) files which are different. The main difference between these two
-folders and the makefiles is that the src folder contents are used to compile
-an executable file(curl.exe) while the lib folder contents are used to compile
-a static (libcurl.a) and dynamic (libcurl.dll & libcurldll.a) file that can be
-used to compile libcurl with your own source code so that one can use and
-access all libcurl functions.
-
-Before we start please make sure that DevCpp is installed properly. In
-particular make sure you have no spaces in the name of any of the directories
-and subdirectories where DevCpp is installed. Failure to comply with the
-install instructions may produce erratic behaviour in DevCpp. For further info
-check the following sites
-
-http://aditsu.freeunixhost.com/dev-cpp-faq.html
-https://sourceforge.net/p/dev-cpp/discussion/48211/thread/2a85ea46
-
-As I have mentioned before I will confine this to the SSL Library compilations
-but the process is very similar for compilation of the executable - curl.exe;
-just substitute the src folder makefile in its stead.
-
-First use a text processor Notepad, or your own favourite text processor. To
-engage your favourite text processor, select Makefile.m32 click once with your
-mouse on file icon; icon turns blue, press the shift key and right-click on
-mouse, menu appears select "Open with", select your favourite text processor.
-
-Next read the contents of Makefile.m32. It includes instructions on its use.
-
-Method I - DOS Command Line
----------------------------
-
-Note - The only reason I have included this method is that Method II which is
-the preferred method for compiling does not allow for the setting of option
-switches (e.g. SSL = 1 or SSL =0). At least that's what they tell me at the
-Dev-Cpp forum.
-
-1 - Make a copy of (D:\Dev-Cpp\bin) bin folder and name it "bin Original"
-place it in the Dev-Cpp installed directory (D:\Dev-Cpp\ for this example)
-
-2 - Copy the entire contents of the LIB folder of curl-7.14.0.tar.gz or zip
-version into the bin folder above (D:\Dev-Cpp\bin). The reason being is that
-the make.exe file resides in this folder. Make.exe will use - Makefile.m32,
-Makefile.inc, and the source code included in the lib folder to compile the
-source code. There is a PATH issue with make.exe that remains unresolved at
-least for me. Unless the entire source code to be compiled is placed entirely
-within the directory of make.exe an error message will be generated - "file
-xxxx.yyy not available".
-
-3- Go to Dev-Cpp\bin and double click on make .exe. You will see a DOS window
-quickly pop up and close very quickly. Not to worry! Please do not skip this
-step.
-
-4- Click on the start button\Programs\MS-DOS Prompt.Once the DOS Window is up
-Type the disk drive letter (e.g. E: ) engage the enter button. The path should
-automatically take you to the directory of the make.exe file.
-
-5- To compile the source code simply type at the DOS prompt make -f
-Makefile.m32 as per instructions contained in the Makefile.m32 file (use any
-text processor to read instructions). I don't believe that this makefile
-allows for the option of non SSL. Ignore any warnings.
-
-6- Collect and make copies of libcurl.a, libcurl.dll, libcurldll.a and any *.o
-compilations you might need in another directory outside of the bin directory
-as you will need this files shortly to set up libcurl for use with
-Dev-cpp. For most apps *.o is not required. Later on we will show what to do
-with these files.
-
-7- You are finished but before closing we need to do cleanup - erase the bin
-folder and rename the "bin Original" folder created in step 1 to bin.
-
-Note to compile a curl executable the process is probably similar but instead
-of using the LIB folder contents use the SRC folder contents and Makefiles in
-curl-7.14.0.tar.gz. File directories relative placements must be respected for
-compiling to take place successfully. This may not be possible with the PATH
-problem that make.exe experiences. If anyone has solved this PATH issue and
-please make sure it actually works on Win 9x/2000/XP before letting me
-know. Then please let me or Daniel in on the solution so that it can be
-included with these instructions. Thanks.
-
-or
-
-Method II - Dev-Cpp GUI
------------------------
-
-1- Copy the entire contents of the LIB folder of curl-7.14.0.tar.gz or zip
-version into any folder outside of (Dev-Cpp\bin).
-
-2- Drop the File/New/click on Project.
-
-3- New Project Dialogue box appears. Double click on the Static Library.
-
-4- Create Project Dialogue box appears. Select the LIB folder location to
-place and locate your Project File Name. Placing the Project File Name
-elsewhere may cause problems (PATH issue problem again).
-
-5- Drop down the Project/Project Options. Project Options Dialogue box
-appears.
-
-6- Select the Makefile tab in the Project Options Dialogue Box. Check Box -
-Use Custom Makefile. Click on the Folder icon at the extreme right of the
-Check Box. Select Makefile.m32 in the folder wherever you have placed the
-contents of the LIB Folder. Press OK and close the Dialogue Box.
-
-7- Drop the Menu Project/Click on Add to Project. Open File Dialogue Box
-appears. The Dialogue Box should open in the folder wherever you have placed
-the contents of the LIB Folder. If not go there.
-
-8- Select Crtl-A to select all files in the LIB folder. Click on open to add
-files and close box. Wait till all files are added. This may take 30 seconds
-or longer.
-
-9- Drop the Menu Execute/Click on Compile.
-
-10- That's it.
-
-
- The following steps must be completed if Curl is to work properly
- =================================================================
-
-LIB folder inclusions (*.a placement)
--------------------------------------
-
-1- Refer to Method I - DOS Command Line point # 6 Take libcurl.a, libcurldll.a
-and install it in the directory C( or whichever drive Dev is installed)
-:\Dev-Cpp\lib.
-
-
-Include Folder
---------------
-
-1- Create a new folder by the name of curl (do not change the name curl to
-some other name as it will cause major issues) in the directory
-C:\Dev-Cpp\include.
-
-2- Copy the entire contents of the curl folder of curl-7.14.0.tar.gz or zip
- version into the newly created curl directory - C:\Dev-Cpp\include\curl.
-
-Links To Include And Lib Folder
--------------------------------
-
-1- Drop the Menu - Tools\Compiler Options\Directories\Libraries. Make sure
-that C( or whichever drive Dev is installed):\DEV-CPP\lib is included.
-
-2- Next select the Menu - Tools\Compiler Options\Directories\C Includes. Make
-sure that C:\DEV-CPP\include and C:\Dev-Cpp\include\curl are included.
-
-3- Next select the Menu - Tools\Compiler Options\Directories\C++
-Includes. Make sure that C:\DEV-CPP\include and C:\Dev-Cpp\include\curl are
-included.
-
-Linker Links
-------------
-
-1- Drop the Menu - Tools\Compiler Options\Directories\Compiler.
-
-2- Make sure that the box "Add these commands to the linker command line" is
-checked.
-
-3- Include in the white space immediately below the box referred in 2 -lcurl
--lws2_32.
-
-SSL Files
----------
-
-1- Get the latest openSSL (as of time of this writing)
-openssl-0.9.7e-win32-bin.zip for the minimalist package of the openssl-0.9.7e
-binaries ported to MS Windows 95/98/NT/XP using the MingW32/GCC-3.1
-development environment. The file may be downloaded at
-https://curl.haxx.se/download/.
-
-2- Open the above zip file. You will find two files - SDL.dll,
-SDL_mixer.dll. Install them in the directory C:\WINDOWS\SYSTEM32 for Win 9x
-users and c:\winnt\system32 for NT-family users.
-
-Multithreading Files
---------------------
-
-To be completed
-
-#define
--------
-
-1- Make sure that your program includes the following - #define CURL_STATICLIB
-must be declared FIRST before any other define functions may be
-added. Otherwise you may experience link errors.
-
-2- Don't forget to include #include "curl/curl.h".
-
-e.g.
- #define CURL_STATICLIB
-#include <windows.h>
- #include "curl/curl.h"
-#include <fstream>
-#include <iostream>
-#include <vector>
-etc...
-
-
-Static or Dynamic Library
--------------------------
-
-The above steps apply for the use by a static library. Should you choose to
-use a dynamic library you will be required to perform these additional steps.
-
-1- Refer to Method I - DOS Command Line point # 6. Install libcurl.dll in the
-directory C:\WINDOWS\SYSTEM32 for Win 9x users and c:\winnt\system32 for
-NT-family users.
-
-2- Refer to Linker Links point 3 - Replace -lcurl with -lcurldll.
-
-Voila you're done.
-
-The non-SSL static Library build may not be possible to use at least as of the
-time of this writing - v7.14. Check reference emails - Phillipe and I found it
-impossible to fully compile as certain files were missing for linking. No big
-loss as SSL is a major plus.
-
-Hope this Helps
-
-Tom
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
new file mode 100644
index 00000000..610add65
--- /dev/null
+++ b/docs/INSTALL.md
@@ -0,0 +1,513 @@
+# how to install curl and libcurl
+
+## Installing Binary Packages
+
+Lots of people download binary distributions of curl and libcurl. This
+document does not describe how to install curl or libcurl using such a binary
+package. This document describes how to compile, build and install curl and
+libcurl from source code.
+
+## Building from git
+
+If you get your code off a git repository instead of a release tarball, see
+the `GIT-INFO` file in the root directory for specific instructions on how to
+proceed.
+
+# Unix
+
+A normal Unix installation is made in three or four steps (after you've
+unpacked the source archive):
+
+ ./configure
+ make
+ make test (optional)
+ make install
+
+You probably need to be root when doing the last command.
+
+Get a full listing of all available configure options by invoking it like:
+
+ ./configure --help
+
+If you want to install curl in a different file hierarchy than `/usr/local`,
+specify that when running configure:
+
+ ./configure --prefix=/path/to/curl/tree
+
+If you have write permission in that directory, you can do 'make install'
+without being root. An example of this would be to make a local install in
+your own home directory:
+
+ ./configure --prefix=$HOME
+ make
+ make install
+
+The configure script always tries to find a working SSL library unless
+explicitly told not to. If you have OpenSSL installed in the default search
+path for your compiler/linker, you don't need to do anything special. If you
+have OpenSSL installed in /usr/local/ssl, you can run configure like:
+
+ ./configure --with-ssl
+
+If you have OpenSSL installed somewhere else (for example, /opt/OpenSSL) and
+you have pkg-config installed, set the pkg-config path first, like this:
+
+ env PKG_CONFIG_PATH=/opt/OpenSSL/lib/pkgconfig ./configure --with-ssl
+
+Without pkg-config installed, use this:
+
+ ./configure --with-ssl=/opt/OpenSSL
+
+If you insist on forcing a build without SSL support, even though you may
+have OpenSSL installed in your system, you can run configure like this:
+
+ ./configure --without-ssl
+
+If you have OpenSSL installed, but with the libraries in one place and the
+header files somewhere else, you have to set the LDFLAGS and CPPFLAGS
+environment variables prior to running configure. Something like this should
+work:
+
+ CPPFLAGS="-I/path/to/ssl/include" LDFLAGS="-L/path/to/ssl/lib" ./configure
+
+If you have shared SSL libs installed in a directory where your run-time
+linker doesn't find them (which usually causes configure failures), you can
+provide the -R option to ld on some operating systems to set a hard-coded
+path to the run-time linker:
+
+ LDFLAGS=-R/usr/local/ssl/lib ./configure --with-ssl
+
+## More Options
+
+To force a static library compile, disable the shared library creation by
+running configure like:
+
+ ./configure --disable-shared
+
+To tell the configure script to skip searching for thread-safe functions, add
+an option like:
+
+ ./configure --disable-thread
+
+If you're a curl developer and use gcc, you might want to enable more debug
+options with the `--enable-debug` option.
+
+curl can be built to use a whole range of libraries to provide various useful
+services, and configure will try to auto-detect a decent default. But if you
+want to alter it, you can select how to deal with each individual library.
+
+## Select TLS backend
+
+The default OpenSSL configure check will also detect and use BoringSSL or
+libressl.
+
+ - GnuTLS: `--without-ssl --with-gnutls`.
+ - Cyassl: `--without-ssl --with-cyassl`
+ - NSS: `--without-ssl --with-nss`
+ - PolarSSL: `--without-ssl --with-polarssl`
+ - mbedTLS: `--without-ssl --with-mbedtls`
+ - axTLS: `--without-ssl --with-axtls`
+ - schannel: `--without-ssl --with-winssl`
+ - secure transport: `--with-winssl --with-darwinssl`
+
+# Windows
+
+## Building Windows DLLs and C run-time (CRT) linkage issues
+
+ As a general rule, building a DLL with static CRT linkage is highly
+ discouraged, and intermixing CRTs in the same app is something to avoid at
+ any cost.
+
+ Reading and comprehending Microsoft Knowledge Base articles KB94248 and
+ KB140584 is a must for any Windows developer. Especially important is full
+ understanding if you are not going to follow the advice given above.
+
+ - [How To Use the C Run-Time](https://support.microsoft.com/kb/94248/en-us)
+ - [How to link with the correct C Run-Time CRT library](https://support.microsoft.com/kb/140584/en-us)
+ - [Potential Errors Passing CRT Objects Across DLL Boundaries](https://msdn.microsoft.com/en-us/library/ms235460)
+
+If your app is misbehaving in some strange way, or it is suffering from
+memory corruption, before asking for further help, please try first to
+rebuild every single library your app uses as well as your app using the
+debug multithreaded dynamic C runtime.
+
+ If you get linkage errors read section 5.7 of the FAQ document.
+
+## MingW32
+
+Make sure that MinGW32's bin dir is in the search path, for example:
+
+ set PATH=c:\mingw32\bin;%PATH%
+
+then run `mingw32-make mingw32` in the root dir. There are other
+make targets available to build libcurl with more features, use:
+
+ - `mingw32-make mingw32-zlib` to build with Zlib support;
+ - `mingw32-make mingw32-ssl-zlib` to build with SSL and Zlib enabled;
+ - `mingw32-make mingw32-ssh2-ssl-zlib` to build with SSH2, SSL, Zlib;
+ - `mingw32-make mingw32-ssh2-ssl-sspi-zlib` to build with SSH2, SSL, Zlib
+ and SSPI support.
+
+If you have any problems linking libraries or finding header files, be sure
+to verify that the provided "Makefile.m32" files use the proper paths, and
+adjust as necessary. It is also possible to override these paths with
+environment variables, for example:
+
+ set ZLIB_PATH=c:\zlib-1.2.8
+ set OPENSSL_PATH=c:\openssl-1.0.2c
+ set LIBSSH2_PATH=c:\libssh2-1.6.0
+
+It is also possible to build with other LDAP SDKs than MS LDAP; currently
+it is possible to build with native Win32 OpenLDAP, or with the Novell CLDAP
+SDK. If you want to use these you need to set these vars:
+
+ set LDAP_SDK=c:\openldap
+ set USE_LDAP_OPENLDAP=1
+
+or for using the Novell SDK:
+
+ set USE_LDAP_NOVELL=1
+
+If you want to enable LDAPS support then set LDAPS=1.
+
+## Cygwin
+
+Almost identical to the unix installation. Run the configure script in the
+curl source tree root with `sh configure`. Make sure you have the sh
+executable in /bin/ or you'll see the configure fail toward the end.
+
+Run `make`
+
+## Borland C++ compiler
+
+Ensure that your build environment is properly set up to use the compiler and
+associated tools. PATH environment variable must include the path to bin
+subdirectory of your compiler installation, eg: `c:\Borland\BCC55\bin`
+
+It is advisable to set environment variable BCCDIR to the base path of the
+compiler installation.
+
+ set BCCDIR=c:\Borland\BCC55
+
+In order to build a plain vanilla version of curl and libcurl run the
+following command from curl's root directory:
+
+ make borland
+
+To build curl and libcurl with zlib and OpenSSL support set environment
+variables `ZLIB_PATH` and `OPENSSL_PATH` to the base subdirectories of the
+already built zlib and OpenSSL libraries and from curl's root directory run
+command:
+
+ make borland-ssl-zlib
+
+libcurl library will be built in 'lib' subdirectory while curl tool is built
+in 'src' subdirectory. In order to use libcurl library it is advisable to
+modify compiler's configuration file bcc32.cfg located in
+`c:\Borland\BCC55\bin` to reflect the location of libraries include paths for
+example the '-I' line could result in something like:
+
+ -I"c:\Borland\BCC55\include;c:\curl\include;c:\openssl\inc32"
+
+bcc3.cfg `-L` line could also be modified to reflect the location of of
+libcurl library resulting for example:
+
+ -L"c:\Borland\BCC55\lib;c:\curl\lib;c:\openssl\out32"
+
+In order to build sample program `simple.c` from the docs\examples
+subdirectory run following command from mentioned subdirectory:
+
+ bcc32 simple.c libcurl.lib cw32mt.lib
+
+In order to build sample program simplessl.c an SSL enabled libcurl is
+required, as well as the OpenSSL libeay32.lib and ssleay32.lib libraries.
+
+## Disabling Specific Protocols in Windows builds
+
+The configure utility, unfortunately, is not available for the Windows
+environment, therefore, you cannot use the various disable-protocol options of
+the configure utility on this platform.
+
+However, you can use the following defines to disable specific
+protocols:
+
+ - `HTTP_ONLY` disables all protocols except HTTP
+ - `CURL_DISABLE_FTP` disables FTP
+ - `CURL_DISABLE_LDAP` disables LDAP
+ - `CURL_DISABLE_TELNET` disables TELNET
+ - `CURL_DISABLE_DICT` disables DICT
+ - `CURL_DISABLE_FILE` disables FILE
+ - `CURL_DISABLE_TFTP` disables TFTP
+ - `CURL_DISABLE_HTTP` disables HTTP
+ - `CURL_DISABLE_IMAP` disables IMAP
+ - `CURL_DISABLE_POP3` disables POP3
+ - `CURL_DISABLE_SMTP` disables SMTP
+
+If you want to set any of these defines you have the following options:
+
+ - Modify lib/config-win32.h
+ - Modify lib/curl_setup.h
+ - Modify lib/Makefile.vc6
+ - Modify the "Preprocessor Definitions" in the libcurl project
+
+Note: The pre-processor settings can be found using the Visual Studio IDE
+under "Project -> Settings -> C/C++ -> General" in VC6 and "Project ->
+Properties -> Configuration Properties -> C/C++ -> Preprocessor" in later
+versions.
+
+## Using BSD-style lwIP instead of Winsock TCP/IP stack in Win32 builds
+
+In order to compile libcurl and curl using BSD-style lwIP TCP/IP stack it is
+necessary to make definition of preprocessor symbol USE_LWIPSOCK visible to
+libcurl and curl compilation processes. To set this definition you have the
+following alternatives:
+
+ - Modify lib/config-win32.h and src/config-win32.h
+ - Modify lib/Makefile.vc6
+ - Modify the "Preprocessor Definitions" in the libcurl project
+
+Note: The pre-processor settings can be found using the Visual Studio IDE
+under "Project -> Settings -> C/C++ -> General" in VC6 and "Project ->
+Properties -> Configuration Properties -> C/C++ -> Preprocessor" in later
+versions.
+
+Once that libcurl has been built with BSD-style lwIP TCP/IP stack support, in
+order to use it with your program it is mandatory that your program includes
+lwIP header file `<lwip/opt.h>` (or another lwIP header that includes this)
+before including any libcurl header. Your program does not need the
+`USE_LWIPSOCK` preprocessor definition which is for libcurl internals only.
+
+Compilation has been verified with [lwIP
+1.4.0](http://download.savannah.gnu.org/releases/lwip/lwip-1.4.0.zip) and
+[contrib-1.4.0](http://download.savannah.gnu.org/releases/lwip/contrib-1.4.0.zip).
+
+This BSD-style lwIP TCP/IP stack support must be considered experimental given
+that it has been verified that lwIP 1.4.0 still needs some polish, and libcurl
+might yet need some additional adjustment, caveat emptor.
+
+## Important static libcurl usage note
+
+When building an application that uses the static libcurl library on Windows,
+you must add `-DCURL_STATICLIB` to your `CFLAGS`. Otherwise the linker will
+look for dynamic import symbols.
+
+## Legacy Windows and SSL
+
+WinSSL (specifically SChannel from Windows SSPI), is the native SSL library in
+Windows. However, WinSSL in Windows <= XP is unable to connect to servers that
+no longer support the legacy handshakes and algorithms used by those
+versions. If you will be using curl in one of those earlier versions of
+Windows you should choose another SSL backend such as OpenSSL.
+
+# Apple iOS and Mac OS X
+
+On modern Apple operating systems, curl can be built to use Apple's SSL/TLS
+implementation, Secure Transport, instead of OpenSSL. To build with Secure
+Transport for SSL/TLS, use the configure option `--with-darwinssl`. (It is not
+necessary to use the option `--without-ssl`.) This feature requires iOS 5.0 or
+later, or OS X 10.5 ("Leopard") or later.
+
+When Secure Transport is in use, the curl options `--cacert` and `--capath`
+and their libcurl equivalents, will be ignored, because Secure Transport uses
+the certificates stored in the Keychain to evaluate whether or not to trust
+the server. This, of course, includes the root certificates that ship with the
+OS. The `--cert` and `--engine` options, and their libcurl equivalents, are
+currently unimplemented in curl with Secure Transport.
+
+For OS X users: In OS X 10.8 ("Mountain Lion"), Apple made a major overhaul to
+the Secure Transport API that, among other things, added support for the newer
+TLS 1.1 and 1.2 protocols. To get curl to support TLS 1.1 and 1.2, you must
+build curl on Mountain Lion or later, or by using the equivalent SDK. If you
+set the `MACOSX_DEPLOYMENT_TARGET` environmental variable to an earlier
+version of OS X prior to building curl, then curl will use the new Secure
+Transport API on Mountain Lion and later, and fall back on the older API when
+the same curl binary is executed on older cats. For example, running these
+commands in curl's directory in the shell will build the code such that it
+will run on cats as old as OS X 10.6 ("Snow Leopard") (using bash):
+
+ export MACOSX_DEPLOYMENT_TARGET="10.6"
+ ./configure --with-darwinssl
+ make
+
+# Cross compile
+
+Download and unpack the curl package.
+
+'cd' to the new directory. (e.g. `cd curl-7.12.3`)
+
+Set environment variables to point to the cross-compile toolchain and call
+configure with any options you need. Be sure and specify the `--host` and
+`--build` parameters at configuration time. The following script is an
+example of cross-compiling for the IBM 405GP PowerPC processor using the
+toolchain from MonteVista for Hardhat Linux.
+
+ #! /bin/sh
+
+ export PATH=$PATH:/opt/hardhat/devkit/ppc/405/bin
+ export CPPFLAGS="-I/opt/hardhat/devkit/ppc/405/target/usr/include"
+ export AR=ppc_405-ar
+ export AS=ppc_405-as
+ export LD=ppc_405-ld
+ export RANLIB=ppc_405-ranlib
+ export CC=ppc_405-gcc
+ export NM=ppc_405-nm
+
+ ./configure --target=powerpc-hardhat-linux
+ --host=powerpc-hardhat-linux
+ --build=i586-pc-linux-gnu
+ --prefix=/opt/hardhat/devkit/ppc/405/target/usr/local
+ --exec-prefix=/usr/local
+
+You may also need to provide a parameter like `--with-random=/dev/urandom` to
+configure as it cannot detect the presence of a random number generating
+device for a target system. The `--prefix` parameter specifies where curl
+will be installed. If `configure` completes successfully, do `make` and `make
+install` as usual.
+
+In some cases, you may be able to simplify the above commands to as little as:
+
+ ./configure --host=ARCH-OS
+
+# REDUCING SIZE
+
+There are a number of configure options that can be used to reduce the size of
+libcurl for embedded applications where binary size is an important factor.
+First, be sure to set the CFLAGS variable when configuring with any relevant
+compiler optimization flags to reduce the size of the binary. For gcc, this
+would mean at minimum the -Os option, and potentially the `-march=X`,
+`-mdynamic-no-pic` and `-flto` options as well, e.g.
+
+ ./configure CFLAGS='-Os' LDFLAGS='-Wl,-Bsymbolic'...
+
+Note that newer compilers often produce smaller code than older versions
+due to improved optimization.
+
+Be sure to specify as many `--disable-` and `--without-` flags on the
+configure command-line as you can to disable all the libcurl features that you
+know your application is not going to need. Besides specifying the
+`--disable-PROTOCOL` flags for all the types of URLs your application will not
+use, here are some other flags that can reduce the size of the library:
+
+ - `--disable-ares` (disables support for the C-ARES DNS library)
+ - `--disable-cookies` (disables support for HTTP cookies)
+ - `--disable-crypto-auth` (disables HTTP cryptographic authentication)
+ - `--disable-ipv6` (disables support for IPv6)
+ - `--disable-manual` (disables support for the built-in documentation)
+ - `--disable-proxy` (disables support for HTTP and SOCKS proxies)
+ - `--disable-unix-sockets` (disables support for UNIX sockets)
+ - `--disable-verbose` (eliminates debugging strings and error code strings)
+ - `--disable-versioned-symbols` (disables support for versioned symbols)
+ - `--enable-hidden-symbols` (eliminates unneeded symbols in the shared library)
+ - `--without-libidn` (disables support for the libidn DNS library)
+ - `--without-librtmp` (disables support for RTMP)
+ - `--without-ssl` (disables support for SSL/TLS)
+ - `--without-zlib` (disables support for on-the-fly decompression)
+
+The GNU compiler and linker have a number of options that can reduce the
+size of the libcurl dynamic libraries on some platforms even further.
+Specify them by providing appropriate CFLAGS and LDFLAGS variables on the
+configure command-line, e.g.
+
+ CFLAGS="-Os -ffunction-sections -fdata-sections
+ -fno-unwind-tables -fno-asynchronous-unwind-tables -flto"
+ LDFLAGS="-Wl,-s -Wl,-Bsymbolic -Wl,--gc-sections"
+
+Be sure also to strip debugging symbols from your binaries after compiling
+using 'strip' (or the appropriate variant if cross-compiling). If space is
+really tight, you may be able to remove some unneeded sections of the shared
+library using the -R option to objcopy (e.g. the .comment section).
+
+Using these techniques it is possible to create a basic HTTP-only shared
+libcurl library for i386 Linux platforms that is only 113 KiB in size, and an
+FTP-only library that is 113 KiB in size (as of libcurl version 7.50.3, using
+gcc 5.4.0).
+
+You may find that statically linking libcurl to your application will result
+in a lower total size than dynamically linking.
+
+Note that the curl test harness can detect the use of some, but not all, of
+the `--disable` statements suggested above. Use will cause tests relying on
+those features to fail. The test harness can be manually forced to skip the
+relevant tests by specifying certain key words on the runtests.pl command
+line. Following is a list of appropriate key words:
+
+ - `--disable-cookies` !cookies
+ - `--disable-manual` !--manual
+ - `--disable-proxy` !HTTP\ proxy !proxytunnel !SOCKS4 !SOCKS5
+
+# PORTS
+
+This is a probably incomplete list of known hardware and operating systems
+that curl has been compiled for. If you know a system curl compiles and
+runs on, that isn't listed, please let us know!
+
+ - Alpha DEC OSF 4
+ - Alpha Digital UNIX v3.2
+ - Alpha FreeBSD 4.1, 4.5
+ - Alpha Linux 2.2, 2.4
+ - Alpha NetBSD 1.5.2
+ - Alpha OpenBSD 3.0
+ - Alpha OpenVMS V7.1-1H2
+ - Alpha Tru64 v5.0 5.1
+ - AVR32 Linux
+ - ARM Android 1.5, 2.1, 2.3, 3.2, 4.x
+ - ARM INTEGRITY
+ - ARM iOS
+ - Cell Linux
+ - Cell Cell OS
+ - HP-PA HP-UX 9.X 10.X 11.X
+ - HP-PA Linux
+ - HP3000 MPE/iX
+ - MicroBlaze uClinux
+ - MIPS IRIX 6.2, 6.5
+ - MIPS Linux
+ - OS/400
+ - Pocket PC/Win CE 3.0
+ - Power AIX 3.2.5, 4.2, 4.3.1, 4.3.2, 5.1, 5.2
+ - PowerPC Darwin 1.0
+ - PowerPC INTEGRITY
+ - PowerPC Linux
+ - PowerPC Mac OS 9
+ - PowerPC Mac OS X
+ - SH4 Linux 2.6.X
+ - SH4 OS21
+ - SINIX-Z v5
+ - Sparc Linux
+ - Sparc Solaris 2.4, 2.5, 2.5.1, 2.6, 7, 8, 9, 10
+ - Sparc SunOS 4.1.X
+ - StrongARM (and other ARM) RISC OS 3.1, 4.02
+ - StrongARM/ARM7/ARM9 Linux 2.4, 2.6
+ - StrongARM NetBSD 1.4.1
+ - Symbian OS (P.I.P.S.) 9.x
+ - TPF
+ - Ultrix 4.3a
+ - UNICOS 9.0
+ - i386 BeOS
+ - i386 DOS
+ - i386 eCos 1.3.1
+ - i386 Esix 4.1
+ - i386 FreeBSD
+ - i386 HURD
+ - i386 Haiku OS
+ - i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4, 2.6
+ - i386 Mac OS X
+ - i386 MINIX 3.1
+ - i386 NetBSD
+ - i386 Novell NetWare
+ - i386 OS/2
+ - i386 OpenBSD
+ - i386 QNX 6
+ - i386 SCO unix
+ - i386 Solaris 2.7
+ - i386 Windows 95, 98, ME, NT, 2000, XP, 2003
+ - i486 ncr-sysv4.3.03 (NCR MP-RAS)
+ - ia64 Linux 2.3.99
+ - m68k AmigaOS 3
+ - m68k Linux
+ - m68k uClinux
+ - m68k OpenBSD
+ - m88k dg-dgux5.4R3.00
+ - s390 Linux
+ - x86_64 Linux
+ - XScale/PXA250 Linux 2.4
+ - Nios II uClinux
diff --git a/docs/INTERNALS b/docs/INTERNALS.md
index 565d9df6..77b993ec 100644
--- a/docs/INTERNALS
+++ b/docs/INTERNALS.md
@@ -1,5 +1,5 @@
-Table of Contents
-=================
+curl internals
+==============
- [Intro](#intro)
- [git](#git)
@@ -40,8 +40,8 @@ Table of Contents
- [Structs in libcurl](#structs)
<a name="intro"></a>
-curl internals
-==============
+Intro
+=====
This project is split in two. The library and the client. The client part
uses the library, but the library is designed to allow other applications to
@@ -174,7 +174,7 @@ Library
rather small and easy-to-follow. All the ones prefixed with `curl_easy` are
put in the lib/easy.c file.
- `curl_global_init_()` and `curl_global_cleanup()` should be called by the
+ `curl_global_init()` and `curl_global_cleanup()` should be called by the
application to initialize and clean up global stuff in the library. As of
today, it can handle the global SSL initing if SSL is enabled and it can init
the socket layer on windows machines. libcurl itself has no "global" scope.
@@ -184,14 +184,14 @@ Library
[ `curl_easy_init()`][2] allocates an internal struct and makes some
initializations. The returned handle does not reveal internals. This is the
- 'Curl_easy' struct which works as an "anchor" struct for all `curl_easy`
+ `Curl_easy` struct which works as an "anchor" struct for all `curl_easy`
functions. All connections performed will get connect-specific data allocated
that should be used for things related to particular connections/requests.
[`curl_easy_setopt()`][1] takes three arguments, where the option stuff must
be passed in pairs: the parameter-ID and the parameter-value. The list of
options is documented in the man page. This function mainly sets things in
- the 'Curl_easy' struct.
+ the `Curl_easy` struct.
`curl_easy_perform()` is just a wrapper function that makes use of the multi
API. It basically calls `curl_multi_init()`, `curl_multi_add_handle()`,
@@ -218,7 +218,7 @@ Curl_connect()
This function makes sure there's an allocated and initiated 'connectdata'
struct that is used for this particular connection only (although there may
be several requests performed on the same connect). A bunch of things are
- inited/inherited from the Curl_easy struct.
+ inited/inherited from the `Curl_easy` struct.
<a name="Curl_do"></a>
Curl_do()
@@ -385,11 +385,11 @@ Persistent Connections
The persistent connection support in libcurl requires some considerations on
how to do things inside of the library.
- - The 'Curl_easy' struct returned in the [`curl_easy_init()`][2] call
+ - The `Curl_easy` struct returned in the [`curl_easy_init()`][2] call
must never hold connection-oriented data. It is meant to hold the root data
as well as all the options etc that the library-user may choose.
- - The 'Curl_easy' struct holds the "connection cache" (an array of
+ - The `Curl_easy` struct holds the "connection cache" (an array of
pointers to 'connectdata' structs).
- This enables the 'curl handle' to be reused on subsequent transfers.
@@ -485,7 +485,7 @@ Client
main() resides in `src/tool_main.c`.
`src/tool_hugehelp.c` is automatically generated by the mkhelp.pl perl script
- to display the complete "manual" and the src/tool_urlglob.c file holds the
+ to display the complete "manual" and the `src/tool_urlglob.c` file holds the
functions used for the URL-"globbing" support. Globbing in the sense that the
{} and [] expansion stuff is there.
@@ -589,7 +589,7 @@ Asynchronous name resolves
`curl_off_t`
==========
- curl_off_t is a data type provided by the external libcurl include
+ `curl_off_t` is a data type provided by the external libcurl include
headers. It is the type meant to be used for the [`curl_easy_setopt()`][1]
options that end with LARGE. The type is 64bit large on most modern
platforms.
@@ -607,10 +607,10 @@ curlx
`curlx_strtoofft()`
-------------------
- A macro that converts a string containing a number to a curl_off_t number.
- This might use the curlx_strtoll() function which is provided as source
+ A macro that converts a string containing a number to a `curl_off_t` number.
+ This might use the `curlx_strtoll()` function which is provided as source
code in strtoofft.c. Note that the function is only provided if no
- strtoll() (or equivalent) function exist on your platform. If curl_off_t
+ strtoll() (or equivalent) function exist on your platform. If `curl_off_t`
is only a 32 bit number on your platform, this macro uses strtol().
`curlx_tvnow()`
@@ -624,17 +624,17 @@ curlx
`curlx_tvdiff_secs()`
---------------------
- returns the same as curlx_tvdiff but with full usec resolution (as a
+ returns the same as `curlx_tvdiff` but with full usec resolution (as a
double)
Future
------
- Several functions will be removed from the public curl_ name space in a
- future libcurl release. They will then only become available as curlx_
+ Several functions will be removed from the public `curl_` name space in a
+ future libcurl release. They will then only become available as `curlx_`
functions instead. To make the transition easier, we already today provide
- these functions with the curlx_ prefix to allow sources to get built properly
- with the new function names. The functions this concerns are:
+ these functions with the `curlx_` prefix to allow sources to get built
+ properly with the new function names. The functions this concerns are:
- `curlx_getenv`
- `curlx_strequal`
@@ -719,7 +719,7 @@ hostip.c explained
this host has getaddrinfo() and family, and thus we use that. The host may
not be able to resolve IPv6, but we don't really have to take that into
- account. Hosts that aren't IPv6-enabled have CURLRES_IPV4 defined.
+ account. Hosts that aren't IPv6-enabled have `CURLRES_IPV4` defined.
## `CURLRES_ARES`
@@ -750,7 +750,7 @@ hostip.c explained
- hostip6.c - IPv6 specific functions
The hostip.h is the single united header file for all this. It defines the
- `CURLRES_*` defines based on the config*.h and curl_setup.h defines.
+ `CURLRES_*` defines based on the config*.h and `curl_setup.h` defines.
<a name="memoryleak"></a>
Track Down Memory Leaks
@@ -858,7 +858,7 @@ for older and later versions as things don't change drastically that often.
## Curl_easy
- The Curl_easy struct is the one returned to the outside in the external API
+ The `Curl_easy` struct is the one returned to the outside in the external API
as a "CURL *". This is usually known as an easy handle in API documentations
and examples.
@@ -866,27 +866,27 @@ for older and later versions as things don't change drastically that often.
'connectdata' struct. When a transfer is about to be made, libcurl will
either create a new connection or re-use an existing one. The particular
connectdata that is used by this handle is pointed out by
- Curl_easy->easy_conn.
+ `Curl_easy->easy_conn`.
Data and information that regard this particular single transfer is put in
the SingleRequest sub-struct.
- When the Curl_easy struct is added to a multi handle, as it must be in order
- to do any transfer, the ->multi member will point to the `Curl_multi` struct
- it belongs to. The ->prev and ->next members will then be used by the multi
- code to keep a linked list of Curl_easy structs that are added to that same
- multi handle. libcurl always uses multi so ->multi *will* point to a
- `Curl_multi` when a transfer is in progress.
+ When the `Curl_easy` struct is added to a multi handle, as it must be in
+ order to do any transfer, the ->multi member will point to the `Curl_multi`
+ struct it belongs to. The ->prev and ->next members will then be used by the
+ multi code to keep a linked list of `Curl_easy` structs that are added to
+ that same multi handle. libcurl always uses multi so ->multi *will* point to
+ a `Curl_multi` when a transfer is in progress.
- ->mstate is the multi state of this particular Curl_easy. When
+ ->mstate is the multi state of this particular `Curl_easy`. When
`multi_runsingle()` is called, it will act on this handle according to which
state it is in. The mstate is also what tells which sockets to return for a
- specific Curl_easy when [`curl_multi_fdset()`][12] is called etc.
+ specific `Curl_easy` when [`curl_multi_fdset()`][12] is called etc.
The libcurl source code generally use the name 'data' for the variable that
- points to the Curl_easy.
+ points to the `Curl_easy`.
- When doing multiplexed HTTP/2 transfers, each Curl_easy is associated with
+ When doing multiplexed HTTP/2 transfers, each `Curl_easy` is associated with
an individual stream, sharing the same connectdata struct. Multiplexing
makes it even more important to keep things associated with the right thing!
@@ -901,21 +901,21 @@ for older and later versions as things don't change drastically that often.
the connection can't be kept alive, the connection will be closed after use
and then this struct can be removed from the cache and freed.
- Thus, the same Curl_easy can be used multiple times and each time select
+ Thus, the same `Curl_easy` can be used multiple times and each time select
another connectdata struct to use for the connection. Keep this in mind, as
it is then important to consider if options or choices are based on the
- connection or the Curl_easy.
+ connection or the `Curl_easy`.
Functions in libcurl will assume that connectdata->data points to the
- Curl_easy that uses this connection (for the moment).
+ `Curl_easy` that uses this connection (for the moment).
As a special complexity, some protocols supported by libcurl require a
special disconnect procedure that is more than just shutting down the
socket. It can involve sending one or more commands to the server before
doing so. Since connections are kept in the connection cache after use, the
- original Curl_easy may no longer be around when the time comes to shut down
+ original `Curl_easy` may no longer be around when the time comes to shut down
a particular connection. For this purpose, libcurl holds a special dummy
- `closure_handle` Curl_easy in the `Curl_multi` struct to use when needed.
+ `closure_handle` `Curl_easy` in the `Curl_multi` struct to use when needed.
FTP uses two TCP connections for a typical transfer but it keeps both in
this single struct and thus can be considered a single connection for most
@@ -929,36 +929,37 @@ for older and later versions as things don't change drastically that often.
Internally, the easy interface is implemented as a wrapper around multi
interface functions. This makes everything multi interface.
- `Curl_multi` is the multi handle struct exposed as "CURLM *" in external APIs.
+ `Curl_multi` is the multi handle struct exposed as "CURLM *" in external
+ APIs.
- This struct holds a list of Curl_easy structs that have been added to this
+ This struct holds a list of `Curl_easy` structs that have been added to this
handle with [`curl_multi_add_handle()`][13]. The start of the list is
- ->easyp and ->num_easy is a counter of added Curl_easys.
+ `->easyp` and `->num_easy` is a counter of added `Curl_easy`s.
- ->msglist is a linked list of messages to send back when
+ `->msglist` is a linked list of messages to send back when
[`curl_multi_info_read()`][14] is called. Basically a node is added to that
- list when an individual Curl_easy's transfer has completed.
+ list when an individual `Curl_easy`'s transfer has completed.
- ->hostcache points to the name cache. It is a hash table for looking up name
- to IP. The nodes have a limited life time in there and this cache is meant
- to reduce the time for when the same name is wanted within a short period of
- time.
+ `->hostcache` points to the name cache. It is a hash table for looking up
+ name to IP. The nodes have a limited life time in there and this cache is
+ meant to reduce the time for when the same name is wanted within a short
+ period of time.
- ->timetree points to a tree of Curl_easys, sorted by the remaining time
- until it should be checked - normally some sort of timeout. Each Curl_easy
+ `->timetree` points to a tree of `Curl_easy`s, sorted by the remaining time
+ until it should be checked - normally some sort of timeout. Each `Curl_easy`
has one node in the tree.
- ->sockhash is a hash table to allow fast lookups of socket descriptor to
- which Curl_easy that uses that descriptor. This is necessary for the
+ `->sockhash` is a hash table to allow fast lookups of socket descriptor to
+ which `Curl_easy` that uses that descriptor. This is necessary for the
`multi_socket` API.
- ->conn_cache points to the connection cache. It keeps track of all
+ `->conn_cache` points to the connection cache. It keeps track of all
connections that are kept after use. The cache has a maximum size.
- ->closure_handle is described in the 'connectdata' section.
+ `->closure_handle` is described in the 'connectdata' section.
The libcurl source code generally use the name 'multi' for the variable that
- points to the Curl_multi struct.
+ points to the `Curl_multi` struct.
## Curl_handler
@@ -971,41 +972,41 @@ for older and later versions as things don't change drastically that often.
from a single array which is scanned through when a URL is given to libcurl
to work with.
- ->scheme is the URL scheme name, usually spelled out in uppercase. That's
- "HTTP" or "FTP" etc. SSL versions of the protcol need its own `Curl_handler`
+ `->scheme` is the URL scheme name, usually spelled out in uppercase. That's
+ "HTTP" or "FTP" etc. SSL versions of the protocol need its own `Curl_handler`
setup so HTTPS separate from HTTP.
- ->setup_connection is called to allow the protocol code to allocate protocol
- specific data that then gets associated with that Curl_easy for the rest of
- this transfer. It gets freed again at the end of the transfer. It will be
- called before the 'connectdata' for the transfer has been selected/created.
- Most protocols will allocate its private 'struct [PROTOCOL]' here and assign
- Curl_easy->req.protop to point to it.
+ `->setup_connection` is called to allow the protocol code to allocate
+ protocol specific data that then gets associated with that `Curl_easy` for
+ the rest of this transfer. It gets freed again at the end of the transfer.
+ It will be called before the 'connectdata' for the transfer has been
+ selected/created. Most protocols will allocate its private
+ 'struct [PROTOCOL]' here and assign `Curl_easy->req.protop` to point to it.
- ->connect_it allows a protocol to do some specific actions after the TCP
+ `->connect_it` allows a protocol to do some specific actions after the TCP
connect is done, that can still be considered part of the connection phase.
- Some protocols will alter the connectdata->recv[] and connectdata->send[]
- function pointers in this function.
+ Some protocols will alter the `connectdata->recv[]` and
+ `connectdata->send[]` function pointers in this function.
- ->connecting is similarly a function that keeps getting called as long as the
- protocol considers itself still in the connecting phase.
+ `->connecting` is similarly a function that keeps getting called as long as
+ the protocol considers itself still in the connecting phase.
- ->do_it is the function called to issue the transfer request. What we call
+ `->do_it` is the function called to issue the transfer request. What we call
the DO action internally. If the DO is not enough and things need to be kept
- getting done for the entire DO sequence to complete, ->doing is then usually
- also provided. Each protocol that needs to do multiple commands or similar
- for do/doing need to implement their own state machines (see SCP, SFTP,
- FTP). Some protocols (only FTP and only due to historical reasons) has a
- separate piece of the DO state called `DO_MORE`.
+ getting done for the entire DO sequence to complete, `->doing` is then
+ usually also provided. Each protocol that needs to do multiple commands or
+ similar for do/doing need to implement their own state machines (see SCP,
+ SFTP, FTP). Some protocols (only FTP and only due to historical reasons) has
+ a separate piece of the DO state called `DO_MORE`.
- ->doing keeps getting called while issuing the transfer request command(s)
+ `->doing` keeps getting called while issuing the transfer request command(s)
- ->done gets called when the transfer is complete and DONE. That's after the
+ `->done` gets called when the transfer is complete and DONE. That's after the
main data has been transferred.
- ->do_more gets called during the `DO_MORE` state. The FTP protocol uses this
- state when setting up the second connection.
+ `->do_more` gets called during the `DO_MORE` state. The FTP protocol uses
+ this state when setting up the second connection.
->`proto_getsock`
->`doing_getsock`
@@ -1050,9 +1051,9 @@ for older and later versions as things don't change drastically that often.
## conncache
- Is a hash table with connections for later re-use. Each Curl_easy has a
+ Is a hash table with connections for later re-use. Each `Curl_easy` has a
pointer to its connection cache. Each multi handle sets up a connection
- cache that all added Curl_easys share by default.
+ cache that all added `Curl_easy`s share by default.
## Curl_share
@@ -1061,10 +1062,10 @@ for older and later versions as things don't change drastically that often.
The idea is that the struct can have a set of own versions of caches and
pools and then by providing this struct in the `CURLOPT_SHARE` option, those
- specific Curl_easys will use the caches/pools that this share handle
+ specific `Curl_easy`s will use the caches/pools that this share handle
holds.
- Then individual Curl_easy structs can be made to share specific things
+ Then individual `Curl_easy` structs can be made to share specific things
that they otherwise wouldn't, such as cookies.
The `Curl_share` struct can currently hold cookies, DNS cache and the SSL
@@ -1073,7 +1074,7 @@ for older and later versions as things don't change drastically that often.
## CookieInfo
This is the main cookie struct. It holds all known cookies and related
- information. Each Curl_easy has its own private CookieInfo even when
+ information. Each `Curl_easy` has its own private CookieInfo even when
they are added to a multi handle. They can be made to share cookies by using
the share API.
diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS
index 578e0153..84339ba9 100644
--- a/docs/KNOWN_BUGS
+++ b/docs/KNOWN_BUGS
@@ -22,8 +22,8 @@ problems may have been fixed or changed somewhat since this was written!
1.8 DNS timing is wrong for HTTP redirects
1.9 HTTP/2 frames while in the connection pool kill reuse
1.10 Strips trailing dot from host name
- 1.11 transfer-encoding: chunked in HTTP/2
- 1.12 CURLOPT_SEEKFUNCTION not called with CURLFORM_STREAM
+ 1.11 CURLOPT_SEEKFUNCTION not called with CURLFORM_STREAM
+ 1.12 HTTP/2 server push enabled when no pushes can be accepted
2. TLS
2.1 Hangs with PolarSSL
@@ -48,12 +48,17 @@ problems may have been fixed or changed somewhat since this was written!
5.3 libidn and old iconv
5.4 AIX shared build with c-ares fails
5.5 can't handle Unicode arguments in Windows
+ 5.6 cmake support gaps
+ 5.7 Visual Studio project gaps
+ 5.8 configure finding libs in wrong directory
+ 5.9 Utilize Requires.private directives in libcurl.pc
+ 5.10 Fix the gcc typechecks
6. Authentication
6.1 NTLM authentication and unicode
6.2 MIT Kerberos for Windows build
6.3 NTLM in system context uses wrong name
- 6.4 Negotiate needs a fake user name
+ 6.4 Negotiate and Kerberos V5 need a fake user name
7. FTP
7.1 FTP without or slow 220 response
@@ -63,6 +68,7 @@ problems may have been fixed or changed somewhat since this was written!
7.5 ASCII FTP
7.6 FTP with NULs in URL parts
7.7 FTP and empty path parts in the URL
+ 7.8 Premature transfer end but healthy control channel
8. TELNET
8.1 TELNET and time limtiations don't work
@@ -76,16 +82,16 @@ problems may have been fixed or changed somewhat since this was written!
10.2 SOCKS don't support timeouts
10.3 FTPS over SOCKS
10.4 active FTP over a SOCKS
- 10.5 SOCKS proxy not working via IPv6
11. Internals
11.1 Curl leaks .onion hostnames in DNS
11.2 error buffer not set if connection to multiple addresses fails
+ 11.3 c-ares deviates from stock resolver on http://1346569778
12. LDAP and OpenLDAP
12.1 OpenLDAP hangs after returning results
- 13 TCP/IP
+ 13. TCP/IP
13.1 --interface for ipv6 binds to unusable IP address
@@ -196,15 +202,7 @@ problems may have been fixed or changed somewhat since this was written!
See https://github.com/curl/curl/issues/716 for the discussion.
-1.11 transfer-encoding: chunked in HTTP/2
-
- For HTTP/1, when -H transfer-encoding:chunked option is given, curl encodes
- the request using chunked encoding. But when HTTP/2 is being used, the
- command wrongly sends a request with both content-length and
- transfer-encoding: chunked headers being set (and the request body is not
- chunked-encoded). See https://github.com/curl/curl/issues/662
-
-1.12 CURLOPT_SEEKFUNCTION not called with CURLFORM_STREAM
+1.11 CURLOPT_SEEKFUNCTION not called with CURLFORM_STREAM
I'm using libcurl to POST form data using a FILE* with the CURLFORM_STREAM
option of curl_formadd(). I've noticed that if the connection drops at just
@@ -215,6 +213,13 @@ problems may have been fixed or changed somewhat since this was written!
seem to fix the issue or even get called. See
https://github.com/curl/curl/issues/768
+1.12 HTTP/2 server push enabled when no pushes can be accepted
+
+ If the easy interface is used, we can't accept any server pushes so we should
+ switch off them already in the h2 settings as otherwise we risk wasting
+ bandwidth when the server tries to send pushes libcurl will never accept.
+
+ See https://github.com/curl/curl/issues/927
2. TLS
@@ -341,6 +346,59 @@ problems may have been fixed or changed somewhat since this was written!
https://curl.haxx.se/bug/?i=345
https://curl.haxx.se/bug/?i=731
+5.6 cmake support gaps
+
+ The cmake build setup lacks several features that the autoconf build
+ offers. This includes:
+
+ - symbol hiding when the shared library is built
+ - use of correct soname for the shared library build
+ - support for several TLS backends are missing
+ - the unit tests cause link failures in regular non-static builds
+ - no nghttp2 check
+
+5.7 Visual Studio project gaps
+
+ The Visual Studio projects lack some features that the autoconf and nmake
+ builds offer, such as the following:
+
+ - support for zlib and nghttp2
+ - use of static runtime libraries
+ - add the test suite components
+
+ In addition to this the following could be implemented:
+
+ - support for other development IDEs
+ - add PATH environment variables for third-party DLLs
+
+5.8 configure finding libs in wrong directory
+
+ When the configure script checks for third-party libraries, it adds those
+ directories to the LDFLAGS variable and then tries linking to see if it
+ works. When successful, the found directory is kept in the LDFLAGS variable
+ when the script continues to execute and do more tests and possibly check for
+ more libraries.
+
+ This can make subsequent checks for libraries wrongly detect another
+ installation in a directory that was previously added to LDFLAGS by another
+ library check!
+
+ A possibly better way to do these checks would be to keep the pristine LDFLAGS
+ even after successful checks and instead add those verified paths to a
+ separate variable that only after all library checks have been performed gets
+ appended to LDFLAGS.
+
+5.9 Utilize Requires.private directives in libcurl.pc
+
+ https://github.com/curl/curl/issues/864
+
+5.10 Fix the gcc typechecks
+
+ Issue #846 identifies a problem with the gcc-typechecks and how the types are
+ documented and checked for CURLINFO_CERTINFO but our attempts to fix the
+ issue were futile and needs more attention.
+
+ https://github.com/curl/curl/issues/846
6. Authentication
@@ -367,13 +425,17 @@ problems may have been fixed or changed somewhat since this was written!
"system context" will make it use wrong(?) user name - at least when compared
to what winhttp does. See https://curl.haxx.se/bug/view.cgi?id=535
-6.4 Negotiate needs a fake user name
+6.4 Negotiate and Kerberos V5 need a fake user name
- To get HTTP Negotiate (SPNEGO) authentication to work fine, you need to
- provide a (fake) user name (this concerns both curl and the lib) because the
- code wrongly only considers authentication if there's a user name provided.
- https://curl.haxx.se/bug/view.cgi?id=440 How?
- https://curl.haxx.se/mail/lib-2004-08/0182.html
+ In order to get Negotiate (SPNEGO) authentication to work in HTTP or Kerberos
+ V5 in the e-mail protocols, you need to provide a (fake) user name (this
+ concerns both curl and the lib) because the code wrongly only considers
+ authentication if there's a user name provided by setting
+ conn->bits.user_passwd in url.c https://curl.haxx.se/bug/view.cgi?id=440 How?
+ https://curl.haxx.se/mail/lib-2004-08/0182.html A possible solution is to
+ either modify this variable to be set or introduce a variable such as
+ new conn->bits.want_authentication which is set when any of the authentication
+ options are set.
7. FTP
@@ -442,6 +504,17 @@ problems may have been fixed or changed somewhat since this was written!
the user wants to reach the root dir (this exception SHALL remain even when
this bug is fixed).
+7.8 Premature transfer end but healthy control channel
+
+ When 'multi_done' is called before the transfer has been completed the normal
+ way, it is considered a "premature" transfer end. In this situation, libcurl
+ closes the connection assuming it doesn't know the state of the connection so
+ it can't be reused for subsequent requests.
+
+ With FTP however, this isn't necessarily true but there are a bunch of
+ situations (listed in the ftp_done code) where it *could* keep the connection
+ alive even in this situation - but the current code doesn't. Fixing this would
+ allow libcurl to reuse FTP connections better.
8. TELNET
@@ -493,12 +566,6 @@ problems may have been fixed or changed somewhat since this was written!
libcurl doesn't support active FTP over a SOCKS proxy
-10.5 SOCKS proxy not working via IPv6
-
- `curl --proxy "socks://hostname-with-AAAA-record" example.com`
-
- curl: (7) Can't complete SOCKS4 connection to 1.2.3.4:109. (91),
- request rejected or failed.
11. Internals
@@ -517,6 +584,18 @@ problems may have been fixed or changed somewhat since this was written!
CURLE_COULDNT_CONNECT. But the error buffer set by CURLOPT_ERRORBUFFER
remains empty. Issue: https://github.com/curl/curl/issues/544
+11.3 c-ares deviates from stock resolver on http://1346569778
+
+ When using the socket resolvers, that URL becomes:
+
+ * Rebuilt URL to: http://1346569778/
+ * Trying 80.67.6.50...
+
+ but with c-ares it instead says "Could not resolve: 1346569778 (Domain name
+ not found)"
+
+ See https://github.com/curl/curl/issues/893
+
12. LDAP and OpenLDAP
@@ -540,7 +619,7 @@ problems may have been fixed or changed somewhat since this was written!
https://curl.haxx.se/mail/lib-2016-01/0101.html
-13 TCP/IP
+13. TCP/IP
13.1 --interface for ipv6 binds to unusable IP address
diff --git a/docs/LICENSE-MIXING b/docs/LICENSE-MIXING
deleted file mode 100644
index d8e36ca4..00000000
--- a/docs/LICENSE-MIXING
+++ /dev/null
@@ -1,130 +0,0 @@
- License Mixing with apps, libcurl and Third Party Libraries
- ===========================================================
-
-libcurl can be built to use a fair amount of various third party libraries,
-libraries that are written and provided by other parties that are distributed
-using their own licenses. Even libcurl itself contains code that may cause
-problems to some. This document attempts to describe what licenses libcurl and
-the other libraries use and what possible dilemmas linking and mixing them all
-can lead to for end users.
-
-I am not a lawyer and this is not legal advice!
-
-One common dilemma is that GPL[1]-licensed code is not allowed to be linked
-with code licensed under the Original BSD license (with the announcement
-clause). You may still build your own copies that use them all, but
-distributing them as binaries would be to violate the GPL license - unless you
-accompany your license with an exception[2]. This particular problem was
-addressed when the Modified BSD license was created, which does not have the
-announcement clause that collides with GPL.
-
-libcurl https://curl.haxx.se/docs/copyright.html
-
- Uses an MIT (or Modified BSD)-style license that is as liberal as
- possible.
-
-OpenSSL https://www.openssl.org/source/license.html
-
- (May be used for SSL/TLS support) Uses an Original BSD-style license
- with an announcement clause that makes it "incompatible" with GPL. You
- are not allowed to ship binaries that link with OpenSSL that includes
- GPL code (unless that specific GPL code includes an exception for
- OpenSSL - a habit that is growing more and more common). If OpenSSL's
- licensing is a problem for you, consider using another TLS library.
-
-GnuTLS http://www.gnutls.org/
-
- (May be used for SSL/TLS support) Uses the LGPL[3] license. If this is
- a problem for you, consider using another TLS library. Also note that
- GnuTLS itself depends on and uses other libs (libgcrypt and
- libgpg-error) and they too are LGPL- or GPL-licensed.
-
-WolfSSL https://www.wolfssl.com/
-
- (May be used for SSL/TLS support) Uses the GPL[1] license or a
- propietary license. If this is a problem for you, consider using
- another TLS library.
-
-NSS https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS
-
- (May be used for SSL/TLS support) Is covered by the MPL[4] license,
- the GPL[1] license and the LGPL[3] license. You may choose to license
- the code under MPL terms, GPL terms, or LGPL terms. These licenses
- grant you different permissions and impose different obligations. You
- should select the license that best meets your needs.
-
-axTLS http://axtls.sourceforge.net/
-
- (May be used for SSL/TLS support) Uses a Modified BSD-style license.
-
-mbedTLS https://tls.mbed.org/
-
- (May be used for SSL/TLS support) Uses the GPL[1] license or a
- propietary license. If this is a problem for you, consider using
- another TLS library.
-
-BoringSSL https://boringssl.googlesource.com/
-
- (May be used for SSL/TLS support) As an OpenSSL fork, it has the same
- license as that.
-
-libressl http://www.libressl.org/
-
- (May be used for SSL/TLS support) As an OpenSSL fork, it has the same
- license as that.
-
-c-ares https://daniel.haxx.se/projects/c-ares/license.html
-
- (Used for asynchronous name resolves) Uses an MIT license that is very
- liberal and imposes no restrictions on any other library or part you
- may link with.
-
-zlib http://www.zlib.net/zlib_license.html
-
- (Used for compressed Transfer-Encoding support) Uses an MIT-style
- license that shouldn't collide with any other library.
-
-MIT Kerberos http://web.mit.edu/kerberos/www/dist/
-
- (May be used for GSS support) MIT licensed, that shouldn't collide
- with any other parts.
-
-Heimdal http://www.h5l.org
-
- (May be used for GSS support) Heimdal is Original BSD licensed with
- the announcement clause.
-
-GNU GSS https://www.gnu.org/software/gss/
-
- (May be used for GSS support) GNU GSS is GPL licensed. Note that you
- may not distribute binary curl packages that uses this if you build
- curl to also link and use any Original BSD licensed libraries!
-
-libidn http://josefsson.org/libidn/
-
- (Used for IDNA support) Uses the GNU Lesser General Public
- License [3]. LGPL is a variation of GPL with slightly less aggressive
- "copyleft". This license requires more requirements to be met when
- distributing binaries, see the license for details. Also note that if
- you distribute a binary that includes this library, you must also
- include the full LGPL license text. Please properly point out what
- parts of the distributed package that the license addresses.
-
-OpenLDAP http://www.openldap.org/software/release/license.html
-
- (Used for LDAP support) Uses a Modified BSD-style license. Since
- libcurl uses OpenLDAP as a shared library only, I have not heard of
- anyone that ships OpenLDAP linked with libcurl in an app.
-
-libssh2 https://www.libssh2.org/
-
- (Used for scp and sftp support) libssh2 uses a Modified BSD-style
- license.
-
-[1] = GPL - GNU General Public License: https://www.gnu.org/licenses/gpl.html
-[2] = https://www.gnu.org/licenses/gpl-faq.html#GPLIncompatibleLibs details on
- how to write such an exception to the GPL
-[3] = LGPL - GNU Lesser General Public License:
- https://www.gnu.org/licenses/lgpl.html
-[4] = MPL - Mozilla Public License:
- https://www.mozilla.org/MPL/
diff --git a/docs/LICENSE-MIXING.md b/docs/LICENSE-MIXING.md
new file mode 100644
index 00000000..5376bdb7
--- /dev/null
+++ b/docs/LICENSE-MIXING.md
@@ -0,0 +1,127 @@
+License Mixing
+==============
+
+libcurl can be built to use a fair amount of various third party libraries,
+libraries that are written and provided by other parties that are distributed
+using their own licenses. Even libcurl itself contains code that may cause
+problems to some. This document attempts to describe what licenses libcurl and
+the other libraries use and what possible dilemmas linking and mixing them all
+can lead to for end users.
+
+I am not a lawyer and this is not legal advice!
+
+One common dilemma is that [GPL](https://www.gnu.org/licenses/gpl.html)
+licensed code is not allowed to be linked with code licensed under the
+[Original BSD license](https://spdx.org/licenses/BSD-4-Clause.html) (with the
+announcement clause). You may still build your own copies that use them all,
+but distributing them as binaries would be to violate the GPL license - unless
+you accompany your license with an
+[exception](https://www.gnu.org/licenses/gpl-faq.html#GPLIncompatibleLibs). This
+particular problem was addressed when the [Modified BSD
+license](https://opensource.org/licenses/BSD-3-Clause) was created, which does
+not have the announcement clause that collides with GPL.
+
+## libcurl
+
+ Uses an [MIT style license](https://curl.haxx.se/docs/copyright.html) that is
+ very liberal.
+
+## OpenSSL
+
+ (May be used for SSL/TLS support) Uses an Original BSD-style license with an
+ announcement clause that makes it "incompatible" with GPL. You are not
+ allowed to ship binaries that link with OpenSSL that includes GPL code
+ (unless that specific GPL code includes an exception for OpenSSL - a habit
+ that is growing more and more common). If OpenSSL's licensing is a problem
+ for you, consider using another TLS library.
+
+## GnuTLS
+
+ (May be used for SSL/TLS support) Uses the
+ [LGPL](https://www.gnu.org/licenses/lgpl.html) license. If this is a problem
+ for you, consider using another TLS library. Also note that GnuTLS itself
+ depends on and uses other libs (libgcrypt and libgpg-error) and they too are
+ LGPL- or GPL-licensed.
+
+## WolfSSL
+
+ (May be used for SSL/TLS support) Uses the GPL license or a proprietary
+ license. If this is a problem for you, consider using another TLS library.
+
+## NSS
+
+ (May be used for SSL/TLS support) Is covered by the
+ [MPL](https://www.mozilla.org/MPL/) license, the GPL license and the LGPL
+ license. You may choose to license the code under MPL terms, GPL terms, or
+ LGPL terms. These licenses grant you different permissions and impose
+ different obligations. You should select the license that best meets your
+ needs.
+
+## axTLS
+
+ (May be used for SSL/TLS support) Uses a Modified BSD-style license.
+
+## mbedTLS
+
+ (May be used for SSL/TLS support) Uses the [Apache 2.0
+ license](https://opensource.org/licenses/Apache-2.0) or the GPL license.
+ You may choose to license the code under Apache 2.0 terms or GPL terms.
+ These licenses grant you different permissions and impose different
+ obligations. You should select the license that best meets your needs.
+
+## BoringSSL
+
+ (May be used for SSL/TLS support) As an OpenSSL fork, it has the same
+ license as that.
+
+## libressl
+
+ (May be used for SSL/TLS support) As an OpenSSL fork, it has the same
+ license as that.
+
+## c-ares
+
+ (Used for asynchronous name resolves) Uses an MIT license that is very
+ liberal and imposes no restrictions on any other library or part you may link
+ with.
+
+## zlib
+
+ (Used for compressed Transfer-Encoding support) Uses an MIT-style license
+ that shouldn't collide with any other library.
+
+## MIT Kerberos
+
+ (May be used for GSS support) MIT licensed, that shouldn't collide with any
+ other parts.
+
+## Heimdal
+
+ (May be used for GSS support) Heimdal is Original BSD licensed with the
+ announcement clause.
+
+## GNU GSS
+
+ (May be used for GSS support) GNU GSS is GPL licensed. Note that you may not
+ distribute binary curl packages that uses this if you build curl to also link
+ and use any Original BSD licensed libraries!
+
+## libidn
+
+ (Used for IDNA support) Uses the GNU Lesser General Public License [3]. LGPL
+ is a variation of GPL with slightly less aggressive "copyleft". This license
+ requires more requirements to be met when distributing binaries, see the
+ license for details. Also note that if you distribute a binary that includes
+ this library, you must also include the full LGPL license text. Please
+ properly point out what parts of the distributed package that the license
+ addresses.
+
+## OpenLDAP
+
+ (Used for LDAP support) Uses a Modified BSD-style license. Since libcurl uses
+ OpenLDAP as a shared library only, I have not heard of anyone that ships
+ OpenLDAP linked with libcurl in an app.
+
+## libssh2
+
+ (Used for scp and sftp support) libssh2 uses a Modified BSD-style license.
diff --git a/docs/MAIL-ETIQUETTE b/docs/MAIL-ETIQUETTE
index 75058009..4d439aa4 100644
--- a/docs/MAIL-ETIQUETTE
+++ b/docs/MAIL-ETIQUETTE
@@ -48,7 +48,7 @@ MAIL ETIQUETTE
each particular group and subculture there will be differences in what is
acceptable and what is considered good manners.
- This document outlines what we in the cURL project considers to be good
+ This document outlines what we in the curl project considers to be good
etiquette, and primarily this focus on how to behave on and how to use our
mailing lists.
@@ -108,7 +108,7 @@ MAIL ETIQUETTE
off-list. The subject will be taken care of as good as possible to prevent
repeated offenses, but responding on the list to such messages never lead to
anything good and only puts the light even more on the offender: which was
- the entire purpose of it getting to the list in the first place.
+ the entire purpose of it getting sent to the list in the first place.
Don't feed the trolls!
@@ -119,7 +119,7 @@ MAIL ETIQUETTE
your email address and password and press the unsubscribe button.
Also, this information is included in the headers of every mail that is sent
- out to all curl related mailing lists and there's footer in each mail that
+ out to all curl related mailing lists and there's a footer in each mail that
links to the "admin" page on which you can unsubscribe and change other
options.
@@ -200,8 +200,7 @@ MAIL ETIQUETTE
This is why top posting is so bad:
- A: Because it messes up the order in which people normally read
- text.
+ A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?
diff --git a/docs/MANUAL b/docs/MANUAL
index 08fdb57a..0ea3e61f 100644
--- a/docs/MANUAL
+++ b/docs/MANUAL
@@ -817,12 +817,8 @@ LDAP
and offer ldap:// support.
LDAP is a complex thing and writing an LDAP query is not an easy task. I do
- advise you to dig up the syntax description for that elsewhere. Two places
- that might suit you are:
-
- Netscape's "Netscape Directory SDK 3.0 for C Programmer's Guide Chapter 10:
- Working with LDAP URLs":
- http://developer.netscape.com/docs/manuals/dirsdk/csdk30/url.htm
+ advise you to dig up the syntax description for that elsewhere. One such
+ place might be:
RFC 2255, "The LDAP URL Format" https://curl.haxx.se/rfc/rfc2255.txt
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 284e5312..fd045d26 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -33,12 +33,12 @@ SUBDIRS = examples libcurl
CLEANFILES = $(GENHTMLPAGES) $(PDFPAGES)
-EXTRA_DIST = MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS SSLCERTS \
- README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS VERSIONS \
- KNOWN_BUGS BINDINGS $(man_MANS) $(HTMLPAGES) HISTORY INSTALL \
- $(PDFPAGES) LICENSE-MIXING README.netware INSTALL.devcpp \
- MAIL-ETIQUETTE HTTP-COOKIES.md SECURITY RELEASE-PROCEDURE SSL-PROBLEMS \
- HTTP2.md ROADMAP.md CODE_OF_CONDUCT.md CODE_STYLE.md CHECKSRC.md
+EXTRA_DIST = MANUAL BUGS CONTRIBUTE.md FAQ FEATURES INTERNALS.md SSLCERTS.md \
+ README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS VERSIONS KNOWN_BUGS \
+ BINDINGS.md $(man_MANS) HISTORY.md INSTALL INSTALL.md LICENSE-MIXING.md \
+ README.netware MAIL-ETIQUETTE HTTP-COOKIES.md SECURITY.md RELEASE-PROCEDURE \
+ SSL-PROBLEMS.md HTTP2.md ROADMAP.md CODE_OF_CONDUCT.md CODE_STYLE.md \
+ CHECKSRC.md
MAN2HTML= roffit $< >$@
diff --git a/docs/RELEASE-PROCEDURE b/docs/RELEASE-PROCEDURE
index 479078fa..1b574526 100644
--- a/docs/RELEASE-PROCEDURE
+++ b/docs/RELEASE-PROCEDURE
@@ -83,10 +83,10 @@ Coming dates
Based on the description above, here are some planned release dates (at the
time of this writing):
-- March 23, 2016 (version 7.48.0)
-- May 18, 2016
-- July 13, 2016
-- September 7, 2016
+- September 7, 2016 (version 7.50.2)
- November 2, 2016
- December 28, 2016
- February 22, 2017
+- April 19, 2017
+- June 14, 2017
+- August 9, 2017
diff --git a/docs/SECURITY b/docs/SECURITY.md
index 3c07e0bb..c88cc9c8 100644
--- a/docs/SECURITY
+++ b/docs/SECURITY.md
@@ -1,9 +1,3 @@
- _ _ ____ _
- ___| | | | _ \| |
- / __| | | | |_) | |
- | (__| |_| | _ <| |___
- \___|\___/|_| \_\_____|
-
curl security for developers
============================
@@ -81,9 +75,11 @@ announcement.
to the 'distros' mailing list to allow them to use the fix prior to the
public announcement.
-- At the day of the next release, the private branch is merged into the master
- branch and pushed. Once pushed, the information is accessible to the public
- and the actual release should follow suit immediately afterwards.
+- No more than 48 hours before the release, the private branch is merged into
+ the master branch and pushed. Once pushed, the information is accessible to
+ the public and the actual release should follow suit immediately afterwards.
+ The time between the push and the release is used for final tests and
+ reviews.
- The project team creates a release that includes the fix.
@@ -94,9 +90,19 @@ announcement.
- The security web page on the web site should get the new vulnerability
mentioned.
+Pre-notification
+----------------
+
+If you think you are or should be eligible for a pre-notification about
+upcoming security announcements for curl, we urge OS distros and similar
+vendors to primarily join the distros@openwall list as that is one of the
+purposes of that list - and not just for curl of course.
+If you are not a distro or otherwise not suitable for distros@openwall and yet
+want pre-notifications from us, contact the curl security team with a detailed
+and clear explanation why this is the case.
-CURL-SECURITY (at haxx dot se)
+curl-security (at haxx dot se)
------------------------------
Who is on this list? There are a couple of criteria you must meet, and then we
@@ -106,5 +112,5 @@ curl project and you have shown an understanding for the project and its way
of working. You must've been around for a good while and you should have no
plans in vanishing in the near future.
-We do not make the list of partipants public mostly because it tends to vary
+We do not make the list of participants public mostly because it tends to vary
somewhat over time and a list somewhere will only risk getting outdated.
diff --git a/docs/SSL-PROBLEMS b/docs/SSL-PROBLEMS.md
index e6398710..91803e22 100644
--- a/docs/SSL-PROBLEMS
+++ b/docs/SSL-PROBLEMS.md
@@ -4,7 +4,7 @@
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
-SSL problems
+# SSL problems
First, let's establish that we often refer to TLS and SSL interchangeably as
SSL here. The current protocol is called TLS, it was called SSL a long time
@@ -14,19 +14,19 @@ SSL problems
fail. This is a document that attempts to details the most common ones and
how to mitigate them.
-CA certs
+## CA certs
CA certs are used to digitally verify the server's certificate. You need a
"ca bundle" for this. See lots of more details on this in the SSLCERTS
document.
-CA bundle missing intermediate certificates
+## CA bundle missing intermediate certificates
When using said CA bundle to verify a server cert, you will experience
problems if your CA cert does not have the certificates for the
intermediates in the whole trust chain.
-Protocol version
+## Protocol version
Some broken servers fail to support the protocol negotiation properly that
SSL servers are supposed to handle. This may cause the connection to fail
@@ -38,7 +38,7 @@ Protocol version
All versions of SSL are considered insecure and should be avoided. Use TLS.
-Ciphers
+## Ciphers
Clients give servers a list of ciphers to select from. If the list doesn't
include any ciphers the server wants/can use, the connection handshake
@@ -61,7 +61,7 @@ Ciphers
https://tools.ietf.org/html/draft-popov-tls-prohibiting-rc4-01
-Allow BEAST
+## Allow BEAST
BEAST is the name of a TLS 1.0 attack that surfaced 2011. When adding means
to mitigate this attack, it turned out that some broken servers out there in
@@ -72,7 +72,7 @@ Allow BEAST
but on the other hand it allows curl to connect to that kind of strange
servers.
-Disabling certificate revocation checks
+## Disabling certificate revocation checks
Some SSL backends may do certificate revocation checks (CRL, OCSP, etc)
depending on the OS or build configuration. The --ssl-no-revoke option was
diff --git a/docs/SSLCERTS b/docs/SSLCERTS.md
index 7755609c..7755609c 100644
--- a/docs/SSLCERTS
+++ b/docs/SSLCERTS.md
diff --git a/docs/THANKS b/docs/THANKS
index 0f1a94fa..2ebbf474 100644
--- a/docs/THANKS
+++ b/docs/THANKS
@@ -20,6 +20,7 @@ Adriano Meirelles
Ajit Dhumale
Aki Koskinen
Akos Pasztory
+Akshay Vernekar
Alain Danteny
Alan Pinstein
Albert Chin-A-Young
@@ -28,6 +29,7 @@ Ale Vesely
Alejandro Alvarez Ayllon
Aleksandar Milivojevic
Aleksey Tulinov
+Ales Novak
Alessandro Ghedini
Alessandro Vesely
Alex Bligh
@@ -47,6 +49,7 @@ Alexander Krasnostavsky
Alexander Lazic
Alexander Pepper
Alexander Peslyak
+Alexander Sinditskiy
Alexander Traud
Alexander Zhuravlev
Alexey Borzov
@@ -76,10 +79,12 @@ Andreas Ntaflos
Andreas Olsson
Andreas Rieke
Andreas Schuldei
+Andreas Streichardt
Andreas Wurf
Andrei Benea
Andrei Cipu
Andrei Kurushin
+Andrei Sedoi
Andrej E Baranov
Andrew Benham
Andrew Biggs
@@ -212,7 +217,9 @@ Chris Maltby
Chris Mumford
Chris Smowton
Chris Young
+Christian Fillion
Christian Grothoff
+Christian Heimes
Christian Hägele
Christian Krause
Christian Kurz
@@ -256,12 +263,14 @@ D. Flinkmann
Da-Yoon Chung
Dag Ekengren
Dagobert Michelsen
+Dambaev Alexander
Damian Dixon
Damien Adant
Damien Vielpeau
Dan Becker
Dan C
Dan Cristian
+Dan Donahue
Dan Fandrich
Dan Locks
Dan Nelson
@@ -271,6 +280,7 @@ Dan Zitter
Daniel Black
Daniel Cater
Daniel Egger
+Daniel Gustafsson
Daniel Hwang
Daniel Johnson
Daniel Kahn Gillmor
@@ -286,6 +296,7 @@ Daniel Theron
Daniel at touchtunes
Darryl House
Darshan Mody
+Darío Hereñú
Dave Dribin
Dave Halbakken
Dave Hamilton
@@ -305,6 +316,7 @@ David Houlder
David Hull
David J Meyer
David James
+David Kalnischkies
David Kierznowski
David Kimdon
David Lang
@@ -450,6 +462,7 @@ Gabriel Kuri
Gabriel Sjoberg
Garrett Holmstrom
Gary Maxwell
+Gaurav Malhotra
Gautam Kachroo
Gautam Mani
Gavrie Philipson
@@ -489,6 +502,7 @@ Greg Morse
Greg Onufer
Greg Pratt
Greg Zavertnik
+Gregory Szorc
Grigory Entin
Guenole Bescon
Guenter Knauf
@@ -509,6 +523,7 @@ Hans Steegers
Hans-Jurgen May
Hardeep Singh
Haris Okanovic
+Harold Stuart
Harshal Pradhan
Hauke Duden
He Qin
@@ -711,6 +726,7 @@ Justin Ehlert
Justin Fletcher
Justin Karneges
Justin Maggard
+János Fekete
Jörg Mueller-Tolk
Jörn Hartroth
K. R. Walker
@@ -808,6 +824,7 @@ Luke Call
Luke Dashjr
Luo Jinghua
Luong Dinh Dung
+Luật Nguyễn
Lyndon Hill
Maciej Karpiuk
Maciej Puzio
@@ -823,7 +840,7 @@ Marc Boucher
Marc Deslauriers
Marc Doughty
Marc Hesse
-Marc Hoersken
+Marc Hörsken
Marc Kleine-Budde
Marc Renault
Marcel Raad
@@ -833,6 +850,7 @@ Marcelo Juchem
Marcin Adamski
Marcin Gryszkalis
Marcin Konicki
+Marco Deckel
Marco G. Salvagno
Marco Maggi
Marcus Sundberg
@@ -842,9 +860,11 @@ Mark Brand
Mark Butler
Mark Davies
Mark Eichin
+Mark Hamilton
Mark Incley
Mark Karpeles
Mark Lentczner
+Mark Nottingham
Mark Salisbury
Mark Snelling
Mark Tully
@@ -857,12 +877,13 @@ Marquis de Muesli
Martijn Koster
Martin C. Martin
Martin Drasar
+Martin Frodl
Martin Hager
Martin Hedenfalk
Martin Jansen
Martin Lemke
Martin Skinner
-Martin Storsjo
+Martin Storsjö
Martin Vejnár
Marty Kuhrt
Maruko
@@ -936,6 +957,7 @@ Mike Power
Mike Protts
Mike Revi
Miklos Nemeth
+Miloš Ljumović
Miroslav Franc
Miroslav Spousta
Mitz Wark
@@ -990,6 +1012,7 @@ Oliver Graute
Oliver Kuckertz
Oliver Schindler
Olivier Berger
+Olivier Brunel
Orange Tsai
Oren Souroujon
Oren Tirosh
@@ -1018,6 +1041,7 @@ Pau Garcia i Quiles
Paul Donohue
Paul Harrington
Paul Howarth
+Paul Joyce
Paul Marks
Paul Marquis
Paul Moore
@@ -1088,12 +1112,14 @@ Rafaël Carré
Rainer Canavan
Rainer Jung
Rainer Koenig
+Rainer Müller
Rajesh Naganathan
Rajkumar Mandal
Ralf S. Engelschall
Ralph Beckmann
Ralph Mitchell
Ramana Mokkapati
+Randy Armstrong
Randy McMurchy
Ravi Pratap
Ray Dassen
@@ -1103,6 +1129,7 @@ Razvan Cojocaru
Reinhard Max
Reinout van Schouwen
Remi Gacogne
+Remo E
Renato Botelho
Renaud Chaillat
Renaud Duhaut
@@ -1131,6 +1158,7 @@ Richard Silverman
Richard van den Berg
Rick Jones
Rick Richardson
+Rider Linden
Rob Crittenden
Rob Davies
Rob Jones
@@ -1164,6 +1192,7 @@ Roman Mamedov
Romulo A. Ceccon
Ron Parker
Ron Zapp
+Ronnie Mose
Rosimildo da Silva
Roy Shan
Rune Kleveland
@@ -1173,6 +1202,7 @@ Ryan Braud
Ryan Chan
Ryan Nelson
Ryan Schmidt
+Ryan Scott
Rémy Léone
S. Moonesamy
Salvador Dávila
@@ -1200,12 +1230,15 @@ Scott Cantor
Scott Davis
Scott McCreary
Sean Boudreau
+Sebastian Mundry
Sebastian Pohlschmidt
Sebastian Rasmussen
Senthil Raja Velu
+Sergei Kuzmin
Sergei Nikulov
Sergey Tatarincev
Sergio Ballestrero
+Serj Kalichev
Seshubabu Pasam
Seth Mos
Sh Diao
@@ -1223,6 +1256,7 @@ Simon Dick
Simon H.
Simon Josefsson
Simon Liu
+Simon Warta
Song Ma
Sonia Subramanian
Spacen Jasset
@@ -1242,6 +1276,7 @@ Stefan Tomanek
Stefan Ulrich
Steinar H. Gunderson
Stephan Bergmann
+Stephen Brokenshire
Stephen Collyer
Stephen Kick
Stephen More
@@ -1312,6 +1347,7 @@ Tobias Stoeckmann
Toby Peterson
Todd A Ouska
Todd Kulesza
+Todd Short
Todd Vierling
Tom Benoist
Tom Donovan
@@ -1336,8 +1372,10 @@ Tommie Gannert
Tommy Tam
Ton Voon
Toni Moreno
+Tony Kelman
Toon Verwaest
Tor Arntsen
+Torben Dannhauer
Torsten Foertsch
Toshio Kuratomi
Toshiyuki Maezawa
@@ -1353,6 +1391,7 @@ Ulf Samuelsson
Ulrich Doehner
Ulrich Telle
Ulrich Zadow
+Valentin David
Venkat Akella
Victor Snezhko
Vijay Panghal
@@ -1420,12 +1459,15 @@ dkjjr89 on github
eXeC64 on github
jveazey on github
kreshano on github
+lukaszgn on github
marc-groundctl on github
neex on github
nk
+nopjmp on github
silveja1 on github
swalkaus at yahoo.com
tommink[at]post.pl
vanillajonathan on github
+wmsch on github
Štefan Kremeň
Ðикита Дорохин
diff --git a/docs/THANKS-filter b/docs/THANKS-filter
index defd6051..1c6f3986 100644
--- a/docs/THANKS-filter
+++ b/docs/THANKS-filter
@@ -68,3 +68,5 @@ s/Jean-Philippe Barette-LaPierre$/Jean-Philippe Barrette-LaPierre/
s/Joern Hartroth$/Jörn Hartroth/
s/Hongli Lai (Phusion)$/Hongli Lai/
s/github user 'kreshano'$/kreshano on github/
+s/Marc Hoersken$/Marc Hörsken/
+s/Martin Storsjo$/Martin Storsjö/
diff --git a/docs/TODO b/docs/TODO
index 30f20871..99c610fe 100644
--- a/docs/TODO
+++ b/docs/TODO
@@ -6,7 +6,7 @@
Things that could be nice to do in the future
- Things to do in project cURL. Please tell us what you think, contribute and
+ Things to do in project curl. Please tell us what you think, contribute and
send us patches that improve things!
Be aware that these are things that we could do, or have once been considered
@@ -25,16 +25,19 @@
1.7 Detect when called from within callbacks
1.8 Allow SSL (HTTPS) to proxy
1.9 Cache negative name resolves
- 1.10 Support IDNA2008
1.11 minimize dependencies with dynamicly loaded modules
1.12 have form functions use CURL handle argument
- 1.13 Add CURLOPT_MAIL_CLIENT option
1.14 Typesafe curl_easy_setopt()
- 1.15 TCP Fast Open
+ 1.15 Monitor connections in the connection pool
1.16 Try to URL encode given URL
1.17 Add support for IRIs
1.18 try next proxy if one doesn't work
1.19 Timeout idle connections from the pool
+ 1.20 SRV and URI DNS records
+ 1.21 API for URL parsing/splitting
+ 1.23 Offer API to flush the connection pool
+ 1.24 TCP Fast Open for windows
+ 1.25 Remove the generated include file
2. libcurl - multi interface
2.1 More non-blocking
@@ -60,10 +63,12 @@
5.1 Better persistency for HTTP 1.0
5.2 support FF3 sqlite cookie files
5.3 Rearrange request header order
- 5.4 SPDY
5.5 auth= in URLs
5.6 Refuse "downgrade" redirects
- 5.7 More compressions
+ 5.7 Brotli compression
+ 5.8 QUIC
+ 5.9 Add easy argument to formpost functions
+ 5.10 Leave secure cookies alone
6. TELNET
6.1 ditch stdin
@@ -74,6 +79,7 @@
7. SMTP
7.1 Pipelining
7.2 Enhanced capability support
+ 7.3 Add CURLOPT_MAIL_CLIENT option
8. POP3
8.1 Pipelining
@@ -103,6 +109,11 @@
13.6 Provide callback for cert verification
13.7 improve configure --with-ssl
13.8 Support DANE
+ 13.9 Support TLS v1.3
+ 13.10 Support SSLKEYLOGFILE
+ 13.11 Support intermediate & root pinning for PINNEDPUBLICKEY
+ 13.12 Support HSTS
+ 13.13 Support HPKP
14. GnuTLS
14.1 SSL engine stuff
@@ -118,47 +129,55 @@
16.2 Add QOP support to GSSAPI authentication
16.3 Support binary messages (i.e.: non-base64)
- 17. Command line tool
- 17.1 sync
- 17.2 glob posts
- 17.3 prevent file overwriting
- 17.4 simultaneous parallel transfers
- 17.5 provide formpost headers
- 17.6 warning when setting an option
- 17.7 warning when sending binary output to terminal
- 17.8 offer color-coded HTTP header output
- 17.9 Choose the name of file in braces for complex URLs
- 17.10 improve how curl works in a windows console window
- 17.11 -w output to stderr
- 17.12 keep running, read instructions from pipe/socket
- 17.13 support metalink in http headers
- 17.14 --fail without --location should treat 3xx as a failure
-
- 18. Build
- 18.1 roffit
-
- 19. Test suite
- 19.1 SSL tunnel
- 19.2 nicer lacking perl message
- 19.3 more protocols supported
- 19.4 more platforms supported
- 19.5 Add support for concurrent connections
- 19.6 Use the RFC6265 test suite
-
- 20. Next SONAME bump
- 20.1 http-style HEAD output for FTP
- 20.2 combine error codes
- 20.3 extend CURLOPT_SOCKOPTFUNCTION prototype
-
- 21. Next major release
- 21.1 cleanup return codes
- 21.2 remove obsolete defines
- 21.3 size_t
- 21.4 remove several functions
- 21.5 remove CURLOPT_FAILONERROR
- 21.6 remove CURLOPT_DNS_USE_GLOBAL_CACHE
- 21.7 remove progress meter from libcurl
- 21.8 remove 'curl_httppost' from public
+ 17. SSH protocols
+ 17.1 Multiplexing
+ 17.2 SFTP performance
+ 17.3 Support better than MD5 hostkey hash
+
+ 18. Command line tool
+ 18.1 sync
+ 18.2 glob posts
+ 18.3 prevent file overwriting
+ 18.4 simultaneous parallel transfers
+ 18.5 provide formpost headers
+ 18.6 warning when setting an option
+ 18.7 warning when sending binary output to terminal
+ 18.8 offer color-coded HTTP header output
+ 18.9 Choose the name of file in braces for complex URLs
+ 18.10 improve how curl works in a windows console window
+ 18.11 -w output to stderr
+ 18.12 keep running, read instructions from pipe/socket
+ 18.13 support metalink in http headers
+ 18.14 --fail without --location should treat 3xx as a failure
+ 18.15 Introduce --fail-fast to exit on first transfer fail
+ 18.16 --retry should resume
+
+ 19. Build
+ 19.1 roffit
+ 19.2 Enable PIE and RELRO by default
+
+ 20. Test suite
+ 20.1 SSL tunnel
+ 20.2 nicer lacking perl message
+ 20.3 more protocols supported
+ 20.4 more platforms supported
+ 20.5 Add support for concurrent connections
+ 20.6 Use the RFC6265 test suite
+
+ 21. Next SONAME bump
+ 21.1 http-style HEAD output for FTP
+ 21.2 combine error codes
+ 21.3 extend CURLOPT_SOCKOPTFUNCTION prototype
+
+ 22. Next major release
+ 22.1 cleanup return codes
+ 22.2 remove obsolete defines
+ 22.3 size_t
+ 22.4 remove several functions
+ 22.5 remove CURLOPT_FAILONERROR
+ 22.6 remove CURLOPT_DNS_USE_GLOBAL_CACHE
+ 22.7 remove progress meter from libcurl
+ 22.8 remove 'curl_httppost' from public
==============================================================================
@@ -227,23 +246,18 @@
1.8 Allow SSL (HTTPS) to proxy
To prevent local users from snooping on your traffic to the proxy. Supported
- by Chrome already:
+ by Firefox and Chrome already:
https://www.chromium.org/developers/design-documents/secure-web-proxy
- ...and by Firefox soon:
- https://bugzilla.mozilla.org/show_bug.cgi?id=378637
+ See this stale work in progress branch:
+ https://github.com/curl/curl/tree/HTTPS-proxy based on this PR:
+ https://github.com/curl/curl/pull/305
1.9 Cache negative name resolves
A name resolve that has failed is likely to fail when made again within a
short period of time. Currently we only cache positive responses.
-1.10 Support IDNA2008
-
- International Domain Names are supported in libcurl since years back, powered
- by libidn. libidn implements IDNA2003 which has been superseded by IDNA2008.
- libidn2 is an existing library offering support for IDNA2008.
-
1.11 minimize dependencies with dynamicly loaded modules
We can create a system with loadable modules/plug-ins, where these modules
@@ -264,16 +278,6 @@
to use and less error-prone. Probably easiest by splitting it into several
function calls.
-1.13 Add CURLOPT_MAIL_CLIENT option
-
- Rather than use the URL to specify the mail client string to present in the
- HELO and EHLO commands, libcurl should support a new CURLOPT specifically for
- specifying this data as the URL is non-standard and to be honest a bit of a
- hack ;-)
-
- Please see the following thread for more information:
- https://curl.haxx.se/mail/lib-2012-05/0178.html
-
1.14 Typesafe curl_easy_setopt()
One of the most common problems in libcurl using applications is the lack of
@@ -342,6 +346,56 @@
in the pool), we should introduce a timeout so that connections that have
been idle for N seconds get closed.
+1.20 SRV and URI DNS records
+
+ Offer support for resolving SRV and URI DNS records for libcurl to know which
+ server to connect to for various protocols (including HTTP!).
+
+1.21 API for URL parsing/splitting
+
+ libcurl has always parsed URLs internally and never exposed any API or
+ features to allow applications to do it. Still most or many applications
+ using libcurl need that ability. In polls to users, we've learned that many
+ libcurl users would like to see and use such an API.
+
+1.23 Offer API to flush the connection pool
+
+ Sometimes applications want to flush all the existing connections kept alive.
+ An API could allow a forced flush or just a forced loop that would properly
+ close all connections that have been closed by the server already.
+
+1.24 TCP Fast Open for windows
+
+ libcurl supports the CURLOPT_TCP_FASTOPEN option since 7.49.0 for Linux and
+ Mac OS. Windows supports TCP Fast Open starting with Windows 10, version 1607
+ and we should add support for it.
+
+1.25 Remove the generated include file
+
+ When curl and libcurl are built, one of the public include files are
+ generated and is populated with a set of defines that are derevid from sizes
+ and constants for the particular target architecture that build is made. For
+ platforms that can select between 32 bit and 64 bit at build time, this
+ approach makes the libcurl build only create a set of public headers suitable
+ for one of the architectures and not both. If you build libcurl for such a
+ platform and you want to allow applications to get built using either 32/64
+ version, you must generate the libcurl headers once for each setup and you
+ must then add a replacement curl header that would itself select the correct
+ 32 or 64 bit specific header as necessary.
+
+ Your curl/curl.h alternative could then look like (replace with suitable CPP
+ variable to check):
+
+ #ifdef ARCH_32bit
+ #include <curl32/curl.h>
+ #else /* ARCH_64bit */
+ #include <curl64/curl.h>
+ #endif
+
+ A fix would either (A) fix the 32/64 setup automatically or even better (B)
+ work away the architecture specific defines from the headers so that they can
+ be used for all architectures independently of what libcurl was built for.
+
2. libcurl - multi interface
@@ -473,14 +527,6 @@ This is not detailed in any FTP specification.
headers use a default value so only headers that need to be moved have to be
specified.
-5.4 SPDY
-
- Chrome and Firefox already support SPDY and lots of web services do. There's
- a library for us to use for this (spdylay) that has a similar API and the
- same author as nghttp2.
-
- spdylay: https://github.com/tatsuhiro-t/spdylay
-
5.5 auth= in URLs
Add the ability to specify the preferred authentication mechanism to use by
@@ -500,7 +546,7 @@ This is not detailed in any FTP specification.
Consider a way to tell curl to refuse to "downgrade" protocol with a redirect
and/or possibly a bit that refuses redirect to change protocol completely.
-5.7 More compressions
+5.7 Brotli compression
Compression algorithms that perform better than gzip are being considered for
use and inclusion in existing browsers. For example 'brotli'. If servers
@@ -508,6 +554,30 @@ This is not detailed in any FTP specification.
of this. The algorithm: https://github.com/google/brotli The Firefox bug:
https://bugzilla.mozilla.org/show_bug.cgi?id=366559
+5.8 QUIC
+
+ The standardization process of QUIC has been taken to the IETF and can be
+ followed on the [IETF QUIC Mailing
+ list](https://www.ietf.org/mailman/listinfo/quic). I'd like us to get on the
+ bandwagon. Ideally, this would be done with a separate library/project to
+ handle the binary/framing layer in a similar fashion to how HTTP/2 is
+ implemented. This, to allow other projects to benefit from the work and to
+ thus broaden the interest and chance of others to participate.
+
+5.9 Add easy argument to formpost functions
+
+ Make sure there's an easy handle passed in to `curl_formadd()`,
+ `curl_formget()` and `curl_formfree()` by adding replacement functions and
+ deprecating the old ones. Allows better error messages and is generally good
+ API hygiene.
+
+5.10 Leave secure cookies alone
+
+ Non-secure origins (HTTP sites) should not be allowed to set or modify
+ cookies with the 'secure' property:
+
+ https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone-01
+
6. TELNET
@@ -544,6 +614,17 @@ to provide the data to send.
Add the ability, for an application that uses libcurl, to obtain the list of
capabilities returned from the EHLO command.
+7.3 Add CURLOPT_MAIL_CLIENT option
+
+ Rather than use the URL to specify the mail client string to present in the
+ HELO and EHLO commands, libcurl should support a new CURLOPT specifically for
+ specifying this data as the URL is non-standard and to be honest a bit of a
+ hack ;-)
+
+ Please see the following thread for more information:
+ https://curl.haxx.se/mail/lib-2012-05/0178.html
+
+
8. POP3
8.1 Pipelining
@@ -658,6 +739,63 @@ that doesn't exist on the server, just like --ftp-create-dirs.
https://curl.haxx.se/mail/lib-2013-03/0103.html . libunbound may be the
correct library to base this development on.
+ Björn Stenberg wrote a separate initial take on DANE that was never
+ completed.
+
+13.9 Support TLS v1.3
+
+ TLS version 1.3 is about to ship and is getting implemented by TLS libraries
+ as we speak. We should start to support the symbol and make sure all backends
+ handle it accordingly, then gradually add support as the TLS libraries add
+ the corresponding support. There may be a need to add some additional options
+ to allow libcurl to take advantage of the new features in 1.3.
+
+13.10 Support SSLKEYLOGFILE
+
+ When used, Firefox and Chrome dumps their master TLS keys to the file name
+ this environment variable specifies. This allows tools like for example
+ Wireshark to capture and decipher TLS traffic to/from those clients. libcurl
+ could be made to support this more widely (presumably this already works when
+ built with NSS). Peter Wu made a OpenSSL preload to make possible that can be
+ used as inspiration and guidance
+ https://git.lekensteyn.nl/peter/wireshark-notes/tree/src/sslkeylog.c
+
+13.11 Support intermediate & root pinning for PINNEDPUBLICKEY
+
+ CURLOPT_PINNEDPUBLICKEY does not consider the hashes of intermediate & root
+ certificates when comparing the pinned keys. Therefore it is not compatible
+ with "HTTP Public Key Pinning" as there also intermediate and root certificates
+ can be pinned. This is very useful as it prevents webadmins from "locking
+ themself out of their servers".
+
+ Adding this feature would make curls pinning 100% compatible to HPKP and allow
+ more flexible pinning.
+
+13.12 Support HSTS
+
+ "HTTP Strict Transport Security" is TOFU (trust on first use), time-based
+ features indicated by a HTTP header send by the webserver. It is widely used
+ in browsers and it's purpose is to prevent insecure HTTP connections after
+ a previous HTTPS connection. It protects against SSLStripping attacks.
+
+ Doc: https://developer.mozilla.org/en-US/docs/Web/Security/HTTP_strict_transport_security
+ RFC 6797: https://tools.ietf.org/html/rfc6797
+
+13.13 Support HPKP
+
+ "HTTP Public Key Pinning" is TOFU (trust on first use), time-based
+ features indicated by a HTTP header send by the webserver. It's purpose is
+ to prevent Man-in-the-middle attacks by trusted CAs by allowing webadmins
+ to specify which CAs/certificates/public keys to trust when connection to
+ their websites.
+
+ It can be build based on PINNEDPUBLICKEY.
+
+ Wikipedia: https://en.wikipedia.org/wiki/HTTP_Public_Key_Pinning
+ OWASP: https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning
+ Doc: https://developer.mozilla.org/de/docs/Web/Security/Public_Key_Pinning
+ RFC: https://tools.ietf.org/html/draft-ietf-websec-key-pinning-21
+
14. GnuTLS
14.1 SSL engine stuff
@@ -722,9 +860,38 @@ that doesn't exist on the server, just like --ftp-create-dirs.
Mandatory to support LDAP SASL authentication.
-17. Command line tool
-17.1 sync
+17. SSH protocols
+
+17.1 Multiplexing
+
+ SSH is a perfectly fine multiplexed protocols which would allow libcurl to do
+ multiple parallel transfers from the same host using the same connection,
+ much in the same spirit as HTTP/2 does. libcurl however does not take
+ advantage of that ability but will instead always create a new connection for
+ new transfers even if an existing connection already exists to the host.
+
+ To fix this, libcurl would have to detect an existing connection and "attach"
+ the new transfer to the existing one.
+
+17.2 SFTP performance
+
+ libcurl's SFTP transfer performance is sub par and can be improved, mostly by
+ the approach mentioned in "1.6 Modified buffer size approach".
+
+17.3 Support better than MD5 hostkey hash
+
+ libcurl offers the CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 option for verifying the
+ server's key. MD5 is generally being deprecated so we should implement
+ support for stronger hashing algorithms. libssh2 itself is what provides this
+ underlying functionality and it supports at least SHA-1 as an alternative.
+ SHA-1 is also being deprecated these days so we should consider workign with
+ libssh2 to instead offer support for SHA-256 or similar.
+
+
+18. Command line tool
+
+18.1 sync
"curl --sync http://example.com/feed[1-100].rss" or
"curl --sync http://example.net/{index,calendar,history}.html"
@@ -733,20 +900,20 @@ that doesn't exist on the server, just like --ftp-create-dirs.
remote file is newer than the local file. A Last-Modified HTTP date header
should also be used to set the mod date on the downloaded file.
-17.2 glob posts
+18.2 glob posts
Globbing support for -d and -F, as in 'curl -d "name=foo[0-9]" URL'.
This is easily scripted though.
-17.3 prevent file overwriting
+18.3 prevent file overwriting
- Add an option that prevents cURL from overwriting existing local files. When
+ Add an option that prevents curl from overwriting existing local files. When
used, and there already is an existing file with the target file name
(either -O or -o), a number should be appended (and increased if already
existing). So that index.html becomes first index.html.1 and then
index.html.2 etc.
-17.4 simultaneous parallel transfers
+18.4 simultaneous parallel transfers
The client could be told to use maximum N simultaneous parallel transfers and
then just make sure that happens. It should of course not make more than one
@@ -756,7 +923,7 @@ that doesn't exist on the server, just like --ftp-create-dirs.
Using the multi interface would also allow properly using parallel transfers
with HTTP/2 and supporting HTTP/2 server push from the command line.
-17.5 provide formpost headers
+18.5 provide formpost headers
Extending the capabilities of the multipart formposting. How about leaving
the ';type=foo' syntax as it is and adding an extra tag (headers) which
@@ -770,24 +937,24 @@ that doesn't exist on the server, just like --ftp-create-dirs.
which should overwrite the program reasonable defaults (plain/text,
8bit...)
-17.6 warning when setting an option
+18.6 warning when setting an option
Display a warning when libcurl returns an error when setting an option.
This can be useful to tell when support for a particular feature hasn't been
compiled into the library.
-17.7 warning when sending binary output to terminal
+18.7 warning when sending binary output to terminal
Provide a way that prompts the user for confirmation before binary data is
sent to the terminal, much in the style 'less' does it.
-17.8 offer color-coded HTTP header output
+18.8 offer color-coded HTTP header output
By offering different color output on the header name and the header
contents, they could be made more readable and thus help users working on
HTTP services.
-17.9 Choose the name of file in braces for complex URLs
+18.9 Choose the name of file in braces for complex URLs
When using braces to download a list of URLs and you use complicated names
in the list of alternatives, it could be handy to allow curl to use other
@@ -799,13 +966,13 @@ that doesn't exist on the server, just like --ftp-create-dirs.
See https://github.com/curl/curl/issues/221
-17.10 improve how curl works in a windows console window
+18.10 improve how curl works in a windows console window
If you pull the scrollbar when transferring with curl in a Windows console
window, the transfer is interrupted and can get disconnected. This can
probably be improved. See https://github.com/curl/curl/issues/322
-17.11 -w output to stderr
+18.11 -w output to stderr
-w is quite useful, but not to those of us who use curl without -o or -O
(such as for scripting through a higher level language). It would be nice to
@@ -813,7 +980,7 @@ that doesn't exist on the server, just like --ftp-create-dirs.
instead. Proposed name: --write-stderr. See
https://github.com/curl/curl/issues/613
-17.12 keep running, read instructions from pipe/socket
+18.12 keep running, read instructions from pipe/socket
Provide an option that makes curl not exit after the last URL (or even work
without a given URL), and then make it read instructions passed on a pipe or
@@ -821,7 +988,7 @@ that doesn't exist on the server, just like --ftp-create-dirs.
invoke can talk to the still running instance and ask for transfers to get
done, and thus maintain its connection pool, DNS cache and more.
-17.13 support metalink in http headers
+18.13 support metalink in http headers
Curl has support for downloading a metalink xml file, processing it, and then
downloading the target of the metalink. This is done via the --metalink option.
@@ -834,7 +1001,7 @@ that doesn't exist on the server, just like --ftp-create-dirs.
See also https://lists.gnu.org/archive/html/bug-wget/2015-06/msg00034.html for
an implematation of this in wget.
-17.14 --fail without --location should treat 3xx as a failure
+18.14 --fail without --location should treat 3xx as a failure
To allow a command line like this to detect a redirect and consider it a
failure:
@@ -845,38 +1012,68 @@ that doesn't exist on the server, just like --ftp-create-dirs.
way to implement this is probably to add that new logic in the command line
tool only and not in the underlying CURLOPT_FAILONERROR logic.
+18.15 Introduce --fail-fast to exit on first transfer fail
+
+ curl will transfer all URLs given on the command line one by one but only
+ returns the error code for the last transfer. Transfer failures on the first
+ ones will not be returned as error code etc to the shell. A --fail-fast
+ option would make curl exit and return an error for the first transfer that
+ fails.
+
+18.16 --retry should resume
+
+ When --retry is used and curl actually retries transfer, it should use the
+ already transfered data and do a resumed transfer for the rest (when
+ possible) so that it doesn't have to transfer the same data again that was
+ already tranfered before the retry.
+
+ See https://github.com/curl/curl/issues/1084
-18. Build
-18.1 roffit
+19. Build
+
+19.1 roffit
Consider extending 'roffit' to produce decent ASCII output, and use that
instead of (g)nroff when building src/tool_hugehelp.c
-19. Test suite
+19.2 Enable PIE and RELRO by default
+
+ Especially when having programs that execute curl via the command line, PIE
+ renders the exploitation of memory corruption vulnerabilities a lot more
+ difficult. This can be attributed to the additional information leaks being
+ required to conduct a successful attack. RELRO, on the other hand, masks
+ different binary sections like the GOT as read-only and thus kills a handful
+ of techniques that come in handy when attackers are able to arbitrarily
+ overwrite memory. A few tests showed that enabling these features had close
+ to no impact, neither on the performance nor on the general functionality of
+ curl.
+
+
+20. Test suite
-19.1 SSL tunnel
+20.1 SSL tunnel
Make our own version of stunnel for simple port forwarding to enable HTTPS
and FTP-SSL tests without the stunnel dependency, and it could allow us to
provide test tools built with either OpenSSL or GnuTLS
-19.2 nicer lacking perl message
+20.2 nicer lacking perl message
If perl wasn't found by the configure script, don't attempt to run the tests
but explain something nice why it doesn't.
-19.3 more protocols supported
+20.3 more protocols supported
Extend the test suite to include more protocols. The telnet could just do FTP
or http operations (for which we have test servers).
-19.4 more platforms supported
+20.4 more platforms supported
Make the test suite work on more platforms. OpenBSD and Mac OS. Remove
fork()s and it should become even more portable.
-19.5 Add support for concurrent connections
+20.5 Add support for concurrent connections
Tests 836, 882 and 938 were designed to verify that separate connections aren't
used when using different login credentials in protocols that shouldn't re-use
@@ -890,7 +1087,7 @@ that doesn't exist on the server, just like --ftp-create-dirs.
and thus the wait for connections loop is never entered to receive the second
connection.
-19.6 Use the RFC6265 test suite
+20.6 Use the RFC6265 test suite
A test suite made for HTTP cookies (RFC 6265) by Adam Barth is available at
https://github.com/abarth/http-state/tree/master/tests
@@ -900,14 +1097,14 @@ that doesn't exist on the server, just like --ftp-create-dirs.
incorporated into our regular test suite.
-20. Next SONAME bump
+21. Next SONAME bump
-20.1 http-style HEAD output for FTP
+21.1 http-style HEAD output for FTP
#undef CURL_FTP_HTTPSTYLE_HEAD in lib/ftp.c to remove the HTTP-style headers
from being output in NOBODY requests over FTP
-20.2 combine error codes
+21.2 combine error codes
Combine some of the error codes to remove duplicates. The original
numbering should not be changed, and the old identifiers would be
@@ -932,29 +1129,29 @@ that doesn't exist on the server, just like --ftp-create-dirs.
CURLE_TFTP_PERM => CURLE_REMOTE_ACCESS_DENIED
-20.3 extend CURLOPT_SOCKOPTFUNCTION prototype
+21.3 extend CURLOPT_SOCKOPTFUNCTION prototype
The current prototype only provides 'purpose' that tells what the
connection/socket is for, but not any protocol or similar. It makes it hard
for applications to differentiate on TCP vs UDP and even HTTP vs FTP and
similar.
-21. Next major release
+22. Next major release
-21.1 cleanup return codes
+22.1 cleanup return codes
curl_easy_cleanup() returns void, but curl_multi_cleanup() returns a
CURLMcode. These should be changed to be the same.
-21.2 remove obsolete defines
+22.2 remove obsolete defines
remove obsolete defines from curl/curl.h
-21.3 size_t
+22.3 size_t
make several functions use size_t instead of int in their APIs
-21.4 remove several functions
+22.4 remove several functions
remove the following functions from the public API:
@@ -975,18 +1172,18 @@ that doesn't exist on the server, just like --ftp-create-dirs.
curl_multi_socket_all
-21.5 remove CURLOPT_FAILONERROR
+22.5 remove CURLOPT_FAILONERROR
Remove support for CURLOPT_FAILONERROR, it has gotten too kludgy and weird
internally. Let the app judge success or not for itself.
-21.6 remove CURLOPT_DNS_USE_GLOBAL_CACHE
+22.6 remove CURLOPT_DNS_USE_GLOBAL_CACHE
Remove support for a global DNS cache. Anything global is silly, and we
already offer the share interface for the same functionality but done
"right".
-21.7 remove progress meter from libcurl
+22.7 remove progress meter from libcurl
The internally provided progress meter output doesn't belong in the library.
Basically no application wants it (apart from curl) but instead applications
@@ -996,7 +1193,7 @@ that doesn't exist on the server, just like --ftp-create-dirs.
variable types passed to it instead of doubles so that big files work
correctly.
-21.8 remove 'curl_httppost' from public
+22.8 remove 'curl_httppost' from public
curl_formadd() was made to fill in a public struct, but the fact that the
struct is public is never really used by application for their own advantage
diff --git a/docs/TheArtOfHttpScripting b/docs/TheArtOfHttpScripting
index 047db809..0e81d1a3 100644
--- a/docs/TheArtOfHttpScripting
+++ b/docs/TheArtOfHttpScripting
@@ -755,4 +755,4 @@ The Art Of Scripting HTTP Requests Using Curl
14.2 Sites
- https://curl.haxx.se is the home of the cURL project
+ https://curl.haxx.se is the home of the curl project
diff --git a/docs/cmdline-opts/MANPAGE.md b/docs/cmdline-opts/MANPAGE.md
new file mode 100644
index 00000000..d9f550f5
--- /dev/null
+++ b/docs/cmdline-opts/MANPAGE.md
@@ -0,0 +1,53 @@
+# curl man page generator
+
+This is the curl man page generator. It generates a single nroff man page
+output from the set of sources files in this directory.
+
+There is one source file for each supported command line option. The format is
+described below.
+
+## Option files
+
+Each command line option is described in a file named `<long name>.d`, where
+option name is written without any prefixing dashes. Like the file name for
+the -v, --verbose option is named `verbose.d`.
+
+Each file has a set of meta-data and a body of text.
+
+### Meta-data
+
+ Short: (single letter, without dash)
+ Long: (long form name, without dashes)
+ Arg: (the argument the option takes)
+ Magic: (description of "magic" options)
+ Tags: (space separated list)
+ Protocols: (space separated list for which protocols this option works)
+ Added: (version number in which this was added)
+ Mutexed: (space separated list of options this overrides)
+ Requires: (space separated list of features this option requires)
+ See-also: (space separated list of related options)
+ Redirect: (option name to use instead)
+ Help: (short text for the --help output for this option)
+ --- (end of meta-data)
+
+### Body
+
+The body of the description. Only refer to options with their long form option
+version, like --verbose. The output generator will replace such with the
+correct markup that shows both short and long version.
+
+## Header
+
+`page-header` is the nroff formatted file that will be output before the
+generated options output for the master man page.
+
+## Generate
+
+`./gen.pl mainpage`
+
+This command outputs a single huge nroff file, meant to become `curl.1`. The
+full curl man page.
+
+`./gen.pl listhelp`
+
+Generates a full `curl --help` output for all known command line options.
diff --git a/docs/cmdline-opts/anyauth.d b/docs/cmdline-opts/anyauth.d
new file mode 100644
index 00000000..c32d1ed5
--- /dev/null
+++ b/docs/cmdline-opts/anyauth.d
@@ -0,0 +1,17 @@
+Long: anyauth
+Help: Pick any authentication method
+Protocols: HTTP
+See-also: proxy-anyauth basic digest
+---
+Tells curl to figure out authentication method by itself, and use the most
+secure one the remote site claims to support. This is done by first doing a
+request and checking the response-headers, thus possibly inducing an extra
+network round-trip. This is used instead of setting a specific authentication
+method, which you can do with --basic, --digest, --ntlm, and --negotiate.
+
+Using --anyauth is not recommended if you do uploads from stdin, since it may
+require data to be sent twice and then the client must be able to rewind. If
+the need should arise when uploading from stdin, the upload operation will
+fail.
+
+Used together with --user.
diff --git a/docs/cmdline-opts/append.d b/docs/cmdline-opts/append.d
new file mode 100644
index 00000000..f001b123
--- /dev/null
+++ b/docs/cmdline-opts/append.d
@@ -0,0 +1,8 @@
+Short: a
+Long: append
+Help: Append to target file when uploading
+Protocols: FTP SFTP
+---
+When used in an upload, this makes curl append to the target file instead of
+overwriting it. If the remote file doesn't exist, it will be created. Note
+that this flag is ignored by some SFTP servers (including OpenSSH).
diff --git a/docs/cmdline-opts/basic.d b/docs/cmdline-opts/basic.d
new file mode 100644
index 00000000..09d42af9
--- /dev/null
+++ b/docs/cmdline-opts/basic.d
@@ -0,0 +1,11 @@
+Long: basic
+Help: Use HTTP Basic Authentication
+See-also: proxy-basic
+Protocols: HTTP
+---
+Tells curl to use HTTP Basic authentication with the remote host. This is the
+default and this option is usually pointless, unless you use it to override a
+previously set option that sets a different authentication method (such as
+--ntlm, --digest, or --negotiate).
+
+Used together with --user.
diff --git a/docs/cmdline-opts/cacert.d b/docs/cmdline-opts/cacert.d
new file mode 100644
index 00000000..04e11398
--- /dev/null
+++ b/docs/cmdline-opts/cacert.d
@@ -0,0 +1,28 @@
+Long: cacert
+Arg: <CA certificate>
+Help: CA certificate to verify peer against
+Protocols: TLS
+---
+Tells curl to use the specified certificate file to verify the peer. The file
+may contain multiple CA certificates. The certificate(s) must be in PEM
+format. Normally curl is built to use a default file for this, so this option
+is typically used to alter that default file.
+
+curl recognizes the environment variable named 'CURL_CA_BUNDLE' if it is
+set, and uses the given path as a path to a CA cert bundle. This option
+overrides that variable.
+
+The windows version of curl will automatically look for a CA certs file named
+\'curl-ca-bundle.crt\', either in the same directory as curl.exe, or in the
+Current Working Directory, or in any folder along your PATH.
+
+If curl is built against the NSS SSL library, the NSS PEM PKCS#11 module
+(libnsspem.so) needs to be available for this option to work properly.
+
+(iOS and macOS only) If curl is built against Secure Transport, then this
+option is supported for backward compatibility with other SSL engines, but it
+should not be set. If the option is not set, then curl will use the
+certificates in the system and user Keychain to verify the peer, which is the
+preferred method of verifying the peer's certificate chain.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/capath.d b/docs/cmdline-opts/capath.d
new file mode 100644
index 00000000..0763f7a0
--- /dev/null
+++ b/docs/cmdline-opts/capath.d
@@ -0,0 +1,15 @@
+Long: capath
+Arg: <dir>
+Help: CA directory to verify peer against
+Protocols: TLS
+---
+Tells curl to use the specified certificate directory to verify the
+peer. Multiple paths can be provided by separating them with ":" (e.g.
+\&"path1:path2:path3"). The certificates must be in PEM format, and if curl is
+built against OpenSSL, the directory must have been processed using the
+c_rehash utility supplied with OpenSSL. Using --capath can allow
+OpenSSL-powered curl to make SSL-connections much more efficiently than using
+--cacert if the --cacert file contains many CA certificates.
+
+If this option is set, the default capath value will be ignored, and if it is
+used several times, the last one will be used.
diff --git a/docs/cmdline-opts/cert-status.d b/docs/cmdline-opts/cert-status.d
new file mode 100644
index 00000000..f1aaa217
--- /dev/null
+++ b/docs/cmdline-opts/cert-status.d
@@ -0,0 +1,13 @@
+Long: cert-status
+Protocols: TLS
+Added: 7.41.0
+Help: Verify the status of the server certificate
+---
+Tells curl to verify the status of the server certificate by using the
+Certificate Status Request (aka. OCSP stapling) TLS extension.
+
+If this option is enabled and the server sends an invalid (e.g. expired)
+response, if the response suggests that the server certificate has been revoked,
+or no response at all is received, the verification fails.
+
+This is currently only implemented in the OpenSSL, GnuTLS and NSS backends.
diff --git a/docs/cmdline-opts/cert-type.d b/docs/cmdline-opts/cert-type.d
new file mode 100644
index 00000000..a04bdce5
--- /dev/null
+++ b/docs/cmdline-opts/cert-type.d
@@ -0,0 +1,10 @@
+Long: cert-type
+Protocols: TLS
+Arg: <type>
+Help: Certificate file type (DER/PEM/ENG)
+See-also: cert key key-type
+---
+Tells curl what certificate type the provided certificate is in. PEM, DER and
+ENG are recognized types. If not specified, PEM is assumed.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/cert.d b/docs/cmdline-opts/cert.d
new file mode 100644
index 00000000..0cd5d535
--- /dev/null
+++ b/docs/cmdline-opts/cert.d
@@ -0,0 +1,32 @@
+Short: E
+Long: cert
+Arg: <certificate[:password]>
+Help: Client certificate file and password
+Protocols: TLS
+See-also: cert-type key key-type
+---
+Tells curl to use the specified client certificate file when getting a file
+with HTTPS, FTPS or another SSL-based protocol. The certificate must be in
+PKCS#12 format if using Secure Transport, or PEM format if using any other
+engine. If the optional password isn't specified, it will be queried for on
+the terminal. Note that this option assumes a \&"certificate" file that is the
+private key and the client certificate concatenated! See --cert and --key to
+specify them independently.
+
+If curl is built against the NSS SSL library then this option can tell
+curl the nickname of the certificate to use within the NSS database defined
+by the environment variable SSL_DIR (or by default /etc/pki/nssdb). If the
+NSS PEM PKCS#11 module (libnsspem.so) is available then PEM files may be
+loaded. If you want to use a file from the current directory, please precede
+it with "./" prefix, in order to avoid confusion with a nickname. If the
+nickname contains ":", it needs to be preceded by "\\" so that it is not
+recognized as password delimiter. If the nickname contains "\\", it needs to
+be escaped as "\\\\" so that it is not recognized as an escape character.
+
+(iOS and macOS only) If curl is built against Secure Transport, then the
+certificate string can either be the name of a certificate/private key in the
+system or user keychain, or the path to a PKCS#12-encoded certificate and
+private key. If you want to use a file from the current directory, please
+precede it with "./" prefix, in order to avoid confusion with a nickname.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/ciphers.d b/docs/cmdline-opts/ciphers.d
new file mode 100644
index 00000000..b1e5ac9a
--- /dev/null
+++ b/docs/cmdline-opts/ciphers.d
@@ -0,0 +1,16 @@
+Long: ciphers
+Arg: <list of ciphers>
+help: SSL ciphers to use
+Protocols: TLS
+---
+Specifies which ciphers to use in the connection. The list of ciphers must
+specify valid ciphers. Read up on SSL cipher list details on this URL:
+
+ https://www.openssl.org/docs/apps/ciphers.html
+
+NSS ciphers are done differently than OpenSSL and GnuTLS. The full list of NSS
+ciphers is in the NSSCipherSuite entry at this URL:
+
+ https://git.fedorahosted.org/cgit/mod_nss.git/plain/docs/mod_nss.html#Directives
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/compressed.d b/docs/cmdline-opts/compressed.d
new file mode 100644
index 00000000..dc130c1f
--- /dev/null
+++ b/docs/cmdline-opts/compressed.d
@@ -0,0 +1,7 @@
+Long: compressed
+Help: Request compressed response
+Protocols: HTTP
+---
+Request a compressed response using one of the algorithms curl supports, and
+save the uncompressed document. If this option is used and the server sends
+an unsupported encoding, curl will report an error.
diff --git a/docs/cmdline-opts/config.d b/docs/cmdline-opts/config.d
new file mode 100644
index 00000000..4a325127
--- /dev/null
+++ b/docs/cmdline-opts/config.d
@@ -0,0 +1,60 @@
+Long: config
+Arg: <file>
+Help: Read config from a file
+Short: K
+---
+Specify which config file to read curl arguments from. The config file is a
+text file in which command line arguments can be written which then will be
+used as if they were written on the actual command line.
+
+Options and their parameters must be specified on the same config file line,
+separated by whitespace, colon, or the equals sign. Long option names can
+optionally be given in the config file without the initial double dashes and
+if so, the colon or equals characters can be used as separators. If the option
+is specified with one or two dashes, there can be no colon or equals character
+between the option and its parameter.
+
+If the parameter is to contain whitespace, the parameter must be enclosed
+within quotes. Within double quotes, the following escape sequences are
+available: \\\\, \\", \\t, \\n, \\r and \\v. A backslash preceding any other
+letter is ignored. If the first column of a config line is a '#' character,
+the rest of the line will be treated as a comment. Only write one option per
+physical line in the config file.
+
+Specify the filename to --config as '-' to make curl read the file from stdin.
+
+Note that to be able to specify a URL in the config file, you need to specify
+it using the --url option, and not by simply writing the URL on its own
+line. So, it could look similar to this:
+
+url = "https://curl.haxx.se/docs/"
+
+When curl is invoked, it always (unless --disable is used) checks for a
+default config file and uses it if found. The default config file is checked
+for in the following places in this order:
+
+1) curl tries to find the "home dir": It first checks for the CURL_HOME and
+then the HOME environment variables. Failing that, it uses getpwuid() on
+Unix-like systems (which returns the home dir given the current user in your
+system). On Windows, it then checks for the APPDATA variable, or as a last
+resort the '%USERPROFILE%\\Application Data'.
+
+2) On windows, if there is no _curlrc file in the home dir, it checks for one
+in the same dir the curl executable is placed. On Unix-like systems, it will
+simply try to load .curlrc from the determined home dir.
+
+.nf
+# --- Example file ---
+# this is a comment
+url = "example.com"
+output = "curlhere.html"
+user-agent = "superagent/1.0"
+
+# and fetch another URL too
+url = "example.com/docs/manpage.html"
+-O
+referer = "http://nowhereatall.example.com/"
+# --- End of example file ---
+.fi
+
+This option can be used multiple times to load multiple config files.
diff --git a/docs/cmdline-opts/connect-timeout.d b/docs/cmdline-opts/connect-timeout.d
new file mode 100644
index 00000000..3a32d868
--- /dev/null
+++ b/docs/cmdline-opts/connect-timeout.d
@@ -0,0 +1,11 @@
+Long: connect-timeout
+Arg: <seconds>
+Help: Maximum time allowed for connection
+See-also: max-time
+---
+Maximum time in seconds that you allow curl's connection to take. This only
+limits the connection phase, so if curl connects within the given period it
+will continue - if not it will exit. Since version 7.32.0, this option
+accepts decimal values.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/connect-to.d b/docs/cmdline-opts/connect-to.d
new file mode 100644
index 00000000..3fa0568a
--- /dev/null
+++ b/docs/cmdline-opts/connect-to.d
@@ -0,0 +1,18 @@
+Long: connect-to
+Arg: <HOST1:PORT1:HOST2:PORT2>
+Help: Connect to host
+Added: 7.49.0
+See-also: resolve header
+---
+
+For a request to the given HOST:PORT pair, connect to
+CONNECT-TO-HOST:CONNECT-TO-PORT instead. This option is suitable to direct
+requests at a specific server, e.g. at a specific cluster node in a cluster of
+servers. This option is only used to establish the network connection. It
+does NOT affect the hostname/port that is used for TLS/SSL (e.g. SNI,
+certificate verification) or for the application protocols. "host" and "port"
+may be the empty string, meaning "any host/port". "connect-to-host" and
+"connect-to-port" may also be the empty string, meaning "use the request's
+original host/port".
+
+This option can be used many times to add many connect rules.
diff --git a/docs/cmdline-opts/continue-at.d b/docs/cmdline-opts/continue-at.d
new file mode 100644
index 00000000..733f4941
--- /dev/null
+++ b/docs/cmdline-opts/continue-at.d
@@ -0,0 +1,15 @@
+Short: C
+Long: continue-at
+Arg: <offset>
+Help: Resumed transfer offset
+See-also: range
+---
+Continue/Resume a previous file transfer at the given offset. The given offset
+is the exact number of bytes that will be skipped, counting from the beginning
+of the source file before it is transferred to the destination. If used with
+uploads, the FTP server command SIZE will not be used by curl.
+
+Use "-C -" to tell curl to automatically find out where/how to resume the
+transfer. It then uses the given output/input files to figure that out.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/cookie-jar.d b/docs/cmdline-opts/cookie-jar.d
new file mode 100644
index 00000000..da79777e
--- /dev/null
+++ b/docs/cmdline-opts/cookie-jar.d
@@ -0,0 +1,24 @@
+Short: c
+Long: cookie-jar
+Arg: <filename>
+Protocols: HTTP
+Help: Write cookies to <filename> after operation
+---
+Specify to which file you want curl to write all cookies after a completed
+operation. Curl writes all cookies from its in-memory cookie storage to the
+given file at the end of operations. If no cookies are known, no data will be
+written. The file will be written using the Netscape cookie file format. If
+you set the file name to a single dash, "-", the cookies will be written to
+stdout.
+
+This command line option will activate the cookie engine that makes curl
+record and use cookies. Another way to activate it is to use the --cookie
+option.
+
+If the cookie jar can't be created or written to, the whole curl operation
+won't fail or even report an error clearly. Using --verbose will get a warning
+displayed, but that is the only visible feedback you get about this possibly
+lethal situation.
+
+If this option is used several times, the last specified file name will be
+used.
diff --git a/docs/cmdline-opts/cookie.d b/docs/cmdline-opts/cookie.d
new file mode 100644
index 00000000..383adda6
--- /dev/null
+++ b/docs/cmdline-opts/cookie.d
@@ -0,0 +1,36 @@
+Short: b
+Long: cookie
+Arg: <data>
+Protocols: HTTP
+Help: Send cookies from string/file
+---
+Pass the data to the HTTP server in the Cookie header. It is supposedly
+the data previously received from the server in a "Set-Cookie:" line. The
+data should be in the format "NAME1=VALUE1; NAME2=VALUE2".
+
+If no '=' symbol is used in the argument, it is instead treated as a filename
+to read previously stored cookie from. This option also activates the cookie
+engine which will make curl record incoming cookies, which may be handy if
+you're using this in combination with the --location option or do multiple URL
+transfers on the same invoke.
+
+The file format of the file to read cookies from should be plain HTTP headers
+(Set-Cookie style) or the Netscape/Mozilla cookie file format.
+
+The file specified with --cookie is only used as input. No cookies will be
+written to the file. To store cookies, use the --cookie-jar option.
+
+Exercise caution if you are using this option and multiple transfers may
+occur. If you use the NAME1=VALUE1; format, or in a file use the Set-Cookie
+format and don't specify a domain, then the cookie is sent for any domain
+(even after redirects are followed) and cannot be modified by a server-set
+cookie. If the cookie engine is enabled and a server sets a cookie of the same
+name then both will be sent on a future transfer to that server, likely not
+what you intended. To address these issues set a domain in Set-Cookie (doing
+that will include sub domains) or use the Netscape format.
+
+If this option is used several times, the last one will be used.
+
+Users very often want to both read cookies from a file and write updated
+cookies back to a file, so using both --cookie and --cookie-jar in the same
+command line is common.
diff --git a/docs/cmdline-opts/create-dirs.d b/docs/cmdline-opts/create-dirs.d
new file mode 100644
index 00000000..49e22e75
--- /dev/null
+++ b/docs/cmdline-opts/create-dirs.d
@@ -0,0 +1,9 @@
+Long: create-dirs
+Help: Create necessary local directory hierarchy
+---
+When used in conjunction with the --output option, curl will create the
+necessary local directory hierarchy as needed. This option creates the dirs
+mentioned with the --output option, nothing else. If the --output file name
+uses no dir or if the dirs it mentions already exist, no dir will be created.
+
+To create remote directories when using FTP or SFTP, try --ftp-create-dirs.
diff --git a/docs/cmdline-opts/crlf.d b/docs/cmdline-opts/crlf.d
new file mode 100644
index 00000000..f6694b65
--- /dev/null
+++ b/docs/cmdline-opts/crlf.d
@@ -0,0 +1,7 @@
+Long: crlf
+Help: Convert LF to CRLF in upload
+Protocols: FTP SMTP
+---
+Convert LF to CRLF in upload. Useful for MVS (OS/390).
+
+(SMTP added in 7.40.0)
diff --git a/docs/cmdline-opts/crlfile.d b/docs/cmdline-opts/crlfile.d
new file mode 100644
index 00000000..ae216b9e
--- /dev/null
+++ b/docs/cmdline-opts/crlfile.d
@@ -0,0 +1,10 @@
+Long: crfile
+Arg: <file>
+Protocols: TLS
+Help: Get a CRL list in PEM format from the given file
+Added: 7.19.7
+---
+Provide a file using PEM format with a Certificate Revocation List that may
+specify peer certificates that are to be considered revoked.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/data-ascii.d b/docs/cmdline-opts/data-ascii.d
new file mode 100644
index 00000000..52f80312
--- /dev/null
+++ b/docs/cmdline-opts/data-ascii.d
@@ -0,0 +1,5 @@
+Long: data-ascii
+Arg: <data>
+Help: HTTP POST ASCII data
+Protocols: HTTP
+Redirect: data
diff --git a/docs/cmdline-opts/data-binary.d b/docs/cmdline-opts/data-binary.d
new file mode 100644
index 00000000..c6721c64
--- /dev/null
+++ b/docs/cmdline-opts/data-binary.d
@@ -0,0 +1,13 @@
+Long: data-binary
+Arg: <data>
+Help: HTTP POST binary data
+Protocols: HTTP
+---
+This posts data exactly as specified with no extra processing whatsoever.
+
+If you start the data with the letter @, the rest should be a filename. Data
+is posted in a similar manner as --data does, except that newlines and
+carriage returns are preserved and conversions are never done.
+
+If this option is used several times, the ones following the first will append
+data as described in --data.
diff --git a/docs/cmdline-opts/data-raw.d b/docs/cmdline-opts/data-raw.d
new file mode 100644
index 00000000..7669b4ab
--- /dev/null
+++ b/docs/cmdline-opts/data-raw.d
@@ -0,0 +1,9 @@
+Long: data-raw
+Arg: <data>
+Protocols: HTTP
+Help: HTTP POST data, '@' allowed
+Added: 7.43.0
+See-also: data
+---
+This posts data similarly to --data but without the special
+interpretation of the @ character.
diff --git a/docs/cmdline-opts/data-urlencode.d b/docs/cmdline-opts/data-urlencode.d
new file mode 100644
index 00000000..9873f335
--- /dev/null
+++ b/docs/cmdline-opts/data-urlencode.d
@@ -0,0 +1,33 @@
+Long: data-urlencode
+Arg: <data>
+Help: HTTP POST data url encoded
+Protocols: HTTP
+See-also: data data-raw
+Added: 7.18.0
+---
+This posts data, similar to the other --data options with the exception
+that this performs URL-encoding.
+
+To be CGI-compliant, the <data> part should begin with a \fIname\fP followed
+by a separator and a content specification. The <data> part can be passed to
+curl using one of the following syntaxes:
+.RS
+.IP "content"
+This will make curl URL-encode the content and pass that on. Just be careful
+so that the content doesn't contain any = or @ symbols, as that will then make
+the syntax match one of the other cases below!
+.IP "=content"
+This will make curl URL-encode the content and pass that on. The preceding =
+symbol is not included in the data.
+.IP "name=content"
+This will make curl URL-encode the content part and pass that on. Note that
+the name part is expected to be URL-encoded already.
+.IP "@filename"
+This will make curl load data from the given file (including any newlines),
+URL-encode that data and pass it on in the POST.
+.IP "name@filename"
+This will make curl load data from the given file (including any newlines),
+URL-encode that data and pass it on in the POST. The name part gets an equal
+sign appended, resulting in \fIname=urlencoded-file-content\fP. Note that the
+name is expected to be URL-encoded already.
+.RE
diff --git a/docs/cmdline-opts/data.d b/docs/cmdline-opts/data.d
new file mode 100644
index 00000000..353b41f2
--- /dev/null
+++ b/docs/cmdline-opts/data.d
@@ -0,0 +1,30 @@
+Long: data
+Short: d
+Arg: <data>
+Help: HTTP POST data
+Protocols: HTTP
+See-also: data-binary data-urlencode data-raw
+Mutexed: form head upload
+---
+Sends the specified data in a POST request to the HTTP server, in the same way
+that a browser does when a user has filled in an HTML form and presses the
+submit button. This will cause curl to pass the data to the server using the
+content-type application/x-www-form-urlencoded. Compare to --form.
+
+--data-raw is almost the same but does not have a special interpretation of
+the @ character. To post data purely binary, you should instead use the
+--data-binary option. To URL-encode the value of a form field you may use
+--data-urlencode.
+
+If any of these options is used more than once on the same command line, the
+data pieces specified will be merged together with a separating
+&-symbol. Thus, using '-d name=daniel -d skill=lousy' would generate a post
+chunk that looks like \&'name=daniel&skill=lousy'.
+
+If you start the data with the letter @, the rest should be a file name to
+read the data from, or - if you want curl to read the data from
+stdin. Multiple files can also be specified. Posting data from a file named
+'foobar' would thus be done with \fI--data\fP @foobar. When --data is told to
+read from a file like that, carriage returns and newlines will be stripped
+out. If you don't want the @ character to have a special interpretation use
+--data-raw instead.
diff --git a/docs/cmdline-opts/delegation.d b/docs/cmdline-opts/delegation.d
new file mode 100644
index 00000000..138d8233
--- /dev/null
+++ b/docs/cmdline-opts/delegation.d
@@ -0,0 +1,16 @@
+Long: delegation
+Arg: <LEVEL>
+Help: GSS-API delegation permission
+Protocols: GSS/kerberos
+---
+Set LEVEL to tell the server what it is allowed to delegate when it
+comes to user credentials.
+.RS
+.IP "none"
+Don't allow any delegation.
+.IP "policy"
+Delegates if and only if the OK-AS-DELEGATE flag is set in the Kerberos
+service ticket, which is a matter of realm policy.
+.IP "always"
+Unconditionally allow the server to delegate.
+.RE
diff --git a/docs/cmdline-opts/digest.d b/docs/cmdline-opts/digest.d
new file mode 100644
index 00000000..5cdd9258
--- /dev/null
+++ b/docs/cmdline-opts/digest.d
@@ -0,0 +1,11 @@
+Long: digest
+Help: Use HTTP Digest Authentication
+Protocols: HTTP
+Mutexed: basic ntlm negotiate
+See-also: user proxy-digest anyauth
+---
+Enables HTTP Digest authentication. This is an authentication scheme that
+prevents the password from being sent over the wire in clear text. Use this in
+combination with the normal --user option to set user name and password.
+
+If this option is used several times, only the first one is used.
diff --git a/docs/cmdline-opts/disable-eprt.d b/docs/cmdline-opts/disable-eprt.d
new file mode 100644
index 00000000..a1e53c0b
--- /dev/null
+++ b/docs/cmdline-opts/disable-eprt.d
@@ -0,0 +1,19 @@
+Long: disable-eprt
+Help: Inhibit using EPRT or LPRT
+Protocols: FTP
+---
+Tell curl to disable the use of the EPRT and LPRT commands when doing active
+FTP transfers. Curl will normally always first attempt to use EPRT, then LPRT
+before using PORT, but with this option, it will use PORT right away. EPRT and
+LPRT are extensions to the original FTP protocol, and may not work on all
+servers, but they enable more functionality in a better way than the
+traditional PORT command.
+
+--eprt can be used to explicitly enable EPRT again and --no-eprt is an alias
+for --disable-eprt.
+
+If the server is accessed using IPv6, this option will have no effect as EPRT
+is necessary then.
+
+Disabling EPRT only changes the active behavior. If you want to switch to
+passive mode you need to not use --ftp-port or force it with --ftp-pasv.
diff --git a/docs/cmdline-opts/dns-interface.d b/docs/cmdline-opts/dns-interface.d
new file mode 100644
index 00000000..45e5af26
--- /dev/null
+++ b/docs/cmdline-opts/dns-interface.d
@@ -0,0 +1,11 @@
+Long: dns-interface
+Arg: <interface>
+Help: Interface to use for DNS requests
+Protocols: DNS
+See-also: dns-ipv4-addr dns-ipv6-addr
+Added: 7.33.0
+Requires: c-ares
+---
+Tell curl to send outgoing DNS requests through <interface>. This option is a
+counterpart to --interface (which does not affect DNS). The supplied string
+must be an interface name (not an address).
diff --git a/docs/cmdline-opts/dns-ipv4-addr.d b/docs/cmdline-opts/dns-ipv4-addr.d
new file mode 100644
index 00000000..597b8588
--- /dev/null
+++ b/docs/cmdline-opts/dns-ipv4-addr.d
@@ -0,0 +1,11 @@
+Long: dns-ipv4-addr
+Arg: <address>
+Help: IPv4 address to use for DNS requests
+Protocols: DNS
+See-also: dns-interface dns-ipv6-addr
+Added: 7.33.0
+Requires: c-ares
+---
+Tell curl to bind to <ip-address> when making IPv4 DNS requests, so that
+the DNS requests originate from this address. The argument should be a
+single IPv4 address.
diff --git a/docs/cmdline-opts/dns-ipv6-addr.d b/docs/cmdline-opts/dns-ipv6-addr.d
new file mode 100644
index 00000000..581f0195
--- /dev/null
+++ b/docs/cmdline-opts/dns-ipv6-addr.d
@@ -0,0 +1,11 @@
+Long: dns-ipv6-addr
+Arg: <address>
+Help: IPv6 address to use for DNS requests
+Protocols: DNS
+See-also: dns-interface dns-ipv4-addr
+Added: 7.33.0
+Requires: c-ares
+---
+Tell curl to bind to <ip-address> when making IPv6 DNS requests, so that
+the DNS requests originate from this address. The argument should be a
+single IPv6 address.
diff --git a/docs/cmdline-opts/dns-servers.d b/docs/cmdline-opts/dns-servers.d
new file mode 100644
index 00000000..a98fd07d
--- /dev/null
+++ b/docs/cmdline-opts/dns-servers.d
@@ -0,0 +1,10 @@
+Long: dns-servers
+Arg: <addresses>
+Help: DNS server addrs to use
+Requires: c-ares
+Added: 7.33.0
+---
+Set the list of DNS servers to be used instead of the system default.
+The list of IP addresses should be separated with commas. Port numbers
+may also optionally be given as \fI:<port-number>\fP after each IP
+address.
diff --git a/docs/cmdline-opts/dump-header.d b/docs/cmdline-opts/dump-header.d
new file mode 100644
index 00000000..05c10aff
--- /dev/null
+++ b/docs/cmdline-opts/dump-header.d
@@ -0,0 +1,18 @@
+Long: dump-header
+Short: D
+Arg: <filename>
+Help: Write the received headers to <filename>
+Protocols: HTTP FTP
+See-also: output
+---
+Write the received protocol headers to the specified file.
+
+This option is handy to use when you want to store the headers that an HTTP
+site sends to you. Cookies from the headers could then be read in a second
+curl invocation by using the --cookie option! The --cookie-jar option is a
+better way to store cookies.
+
+When used in FTP, the FTP server response lines are considered being "headers"
+and thus are saved there.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/egd-file.d b/docs/cmdline-opts/egd-file.d
new file mode 100644
index 00000000..2ee6d34d
--- /dev/null
+++ b/docs/cmdline-opts/egd-file.d
@@ -0,0 +1,7 @@
+Long: egd-file
+Help: EGD socket path for random data
+Protocols: TLS
+See-also: random-file
+---
+Specify the path name to the Entropy Gathering Daemon socket. The socket is
+used to seed the random engine for SSL connections.
diff --git a/docs/cmdline-opts/engine.d b/docs/cmdline-opts/engine.d
new file mode 100644
index 00000000..53b7c333
--- /dev/null
+++ b/docs/cmdline-opts/engine.d
@@ -0,0 +1,8 @@
+Long: engine
+Arg: <name>
+Help: Crypto engine to use
+Protocols: TLS
+---
+Select the OpenSSL crypto engine to use for cipher operations. Use \fI--engine
+list\fP to print a list of build-time supported engines. Note that not all (or
+none) of the engines may be available at run-time.
diff --git a/docs/cmdline-opts/environment.d b/docs/cmdline-opts/environment.d
new file mode 100644
index 00000000..6289e53d
--- /dev/null
+++ b/docs/cmdline-opts/environment.d
@@ -0,0 +1,7 @@
+Long: environment
+Help: Write results to environment variables
+Requires: RISC OS
+---
+Sets a range of environment variables, using the names the --write-out option
+supports, to allow easier extraction of useful information after having run
+curl.
diff --git a/docs/cmdline-opts/expect100-timeout.d b/docs/cmdline-opts/expect100-timeout.d
new file mode 100644
index 00000000..c88f0b84
--- /dev/null
+++ b/docs/cmdline-opts/expect100-timeout.d
@@ -0,0 +1,11 @@
+Long: expect100-timeout
+Arg: <seconds>
+Help: How long to wait for 100-continue
+Protocols: HTTP
+Added: 7.47.0
+See-also: connect-timeout
+---
+Maximum time in seconds that you allow curl to wait for a 100-continue
+response when curl emits an Expects: 100-continue header in its request. By
+default curl will wait one second. This option accepts decimal values! When
+curl stops waiting, it will continue as if the response has been received.
diff --git a/docs/cmdline-opts/fail-early.d b/docs/cmdline-opts/fail-early.d
new file mode 100644
index 00000000..4489b4fc
--- /dev/null
+++ b/docs/cmdline-opts/fail-early.d
@@ -0,0 +1,18 @@
+Long: fail-early
+Help: Fail on first transfer error, do not continue
+Added: 7.52.0
+---
+Fail and exit on first detected error.
+
+When curl is used to do multiple transfers on the command line, it will
+attempt to operate on each given URL, one by one. By default, it will ignore
+errors if there are more URLs given and the last URL's success will determine
+the error code curl returns. So early failures will be "hidden" by subsequent
+successful transfers.
+
+Using this option, curl will instead return an error on the first transfers
+that fails, independent on the amount of more URLs that are given on the
+command line. This way, no transfer failures go undetected by scripts and
+similar.
+
+This option will apply for all given URLs even if you use --next.
diff --git a/docs/cmdline-opts/fail.d b/docs/cmdline-opts/fail.d
new file mode 100644
index 00000000..c46c571b
--- /dev/null
+++ b/docs/cmdline-opts/fail.d
@@ -0,0 +1,14 @@
+Long: fail
+Short: f
+Protocols: HTTP
+Help: Fail silently (no output at all) on HTTP errors
+---
+Fail silently (no output at all) on server errors. This is mostly done to
+better enable scripts etc to better deal with failed attempts. In normal cases
+when an HTTP server fails to deliver a document, it returns an HTML document
+stating so (which often also describes why and more). This flag will prevent
+curl from outputting that and return error 22.
+
+This method is not fail-safe and there are occasions where non-successful
+response codes will slip through, especially when authentication is involved
+(response codes 401 and 407).
diff --git a/docs/cmdline-opts/false-start.d b/docs/cmdline-opts/false-start.d
new file mode 100644
index 00000000..65a8afb8
--- /dev/null
+++ b/docs/cmdline-opts/false-start.d
@@ -0,0 +1,12 @@
+Long: false-start
+Help: Enable TLS False Start
+Protocols: TLS
+Added: 7.42.0
+---
+Tells curl to use false start during the TLS handshake. False start is a mode
+where a TLS client will start sending application data before verifying the
+server's Finished message, thus saving a round trip when performing a full
+handshake.
+
+This is currently only implemented in the NSS and Secure Transport (on iOS 7.0
+or later, or OS X 10.9 or later) backends.
diff --git a/docs/cmdline-opts/form-string.d b/docs/cmdline-opts/form-string.d
new file mode 100644
index 00000000..db1856b4
--- /dev/null
+++ b/docs/cmdline-opts/form-string.d
@@ -0,0 +1,10 @@
+Long: form-string
+Help: Specify HTTP multipart POST data
+Protocols: HTTP
+See-also: form
+---
+Similar to --form except that the value string for the named parameter is used
+literally. Leading \&'@' and \&'<' characters, and the \&';type=' string in
+the value have no special meaning. Use this in preference to --form\fP if
+there's any possibility that the string value may accidentally trigger the
+\&'@' or \&'<' features of --form.
diff --git a/docs/cmdline-opts/form.d b/docs/cmdline-opts/form.d
new file mode 100644
index 00000000..87a7d076
--- /dev/null
+++ b/docs/cmdline-opts/form.d
@@ -0,0 +1,54 @@
+Long: form
+Short: F
+Arg: <name=content>
+Help: Specify HTTP multipart POST data
+Protocols: HTTP
+Mutexed: data head upload
+---
+This lets curl emulate a filled-in form in which a user has pressed the submit
+button. This causes curl to POST data using the Content-Type
+multipart/form-data according to RFC 2388. This enables uploading of binary
+files etc. To force the 'content' part to be a file, prefix the file name with
+an @ sign. To just get the content part from a file, prefix the file name with
+the symbol <. The difference between @ and < is then that @ makes a file get
+attached in the post as a file upload, while the < makes a text field and just
+get the contents for that text field from a file.
+
+Example: to send an image to a server, where \&'profile' is the name of the
+form-field to which portrait.jpg will be the input:
+
+ curl -F profile=@portrait.jpg https://example.com/upload.cgi
+
+To read content from stdin instead of a file, use - as the filename. This goes
+for both @ and < constructs. Unfortunately it does not support reading the
+file from a named pipe or similar, as it needs the full size before the
+transfer starts.
+
+You can also tell curl what Content-Type to use by using 'type=', in a manner
+similar to:
+
+ curl -F "web=@index.html;type=text/html" example.com
+
+or
+
+ curl -F "name=daniel;type=text/foo" example.com
+
+You can also explicitly change the name field of a file upload part by setting
+filename=, like this:
+
+ curl -F "file=@localfile;filename=nameinpost" example.com
+
+If filename/path contains ',' or ';', it must be quoted by double-quotes like:
+
+ curl -F "file=@\\"localfile\\";filename=\\"nameinpost\\"" example.com
+
+or
+
+ curl -F 'file=@"localfile";filename="nameinpost"' example.com
+
+Note that if a filename/path is quoted by double-quotes, any double-quote
+or backslash within the filename must be escaped by backslash.
+
+See further examples and details in the MANUAL.
+
+This option can be used multiple times.
diff --git a/docs/cmdline-opts/ftp-account.d b/docs/cmdline-opts/ftp-account.d
new file mode 100644
index 00000000..013c4f37
--- /dev/null
+++ b/docs/cmdline-opts/ftp-account.d
@@ -0,0 +1,10 @@
+Long: ftp-account
+Arg: <data>
+Help: Account data string
+Protocols: FTP
+Added: 7.13.0
+---
+When an FTP server asks for "account data" after user name and password has
+been provided, this data is sent off using the ACCT command.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/ftp-alternative-to-user.d b/docs/cmdline-opts/ftp-alternative-to-user.d
new file mode 100644
index 00000000..8982ba8b
--- /dev/null
+++ b/docs/cmdline-opts/ftp-alternative-to-user.d
@@ -0,0 +1,10 @@
+Long: ftp-alternative-to-user
+Arg: <command>
+Help: String to replace USER [name]
+Protocols: FTP
+Added: 7.15.5
+---
+If authenticating with the USER and PASS commands fails, send this command.
+When connecting to Tumbleweed's Secure Transport server over FTPS using a
+client certificate, using "SITE AUTH" will tell the server to retrieve the
+username from the certificate.
diff --git a/docs/cmdline-opts/ftp-create-dirs.d b/docs/cmdline-opts/ftp-create-dirs.d
new file mode 100644
index 00000000..ede57100
--- /dev/null
+++ b/docs/cmdline-opts/ftp-create-dirs.d
@@ -0,0 +1,8 @@
+Long: ftp-create-dirs
+Protocols: FTP SFTP
+Help: Create the remote dirs if not present
+See-also: create-dirs
+---
+When an FTP or SFTP URL/operation uses a path that doesn't currently exist on
+the server, the standard behavior of curl is to fail. Using this option, curl
+will instead attempt to create missing directories.
diff --git a/docs/cmdline-opts/ftp-method.d b/docs/cmdline-opts/ftp-method.d
new file mode 100644
index 00000000..95aa522e
--- /dev/null
+++ b/docs/cmdline-opts/ftp-method.d
@@ -0,0 +1,21 @@
+Long: ftp-method
+Arg: <method>
+Help: Control CWD usage
+Protocols: FTP
+Added: 7.15.1
+---
+Control what method curl should use to reach a file on an FTP(S)
+server. The method argument should be one of the following alternatives:
+.RS
+.IP multicwd
+curl does a single CWD operation for each path part in the given URL. For deep
+hierarchies this means very many commands. This is how RFC 1738 says it should
+be done. This is the default but the slowest behavior.
+.IP nocwd
+curl does no CWD at all. curl will do SIZE, RETR, STOR etc and give a full
+path to the server for all these commands. This is the fastest behavior.
+.IP singlecwd
+curl does one CWD with the full target directory and then operates on the file
+\&"normally" (like in the multicwd case). This is somewhat more standards
+compliant than 'nocwd' but without the full penalty of 'multicwd'.
+.RE
diff --git a/docs/cmdline-opts/ftp-pasv.d b/docs/cmdline-opts/ftp-pasv.d
new file mode 100644
index 00000000..44103e21
--- /dev/null
+++ b/docs/cmdline-opts/ftp-pasv.d
@@ -0,0 +1,16 @@
+Long: ftp-pasv
+Help: Use PASV/EPSV instead of PORT
+Protocols: FTP
+Added: 7.11.0
+See-also: disable-epsv
+---
+Use passive mode for the data connection. Passive is the internal default
+behavior, but using this option can be used to override a previous --ftp-port
+option.
+
+If this option is used several times, only the first one is used. Undoing an
+enforced passive really isn't doable but you must then instead enforce the
+correct --ftp-port again.
+
+Passive mode means that curl will try the EPSV command first and then PASV,
+unless --disable-epsv is used.
diff --git a/docs/cmdline-opts/ftp-port.d b/docs/cmdline-opts/ftp-port.d
new file mode 100644
index 00000000..a852e905
--- /dev/null
+++ b/docs/cmdline-opts/ftp-port.d
@@ -0,0 +1,32 @@
+Long: ftp-port
+Arg: <address>
+Help: Use PORT instead of PASV
+Short: P
+Protocols: FTP
+See-also: ftp-pasv disable-eprt
+---
+Reverses the default initiator/listener roles when connecting with FTP. This
+option makes curl use active mode. curl then tells the server to connect back
+to the client's specified address and port, while passive mode asks the server
+to setup an IP address and port for it to connect to. <address> should be one
+of:
+.RS
+.IP interface
+i.e "eth0" to specify which interface's IP address you want to use (Unix only)
+.IP "IP address"
+i.e "192.168.10.1" to specify the exact IP address
+.IP "host name"
+i.e "my.host.domain" to specify the machine
+.IP "-"
+make curl pick the same IP address that is already used for the control
+connection
+.RE
+
+If this option is used several times, the last one will be used. Disable the
+use of PORT with --ftp-pasv. Disable the attempt to use the EPRT command
+instead of PORT by using --disable-eprt. EPRT is really PORT++.
+
+Since 7.19.5, you can append \&":[start]-[end]\&" to the right of the address,
+to tell curl what TCP port range to use. That means you specify a port range,
+from a lower to a higher number. A single number works as well, but do note
+that it increases the risk of failure since the port may not be available.
diff --git a/docs/cmdline-opts/ftp-pret.d b/docs/cmdline-opts/ftp-pret.d
new file mode 100644
index 00000000..dac4c353
--- /dev/null
+++ b/docs/cmdline-opts/ftp-pret.d
@@ -0,0 +1,8 @@
+Long: ftp-pret
+Help: Send PRET before PASV
+Protocols: FTP
+Added: 7.20.0
+---
+Tell curl to send a PRET command before PASV (and EPSV). Certain FTP servers,
+mainly drftpd, require this non-standard command for directory listings as
+well as up and downloads in PASV mode.
diff --git a/docs/cmdline-opts/ftp-skip-pasv-ip.d b/docs/cmdline-opts/ftp-skip-pasv-ip.d
new file mode 100644
index 00000000..da6ab11f
--- /dev/null
+++ b/docs/cmdline-opts/ftp-skip-pasv-ip.d
@@ -0,0 +1,12 @@
+Long: ftp-skip-pasv-ip
+Help: Skip the IP address for PASV
+Protocols: FTP
+Added: 7.14.2
+See-also: ftp-pasv
+---
+Tell curl to not use the IP address the server suggests in its response
+to curl's PASV command when curl connects the data connection. Instead curl
+will re-use the same IP address it already uses for the control
+connection.
+
+This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
diff --git a/docs/cmdline-opts/ftp-ssl-ccc-mode.d b/docs/cmdline-opts/ftp-ssl-ccc-mode.d
new file mode 100644
index 00000000..be102949
--- /dev/null
+++ b/docs/cmdline-opts/ftp-ssl-ccc-mode.d
@@ -0,0 +1,11 @@
+Long: ftp-ssl-ccc-mode
+Arg: <active/passive>
+Help: Set CCC mode
+Protocols: FTP
+Added: 7.16.2
+See-also: ftp-ssl-ccc
+---
+Sets the CCC mode. The passive mode will not initiate the shutdown, but
+instead wait for the server to do it, and will not reply to the shutdown from
+the server. The active mode initiates the shutdown and waits for a reply from
+the server.
diff --git a/docs/cmdline-opts/ftp-ssl-ccc.d b/docs/cmdline-opts/ftp-ssl-ccc.d
new file mode 100644
index 00000000..c6edc5b3
--- /dev/null
+++ b/docs/cmdline-opts/ftp-ssl-ccc.d
@@ -0,0 +1,10 @@
+Long: ftp-ssl-ccc
+Help: Send CCC after authenticating
+Protocols: FTP
+See-also: ssl ftp-ssl-ccc-mode
+Added: 7.16.1
+---
+Use CCC (Clear Command Channel) Shuts down the SSL/TLS layer after
+authenticating. The rest of the control channel communication will be
+unencrypted. This allows NAT routers to follow the FTP transaction. The
+default mode is passive.
diff --git a/docs/cmdline-opts/ftp-ssl-control.d b/docs/cmdline-opts/ftp-ssl-control.d
new file mode 100644
index 00000000..87a82253
--- /dev/null
+++ b/docs/cmdline-opts/ftp-ssl-control.d
@@ -0,0 +1,8 @@
+Long: ftp-ssl-control
+Help: Require SSL/TLS for FTP login, clear for transfer
+Protocols: FTP
+Added: 7.16.0
+---
+Require SSL/TLS for the FTP login, clear for transfer. Allows secure
+authentication, but non-encrypted data transfers for efficiency. Fails the
+transfer if the server doesn't support SSL/TLS.
diff --git a/docs/cmdline-opts/ftp-ssl-reqd.d b/docs/cmdline-opts/ftp-ssl-reqd.d
new file mode 100644
index 00000000..2f804846
--- /dev/null
+++ b/docs/cmdline-opts/ftp-ssl-reqd.d
@@ -0,0 +1,3 @@
+Long: ftp-ssl-reqd
+Help: Require SSL/TLS
+Redirect: ssl-reqd
diff --git a/docs/cmdline-opts/ftp-ssl.d b/docs/cmdline-opts/ftp-ssl.d
new file mode 100644
index 00000000..aee48a1c
--- /dev/null
+++ b/docs/cmdline-opts/ftp-ssl.d
@@ -0,0 +1,3 @@
+Long: ftp-ssl
+Help: Try SSL/TLS
+Redirect: ssl
diff --git a/docs/cmdline-opts/gen.pl b/docs/cmdline-opts/gen.pl
new file mode 100755
index 00000000..cd9e3cf5
--- /dev/null
+++ b/docs/cmdline-opts/gen.pl
@@ -0,0 +1,374 @@
+#!/usr/bin/perl
+
+my $some_dir=".";
+
+opendir(my $dh, $some_dir) || die "Can't opendir $some_dir: $!";
+my @s = grep { /\.d$/ && -f "$some_dir/$_" } readdir($dh);
+closedir $dh;
+
+my %optshort;
+my %optlong;
+my %helplong;
+my %arglong;
+my %redirlong;
+my %protolong;
+
+# get the long name version, return the man page string
+sub manpageify {
+ my ($k)=@_;
+ my $l;
+ if($optlong{$k} ne "") {
+ # both short + long
+ $l = "\\fI-".$optlong{$k}.", --$k\\fP";
+ }
+ else {
+ # only long
+ $l = "\\fI--$k\\fP";
+ }
+ return $l;
+}
+
+sub printdesc {
+ my @desc = @_;
+ for my $d (@desc) {
+ # skip lines starting with space (examples)
+ if($d =~ /^[^ ]/) {
+ for my $k (keys %optlong) {
+ my $l = manpageify($k);
+ $d =~ s/--$k([^a-z0-9_-])/$l$1/;
+ }
+ }
+ print $d;
+ }
+}
+
+sub seealso {
+ my($standalone, $data)=@_;
+ if($standalone) {
+ return sprintf
+ ".SH \"SEE ALSO\"\n$data\n";
+ }
+ else {
+ return "See also $data. ";
+ }
+}
+
+sub overrides {
+ my ($standalone, $data)=@_;
+ if($standalone) {
+ return ".SH \"OVERRIDES\"\n$data\n";
+ }
+ else {
+ return $data;
+ }
+}
+
+sub protocols {
+ my ($standalone, $data)=@_;
+ if($standalone) {
+ return ".SH \"PROTOCOLS\"\n$data\n";
+ }
+ else {
+ return "($data) ";
+ }
+}
+
+sub added {
+ my ($standalone, $data)=@_;
+ if($standalone) {
+ return ".SH \"ADDED\"\nAdded in curl version $data\n";
+ }
+ else {
+ return "Added in $added. ";
+ }
+}
+
+sub single {
+ my ($f, $standalone)=@_;
+ open(F, "<$f") ||
+ return 1;
+ my $short;
+ my $long;
+ my $tags;
+ my $added;
+ my $protocols;
+ my $arg;
+ my $mutexed;
+ my $requires;
+ my $redirect;
+ my $seealso;
+ my $magic; # cmdline special option
+ while(<F>) {
+ if(/^Short: *(.)/i) {
+ $short=$1;
+ }
+ elsif(/^Long: *(.*)/i) {
+ $long=$1;
+ }
+ elsif(/^Added: *(.*)/i) {
+ $added=$1;
+ }
+ elsif(/^Tags: *(.*)/i) {
+ $tags=$1;
+ }
+ elsif(/^Arg: *(.*)/i) {
+ $arg=$1;
+ }
+ elsif(/^Magic: *(.*)/i) {
+ $magic=$1;
+ }
+ elsif(/^Mutexed: *(.*)/i) {
+ $mutexed=$1;
+ }
+ elsif(/^Protocols: *(.*)/i) {
+ $protocols=$1;
+ }
+ elsif(/^See-also: *(.*)/i) {
+ $seealso=$1;
+ }
+ elsif(/^Requires: *(.*)/i) {
+ $requires=$1;
+ }
+ elsif(/^Redirect: *(.*)/i) {
+ $redirect=$1;
+ }
+ elsif(/^Help: *(.*)/i) {
+ ;
+ }
+ elsif(/^---/) {
+ if(!$long) {
+ print STDERR "WARN: no 'Long:' in $f\n";
+ }
+ last;
+ }
+ else {
+ chomp;
+ print STDERR "WARN: unrecognized line in $f, ignoring:\n:'$_';"
+ }
+ }
+ my @dest;
+ while(<F>) {
+ push @desc, $_;
+ }
+ close(F);
+ my $opt;
+ if(defined($short) && $long) {
+ $opt = "-$short, --$long";
+ }
+ elsif($short && !$long) {
+ $opt = "-$short";
+ }
+ elsif($long && !$short) {
+ $opt = "--$long";
+ }
+
+ if($arg) {
+ $opt .= " $arg";
+ }
+
+ if($standalone) {
+ print ".TH curl 1 \"30 Nov 2016\" \"curl 7.52.0\" \"curl manual\"\n";
+ print ".SH OPTION\n";
+ print "curl $opt\n";
+ }
+ else {
+ print ".IP \"$opt\"\n";
+ }
+ if($redirect) {
+ my $l = manpageify($redirect);
+ print "Use $l instead!\n";
+ }
+ else {
+ if($protocols) {
+ print protocols($standalone, $protocols);
+ }
+ }
+
+ if($standalone) {
+ print ".SH DESCRIPTION\n";
+ }
+
+ printdesc(@desc);
+ undef @desc;
+
+ my @foot;
+ if($seealso) {
+ my @m=split(/ /, $seealso);
+ my $mstr;
+ for my $k (@m) {
+ my $l = manpageify($k);
+ $mstr .= sprintf "%s$l", $mstr?" and ":"";
+ }
+ push @foot, seealso($standalone, $mstr);
+ }
+ if($requires) {
+ my $l = manpageify($long);
+ push @foot, "$l requires that the underlying libcurl".
+ " was built to support $requires. ";
+ }
+ if($mutexed) {
+ my @m=split(/ /, $mutexed);
+ my $mstr;
+ for my $k (@m) {
+ my $l = manpageify($k);
+ $mstr .= sprintf "%s$l", $mstr?" and ":"";
+ }
+ push @foot, overrides($standalone, "This option overrides $mstr. ");
+ }
+ if($added) {
+ push @foot, added($standalone, $added);
+ }
+ if($foot[0]) {
+ print "\n";
+ print @foot;
+ print "\n";
+ }
+ return 0;
+}
+
+sub getshortlong {
+ my ($f)=@_;
+ open(F, "<$f");
+ my $short;
+ my $long;
+ my $help;
+ my $arg;
+ my $protocols;
+ while(<F>) {
+ if(/^Short: (.)/i) {
+ $short=$1;
+ }
+ elsif(/^Long: (.*)/i) {
+ $long=$1;
+ }
+ elsif(/^Help: (.*)/i) {
+ $help=$1;
+ }
+ elsif(/^Arg: (.*)/i) {
+ $arg=$1;
+ }
+ elsif(/^Protocols: (.*)/i) {
+ $protocols=$1;
+ }
+ elsif(/^---/) {
+ last;
+ }
+ }
+ close(F);
+ if($short) {
+ $optshort{$short}=$long;
+ }
+ if($long) {
+ $optlong{$long}=$short;
+ $helplong{$long}=$help;
+ $arglong{$long}=$arg;
+ $protolong{$long}=$protocols;
+ }
+}
+
+sub indexoptions {
+ foreach my $f (@s) {
+ getshortlong($f);
+ }
+}
+
+sub header {
+ my ($f)=@_;
+ open(F, "<$f");
+ my @d;
+ while(<F>) {
+ push @d, $_;
+ }
+ close(F);
+ printdesc(@d);
+}
+
+sub listhelp {
+ foreach my $f (sort keys %helplong) {
+ my $long = $f;
+ my $short = $optlong{$long};
+ my $opt;
+
+ if(defined($short) && $long) {
+ $opt = "-$short, --$long";
+ }
+ elsif($long && !$short) {
+ $opt = " --$long";
+ }
+
+ my $arg = $arglong{$long};
+ if($arg) {
+ $opt .= " $arg";
+ }
+
+ my $line = sprintf " %-19s %s\n", $opt, $helplong{$f};
+
+ if(length($line) > 79) {
+ print STDERR "WARN: the --$long line is too long\n";
+ }
+ print $line;
+ }
+}
+
+sub mainpage {
+ # show the page header
+ header("page-header");
+
+ # output docs for all options
+ foreach my $f (sort @s) {
+ single($f, 0);
+ }
+}
+
+sub showonly {
+ my ($f) = @_;
+ if(single($f, 1)) {
+ print STDERR "$f: failed\n";
+ }
+}
+
+sub showprotocols {
+ my %prots;
+ foreach my $f (keys %optlong) {
+ my @p = split(/ /, $protolong{$f});
+ for my $p (@p) {
+ $prots{$p}++;
+ }
+ }
+ for(sort keys %prots) {
+ printf "$_ (%d options)\n", $prots{$_};
+ }
+}
+
+sub getargs {
+ my $f;
+ do {
+ $f = shift @ARGV;
+ if($f eq "mainpage") {
+ mainpage();
+ return;
+ }
+ elsif($f eq "listhelp") {
+ listhelp();
+ return;
+ }
+ elsif($f eq "single") {
+ showonly(shift @ARGV);
+ return;
+ }
+ elsif($f eq "protos") {
+ showprotocols();
+ return;
+ }
+ } while($f);
+
+ print "Usage: gen.pl <mainpage/listhelp/single FILE/protos>\n";
+}
+
+#------------------------------------------------------------------------
+
+# learn all existing options
+indexoptions();
+
+getargs();
+
diff --git a/docs/cmdline-opts/get.d b/docs/cmdline-opts/get.d
new file mode 100644
index 00000000..be7cb25f
--- /dev/null
+++ b/docs/cmdline-opts/get.d
@@ -0,0 +1,15 @@
+Long: get
+Short: G
+Help: Put the post data in the URL and use GET
+---
+When used, this option will make all data specified with --data, --data-binary
+or --data-urlencode to be used in an HTTP GET request instead of the POST
+request that otherwise would be used. The data will be appended to the URL
+with a '?' separator.
+
+If used in combination with --head, the POST data will instead be appended to
+the URL with a HEAD request.
+
+If this option is used several times, only the first one is used. This is
+because undoing a GET doesn't make sense, but you should then instead enforce
+the alternative method you prefer.
diff --git a/docs/cmdline-opts/globoff.d b/docs/cmdline-opts/globoff.d
new file mode 100644
index 00000000..fff6516b
--- /dev/null
+++ b/docs/cmdline-opts/globoff.d
@@ -0,0 +1,8 @@
+Long: globoff
+Short: g
+Help: Disable URL sequences and ranges using {} and []
+---
+This option switches off the "URL globbing parser". When you set this option,
+you can specify URLs that contain the letters {}[] without having them being
+interpreted by curl itself. Note that these letters are not normal legal URL
+contents but they should be encoded according to the URI standard.
diff --git a/docs/cmdline-opts/head.d b/docs/cmdline-opts/head.d
new file mode 100644
index 00000000..350a100f
--- /dev/null
+++ b/docs/cmdline-opts/head.d
@@ -0,0 +1,8 @@
+Long: head
+Short: I
+Help: Show document info only
+Protocols: HTTP FTP FILE
+---
+Fetch the headers only! HTTP-servers feature the command HEAD which this uses
+to get nothing but the header of a document. When used on an FTP or FILE file,
+curl displays the file size and last modification time only.
diff --git a/docs/cmdline-opts/header.d b/docs/cmdline-opts/header.d
new file mode 100644
index 00000000..762334fe
--- /dev/null
+++ b/docs/cmdline-opts/header.d
@@ -0,0 +1,39 @@
+Long: header
+Short: H
+Arg: <header>
+Help: Pass custom header LINE to server
+Protocols: HTTP
+---
+
+Extra header to include in the request when sending HTTP to a server. You may
+specify any number of extra headers. Note that if you should add a custom
+header that has the same name as one of the internal ones curl would use, your
+externally set header will be used instead of the internal one. This allows
+you to make even trickier stuff than curl would normally do. You should not
+replace internally set headers without knowing perfectly well what you're
+doing. Remove an internal header by giving a replacement without content on
+the right side of the colon, as in: -H \&"Host:". If you send the custom
+header with no-value then its header must be terminated with a semicolon, such
+as \-H \&"X-Custom-Header;" to send "X-Custom-Header:".
+
+curl will make sure that each header you add/replace is sent with the proper
+end-of-line marker, you should thus \fBnot\fP add that as a part of the header
+content: do not add newlines or carriage returns, they will only mess things up
+for you.
+
+See also the --user-agent and --referer options.
+
+Starting in 7.37.0, you need --proxy-header to send custom headers intended
+for a proxy.
+
+Example:
+
+ curl -H "X-First-Name: Joe" http://example.com/
+
+\fBWARNING\fP: headers set with this option will be set in all requests - even
+after redirects are followed, like when told with \fB-L, --location\fP. This
+can lead to the header being sent to other hosts than the original host, so
+sensitive headers should be used with caution combined with following
+redirects.
+
+This option can be used multiple times to add/replace/remove multiple headers.
diff --git a/docs/cmdline-opts/hostpubmd5.d b/docs/cmdline-opts/hostpubmd5.d
new file mode 100644
index 00000000..a8511580
--- /dev/null
+++ b/docs/cmdline-opts/hostpubmd5.d
@@ -0,0 +1,9 @@
+Long: hostpubmd5
+Arg: <md5>
+Help: Acceptable MD5 hash of the host public key
+Protocols: SFTP SCP
+Added: 7.17.1
+---
+Pass a string containing 32 hexadecimal digits. The string should
+be the 128 bit MD5 checksum of the remote host's public key, curl will refuse
+the connection with the host unless the md5sums match.
diff --git a/docs/cmdline-opts/http1.0.d b/docs/cmdline-opts/http1.0.d
new file mode 100644
index 00000000..d9bbd76f
--- /dev/null
+++ b/docs/cmdline-opts/http1.0.d
@@ -0,0 +1,10 @@
+Short: 0
+Long: http1.0
+Tags: Versions
+Protocols: HTTP
+Added:
+Mutexed: http1.1 http2
+Help: Use HTTP 1.0
+---
+Tells curl to use HTTP version 1.0 instead of using its internally preferred
+HTTP version.
diff --git a/docs/cmdline-opts/http1.1.d b/docs/cmdline-opts/http1.1.d
new file mode 100644
index 00000000..f1e6b5c3
--- /dev/null
+++ b/docs/cmdline-opts/http1.1.d
@@ -0,0 +1,8 @@
+Long: http1.1
+Tags: Versions
+Protocols: HTTP
+Added: 7.33.0
+Mutexed: http1.0 http2
+Help: Use HTTP 1.1
+---
+Tells curl to use HTTP version 1.1.
diff --git a/docs/cmdline-opts/http2-prior-knowledge.d b/docs/cmdline-opts/http2-prior-knowledge.d
new file mode 100644
index 00000000..f793f775
--- /dev/null
+++ b/docs/cmdline-opts/http2-prior-knowledge.d
@@ -0,0 +1,12 @@
+Long: http2-prior-knowledge
+Tags: Versions
+Protocols: HTTP
+Added: 7.49.0
+Mutexed: http1.1 http1.0 http2
+Requires: HTTP/2
+Help: Use HTTP 2 without HTTP/1.1 Upgrade
+---
+Tells curl to issue its non-TLS HTTP requests using HTTP/2 without HTTP/1.1
+Upgrade. It requires prior knowledge that the server supports HTTP/2 straight
+away. HTTPS requests will still do HTTP/2 the standard way with negotiated
+protocol version in the TLS handshake.
diff --git a/docs/cmdline-opts/http2.d b/docs/cmdline-opts/http2.d
new file mode 100644
index 00000000..04cff00a
--- /dev/null
+++ b/docs/cmdline-opts/http2.d
@@ -0,0 +1,10 @@
+Long: http2
+Tags: Versions
+Protocols: HTTP
+Added: 7.33.0
+Mutexed: http1.1 http1.0 http2-prior-knowledge
+Requires: HTTP/2
+See-also: no-alpn
+Help: Use HTTP 2
+---
+Tells curl to use HTTP version 2.
diff --git a/docs/cmdline-opts/ignore-content-length.d b/docs/cmdline-opts/ignore-content-length.d
new file mode 100644
index 00000000..53524f51
--- /dev/null
+++ b/docs/cmdline-opts/ignore-content-length.d
@@ -0,0 +1,10 @@
+Long: ignore-content-length
+Help: Ignore the size of the remote resource
+Protocols: FTP HTTP
+---
+For HTTP, Ignore the Content-Length header. This is particularly useful for
+servers running Apache 1.x, which will report incorrect Content-Length for
+files larger than 2 gigabytes.
+
+For FTP (since 7.46.0), skip the RETR command to figure out the size before
+downloading a file.
diff --git a/docs/cmdline-opts/include.d b/docs/cmdline-opts/include.d
new file mode 100644
index 00000000..e55d5163
--- /dev/null
+++ b/docs/cmdline-opts/include.d
@@ -0,0 +1,7 @@
+Long: include
+Short: i
+Help: Include protocol headers in the output
+See-also: verbose
+---
+Include the HTTP-header in the output. The HTTP-header includes things like
+server-name, date of the document, HTTP-version and more...
diff --git a/docs/cmdline-opts/insecure.d b/docs/cmdline-opts/insecure.d
new file mode 100644
index 00000000..1dd0fa8c
--- /dev/null
+++ b/docs/cmdline-opts/insecure.d
@@ -0,0 +1,12 @@
+Long: insecure
+Short: k
+Help: Allow insecure connections when using SSL
+Protocols: TLS
+---
+This option explicitly allows curl to perform "insecure" SSL connections and
+transfers. All SSL connections are attempted to be made secure by using the CA
+certificate bundle installed by default. This makes all connections considered
+\&"insecure" fail unless --insecure is used.
+
+See this online resource for further details:
+ https://curl.haxx.se/docs/sslcerts.html
diff --git a/docs/cmdline-opts/interface.d b/docs/cmdline-opts/interface.d
new file mode 100644
index 00000000..da84cd2b
--- /dev/null
+++ b/docs/cmdline-opts/interface.d
@@ -0,0 +1,12 @@
+Long: interface
+Arg: <name>
+Help: Use network INTERFACE (or address)
+See-also: dns-interface
+---
+
+Perform an operation using a specified interface. You can enter interface
+name, IP address or host name. An example could look like:
+
+ curl --interface eth0:1 https://www.example.com/
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/ipv4.d b/docs/cmdline-opts/ipv4.d
new file mode 100644
index 00000000..9c40c8c3
--- /dev/null
+++ b/docs/cmdline-opts/ipv4.d
@@ -0,0 +1,12 @@
+Short: 4
+Long: ipv4
+Tags: Versions
+Protocols:
+Added:
+Mutexed: ipv6
+Requires:
+See-also: http1.1 http2
+Help: Resolve names to IPv4 addresses
+---
+This option tells curl to resolve names to IPv4 addresses only, and not for
+example try IPv6.
diff --git a/docs/cmdline-opts/ipv6.d b/docs/cmdline-opts/ipv6.d
new file mode 100644
index 00000000..c2392e77
--- /dev/null
+++ b/docs/cmdline-opts/ipv6.d
@@ -0,0 +1,12 @@
+Short: 6
+Long: ipv6
+Tags: Versions
+Protocols:
+Added:
+Mutexed: ipv6
+Requires:
+See-also: http1.1 http2
+Help: Resolve names to IPv6 addresses
+---
+This option tells curl to resolve names to IPv6 addresses only, and not for
+example try IPv4.
diff --git a/docs/cmdline-opts/junk-session-cookies.d b/docs/cmdline-opts/junk-session-cookies.d
new file mode 100644
index 00000000..40ccd9c2
--- /dev/null
+++ b/docs/cmdline-opts/junk-session-cookies.d
@@ -0,0 +1,10 @@
+Long: junk-session-cookies
+Short: j
+Help: Ignore session cookies read from file
+Protocols: HTTP
+See-also: cookie cookie-jar
+---
+When curl is told to read cookies from a given file, this option will make it
+discard all "session cookies". This will basically have the same effect as if
+a new session is started. Typical browsers always discard session cookies when
+they're closed down.
diff --git a/docs/cmdline-opts/keepalive-time.d b/docs/cmdline-opts/keepalive-time.d
new file mode 100644
index 00000000..c816e13f
--- /dev/null
+++ b/docs/cmdline-opts/keepalive-time.d
@@ -0,0 +1,13 @@
+Long: keepalive-time
+Arg: <seconds>
+Help: Interval time for keepalive probes
+Added: 7.18.0
+---
+This option sets the time a connection needs to remain idle before sending
+keepalive probes and the time between individual keepalive probes. It is
+currently effective on operating systems offering the TCP_KEEPIDLE and
+TCP_KEEPINTVL socket options (meaning Linux, recent AIX, HP-UX and more). This
+option has no effect if --no-keepalive is used.
+
+If this option is used several times, the last one will be used. If
+unspecified, the option defaults to 60 seconds.
diff --git a/docs/cmdline-opts/key-type.d b/docs/cmdline-opts/key-type.d
new file mode 100644
index 00000000..bf39bcd3
--- /dev/null
+++ b/docs/cmdline-opts/key-type.d
@@ -0,0 +1,9 @@
+Long: key-type
+Arg: <type>
+Help: Private key file type (DER/PEM/ENG)
+Protocols: TLS
+---
+Private key file type. Specify which type your --key provided private key
+is. DER, PEM, and ENG are supported. If not specified, PEM is assumed.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/key.d b/docs/cmdline-opts/key.d
new file mode 100644
index 00000000..fbf583af
--- /dev/null
+++ b/docs/cmdline-opts/key.d
@@ -0,0 +1,10 @@
+Long: key
+Arg: <key>
+Protocols: TLS SSH
+Help: Private key file name
+---
+Private key file name. Allows you to provide your private key in this separate
+file. For SSH, if not specified, curl tries the following candidates in order:
+'~/.ssh/id_rsa', '~/.ssh/id_dsa', './id_rsa', './id_dsa'.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/krb.d b/docs/cmdline-opts/krb.d
new file mode 100644
index 00000000..19547af0
--- /dev/null
+++ b/docs/cmdline-opts/krb.d
@@ -0,0 +1,11 @@
+Long: krb
+Arg: <level>
+Help: Enable Kerberos with security <level>
+Protocols: FTP
+Requires: Kerberos
+---
+Enable Kerberos authentication and use. The level must be entered and should
+be one of 'clear', 'safe', 'confidential', or 'private'. Should you use a
+level that is not one of these, 'private' will instead be used.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/krb4.d b/docs/cmdline-opts/krb4.d
new file mode 100644
index 00000000..79bab81b
--- /dev/null
+++ b/docs/cmdline-opts/krb4.d
@@ -0,0 +1,2 @@
+Long: krb4
+Redirect: krb
diff --git a/docs/cmdline-opts/libcurl.d b/docs/cmdline-opts/libcurl.d
new file mode 100644
index 00000000..ef132fe7
--- /dev/null
+++ b/docs/cmdline-opts/libcurl.d
@@ -0,0 +1,11 @@
+Long: libcurl
+Arg: <file>
+Help: Dump libcurl equivalent code of this command line
+Added: 7.16.1
+---
+Append this option to any ordinary curl command line, and you will get a
+libcurl-using C source code written to the file that does the equivalent
+of what your command-line operation does!
+
+If this option is used several times, the last given file name will be
+used.
diff --git a/docs/cmdline-opts/limit-rate.d b/docs/cmdline-opts/limit-rate.d
new file mode 100644
index 00000000..8784a84d
--- /dev/null
+++ b/docs/cmdline-opts/limit-rate.d
@@ -0,0 +1,18 @@
+Long: limit-rate
+Arg: <speed>
+Help: Limit transfer speed to RATE
+---
+Specify the maximum transfer rate you want curl to use - for both downloads
+and uploads. This feature is useful if you have a limited pipe and you'd like
+your transfer not to use your entire bandwidth. To make it slower than it
+otherwise would be.
+
+The given speed is measured in bytes/second, unless a suffix is appended.
+Appending 'k' or 'K' will count the number as kilobytes, 'm' or M' makes it
+megabytes, while 'g' or 'G' makes it gigabytes. Examples: 200K, 3m and 1G.
+
+If you also use the --speed-limit option, that option will take precedence and
+might cripple the rate-limiting slightly, to help keeping the speed-limit
+logic working.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/list-only.d b/docs/cmdline-opts/list-only.d
new file mode 100644
index 00000000..4c56304a
--- /dev/null
+++ b/docs/cmdline-opts/list-only.d
@@ -0,0 +1,24 @@
+Long: list-only
+Short: l
+Protocols: FTP POP3
+Help: List only mode
+Added: 7.21.5
+---
+(FTP)
+When listing an FTP directory, this switch forces a name-only view. This is
+especially useful if the user wants to machine-parse the contents of an FTP
+directory since the normal directory view doesn't use a standard look or
+format. When used like this, the option causes a NLST command to be sent to
+the server instead of LIST.
+
+Note: Some FTP servers list only files in their response to NLST; they do not
+include sub-directories and symbolic links.
+
+(POP3)
+When retrieving a specific email from POP3, this switch forces a LIST command
+to be performed instead of RETR. This is particularly useful if the user wants
+to see if a specific message id exists on the server and what size it is.
+
+Note: When combined with --request, this option can be used to send an UIDL
+command instead, so the user may use the email's unique identifier rather than
+it's message id to make the request.
diff --git a/docs/cmdline-opts/local-port.d b/docs/cmdline-opts/local-port.d
new file mode 100644
index 00000000..d96b46eb
--- /dev/null
+++ b/docs/cmdline-opts/local-port.d
@@ -0,0 +1,9 @@
+Long: local-port
+Arg: <num/range>
+Help: Force use of RANGE for local port numbers
+Added: 7.15.2
+---
+Set a preferred single number or range (FROM-TO) of local port numbers to use
+for the connection(s). Note that port numbers by nature are a scarce resource
+that will be busy at times so setting this range to something too narrow might
+cause unnecessary connection setup failures.
diff --git a/docs/cmdline-opts/location-trusted.d b/docs/cmdline-opts/location-trusted.d
new file mode 100644
index 00000000..995a8718
--- /dev/null
+++ b/docs/cmdline-opts/location-trusted.d
@@ -0,0 +1,9 @@
+Long: location-trusted
+Help: Like --location, and send auth to other hosts
+Protocols: HTTP
+See-also: user
+---
+Like --location, but will allow sending the name + password to all hosts that
+the site may redirect to. This may or may not introduce a security breach if
+the site redirects you to a site to which you'll send your authentication info
+(which is plaintext in the case of HTTP Basic authentication).
diff --git a/docs/cmdline-opts/location.d b/docs/cmdline-opts/location.d
new file mode 100644
index 00000000..7c70e698
--- /dev/null
+++ b/docs/cmdline-opts/location.d
@@ -0,0 +1,23 @@
+Long: location
+Short: L
+Help: Follow redirects
+Protocols: HTTP
+---
+If the server reports that the requested page has moved to a different
+location (indicated with a Location: header and a 3XX response code), this
+option will make curl redo the request on the new place. If used together with
+--include or --head, headers from all requested pages will be shown. When
+authentication is used, curl only sends its credentials to the initial
+host. If a redirect takes curl to a different host, it won't be able to
+intercept the user+password. See also --location-trusted on how to change
+this. You can limit the amount of redirects to follow by using the
+--max-redirs option.
+
+When curl follows a redirect and the request is not a plain GET (for example
+POST or PUT), it will do the following request with a GET if the HTTP response
+was 301, 302, or 303. If the response code was any other 3xx code, curl will
+re-send the following request using the same unmodified method.
+
+You can tell curl to not change the non-GET request method to GET after a 30x
+response by using the dedicated options for that: --post301, --post302 and
+--post303.
diff --git a/docs/cmdline-opts/login-options.d b/docs/cmdline-opts/login-options.d
new file mode 100644
index 00000000..ea2af082
--- /dev/null
+++ b/docs/cmdline-opts/login-options.d
@@ -0,0 +1,13 @@
+Long: login-options
+Arg: <options>
+Protocols: IMAP POP3 SMTP
+Added: 7.34.0
+---
+Specify the login options to use during server authentication.
+
+You can use the login options to specify protocol specific options that may
+be used during authentication. At present only IMAP, POP3 and SMTP support
+login options. For more information about the login options please see
+RFC 2384, RFC 5092 and IETF draft draft-earhart-url-smtp-00.txt
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/mail-auth.d b/docs/cmdline-opts/mail-auth.d
new file mode 100644
index 00000000..70cf0eda
--- /dev/null
+++ b/docs/cmdline-opts/mail-auth.d
@@ -0,0 +1,10 @@
+Long: mail-auth
+Arg: <address>
+Protocols: SMTP
+Help: Originator address of the original email
+Added: 7.25.0
+See-also: mail-rcpt mail-from
+---
+Specify a single address. This will be used to specify the authentication
+address (identity) of a submitted message that is being relayed to another
+server.
diff --git a/docs/cmdline-opts/mail-from.d b/docs/cmdline-opts/mail-from.d
new file mode 100644
index 00000000..1d932344
--- /dev/null
+++ b/docs/cmdline-opts/mail-from.d
@@ -0,0 +1,8 @@
+Long: mail-from
+Arg: <address>
+Help: Mail from this address
+Protocols: SMTP
+Added: 7.20.0
+See-also: mail-rcpt mail-auth
+---
+Specify a single address that the given mail should get sent from.
diff --git a/docs/cmdline-opts/mail-rcpt.d b/docs/cmdline-opts/mail-rcpt.d
new file mode 100644
index 00000000..d747ceab
--- /dev/null
+++ b/docs/cmdline-opts/mail-rcpt.d
@@ -0,0 +1,19 @@
+Long: mail-rcpt
+Arg: <address>
+Help: Mail from this address
+Protocols: SMTP
+Added: 7.20.0
+---
+Specify a single address, user name or mailing list name. Repeat this
+option several times to send to multiple recipients.
+
+When performing a mail transfer, the recipient should specify a valid email
+address to send the mail to.
+
+When performing an address verification (VRFY command), the recipient should be
+specified as the user name or user name and domain (as per Section 3.5 of
+RFC5321). (Added in 7.34.0)
+
+When performing a mailing list expand (EXPN command), the recipient should be
+specified using the mailing list name, such as "Friends" or "London-Office".
+(Added in 7.34.0)
diff --git a/docs/cmdline-opts/max-filesize.d b/docs/cmdline-opts/max-filesize.d
new file mode 100644
index 00000000..e92ef583
--- /dev/null
+++ b/docs/cmdline-opts/max-filesize.d
@@ -0,0 +1,12 @@
+Long: max-filesize
+Arg: <bytes>
+Help: Maximum file size to download
+See-also: limit-rate
+---
+Specify the maximum size (in bytes) of a file to download. If the file
+requested is larger than this value, the transfer will not start and curl will
+return with exit code 63.
+
+\fBNOTE:\fP The file size is not always known prior to download, and for such
+files this option has no effect even if the file transfer ends up being larger
+than this given limit. This concerns both FTP and HTTP transfers.
diff --git a/docs/cmdline-opts/max-redirs.d b/docs/cmdline-opts/max-redirs.d
new file mode 100644
index 00000000..04b824bd
--- /dev/null
+++ b/docs/cmdline-opts/max-redirs.d
@@ -0,0 +1,11 @@
+Long: max-redirs
+Arg: <num>
+Help: Maximum number of redirects allowed
+Protocols: HTTP
+---
+Set maximum number of redirection-followings allowed. When --location is used,
+is used to prevent curl from following redirections \&"in absurdum". By
+default, the limit is set to 50 redirections. Set this option to -1 to make it
+unlimited.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/max-time.d b/docs/cmdline-opts/max-time.d
new file mode 100644
index 00000000..c22343d3
--- /dev/null
+++ b/docs/cmdline-opts/max-time.d
@@ -0,0 +1,13 @@
+Long: max-time
+Short: m
+Arg: <time>
+Help: Maximum time allowed for the transfer
+See-also: connect-timeout
+---
+Maximum time in seconds that you allow the whole operation to take. This is
+useful for preventing your batch jobs from hanging for hours due to slow
+networks or links going down. Since 7.32.0, this option accepts decimal
+values, but the actual timeout will decrease in accuracy as the specified
+timeout increases in decimal precision.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/metalink.d b/docs/cmdline-opts/metalink.d
new file mode 100644
index 00000000..8047e9f5
--- /dev/null
+++ b/docs/cmdline-opts/metalink.d
@@ -0,0 +1,27 @@
+Long: metalink
+Help: Process given URLs as metalink XML file
+Added: 7.27.0
+Requires: metalink
+---
+This option can tell curl to parse and process a given URI as Metalink file
+(both version 3 and 4 (RFC 5854) are supported) and make use of the mirrors
+listed within for failover if there are errors (such as the file or server not
+being available). It will also verify the hash of the file after the download
+completes. The Metalink file itself is downloaded and processed in memory and
+not stored in the local file system.
+
+Example to use a remote Metalink file:
+
+ curl --metalink http://www.example.com/example.metalink
+
+To use a Metalink file in the local file system, use FILE protocol (file://):
+
+ curl --metalink file://example.metalink
+
+Please note that if FILE protocol is disabled, there is no way to use a local
+Metalink file at the time of this writing. Also note that if --metalink and
+--include are used together, --include will be ignored. This is because
+including headers in the response will break Metalink parser and if the
+headers are included in the file described in Metalink file, hash check will
+fail.
+
diff --git a/docs/cmdline-opts/negotiate.d b/docs/cmdline-opts/negotiate.d
new file mode 100644
index 00000000..69a6b917
--- /dev/null
+++ b/docs/cmdline-opts/negotiate.d
@@ -0,0 +1,15 @@
+Long: negotiate
+Help: Use HTTP Negotiate (SPNEGO) authentication
+Protocols: HTTP
+See-also: basic ntlm anyauth proxy-negotiate
+---
+Enables Negotiate (SPNEGO) authentication.
+
+This option requires a library built with GSS-API or SSPI support. Use
+--version to see if your curl supports GSS-API/SSPI or SPNEGO.
+
+When using this option, you must also provide a fake --user option to activate
+the authentication code properly. Sending a '-u :' is enough as the user name
+and password from the --user option aren't actually used.
+
+If this option is used several times, only the first one is used.
diff --git a/docs/cmdline-opts/netrc-file.d b/docs/cmdline-opts/netrc-file.d
new file mode 100644
index 00000000..4118b4db
--- /dev/null
+++ b/docs/cmdline-opts/netrc-file.d
@@ -0,0 +1,12 @@
+Long: netrc-file
+Help: Specify FILE for netrc
+Arg: <filemame>
+Added: 7.21.5
+Mutexed: netrc
+---
+This option is similar to --netrc, except that you provide the path (absolute
+or relative) to the netrc file that Curl should use. You can only specify one
+netrc file per invocation. If several --netrc-file options are provided,
+the last one will be used.
+
+It will abide by --netrc-optional if specified.
diff --git a/docs/cmdline-opts/netrc-optional.d b/docs/cmdline-opts/netrc-optional.d
new file mode 100644
index 00000000..c2854030
--- /dev/null
+++ b/docs/cmdline-opts/netrc-optional.d
@@ -0,0 +1,7 @@
+Long: netrc-optional
+Help: Use either .netrc or URL
+Mutexed: netrc
+See-also: netrc-file
+---
+Very similar to --netrc, but this option makes the .netrc usage \fBoptional\fP
+and not mandatory as the --netrc option does.
diff --git a/docs/cmdline-opts/netrc.d b/docs/cmdline-opts/netrc.d
new file mode 100644
index 00000000..2df26782
--- /dev/null
+++ b/docs/cmdline-opts/netrc.d
@@ -0,0 +1,17 @@
+Long: netrc
+Short: n
+Help: Must read .netrc for user name and password
+---
+Makes curl scan the \fI.netrc\fP (\fI_netrc\fP on Windows) file in the user's
+home directory for login name and password. This is typically used for FTP on
+Unix. If used with HTTP, curl will enable user authentication. See
+\fInetrc(5)\fP \fIftp(1)\fP for details on the file format. Curl will not
+complain if that file doesn't have the right permissions (it should not be
+either world- or group-readable). The environment variable "HOME" is used to
+find the home directory.
+
+A quick and very simple example of how to setup a \fI.netrc\fP to allow curl
+to FTP to the machine host.domain.com with user name \&'myself' and password
+\&'secret' should look similar to:
+
+.B "machine host.domain.com login myself password secret"
diff --git a/docs/cmdline-opts/next.d b/docs/cmdline-opts/next.d
new file mode 100644
index 00000000..f368c1b7
--- /dev/null
+++ b/docs/cmdline-opts/next.d
@@ -0,0 +1,20 @@
+Short: :
+Long: next
+Tags:
+Protocols:
+Added: 7.36.0
+Magic: divider
+Help: Make next URL use its separate set of options
+---
+Tells curl to use a separate operation for the following URL and associated
+options. This allows you to send several URL requests, each with their own
+specific options, for example, such as different user names or custom requests
+for each.
+
+--next will reset all local options and only global ones will have their
+values survive over to the operation following the --next instruction. Global
+options include --verbose and --fail-early.
+
+For example, you can do both a GET and a POST in a single command line:
+
+ curl www1.example.com --next -d postthis www2.example.com
diff --git a/docs/cmdline-opts/no-alpn.d b/docs/cmdline-opts/no-alpn.d
new file mode 100644
index 00000000..88abb836
--- /dev/null
+++ b/docs/cmdline-opts/no-alpn.d
@@ -0,0 +1,11 @@
+Long: no-alpn
+Tags: HTTP/2
+Protocols: HTTPS
+Added: 7.36.0
+See-also: no-npn http2
+Requires: TLS
+Help: Disable the ALPN TLS extension
+---
+Disable the ALPN TLS extension. ALPN is enabled by default if libcurl was built
+with an SSL library that supports ALPN. ALPN is used by a libcurl that supports
+HTTP/2 to negotiate HTTP/2 support with the server during https sessions.
diff --git a/docs/cmdline-opts/no-buffer.d b/docs/cmdline-opts/no-buffer.d
new file mode 100644
index 00000000..65a6282f
--- /dev/null
+++ b/docs/cmdline-opts/no-buffer.d
@@ -0,0 +1,11 @@
+Long: no-buffer
+Short: N
+Help: Disable buffering of the output stream
+---
+Disables the buffering of the output stream. In normal work situations, curl
+will use a standard buffered output stream that will have the effect that it
+will output the data in chunks, not necessarily exactly when the data arrives.
+Using this option will disable that buffering.
+
+Note that this is the negated option name documented. You can thus use
+--buffer to enforce the buffering.
diff --git a/docs/cmdline-opts/no-keepalive.d b/docs/cmdline-opts/no-keepalive.d
new file mode 100644
index 00000000..7eb3d639
--- /dev/null
+++ b/docs/cmdline-opts/no-keepalive.d
@@ -0,0 +1,8 @@
+Long: no-keepalive
+Help: Disable TCP keepalive on the connection
+---
+Disables the use of keepalive messages on the TCP connection. curl otherwis
+enables them by default.
+
+Note that this is the negated option name documented. You can thus use
+--keepalive to enforce keepalive.
diff --git a/docs/cmdline-opts/no-npn.d b/docs/cmdline-opts/no-npn.d
new file mode 100644
index 00000000..ab0f6de2
--- /dev/null
+++ b/docs/cmdline-opts/no-npn.d
@@ -0,0 +1,12 @@
+Long: no-npn
+Tags: Versions HTTP/2
+Protocols: HTTPS
+Added: 7.36.0
+Mutexed:
+See-also: no-alpn http2
+Requires: TLS
+Help: Disable the NPN TLS extension
+---
+Disable the NPN TLS extension. NPN is enabled by default if libcurl was built
+with an SSL library that supports NPN. NPN is used by a libcurl that supports
+HTTP/2 to negotiate HTTP/2 support with the server during https sessions.
diff --git a/docs/cmdline-opts/no-sessionid.d b/docs/cmdline-opts/no-sessionid.d
new file mode 100644
index 00000000..397a1586
--- /dev/null
+++ b/docs/cmdline-opts/no-sessionid.d
@@ -0,0 +1,13 @@
+Long: no-sessionid
+Help: Disable SSL session-ID reusing
+Protocols: TLS
+Added: 7.16.0
+---
+Disable curl's use of SSL session-ID caching. By default all transfers are
+done using the cache. Note that while nothing should ever get hurt by
+attempting to reuse SSL session-IDs, there seem to be broken SSL
+implementations in the wild that may require you to disable this in order for
+you to succeed.
+
+Note that this is the negated option name documented. You can thus use
+--sessionid to enforce session-ID caching.
diff --git a/docs/cmdline-opts/noproxy.d b/docs/cmdline-opts/noproxy.d
new file mode 100644
index 00000000..4f06d9f5
--- /dev/null
+++ b/docs/cmdline-opts/noproxy.d
@@ -0,0 +1,11 @@
+Long: noproxy
+Arg: <no-proxy-list>
+Help: List of hosts which do not use proxy
+Added: 7.19.4
+---
+Comma-separated list of hosts which do not use a proxy, if one is specified.
+The only wildcard is a single * character, which matches all hosts, and
+effectively disables the proxy. Each name in this list is matched as either
+a domain which contains the hostname, or the hostname itself. For example,
+local.com would match local.com, local.com:80, and www.local.com, but not
+www.notlocal.com.
diff --git a/docs/cmdline-opts/ntlm-wb.d b/docs/cmdline-opts/ntlm-wb.d
new file mode 100644
index 00000000..7b933840
--- /dev/null
+++ b/docs/cmdline-opts/ntlm-wb.d
@@ -0,0 +1,7 @@
+Long: ntlm-wb
+Help: Use HTTP NTLM authentication with winbind
+Protocols: HTTP
+See-also: ntlm proxy-ntlm
+---
+Enables NTLM much in the style --ntlm does, but hand over the authentication
+to the separate binary ntlmauth application that is executed when needed.
diff --git a/docs/cmdline-opts/ntlm.d b/docs/cmdline-opts/ntlm.d
new file mode 100644
index 00000000..d71cd43f
--- /dev/null
+++ b/docs/cmdline-opts/ntlm.d
@@ -0,0 +1,18 @@
+Long: ntlm
+Help: Use HTTP NTLM authentication
+Mutexed: basic negotiated digest anyauth
+See-also: proxy-ntlm
+Protocols: HTTP
+Requires: TLS
+---
+Enables NTLM authentication. The NTLM authentication method was designed by
+Microsoft and is used by IIS web servers. It is a proprietary protocol,
+reverse-engineered by clever people and implemented in curl based on their
+efforts. This kind of behavior should not be endorsed, you should encourage
+everyone who uses NTLM to switch to a public and documented authentication
+method instead, such as Digest.
+
+If you want to enable NTLM for your proxy authentication, then use
+--proxy-ntlm.
+
+If this option is used several times, only the first one is used.
diff --git a/docs/cmdline-opts/oauth2-bearer.d b/docs/cmdline-opts/oauth2-bearer.d
new file mode 100644
index 00000000..adad532c
--- /dev/null
+++ b/docs/cmdline-opts/oauth2-bearer.d
@@ -0,0 +1,11 @@
+Long: oauth2-bearer
+Help: OAuth 2 Bearer Token
+Protocols: IMAP POP3 SMTP
+---
+Specify the Bearer Token for OAUTH 2.0 server authentication. The Bearer Token
+is used in conjunction with the user name which can be specified as part of
+the --url or --user options.
+
+The Bearer Token and user name are formatted according to RFC 6750.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/output.d b/docs/cmdline-opts/output.d
new file mode 100644
index 00000000..35f52a21
--- /dev/null
+++ b/docs/cmdline-opts/output.d
@@ -0,0 +1,32 @@
+Long: output
+Arg: <file>
+Short: o
+Help: Write to file instead of stdout
+See-also: remote-name remote-name-all remote-header-name
+---
+Write output to <file> instead of stdout. If you are using {} or [] to fetch
+multiple documents, you can use '#' followed by a number in the <file>
+specifier. That variable will be replaced with the current string for the URL
+being fetched. Like in:
+
+ curl http://{one,two}.example.com -o "file_#1.txt"
+
+or use several variables like:
+
+ curl http://{site,host}.host[1-5].com -o "#1_#2"
+
+You may use this option as many times as the number of URLs you have. For
+example, if you specify two URLs on the same command line, you can use it like
+this:
+
+ curl -o aa example.com -o bb example.net
+
+and the order of the -o options and the URLs doesn't matter, just that the
+first -o is for the first URL and so on, so the above command line can also be
+written as
+
+ curl example.com example.net -o aa -o bb
+
+See also the --create-dirs option to create the local directories
+dynamically. Specifying the output as '-' (a single dash) will force the
+output to be done to stdout.
diff --git a/docs/cmdline-opts/page-header b/docs/cmdline-opts/page-header
new file mode 100644
index 00000000..4ba90f97
--- /dev/null
+++ b/docs/cmdline-opts/page-header
@@ -0,0 +1,138 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH curl 1 "30 Nov 2014" "Curl 7.40.0" "Curl Manual"
+.SH NAME
+curl \- transfer a URL
+.SH SYNOPSIS
+.B curl [options]
+.I [URL...]
+.SH DESCRIPTION
+.B curl
+is a tool to transfer data from or to a server, using one of the supported
+protocols (DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP,
+LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET
+and TFTP). The command is designed to work without user interaction.
+
+curl offers a busload of useful tricks like proxy support, user
+authentication, FTP upload, HTTP post, SSL connections, cookies, file transfer
+resume, Metalink, and more. As you will see below, the number of features will
+make your head spin!
+
+curl is powered by libcurl for all transfer-related features. See
+\fIlibcurl(3)\fP for details.
+.SH URL
+The URL syntax is protocol-dependent. You'll find a detailed description in
+RFC 3986.
+
+You can specify multiple URLs or parts of URLs by writing part sets within
+braces as in:
+
+ http://site.{one,two,three}.com
+
+or you can get sequences of alphanumeric series by using [] as in:
+
+ ftp://ftp.example.com/file[1-100].txt
+
+ ftp://ftp.example.com/file[001-100].txt (with leading zeros)
+
+ ftp://ftp.example.com/file[a-z].txt
+
+Nested sequences are not supported, but you can use several ones next to each
+other:
+
+ http://example.com/archive[1996-1999]/vol[1-4]/part{a,b,c}.html
+
+You can specify any amount of URLs on the command line. They will be fetched
+in a sequential manner in the specified order.
+
+You can specify a step counter for the ranges to get every Nth number or
+letter:
+
+ http://example.com/file[1-100:10].txt
+
+ http://example.com/file[a-z:2].txt
+
+When using [] or {} sequences when invoked from a command line prompt, you
+probably have to put the full URL within double quotes to avoid the shell from
+interfering with it. This also goes for other characters treated special, like
+for example '&', '?' and '*'.
+
+Provide the IPv6 zone index in the URL with an escaped percentage sign and the
+interface name. Like in
+
+ http://[fe80::3%25eth0]/
+
+If you specify URL without protocol:// prefix, curl will attempt to guess what
+protocol you might want. It will then default to HTTP but try other protocols
+based on often-used host name prefixes. For example, for host names starting
+with "ftp." curl will assume you want to speak FTP.
+
+curl will do its best to use what you pass to it as a URL. It is not trying to
+validate it as a syntactically correct URL by any means but is instead
+\fBvery\fP liberal with what it accepts.
+
+curl will attempt to re-use connections for multiple file transfers, so that
+getting many files from the same server will not do multiple connects /
+handshakes. This improves speed. Of course this is only done on files
+specified on a single command line and cannot be used between separate curl
+invokes.
+.SH "PROGRESS METER"
+curl normally displays a progress meter during operations, indicating the
+amount of transferred data, transfer speeds and estimated time left, etc. The
+progress meter displays number of bytes and the speeds are in bytes per
+second. The suffixes (k, M, G, T, P) are 1024 based. For example 1k is 1024
+bytes. 1M is 1048576 bytes.
+
+curl displays this data to the terminal by default, so if you invoke curl to
+do an operation and it is about to write data to the terminal, it
+\fIdisables\fP the progress meter as otherwise it would mess up the output
+mixing progress meter and response data.
+
+If you want a progress meter for HTTP POST or PUT requests, you need to
+redirect the response output to a file, using shell redirect (>), -o [file] or
+similar.
+
+It is not the same case for FTP upload as that operation does not spit out
+any response data to the terminal.
+
+If you prefer a progress "bar" instead of the regular meter, --progress-bar is
+your friend.
+.SH OPTIONS
+Options start with one or two dashes. Many of the options require an
+additional value next to them.
+
+The short "single-dash" form of the options, -d for example, may be used with
+or without a space between it and its value, although a space is a recommended
+separator. The long "double-dash" form, --data for example, requires a space
+between it and its value.
+
+Short version options that don't need any additional values can be used
+immediately next to each other, like for example you can specify all the
+options -O, -L and -v at once as -OLv.
+
+In general, all boolean options are enabled with --\fBoption\fP and yet again
+disabled with --\fBno-\fPoption. That is, you use the exact same option name
+but prefix it with "no-". However, in this list we mostly only list and show
+the --option version of them. (This concept with --no options was added in
+7.19.0. Previously most options were toggled on/off on repeated use of the
+same command line option.)
diff --git a/docs/cmdline-opts/pass.d b/docs/cmdline-opts/pass.d
new file mode 100644
index 00000000..2639cb9d
--- /dev/null
+++ b/docs/cmdline-opts/pass.d
@@ -0,0 +1,8 @@
+Long: pass
+Arg: <phrase>
+Help: Pass phrase for the private key
+Protocols: SSH TLS
+---
+Passphrase for the private key
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/path-as-is.d b/docs/cmdline-opts/path-as-is.d
new file mode 100644
index 00000000..946e2f07
--- /dev/null
+++ b/docs/cmdline-opts/path-as-is.d
@@ -0,0 +1,7 @@
+Long: path-as-is
+Help: Do not squash .. sequences in URL path
+Added: 7.42.0
+---
+Tell curl to not handle sequences of /../ or /./ in the given URL
+path. Normally curl will squash or merge them according to standards but with
+this option set you tell it not to do that.
diff --git a/docs/cmdline-opts/pinnedpubkey.d b/docs/cmdline-opts/pinnedpubkey.d
new file mode 100644
index 00000000..0657e6e7
--- /dev/null
+++ b/docs/cmdline-opts/pinnedpubkey.d
@@ -0,0 +1,27 @@
+Long: pinnedpubkey
+Arg: <hashes>
+Help: FILE/HASHES Public key to verify peer against
+Protocols: TLS
+---
+Tells curl to use the specified public key file (or hashes) to verify the
+peer. This can be a path to a file which contains a single public key in PEM
+or DER format, or any number of base64 encoded sha256 hashes preceded by
+\'sha256//\' and separated by \';\'
+
+When negotiating a TLS or SSL connection, the server sends a certificate
+indicating its identity. A public key is extracted from this certificate and
+if it does not exactly match the public key provided to this option, curl will
+abort the connection before sending or receiving any data.
+
+PEM/DER support:
+ 7.39.0: OpenSSL, GnuTLS and GSKit
+ 7.43.0: NSS and wolfSSL/CyaSSL
+ 7.47.0: mbedtls
+ 7.49.0: PolarSSL
+sha256 support:
+ 7.44.0: OpenSSL, GnuTLS, NSS and wolfSSL/CyaSSL.
+ 7.47.0: mbedtls
+ 7.49.0: PolarSSL
+Other SSL backends not supported.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/post301.d b/docs/cmdline-opts/post301.d
new file mode 100644
index 00000000..edcaf875
--- /dev/null
+++ b/docs/cmdline-opts/post301.d
@@ -0,0 +1,11 @@
+Long: post301
+Help: Do not switch to GET after following a 301
+Protocols: HTTP
+See-also: post302 post303 location
+Added: 7.17.1
+---
+Tells curl to respect RFC 7230/6.4.2 and not convert POST requests into GET
+requests when following a 301 redirection. The non-RFC behaviour is ubiquitous
+in web browsers, so curl does the conversion by default to maintain
+consistency. However, a server may require a POST to remain a POST after such
+a redirection. This option is meaningful only when using --location.
diff --git a/docs/cmdline-opts/post302.d b/docs/cmdline-opts/post302.d
new file mode 100644
index 00000000..6ea5f09b
--- /dev/null
+++ b/docs/cmdline-opts/post302.d
@@ -0,0 +1,11 @@
+Long: post302
+Help: Do not switch to GET after following a 302
+Protocols: HTTP
+See-also: post301 post303 location
+Added: 7.19.1
+---
+Tells curl to respect RFC 7230/6.4.2 and not convert POST requests into GET
+requests when following a 302 redirection. The non-RFC behaviour is ubiquitous
+in web browsers, so curl does the conversion by default to maintain
+consistency. However, a server may require a POST to remain a POST after such
+a redirection. This option is meaningful only when using --location.
diff --git a/docs/cmdline-opts/post303.d b/docs/cmdline-opts/post303.d
new file mode 100644
index 00000000..8b36c821
--- /dev/null
+++ b/docs/cmdline-opts/post303.d
@@ -0,0 +1,11 @@
+Long: post303
+Help: Do not switch to GET after following a 303
+Protocols: HTTP
+See-also: post302 post301 location
+Added: 7.26.0
+---
+Tells curl to respect RFC 7230/6.4.2 and not convert POST requests into GET
+requests when following a 303 redirection. The non-RFC behaviour is ubiquitous
+in web browsers, so curl does the conversion by default to maintain
+consistency. However, a server may require a POST to remain a POST after such
+a redirection. This option is meaningful only when using --location.
diff --git a/docs/cmdline-opts/progress-bar.d b/docs/cmdline-opts/progress-bar.d
new file mode 100644
index 00000000..360690c1
--- /dev/null
+++ b/docs/cmdline-opts/progress-bar.d
@@ -0,0 +1,11 @@
+Short: #
+Long: progress-bar
+Help: Disable the ALPN TLS extension
+---
+Make curl display transfer progress as a simple progress bar instead of the
+standard, more informational, meter.
+
+This progress bar draws a single line of '#' characters across the screen and
+shows a percentage if the transfer size is known. For transfers without a
+known size, it will instead output one '#' character for every 1024 bytes
+transferred.
diff --git a/docs/cmdline-opts/proto-default.d b/docs/cmdline-opts/proto-default.d
new file mode 100644
index 00000000..ccc3b85f
--- /dev/null
+++ b/docs/cmdline-opts/proto-default.d
@@ -0,0 +1,18 @@
+Long: proto-default
+Help: Use PROTOCOL for any URL missing a scheme
+Arg: <protocol>
+Added: 7.45.0
+---
+Tells curl to use \fIprotocol\fP for any URL missing a scheme name.
+
+Example:
+
+ curl --proto-default https ftp.mozilla.org
+
+An unknown or unsupported protocol causes error
+\fICURLE_UNSUPPORTED_PROTOCOL\fP (1).
+
+This option does not change the default proxy protocol (http).
+
+Without this option curl would make a guess based on the host, see --url for
+details.
diff --git a/docs/cmdline-opts/proto-redir.d b/docs/cmdline-opts/proto-redir.d
new file mode 100644
index 00000000..c9eeeab1
--- /dev/null
+++ b/docs/cmdline-opts/proto-redir.d
@@ -0,0 +1,17 @@
+Long: proto-redir
+Arg: <protocols>
+Help: Enable/disable PROTOCOLS on redirect
+Added: 7.20.2
+---
+Tells curl to limit what protocols it may use on redirect. Protocols denied by
+--proto are not overridden by this option. See --proto for how protocols are
+represented.
+
+Example, allow only HTTP and HTTPS on redirect:
+
+ curl --proto-redir -all,http,https http://example.com
+
+By default curl will allow all protocols on redirect except several disabled
+for security reasons: Since 7.19.4 FILE and SCP are disabled, and since 7.40.0
+SMB and SMBS are also disabled. Specifying \fIall\fP or \fI+all\fP enables all
+protocols on redirect, including those disabled for security.
diff --git a/docs/cmdline-opts/proto.d b/docs/cmdline-opts/proto.d
new file mode 100644
index 00000000..1513fdc0
--- /dev/null
+++ b/docs/cmdline-opts/proto.d
@@ -0,0 +1,43 @@
+Long: proto
+Arg: <protocols>
+Help: Enable/disable PROTOCOLS
+See-also: proto-redir proto-default
+Added: 7.20.2
+---
+Tells curl to limit what protocols it may use in the transfer. Protocols are
+evaluated left to right, are comma separated, and are each a protocol name or
+'all', optionally prefixed by zero or more modifiers. Available modifiers are:
+.RS
+.TP 3
+.B +
+Permit this protocol in addition to protocols already permitted (this is
+the default if no modifier is used).
+.TP
+.B -
+Deny this protocol, removing it from the list of protocols already permitted.
+.TP
+.B =
+Permit only this protocol (ignoring the list already permitted), though
+subject to later modification by subsequent entries in the comma separated
+list.
+.RE
+.IP
+For example:
+.RS
+.TP 15
+.B --proto -ftps
+uses the default protocols, but disables ftps
+.TP
+.B --proto -all,https,+http
+only enables http and https
+.TP
+.B --proto =http,https
+also only enables http and https
+.RE
+
+Unknown protocols produce a warning. This allows scripts to safely rely on
+being able to disable potentially dangerous protocols, without relying upon
+support for that protocol being built into curl to avoid an error.
+
+This option can be used multiple times, in which case the effect is the same
+as concatenating the protocols into one instance of the option.
diff --git a/docs/cmdline-opts/proxy-header.d b/docs/cmdline-opts/proxy-header.d
new file mode 100644
index 00000000..1ef696bc
--- /dev/null
+++ b/docs/cmdline-opts/proxy-header.d
@@ -0,0 +1,20 @@
+Long: proxy-header
+Arg: <header>
+Help: Pass custom header LINE to proxy
+Protocols: HTTP
+Added: 7.37.0
+---
+Extra header to include in the request when sending HTTP to a proxy. You may
+specify any number of extra headers. This is the equivalent option to --header
+but is for proxy communication only like in CONNECT requests when you want a
+separate header sent to the proxy to what is sent to the actual remote host.
+
+curl will make sure that each header you add/replace is sent with the proper
+end-of-line marker, you should thus \fBnot\fP add that as a part of the header
+content: do not add newlines or carriage returns, they will only mess things
+up for you.
+
+Headers specified with this option will not be included in requests that curl
+knows will not be sent to a proxy.
+
+This option can be used multiple times to add/replace/remove multiple headers.
diff --git a/docs/cmdline-opts/proxytunnel.d b/docs/cmdline-opts/proxytunnel.d
new file mode 100644
index 00000000..3328dab6
--- /dev/null
+++ b/docs/cmdline-opts/proxytunnel.d
@@ -0,0 +1,9 @@
+Long: proxytunnel
+Help: Operate through a HTTP proxy tunnel (using CONNECT)
+See-also: proxy
+---
+When an HTTP proxy is used --proxy, this option will cause non-HTTP protocols
+to attempt to tunnel through the proxy instead of merely using it to do
+HTTP-like operations. The tunnel approach is made with the HTTP proxy CONNECT
+request and requires that the proxy allows direct connect to the remote port
+number curl wants to tunnel through to.
diff --git a/docs/cmdline-opts/referer.d b/docs/cmdline-opts/referer.d
new file mode 100644
index 00000000..dbecd785
--- /dev/null
+++ b/docs/cmdline-opts/referer.d
@@ -0,0 +1,12 @@
+Long: referer
+Protocols: HTTP
+Help: Referer URL
+See-also: user-agent header
+---
+Sends the "Referrer Page" information to the HTTP server. This can also be set
+with the --header flag of course. When used with --location you can append
+";auto" to the --referer URL to make curl automatically set the previous URL
+when it follows a Location: header. The \&";auto" string can be used alone,
+even if you don't set an initial --referer.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/remote-header-name.d b/docs/cmdline-opts/remote-header-name.d
new file mode 100644
index 00000000..771b6d46
--- /dev/null
+++ b/docs/cmdline-opts/remote-header-name.d
@@ -0,0 +1,19 @@
+Long: remote-header-name
+Short: J
+Protocols: HTTP
+Help: Use the header-provided filename
+---
+This option tells the --remote-name option to use the server-specified
+Content-Disposition filename instead of extracting a filename from the URL.
+
+If the server specifies a file name and a file with that name already exists
+in the current working directory it will not be overwritten and an error will
+occur. If the server doesn't specify a file name then this option has no
+effect.
+
+There's no attempt to decode %-sequences (yet) in the provided file name, so
+this option may provide you with rather unexpected file names.
+
+\fBWARNING\fP: Exercise judicious use of this option, especially on Windows. A
+rogue server could send you the name of a DLL or other file that could possibly
+be loaded automatically by Windows or some third party software.
diff --git a/docs/cmdline-opts/remote-name.d b/docs/cmdline-opts/remote-name.d
new file mode 100644
index 00000000..9fed64bf
--- /dev/null
+++ b/docs/cmdline-opts/remote-name.d
@@ -0,0 +1,21 @@
+Long: remote-name
+Short: O
+Help: Write output to a file named as the remote file
+---
+Write output to a local file named like the remote file we get. (Only the file
+part of the remote file is used, the path is cut off.)
+
+The file will be saved in the current working directory. If you want the file
+saved in a different directory, make sure you change the current working
+directory before invoking curl with this option.
+
+The remote file name to use for saving is extracted from the given URL,
+nothing else, and if it already exists it will be overwritten. If you want the
+server to be able to choose the file name refer to --remote-header-name which
+can be used in addition to this option. If the server chooses a file name and
+that name already exists it will not be overwritten.
+
+There is no URL decoding done on the file name. If it has %20 or other URL
+encoded parts of the name, they will end up as-is as file name.
+
+You may use this option as many times as the number of URLs you have.
diff --git a/docs/cmdline-opts/sslv2.d b/docs/cmdline-opts/sslv2.d
new file mode 100644
index 00000000..67d2b850
--- /dev/null
+++ b/docs/cmdline-opts/sslv2.d
@@ -0,0 +1,13 @@
+Short: 2
+Long: sslv2
+Tags: Versions
+Protocols: SSL
+Added:
+Mutexed: sslv3 tlsv1 tlsv1.1 tlsv1.2
+Requires: TLS
+See-also: http1.1 http2
+Help: Use SSLv2
+---
+Forces curl to use SSL version 2 when negotiating with a remote SSL
+server. Sometimes curl is built without SSLv2 support. SSLv2 is widely
+considered insecure (see RFC 6176).
diff --git a/docs/cmdline-opts/sslv3.d b/docs/cmdline-opts/sslv3.d
new file mode 100644
index 00000000..101ad100
--- /dev/null
+++ b/docs/cmdline-opts/sslv3.d
@@ -0,0 +1,13 @@
+Short: 3
+Long: sslv3
+Tags: Versions
+Protocols: SSL
+Added:
+Mutexed: sslv2 tlsv1 tlsv1.1 tlsv1.2
+Requires: TLS
+See-also: http1.1 http2
+Help: Use SSLv3
+---
+Forces curl to use SSL version 3 when negotiating with a remote SSL
+server. Sometimes curl is built without SSLv3 support. SSLv3 is widely
+considered insecure (see RFC 7568).
diff --git a/docs/cmdline-opts/tlsv1.d b/docs/cmdline-opts/tlsv1.d
new file mode 100644
index 00000000..d96fd1cc
--- /dev/null
+++ b/docs/cmdline-opts/tlsv1.d
@@ -0,0 +1,14 @@
+Short: 1
+Long: tlsv1
+Tags: Versions
+Protocols: SSL
+Added:
+Mutexed: tlsv1.1 tlsv1.2
+Requires: TLS
+See-also: http1.1 http2
+Help: Use TLSv1.0 or greater
+---
+Forces curl to use TLS version 1.x when negotiating with a remote TLS server.
+You can use options --tlsv1.0, --tlsv1.1, --tlsv1.2, and --tlsv1.3 to control
+the TLS version more precisely (if the SSL backend in use supports such a
+level of control).
diff --git a/docs/cmdline-opts/use-ascii.d b/docs/cmdline-opts/use-ascii.d
new file mode 100644
index 00000000..da307dc4
--- /dev/null
+++ b/docs/cmdline-opts/use-ascii.d
@@ -0,0 +1,8 @@
+Short: B
+Long: use-ascii
+Help: Use ASCII/text transfer
+Protocols: FTP LDAP
+---
+Enable ASCII transfer. For FTP, this can also be enforced by using an URL that
+ends with ";type=A". This option causes data sent to stdout to be in text mode
+for win32 systems.
diff --git a/docs/cmdline-opts/user-agent.d b/docs/cmdline-opts/user-agent.d
new file mode 100644
index 00000000..c98619d7
--- /dev/null
+++ b/docs/cmdline-opts/user-agent.d
@@ -0,0 +1,12 @@
+Short: A
+Long: user-agent
+Arg: <name>
+Help: Send User-Agent <name> to server
+Protocols: HTTP
+---
+
+Specify the User-Agent string to send to the HTTP server. To encode blanks in
+the string, surround the string with single quote marks. This can also be set
+with the --header option of course.
+
+If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/verbose.d b/docs/cmdline-opts/verbose.d
new file mode 100644
index 00000000..5d335218
--- /dev/null
+++ b/docs/cmdline-opts/verbose.d
@@ -0,0 +1,19 @@
+Short: v
+Long: verbose
+Mutexed: trace trace-ascii
+Help: Make the operation more talkative
+See-also: include
+---
+Makes curl verbose during the operation. Useful for debugging and seeing
+what's going on "under the hood". A line starting with '>' means "header data"
+sent by curl, '<' means "header data" received by curl that is hidden in
+normal cases, and a line starting with '*' means additional info provided by
+curl.
+
+If you only want HTTP headers in the output, --include might be the option
+you're looking for.
+
+If you think this option still doesn't give you enough details, consider using
+--trace or --trace-ascii instead.
+
+Use --silent to make curl really quiet.
diff --git a/docs/curl.1 b/docs/curl.1
index c573ff95..51680315 100644
--- a/docs/curl.1
+++ b/docs/curl.1
@@ -176,9 +176,9 @@ HTTP 2 to negotiate HTTP 2 support with the server during https sessions.
.IP "-1, --tlsv1"
(SSL)
Forces curl to use TLS version 1.x when negotiating with a remote TLS server.
-You can use options \fI--tlsv1.0\fP, \fI--tlsv1.1\fP, and \fI--tlsv1.2\fP to
-control the TLS version more precisely (if the SSL backend in use supports such
-a level of control).
+You can use options \fI--tlsv1.0\fP, \fI--tlsv1.1\fP, \fI--tlsv1.2\fP, and
+\fI--tlsv1.3\fP to control the TLS version more precisely (if the SSL backend
+in use supports such a level of control).
.IP "-2, --sslv2"
(SSL) Forces curl to use SSL version 2 when negotiating with a remote SSL
server. Sometimes curl is built without SSLv2 support. SSLv2 is widely
@@ -356,7 +356,7 @@ told to read from a file like that, carriage returns and newlines will be
stripped out. If you don't want the @ character to have a special
interpretation use \fI--data-raw\fP instead.
.IP "-D, --dump-header <file>"
-Write the protocol headers to the specified file.
+Write the received protocol headers to the specified file.
This option is handy to use when you want to store the headers that an HTTP
site sends to you. Cookies from the headers could then be read in a second
@@ -520,7 +520,7 @@ nickname contains ":", it needs to be preceded by "\\" so that it is not
recognized as password delimiter. If the nickname contains "\\", it needs to
be escaped as "\\\\" so that it is not recognized as an escape character.
-(iOS and Mac OS X only) If curl is built against Secure Transport, then the
+(iOS and macOS only) If curl is built against Secure Transport, then the
certificate string can either be the name of a certificate/private key in the
system or user keychain, or the path to a PKCS#12-encoded certificate and
private key. If you want to use a file from the current directory, please
@@ -569,6 +569,12 @@ Current Working Directory, or in any folder along your PATH.
If curl is built against the NSS SSL library, the NSS PEM PKCS#11 module
(libnsspem.so) needs to be available for this option to work properly.
+(iOS and macOS only) If curl is built against Secure Transport, then this
+option is supported for backward compatibility with other SSL engines, but it
+should not be set. If the option is not set, then curl will use the
+certificates in the system and user Keychain to verify the peer, which is the
+preferred method of verifying the peer's certificate chain.
+
If this option is used several times, the last one will be used.
.IP "--capath <CA certificate directory>"
(SSL) Tells curl to use the specified certificate directory to verify the
@@ -614,6 +620,23 @@ or no response at all is received, the verification fails.
This is currently only implemented in the OpenSSL, GnuTLS and NSS backends.
(Added in 7.41.0)
+.IP "--fail-early"
+Fail and exit on first detected error.
+
+When curl is used to do multiple transfers on the command line, it will
+attempt to operate on each given URL, one by one. By default, it will ignore
+errors if there are more URLs given and the last URL's success will determine
+the error code curl returns. So early failures will be "hidden" by subsequent
+successful transfers.
+
+Using this option, curl will instead return an error on the first transfers
+that fails, independent on the amount of more URLs that are given on the
+command line. This way, no transfer failures go undetected by scripts and
+similar.
+
+This option will apply for all given URLs even if you use \fI--next\fP.
+
+(Added in 7.52.0)
.IP "--false-start"
(SSL) Tells curl to use false start during the TLS handshake. False start is a
@@ -1018,10 +1041,6 @@ The given speed is measured in bytes/second, unless a suffix is appended.
Appending 'k' or 'K' will count the number as kilobytes, 'm' or M' makes it
megabytes, while 'g' or 'G' makes it gigabytes. Examples: 200K, 3m and 1G.
-The given rate is the average speed counted during the entire transfer. It
-means that curl might use higher transfer speeds in short bursts, but over
-time it uses no more than the given rate.
-
If you also use the \fI-Y, --speed-limit\fP option, that option will take
precedence and might cripple the rate-limiting slightly, to help keeping the
speed-limit logic working.
@@ -1237,7 +1256,17 @@ or use several variables like:
curl http://{site,host}.host[1-5].com -o "#1_#2"
-You may use this option as many times as the number of URLs you have.
+You may use this option as many times as the number of URLs you have. For
+example, if you specify two URLs on the same command line, you can use it like
+this:
+
+ curl -o aa example.com -o bb example.net
+
+and the order of the -o options and the URLs doesn't matter, just that the
+first -o is for the first URL and so on, so the above command line can also be
+written as
+
+ curl example.com example.net -o aa -o bb
See also the \fI--create-dirs\fP option to create the local directories
dynamically. Specifying the output as '-' (a single dash) will force the
@@ -1352,10 +1381,9 @@ consistency. However, a server may require a POST to remain a POST after such
a redirection. This option is meaningful only when using \fI-L, --location\fP
(Added in 7.26.0)
.IP "--proto <protocols>"
-Tells curl to use the listed protocols for its initial retrieval. Protocols
-are evaluated left to right, are comma separated, and are each a protocol
-name or 'all', optionally prefixed by zero or more modifiers. Available
-modifiers are:
+Tells curl to limit what protocols it may use in the transfer. Protocols are
+evaluated left to right, are comma separated, and are each a protocol name or
+'all', optionally prefixed by zero or more modifiers. Available modifiers are:
.RS
.TP 3
.B +
@@ -1412,8 +1440,9 @@ for details.
(Added in 7.45.0)
.IP "--proto-redir <protocols>"
-Tells curl to use the listed protocols on redirect. See --proto for how
-protocols are represented.
+Tells curl to limit what protocols it may use on redirect. Protocols denied by
+--proto are not overridden by this option. See \fI--proto\fP for how protocols
+are represented.
Example:
@@ -1439,6 +1468,33 @@ the default authentication method curl uses with proxies.
.IP "--proxy-digest"
Tells curl to use HTTP Digest authentication when communicating with the given
proxy. Use \fI--digest\fP for enabling HTTP Digest with a remote host.
+.IP "--proxy-cacert <CA certificate>"
+(SSL) Same as --cacert but used in HTTPS proxy context.
+(Added in 7.52.0)
+.IP "--proxy-capath <CA certificate directory>"
+(SSL) Same as --capath but used in HTTPS proxy context.
+(Added in 7.52.0)
+.IP "--proxy-cert <certificate[:password]>"
+(SSL) Same as \fI--cert\fP but used in HTTPS proxy context.
+(Added in 7.52.0)
+.IP "--proxy-cert-type <type>"
+(SSL) Same as \fI--cert-type\fP but used in HTTPS proxy context.
+(Added in 7.52.0)
+.IP "--proxy-ciphers <list of ciphers>"
+(SSL) Same as \fI--ciphers\fP but used in HTTPS proxy context.
+(Added in 7.52.0)
+.IP "--proxy-crlfile <file>"
+(HTTPS) Same as \fI--crlfile\fP but used in HTTPS proxy context.
+(Added in 7.52.0)
+.IP "--proxy-insecure"
+(SSL) Same as \fI--insecure\fP but used in HTTPS proxy context.
+(Added in 7.52.0)
+.IP "--proxy-key <key>"
+(SSL) Same as \fI--key\fP but used in HTTPS proxy context.
+(Added in 7.52.0)
+.IP "--proxy-key-type <type>"
+(SSL) Same as \fI--key-type\fP but used in HTTPS proxy context.
+(Added in 7.52.0)
.IP "--proxy-negotiate"
Tells curl to use HTTP Negotiate (SPNEGO) authentication when communicating
with the given proxy. Use \fI--negotiate\fP for enabling HTTP Negotiate (SPNEGO)
@@ -1446,11 +1502,35 @@ with a remote host. (Added in 7.17.1)
.IP "--proxy-ntlm"
Tells curl to use HTTP NTLM authentication when communicating with the given
proxy. Use \fI--ntlm\fP for enabling NTLM with a remote host.
+.IP "--proxy-pass <phrase>"
+(SSL) Same as \fI--pass\fP but used in HTTPS proxy context.
+(Added in 7.52.0)
.IP "--proxy-service-name <servicename>"
This option allows you to change the service name for proxy negotiation.
Examples: --proxy-negotiate proxy-name \fI--proxy-service-name\fP sockd would use
sockd/proxy-name. (Added in 7.43.0).
+.IP "--proxy-ssl-allow-beast"
+(SSL) Same as \fI--ssl-allow-beast\fP but used in HTTPS proxy context.
+(Added in 7.52.0)
+.IP "--proxy-sslv2"
+(SSL) Same as \fI--sslv2\fP but used in HTTPS proxy context.
+(Added in 7.52.0)
+.IP "--proxy-sslv3"
+(SSL) Same as \fI--sslv3\fP but used in HTTPS proxy context.
+(Added in 7.52.0)
+.IP "--proxy-tlsauthtype <authtype>"
+Same as \fI--tlsauthtype\fP but used in HTTPS proxy context.
+(Added in 7.52.0)
+.IP "--proxy-tlspassword <password>"
+Same as \fI--tlspassword\fP but used in HTTPS proxy context.
+(Added in 7.52.0)
+.IP "--proxy-tlsuser <user>"
+Same as \fI--tlsuser\fP but used in HTTPS proxy context.
+(Added in 7.52.0)
+.IP "--proxy-tlsv1"
+(SSL) Same as \fI--tlsv1\fP but used in HTTPS proxy context.
+(Added in 7.52.0)
.IP "--proxy1.0 <proxyhost[:port]>"
Use the specified HTTP 1.0 proxy. If the port number is not specified, it is
assumed at port 1080.
@@ -1608,6 +1688,10 @@ also \fI--retry-max-time\fP to limit the total time allowed for
retries. (Added in 7.12.3)
If this option is used several times, the last one will be used.
+.IP "--retry-connrefused"
+In addition to the other conditions, consider ECONNREFUSED as a transient
+error too for \fI--retry\fP. This option is used together with
+\fI--retry\fP. (Added in 7.52.0)
.IP "--retry-delay <seconds>"
Make curl sleep this amount of time before each retry when a transfer has
failed with a transient error (it changes the default backoff time algorithm
@@ -1762,6 +1846,11 @@ curl -T "{file1,file2}" http://www.example.com
or even
curl -T "img[1-1000].png" ftp://ftp.example.com/upload/
+
+When uploading to an SMTP server: the uploaded data is assumed to be RFC 5322
+formatted. It has to feature the necessary set of headers and mail body
+formatted correctly by the user as curl will not transcode nor encode it
+further in any way.
.IP "--tcp-nodelay"
Turn on the TCP_NODELAY option. See the \fIcurl_easy_setopt(3)\fP man page for
details about this option. (Added in 7.11.2)
@@ -1808,6 +1897,10 @@ Forces curl to use TLS version 1.1 when negotiating with a remote TLS server.
(SSL)
Forces curl to use TLS version 1.2 when negotiating with a remote TLS server.
(Added in 7.34.0)
+.IP "--tlsv1.3"
+(SSL)
+Forces curl to use TLS version 1.3 when negotiating with a remote TLS server.
+(Added in 7.52.0)
.IP "--tr-encoding"
(HTTP) Request a compressed Transfer-Encoding response using one of the
algorithms curl supports, and uncompress the data while receiving it.
@@ -1816,7 +1909,8 @@ algorithms curl supports, and uncompress the data while receiving it.
.IP "--trace <file>"
Enables a full trace dump of all incoming and outgoing data, including
descriptive information, to the given output file. Use "-" as filename to have
-the output sent to stdout.
+the output sent to stdout. Use "%" as filename to have the output sent to
+stderr.
This option overrides previous uses of \fI-v, --verbose\fP or
\fI--trace-ascii\fP.
@@ -1974,6 +2068,9 @@ IPv4 or IPv6 (Added in 7.29.0)
.B remote_port
The remote port number of the most recently done connection (Added in 7.29.0)
.TP
+.B scheme
+The URL scheme (sometimes called protocol) that was effectively used (Added in 7.52.0)
+.TP
.B size_download
The total amount of bytes that were downloaded.
.TP
@@ -2252,7 +2349,7 @@ Couldn't resolve host. The given remote host was not resolved.
.IP 7
Failed to connect to host.
.IP 8
-FTP weird server reply. The server sent data curl couldn't parse.
+Weird server reply. The server sent data curl couldn't parse.
.IP 9
FTP access denied. The server denied login or denied access to the particular
resource or directory you wanted to reach. Most often you tried to change to a
diff --git a/docs/examples/10-at-a-time.c b/docs/examples/10-at-a-time.c
index aa1862ec..45552918 100644
--- a/docs/examples/10-at-a-time.c
+++ b/docs/examples/10-at-a-time.c
@@ -86,7 +86,7 @@ static const char *urls[] = {
};
#define MAX 10 /* number of simultaneous transfers */
-#define CNT sizeof(urls)/sizeof(char*) /* total number of transfers to do */
+#define CNT sizeof(urls)/sizeof(char *) /* total number of transfers to do */
static size_t cb(char *d, size_t n, size_t l, void *p)
{
diff --git a/docs/examples/Makefile.netware b/docs/examples/Makefile.netware
index 2d85e736..9fe9db45 100644
--- a/docs/examples/Makefile.netware
+++ b/docs/examples/Makefile.netware
@@ -60,7 +60,7 @@ endif
TARGET = examples
VERSION = $(LIBCURL_VERSION)
COPYR = Copyright (C) $(LIBCURL_COPYRIGHT_STR)
-DESCR = cURL ($(LIBARCH))
+DESCR = curl ($(LIBARCH))
MTSAFE = YES
STACK = 8192
SCREEN = Example Program
diff --git a/docs/examples/anyauthput.c b/docs/examples/anyauthput.c
index b1367deb..1c9f965d 100644
--- a/docs/examples/anyauthput.c
+++ b/docs/examples/anyauthput.c
@@ -147,13 +147,13 @@ int main(int argc, char **argv)
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
/* which file to upload */
- curl_easy_setopt(curl, CURLOPT_READDATA, (void*)&hd);
+ curl_easy_setopt(curl, CURLOPT_READDATA, (void *)&hd);
/* set the ioctl function */
curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, my_ioctl);
/* pass the file descriptor to the ioctl callback as well */
- curl_easy_setopt(curl, CURLOPT_IOCTLDATA, (void*)&hd);
+ curl_easy_setopt(curl, CURLOPT_IOCTLDATA, (void *)&hd);
/* enable "uploading" (which means PUT when doing HTTP) */
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
diff --git a/docs/examples/cacertinmem.c b/docs/examples/cacertinmem.c
index bba8c722..ace58e48 100644
--- a/docs/examples/cacertinmem.c
+++ b/docs/examples/cacertinmem.c
@@ -34,12 +34,12 @@ size_t writefunction(void *ptr, size_t size, size_t nmemb, void *stream)
return (nmemb*size);
}
-static CURLcode sslctx_function(CURL * curl, void * sslctx, void * parm)
+static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
{
- X509_STORE * store;
- X509 * cert=NULL;
- BIO * bio;
- char * mypem = /* www.cacert.org */
+ X509_STORE *store;
+ X509 *cert=NULL;
+ BIO *bio;
+ char *mypem = /* www.cacert.org */
"-----BEGIN CERTIFICATE-----\n"\
"MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290\n"\
"IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB\n"\
@@ -107,7 +107,7 @@ static CURLcode sslctx_function(CURL * curl, void * sslctx, void * parm)
int main(void)
{
- CURL * ch;
+ CURL *ch;
CURLcode rv;
rv=curl_global_init(CURL_GLOBAL_ALL);
diff --git a/docs/examples/curlx.c b/docs/examples/curlx.c
index 155da237..e0d70999 100644
--- a/docs/examples/curlx.c
+++ b/docs/examples/curlx.c
@@ -133,14 +133,14 @@ static const char *curlx_usage[]={
/* This is a context that we pass to all callbacks */
typedef struct sslctxparm_st {
- unsigned char * p12file;
- const char * pst;
- PKCS12 * p12;
- EVP_PKEY * pkey;
- X509 * usercert;
+ unsigned char *p12file;
+ const char *pst;
+ PKCS12 *p12;
+ EVP_PKEY *pkey;
+ X509 *usercert;
STACK_OF(X509) * ca;
- CURL * curl;
- BIO * errorbio;
+ CURL *curl;
+ BIO *errorbio;
int accesstype;
int verbose;
@@ -196,7 +196,7 @@ static int ssl_app_verify_callback(X509_STORE_CTX *ctx, void *arg)
BIO_printf(p->errorbio, "entering ssl_app_verify_callback\n");
if((ok= X509_verify_cert(ctx)) && ctx->cert) {
- unsigned char * accessinfo;
+ unsigned char *accessinfo;
if(p->verbose > 1)
X509_print_ex(p->errorbio, ctx->cert, 0, 0);
@@ -228,10 +228,10 @@ static int ssl_app_verify_callback(X509_STORE_CTX *ctx, void *arg)
- an application verification callback (the function above)
*/
-static CURLcode sslctxfun(CURL * curl, void * sslctx, void * parm)
+static CURLcode sslctxfun(CURL *curl, void *sslctx, void *parm)
{
- sslctxparm * p = (sslctxparm *) parm;
- SSL_CTX * ctx = (SSL_CTX *) sslctx;
+ sslctxparm *p = (sslctxparm *) parm;
+ SSL_CTX *ctx = (SSL_CTX *) sslctx;
if(!SSL_CTX_use_certificate(ctx, p->usercert)) {
BIO_printf(p->errorbio, "SSL_CTX_use_certificate problem\n");
@@ -270,24 +270,24 @@ int main(int argc, char **argv)
BIO* in=NULL;
BIO* out=NULL;
- char * outfile = NULL;
- char * infile = NULL;
+ char *outfile = NULL;
+ char *infile = NULL;
int tabLength=100;
char *binaryptr;
- char* mimetype;
- char* mimetypeaccept=NULL;
- char* contenttype;
- const char** pp;
- unsigned char* hostporturl = NULL;
- BIO * p12bio;
+ char *mimetype;
+ char *mimetypeaccept=NULL;
+ char *contenttype;
+ const char **pp;
+ unsigned char *hostporturl = NULL;
+ BIO *p12bio;
char **args = argv + 1;
- unsigned char * serverurl;
+ unsigned char *serverurl;
sslctxparm p;
char *response;
CURLcode res;
- struct curl_slist * headers=NULL;
+ struct curl_slist *headers=NULL;
int badarg=0;
binaryptr = malloc(tabLength);
diff --git a/docs/examples/evhiperfifo.c b/docs/examples/evhiperfifo.c
index 118f152e..52f68281 100644
--- a/docs/examples/evhiperfifo.c
+++ b/docs/examples/evhiperfifo.c
@@ -86,7 +86,7 @@ typedef struct _GlobalInfo
struct ev_timer timer_event;
CURLM *multi;
int still_running;
- FILE* input;
+ FILE *input;
} GlobalInfo;
@@ -243,7 +243,8 @@ static void remsock(SockInfo *f, GlobalInfo *g)
/* Assign information to a SockInfo structure */
-static void setsock(SockInfo*f, curl_socket_t s, CURL*e, int act, GlobalInfo*g)
+static void setsock(SockInfo *f, curl_socket_t s, CURL *e, int act,
+ GlobalInfo *g)
{
printf("%s \n", __PRETTY_FUNCTION__);
diff --git a/docs/examples/fileupload.c b/docs/examples/fileupload.c
index 363fae69..6b05c4ce 100644
--- a/docs/examples/fileupload.c
+++ b/docs/examples/fileupload.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,16 +37,12 @@ int main(void)
FILE *fd;
fd = fopen("debugit", "rb"); /* open file to upload */
- if(!fd) {
-
+ if(!fd)
return 1; /* can't continue */
- }
/* to get the file size */
- if(fstat(fileno(fd), &file_info) != 0) {
-
+ if(fstat(fileno(fd), &file_info) != 0)
return 1; /* can't continue */
- }
curl = curl_easy_init();
if(curl) {
@@ -86,5 +82,6 @@ int main(void)
/* always cleanup */
curl_easy_cleanup(curl);
}
+ fclose(fd);
return 0;
}
diff --git a/docs/examples/fopen.c b/docs/examples/fopen.c
index 71be178e..7435264a 100644
--- a/docs/examples/fopen.c
+++ b/docs/examples/fopen.c
@@ -84,7 +84,7 @@ URL_FILE *url_fopen(const char *url, const char *operation);
int url_fclose(URL_FILE *file);
int url_feof(URL_FILE *file);
size_t url_fread(void *ptr, size_t size, size_t nmemb, URL_FILE *file);
-char * url_fgets(char *ptr, size_t size, URL_FILE *file);
+char *url_fgets(char *ptr, size_t size, URL_FILE *file);
void url_rewind(URL_FILE *file);
/* we use a global one for convenience */
diff --git a/docs/examples/ftpuploadresume.c b/docs/examples/ftpuploadresume.c
index 64156340..8f7f45da 100644
--- a/docs/examples/ftpuploadresume.c
+++ b/docs/examples/ftpuploadresume.c
@@ -36,8 +36,8 @@
/* The MinGW headers are missing a few Win32 function definitions,
you shouldn't need this if you use VC++ */
#if defined(__MINGW32__) && !defined(__MINGW64__)
-int __cdecl _snscanf(const char * input, size_t length,
- const char * format, ...);
+int __cdecl _snscanf(const char *input, size_t length,
+ const char *format, ...);
#endif
@@ -77,7 +77,7 @@ size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)
}
-int upload(CURL *curlhandle, const char * remotepath, const char * localpath,
+int upload(CURL *curlhandle, const char *remotepath, const char *localpath,
long timeout, long tries)
{
FILE *f;
diff --git a/docs/examples/ghiper.c b/docs/examples/ghiper.c
index 7317a63d..c0fbd824 100644
--- a/docs/examples/ghiper.c
+++ b/docs/examples/ghiper.c
@@ -94,7 +94,8 @@ typedef struct _SockInfo {
} SockInfo;
/* Die if we get a bad CURLMcode somewhere */
-static void mcode_or_die(const char *where, CURLMcode code) {
+static void mcode_or_die(const char *where, CURLMcode code)
+{
if(CURLM_OK != code) {
const char *s;
switch (code) {
@@ -206,7 +207,8 @@ static void remsock(SockInfo *f)
}
/* Assign information to a SockInfo structure */
-static void setsock(SockInfo*f, curl_socket_t s, CURL*e, int act, GlobalInfo*g)
+static void setsock(SockInfo *f, curl_socket_t s, CURL *e, int act,
+ GlobalInfo *g)
{
GIOCondition kind =
(act&CURL_POLL_IN?G_IO_IN:0)|(act&CURL_POLL_OUT?G_IO_OUT:0);
diff --git a/docs/examples/hiperfifo.c b/docs/examples/hiperfifo.c
index 98bcafe6..dce009c5 100644
--- a/docs/examples/hiperfifo.c
+++ b/docs/examples/hiperfifo.c
@@ -82,7 +82,7 @@ typedef struct _GlobalInfo
struct event *timer_event;
CURLM *multi;
int still_running;
- FILE* input;
+ FILE *input;
} GlobalInfo;
@@ -230,7 +230,8 @@ static void remsock(SockInfo *f)
/* Assign information to a SockInfo structure */
-static void setsock(SockInfo*f, curl_socket_t s, CURL*e, int act, GlobalInfo*g)
+static void setsock(SockInfo *f, curl_socket_t s, CURL *e, int act,
+ GlobalInfo *g)
{
int kind =
(act&CURL_POLL_IN?EV_READ:0)|(act&CURL_POLL_OUT?EV_WRITE:0)|EV_PERSIST;
diff --git a/docs/examples/imap-append.c b/docs/examples/imap-append.c
index 3f832897..bbf9fe43 100644
--- a/docs/examples/imap-append.c
+++ b/docs/examples/imap-append.c
@@ -85,6 +85,8 @@ int main(void)
{
CURL *curl;
CURLcode res = CURLE_OK;
+ const char **p;
+ long infilesize;
struct upload_status upload_ctx;
upload_ctx.lines_read = 0;
@@ -107,6 +109,12 @@ int main(void)
curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+ infilesize = 0;
+ for(p = payload_text; *p; ++p) {
+ infilesize += (long)strlen(*p);
+ }
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE, infilesize);
+
/* Perform the append */
res = curl_easy_perform(curl);
diff --git a/docs/examples/multi-uv.c b/docs/examples/multi-uv.c
index 51526c89..c0228945 100644
--- a/docs/examples/multi-uv.c
+++ b/docs/examples/multi-uv.c
@@ -24,18 +24,12 @@
* multi_socket API using libuv
* </DESC>
*/
-/* Example application code using the multi socket interface to download
- multiple files at once, but instead of using curl_multi_perform and
- curl_multi_wait, which uses select(), we use libuv.
- It supports epoll, kqueue, etc. on unixes and fast IO completion ports on
- Windows, which means, it should be very fast on all platforms..
-
- Written by Clemens Gruber, based on an outdated example from uvbook and
- some tests from libuv.
+/* Example application using the multi socket interface to download multiple
+ files in parallel, powered by libuv.
Requires libuv and (of course) libcurl.
- See http://nikhilm.github.com/uvbook/ for more information on libuv.
+ See https://nikhilm.github.com/uvbook/ for more information on libuv.
*/
#include <stdio.h>
@@ -77,7 +71,6 @@ void destroy_curl_context(curl_context_t *context)
uv_close((uv_handle_t *) &context->poll_handle, curl_close_cb);
}
-
void add_download(const char *url, int num)
{
char filename[50];
@@ -102,22 +95,28 @@ void add_download(const char *url, int num)
static void check_multi_info(void)
{
- int running_handles;
char *done_url;
CURLMsg *message;
int pending;
+ CURL *easy_handle;
FILE *file;
while((message = curl_multi_info_read(curl_handle, &pending))) {
switch(message->msg) {
case CURLMSG_DONE:
- curl_easy_getinfo(message->easy_handle, CURLINFO_EFFECTIVE_URL,
- &done_url);
- curl_easy_getinfo(message->easy_handle, CURLINFO_PRIVATE, &file);
+ /* Do not use message data after calling curl_multi_remove_handle() and
+ curl_easy_cleanup(). As per curl_multi_info_read() docs:
+ "WARNING: The data the returned pointer points to will not survive
+ calling curl_multi_cleanup, curl_multi_remove_handle or
+ curl_easy_cleanup." */
+ easy_handle = message->easy_handle;
+
+ curl_easy_getinfo(easy_handle, CURLINFO_EFFECTIVE_URL, &done_url);
+ curl_easy_getinfo(easy_handle, CURLINFO_PRIVATE, &file);
printf("%s DONE\n", done_url);
- curl_multi_remove_handle(curl_handle, message->easy_handle);
- curl_easy_cleanup(message->easy_handle);
+ curl_multi_remove_handle(curl_handle, easy_handle);
+ curl_easy_cleanup(easy_handle);
if(file) {
fclose(file);
}
@@ -135,9 +134,6 @@ void curl_perform(uv_poll_t *req, int status, int events)
int running_handles;
int flags = 0;
curl_context_t *context;
- char *done_url;
- CURLMsg *message;
- int pending;
uv_timer_stop(&timeout);
@@ -146,7 +142,7 @@ void curl_perform(uv_poll_t *req, int status, int events)
if(events & UV_WRITABLE)
flags |= CURL_CSELECT_OUT;
- context = (curl_context_t *) req;
+ context = (curl_context_t *) req->data;
curl_multi_socket_action(curl_handle, context->sockfd, flags,
&running_handles);
@@ -174,22 +170,23 @@ int handle_socket(CURL *easy, curl_socket_t s, int action, void *userp,
void *socketp)
{
curl_context_t *curl_context;
- if(action == CURL_POLL_IN || action == CURL_POLL_OUT) {
- if(socketp) {
- curl_context = (curl_context_t *) socketp;
- }
- else {
- curl_context = create_curl_context(s);
- }
- curl_multi_assign(curl_handle, s, (void *) curl_context);
- }
+ int events = 0;
switch(action) {
case CURL_POLL_IN:
- uv_poll_start(&curl_context->poll_handle, UV_READABLE, curl_perform);
- break;
case CURL_POLL_OUT:
- uv_poll_start(&curl_context->poll_handle, UV_WRITABLE, curl_perform);
+ case CURL_POLL_INOUT:
+ curl_context = socketp ?
+ (curl_context_t *) socketp : create_curl_context(s);
+
+ curl_multi_assign(curl_handle, s, (void *) curl_context);
+
+ if(action != CURL_POLL_IN)
+ events |= UV_WRITABLE;
+ if(action != CURL_POLL_OUT)
+ events |= UV_READABLE;
+
+ uv_poll_start(&curl_context->poll_handle, events, curl_perform);
break;
case CURL_POLL_REMOVE:
if(socketp) {
@@ -213,7 +210,7 @@ int main(int argc, char **argv)
return 0;
if(curl_global_init(CURL_GLOBAL_ALL)) {
- fprintf(stderr, "Could not init cURL\n");
+ fprintf(stderr, "Could not init curl\n");
return 1;
}
diff --git a/docs/examples/opensslthreadlock.c b/docs/examples/opensslthreadlock.c
index eebc42ee..6f86c7f7 100644
--- a/docs/examples/opensslthreadlock.c
+++ b/docs/examples/opensslthreadlock.c
@@ -52,7 +52,7 @@ void handle_error(const char *file, int lineno, const char *msg)
/* This array will store all of the mutexes available to OpenSSL. */
static MUTEX_TYPE *mutex_buf= NULL;
-static void locking_function(int mode, int n, const char * file, int line)
+static void locking_function(int mode, int n, const char *file, int line)
{
if(mode & CRYPTO_LOCK)
MUTEX_LOCK(mutex_buf[n]);
diff --git a/docs/examples/rtsp.c b/docs/examples/rtsp.c
index 63c46e15..bdab3954 100644
--- a/docs/examples/rtsp.c
+++ b/docs/examples/rtsp.c
@@ -188,7 +188,7 @@ int main(int argc, char * const argv[])
printf("\nRTSP request %s\n", VERSION_STR);
printf(" Project web site: http://code.google.com/p/rtsprequest/\n");
- printf(" Requires cURL V7.20 or greater\n\n");
+ printf(" Requires curl V7.20 or greater\n\n");
/* check command line */
if((argc != 2) && (argc != 3)) {
@@ -226,7 +226,7 @@ int main(int argc, char * const argv[])
if(res == CURLE_OK) {
curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
CURL *curl;
- fprintf(stderr, " cURL V%s loaded\n", data->version);
+ fprintf(stderr, " curl V%s loaded\n", data->version);
/* initialize this curl session */
curl = curl_easy_init();
diff --git a/docs/examples/sessioninfo.c b/docs/examples/sessioninfo.c
index 11c87cd1..024a0e12 100644
--- a/docs/examples/sessioninfo.c
+++ b/docs/examples/sessioninfo.c
@@ -24,7 +24,7 @@
* </DESC>
*/
-/* Note that this example currently requires cURL to be linked against
+/* Note that this example currently requires curl to be linked against
GnuTLS (and this program must also be linked against -lgnutls). */
#include <stdio.h>
diff --git a/docs/libcurl/Makefile.am b/docs/libcurl/Makefile.am
index 49acd977..2d51b460 100644
--- a/docs/libcurl/Makefile.am
+++ b/docs/libcurl/Makefile.am
@@ -90,8 +90,8 @@ dist_m4macro_DATA = libcurl.m4
CLEANFILES = $(HTMLPAGES) $(PDFPAGES) $(TESTS) libcurl-symbols.3
-EXTRA_DIST = $(man_MANS) $(HTMLPAGES) index.html $(PDFPAGES) ABI \
- symbols-in-versions symbols.pl mksymbolsmanpage.pl
+EXTRA_DIST = $(man_MANS) index.html ABI symbols-in-versions symbols.pl \
+ mksymbolsmanpage.pl
MAN2HTML= roffit --mandir=. $< >$@
SUFFIXES = .3 .html
diff --git a/docs/libcurl/curl_easy_getinfo.3 b/docs/libcurl/curl_easy_getinfo.3
index 9ffcd14a..fabc7e92 100644
--- a/docs/libcurl/curl_easy_getinfo.3
+++ b/docs/libcurl/curl_easy_getinfo.3
@@ -104,6 +104,9 @@ See \fICURLINFO_REQUEST_SIZE(3)\fP
.IP CURLINFO_SSL_VERIFYRESULT
Certificate verification result.
See \fICURLINFO_SSL_VERIFYRESULT(3)\fP
+.IP CURLINFO_PROXY_SSL_VERIFYRESULT
+Proxy certificate verification result.
+See \fICURLINFO_PROXY_SSL_VERIFYRESULT(3)\fP
.IP CURLINFO_SSL_ENGINES
A list of OpenSSL crypto engines.
See \fICURLINFO_SSL_ENGINES(3)\fP
@@ -180,6 +183,12 @@ See \fICURLINFO_RTSP_SERVER_CSEQ(3)\fP
.IP CURLINFO_RTSP_CSEQ_RECV
RTSP CSeq last received.
See \fICURLINFO_RTSP_CSEQ_RECV(3)\fP
+.IP CURLINFO_PROTOCOL
+The protocol used for the connection. (Added in 7.52.0)
+See \fICURLINFO_PROTOCOL(3)\fP
+.IP CURLINFO_SCHEME
+The scheme used for the connection. (Added in 7.52.0)
+See \fICURLINFO_SCHEME(3)\fP
.SH TIMES
.nf
An overview of the six time values available from curl_easy_getinfo()
diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3
index 75f1ce46..590a47f8 100644
--- a/docs/libcurl/curl_easy_setopt.3
+++ b/docs/libcurl/curl_easy_setopt.3
@@ -144,6 +144,8 @@ Error message buffer. See \fICURLOPT_ERRORBUFFER(3)\fP
stderr replacement stream. See \fICURLOPT_STDERR(3)\fP
.IP CURLOPT_FAILONERROR
Fail on HTTP 4xx errors. \fICURLOPT_FAILONERROR(3)\fP
+.IP CURLOPT_KEEP_SENDING_ON_ERROR
+Keep sending on HTTP >= 300 errors. \fICURLOPT_KEEP_SENDING_ON_ERROR(3)\fP
.SH NETWORK OPTIONS
.IP CURLOPT_URL
URL to work on. See \fICURLOPT_URL(3)\fP
@@ -157,10 +159,14 @@ Protocols to allow redirects to. See \fICURLOPT_REDIR_PROTOCOLS(3)\fP
Default protocol. See \fICURLOPT_DEFAULT_PROTOCOL(3)\fP
.IP CURLOPT_PROXY
Proxy to use. See \fICURLOPT_PROXY(3)\fP
+.IP CURLOPT_SOCKS_PROXY
+Socks proxy to use. See \fICURLOPT_SOCKS_PROXY(3)\fP
.IP CURLOPT_PROXYPORT
Proxy port to use. See \fICURLOPT_PROXYPORT(3)\fP
.IP CURLOPT_PROXYTYPE
Proxy type. See \fICURLOPT_PROXYTYPE(3)\fP
+.IP CURLOPT_SOCKS_PROXYTYPE
+Socks proxy type. See \fICURLOPT_SOCKS_PROXYTYPE(3)\fP
.IP CURLOPT_NOPROXY
Filter out hosts from proxy use. \fICURLOPT_NOPROXY(3)\fP
.IP CURLOPT_HTTPPROXYTUNNEL
@@ -226,10 +232,16 @@ Proxy password. See \fICURLOPT_PROXYPASSWORD(3)\fP
HTTP server authentication methods. See \fICURLOPT_HTTPAUTH(3)\fP
.IP CURLOPT_TLSAUTH_USERNAME
TLS authentication user name. See \fICURLOPT_TLSAUTH_USERNAME(3)\fP
+.IP CURLOPT_PROXY_TLSAUTH_USERNAME
+Proxy TLS authentication user name. See \fICURLOPT_PROXY_TLSAUTH_USERNAME(3)\fP
.IP CURLOPT_TLSAUTH_PASSWORD
TLS authentication password. See \fICURLOPT_TLSAUTH_PASSWORD(3)\fP
+.IP CURLOPT_PROXY_TLSAUTH_PASSWORD
+Proxy TLS authentication password. See \fICURLOPT_PROXY_TLSAUTH_PASSWORD(3)\fP
.IP CURLOPT_TLSAUTH_TYPE
TLS authentication methods. See \fICURLOPT_TLSAUTH_TYPE(3)\fP
+.IP CURLOPT_PROXY_TLSAUTH_TYPE
+Proxy TLS authentication methods. See \fICURLOPT_PROXY_TLSAUTH_TYPE(3)\fP
.IP CURLOPT_PROXYAUTH
HTTP proxy authentication methods. See \fICURLOPT_PROXYAUTH(3)\fP
.IP CURLOPT_SASL_IR
@@ -445,14 +457,24 @@ Timeout for waiting for the server's connect back to be accepted. See \fICURLOPT
.SH SSL and SECURITY OPTIONS
.IP CURLOPT_SSLCERT
Client cert. See \fICURLOPT_SSLCERT(3)\fP
+.IP CURLOPT_PROXY_SSLCERT
+Proxy client cert. See \fICURLOPT_PROXY_SSLCERT(3)\fP
.IP CURLOPT_SSLCERTTYPE
Client cert type. See \fICURLOPT_SSLCERTTYPE(3)\fP
+.IP CURLOPT_PROXY_SSLCERTTYPE
+Proxy client cert type. See \fICURLOPT_PROXY_SSLCERTTYPE(3)\fP
.IP CURLOPT_SSLKEY
Client key. See \fICURLOPT_SSLKEY(3)\fP
+.IP CURLOPT_PROXY_SSLKEY
+Proxy client key. See \fICURLOPT_PROXY_SSLKEY(3)\fP
.IP CURLOPT_SSLKEYTYPE
Client key type. See \fICURLOPT_SSLKEYTYPE(3)\fP
+.IP CURLOPT_PROXY_SSLKEYTYPE
+Proxy client key type. See \fICURLOPT_PROXY_SSLKEYTYPE(3)\fP
.IP CURLOPT_KEYPASSWD
Client key password. See \fICURLOPT_KEYPASSWD(3)\fP
+.IP CURLOPT_PROXY_KEYPASSWD
+Proxy client key password. See \fICURLOPT_PROXY_KEYPASSWD(3)\fP
.IP CURLOPT_SSL_ENABLE_ALPN
Enable use of ALPN. See \fICURLOPT_SSL_ENABLE_ALPN(3)\fP
.IP CURLOPT_SSL_ENABLE_NPN
@@ -465,20 +487,32 @@ Default SSL engine. See \fICURLOPT_SSLENGINE_DEFAULT(3)\fP
Enable TLS False Start. See \fICURLOPT_SSL_FALSESTART(3)\fP
.IP CURLOPT_SSLVERSION
SSL version to use. See \fICURLOPT_SSLVERSION(3)\fP
+.IP CURLOPT_PROXY_SSLVERSION
+Proxy SSL version to use. See \fICURLOPT_PROXY_SSLVERSION(3)\fP
.IP CURLOPT_SSL_VERIFYHOST
Verify the host name in the SSL certificate. See \fICURLOPT_SSL_VERIFYHOST(3)\fP
+.IP CURLOPT_PROXY_SSL_VERIFYHOST
+Verify the host name in the proxy SSL certificate. See \fICURLOPT_PROXY_SSL_VERIFYHOST(3)\fP
.IP CURLOPT_SSL_VERIFYPEER
Verify the SSL certificate. See \fICURLOPT_SSL_VERIFYPEER(3)\fP
+.IP CURLOPT_PROXY_SSL_VERIFYPEER
+Verify the proxy SSL certificate. See \fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP
.IP CURLOPT_SSL_VERIFYSTATUS
Verify the SSL certificate's status. See \fICURLOPT_SSL_VERIFYSTATUS(3)\fP
.IP CURLOPT_CAINFO
CA cert bundle. See \fICURLOPT_CAINFO(3)\fP
+.IP CURLOPT_PROXY_CAINFO
+Proxy CA cert bundle. See \fICURLOPT_PROXY_CAINFO(3)\fP
.IP CURLOPT_ISSUERCERT
Issuer certificate. See \fICURLOPT_ISSUERCERT(3)\fP
.IP CURLOPT_CAPATH
Path to CA cert bundle. See \fICURLOPT_CAPATH(3)\fP
+.IP CURLOPT_PROXY_CAPATH
+Path to proxy CA cert bundle. See \fICURLOPT_PROXY_CAPATH(3)\fP
.IP CURLOPT_CRLFILE
Certificate Revocation List. See \fICURLOPT_CRLFILE(3)\fP
+.IP CURLOPT_PROXY_CRLFILE
+Proxy Certificate Revocation List. See \fICURLOPT_PROXY_CRLFILE(3)\fP
.IP CURLOPT_CERTINFO
Extract certificate info. See \fICURLOPT_CERTINFO(3)\fP
.IP CURLOPT_PINNEDPUBLICKEY
@@ -489,10 +523,14 @@ Provide source for entropy random data. See \fICURLOPT_RANDOM_FILE(3)\fP
Identify EGD socket for entropy. See \fICURLOPT_EGDSOCKET(3)\fP
.IP CURLOPT_SSL_CIPHER_LIST
Ciphers to use. See \fICURLOPT_SSL_CIPHER_LIST(3)\fP
+.IP CURLOPT_PROXY_SSL_CIPHER_LIST
+Proxy ciphers to use. See \fICURLOPT_PROXY_SSL_CIPHER_LIST(3)\fP
.IP CURLOPT_SSL_SESSIONID_CACHE
Disable SSL session-id cache. See \fICURLOPT_SSL_SESSIONID_CACHE(3)\fP
.IP CURLOPT_SSL_OPTIONS
Control SSL behavior. See \fICURLOPT_SSL_OPTIONS(3)\fP
+.IP CURLOPT_PROXY_SSL_OPTIONS
+Control proxy SSL behavior. See \fICURLOPT_PROXY_SSL_OPTIONS(3)\fP
.IP CURLOPT_KRBLEVEL
Kerberos security level. See \fICURLOPT_KRBLEVEL(3)\fP
.IP CURLOPT_GSSAPI_DELEGATION
diff --git a/docs/libcurl/curl_easy_unescape.3 b/docs/libcurl/curl_easy_unescape.3
index 06fd6fcb..50ce97db 100644
--- a/docs/libcurl/curl_easy_unescape.3
+++ b/docs/libcurl/curl_easy_unescape.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -40,7 +40,10 @@ will use strlen() on the input \fIurl\fP string to find out the size.
If \fBoutlength\fP is non-NULL, the function will write the length of the
returned string in the integer it points to. This allows an escaped string
-containing %00 to still get used properly after unescaping.
+containing %00 to still get used properly after unescaping. Since this is a
+pointer to an \fIint\fP type, it can only return a value up to INT_MAX so no
+longer string can be unescaped if the string length is returned in this
+parameter.
You must \fIcurl_free(3)\fP the returned string when you're done with it.
.SH AVAILABILITY
diff --git a/docs/libcurl/curl_formadd.3 b/docs/libcurl/curl_formadd.3
index 6923913d..bf1b11e1 100644
--- a/docs/libcurl/curl_formadd.3
+++ b/docs/libcurl/curl_formadd.3
@@ -105,6 +105,8 @@ content then you must make sure strlen() on the data pointer returns zero.
followed by a filename, causes that file to be read and its contents used
as data in this part. This part does \fInot\fP automatically become a file
upload part simply because its data was read from a file.
+
+The specified file needs to kept around until the associated transfer is done.
.IP CURLFORM_FILE
followed by a filename, makes this part a file upload part. It sets the
\fIfilename\fP field to the basename of the provided filename, it reads the
@@ -117,6 +119,8 @@ providing multiple \fBCURLFORM_FILE\fP arguments each followed by the filename
The given upload file has to exist in its full in the file system already when
the upload starts, as libcurl needs to read the correct file size beforehand.
+
+The specified file needs to kept around until the associated transfer is done.
.IP CURLFORM_CONTENTTYPE
is used in combination with \fICURLFORM_FILE\fP. Followed by a pointer to a
string which provides the content-type for this part, possibly instead of an
diff --git a/docs/libcurl/curl_global_cleanup.3 b/docs/libcurl/curl_global_cleanup.3
index 2e3ff036..04ab0437 100644
--- a/docs/libcurl/curl_global_cleanup.3
+++ b/docs/libcurl/curl_global_cleanup.3
@@ -42,8 +42,14 @@ these other libraries.
See the description in \fIlibcurl(3)\fP of global environment requirements for
details of how to use this function.
-
+.SH CAUTION
+\fIcurl_global_cleanup(3)\fP does not block waiting for any libcurl-created
+threads to terminate (such as threads used for name resolving). If a module
+containing libcurl is dynamically unloaded while libcurl-created threads are
+still running then your program may crash or other corruption may occur. We
+recommend you do not run libcurl from any module that may be unloaded
+dynamically. This behavior may be addressed in the future.
.SH "SEE ALSO"
.BR curl_global_init "(3), "
.BR libcurl "(3), "
-
+.BR libcurl-thread "(3), "
diff --git a/docs/libcurl/libcurl-errors.3 b/docs/libcurl/libcurl-errors.3
index 0a21a758..1b6e34f5 100644
--- a/docs/libcurl/libcurl-errors.3
+++ b/docs/libcurl/libcurl-errors.3
@@ -60,9 +60,8 @@ Couldn't resolve host. The given remote host was not resolved.
.IP "CURLE_COULDNT_CONNECT (7)"
Failed to connect() to host or proxy.
.IP "CURLE_FTP_WEIRD_SERVER_REPLY (8)"
-After connecting to a FTP server, libcurl expects to get a certain reply
-back. This error code implies that it got a strange or bad reply. The given
-remote server is probably not an OK FTP server.
+The server sent data libcurl couldn't parse. This error code is used for more
+than just FTP and is aliased as \fICURLE_WEIRD_SERVER_REPLY\fP since 7.51.0.
.IP "CURLE_REMOTE_ACCESS_DENIED (9)"
We were denied access to the resource given in the URL. For FTP, this occurs
while trying to change to the remote directory.
diff --git a/docs/libcurl/opts/CURLINFO_COOKIELIST.3 b/docs/libcurl/opts/CURLINFO_COOKIELIST.3
index 961fd982..b9f75f4d 100644
--- a/docs/libcurl/opts/CURLINFO_COOKIELIST.3
+++ b/docs/libcurl/opts/CURLINFO_COOKIELIST.3
@@ -30,7 +30,7 @@ CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_COOKIELIST,
struct curl_slist **cookies);
.SH DESCRIPTION
Pass a pointer to a 'struct curl_slist *' to receive a linked-list of all
-cookies cURL knows (expired ones, too). Don't forget to call
+cookies curl knows (expired ones, too). Don't forget to call
\fIcurl_slist_free_all(3)\fP on the list after it has been used. If there are
no cookies (cookies for the handle have not been enabled or simply none have
been received) 'struct curl_slist *' will be set to point to NULL.
diff --git a/docs/libcurl/opts/CURLINFO_PROTOCOL.3 b/docs/libcurl/opts/CURLINFO_PROTOCOL.3
new file mode 100644
index 00000000..b8211187
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_PROTOCOL.3
@@ -0,0 +1,55 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLINFO_PROTOCOL 3 "23 November 2016" "libcurl 7.52.0" "curl_easy_getinfo options"
+.SH NAME
+CURLINFO_PROTOCOL \- get the protocol used in the connection
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROTOCOL, long *p);
+.SH DESCRIPTION
+Pass a pointer to a long to receive the version used in the last http connection.
+The returned value will be one of the CURLPROTO_* values.
+.SH PROTOCOLS
+All
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ long protocol;
+ curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
+ }
+ curl_easy_cleanup(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in 7.52.0
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR CURLINFO_RESPONSE_CODE "(3), "
+.BR curl_easy_getinfo "(3), " curl_easy_setopt "(3), "
diff --git a/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.3 b/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.3
new file mode 100644
index 00000000..34892f54
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.3
@@ -0,0 +1,44 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLINFO_PROXY_SSL_VERIFYRESULT 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_getinfo options"
+.SH NAME
+CURLINFO_PROXY_SSL_VERIFYRESULT \- get the result of the proxy certification verification
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXY_SSL_VERIFYRESULT, long *result);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a pointer to a long to receive the result of the certification
+verification that was requested (using the \fICURLOPT_SSL_VERIFYPEER(3)\fP
+option.
+.SH PROTOCOLS
+All using TLS
+.SH EXAMPLE
+TODO
+.SH AVAILABILITY
+Added in 7.5
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR curl_easy_getinfo "(3), " curl_easy_setopt "(3), "
diff --git a/docs/libcurl/opts/CURLINFO_SCHEME.3 b/docs/libcurl/opts/CURLINFO_SCHEME.3
new file mode 100644
index 00000000..78c3d688
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_SCHEME.3
@@ -0,0 +1,59 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLINFO_SCHEME 3 "23 November 2016" "libcurl 7.52.0" "curl_easy_getinfo options"
+.SH NAME
+CURLINFO_SCHEME \- get the URL scheme (sometimes called protocol) used in the connection
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SCHEME, long *p);
+.SH DESCRIPTION
+Pass a pointer to a char pointer to receive the pointer to a zero-terminated
+string holding the URL scheme used for the most recent connection done with this
+\fBcurl\fP handle.
+
+The \fBid\fP pointer will be NULL or pointing to private read-only memory you
+MUST NOT free or modify.
+.SH PROTOCOLS
+All
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ char * scheme;
+ curl_easy_getinfo(curl, CURLINFO_SCHEME, &scheme);
+ }
+ curl_easy_cleanup(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in 7.52.0
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR CURLINFO_RESPONSE_CODE "(3), "
+.BR curl_easy_getinfo "(3), " curl_easy_setopt "(3), "
diff --git a/docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.3 b/docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.3
index cac3c719..1204a0f9 100644
--- a/docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.3
+++ b/docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.3
@@ -29,8 +29,8 @@ CURLMOPT_MAX_PIPELINE_LENGTH \- maximum number of requests in a pipeline
CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_PIPELINE_LENGTH, long max);
.SH DESCRIPTION
Pass a long. The set \fBmax\fP number will be used as the maximum amount of
-outstanding requests in a pipelined connection. Only used if pipelining is
-enabled.
+outstanding requests in an HTTP/1.1 pipelined connection. This option is only
+used for HTTP/1.1 pipelining, not for HTTP/2 multiplexing.
When this limit is reached, libcurl will use another connection to the same
host (see \fICURLMOPT_MAX_HOST_CONNECTIONS(3)\fP), or queue the request until
diff --git a/docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.3 b/docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.3
index 835c2bd4..ea53bfff 100644
--- a/docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.3
+++ b/docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -34,7 +34,7 @@ handle. For each new session, libcurl will open a new connection up to the
limit set by \fICURLMOPT_MAX_TOTAL_CONNECTIONS(3)\fP. When the limit is
reached, the sessions will be pending until there are available
connections. If \fICURLMOPT_PIPELINING(3)\fP is enabled, libcurl will try to
-pipeline if the host is capable of it.
+pipeline or use multiplexing if the host is capable of it.
.SH DEFAULT
The default value is 0, which means that there is no limit. It is then simply
controlled by the number of easy handles added.
diff --git a/docs/libcurl/opts/CURLMOPT_PIPELINING.3 b/docs/libcurl/opts/CURLMOPT_PIPELINING.3
index 4c79b1be..1a404765 100644
--- a/docs/libcurl/opts/CURLMOPT_PIPELINING.3
+++ b/docs/libcurl/opts/CURLMOPT_PIPELINING.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,24 +22,36 @@
.\"
.TH CURLMOPT_PIPELINING 3 "17 Jun 2014" "libcurl 7.37.0" "curl_multi_setopt options"
.SH NAME
-CURLMOPT_PIPELINING \- enable/disable HTTP pipelining
+CURLMOPT_PIPELINING \- enable HTTP pipelining and multiplexing
.SH SYNOPSIS
#include <curl/curl.h>
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING, long bits);
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING, long bitmask);
.SH DESCRIPTION
-Set the \fBbits\fP parameter to 1 to make libcurl use HTTP pipelining for
-HTTP/1.1 transfers done using this multi handle, as far as possible. This
-means that if you add a second request that can use an already existing
-connection, the second request will be \&"piped" on the same connection rather
-than being executed in parallel.
+Pass in the \fBbitmask\fP parameter to instruct libcurl to enable HTTP
+pipelining and/or HTTP/2 multiplexing for this multi handle.
-When using pipelining, there are also several other related options that are
-interesting to tweak and adjust to alter how libcurl spreads out requests on
-different connections or not etc.
+When enabled, libcurl will attempt to use those protocol features when doing
+parallel requests to the same hosts.
-Starting in 7.43.0, the \fBbits\fP parameter's bit 1 also has a meaning and
-libcurl is now offering symbol names for the bits:
+For pipelining, this means that if you add a second request that can use an
+already existing connection, the second request will be \&"piped" on the same
+connection rather than being executed in parallel.
+
+For multiplexing, this means that follow-up requests can re-use an existing
+connection and send the new request multiplexed over that at the same time as
+other transfers are already using that single connection.
+
+There are several other related options that are interesting to tweak and
+adjust to alter how libcurl spreads out requests on different connections or
+not etc.
+
+Before 7.43.0, this option was set to 1 and 0 to enable and disable HTTP/1.1
+pipelining.
+
+Starting in 7.43.0, \fBbitmask\fP's second bit also has a meaning, and you can
+ask for pipelining and multiplexing independently of each other by toggling
+the correct bits.
.IP CURLPIPE_NOTHING (0)
Default, which means doing no attempts at pipelining or multiplexing.
.IP CURLPIPE_HTTP1 (1)
@@ -49,7 +61,7 @@ connections that are already established and in use to hosts.
If this bit is set, libcurl will try to multiplex the new transfer over an
existing connection if possible. This requires HTTP/2.
.SH DEFAULT
-0 (off)
+0 (both pipeline and multiplexing are off)
.SH PROTOCOLS
HTTP(S)
.SH EXAMPLE
diff --git a/docs/libcurl/opts/CURLOPT_CAINFO.3 b/docs/libcurl/opts/CURLOPT_CAINFO.3
index a05f5c0c..7db50a8f 100644
--- a/docs/libcurl/opts/CURLOPT_CAINFO.3
+++ b/docs/libcurl/opts/CURLOPT_CAINFO.3
@@ -40,6 +40,12 @@ is assumed to be stored, as established at build time.
If curl is built against the NSS SSL library, the NSS PEM PKCS#11 module
(libnsspem.so) needs to be available for this option to work properly.
+
+(iOS and macOS only) If curl is built against Secure Transport, then this
+option is supported for backward compatibility with other SSL engines, but it
+should not be set. If the option is not set, then curl will use the
+certificates in the system and user Keychain to verify the peer, which is the
+preferred method of verifying the peer's certificate chain.
.SH DEFAULT
Built-in system specific
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.3 b/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.3
index bf07499a..535c5302 100644
--- a/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.3
+++ b/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.3
@@ -119,6 +119,7 @@ int my_trace(CURL *handle, curl_infotype type,
{
const char *text;
(void)handle; /* prevent compiler warning */
+ (void)userp;
switch (type) {
case CURLINFO_TEXT:
diff --git a/docs/libcurl/opts/CURLOPT_FAILONERROR.3 b/docs/libcurl/opts/CURLOPT_FAILONERROR.3
index 79474cef..93d8ba6e 100644
--- a/docs/libcurl/opts/CURLOPT_FAILONERROR.3
+++ b/docs/libcurl/opts/CURLOPT_FAILONERROR.3
@@ -53,4 +53,4 @@ Along with HTTP
.SH RETURN VALUE
Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
-.BR CURLOPT_HTTP200ALIASES "(3), "
+.BR CURLOPT_HTTP200ALIASES "(3), " CURLOPT_KEEP_SENDING_ON_ERROR "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.3 b/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.3
new file mode 100644
index 00000000..277125b6
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.3
@@ -0,0 +1,52 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_KEEP_SENDING_ON_ERROR 3 "22 Sep 2016" "libcurl 7.51.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_KEEP_SENDING_ON_ERROR \- keep sending on early HTTP response >= 300
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KEEP_SENDING_ON_ERROR,
+ long keep_sending);
+.SH DESCRIPTION
+A long parameter set to 1 tells the library to keep sending the request body
+if the HTTP code returned is equal to or larger than 300. The default action
+would be to stop sending and close the stream or connection.
+
+This option is suitable for manual NTLM authentication, i.e. if an application
+does not use \fICURLOPT_HTTPAUTH(3)\fP, but instead sets "Authorization: NTLM ..."
+headers manually using \fICURLOPT_HTTPHEADER(3)\fP.
+
+Most applications do not need this option.
+.SH DEFAULT
+0, stop sending on error
+.SH PROTOCOLS
+HTTP
+.SH EXAMPLE
+TODO
+.SH AVAILABILITY
+Along with HTTP. Added in 7.51.0.
+.SH RETURN VALUE
+Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR CURLOPT_FAILONERROR "(3), " CURLOPT_HTTPHEADER "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.3 b/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.3
index 031f2cd3..c99ff61e 100644
--- a/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.3
+++ b/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.3
@@ -31,9 +31,8 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAX_RECV_SPEED_LARGE,
curl_off_t speed);
.SH DESCRIPTION
Pass a curl_off_t as parameter. If a download exceeds this \fIspeed\fP
-(counted in bytes per second) on cumulative average during the transfer, the
-transfer will pause to keep the average rate less than or equal to the
-parameter value. Defaults to unlimited speed.
+(counted in bytes per second) the transfer will pause to keep the speed less
+than or equal to the parameter value. Defaults to unlimited speed.
This option doesn't affect transfer speeds done with FILE:// URLs.
.SH DEFAULT
diff --git a/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.3 b/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.3
index c2c6336f..7f3efe57 100644
--- a/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.3
+++ b/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.3
@@ -31,9 +31,9 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAX_SEND_SPEED_LARGE,
curl_off_t maxspeed);
.SH DESCRIPTION
Pass a curl_off_t as parameter with the \fImaxspeed\fP. If an upload exceeds
-this speed (counted in bytes per second) on cumulative average during the
-transfer, the transfer will pause to keep the average rate less than or equal
-to the parameter value. Defaults to unlimited speed.
+this speed (counted in bytes per second) the transfer will pause to keep the
+speed less than or equal to the parameter value. Defaults to unlimited
+speed.
This option doesn't affect transfer speeds done with FILE:// URLs.
.SH DEFAULT
diff --git a/docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.3 b/docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.3
index 4e673bd4..33d201d9 100644
--- a/docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.3
+++ b/docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -91,14 +91,23 @@ footer:
.fi
.SH AVAILABILITY
PEM/DER support:
+
7.39.0: OpenSSL, GnuTLS and GSKit
+
7.43.0: NSS and wolfSSL/CyaSSL
+
7.47.0: mbedtls
+
7.49.0: PolarSSL
+
sha256 support:
- 7.44.0: OpenSSL, GnuTLS, NSS and wolfSSL/CyaSSL.
+
+ 7.44.0: OpenSSL, GnuTLS, NSS and wolfSSL/CyaSSL
+
7.47.0: mbedtls
+
7.49.0: PolarSSL
+
Other SSL backends not supported.
.SH RETURN VALUE
Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
diff --git a/docs/libcurl/opts/CURLOPT_PROXY.3 b/docs/libcurl/opts/CURLOPT_PROXY.3
index f6975bbd..64b74fae 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -41,8 +41,7 @@ The proxy string may be prefixed with [scheme]:// to specify which kind of
proxy is used. Use socks4://, socks4a://, socks5:// or socks5h:// (the last
one to enable socks5 and asking the proxy to do the resolving, also known as
\fICURLPROXY_SOCKS5_HOSTNAME\fP type) to request the specific SOCKS version to
-be used. No protocol specified, http:// and all others will be treated as HTTP
-proxies.
+be used. No scheme specified or http://, will be treated as HTTP proxies.
Without a scheme prefix, \fICURLOPT_PROXYTYPE(3)\fP can be used to specify
which kind of proxy the string identifies.
@@ -77,6 +76,9 @@ Since 7.14.1 the proxy environment variable names can include the protocol
scheme.
Since 7.21.7 the proxy string supports the socks protocols as "schemes".
+
+Since 7.50.2, unsupported schemes in proxy strings cause libcurl to return
+error.
.SH RETURN VALUE
Returns CURLE_OK if proxies are supported, CURLE_UNKNOWN_OPTION if not, or
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.3 b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.3
new file mode 100644
index 00000000..d240b37f
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.3
@@ -0,0 +1,64 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_CAINFO 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_CAINFO \- path to proxy Certificate Authority (CA) bundle
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAINFO, char *path);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a char * to a zero terminated string naming a file holding one or more
+certificates to verify the peer with.
+
+If \fICURLOPT_SSL_VERIFYPEER(3)\fP is zero and you avoid verifying the
+server's certificate, \fICURLOPT_CAINFO(3)\fP need not even indicate an
+accessible file.
+
+This option is by default set to the system path where libcurl's cacert bundle
+is assumed to be stored, as established at build time.
+
+If curl is built against the NSS SSL library, the NSS PEM PKCS#11 module
+(libnsspem.so) needs to be available for this option to work properly.
+
+(iOS and macOS only) If curl is built against Secure Transport, then this
+option is supported for backward compatibility with other SSL engines, but it
+should not be set. If the option is not set, then curl will use the
+certificates in the system and user Keychain to verify the peer, which is the
+preferred method of verifying the peer's certificate chain.
+.SH DEFAULT
+Built-in system specific
+.SH PROTOCOLS
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+.SH EXAMPLE
+TODO
+.SH AVAILABILITY
+For SSL engines that don't support certificate files the CURLOPT_PROXY_CAINFO option
+is ignored. Refer to https://curl.haxx.se/docs/ssl-compared.html
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_CAPATH "(3), "
+.BR CURLOPT_SSL_VERIFYPEER "(3), " CURLOPT_SSL_VERIFYHOST "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.3 b/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.3
new file mode 100644
index 00000000..d1dfb06a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.3
@@ -0,0 +1,54 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_CAPATH 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_CAPATH \- specify directory holding proxy CA certificates
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAPATH, char *capath);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a char * to a zero terminated string naming a directory holding multiple
+CA certificates to verify the peer with. If libcurl is built against OpenSSL,
+the certificate directory must be prepared using the openssl c_rehash utility.
+This makes sense only when used in combination with the
+\fICURLOPT_SSL_VERIFYPEER(3)\fP option.
+
+The \fICURLOPT_CAPATH(3)\fP function apparently does not work in Windows due
+to some limitation in openssl.
+.SH DEFAULT
+NULL
+.SH PROTOCOLS
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+.SH EXAMPLE
+TODO
+.SH AVAILABILITY
+This option is supported by the OpenSSL, GnuTLS and PolarSSL backends. The NSS
+backend provides the option only for backward compatibility.
+.SH RETURN VALUE
+Returns CURLE_OK if TLS enabled, and CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_CAINFO "(3), "
+.BR CURLOPT_STDERR "(3), " CURLOPT_DEBUGFUNCTION "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.3 b/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.3
new file mode 100644
index 00000000..1d0dc639
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.3
@@ -0,0 +1,59 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_CRLFILE 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_CRLFILE \- specify a proxy Certificate Revocation List file
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CRLFILE, char *file);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a char * to a zero terminated string naming a \fIfile\fP with the
+concatenation of CRL (in PEM format) to use in the certificate validation that
+occurs during the SSL exchange.
+
+When curl is built to use NSS or GnuTLS, there is no way to influence the use
+of CRL passed to help in the verification process. When libcurl is built with
+OpenSSL support, X509_V_FLAG_CRL_CHECK and X509_V_FLAG_CRL_CHECK_ALL are both
+set, requiring CRL check against all the elements of the certificate chain if
+a CRL file is passed.
+
+This option makes sense only when used in combination with the
+\fICURLOPT_SSL_VERIFYPEER(3)\fP option.
+
+A specific error code (\fICURLE_SSL_CRL_BADFILE\fP) is defined with the
+option. It is returned when the SSL exchange fails because the CRL file cannot
+be loaded. A failure in certificate verification due to a revocation
+information found in the CRL does not trigger this specific error.
+.SH DEFAULT
+NULL
+.SH PROTOCOLS
+All TLS-based protocols
+.SH EXAMPLE
+TODO
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_SSL_VERIFYPEER "(3), " CURLOPT_SSL_VERIFYHOST "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.3 b/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.3
new file mode 100644
index 00000000..1abd329d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.3
@@ -0,0 +1,46 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_KEYPASSWD 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_KEYPASSWD \- set passphrase to proxy private key
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_KEYPASSWD, char *pwd);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a pointer to a zero terminated string as parameter. It will be used as
+the password required to use the \fICURLOPT_SSLKEY(3)\fP or
+\fICURLOPT_SSH_PRIVATE_KEYFILE(3)\fP private key. You never needed a pass
+phrase to load a certificate but you need one to load your private key.
+.SH DEFAULT
+NULL
+.SH PROTOCOLS
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+.SH EXAMPLE
+TODO
+.SH RETURN VALUE
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_SSLKEY "(3), " CURLOPT_SSH_PRIVATE_KEYFILE "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.3
new file mode 100644
index 00000000..d69f6e63
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.3
@@ -0,0 +1,56 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_SSLCERT 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_SSLCERT \- set SSL proxy client certificate
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERT, char *cert);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a pointer to a zero terminated string as parameter. The string should be
+the file name of your client certificate. The default format is "P12" on
+Secure Transport and "PEM" on other engines, and can be changed with
+\fICURLOPT_SSLCERTTYPE(3)\fP.
+
+With NSS or Secure Transport, this can also be the nickname of the certificate
+you wish to authenticate with as it is named in the security database. If you
+want to use a file from the current directory, please precede it with "./"
+prefix, in order to avoid confusion with a nickname.
+
+When using a client certificate, you most likely also need to provide a
+private key with \fICURLOPT_SSLKEY(3)\fP.
+.SH DEFAULT
+NULL
+.SH PROTOCOLS
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+.SH EXAMPLE
+TODO
+.SH AVAILABILITY
+If built TLS enabled.
+.SH RETURN VALUE
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_SSLCERTTYPE "(3), " CURLOPT_SSLKEY "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.3
new file mode 100644
index 00000000..326330c6
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.3
@@ -0,0 +1,49 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_SSLCERTTYPE 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_SSLCERTTYPE \- specify type of the proxy client SSL certificate
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERTTYPE, char *type);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a pointer to a zero terminated string as parameter. The string should be
+the format of your certificate. Supported formats are "PEM" and "DER", except
+with Secure Transport. OpenSSL (versions 0.9.3 and later) and Secure Transport
+(on iOS 5 or later, or OS X 10.7 or later) also support "P12" for
+PKCS#12-encoded files.
+.SH DEFAULT
+"PEM"
+.SH PROTOCOLS
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+.SH EXAMPLE
+TODO
+.SH AVAILABILITY
+If built TLS enabled.
+.SH RETURN VALUE
+Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_SSLCERT "(3), " CURLOPT_SSLKEY "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.3
new file mode 100644
index 00000000..e5c7369a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.3
@@ -0,0 +1,51 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_SSLKEY 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_SSLKEY \- specify private keyfile for TLS and SSL proxy client cert
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEY, char *keyfile);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a pointer to a zero terminated string as parameter. The string should be
+the file name of your private key. The default format is "PEM" and can be
+changed with \fICURLOPT_SSLKEYTYPE(3)\fP.
+
+(iOS and Mac OS X only) This option is ignored if curl was built against
+Secure Transport. Secure Transport expects the private key to be already
+present in the keychain or PKCS#12 file containing the certificate.
+.SH DEFAULT
+NULL
+.SH PROTOCOLS
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+.SH EXAMPLE
+TODO
+.SH AVAILABILITY
+If built TLS enabled.
+.SH RETURN VALUE
+Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_SSLKEYTYPE "(3), " CURLOPT_SSLCERT "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.3
new file mode 100644
index 00000000..97454f92
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.3
@@ -0,0 +1,51 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_SSLKEYTYPE 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_SSLKEYTYPE \- set type of the proxy private key file
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEYTYPE, char *type);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a pointer to a zero terminated string as parameter. The string should be
+the format of your private key. Supported formats are "PEM", "DER" and "ENG".
+
+The format "ENG" enables you to load the private key from a crypto engine. In
+this case \fICURLOPT_SSLKEY(3)\fP is used as an identifier passed to the
+engine. You have to set the crypto engine with \fICURLOPT_SSLENGINE(3)\fP.
+\&"DER" format key file currently does not work because of a bug in OpenSSL.
+.SH DEFAULT
+"PEM"
+.SH PROTOCOLS
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+.SH EXAMPLE
+TODO
+.SH AVAILABILITY
+If built TLS enabled.
+.SH RETURN VALUE
+Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_SSLKEY "(3), " CURLOPT_SSLCERT "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.3
new file mode 100644
index 00000000..0e91be93
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.3
@@ -0,0 +1,81 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_SSLVERSION 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_SSLVERSION \- set proxy preferred TLS/SSL version
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLVERSION, long version);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a long as parameter to control which version of SSL/TLS to attempt to
+use.
+
+Use one of the available defines for this purpose. The available options are:
+.RS
+.IP CURL_SSLVERSION_DEFAULT
+The default action. This will attempt to figure out the remote SSL protocol
+version.
+.IP CURL_SSLVERSION_TLSv1
+TLSv1.x
+.IP CURL_SSLVERSION_SSLv2
+SSLv2
+.IP CURL_SSLVERSION_SSLv3
+SSLv3
+.IP CURL_SSLVERSION_TLSv1_0
+TLSv1.0 (Added in 7.34.0)
+.IP CURL_SSLVERSION_TLSv1_1
+TLSv1.1 (Added in 7.34.0)
+.IP CURL_SSLVERSION_TLSv1_2
+TLSv1.2 (Added in 7.34.0)
+.IP CURL_SSLVERSION_TLSv1_3
+TLSv1.3 (Added in 7.52.0)
+.RE
+.SH DEFAULT
+CURL_SSLVERSION_DEFAULT
+.SH PROTOCOLS
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* ask libcurl to use TLS version 1.0 or later */
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLVERSION, CURL_SSLVERSION_TLSv1);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+}
+.fi
+.SH AVAILABILITY
+SSLv2 is disabled by default since 7.18.1. Other SSL versions availability may
+vary depending on which backend libcurl has been built to use.
+
+SSLv3 is disabled by default since 7.39.0.
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR CURLOPT_USE_SSL "(3), " CURLOPT_HTTP_VERSION "(3), "
+.BR CURLOPT_IPRESOLVE "(3) "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.3
new file mode 100644
index 00000000..f872952a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.3
@@ -0,0 +1,66 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_SSL_CIPHER_LIST 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_SSL_CIPHER_LIST \- specify ciphers to use for proxy TLS
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_CIPHER_LIST, char *list);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a char *, pointing to a zero terminated string holding the list of
+ciphers to use for the SSL connection. The list must be syntactically correct,
+it consists of one or more cipher strings separated by colons. Commas or
+spaces are also acceptable separators but colons are normally used, \&!, \&-
+and \&+ can be used as operators.
+
+For OpenSSL and GnuTLS valid examples of cipher lists include 'RC4-SHA',
+\'SHA1+DES\', 'TLSv1' and 'DEFAULT'. The default list is normally set when you
+compile OpenSSL.
+
+You'll find more details about cipher lists on this URL:
+
+ https://www.openssl.org/docs/apps/ciphers.html
+
+For NSS, valid examples of cipher lists include 'rsa_rc4_128_md5',
+\'rsa_aes_128_sha\', etc. With NSS you don't add/remove ciphers. If one uses
+this option then all known ciphers are disabled and only those passed in are
+enabled.
+
+You'll find more details about the NSS cipher lists on this URL:
+
+ http://git.fedorahosted.org/cgit/mod_nss.git/plain/docs/mod_nss.html#Directives
+.SH DEFAULT
+NULL, use internal default
+.SH PROTOCOLS
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+.SH EXAMPLE
+TODO
+.SH AVAILABILITY
+If built TLS enabled.
+.SH RETURN VALUE
+Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_SSLVERSION "(3), " CURLOPT_USE_SSL "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3
new file mode 100644
index 00000000..45402dfa
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3
@@ -0,0 +1,62 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_SSL_OPTIONS 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_SSL_OPTIONS \- set proxy SSL behavior options
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_OPTIONS, long bitmask);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a long with a bitmask to tell libcurl about specific SSL behaviors.
+
+\fICURLSSLOPT_ALLOW_BEAST\fP tells libcurl to not attempt to use any
+workarounds for a security flaw in the SSL3 and TLS1.0 protocols. If this
+option isn't used or this bit is set to 0, the SSL layer libcurl uses may use a
+work-around for this flaw although it might cause interoperability problems
+with some (older) SSL implementations. WARNING: avoiding this work-around
+lessens the security, and by setting this option to 1 you ask for exactly that.
+This option is only supported for DarwinSSL, NSS and OpenSSL.
+
+Added in 7.44.0:
+
+\fICURLSSLOPT_NO_REVOKE\fP tells libcurl to disable certificate revocation
+checks for those SSL backends where such behavior is present. \fBCurrently this
+option is only supported for WinSSL (the native Windows SSL library), with an
+exception in the case of Windows' Untrusted Publishers blacklist which it seems
+can't be bypassed.\fP This option may have broader support to accommodate other
+SSL backends in the future.
+https://curl.haxx.se/docs/ssl-compared.html
+
+
+.SH DEFAULT
+0
+.SH PROTOCOLS
+All TLS-based protocols
+.SH EXAMPLE
+TODO
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR CURLOPT_SSLVERSION "(3), " CURLOPT_SSL_CIPHER_LIST "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.3
new file mode 100644
index 00000000..e72027a8
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.3
@@ -0,0 +1,88 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_SSL_VERIFYHOST 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_SSL_VERIFYHOST \- verify the proxy certificate's name against host
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_VERIFYHOST, long verify);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a long as parameter specifying what to \fIverify\fP.
+
+This option determines whether libcurl verifies that the server cert is for
+the server it is known as.
+
+When negotiating TLS and SSL connections, the server sends a certificate
+indicating its identity.
+
+When \fICURLOPT_SSL_VERIFYHOST(3)\fP is 2, that certificate must indicate that
+the server is the server to which you meant to connect, or the connection
+fails. Simply put, it means it has to have the same name in the certificate as
+is in the URL you operate against.
+
+Curl considers the server the intended one when the Common Name field or a
+Subject Alternate Name field in the certificate matches the host name in the
+URL to which you told Curl to connect.
+
+When the \fIverify\fP value is 1, \fIcurl_easy_setopt\fP will return an error
+and the option value will not be changed. It was previously (in 7.28.0 and
+earlier) a debug option of some sorts, but it is no longer supported due to
+frequently leading to programmer mistakes. Future versions will stop returning
+an error for 1 and just treat 1 and 2 the same.
+
+When the \fIverify\fP value is 0, the connection succeeds regardless of the
+names in the certificate. Use that ability with caution!
+
+The default value for this option is 2.
+
+This option controls checking the server's certificate's claimed identity.
+The server could be lying. To control lying, see
+\fICURLOPT_SSL_VERIFYPEER(3)\fP. If libcurl is built against NSS and
+\fICURLOPT_SSL_VERIFYPEER(3)\fP is zero, \fICURLOPT_SSL_VERIFYHOST(3)\fP is
+also set to zero and cannot be overridden.
+.SH DEFAULT
+2
+.SH PROTOCOLS
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Set the default value: strict name check please */
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 2L);
+
+ curl_easy_perform(curl);
+}
+.fi
+.SH AVAILABILITY
+If built TLS enabled.
+.SH RETURN VALUE
+Returns CURLE_OK if TLS is supported, and CURLE_UNKNOWN_OPTION if not.
+
+If 1 is set as argument, \fICURLE_BAD_FUNCTION_ARGUMENT\fP is returned.
+.SH "SEE ALSO"
+.BR CURLOPT_SSL_VERIFYPEER "(3), " CURLOPT_CAINFO "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.3
new file mode 100644
index 00000000..0eb902bb
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.3
@@ -0,0 +1,82 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_SSL_VERIFYPEER 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_SSL_VERIFYPEER \- verify the proxy peer's SSL certificate
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_VERIFYPEER, long verify);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a long as parameter to enable or disable.
+
+This option determines whether curl verifies the authenticity of the peer's
+certificate. A value of 1 means curl verifies; 0 (zero) means it doesn't.
+
+When negotiating a TLS or SSL connection, the server sends a certificate
+indicating its identity. Curl verifies whether the certificate is authentic,
+i.e. that you can trust that the server is who the certificate says it is.
+This trust is based on a chain of digital signatures, rooted in certification
+authority (CA) certificates you supply. curl uses a default bundle of CA
+certificates (the path for that is determined at build time) and you can
+specify alternate certificates with the \fICURLOPT_CAINFO(3)\fP option or the
+\fICURLOPT_CAPATH(3)\fP option.
+
+When \fICURLOPT_SSL_VERIFYPEER(3)\fP is enabled, and the verification fails to
+prove that the certificate is authentic, the connection fails. When the
+option is zero, the peer certificate verification succeeds regardless.
+
+Authenticating the certificate is not enough to be sure about the server. You
+typically also want to ensure that the server is the server you mean to be
+talking to. Use \fICURLOPT_SSL_VERIFYHOST(3)\fP for that. The check that the
+host name in the certificate is valid for the host name you're connecting to
+is done independently of the \fICURLOPT_SSL_VERIFYPEER(3)\fP option.
+
+WARNING: disabling verification of the certificate allows bad guys to
+man-in-the-middle the communication without you knowing it. Disabling
+verification makes the communication insecure. Just having encryption on a
+transfer is not enough as you cannot be sure that you are communicating with
+the correct end-point.
+.SH DEFAULT
+By default, curl assumes a value of 1.
+.SH PROTOCOLS
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Set the default value: strict certificate check please */
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 1L);
+
+ curl_easy_perform(curl);
+}
+.fi
+.SH AVAILABILITY
+If built TLS enabled.
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR CURLOPT_SSL_VERIFYHOST "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.3 b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.3
new file mode 100644
index 00000000..1d824fed
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.3
@@ -0,0 +1,48 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_TLSAUTH_PASSWORD 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_TLSAUTH_PASSWORD \- password to use for proxy TLS authentication
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_PASSWORD, char *pwd);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a char * as parameter, which should point to the zero terminated password
+to use for the TLS authentication method specified with the
+\fICURLOPT_TLSAUTH_TYPE(3)\fP option. Requires that the
+\fICURLOPT_TLSAUTH_USERNAME(3)\fP option also be set.
+.SH DEFAULT
+NULL
+.SH PROTOCOLS
+All TLS-based protocols
+.SH EXAMPLE
+TODO
+.SH AVAILABILITY
+Added in 7.21.4
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_TLSAUTH_TYPE "(3), " CURLOPT_TLSAUTH_USERNAME "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.3 b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.3
new file mode 100644
index 00000000..228a42e4
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.3
@@ -0,0 +1,53 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_TLSAUTH_TYPE 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_TLSAUTH_TYPE \- set proxy TLS authentication methods
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_TYPE, char *type);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a pointer to a zero terminated string as parameter. The string
+should be the method of the TLS authentication. Supported method is "SRP".
+
+.IP SRP
+TLS-SRP authentication. Secure Remote Password authentication for TLS is
+defined in RFC5054 and provides mutual authentication if both sides have a
+shared secret. To use TLS-SRP, you must also set the
+\fICURLOPT_TLSAUTH_USERNAME(3)\fP and \fICURLOPT_TLSAUTH_PASSWORD(3)\fP
+options.
+.SH DEFAULT
+blank
+.SH PROTOCOLS
+All TLS-based protocols
+.SH EXAMPLE
+TODO
+.SH AVAILABILITY
+You need to build libcurl with GnuTLS or OpenSSL with TLS-SRP support for this
+to work.
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR CURLOPT_TLSAUTH_USERNAME "(3), " CURLOPT_TLSAUTH_PASSWORD "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.3 b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.3
new file mode 100644
index 00000000..e8d4e4d1
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.3
@@ -0,0 +1,46 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_TLSAUTH_USERNAME 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_TLSAUTH_USERNAME \- user name to use for proxy TLS authentication
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_USERNAME, char *user);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a char * as parameter, which should point to the zero terminated username
+to use for the TLS authentication method specified with the
+\fICURLOPT_TLSAUTH_TYPE(3)\fP option. Requires that the
+\fICURLOPT_TLSAUTH_PASSWORD(3)\fP option also be set.
+.SH DEFAULT
+NULL
+.SH PROTOCOLS
+All TLS-based protocols
+.SH EXAMPLE
+TODO
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_TLSAUTH_TYPE "(3), " CURLOPT_TLSAUTH_PASSWORD "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.3 b/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.3
index 8bd76f6b..3a5c3fcd 100644
--- a/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.3
+++ b/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.3
@@ -34,6 +34,9 @@ redirect when \fICURLOPT_FOLLOWLOCATION(3)\fP is enabled. This allows you to
limit specific transfers to only be allowed to use a subset of protocols in
redirections.
+Protocols denied by \fICURLOPT_PROTOCOLS(3)\fP are not overridden by this
+option.
+
By default libcurl will allow all protocols on redirect except several disabled
for security reasons: Since 7.19.4 FILE and SCP are disabled, and since 7.40.0
SMB and SMBS are also disabled. \fICURLPROTO_ALL\fP enables all protocols on
diff --git a/docs/libcurl/opts/CURLOPT_SOCKS_PROXY.3 b/docs/libcurl/opts/CURLOPT_SOCKS_PROXY.3
new file mode 100644
index 00000000..aad3d40a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SOCKS_PROXY.3
@@ -0,0 +1,88 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_SOCKS_PROXY 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_SOCKS_PROXY \- set socks proxy to use
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS_PROXY, char *proxy);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Set the \fIproxy\fP to use for the upcoming request. The parameter should be a
+char * to a zero terminated string holding the host name or dotted numerical
+IP address. A numerical IPv6 address must be written within [brackets].
+
+To specify port number in this string, append :[port] to the end of the host
+name. The proxy's port number may optionally be specified with the separate
+option \fICURLOPT_PROXYPORT(3)\fP. If not specified, libcurl will default to
+using port 1080 for proxies.
+
+The proxy string may be prefixed with [scheme]:// to specify which kind of
+proxy is used. Use socks4://, socks4a://, socks5:// or socks5h:// (the last
+one to enable socks5 and asking the proxy to do the resolving, also known as
+\fICURLPROXY_SOCKS5_HOSTNAME\fP type) to request the specific SOCKS version to
+be used. No scheme specified or http://, will be treated as HTTP proxies.
+
+Without a scheme prefix, \fICURLOPT_PROXYTYPE(3)\fP can be used to specify
+which kind of proxy the string identifies.
+
+When you tell the library to use a HTTP proxy, libcurl will transparently
+convert operations to HTTP even if you specify an FTP URL etc. This may have
+an impact on what other features of the library you can use, such as
+\fICURLOPT_QUOTE(3)\fP and similar FTP specifics that don't work unless you
+tunnel through the HTTP proxy. Such tunneling is activated with
+\fICURLOPT_HTTPPROXYTUNNEL(3)\fP.
+
+libcurl respects the environment variables \fBhttp_proxy\fP, \fBftp_proxy\fP,
+\fBall_proxy\fP etc, if any of those are set. The \fICURLOPT_PROXY(3)\fP
+option does however override any possibly set environment variables.
+
+Setting the proxy string to "" (an empty string) will explicitly disable the
+use of a proxy, even if there is an environment variable set for it.
+
+A proxy host string can also include protocol scheme (http://) and embedded
+user + password.
+.SH DEFAULT
+Default is NULL, meaning no proxy is used.
+
+When you set a host name to use, do not assume that there's any particular
+single port number used widely for proxies. Specify it!
+.SH PROTOCOLS
+All except file://. Note that some protocols don't do very well over proxy.
+.SH EXAMPLE
+TODO
+.SH AVAILABILITY
+Since 7.14.1 the proxy environment variable names can include the protocol
+scheme.
+
+Since 7.21.7 the proxy string supports the socks protocols as "schemes".
+
+Since 7.50.2, unsupported schemes in proxy strings cause libcurl to return
+error.
+.SH RETURN VALUE
+Returns CURLE_OK if proxies are supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_PROXYPORT "(3), " CURLOPT_HTTPPROXYTUNNEL "(3), "
+.BR CURLOPT_PROXYTYPE "(3)"
diff --git a/docs/libcurl/opts/CURLOPT_SOCKS_PROXYTYPE.3 b/docs/libcurl/opts/CURLOPT_SOCKS_PROXYTYPE.3
new file mode 100644
index 00000000..21002406
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SOCKS_PROXYTYPE.3
@@ -0,0 +1,55 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_SOCKS_PROXYTYPE 3 "16 Nov 2016" "libcurl 7.52.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_SOCKS_PROXYTYPE \- socks proxy protocol type
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS_PROXYTYPE, long type);
+.SH DESCRIPTION
+TODO: Make this text specific to HTTPS proxy. (Added in 7.XXX)
+Pass a long with this option to set type of the proxy. Available options for
+this are \fICURLPROXY_HTTP\fP, \fICURLPROXY_HTTP_1_0\fP
+\fICURLPROXY_SOCKS4\fP, \fICURLPROXY_SOCKS5\fP, \fICURLPROXY_SOCKS4A\fP and
+\fICURLPROXY_SOCKS5_HOSTNAME\fP. The HTTP type is default.
+
+If you set \fICURLOPT_PROXYTYPE(3)\fP to \fICURLPROXY_HTTP_1_0\fP, it will
+only affect how libcurl speaks to a proxy when CONNECT is used. The HTTP
+version used for "regular" HTTP requests is instead controlled with
+\fICURLOPT_HTTP_VERSION(3)\fP.
+
+Often it is more convenient to specify the proxy type with the scheme part of
+the \fICURLOPT_PROXY(3)\fP string.
+.SH DEFAULT
+CURLPROXY_HTTP
+.SH PROTOCOLS
+Most
+.SH EXAMPLE
+TODO
+.SH AVAILABILITY
+Always
+.SH RETURN VALUE
+Returns CURLE_OK
+.SH "SEE ALSO"
+.BR CURLOPT_PROXY "(3), " CURLOPT_PROXYPORT "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_SSLVERSION.3 b/docs/libcurl/opts/CURLOPT_SSLVERSION.3
index 2f40e463..77dfcd49 100644
--- a/docs/libcurl/opts/CURLOPT_SSLVERSION.3
+++ b/docs/libcurl/opts/CURLOPT_SSLVERSION.3
@@ -48,6 +48,8 @@ TLSv1.0 (Added in 7.34.0)
TLSv1.1 (Added in 7.34.0)
.IP CURL_SSLVERSION_TLSv1_2
TLSv1.2 (Added in 7.34.0)
+.IP CURL_SSLVERSION_TLSv1_3
+TLSv1.3 (Added in 7.52.0)
.RE
.SH DEFAULT
CURL_SSLVERSION_DEFAULT
diff --git a/docs/libcurl/opts/CURLOPT_TCP_NODELAY.3 b/docs/libcurl/opts/CURLOPT_TCP_NODELAY.3
index efb25869..bd19fbaf 100644
--- a/docs/libcurl/opts/CURLOPT_TCP_NODELAY.3
+++ b/docs/libcurl/opts/CURLOPT_TCP_NODELAY.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -20,7 +20,7 @@
.\" *
.\" **************************************************************************
.\"
-.TH CURLOPT_TCP_NODELAY 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
+.TH CURLOPT_TCP_NODELAY 3 "30 Jun 2016" "libcurl 7.50.0" "curl_easy_setopt options"
.SH NAME
CURLOPT_TCP_NODELAY \- set the TCP_NODELAY option
.SH SYNOPSIS
@@ -29,8 +29,8 @@ CURLOPT_TCP_NODELAY \- set the TCP_NODELAY option
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_NODELAY, long nodelay);
.SH DESCRIPTION
Pass a long specifying whether the TCP_NODELAY option is to be set or cleared
-(1 = set, 0 = clear). The option is cleared by default. This will have no
-effect after the connection has been established.
+(1 = set, 0 = clear). The option is set by default. This will have no effect
+after the connection has been established.
Setting this option will disable TCP's Nagle algorithm. The purpose of this
algorithm is to try to minimize the number of small packets on the network
@@ -43,13 +43,13 @@ need to be sent without delay. This is less efficient than sending larger
amounts of data at a time, and can contribute to congestion on the network if
overdone.
.SH DEFAULT
-0
+1
.SH PROTOCOLS
All
.SH EXAMPLE
TODO
.SH AVAILABILITY
-Always
+Always. The default was changed to 1 from 0 in 7.50.2.
.SH RETURN VALUE
Returns CURLE_OK
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.3 b/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.3
index 299c3ccb..ed2b91b5 100644
--- a/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.3
+++ b/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -33,9 +33,9 @@ to \fIpath\fP. If \fIpath\fP is NULL, then Unix domain sockets are disabled. An
empty string will result in an error at some point, it will not disable use of
Unix domain sockets.
-When enabled, cURL will connect to the Unix domain socket instead of
+When enabled, curl will connect to the Unix domain socket instead of
establishing a TCP connection to a host. Since no TCP connection is created,
-cURL does not need to resolve the DNS hostname in the URL.
+curl does not need to resolve the DNS hostname in the URL.
The maximum path length on Cygwin, Linux and Solaris is 107. On other platforms
it might be even less.
diff --git a/docs/libcurl/opts/Makefile.am b/docs/libcurl/opts/Makefile.am
index a3fc0647..1ef4f2bc 100644
--- a/docs/libcurl/opts/Makefile.am
+++ b/docs/libcurl/opts/Makefile.am
@@ -49,6 +49,7 @@ man_MANS = \
CURLINFO_PRIMARY_IP.3 \
CURLINFO_PRIMARY_PORT.3 \
CURLINFO_PRIVATE.3 \
+ CURLINFO_PROXY_SSL_VERIFYRESULT.3 \
CURLINFO_PROXYAUTH_AVAIL.3 \
CURLINFO_REDIRECT_COUNT.3 \
CURLINFO_REDIRECT_TIME.3 \
@@ -170,6 +171,7 @@ man_MANS = \
CURLOPT_IOCTLFUNCTION.3 \
CURLOPT_IPRESOLVE.3 \
CURLOPT_ISSUERCERT.3 \
+ CURLOPT_KEEP_SENDING_ON_ERROR.3 \
CURLOPT_KEYPASSWD.3 \
CURLOPT_KRBLEVEL.3 \
CURLOPT_LOCALPORT.3 \
@@ -222,6 +224,24 @@ man_MANS = \
CURLOPT_PROXYUSERPWD.3 \
CURLOPT_PROXY_SERVICE_NAME.3 \
CURLOPT_PROXY_TRANSFER_MODE.3 \
+ CURLOPT_PROXY_CAINFO.3 \
+ CURLOPT_PROXY_CAPATH.3 \
+ CURLOPT_PROXY_CRLFILE.3 \
+ CURLOPT_PROXY_KEYPASSWD.3 \
+ CURLOPT_PROXY_SSLCERT.3 \
+ CURLOPT_PROXY_SSLCERTTYPE.3 \
+ CURLOPT_PROXY_SSLKEY.3 \
+ CURLOPT_PROXY_SSLKEYTYPE.3 \
+ CURLOPT_PROXY_SSLVERSION.3 \
+ CURLOPT_PROXY_SSL_CIPHER_LIST.3 \
+ CURLOPT_PROXY_SSL_OPTIONS.3 \
+ CURLOPT_PROXY_SSL_VERIFYHOST.3 \
+ CURLOPT_PROXY_SSL_VERIFYPEER.3 \
+ CURLOPT_PROXY_TLSAUTH_PASSWORD.3 \
+ CURLOPT_PROXY_TLSAUTH_TYPE.3 \
+ CURLOPT_PROXY_TLSAUTH_USERNAME.3 \
+ CURLOPT_SOCKS_PROXY.3 \
+ CURLOPT_SOCKS_PROXYTYPE.3 \
CURLOPT_PUT.3 \
CURLOPT_QUOTE.3 \
CURLOPT_RANDOM_FILE.3 \
@@ -457,6 +477,7 @@ HTMLPAGES = \
CURLOPT_IOCTLFUNCTION.html \
CURLOPT_IPRESOLVE.html \
CURLOPT_ISSUERCERT.html \
+ CURLOPT_KEEP_SENDING_ON_ERROR.html \
CURLOPT_KEYPASSWD.html \
CURLOPT_KRBLEVEL.html \
CURLOPT_LOCALPORT.html \
@@ -744,6 +765,7 @@ PDFPAGES = \
CURLOPT_IOCTLFUNCTION.pdf \
CURLOPT_IPRESOLVE.pdf \
CURLOPT_ISSUERCERT.pdf \
+ CURLOPT_KEEP_SENDING_ON_ERROR.pdf \
CURLOPT_KEYPASSWD.pdf \
CURLOPT_KRBLEVEL.pdf \
CURLOPT_LOCALPORT.pdf \
@@ -886,7 +908,7 @@ PDFPAGES = \
CLEANFILES = $(HTMLPAGES) $(PDFPAGES)
-EXTRA_DIST = $(man_MANS) $(HTMLPAGES) $(PDFPAGES)
+EXTRA_DIST = $(man_MANS)
MAN2HTML= roffit --mandir=. $< >$@
SUFFIXES = .3 .html
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
index d05a4690..0831775b 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
@@ -140,6 +140,7 @@ CURLE_UPLOAD_FAILED 7.16.3
CURLE_URL_MALFORMAT 7.1
CURLE_URL_MALFORMAT_USER 7.1 7.17.0
CURLE_USE_SSL_FAILED 7.17.0
+CURLE_WEIRD_SERVER_REPLY 7.51.0
CURLE_WRITE_ERROR 7.1
CURLFILETYPE_DEVICE_BLOCK 7.21.0
CURLFILETYPE_DEVICE_CHAR 7.21.0
@@ -238,7 +239,9 @@ CURLINFO_PRETRANSFER_TIME 7.4.1
CURLINFO_PRIMARY_IP 7.19.0
CURLINFO_PRIMARY_PORT 7.21.0
CURLINFO_PRIVATE 7.10.3
+CURLINFO_PROTOCOL 7.52.0
CURLINFO_PROXYAUTH_AVAIL 7.10.8
+CURLINFO_PROXY_SSL_VERIFYRESULT 7.52.0
CURLINFO_REDIRECT_COUNT 7.9.7
CURLINFO_REDIRECT_TIME 7.9.7
CURLINFO_REDIRECT_URL 7.18.2
@@ -248,6 +251,7 @@ CURLINFO_RTSP_CLIENT_CSEQ 7.20.0
CURLINFO_RTSP_CSEQ_RECV 7.20.0
CURLINFO_RTSP_SERVER_CSEQ 7.20.0
CURLINFO_RTSP_SESSION_ID 7.20.0
+CURLINFO_SCHEME 7.52.0
CURLINFO_SIZE_DOWNLOAD 7.4.1
CURLINFO_SIZE_UPLOAD 7.4.1
CURLINFO_SLIST 7.12.3
@@ -410,6 +414,7 @@ CURLOPT_IOCTLFUNCTION 7.12.3
CURLOPT_IPRESOLVE 7.10.8
CURLOPT_ISSUERCERT 7.19.0
CURLOPT_KEYPASSWD 7.17.0
+CURLOPT_KEEP_SENDING_ON_ERROR 7.51.0
CURLOPT_KRB4LEVEL 7.3 7.17.0
CURLOPT_KRBLEVEL 7.16.4
CURLOPT_LOCALPORT 7.15.2
@@ -466,7 +471,23 @@ CURLOPT_PROXYPORT 7.1
CURLOPT_PROXYTYPE 7.10
CURLOPT_PROXYUSERNAME 7.19.1
CURLOPT_PROXYUSERPWD 7.1
+CURLOPT_PROXY_CAINFO 7.52.0
+CURLOPT_PROXY_CAPATH 7.52.0
+CURLOPT_PROXY_CRLFILE 7.52.0
+CURLOPT_PROXY_KEYPASSWD 7.52.0
CURLOPT_PROXY_SERVICE_NAME 7.43.0
+CURLOPT_PROXY_SSLCERT 7.52.0
+CURLOPT_PROXY_SSLCERTTYPE 7.52.0
+CURLOPT_PROXY_SSLKEY 7.52.0
+CURLOPT_PROXY_SSLKEYTYPE 7.52.0
+CURLOPT_PROXY_SSLVERSION 7.52.0
+CURLOPT_PROXY_SSL_CIPHER_LIST 7.52.0
+CURLOPT_PROXY_SSL_OPTIONS 7.52.0
+CURLOPT_PROXY_SSL_VERIFYHOST 7.52.0
+CURLOPT_PROXY_SSL_VERIFYPEER 7.52.0
+CURLOPT_PROXY_TLSAUTH_PASSWORD 7.52.0
+CURLOPT_PROXY_TLSAUTH_TYPE 7.52.0
+CURLOPT_PROXY_TLSAUTH_USERNAME 7.52.0
CURLOPT_PROXY_TRANSFER_MODE 7.18.0
CURLOPT_PUT 7.1
CURLOPT_QUOTE 7.1
@@ -496,6 +517,8 @@ CURLOPT_SOCKOPTDATA 7.16.0
CURLOPT_SOCKOPTFUNCTION 7.16.0
CURLOPT_SOCKS5_GSSAPI_NEC 7.19.4
CURLOPT_SOCKS5_GSSAPI_SERVICE 7.19.4 7.49.0
+CURLOPT_SOCKS_PROXY 7.52.0
+CURLOPT_SOCKS_PROXYTYPE 7.52.0
CURLOPT_SOURCE_HOST 7.12.1 - 7.15.5
CURLOPT_SOURCE_PATH 7.12.1 - 7.15.5
CURLOPT_SOURCE_PORT 7.12.1 - 7.15.5
@@ -609,6 +632,7 @@ CURLPROTO_TELNET 7.19.4
CURLPROTO_TFTP 7.19.4
CURLPROXY_HTTP 7.10
CURLPROXY_HTTP_1_0 7.19.4
+CURLPROXY_HTTPS 7.52.0
CURLPROXY_SOCKS4 7.10
CURLPROXY_SOCKS4A 7.18.0
CURLPROXY_SOCKS5 7.10
@@ -763,6 +787,7 @@ CURL_SOCKET_TIMEOUT 7.14.0
CURL_SOCKOPT_ALREADY_CONNECTED 7.21.5
CURL_SOCKOPT_ERROR 7.21.5
CURL_SOCKOPT_OK 7.21.5
+CURL_STRICTER 7.50.2
CURL_SSLVERSION_DEFAULT 7.9.2
CURL_SSLVERSION_SSLv2 7.9.2
CURL_SSLVERSION_SSLv3 7.9.2
@@ -770,6 +795,7 @@ CURL_SSLVERSION_TLSv1 7.9.2
CURL_SSLVERSION_TLSv1_0 7.34.0
CURL_SSLVERSION_TLSv1_1 7.34.0
CURL_SSLVERSION_TLSv1_2 7.34.0
+CURL_SSLVERSION_TLSv1_3 7.52.0
CURL_TIMECOND_IFMODSINCE 7.9.7
CURL_TIMECOND_IFUNMODSINCE 7.9.7
CURL_TIMECOND_LASTMOD 7.9.7
diff --git a/docs/mk-ca-bundle.1 b/docs/mk-ca-bundle.1
index 017bb823..c8f5177e 100644
--- a/docs/mk-ca-bundle.1
+++ b/docs/mk-ca-bundle.1
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 2008 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 2008 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -20,18 +20,18 @@
.\" *
.\" **************************************************************************
.\"
-.TH mk-ca-bundle 1 "5 Jan 2013" "version 1.20" "mk-ca-bundle manual"
+.TH mk-ca-bundle 1 "24 Oct 2016" "version 1.27" "mk-ca-bundle manual"
.SH NAME
mk-ca-bundle \- convert mozilla's certdata.txt to PEM format
.SH SYNOPSIS
-mk-ca-bundle [bilnpqstuv]
+mk-ca-bundle [options]
.I [outputfile]
.SH DESCRIPTION
The mk-ca-bundle tool downloads the certdata.txt file from Mozilla's source
-tree over HTTP, then parses certdata.txt and extracts certificates
-into PEM format. By default, only CA root certificates trusted to issue SSL
-server authentication certificates are extracted. These are then processed with
-the OpenSSL commandline tool to produce the final ca-bundle file.
+tree over HTTPS, then parses certdata.txt and extracts certificates into PEM
+format. By default, only CA root certificates trusted to issue SSL server
+authentication certificates are extracted. These are then processed with the
+OpenSSL commandline tool to produce the final ca-bundle file.
The default \fIoutputfile\fP name is \fBca-bundle.crt\fP. By setting it to '-'
(a single dash) you will get the output sent to STDOUT instead of a file.
@@ -51,8 +51,17 @@ shortcuts for which source tree to get the cert data from.
force rebuild even if certdata.txt is current (Added in version 1.17)
.IP -i
print version info about used modules
+.IP -k
+Allow insecure data transfer. By default (since 1.27) this command will fail
+if the HTTPS transfer fails. This overrides that decision (and opens for
+man-in-the-middle attacks).
.IP -l
print license info about certdata.txt
+.IP -m
+(Added in 1.26) Include meta data comments in the output. The meta data is
+specific information about each certificate that is stored in the original
+file as comments and using this option will make those comments get passed on
+to the output file. The meta data is not parsed in any way by mk-ca-bundle.
.IP -n
no download of certdata.txt (to use existing)
.IP "-p [purposes]:[levels]"
diff --git a/include/README b/include/README
index 3e52a1d0..6eb73b2b 100644
--- a/include/README
+++ b/include/README
@@ -37,7 +37,7 @@ The following notes apply to libcurl version 7.19.0 and later.
also distribute along with it the generated curl/curlbuild.h which has been
used to compile it. Otherwise the library will be of no use for the users of
the library that you have built. It is _your_ responsibility to provide this
- file. No one at the cURL project can know how you have built the library.
+ file. No one at the curl project can know how you have built the library.
* File curl/curlbuild.h includes platform and configuration dependent info,
and must not be modified by anyone. Configure script generates it for you.
diff --git a/include/curl/curl.h b/include/curl/curl.h
index 7fd6d1fa..df2914e2 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -30,6 +30,10 @@
* https://cool.haxx.se/mailman/listinfo/curl-library/
*/
+#ifdef CURL_NO_OLDIES
+#define CURL_STRICTER
+#endif
+
#include "curlver.h" /* libcurl version defines */
#include "curlbuild.h" /* libcurl build definitions */
#include "curlrules.h" /* libcurl rules enforcement */
@@ -139,7 +143,7 @@ struct curl_httppost {
char *buffer; /* pointer to allocated buffer contents */
long bufferlength; /* length of buffer field */
char *contenttype; /* Content-Type */
- struct curl_slist* contentheader; /* list of extra headers for this form */
+ struct curl_slist *contentheader; /* list of extra headers for this form */
struct curl_httppost *more; /* if one field name has more than one
file, this link should link to following
files */
@@ -266,7 +270,7 @@ struct curl_fileinfo {
unsigned int flags;
/* used internally */
- char * b_data;
+ char *b_data;
size_t b_size;
size_t b_used;
};
@@ -431,7 +435,7 @@ typedef enum {
CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
CURLE_COULDNT_RESOLVE_HOST, /* 6 */
CURLE_COULDNT_CONNECT, /* 7 */
- CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */
+ CURLE_WEIRD_SERVER_REPLY, /* 8 */
CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server
due to lack of access - when login fails
this is not returned. */
@@ -562,6 +566,7 @@ typedef enum {
/* compatibility with older names */
#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
+#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY
/* The following were added in 7.21.5, April 2011 */
#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
@@ -635,6 +640,7 @@ typedef enum {
CONNECT HTTP/1.1 */
CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT
HTTP/1.0 */
+ CURLPROXY_HTTPS = 2, /* added in TBD */
CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
in 7.10 */
CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
@@ -1201,7 +1207,8 @@ typedef enum {
CINIT(SHARE, OBJECTPOINT, 100),
/* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
- CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
+ CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and
+ CURLPROXY_SOCKS5. */
CINIT(PROXYTYPE, LONG, 101),
/* Set the Accept-Encoding string. Use this to tell a server you would like
@@ -1695,6 +1702,74 @@ typedef enum {
/* Set TCP Fast Open */
CINIT(TCP_FASTOPEN, LONG, 244),
+ /* Continue to send data if the server responds early with an
+ * HTTP status code >= 300 */
+ CINIT(KEEP_SENDING_ON_ERROR, LONG, 245),
+
+ /* The CApath or CAfile used to validate the proxy certificate
+ this option is used only if PROXY_SSL_VERIFYPEER is true */
+ CINIT(PROXY_CAINFO, STRINGPOINT, 246),
+
+ /* The CApath directory used to validate the proxy certificate
+ this option is used only if PROXY_SSL_VERIFYPEER is true */
+ CINIT(PROXY_CAPATH, STRINGPOINT, 247),
+
+ /* Set if we should verify the proxy in ssl handshake,
+ set 1 to verify. */
+ CINIT(PROXY_SSL_VERIFYPEER, LONG, 248),
+
+ /* Set if we should verify the Common name from the proxy certificate in ssl
+ * handshake, set 1 to check existence, 2 to ensure that it matches
+ * the provided hostname. */
+ CINIT(PROXY_SSL_VERIFYHOST, LONG, 249),
+
+ /* What version to specifically try to use for proxy.
+ See CURL_SSLVERSION defines below. */
+ CINIT(PROXY_SSLVERSION, LONG, 250),
+
+ /* Set a username for authenticated TLS for proxy */
+ CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251),
+
+ /* Set a password for authenticated TLS for proxy */
+ CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252),
+
+ /* Set authentication type for authenticated TLS for proxy */
+ CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253),
+
+ /* name of the file keeping your private SSL-certificate for proxy */
+ CINIT(PROXY_SSLCERT, STRINGPOINT, 254),
+
+ /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for
+ proxy */
+ CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255),
+
+ /* name of the file keeping your private SSL-key for proxy */
+ CINIT(PROXY_SSLKEY, STRINGPOINT, 256),
+
+ /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for
+ proxy */
+ CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257),
+
+ /* password for the SSL private key for proxy */
+ CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258),
+
+ /* Specify which SSL ciphers to use for proxy */
+ CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259),
+
+ /* CRL file for proxy */
+ CINIT(PROXY_CRLFILE, STRINGPOINT, 260),
+
+ /* Enable/disable specific SSL features with a bitmask for proxy, see
+ CURLSSLOPT_* */
+ CINIT(PROXY_SSL_OPTIONS, LONG, 261),
+
+ /* Name of socks proxy to use. */
+ CINIT(SOCKS_PROXY, STRINGPOINT, 262),
+
+ /* indicates type of proxy. accepted values are CURLPROXY_SOCKS4,
+ CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
+ CINIT(SOCKS_PROXYTYPE, LONG, 263),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -1796,6 +1871,7 @@ enum {
CURL_SSLVERSION_TLSv1_0,
CURL_SSLVERSION_TLSv1_1,
CURL_SSLVERSION_TLSv1_2,
+ CURL_SSLVERSION_TLSv1_3,
CURL_SSLVERSION_LAST /* never use, keep last */
};
@@ -2200,9 +2276,12 @@ typedef enum {
CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44,
CURLINFO_TLS_SSL_PTR = CURLINFO_SLIST + 45,
CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46,
+ CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47,
+ CURLINFO_PROTOCOL = CURLINFO_LONG + 48,
+ CURLINFO_SCHEME = CURLINFO_STRING + 49,
/* Fill in new entries below here! */
- CURLINFO_LASTONE = 46
+ CURLINFO_LASTONE = 49
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
diff --git a/include/curl/curlver.h b/include/curl/curlver.h
index 81563f22..10f07d93 100644
--- a/include/curl/curlver.h
+++ b/include/curl/curlver.h
@@ -30,13 +30,13 @@
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "7.50.1-DEV"
+#define LIBCURL_VERSION "7.52.0-DEV"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 50
-#define LIBCURL_VERSION_PATCH 1
+#define LIBCURL_VERSION_MINOR 52
+#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
@@ -57,7 +57,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
-#define LIBCURL_VERSION_NUM 0x073201
+#define LIBCURL_VERSION_NUM 0x073400
/*
* This is the date and time when the full source package was created. The
diff --git a/include/curl/easy.h b/include/curl/easy.h
index afc766cd..752c5049 100644
--- a/include/curl/easy.h
+++ b/include/curl/easy.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -58,7 +58,7 @@ CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
* curl_easy_duphandle() for each new thread to avoid a series of identical
* curl_easy_setopt() invokes in every thread.
*/
-CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl);
+CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl);
/*
* NAME curl_easy_reset()
diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h
index 6ec8bcfd..d20c192d 100644
--- a/include/curl/typecheck-gcc.h
+++ b/include/curl/typecheck-gcc.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -151,7 +151,7 @@ _CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
"curl_easy_setopt expects a curl_off_t argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_string,
"curl_easy_setopt expects a "
- "string (char* or char[]) argument for this option"
+ "string ('char *' or char[]) argument for this option"
)
_CURL_WARNING(_curl_easy_setopt_err_write_callback,
"curl_easy_setopt expects a curl_write_callback argument for this option")
@@ -182,24 +182,25 @@ _CURL_WARNING(_curl_easy_setopt_err_error_buffer,
"curl_easy_setopt expects a "
"char buffer of CURL_ERROR_SIZE as argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_FILE,
- "curl_easy_setopt expects a FILE* argument for this option")
+ "curl_easy_setopt expects a 'FILE *' argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_postfields,
- "curl_easy_setopt expects a void* or char* argument for this option")
+ "curl_easy_setopt expects a 'void *' or 'char *' argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
- "curl_easy_setopt expects a struct curl_httppost* argument for this option")
+ "curl_easy_setopt expects a 'struct curl_httppost *' "
+ "argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_curl_slist,
- "curl_easy_setopt expects a struct curl_slist* argument for this option")
+ "curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
"curl_easy_setopt expects a CURLSH* argument for this option")
_CURL_WARNING(_curl_easy_getinfo_err_string,
- "curl_easy_getinfo expects a pointer to char * for this info")
+ "curl_easy_getinfo expects a pointer to 'char *' for this info")
_CURL_WARNING(_curl_easy_getinfo_err_long,
"curl_easy_getinfo expects a pointer to long for this info")
_CURL_WARNING(_curl_easy_getinfo_err_double,
"curl_easy_getinfo expects a pointer to double for this info")
_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
- "curl_easy_getinfo expects a pointer to struct curl_slist * for this info")
+ "curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
/* groups of curl_easy_setops options that take the same type of argument */
@@ -363,7 +364,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
/* XXX: should evaluate to true iff expr is a pointer */
#define _curl_is_any_ptr(expr) \
- (sizeof(expr) == sizeof(void*))
+ (sizeof(expr) == sizeof(void *))
/* evaluates to true if expr is NULL */
/* XXX: must not evaluate expr, so this check is not accurate */
@@ -455,12 +456,12 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
_curl_callback_compatible((expr), _curl_read_callback4) || \
_curl_callback_compatible((expr), _curl_read_callback5) || \
_curl_callback_compatible((expr), _curl_read_callback6))
-typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*);
-typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*);
-typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*);
-typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*);
-typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*);
-typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*);
+typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void *);
+typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void *);
+typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE *);
+typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void *);
+typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void *);
+typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE *);
/* evaluates to true if expr is of type curl_write_callback or "similar" */
#define _curl_is_write_cb(expr) \
@@ -473,14 +474,14 @@ typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*);
_curl_callback_compatible((expr), _curl_write_callback4) || \
_curl_callback_compatible((expr), _curl_write_callback5) || \
_curl_callback_compatible((expr), _curl_write_callback6))
-typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*);
+typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void *);
typedef size_t (_curl_write_callback2)(const char *, size_t, size_t,
- const void*);
-typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*);
-typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*);
+ const void *);
+typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE *);
+typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void *);
typedef size_t (_curl_write_callback5)(const void *, size_t, size_t,
- const void*);
-typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*);
+ const void *);
+typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE *);
/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
#define _curl_is_ioctl_cb(expr) \
@@ -490,10 +491,10 @@ typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*);
_curl_callback_compatible((expr), _curl_ioctl_callback2) || \
_curl_callback_compatible((expr), _curl_ioctl_callback3) || \
_curl_callback_compatible((expr), _curl_ioctl_callback4))
-typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*);
-typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*);
-typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*);
-typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*);
+typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void *);
+typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void *);
+typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void *);
+typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
#define _curl_is_sockopt_cb(expr) \
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 49a34093..eb2de6d8 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -87,6 +87,11 @@ endif()
set_target_properties(${LIB_NAME} PROPERTIES COMPILE_DEFINITIONS BUILDING_LIBCURL)
+if(HIDES_CURL_PRIVATE_SYMBOLS)
+ set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
+ set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE})
+endif()
+
# Remove the "lib" prefix since the library is already named "libcurl".
set_target_properties(${LIB_NAME} PROPERTIES PREFIX "")
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "")
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index 0ed998c1..19f58000 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -40,31 +40,31 @@ LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \
LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \
ldap.c version.c getenv.c escape.c mprintf.c telnet.c netrc.c \
- getinfo.c transfer.c strequal.c easy.c security.c curl_fnmatch.c \
+ getinfo.c transfer.c strcase.c easy.c security.c curl_fnmatch.c \
fileinfo.c ftplistparser.c wildcard.c krb5.c memdebug.c http_chunks.c \
strtok.c connect.c llist.c hash.c multi.c content_encoding.c share.c \
http_digest.c md4.c md5.c http_negotiate.c inet_pton.c strtoofft.c \
strerror.c amigaos.c hostasyn.c hostip4.c hostip6.c hostsyn.c \
inet_ntop.c parsedate.c select.c tftp.c splay.c strdup.c socks.c \
- ssh.c rawstr.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \
+ ssh.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \
curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.c \
pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c \
openldap.c curl_gethostname.c gopher.c idn_win32.c \
http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c \
- http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c \
+ http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c \
curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c \
x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c
LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \
speedcheck.h urldata.h curl_ldap.h escape.h telnet.h getinfo.h \
- strequal.h curl_sec.h memdebug.h http_chunks.h curl_fnmatch.h \
+ strcase.h curl_sec.h memdebug.h http_chunks.h curl_fnmatch.h \
wildcard.h fileinfo.h ftplistparser.h strtok.h connect.h llist.h \
hash.h content_encoding.h share.h curl_md4.h curl_md5.h http_digest.h \
http_negotiate.h inet_pton.h amigaos.h strtoofft.h strerror.h \
inet_ntop.h curlx.h curl_memory.h curl_setup.h transfer.h select.h \
easyif.h multiif.h parsedate.h tftp.h sockaddr.h splay.h strdup.h \
- socks.h ssh.h curl_base64.h rawstr.h curl_addrinfo.h curl_sspi.h \
+ socks.h ssh.h curl_base64.h curl_addrinfo.h curl_sspi.h \
slist.h nonblock.h curl_memrchr.h imap.h pop3.h smtp.h pingpong.h \
rtsp.h curl_threads.h warnless.h curl_hmac.h curl_rtmp.h \
curl_gethostname.h gopher.h http_proxy.h non-ascii.h asyn.h \
@@ -72,7 +72,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
curl_sasl.h curl_multibyte.h hostcheck.h conncache.h \
curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h \
x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \
- curl_printf.h system_win32.h
+ curl_printf.h system_win32.h rand.h
LIB_RCFILES = libcurl.rc
diff --git a/lib/Makefile.netware b/lib/Makefile.netware
index ee7e87ce..f689a36f 100644
--- a/lib/Makefile.netware
+++ b/lib/Makefile.netware
@@ -87,7 +87,7 @@ endif
TARGET = libcurl
VERSION = $(LIBCURL_VERSION)
COPYR = Copyright (C) $(LIBCURL_COPYRIGHT_STR)
-DESCR = cURL libcurl $(LIBCURL_VERSION_STR) ($(LIBARCH)) - https://curl.haxx.se
+DESCR = curl libcurl $(LIBCURL_VERSION_STR) ($(LIBARCH)) - https://curl.haxx.se
MTSAFE = YES
STACK = 64000
SCREEN = none
diff --git a/lib/Makefile.vc6 b/lib/Makefile.vc6
index e783e3ae..d028428a 100644
--- a/lib/Makefile.vc6
+++ b/lib/Makefile.vc6
@@ -601,7 +601,8 @@ X_OBJS= \
$(DIROBJ)\polarssl_threadlock.obj \
$(DIROBJ)\pop3.obj \
$(DIROBJ)\progress.obj \
- $(DIROBJ)\rawstr.obj \
+ $(DIROBJ)\strcase.obj \
+ $(DIROBJ)\rand.obj \
$(DIROBJ)\rtsp.obj \
$(DIROBJ)\schannel.obj \
$(DIROBJ)\security.obj \
@@ -633,7 +634,6 @@ X_OBJS= \
$(DIROBJ)\vtls.obj \
$(DIROBJ)\openssl.obj \
$(DIROBJ)\strdup.obj \
- $(DIROBJ)\strequal.obj \
$(DIROBJ)\strerror.obj \
$(DIROBJ)\strtok.obj \
$(DIROBJ)\strtoofft.obj \
diff --git a/lib/amigaos.c b/lib/amigaos.c
index 5591d222..4f55b30e 100644
--- a/lib/amigaos.c
+++ b/lib/amigaos.c
@@ -57,7 +57,7 @@ bool Curl_amiga_init()
}
if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno,
- SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "cURL",
+ SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "curl",
TAG_DONE)) {
__request("SocketBaseTags ERROR");
return FALSE;
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index 7cce01aa..da444f09 100644
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -155,8 +155,8 @@ struct thread_sync_data {
curl_mutex_t * mtx;
int done;
- char * hostname; /* hostname to resolve, Curl_async.hostname
- duplicate */
+ char *hostname; /* hostname to resolve, Curl_async.hostname
+ duplicate */
int port;
int sock_error;
Curl_addrinfo *res;
@@ -169,7 +169,7 @@ struct thread_sync_data {
struct thread_data {
curl_thread_t thread_hnd;
unsigned int poll_interval;
- long interval_end;
+ time_t interval_end;
struct thread_sync_data tsd;
};
@@ -200,7 +200,7 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd)
/* Initialize resolver thread synchronization data */
static
int init_thread_sync_data(struct thread_data * td,
- const char * hostname,
+ const char *hostname,
int port,
const struct addrinfo *hints)
{
@@ -382,7 +382,7 @@ static bool init_resolve_thread (struct connectdata *conn,
struct thread_data *td = calloc(1, sizeof(struct thread_data));
int err = RESOLVER_ENOMEM;
- conn->async.os_specific = (void*) td;
+ conn->async.os_specific = (void *)td;
if(!td)
goto err_exit;
@@ -525,7 +525,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
}
else {
/* poll for name lookup done with exponential backoff up to 250ms */
- long elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
+ time_t elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
if(elapsed < 0)
elapsed = 0;
diff --git a/lib/base64.c b/lib/base64.c
index ad254595..204a2273 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -190,6 +190,11 @@ static CURLcode base64_encode(const char *table64,
if(!insize)
insize = strlen(indata);
+#if SIZEOF_SIZE_T == 4
+ if(insize > UINT_MAX/4)
+ return CURLE_OUT_OF_MEMORY;
+#endif
+
base64data = output = malloc(insize * 4 / 3 + 4);
if(!output)
return CURLE_OUT_OF_MEMORY;
diff --git a/lib/checksrc.pl b/lib/checksrc.pl
index f31083a6..479a5dbd 100755
--- a/lib/checksrc.pl
+++ b/lib/checksrc.pl
@@ -55,7 +55,9 @@ my %warnings = (
'COPYRIGHT' => 'file missing a copyright statement',
'BADCOMMAND' => 'bad !checksrc! instruction',
'UNUSEDIGNORE' => 'a warning ignore was not used',
- 'OPENCOMMENT' => 'file ended with a /* comment still "open"'
+ 'OPENCOMMENT' => 'file ended with a /* comment still "open"',
+ 'ASTERISKSPACE' => 'pointer declared with space after asterisk',
+ 'ASTERISKNOSPACE' => 'pointer declared without space before asterisk'
);
sub readwhitelist {
@@ -423,6 +425,7 @@ sub scanfile {
# scan for use of banned functions
if($l =~ /^(.*\W)
(gets|
+ strtok|
v?sprintf|
(str|_mbs|_tcs|_wcs)n?cat|
LoadLibrary(Ex)?(A|W)?)
@@ -470,6 +473,31 @@ sub scanfile {
}
}
+ # check for 'char * name'
+ if(($l =~ /(^.*(char|int|long|void|curl_slist|CURL|CURLM|CURLMsg|curl_httppost) *(\*+)) (\w+)/) && ($4 ne "const")) {
+ checkwarn("ASTERISKNOSPACE",
+ $line, length($1), $file, $ol,
+ "no space after declarative asterisk");
+ }
+ # check for 'char*'
+ if(($l =~ /(^.*(char|int|long|void|curl_slist|CURL|CURLM|CURLMsg|curl_httppost|sockaddr_in|FILE)\*)/)) {
+ checkwarn("ASTERISKNOSPACE",
+ $line, length($1)-1, $file, $ol,
+ "no space before asterisk");
+ }
+
+ # check for 'void func() {', but avoid false positives by requiring
+ # both an open and closed parentheses before the open brace
+ if($l =~ /^((\w).*){\z/) {
+ my $k = $1;
+ $k =~ s/const *//;
+ $k =~ s/static *//;
+ if($k =~ /\(.*\)/) {
+ checkwarn("BRACEPOS",
+ $line, length($l)-1, $file, $ol,
+ "wrongly placed open brace");
+ }
+ }
$line++;
$prevl = $ol;
}
diff --git a/lib/config-symbian.h b/lib/config-symbian.h
index 2603a46b..92983d24 100644
--- a/lib/config-symbian.h
+++ b/lib/config-symbian.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -676,7 +676,7 @@
/*#define RANDOM_FILE "/dev/urandom"*/
#define RECV_TYPE_ARG1 int
-#define RECV_TYPE_ARG2 void*
+#define RECV_TYPE_ARG2 void *
#define RECV_TYPE_ARG3 size_t
#define RECV_TYPE_ARG4 int
#define RECV_TYPE_RETV ssize_t
@@ -692,7 +692,7 @@
#define SEND_TYPE_ARG1 int
#define SEND_QUAL_ARG2 const
-#define SEND_TYPE_ARG2 void*
+#define SEND_TYPE_ARG2 void *
#define SEND_TYPE_ARG3 size_t
#define SEND_TYPE_ARG4 int
#define SEND_TYPE_RETV ssize_t
diff --git a/lib/conncache.c b/lib/conncache.c
index 32a70303..d8ef9a54 100644
--- a/lib/conncache.c
+++ b/lib/conncache.c
@@ -30,7 +30,6 @@
#include "progress.h"
#include "multiif.h"
#include "sendf.h"
-#include "rawstr.h"
#include "conncache.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -133,8 +132,10 @@ static char *hashkey(struct connectdata *conn)
{
const char *hostname;
- if(conn->bits.proxy)
- hostname = conn->proxy.name;
+ if(conn->bits.socksproxy)
+ hostname = conn->socks_proxy.host.name;
+ else if(conn->bits.httpproxy)
+ hostname = conn->http_proxy.host.name;
else if(conn->bits.conn_to_host)
hostname = conn->conn_to_host.name;
else
diff --git a/lib/connect.c b/lib/connect.c
index 0047f9a0..c78d3da3 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -179,12 +179,12 @@ singleipconnect(struct connectdata *conn,
*
* @unittest: 1303
*/
-long Curl_timeleft(struct Curl_easy *data,
- struct timeval *nowp,
- bool duringconnect)
+time_t Curl_timeleft(struct Curl_easy *data,
+ struct timeval *nowp,
+ bool duringconnect)
{
int timeout_set = 0;
- long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
+ time_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
struct timeval now;
/* if a timeout is set, use the most restrictive one */
@@ -601,26 +601,28 @@ void Curl_persistconninfo(struct connectdata *conn)
{
memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
+ conn->data->info.conn_scheme = conn->handler->scheme;
+ conn->data->info.conn_protocol = conn->handler->protocol;
conn->data->info.conn_primary_port = conn->primary_port;
conn->data->info.conn_local_port = conn->local_port;
}
/* retrieves ip address and port from a sockaddr structure */
-static bool getaddressinfo(struct sockaddr* sa, char* addr,
- long* port)
+static bool getaddressinfo(struct sockaddr *sa, char *addr,
+ long *port)
{
unsigned short us_port;
- struct sockaddr_in* si = NULL;
+ struct sockaddr_in *si = NULL;
#ifdef ENABLE_IPV6
- struct sockaddr_in6* si6 = NULL;
+ struct sockaddr_in6 *si6 = NULL;
#endif
#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
- struct sockaddr_un* su = NULL;
+ struct sockaddr_un *su = NULL;
#endif
switch (sa->sa_family) {
case AF_INET:
- si = (struct sockaddr_in*)(void*) sa;
+ si = (struct sockaddr_in *)(void *) sa;
if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
addr, MAX_IPADR_LEN)) {
us_port = ntohs(si->sin_port);
@@ -630,7 +632,7 @@ static bool getaddressinfo(struct sockaddr* sa, char* addr,
break;
#ifdef ENABLE_IPV6
case AF_INET6:
- si6 = (struct sockaddr_in6*)(void*) sa;
+ si6 = (struct sockaddr_in6 *)(void *) sa;
if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
addr, MAX_IPADR_LEN)) {
us_port = ntohs(si6->sin6_port);
@@ -722,7 +724,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
{
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
- long allow;
+ time_t allow;
int error = 0;
struct timeval now;
int rc;
@@ -762,7 +764,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
#endif
/* check socket for connect */
- rc = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
+ rc = SOCKET_WRITABLE(conn->tempsock[i], 0);
if(rc == 0) { /* no connection yet */
error = 0;
@@ -843,7 +845,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
if(result) {
/* no more addresses to try */
- const char* hostname;
+ const char *hostname;
/* if the first address family runs out of addresses to try before
the happy eyeball timeout, go ahead and try the next family now */
@@ -853,8 +855,10 @@ CURLcode Curl_is_connected(struct connectdata *conn,
return result;
}
- if(conn->bits.proxy)
- hostname = conn->proxy.name;
+ if(conn->bits.socksproxy)
+ hostname = conn->socks_proxy.host.name;
+ else if(conn->bits.httpproxy)
+ hostname = conn->http_proxy.host.name;
else if(conn->bits.conn_to_host)
hostname = conn->conn_to_host.name;
else
@@ -1153,7 +1157,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
struct timeval before = Curl_tvnow();
CURLcode result = CURLE_COULDNT_CONNECT;
- long timeout_ms = Curl_timeleft(data, &before, TRUE);
+ time_t timeout_ms = Curl_timeleft(data, &before, TRUE);
if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */
@@ -1368,25 +1372,26 @@ CURLcode Curl_socket(struct connectdata *conn,
}
-#ifdef CURLDEBUG
/*
- * Curl_conncontrol() is used to set the conn->bits.close bit on or off. It
- * MUST be called with the connclose() or connkeep() macros with a stated
- * reason. The reason is only shown in debug builds but helps to figure out
- * decision paths when connections are or aren't re-used as expected.
+ * Curl_conncontrol() marks streams or connection for closure.
*/
-void Curl_conncontrol(struct connectdata *conn, bool closeit,
- const char *reason)
-{
-#if defined(CURL_DISABLE_VERBOSE_STRINGS)
- (void) reason;
+void Curl_conncontrol(struct connectdata *conn,
+ int ctrl /* see defines in header */
+#ifdef DEBUGBUILD
+ , const char *reason
#endif
- if(closeit != conn->bits.close) {
- infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive",
- reason);
-
+ )
+{
+ /* close if a connection, or a stream that isn't multiplexed */
+ bool closeit = (ctrl == CONNCTRL_CONNECTION) ||
+ ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
+ if((ctrl == CONNCTRL_STREAM) &&
+ (conn->handler->flags & PROTOPT_STREAM))
+ DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));
+ else if(closeit != conn->bits.close) {
+ DEBUGF(infof(conn->data, "Marked for [%s]: %s\n",
+ closeit?"closure":"keep alive", reason));
conn->bits.close = closeit; /* the only place in the source code that
should assign this bit */
}
}
-#endif
diff --git a/lib/connect.h b/lib/connect.h
index 6d60e0d8..5e48eb64 100644
--- a/lib/connect.h
+++ b/lib/connect.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,9 +35,9 @@ CURLcode Curl_connecthost(struct connectdata *conn,
/* generic function that returns how much time there's left to run, according
to the timeouts set */
-long Curl_timeleft(struct Curl_easy *data,
- struct timeval *nowp,
- bool duringconnect);
+time_t Curl_timeleft(struct Curl_easy *data,
+ struct timeval *nowp,
+ bool duringconnect);
#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
#define HAPPY_EYEBALLS_TIMEOUT 200 /* milliseconds to wait between
@@ -104,21 +104,37 @@ CURLcode Curl_socket(struct connectdata *conn,
void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd);
-#ifdef CURLDEBUG
/*
- * Curl_connclose() sets the bit.close bit to TRUE with an explanation.
- * Nothing else.
+ * Curl_conncontrol() marks the end of a connection/stream. The 'closeit'
+ * argument specifies if it is the end of a connection or a stream.
+ *
+ * For stream-based protocols (such as HTTP/2), a stream close will not cause
+ * a connection close. Other protocols will close the connection for both
+ * cases.
+ *
+ * It sets the bit.close bit to TRUE (with an explanation for debug builds),
+ * when the connection will close.
*/
-void Curl_conncontrol(struct connectdata *conn,
- bool closeit,
- const char *reason);
-#define connclose(x,y) Curl_conncontrol(x,TRUE, y)
-#define connkeep(x,y) Curl_conncontrol(x, FALSE, y)
-#else /* if !CURLDEBUG */
-#define connclose(x,y) (x)->bits.close = TRUE
-#define connkeep(x,y) (x)->bits.close = FALSE
+#define CONNCTRL_KEEP 0 /* undo a marked closure */
+#define CONNCTRL_CONNECTION 1
+#define CONNCTRL_STREAM 2
+void Curl_conncontrol(struct connectdata *conn,
+ int closeit
+#ifdef DEBUGBUILD
+ , const char *reason
+#endif
+ );
+
+#ifdef DEBUGBUILD
+#define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM, y)
+#define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION, y)
+#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP, y)
+#else /* if !CURLDEBUG */
+#define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM)
+#define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION)
+#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP)
#endif
#endif /* HEADER_CURL_CONNECT_H */
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
index fa36aca4..5a5824db 100644
--- a/lib/content_encoding.c
+++ b/lib/content_encoding.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -28,8 +28,8 @@
#include <curl/curl.h>
#include "sendf.h"
#include "content_encoding.h"
+#include "strdup.h"
#include "curl_memory.h"
-
#include "memdebug.h"
/* Comment this out if zlib is always going to be at least ver. 1.2.0.4
@@ -371,12 +371,9 @@ Curl_unencode_gzip_write(struct connectdata *conn,
{
/* Need more gzip header data state */
ssize_t hlen;
- unsigned char *oldblock = z->next_in;
-
z->avail_in += (uInt)nread;
- z->next_in = realloc(z->next_in, z->avail_in);
+ z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
if(z->next_in == NULL) {
- free(oldblock);
return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
}
/* Append the new block of data to the previous one */
diff --git a/lib/cookie.c b/lib/cookie.c
index b06a1398..31238516 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -89,13 +89,12 @@ Example set of cookies:
#include "urldata.h"
#include "cookie.h"
-#include "strequal.h"
#include "strtok.h"
#include "sendf.h"
#include "slist.h"
#include "share.h"
#include "strtoofft.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "curl_memrchr.h"
#include "inet_pton.h"
@@ -125,7 +124,7 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
if(hostname_len < cookie_domain_len)
return FALSE;
- if(!Curl_raw_equal(cooke_domain, hostname+hostname_len-cookie_domain_len))
+ if(!strcasecompare(cooke_domain, hostname+hostname_len-cookie_domain_len))
return FALSE;
/* A lead char of cookie_domain is not '.'.
@@ -146,12 +145,12 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
* matching cookie path and url path
* RFC6265 5.1.4 Paths and Path-Match
*/
-static bool pathmatch(const char* cookie_path, const char* request_uri)
+static bool pathmatch(const char *cookie_path, const char *request_uri)
{
size_t cookie_path_len;
size_t uri_path_len;
- char* uri_path = NULL;
- char* pos;
+ char *uri_path = NULL;
+ char *pos;
bool ret = FALSE;
/* cookie_path must not have last '/' separator. ex: /sample */
@@ -468,9 +467,9 @@ Curl_cookie_add(struct Curl_easy *data,
/* this was a "<name>=" with no content, and we must allow
'secure' and 'httponly' specified this weirdly */
done = TRUE;
- if(Curl_raw_equal("secure", name))
+ if(strcasecompare("secure", name))
co->secure = TRUE;
- else if(Curl_raw_equal("httponly", name))
+ else if(strcasecompare("httponly", name))
co->httponly = TRUE;
else if(sep)
/* there was a '=' so we're not done parsing this field */
@@ -478,7 +477,7 @@ Curl_cookie_add(struct Curl_easy *data,
}
if(done)
;
- else if(Curl_raw_equal("path", name)) {
+ else if(strcasecompare("path", name)) {
strstore(&co->path, whatptr);
if(!co->path) {
badcookie = TRUE; /* out of memory bad */
@@ -490,7 +489,7 @@ Curl_cookie_add(struct Curl_easy *data,
break;
}
}
- else if(Curl_raw_equal("domain", name)) {
+ else if(strcasecompare("domain", name)) {
bool is_ip;
const char *dotp;
@@ -528,14 +527,14 @@ Curl_cookie_add(struct Curl_easy *data,
whatptr);
}
}
- else if(Curl_raw_equal("version", name)) {
+ else if(strcasecompare("version", name)) {
strstore(&co->version, whatptr);
if(!co->version) {
badcookie = TRUE;
break;
}
}
- else if(Curl_raw_equal("max-age", name)) {
+ else if(strcasecompare("max-age", name)) {
/* Defined in RFC2109:
Optional. The Max-Age attribute defines the lifetime of the
@@ -551,7 +550,7 @@ Curl_cookie_add(struct Curl_easy *data,
break;
}
}
- else if(Curl_raw_equal("expires", name)) {
+ else if(strcasecompare("expires", name)) {
strstore(&co->expirestr, whatptr);
if(!co->expirestr) {
badcookie = TRUE;
@@ -712,7 +711,7 @@ Curl_cookie_add(struct Curl_easy *data,
As far as I can see, it is set to true when the cookie says
.domain.com and to false when the domain is complete www.domain.com
*/
- co->tailmatch = Curl_raw_equal(ptr, "TRUE")?TRUE:FALSE;
+ co->tailmatch = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
break;
case 2:
/* It turns out, that sometimes the file format allows the path
@@ -741,7 +740,7 @@ Curl_cookie_add(struct Curl_easy *data,
fields++; /* add a field and fall down to secure */
/* FALLTHROUGH */
case 3:
- co->secure = Curl_raw_equal(ptr, "TRUE")?TRUE:FALSE;
+ co->secure = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
break;
case 4:
co->expires = curlx_strtoofft(ptr, NULL, 10);
@@ -812,11 +811,12 @@ Curl_cookie_add(struct Curl_easy *data,
clist = c->cookies;
replace_old = FALSE;
while(clist) {
- if(Curl_raw_equal(clist->name, co->name)) {
+ if(strcasecompare(clist->name, co->name)) {
/* the names are identical */
if(clist->domain && co->domain) {
- if(Curl_raw_equal(clist->domain, co->domain))
+ if(strcasecompare(clist->domain, co->domain) &&
+ (clist->tailmatch == co->tailmatch))
/* The domains are identical */
replace_old=TRUE;
}
@@ -827,7 +827,7 @@ Curl_cookie_add(struct Curl_easy *data,
/* the domains were identical */
if(clist->spath && co->spath) {
- if(Curl_raw_equal(clist->spath, co->spath)) {
+ if(strcasecompare(clist->spath, co->spath)) {
replace_old = TRUE;
}
else
@@ -901,6 +901,35 @@ Curl_cookie_add(struct Curl_easy *data,
return co;
}
+/*
+ * get_line() makes sure to only return complete whole lines that fit in 'len'
+ * bytes and end with a newline.
+ */
+static char *get_line(char *buf, int len, FILE *input)
+{
+ bool partial = FALSE;
+ while(1) {
+ char *b = fgets(buf, len, input);
+ if(b) {
+ size_t rlen = strlen(b);
+ if(rlen && (b[rlen-1] == '\n')) {
+ if(partial) {
+ partial = FALSE;
+ continue;
+ }
+ return b;
+ }
+ else
+ /* read a partial, discard the next piece that ends with newline */
+ partial = TRUE;
+ }
+ else
+ break;
+ }
+ return NULL;
+}
+
+
/*****************************************************************************
*
* Curl_cookie_init()
@@ -937,7 +966,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
}
c->running = FALSE; /* this is not running, this is init */
- if(file && strequal(file, "-")) {
+ if(file && !strcmp(file, "-")) {
fp = stdin;
fromfile=FALSE;
}
@@ -957,7 +986,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
line = malloc(MAX_COOKIE_LINE);
if(!line)
goto fail;
- while(fgets(line, MAX_COOKIE_LINE, fp)) {
+ while(get_line(line, MAX_COOKIE_LINE, fp)) {
if(checkprefix("Set-Cookie:", line)) {
/* This is a cookie line, get it! */
lineptr=&line[11];
@@ -1022,6 +1051,40 @@ static int cookie_sort(const void *p1, const void *p2)
return 0;
}
+#define CLONE(field) \
+ do { \
+ if(src->field) { \
+ dup->field = strdup(src->field); \
+ if(!dup->field) \
+ goto fail; \
+ } \
+ } while(0)
+
+static struct Cookie *dup_cookie(struct Cookie *src)
+{
+ struct Cookie *dup = calloc(sizeof(struct Cookie), 1);
+ if(dup) {
+ CLONE(expirestr);
+ CLONE(domain);
+ CLONE(path);
+ CLONE(spath);
+ CLONE(name);
+ CLONE(value);
+ CLONE(maxage);
+ CLONE(version);
+ dup->expires = src->expires;
+ dup->tailmatch = src->tailmatch;
+ dup->secure = src->secure;
+ dup->livecookie = src->livecookie;
+ dup->httponly = src->httponly;
+ }
+ return dup;
+
+ fail:
+ freecookie(dup);
+ return NULL;
+}
+
/*****************************************************************************
*
* Curl_cookie_getlist()
@@ -1066,7 +1129,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
/* now check if the domain is correct */
if(!co->domain ||
(co->tailmatch && !is_ip && tailmatch(co->domain, host)) ||
- ((!co->tailmatch || is_ip) && Curl_raw_equal(host, co->domain)) ) {
+ ((!co->tailmatch || is_ip) && strcasecompare(host, co->domain)) ) {
/* the right part of the host matches the domain stuff in the
cookie data */
@@ -1077,11 +1140,8 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
/* and now, we know this is a match and we should create an
entry for the return-linked-list */
- newco = malloc(sizeof(struct Cookie));
+ newco = dup_cookie(co);
if(newco) {
- /* first, copy the whole source cookie: */
- memcpy(newco, co, sizeof(struct Cookie));
-
/* then modify our next */
newco->next = mainco;
@@ -1093,12 +1153,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
else {
fail:
/* failure, clear up the allocated chain and return NULL */
- while(mainco) {
- co = mainco->next;
- free(mainco);
- mainco = co;
- }
-
+ Curl_cookie_freelist(mainco);
return NULL;
}
}
@@ -1150,7 +1205,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
void Curl_cookie_clearall(struct CookieInfo *cookies)
{
if(cookies) {
- Curl_cookie_freelist(cookies->cookies, TRUE);
+ Curl_cookie_freelist(cookies->cookies);
cookies->cookies = NULL;
cookies->numcookies = 0;
}
@@ -1162,21 +1217,14 @@ void Curl_cookie_clearall(struct CookieInfo *cookies)
*
* Free a list of cookies previously returned by Curl_cookie_getlist();
*
- * The 'cookiestoo' argument tells this function whether to just free the
- * list or actually also free all cookies within the list as well.
- *
****************************************************************************/
-void Curl_cookie_freelist(struct Cookie *co, bool cookiestoo)
+void Curl_cookie_freelist(struct Cookie *co)
{
struct Cookie *next;
while(co) {
next = co->next;
- if(cookiestoo)
- freecookie(co);
- else
- free(co); /* we only free the struct since the "members" are all just
- pointed out in the main cookie list! */
+ freecookie(co);
co = next;
}
}
@@ -1231,7 +1279,7 @@ void Curl_cookie_cleanup(struct CookieInfo *c)
{
if(c) {
free(c->filename);
- Curl_cookie_freelist(c->cookies, TRUE);
+ Curl_cookie_freelist(c->cookies);
free(c); /* free the base struct as well */
}
}
@@ -1289,7 +1337,7 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
/* at first, remove expired cookies */
remove_expired(c);
- if(strequal("-", dumphere)) {
+ if(!strcmp("-", dumphere)) {
/* use stdout */
out = stdout;
use_stdout=TRUE;
diff --git a/lib/cookie.h b/lib/cookie.h
index cd7c54a2..a9a45785 100644
--- a/lib/cookie.h
+++ b/lib/cookie.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -82,7 +82,7 @@ struct Cookie *Curl_cookie_add(struct Curl_easy *data,
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *,
const char *, bool);
-void Curl_cookie_freelist(struct Cookie *cookies, bool cookiestoo);
+void Curl_cookie_freelist(struct Cookie *cookies);
void Curl_cookie_clearall(struct CookieInfo *cookies);
void Curl_cookie_clearsess(struct CookieInfo *cookies);
diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
index 65a414b6..33c15cb6 100644
--- a/lib/curl_config.h.cmake
+++ b/lib/curl_config.h.cmake
@@ -67,7 +67,7 @@
#cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1
/* to make a symbol visible */
-#cmakedefine CURL_EXTERN_SYMBOL 1
+#cmakedefine CURL_EXTERN_SYMBOL ${CURL_EXTERN_SYMBOL}
/* Ensure using CURL_EXTERN_SYMBOL is possible */
#ifndef CURL_EXTERN_SYMBOL
#define CURL_EXTERN_SYMBOL
@@ -906,6 +906,9 @@
/* Define if you want to enable POSIX threaded DNS lookup */
#cmakedefine USE_THREADS_POSIX 1
+/* Define if you want to enable WIN32 threaded DNS lookup */
+#cmakedefine USE_THREADS_WIN32 1
+
/* Define to disable non-blocking sockets. */
#cmakedefine USE_BLOCKING_SOCKETS 1
@@ -933,11 +936,13 @@
/* if OpenSSL is in use */
#cmakedefine USE_OPENSSL 1
+/* to enable NGHTTP2 */
+#cmakedefine USE_NGHTTP2 1
+
/* if Unix domain sockets are enabled */
#cmakedefine USE_UNIX_SOCKETS
-/* Define to 1 if you are building a Windows target without large file
- support. */
+/* Define to 1 if you are building a Windows target with large file support. */
#cmakedefine USE_WIN32_LARGE_FILES 1
/* to enable SSPI support */
diff --git a/lib/curl_endian.c b/lib/curl_endian.c
index 76deca6a..c2d21de5 100644
--- a/lib/curl_endian.c
+++ b/lib/curl_endian.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,7 +37,7 @@
*
* Returns the integer.
*/
-unsigned short Curl_read16_le(unsigned char *buf)
+unsigned short Curl_read16_le(const unsigned char *buf)
{
return (unsigned short)(((unsigned short)buf[0]) |
((unsigned short)buf[1] << 8));
@@ -56,7 +56,7 @@ unsigned short Curl_read16_le(unsigned char *buf)
*
* Returns the integer.
*/
-unsigned int Curl_read32_le(unsigned char *buf)
+unsigned int Curl_read32_le(const unsigned char *buf)
{
return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
@@ -77,7 +77,7 @@ unsigned int Curl_read32_le(unsigned char *buf)
* Returns the integer.
*/
#if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_le(unsigned char *buf)
+unsigned long long Curl_read64_le(const unsigned char *buf)
{
return ((unsigned long long)buf[0]) |
((unsigned long long)buf[1] << 8) |
@@ -89,7 +89,7 @@ unsigned long long Curl_read64_le(unsigned char *buf)
((unsigned long long)buf[7] << 56);
}
#else
-unsigned __int64 Curl_read64_le(unsigned char *buf)
+unsigned __int64 Curl_read64_le(const unsigned char *buf)
{
return ((unsigned __int64)buf[0]) | ((unsigned __int64)buf[1] << 8) |
((unsigned __int64)buf[2] << 16) | ((unsigned __int64)buf[3] << 24) |
@@ -113,7 +113,7 @@ unsigned __int64 Curl_read64_le(unsigned char *buf)
*
* Returns the integer.
*/
-unsigned short Curl_read16_be(unsigned char *buf)
+unsigned short Curl_read16_be(const unsigned char *buf)
{
return (unsigned short)(((unsigned short)buf[0] << 8) |
((unsigned short)buf[1]));
@@ -132,7 +132,7 @@ unsigned short Curl_read16_be(unsigned char *buf)
*
* Returns the integer.
*/
-unsigned int Curl_read32_be(unsigned char *buf)
+unsigned int Curl_read32_be(const unsigned char *buf)
{
return ((unsigned int)buf[0] << 24) | ((unsigned int)buf[1] << 16) |
((unsigned int)buf[2] << 8) | ((unsigned int)buf[3]);
@@ -153,7 +153,7 @@ unsigned int Curl_read32_be(unsigned char *buf)
* Returns the integer.
*/
#if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_be(unsigned char *buf)
+unsigned long long Curl_read64_be(const unsigned char *buf)
{
return ((unsigned long long)buf[0] << 56) |
((unsigned long long)buf[1] << 48) |
@@ -165,7 +165,7 @@ unsigned long long Curl_read64_be(unsigned char *buf)
((unsigned long long)buf[7]);
}
#else
-unsigned __int64 Curl_read64_be(unsigned char *buf)
+unsigned __int64 Curl_read64_be(const unsigned char *buf)
{
return ((unsigned __int64)buf[0] << 56) | ((unsigned __int64)buf[1] << 48) |
((unsigned __int64)buf[2] << 40) | ((unsigned __int64)buf[3] << 32) |
diff --git a/lib/curl_endian.h b/lib/curl_endian.h
index df8398c8..8a2b07ad 100644
--- a/lib/curl_endian.h
+++ b/lib/curl_endian.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,32 +23,32 @@
***************************************************************************/
/* Converts a 16-bit integer from little endian */
-unsigned short Curl_read16_le(unsigned char *buf);
+unsigned short Curl_read16_le(const unsigned char *buf);
/* Converts a 32-bit integer from little endian */
-unsigned int Curl_read32_le(unsigned char *buf);
+unsigned int Curl_read32_le(const unsigned char *buf);
#if (CURL_SIZEOF_CURL_OFF_T > 4)
/* Converts a 64-bit integer from little endian */
#if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_le(unsigned char *buf);
+unsigned long long Curl_read64_le(const unsigned char *buf);
#else
-unsigned __int64 Curl_read64_le(unsigned char *buf);
+unsigned __int64 Curl_read64_le(const unsigned char *buf);
#endif
#endif
/* Converts a 16-bit integer from big endian */
-unsigned short Curl_read16_be(unsigned char *buf);
+unsigned short Curl_read16_be(const unsigned char *buf);
/* Converts a 32-bit integer from big endian */
-unsigned int Curl_read32_be(unsigned char *buf);
+unsigned int Curl_read32_be(const unsigned char *buf);
#if (CURL_SIZEOF_CURL_OFF_T > 4)
/* Converts a 64-bit integer from big endian */
#if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_be(unsigned char *buf);
+unsigned long long Curl_read64_be(const unsigned char *buf);
#else
-unsigned __int64 Curl_read64_be(unsigned char *buf);
+unsigned __int64 Curl_read64_be(const unsigned char *buf);
#endif
#endif
diff --git a/lib/curl_gethostname.c b/lib/curl_gethostname.c
index 2591fd88..8337c72e 100644
--- a/lib/curl_gethostname.c
+++ b/lib/curl_gethostname.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -48,8 +48,8 @@
* For libcurl static library release builds no overriding takes place.
*/
-int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) {
-
+int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen)
+{
#ifndef HAVE_GETHOSTNAME
/* Allow compilation and return failure when unavailable */
@@ -59,7 +59,7 @@ int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) {
#else
int err;
- char* dot;
+ char *dot;
#ifdef DEBUGBUILD
diff --git a/lib/curl_gssapi.c b/lib/curl_gssapi.c
index bf7c766e..83f3fa0c 100644
--- a/lib/curl_gssapi.c
+++ b/lib/curl_gssapi.c
@@ -94,7 +94,7 @@ static size_t display_gss_error(OM_uint32 status, int type,
if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) {
len += snprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
"%.*s. ", (int)status_string.length,
- (char*)status_string.value);
+ (char *)status_string.value);
}
gss_release_buffer(&min_stat, &status_string);
} while(!GSS_ERROR(maj_stat) && msg_ctx != 0);
diff --git a/lib/curl_hmac.h b/lib/curl_hmac.h
index 41703b42..756dc9e4 100644
--- a/lib/curl_hmac.h
+++ b/lib/curl_hmac.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,11 +24,11 @@
#ifndef CURL_DISABLE_CRYPTO_AUTH
-typedef void (* HMAC_hinit_func)(void * context);
-typedef void (* HMAC_hupdate_func)(void * context,
- const unsigned char * data,
+typedef void (* HMAC_hinit_func)(void *context);
+typedef void (* HMAC_hupdate_func)(void *context,
+ const unsigned char *data,
unsigned int len);
-typedef void (* HMAC_hfinal_func)(unsigned char * result, void * context);
+typedef void (* HMAC_hfinal_func)(unsigned char *result, void *context);
/* Per-hash function HMAC parameters. */
@@ -46,21 +46,21 @@ typedef struct {
/* HMAC computation context. */
typedef struct {
- const HMAC_params * hmac_hash; /* Hash function definition. */
- void * hmac_hashctxt1; /* Hash function context 1. */
- void * hmac_hashctxt2; /* Hash function context 2. */
+ const HMAC_params *hmac_hash; /* Hash function definition. */
+ void *hmac_hashctxt1; /* Hash function context 1. */
+ void *hmac_hashctxt2; /* Hash function context 2. */
} HMAC_context;
/* Prototypes. */
-HMAC_context * Curl_HMAC_init(const HMAC_params * hashparams,
- const unsigned char * key,
+HMAC_context * Curl_HMAC_init(const HMAC_params *hashparams,
+ const unsigned char *key,
unsigned int keylen);
-int Curl_HMAC_update(HMAC_context * context,
- const unsigned char * data,
+int Curl_HMAC_update(HMAC_context *context,
+ const unsigned char *data,
unsigned int len);
-int Curl_HMAC_final(HMAC_context * context, unsigned char * result);
+int Curl_HMAC_final(HMAC_context *context, unsigned char *result);
#endif
diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c
index f3fb0132..812a0731 100644
--- a/lib/curl_ntlm_core.c
+++ b/lib/curl_ntlm_core.c
@@ -76,6 +76,11 @@
# define MD5_DIGEST_LENGTH 16
# define MD4_DIGEST_LENGTH 16
+#elif defined(USE_MBEDTLS)
+
+# include <mbedtls/des.h>
+# include <mbedtls/md4.h>
+
#elif defined(USE_NSS)
# include <nss.h>
@@ -100,7 +105,7 @@
#include "urldata.h"
#include "non-ascii.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "curl_ntlm_core.h"
#include "curl_md5.h"
#include "curl_hmac.h"
@@ -188,6 +193,26 @@ static void setup_des_key(const unsigned char *key_56,
gcry_cipher_setkey(*des, key, sizeof(key));
}
+#elif defined(USE_MBEDTLS)
+
+static bool encrypt_des(const unsigned char *in, unsigned char *out,
+ const unsigned char *key_56)
+{
+ mbedtls_des_context ctx;
+ char key[8];
+
+ /* Expand the 56-bit key to 64-bits */
+ extend_key_56_to_64(key_56, key);
+
+ /* Set the key parity to odd */
+ mbedtls_des_key_set_parity((unsigned char *) key);
+
+ /* Perform the encryption */
+ mbedtls_des_init(&ctx);
+ mbedtls_des_setkey_enc(&ctx, (unsigned char *) key);
+ return mbedtls_des_crypt_ecb(&ctx, in, out) == 0;
+}
+
#elif defined(USE_NSS)
/*
@@ -400,8 +425,8 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
setup_des_key(keys + 14, &des);
gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
gcry_cipher_close(des);
-#elif defined(USE_NSS) || defined(USE_DARWINSSL) || defined(USE_OS400CRYPTO) \
- || defined(USE_WIN32_CRYPTO)
+#elif defined(USE_MBEDTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) \
+ || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
encrypt_des(plaintext, results, keys);
encrypt_des(plaintext, results + 8, keys + 7);
encrypt_des(plaintext, results + 16, keys + 14);
@@ -464,8 +489,8 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
setup_des_key(pw + 7, &des);
gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
gcry_cipher_close(des);
-#elif defined(USE_NSS) || defined(USE_DARWINSSL) || defined(USE_OS400CRYPTO) \
- || defined(USE_WIN32_CRYPTO)
+#elif defined(USE_MBEDTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) \
+ || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
encrypt_des(magic, lmbuffer, pw);
encrypt_des(magic, lmbuffer + 8, pw + 7);
#endif
@@ -543,6 +568,8 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
gcry_md_write(MD4pw, pw, 2 * len);
memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH);
gcry_md_close(MD4pw);
+#elif defined(USE_MBEDTLS)
+ mbedtls_md4(pw, 2 * len, ntbuffer);
#elif defined(USE_NSS) || defined(USE_OS400CRYPTO)
Curl_md4it(ntbuffer, pw, 2 * len);
#elif defined(USE_DARWINSSL)
diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c
index afdea16c..4699d8f4 100644
--- a/lib/curl_ntlm_wb.c
+++ b/lib/curl_ntlm_wb.c
@@ -51,6 +51,7 @@
#include "curl_ntlm_wb.h"
#include "url.h"
#include "strerror.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -293,11 +294,10 @@ static CURLcode ntlm_wb_response(struct connectdata *conn,
buf[len_out - 1] = '\0';
break;
}
- newbuf = realloc(buf, len_out + NTLM_BUFSIZE);
- if(!newbuf) {
- free(buf);
+ newbuf = Curl_saferealloc(buf, len_out + NTLM_BUFSIZE);
+ if(!newbuf)
return CURLE_OUT_OF_MEMORY;
- }
+
buf = newbuf;
}
@@ -349,7 +349,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
if(proxy) {
allocuserpwd = &conn->allocptr.proxyuserpwd;
- userp = conn->proxyuser;
+ userp = conn->http_proxy.user;
ntlm = &conn->proxyntlm;
authp = &conn->data->state.authproxy;
}
diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c
index 35e9feaa..807f5de7 100644
--- a/lib/curl_sasl.c
+++ b/lib/curl_sasl.c
@@ -42,8 +42,6 @@
#include "curl_sasl.h"
#include "warnless.h"
#include "strtok.h"
-#include "strequal.h"
-#include "rawstr.h"
#include "sendf.h"
#include "non-ascii.h" /* included for Curl_convert_... prototypes */
/* The last 3 #include files should be in this order */
@@ -159,7 +157,7 @@ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
sasl->prefmech = SASL_AUTH_NONE;
}
- if(strnequal(value, "*", len))
+ if(!strncmp(value, "*", len))
sasl->prefmech = SASL_AUTH_DEFAULT;
else {
mechbit = Curl_sasl_decode_mech(value, len, &mechlen);
@@ -264,10 +262,13 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
size_t len = 0;
saslstate state1 = SASL_STOP;
saslstate state2 = SASL_FINAL;
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
+ const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
#if defined(USE_KERBEROS5)
- const char* service = data->set.str[STRING_SERVICE_NAME] ?
- data->set.str[STRING_SERVICE_NAME] :
- sasl->params->service;
+ const char *service = data->set.str[STRING_SERVICE_NAME] ?
+ data->set.str[STRING_SERVICE_NAME] :
+ sasl->params->service;
#endif
sasl->force_ir = force_ir; /* Latch for future use */
@@ -288,7 +289,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
}
else if(conn->bits.user_passwd) {
#if defined(USE_KERBEROS5)
- if(enabledmechs & SASL_MECH_GSSAPI) {
+ if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() &&
+ Curl_auth_user_contains_domain(conn->user)) {
sasl->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */
mech = SASL_MECH_STRING_GSSAPI;
state1 = SASL_GSSAPI;
@@ -308,7 +310,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
else
#endif
#ifndef CURL_DISABLE_CRYPTO_AUTH
- if(enabledmechs & SASL_MECH_DIGEST_MD5) {
+ if((enabledmechs & SASL_MECH_DIGEST_MD5) &&
+ Curl_auth_is_digest_supported()) {
mech = SASL_MECH_STRING_DIGEST_MD5;
state1 = SASL_DIGESTMD5;
sasl->authused = SASL_MECH_DIGEST_MD5;
@@ -321,7 +324,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
else
#endif
#ifdef USE_NTLM
- if(enabledmechs & SASL_MECH_NTLM) {
+ if((enabledmechs & SASL_MECH_NTLM) && Curl_auth_is_ntlm_supported()) {
mech = SASL_MECH_STRING_NTLM;
state1 = SASL_NTLM;
state2 = SASL_NTLM_TYPE2MSG;
@@ -341,8 +344,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
if(force_ir || data->set.sasl_ir)
result = Curl_auth_create_oauth_bearer_message(data, conn->user,
- conn->host.name,
- conn->port,
+ hostname,
+ port,
conn->oauth_bearer,
&resp, &len);
}
@@ -408,6 +411,9 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
struct Curl_easy *data = conn->data;
saslstate newstate = SASL_FINAL;
char *resp = NULL;
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
+ const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
char *serverdata;
char *chlg = NULL;
@@ -542,8 +548,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
/* Create the authorisation message */
if(sasl->authused == SASL_MECH_OAUTHBEARER) {
result = Curl_auth_create_oauth_bearer_message(data, conn->user,
- conn->host.name,
- conn->port,
+ hostname,
+ port,
conn->oauth_bearer,
&resp, &len);
diff --git a/lib/curl_sec.h b/lib/curl_sec.h
index 3f94e144..073a981f 100644
--- a/lib/curl_sec.h
+++ b/lib/curl_sec.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,8 +30,8 @@ struct Curl_sec_client_mech {
void (*end)(void *);
int (*check_prot)(void *, int);
int (*overhead)(void *, int, int);
- int (*encode)(void *, const void*, int, int, void**);
- int (*decode)(void *, void*, int, int, struct connectdata *);
+ int (*encode)(void *, const void *, int, int, void **);
+ int (*decode)(void *, void *, int, int, struct connectdata *);
};
#define AUTH_OK 0
diff --git a/lib/curl_setup.h b/lib/curl_setup.h
index 3fe00dcc..d267919a 100644
--- a/lib/curl_setup.h
+++ b/lib/curl_setup.h
@@ -440,8 +440,8 @@
# ifdef __minix
/* Minix 3 versions up to at least 3.1.3 are missing these prototypes */
- extern char * strtok_r(char *s, const char *delim, char **last);
- extern struct tm * gmtime_r(const time_t * const timep, struct tm *tmp);
+ extern char *strtok_r(char *s, const char *delim, char **last);
+ extern struct tm *gmtime_r(const time_t * const timep, struct tm *tmp);
# endif
# define DIR_CHAR "/"
@@ -572,10 +572,9 @@ int netware_init(void);
#endif
#endif
-#if defined(HAVE_LIBIDN) && defined(HAVE_TLD_H)
-/* The lib was present and the tld.h header (which is missing in libidn 0.3.X
- but we only work with libidn 0.4.1 or later) */
-#define USE_LIBIDN
+#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H)
+/* The lib and header are present */
+#define USE_LIBIDN2
#endif
#define LIBIDN_REQUIRED_VERSION "0.4.1"
@@ -606,6 +605,13 @@ int netware_init(void);
defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
#define USE_NTLM
+
+#elif defined(USE_MBEDTLS)
+# include <mbedtls/md4.h>
+# if defined(MBEDTLS_MD4_C)
+#define USE_NTLM
+# endif
+
#endif
#endif
@@ -714,4 +720,14 @@ endings either CRLF or LF so 't' is appropriate.
# endif
#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUNDS */
+/* Detect Windows App environment which has a restricted access
+ * to the Win32 APIs. */
+# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)
+# include <winapifamily.h>
+# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
+ !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+# define CURL_WINDOWS_APP
+# endif
+# endif
+
#endif /* HEADER_CURL_SETUP_H */
diff --git a/lib/curl_sspi.c b/lib/curl_sspi.c
index ee3f1b1c..11a7120a 100644
--- a/lib/curl_sspi.c
+++ b/lib/curl_sspi.c
@@ -64,6 +64,12 @@ PSecurityFunctionTable s_pSecFn = NULL;
*
* Once this function has been executed, Windows SSPI functions can be
* called through the Security Service Provider Interface dispatch table.
+ *
+ * Parameters:
+ *
+ * None.
+ *
+ * Returns CURLE_OK on success.
*/
CURLcode Curl_sspi_global_init(void)
{
@@ -102,8 +108,11 @@ CURLcode Curl_sspi_global_init(void)
* Curl_sspi_global_cleanup()
*
* This deinitializes the Security Service Provider Interface from libcurl.
+ *
+ * Parameters:
+ *
+ * None.
*/
-
void Curl_sspi_global_cleanup(void)
{
if(s_hSecDll) {
@@ -205,6 +214,15 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
return CURLE_OK;
}
+/*
+ * Curl_sspi_free_identity()
+ *
+ * This is used to free the contents of a SSPI identifier structure.
+ *
+ * Parameters:
+ *
+ * identity [in/out] - The identity structure.
+ */
void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity)
{
if(identity) {
diff --git a/lib/curl_threads.c b/lib/curl_threads.c
index c98d8bba..d8826987 100644
--- a/lib/curl_threads.c
+++ b/lib/curl_threads.c
@@ -59,7 +59,7 @@ static void *curl_thread_create_thunk(void *arg)
return 0;
}
-curl_thread_t Curl_thread_create(unsigned int (*func) (void*), void *arg)
+curl_thread_t Curl_thread_create(unsigned int (*func) (void *), void *arg)
{
curl_thread_t t = malloc(sizeof(pthread_t));
struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call));
@@ -100,7 +100,7 @@ int Curl_thread_join(curl_thread_t *hnd)
#elif defined(USE_THREADS_WIN32)
-curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*),
+curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
void *arg)
{
#ifdef _WIN32_WCE
diff --git a/lib/curl_threads.h b/lib/curl_threads.h
index 8cbac63a..0778dd55 100644
--- a/lib/curl_threads.h
+++ b/lib/curl_threads.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -50,7 +50,7 @@
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
-curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*),
+curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
void *arg);
void Curl_thread_destroy(curl_thread_t hnd);
diff --git a/lib/curlx.h b/lib/curlx.h
index 448a34ff..6168dc11 100644
--- a/lib/curlx.h
+++ b/lib/curlx.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,8 +34,8 @@
functions while they still are offered publicly. They will be made library-
private one day */
-#include "strequal.h"
-/* "strequal.h" provides the strequal protos */
+#include "strcase.h"
+/* "strcase.h" provides the strcasecompare protos */
#include "strtoofft.h"
/* "strtoofft.h" provides this function: curlx_strtoofft(), returns a
@@ -67,15 +67,12 @@
be removed from a future libcurl official API:
curlx_getenv
curlx_mprintf (and its variations)
- curlx_strequal
- curlx_strnequal
+ curlx_strcasecompare
+ curlx_strncasecompare
*/
#define curlx_getenv curl_getenv
-#define curlx_strequal curl_strequal
-#define curlx_strnequal curl_strnequal
-#define curlx_raw_equal Curl_raw_equal
#define curlx_mvsnprintf curl_mvsnprintf
#define curlx_msnprintf curl_msnprintf
#define curlx_maprintf curl_maprintf
diff --git a/lib/dict.c b/lib/dict.c
index a7b5965b..69defc4c 100644
--- a/lib/dict.c
+++ b/lib/dict.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -52,11 +52,10 @@
#include <curl/curl.h>
#include "transfer.h"
#include "sendf.h"
-
+#include "escape.h"
#include "progress.h"
-#include "strequal.h"
#include "dict.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
@@ -96,12 +95,12 @@ static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
char *newp;
char *dictp;
char *ptr;
- int len;
+ size_t len;
char ch;
int olen=0;
- newp = curl_easy_unescape(data, inputbuff, 0, &len);
- if(!newp)
+ CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE);
+ if(!newp || result)
return NULL;
dictp = malloc(((size_t)len)*2 + 1); /* add one for terminating zero */
@@ -145,9 +144,9 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
/* AUTH is missing */
}
- if(Curl_raw_nequal(path, DICT_MATCH, sizeof(DICT_MATCH)-1) ||
- Curl_raw_nequal(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) ||
- Curl_raw_nequal(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) {
+ if(strncasecompare(path, DICT_MATCH, sizeof(DICT_MATCH)-1) ||
+ strncasecompare(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) ||
+ strncasecompare(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) {
word = strchr(path, ':');
if(word) {
@@ -203,9 +202,9 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL); /* no upload */
}
- else if(Curl_raw_nequal(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
- Curl_raw_nequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
- Curl_raw_nequal(path, DICT_DEFINE3, sizeof(DICT_DEFINE3)-1)) {
+ else if(strncasecompare(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
+ strncasecompare(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
+ strncasecompare(path, DICT_DEFINE3, sizeof(DICT_DEFINE3)-1)) {
word = strchr(path, ':');
if(word) {
diff --git a/lib/easy.c b/lib/easy.c
index dc7139f2..1242369d 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -50,7 +50,6 @@
#include <sys/param.h>
#endif
-#include "strequal.h"
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
@@ -144,28 +143,6 @@ static CURLcode win32_init(void)
return CURLE_OK;
}
-#ifdef USE_LIBIDN
-/*
- * Initialise use of IDNA library.
- * It falls back to ASCII if $CHARSET isn't defined. This doesn't work for
- * idna_to_ascii_lz().
- */
-static void idna_init (void)
-{
-#ifdef WIN32
- char buf[60];
- UINT cp = GetACP();
-
- if(!getenv("CHARSET") && cp > 0) {
- snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp);
- putenv(buf);
- }
-#else
- /* to do? */
-#endif
-}
-#endif /* USE_LIBIDN */
-
/* true globals -- for curl_global_init() and curl_global_cleanup() */
static unsigned int initialized;
static long init_flags;
@@ -217,7 +194,7 @@ curl_calloc_callback Curl_ccalloc;
#endif
/**
- * curl_global_init() globally initializes cURL given a bitwise set of the
+ * curl_global_init() globally initializes curl given a bitwise set of the
* different features of what to initialize.
*/
static CURLcode global_init(long flags, bool memoryfuncs)
@@ -262,10 +239,6 @@ static CURLcode global_init(long flags, bool memoryfuncs)
}
#endif
-#ifdef USE_LIBIDN
- idna_init();
-#endif
-
if(Curl_resolver_global_init()) {
DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n"));
return CURLE_FAILED_INIT;
@@ -292,7 +265,7 @@ static CURLcode global_init(long flags, bool memoryfuncs)
/**
- * curl_global_init() globally initializes cURL given a bitwise set of the
+ * curl_global_init() globally initializes curl given a bitwise set of the
* different features of what to initialize.
*/
CURLcode curl_global_init(long flags)
@@ -301,7 +274,7 @@ CURLcode curl_global_init(long flags)
}
/*
- * curl_global_init_mem() globally initializes cURL and also registers the
+ * curl_global_init_mem() globally initializes curl and also registers the
* user provided callback routines.
*/
CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
@@ -333,7 +306,7 @@ CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
}
/**
- * curl_global_cleanup() globally cleanups cURL, uses the value of
+ * curl_global_cleanup() globally cleanups curl, uses the value of
* "init_flags" to determine what needs to be cleaned up and what doesn't.
*/
void curl_global_cleanup(void)
@@ -954,6 +927,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
Curl_convert_setup(outcurl);
+ Curl_initinfo(outcurl);
+
outcurl->magic = CURLEASY_MAGIC_NUMBER;
/* we reach this point and thus we are OK */
@@ -995,6 +970,9 @@ void curl_easy_reset(struct Curl_easy *data)
/* zero out Progress data: */
memset(&data->progress, 0, sizeof(struct Progress));
+ /* zero out PureInfo data: */
+ Curl_initinfo(data);
+
data->progress.flags |= PGRS_HIDE;
data->state.current_speed = -1; /* init to negative == impossible */
}
@@ -1044,7 +1022,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
if(!result &&
((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) )
- Curl_expire(data, 1); /* get this handle going again */
+ Curl_expire(data, 0); /* get this handle going again */
return result;
}
diff --git a/lib/escape.c b/lib/escape.c
index 04230b4c..9fb8d3e1 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -31,6 +31,7 @@
#include "warnless.h"
#include "non-ascii.h"
#include "escape.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -78,15 +79,21 @@ char *curl_unescape(const char *string, int length)
char *curl_easy_escape(struct Curl_easy *data, const char *string,
int inlength)
{
- size_t alloc = (inlength?(size_t)inlength:strlen(string))+1;
+ size_t alloc;
char *ns;
char *testing_ptr = NULL;
unsigned char in; /* we need to treat the characters unsigned */
- size_t newlen = alloc;
+ size_t newlen;
size_t strindex=0;
size_t length;
CURLcode result;
+ if(inlength < 0)
+ return NULL;
+
+ alloc = (inlength?(size_t)inlength:strlen(string))+1;
+ newlen = alloc;
+
ns = malloc(alloc);
if(!ns)
return NULL;
@@ -103,11 +110,9 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
newlen += 2; /* the size grows with two, since this'll become a %XX */
if(newlen > alloc) {
alloc *= 2;
- testing_ptr = realloc(ns, alloc);
- if(!testing_ptr) {
- free(ns);
+ testing_ptr = Curl_saferealloc(ns, alloc);
+ if(!testing_ptr)
return NULL;
- }
else {
ns = testing_ptr;
}
@@ -211,14 +216,22 @@ char *curl_easy_unescape(struct Curl_easy *data, const char *string,
int length, int *olen)
{
char *str = NULL;
- size_t inputlen = length;
- size_t outputlen;
- CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen,
- FALSE);
- if(res)
- return NULL;
- if(olen)
- *olen = curlx_uztosi(outputlen);
+ if(length >= 0) {
+ size_t inputlen = length;
+ size_t outputlen;
+ CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen,
+ FALSE);
+ if(res)
+ return NULL;
+
+ if(olen) {
+ if(outputlen <= (size_t) INT_MAX)
+ *olen = curlx_uztosi(outputlen);
+ else
+ /* too large to return in an int, fail! */
+ Curl_safefree(str);
+ }
+ }
return str;
}
diff --git a/lib/file.c b/lib/file.c
index b534ec18..3dbc0f2b 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -190,14 +190,15 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
struct FILEPROTO *file = data->req.protop;
int fd;
#ifdef DOS_FILESYSTEM
- int i;
+ size_t i;
char *actual_path;
#endif
- int real_path_len;
+ size_t real_path_len;
- real_path = curl_easy_unescape(data, data->state.path, 0, &real_path_len);
- if(!real_path)
- return CURLE_OUT_OF_MEMORY;
+ CURLcode result = Curl_urldecode(data, data->state.path, 0, &real_path,
+ &real_path_len, FALSE);
+ if(result)
+ return result;
#ifdef DOS_FILESYSTEM
/* If the first character is a slash, and there's
@@ -312,7 +313,7 @@ static CURLcode file_upload(struct connectdata *conn)
curl_off_t bytecount = 0;
struct timeval now = Curl_tvnow();
struct_stat file_stat;
- const char* buf2;
+ const char *buf2;
/*
* Since FILE: doesn't do the full init, we need to provide some extra
diff --git a/lib/formdata.c b/lib/formdata.c
index 673759de..2aef5faf 100644
--- a/lib/formdata.c
+++ b/lib/formdata.c
@@ -33,9 +33,10 @@
#include "urldata.h" /* for struct Curl_easy */
#include "formdata.h"
#include "vtls/vtls.h"
-#include "strequal.h"
+#include "strcase.h"
#include "sendf.h"
#include "strdup.h"
+#include "rand.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -80,7 +81,7 @@ AddHttpPost(char *name, size_t namelength,
char *buffer, size_t bufferlength,
char *contenttype,
long flags,
- struct curl_slist* contentHeader,
+ struct curl_slist *contentHeader,
char *showfilename, char *userp,
struct curl_httppost *parent_post,
struct curl_httppost **httppost,
@@ -201,9 +202,9 @@ static const char *ContentTypeForFilename(const char *filename,
if(filename) { /* in case a NULL was passed in */
for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
if(strlen(filename) >= strlen(ctts[i].extension)) {
- if(strequal(filename +
- strlen(filename) - strlen(ctts[i].extension),
- ctts[i].extension)) {
+ if(strcasecompare(filename +
+ strlen(filename) - strlen(ctts[i].extension),
+ ctts[i].extension)) {
contenttype = ctts[i].type;
break;
}
@@ -547,9 +548,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
{
/* this "cast increases required alignment of target type" but
we consider it OK anyway */
- struct curl_slist* list = array_state?
- (struct curl_slist*)(void*)array_value:
- va_arg(params, struct curl_slist*);
+ struct curl_slist *list = array_state?
+ (struct curl_slist *)(void *)array_value:
+ va_arg(params, struct curl_slist *);
if(current_form->contentheader)
return_value = CURL_FORMADD_OPTION_TWICE;
@@ -761,8 +762,8 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost,
* and CD/DVD images should be either a STREAM_LF format or a fixed format.
*
*/
-curl_off_t VmsRealFileSize(const char * name,
- const struct_stat * stat_buf)
+curl_off_t VmsRealFileSize(const char *name,
+ const struct_stat *stat_buf)
{
char buffer[8192];
curl_off_t count;
@@ -791,8 +792,8 @@ curl_off_t VmsRealFileSize(const char * name,
* if not to call a routine to get the correct size.
*
*/
-static curl_off_t VmsSpecialSize(const char * name,
- const struct_stat * stat_buf)
+static curl_off_t VmsSpecialSize(const char *name,
+ const struct_stat *stat_buf)
{
switch(stat_buf->st_fab_rfm) {
case FAB$C_VAR:
@@ -845,16 +846,23 @@ static CURLcode AddFormData(struct FormData **formp,
goto error;
}
#endif
+ if(type != FORM_DATAMEM) {
+ newform->line = malloc((size_t)length+1);
+ if(!newform->line) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ alloc2 = newform->line;
+ memcpy(newform->line, line, (size_t)length);
- newform->line = malloc((size_t)length+1);
- if(!newform->line) {
- result = CURLE_OUT_OF_MEMORY;
- goto error;
+ /* zero terminate for easier debugging */
+ newform->line[(size_t)length]=0;
+ }
+ else {
+ newform->line = (char *)line;
+ type = FORM_DATA; /* in all other aspects this is just FORM_DATA */
}
- alloc2 = newform->line;
- memcpy(newform->line, line, (size_t)length);
newform->length = (size_t)length;
- newform->line[(size_t)length]=0; /* zero terminate for easier debugging */
}
else
/* For callbacks and files we don't have any actual data so we just keep a
@@ -863,13 +871,6 @@ static CURLcode AddFormData(struct FormData **formp,
newform->type = type;
- if(*formp) {
- (*formp)->next = newform;
- *formp = newform;
- }
- else
- *formp = newform;
-
if(size) {
if(type != FORM_FILE)
/* for static content as well as callback data we add the size given
@@ -878,7 +879,7 @@ static CURLcode AddFormData(struct FormData **formp,
else {
/* Since this is a file to be uploaded here, add the size of the actual
file */
- if(!strequal("-", newform->line)) {
+ if(strcmp("-", newform->line)) {
struct_stat file;
if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode))
*size += filesize(newform->line, file);
@@ -889,6 +890,14 @@ static CURLcode AddFormData(struct FormData **formp,
}
}
}
+
+ if(*formp) {
+ (*formp)->next = newform;
+ *formp = newform;
+ }
+ else
+ *formp = newform;
+
return CURLE_OK;
error:
if(newform)
@@ -906,13 +915,21 @@ static CURLcode AddFormDataf(struct FormData **formp,
curl_off_t *size,
const char *fmt, ...)
{
- char s[4096];
+ char *s;
+ CURLcode result;
va_list ap;
va_start(ap, fmt);
- vsnprintf(s, sizeof(s), fmt, ap);
+ s = curl_mvaprintf(fmt, ap);
va_end(ap);
- return AddFormData(formp, FORM_DATA, s, 0, size);
+ if(!s)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = AddFormData(formp, FORM_DATAMEM, s, 0, size);
+ if(result)
+ free(s);
+
+ return result;
}
/*
@@ -1150,7 +1167,7 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
curl_off_t size = 0; /* support potentially ENORMOUS formposts */
char *boundary;
char *fileboundary = NULL;
- struct curl_slist* curList;
+ struct curl_slist *curList;
*finalform = NULL; /* default form is empty */
@@ -1289,7 +1306,7 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
/* we should include the contents from the specified file */
FILE *fileread;
- fileread = strequal("-", file->contents)?
+ fileread = !strcmp("-", file->contents)?
stdin:fopen(file->contents, "rb"); /* binary read for win32 */
/*
@@ -1410,7 +1427,8 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata)
*
*/
# define fopen_read vmsfopenread
-static FILE * vmsfopenread(const char *file, const char *mode) {
+static FILE * vmsfopenread(const char *file, const char *mode)
+{
struct_stat statbuf;
int result;
@@ -1553,8 +1571,12 @@ static char *formboundary(struct Curl_easy *data)
{
/* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
combinations */
- return aprintf("------------------------%08x%08x",
- Curl_rand(data), Curl_rand(data));
+ unsigned int rnd[2];
+ CURLcode result = Curl_rand(data, &rnd[0], 2);
+ if(result)
+ return NULL;
+
+ return aprintf("------------------------%08x%08x", rnd[0], rnd[1]);
}
#else /* CURL_DISABLE_HTTP */
diff --git a/lib/formdata.h b/lib/formdata.h
index 6eb7c6c9..69629f62 100644
--- a/lib/formdata.h
+++ b/lib/formdata.h
@@ -23,6 +23,7 @@
***************************************************************************/
enum formtype {
+ FORM_DATAMEM, /* already allocated FORM_DATA memory */
FORM_DATA, /* form metadata (convert to network encoding if necessary) */
FORM_CONTENT, /* form content (never convert) */
FORM_CALLBACK, /* 'line' points to the custom pointer we pass to the callback
@@ -64,7 +65,7 @@ typedef struct FormInfo {
file name will be used */
bool showfilename_alloc;
char *userp; /* pointer for the read callback */
- struct curl_slist* contentheader;
+ struct curl_slist *contentheader;
struct FormInfo *more;
} FormInfo;
diff --git a/lib/ftp.c b/lib/ftp.c
index 8af65315..1e61fc55 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -61,7 +61,7 @@
#include "ftplistparser.h"
#include "curl_sec.h"
#include "strtoofft.h"
-#include "strequal.h"
+#include "strcase.h"
#include "vtls/vtls.h"
#include "connect.h"
#include "strerror.h"
@@ -72,7 +72,7 @@
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "multiif.h"
#include "url.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "speedcheck.h"
#include "warnless.h"
#include "http_proxy.h"
@@ -384,10 +384,10 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
* Curl_pgrsTime(..., TIMER_STARTACCEPT);
*
*/
-static long ftp_timeleft_accept(struct Curl_easy *data)
+static time_t ftp_timeleft_accept(struct Curl_easy *data)
{
- long timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
- long other;
+ time_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
+ time_t other;
struct timeval now;
if(data->set.accepttimeout > 0)
@@ -430,7 +430,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
int result;
- long timeout_ms;
+ time_t timeout_ms;
ssize_t nread;
int ftpcode;
@@ -475,7 +475,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
if(ftpcode/100 > 3)
return CURLE_FTP_ACCEPT_FAILED;
- return CURLE_FTP_WEIRD_SERVER_REPLY;
+ return CURLE_WEIRD_SERVER_REPLY;
}
break;
@@ -499,7 +499,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
struct FTP *ftp = data->req.protop;
CURLcode result = CURLE_OK;
- if(conn->ssl[SECONDARYSOCKET].use) {
+ if(conn->bits.ftp_use_data_ssl) {
/* since we only have a plaintext TCP connection here, we must now
* do the TLS stuff */
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
@@ -547,7 +547,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
{
struct Curl_easy *data = conn->data;
- long timeout_ms;
+ time_t timeout_ms;
CURLcode result = CURLE_OK;
*connected = FALSE;
@@ -687,8 +687,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
* line in a response or continue reading. */
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
- long timeout; /* timeout in milliseconds */
- long interval_ms;
+ time_t timeout; /* timeout in milliseconds */
+ time_t interval_ms;
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
struct ftp_conn *ftpc = &conn->proto.ftpc;
@@ -740,8 +740,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
* wait for more data anyway.
*/
}
- else {
- switch (Curl_socket_ready(sockfd, CURL_SOCKET_BAD, interval_ms)) {
+ else if(!Curl_ssl_data_pending(conn, FIRSTSOCKET)) {
+ switch (SOCKET_READABLE(sockfd, interval_ms)) {
case -1: /* select() error, stop reading */
failf(data, "FTP response aborted due to select/poll error: %d",
SOCKERRNO);
@@ -911,7 +911,7 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
}
else {
socks[1] = conn->sock[SECONDARYSOCKET];
- bits |= GETSOCK_WRITESOCK(1);
+ bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1);
}
return bits;
@@ -1835,7 +1835,7 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
if(conn->bits.ipv6) {
/* We can't disable EPSV when doing IPv6, so this is instead a fail */
failf(conn->data, "Failed EPSV attempt, exiting\n");
- return CURLE_FTP_WEIRD_SERVER_REPLY;
+ return CURLE_WEIRD_SERVER_REPLY;
}
infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n");
@@ -1850,84 +1850,6 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
return result;
}
-/*
- * Perform the necessary magic that needs to be done once the TCP connection
- * to the proxy has completed.
- */
-static CURLcode proxy_magic(struct connectdata *conn,
- char *newhost, unsigned short newport,
- bool *magicdone)
-{
- CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
-#if defined(CURL_DISABLE_PROXY)
- (void) newhost;
- (void) newport;
-#endif
-
- *magicdone = FALSE;
-
- switch(conn->proxytype) {
- case CURLPROXY_SOCKS5:
- case CURLPROXY_SOCKS5_HOSTNAME:
- result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost,
- newport, SECONDARYSOCKET, conn);
- *magicdone = TRUE;
- break;
- case CURLPROXY_SOCKS4:
- result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
- SECONDARYSOCKET, conn, FALSE);
- *magicdone = TRUE;
- break;
- case CURLPROXY_SOCKS4A:
- result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
- SECONDARYSOCKET, conn, TRUE);
- *magicdone = TRUE;
- break;
- case CURLPROXY_HTTP:
- case CURLPROXY_HTTP_1_0:
- /* do nothing here. handled later. */
- break;
- default:
- failf(data, "unknown proxytype option given");
- result = CURLE_COULDNT_CONNECT;
- break;
- }
-
- if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
- /* BLOCKING */
- /* We want "seamless" FTP operations through HTTP proxy tunnel */
-
- /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
- * member conn->proto.http; we want FTP through HTTP and we have to
- * change the member temporarily for connecting to the HTTP proxy. After
- * Curl_proxyCONNECT we have to set back the member to the original
- * struct FTP pointer
- */
- struct HTTP http_proxy;
- struct FTP *ftp_save = data->req.protop;
- memset(&http_proxy, 0, sizeof(http_proxy));
- data->req.protop = &http_proxy;
-
- result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport, TRUE);
-
- data->req.protop = ftp_save;
-
- if(result)
- return result;
-
- if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) {
- /* the CONNECT procedure is not complete, the tunnel is not yet up */
- state(conn, FTP_STOP); /* this phase is completed */
- return result;
- }
- else
- *magicdone = TRUE;
- }
-
- return result;
-}
static char *control_address(struct connectdata *conn)
{
@@ -1935,11 +1857,7 @@ static char *control_address(struct connectdata *conn)
If a proxy tunnel is used, returns the original host name instead, because
the effective control connection address is the proxy address,
not the ftp host. */
- if(conn->bits.tunnel_proxy ||
- conn->proxytype == CURLPROXY_SOCKS5 ||
- conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
- conn->proxytype == CURLPROXY_SOCKS4 ||
- conn->proxytype == CURLPROXY_SOCKS4A)
+ if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
return conn->host.name;
return conn->ip_addr_str;
@@ -2063,7 +1981,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
* here. We don't want to rely on a former host lookup that might've
* expired now, instead we remake the lookup here and now!
*/
- rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr);
+ const char * const host_name = conn->bits.socksproxy ?
+ conn->socks_proxy.host.name : conn->http_proxy.host.name;
+ rc = Curl_resolv(conn, host_name, (int)conn->port, &addr);
if(rc == CURLRESOLV_PENDING)
/* BLOCKING, ignores the return code but 'addr' will be NULL in
case of failure */
@@ -2073,8 +1993,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
(unsigned short)conn->port; /* we connect to the proxy's port */
if(!addr) {
- failf(data, "Can't resolve proxy host %s:%hu",
- conn->proxy.name, connectport);
+ failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport);
return CURLE_FTP_CANT_GET_HOST;
}
}
@@ -2115,6 +2034,10 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
/* this just dumps information about this second connection */
ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport);
+ Curl_safefree(conn->secondaryhostname);
+ conn->secondaryhostname = strdup(ftpc->newhost);
+ conn->secondary_port = ftpc->newport;
+
Curl_resolv_unlock(data, addr); /* we're done using this address */
conn->bits.do_more = TRUE;
state(conn, FTP_STOP); /* this phase is completed */
@@ -2742,7 +2665,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
else if(ftpcode != 220) {
failf(data, "Got a %03d ftp-server response when 220 was expected",
ftpcode);
- return CURLE_FTP_WEIRD_SERVER_REPLY;
+ return CURLE_WEIRD_SERVER_REPLY;
}
/* We have received a 220 response fine, now we proceed. */
@@ -2763,7 +2686,10 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
}
#endif
- if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+ if(data->set.use_ssl &&
+ (!conn->ssl[FIRSTSOCKET].use ||
+ (conn->bits.proxy_ssl_connected[FIRSTSOCKET] &&
+ !conn->proxy_ssl[FIRSTSOCKET].use))) {
/* We don't have a SSL/TLS connection yet, but FTPS is
requested. Try a FTPS connection now */
@@ -2808,7 +2734,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* Curl_ssl_connect is BLOCKING */
result = Curl_ssl_connect(conn, FIRSTSOCKET);
if(!result) {
- conn->ssl[SECONDARYSOCKET].use = FALSE; /* clear-text data */
+ conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
result = ftp_state_user(conn);
}
}
@@ -2850,7 +2776,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
case FTP_PROT:
if(ftpcode/100 == 2)
/* We have enabled SSL for the data connection! */
- conn->ssl[SECONDARYSOCKET].use =
+ conn->bits.ftp_use_data_ssl =
(data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE;
/* FTP servers typically responds with 500 if they decide to reject
our 'P' request */
@@ -2999,7 +2925,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* Check for special servers here. */
- if(strequal(os, "OS/400")) {
+ if(strcasecompare(os, "OS/400")) {
/* Force OS400 name format 1. */
result = Curl_pp_sendf(&ftpc->pp, "%s", "SITE NAMEFMT 1");
if(result) {
@@ -3165,7 +3091,7 @@ static CURLcode ftp_multi_statemach(struct connectdata *conn,
struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE);
- /* Check for the state outside of the Curl_socket_ready() return code checks
+ /* Check for the state outside of the Curl_socket_check() return code checks
since at times we are in fact already in this state when this function
gets called. */
*done = (ftpc->state == FTP_STOP) ? TRUE : FALSE;
@@ -3250,8 +3176,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
ssize_t nread;
int ftpcode;
CURLcode result = CURLE_OK;
- bool was_ctl_valid = ftpc->ctl_valid;
- char *path;
+ char *path = NULL;
const char *path_to_use = data->state.path;
if(!ftp)
@@ -3274,10 +3199,9 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
/* the connection stays alive fine even though this happened */
/* fall-through */
case CURLE_OK: /* doesn't affect the control connection's status */
- if(!premature) {
- ftpc->ctl_valid = was_ctl_valid;
+ if(!premature)
break;
- }
+
/* until we cope better with prematurely ended requests, let them
* fallback as if in complete failure */
default: /* by default, an error means the control connection is
@@ -3300,13 +3224,12 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
ftpc->known_filesize = -1;
}
- /* get the "raw" path */
- path = curl_easy_unescape(data, path_to_use, 0, NULL);
- if(!path) {
- /* out of memory, but we can limp along anyway (and should try to
- * since we may already be in the out of memory cleanup path) */
- if(!result)
- result = CURLE_OUT_OF_MEMORY;
+ if(!result)
+ /* get the "raw" path */
+ result = Curl_urldecode(data, path_to_use, 0, &path, NULL, FALSE);
+ if(result) {
+ /* We can limp along anyway (and should try to since we may already be in
+ * the error path) */
ftpc->ctl_valid = FALSE; /* mark control connection as bad */
connclose(conn, "FTP: out of memory!"); /* mark for connection closure */
ftpc->prevpath = NULL; /* no path remembering */
@@ -3669,10 +3592,6 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
/* Ready to do more? */
if(connected) {
DEBUGF(infof(data, "DO-MORE connected phase starts\n"));
- if(conn->bits.proxy) {
- infof(data, "Connection to proxy confirmed\n");
- result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected);
- }
}
else {
if(result && (ftpc->count1 == 0)) {
@@ -3684,6 +3603,18 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
}
}
+ result = Curl_proxy_connect(conn, SECONDARYSOCKET);
+ if(result)
+ return result;
+
+ if(CONNECT_SECONDARYSOCKET_PROXY_SSL())
+ return result;
+
+ if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
+ conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE)
+ return result;
+
+
if(ftpc->state) {
/* already in a state so skip the intial commands.
They are only done to kickstart the do_more state */
@@ -4093,8 +4024,7 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done)
}
-CURLcode Curl_ftpsendf(struct connectdata *conn,
- const char *fmt, ...)
+CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd)
{
ssize_t bytes_written;
#define SBUF_SIZE 1024
@@ -4106,10 +4036,9 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
enum protection_level data_sec = conn->data_prot;
#endif
- va_list ap;
- va_start(ap, fmt);
- write_len = vsnprintf(s, SBUF_SIZE-3, fmt, ap);
- va_end(ap);
+ write_len = strlen(cmd);
+ if(write_len > (sizeof(s) -3))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
write_len +=2;
@@ -4251,8 +4180,8 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
const char *cur_pos;
const char *filename = NULL;
- cur_pos = path_to_use; /* current position in path. point at the begin
- of next path component */
+ cur_pos = path_to_use; /* current position in path. point at the begin of
+ next path component */
ftpc->ctl_valid = FALSE;
ftpc->cwdfail = FALSE;
@@ -4291,6 +4220,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
slash_pos=strrchr(cur_pos, '/');
if(slash_pos || !*cur_pos) {
size_t dirlen = slash_pos-cur_pos;
+ CURLcode result;
ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
if(!ftpc->dirs)
@@ -4299,12 +4229,13 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
if(!dirlen)
dirlen++;
- ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/",
- slash_pos ? curlx_uztosi(dirlen) : 1,
- NULL);
- if(!ftpc->dirs[0]) {
+ result = Curl_urldecode(conn->data, slash_pos ? cur_pos : "/",
+ slash_pos ? dirlen : 1,
+ &ftpc->dirs[0], NULL,
+ FALSE);
+ if(result) {
freedirs(ftpc);
- return CURLE_OUT_OF_MEMORY;
+ return result;
}
ftpc->dirdepth = 1; /* we consider it to be a single dir */
filename = slash_pos ? slash_pos+1 : cur_pos; /* rest is file name */
@@ -4322,7 +4253,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY;
/* we have a special case for listing the root dir only */
- if(strequal(path_to_use, "/")) {
+ if(!strcmp(path_to_use, "/")) {
cur_pos++; /* make it point to the zero byte */
ftpc->dirs[0] = strdup("/");
ftpc->dirdepth++;
@@ -4339,18 +4270,15 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
/* we skip empty path components, like "x//y" since the FTP command
CWD requires a parameter and a non-existent parameter a) doesn't
work on many servers and b) has no effect on the others. */
- int len = curlx_sztosi(slash_pos - cur_pos + absolute_dir);
- ftpc->dirs[ftpc->dirdepth] =
- curl_easy_unescape(conn->data, cur_pos - absolute_dir, len, NULL);
- if(!ftpc->dirs[ftpc->dirdepth]) { /* run out of memory ... */
- failf(data, "no memory");
- freedirs(ftpc);
- return CURLE_OUT_OF_MEMORY;
- }
- if(isBadFtpString(ftpc->dirs[ftpc->dirdepth])) {
+ size_t len = slash_pos - cur_pos + absolute_dir;
+ CURLcode result =
+ Curl_urldecode(conn->data, cur_pos - absolute_dir, len,
+ &ftpc->dirs[ftpc->dirdepth], NULL,
+ TRUE);
+ if(result) {
free(ftpc->dirs[ftpc->dirdepth]);
freedirs(ftpc);
- return CURLE_URL_MALFORMAT;
+ return result;
}
}
else {
@@ -4386,15 +4314,12 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
} /* switch */
if(filename && *filename) {
- ftpc->file = curl_easy_unescape(conn->data, filename, 0, NULL);
- if(NULL == ftpc->file) {
- freedirs(ftpc);
- failf(data, "no memory");
- return CURLE_OUT_OF_MEMORY;
- }
- if(isBadFtpString(ftpc->file)) {
+ CURLcode result =
+ Curl_urldecode(conn->data, filename, 0, &ftpc->file, NULL, TRUE);
+
+ if(result) {
freedirs(ftpc);
- return CURLE_URL_MALFORMAT;
+ return result;
}
}
else
@@ -4412,16 +4337,18 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
if(ftpc->prevpath) {
/* prevpath is "raw" so we convert the input path before we compare the
strings */
- int dlen;
- char *path = curl_easy_unescape(conn->data, data->state.path, 0, &dlen);
- if(!path) {
+ size_t dlen;
+ char *path;
+ CURLcode result =
+ Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, FALSE);
+ if(result) {
freedirs(ftpc);
- return CURLE_OUT_OF_MEMORY;
+ return result;
}
- dlen -= ftpc->file?curlx_uztosi(strlen(ftpc->file)):0;
- if((dlen == curlx_uztosi(strlen(ftpc->prevpath))) &&
- strnequal(path, ftpc->prevpath, dlen)) {
+ dlen -= ftpc->file?strlen(ftpc->file):0;
+ if((dlen == strlen(ftpc->prevpath)) &&
+ !strncmp(path, ftpc->prevpath, dlen)) {
infof(data, "Request has same path as previous transfer\n");
ftpc->cwddone = TRUE;
}
diff --git a/lib/ftp.h b/lib/ftp.h
index 2ed5b434..3bbf2620 100644
--- a/lib/ftp.h
+++ b/lib/ftp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@ extern const struct Curl_handler Curl_handler_ftp;
extern const struct Curl_handler Curl_handler_ftps;
#endif
-CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
+CURLcode Curl_ftpsend(struct connectdata *, const char *cmd);
CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn,
int *ftpcode);
#endif /* CURL_DISABLE_FTP */
@@ -143,7 +143,7 @@ struct ftp_conn {
ftpstate state_saved; /* transfer type saved to be reloaded after
data connection is established */
curl_off_t retr_size_saved; /* Size of retrieved file saved */
- char * server_os; /* The target server operating system. */
+ char *server_os; /* The target server operating system. */
curl_off_t known_filesize; /* file size is different from -1, if wildcard
LIST parsing was done and wc_statemach set
it */
diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c
index abbf76e2..747dbbad 100644
--- a/lib/ftplistparser.c
+++ b/lib/ftplistparser.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -45,7 +45,6 @@
#include "fileinfo.h"
#include "llist.h"
#include "strtoofft.h"
-#include "rawstr.h"
#include "ftp.h"
#include "ftplistparser.h"
#include "curl_fnmatch.h"
diff --git a/lib/getenv.c b/lib/getenv.c
index 50bb79f5..89d181de 100644
--- a/lib/getenv.c
+++ b/lib/getenv.c
@@ -30,7 +30,8 @@
static
char *GetEnv(const char *variable)
{
-#ifdef _WIN32_WCE
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
+ (void)variable;
return NULL;
#else
#ifdef WIN32
diff --git a/lib/getinfo.c b/lib/getinfo.c
index 262cd934..4459a486 100644
--- a/lib/getinfo.c
+++ b/lib/getinfo.c
@@ -36,8 +36,11 @@
#include "memdebug.h"
/*
- * This is supposed to be called in the beginning of a perform() session
- * and should reset all session-info variables
+ * Initialize statistical and informational data.
+ *
+ * This function is called in curl_easy_reset, curl_easy_duphandle and at the
+ * beginning of a perform session. It must reset the session-info variables,
+ * in particular all variables in struct PureInfo.
*/
CURLcode Curl_initinfo(struct Curl_easy *data)
{
@@ -58,23 +61,32 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
info->filetime = -1; /* -1 is an illegal time and thus means unknown */
info->timecond = FALSE;
- free(info->contenttype);
- info->contenttype = NULL;
-
info->header_size = 0;
info->request_size = 0;
+ info->proxyauthavail = 0;
+ info->httpauthavail = 0;
info->numconnects = 0;
+ free(info->contenttype);
+ info->contenttype = NULL;
+
+ free(info->wouldredirect);
+ info->wouldredirect = NULL;
+
info->conn_primary_ip[0] = '\0';
info->conn_local_ip[0] = '\0';
info->conn_primary_port = 0;
info->conn_local_port = 0;
+#ifdef USE_SSL
+ Curl_ssl_free_certinfo(data);
+#endif
+
return CURLE_OK;
}
static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
- char **param_charp)
+ const char **param_charp)
{
switch(info) {
case CURLINFO_EFFECTIVE_URL:
@@ -111,6 +123,9 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
case CURLINFO_RTSP_SESSION_ID:
*param_charp = data->set.str[STRING_RTSP_SESSION_ID];
break;
+ case CURLINFO_SCHEME:
+ *param_charp = data->info.conn_scheme;
+ break;
default:
return CURLE_UNKNOWN_OPTION;
@@ -148,6 +163,9 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
case CURLINFO_SSL_VERIFYRESULT:
*param_longp = data->set.ssl.certverifyresult;
break;
+ case CURLINFO_PROXY_SSL_VERIFYRESULT:
+ *param_longp = data->set.proxy_ssl.certverifyresult;
+ break;
case CURLINFO_REDIRECT_COUNT:
*param_longp = data->set.followlocation;
break;
@@ -214,6 +232,9 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
break;
}
break;
+ case CURLINFO_PROTOCOL:
+ *param_longp = data->info.conn_protocol;
+ break;
default:
return CURLE_UNKNOWN_OPTION;
@@ -370,7 +391,7 @@ CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...)
va_list arg;
long *param_longp = NULL;
double *param_doublep = NULL;
- char **param_charp = NULL;
+ const char **param_charp = NULL;
struct curl_slist **param_slistp = NULL;
curl_socket_t *param_socketp = NULL;
int type;
@@ -384,7 +405,7 @@ CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...)
type = CURLINFO_TYPEMASK & (int)info;
switch(type) {
case CURLINFO_STRING:
- param_charp = va_arg(arg, char **);
+ param_charp = va_arg(arg, const char **);
if(param_charp)
result = getinfo_char(data, info, param_charp);
break;
diff --git a/lib/gopher.c b/lib/gopher.c
index f1efb604..a073d0ba 100644
--- a/lib/gopher.c
+++ b/lib/gopher.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -28,13 +28,11 @@
#include <curl/curl.h>
#include "transfer.h"
#include "sendf.h"
-
#include "progress.h"
-#include "strequal.h"
#include "gopher.h"
-#include "rawstr.h"
#include "select.h"
#include "url.h"
+#include "escape.h"
#include "warnless.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -83,7 +81,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
char *sel;
char *sel_org = NULL;
ssize_t amount, k;
- int len;
+ size_t len;
*done = TRUE; /* unconditionally */
@@ -107,7 +105,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
newp[i] = '\x09';
/* ... and finally unescape */
- sel = curl_easy_unescape(data, newp, 0, &len);
+ result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE);
if(!sel)
return CURLE_OUT_OF_MEMORY;
sel_org = sel;
@@ -121,20 +119,17 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
result = Curl_write(conn, sockfd, sel, k, &amount);
if(!result) { /* Which may not have written it all! */
result = Curl_client_write(conn, CLIENTWRITE_HEADER, sel, amount);
- if(result) {
- free(sel_org);
- return result;
- }
+ if(result)
+ break;
+
k -= amount;
sel += amount;
if(k < 1)
break; /* but it did write it all */
}
- else {
- failf(data, "Failed sending Gopher request");
- free(sel_org);
- return result;
- }
+ else
+ break;
+
/* Don't busyloop. The entire loop thing is a work-around as it causes a
BLOCKING behavior which is a NO-NO. This function should rather be
split up in a do and a doing piece where the pieces that aren't
@@ -144,14 +139,18 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
Wait a while for the socket to be writable. Note that this doesn't
acknowledge the timeout.
*/
- Curl_socket_ready(CURL_SOCKET_BAD, sockfd, 100);
+ if(SOCKET_WRITABLE(sockfd, 100) < 0) {
+ result = CURLE_SEND_ERROR;
+ break;
+ }
}
free(sel_org);
- /* We can use Curl_sendf to send the terminal \r\n relatively safely and
- save allocing another string/doing another _write loop. */
- result = Curl_sendf(sockfd, conn, "\r\n");
+ if(!result)
+ /* We can use Curl_sendf to send the terminal \r\n relatively safely and
+ save allocing another string/doing another _write loop. */
+ result = Curl_sendf(sockfd, conn, "\r\n");
if(result) {
failf(data, "Failed sending Gopher request");
return result;
diff --git a/lib/hash.c b/lib/hash.c
index 937381b6..72a7a9b7 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -291,9 +291,9 @@ Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
}
}
-size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num)
+size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num)
{
- const char* key_str = (const char *) key;
+ const char *key_str = (const char *) key;
const char *end = key_str + key_length;
unsigned long h = 5381;
diff --git a/lib/hash.h b/lib/hash.h
index 57a17f02..a5a6cac7 100644
--- a/lib/hash.h
+++ b/lib/hash.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,16 +29,16 @@
#include "llist.h"
/* Hash function prototype */
-typedef size_t (*hash_function) (void* key,
+typedef size_t (*hash_function) (void *key,
size_t key_length,
size_t slots_num);
/*
Comparator function prototype. Compares two keys.
*/
-typedef size_t (*comp_function) (void* key1,
+typedef size_t (*comp_function) (void *key1,
size_t key1_len,
- void*key2,
+ void *key2,
size_t key2_len);
typedef void (*curl_hash_dtor)(void *);
@@ -76,7 +76,7 @@ int Curl_hash_init(struct curl_hash *h,
void *Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p);
int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len);
-void *Curl_hash_pick(struct curl_hash *, void * key, size_t key_len);
+void *Curl_hash_pick(struct curl_hash *, void *key, size_t key_len);
void Curl_hash_apply(struct curl_hash *h, void *user,
void (*cb)(void *user, void *ptr));
int Curl_hash_count(struct curl_hash *h);
@@ -84,10 +84,9 @@ void Curl_hash_destroy(struct curl_hash *h);
void Curl_hash_clean(struct curl_hash *h);
void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
int (*comp)(void *, void *));
-size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num);
-size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2,
+size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num);
+size_t Curl_str_key_compare(void *k1, size_t key1_len, void *k2,
size_t key2_len);
-
void Curl_hash_start_iterate(struct curl_hash *hash,
struct curl_hash_iterator *iter);
struct curl_hash_element *
diff --git a/lib/hmac.c b/lib/hmac.c
index 3df47158..dae95054 100644
--- a/lib/hmac.c
+++ b/lib/hmac.c
@@ -49,12 +49,12 @@ static const unsigned char hmac_opad = 0x5C;
HMAC_context *
Curl_HMAC_init(const HMAC_params * hashparams,
- const unsigned char * key,
+ const unsigned char *key,
unsigned int keylen)
{
size_t i;
- HMAC_context * ctxt;
- unsigned char * hkey;
+ HMAC_context *ctxt;
+ unsigned char *hkey;
unsigned char b;
/* Create HMAC context. */
@@ -101,7 +101,7 @@ Curl_HMAC_init(const HMAC_params * hashparams,
}
int Curl_HMAC_update(HMAC_context * ctxt,
- const unsigned char * data,
+ const unsigned char *data,
unsigned int len)
{
/* Update first hash calculation. */
@@ -110,7 +110,7 @@ int Curl_HMAC_update(HMAC_context * ctxt,
}
-int Curl_HMAC_final(HMAC_context * ctxt, unsigned char * result)
+int Curl_HMAC_final(HMAC_context *ctxt, unsigned char *result)
{
const HMAC_params * hashparams = ctxt->hmac_hash;
diff --git a/lib/hostcheck.c b/lib/hostcheck.c
index 4db9e6ba..f545254f 100644
--- a/lib/hostcheck.c
+++ b/lib/hostcheck.c
@@ -30,7 +30,7 @@
#endif
#include "hostcheck.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "inet_pton.h"
#include "curl_memory.h"
@@ -77,7 +77,7 @@ static int hostmatch(char *hostname, char *pattern)
pattern_wildcard = strchr(pattern, '*');
if(pattern_wildcard == NULL)
- return Curl_raw_equal(pattern, hostname) ?
+ return strcasecompare(pattern, hostname) ?
CURL_HOST_MATCH : CURL_HOST_NOMATCH;
/* detect IP address as hostname and fail the match if so */
@@ -94,16 +94,16 @@ static int hostmatch(char *hostname, char *pattern)
pattern_label_end = strchr(pattern, '.');
if(pattern_label_end == NULL || strchr(pattern_label_end+1, '.') == NULL ||
pattern_wildcard > pattern_label_end ||
- Curl_raw_nequal(pattern, "xn--", 4)) {
+ strncasecompare(pattern, "xn--", 4)) {
wildcard_enabled = 0;
}
if(!wildcard_enabled)
- return Curl_raw_equal(pattern, hostname) ?
+ return strcasecompare(pattern, hostname) ?
CURL_HOST_MATCH : CURL_HOST_NOMATCH;
hostname_label_end = strchr(hostname, '.');
if(hostname_label_end == NULL ||
- !Curl_raw_equal(pattern_label_end, hostname_label_end))
+ !strcasecompare(pattern_label_end, hostname_label_end))
return CURL_HOST_NOMATCH;
/* The wildcard must match at least one character, so the left-most
@@ -114,8 +114,8 @@ static int hostmatch(char *hostname, char *pattern)
prefixlen = pattern_wildcard - pattern;
suffixlen = pattern_label_end - (pattern_wildcard+1);
- return Curl_raw_nequal(pattern, hostname, prefixlen) &&
- Curl_raw_nequal(pattern_wildcard+1, hostname_label_end - suffixlen,
+ return strncasecompare(pattern, hostname, prefixlen) &&
+ strncasecompare(pattern_wildcard+1, hostname_label_end - suffixlen,
suffixlen) ?
CURL_HOST_MATCH : CURL_HOST_NOMATCH;
}
diff --git a/lib/hostip.c b/lib/hostip.c
index f2d98416..464fa4e1 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -568,7 +568,7 @@ int Curl_resolv_timeout(struct connectdata *conn,
const char *hostname,
int port,
struct Curl_dns_entry **entry,
- long timeoutms)
+ time_t timeoutms)
{
#ifdef USE_ALARM_TIMEOUT
#ifdef HAVE_SIGACTION
@@ -603,11 +603,14 @@ int Curl_resolv_timeout(struct connectdata *conn,
/* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
return Curl_resolv(conn, hostname, port, entry);
- if(timeout < 1000)
+ if(timeout < 1000) {
/* The alarm() function only provides integer second resolution, so if
we want to wait less than one second we must bail out already now. */
+ failf(data,
+ "remaining timeout of %ld too small to resolve via SIGALRM method",
+ timeout);
return CURLRESOLV_TIMEDOUT;
-
+ }
/* This allows us to time-out from the name resolver, as the timeout
will generate a signal and we will siglongjmp() from that here.
This technique has problems (see alarmfunc).
diff --git a/lib/hostip.h b/lib/hostip.h
index 9098ee39..0924d545 100644
--- a/lib/hostip.h
+++ b/lib/hostip.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -87,7 +87,7 @@ int Curl_resolv(struct connectdata *conn, const char *hostname,
int port, struct Curl_dns_entry **dnsentry);
int Curl_resolv_timeout(struct connectdata *conn, const char *hostname,
int port, struct Curl_dns_entry **dnsentry,
- long timeoutms);
+ time_t timeoutms);
#ifdef CURLRES_IPV6
/*
@@ -143,7 +143,7 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
#endif
/* IPv4 threadsafe resolve function used for synch and asynch builds */
-Curl_addrinfo *Curl_ipv4_resolve_r(const char * hostname, int port);
+Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
CURLcode Curl_async_resolved(struct connectdata *conn,
bool *protocol_connect);
diff --git a/lib/hostip4.c b/lib/hostip4.c
index 15895d7c..e459328a 100644
--- a/lib/hostip4.c
+++ b/lib/hostip4.c
@@ -291,7 +291,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
* gethostbyname() is the preferred one.
*/
else {
- h = gethostbyname((void*)hostname);
+ h = gethostbyname((void *)hostname);
#endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
}
diff --git a/lib/http.c b/lib/http.c
index 378d8f77..36317f56 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -53,7 +53,6 @@
#include "progress.h"
#include "curl_base64.h"
#include "cookie.h"
-#include "strequal.h"
#include "vauth/vauth.h"
#include "vtls/vtls.h"
#include "http_digest.h"
@@ -68,7 +67,7 @@
#include "parsedate.h" /* for the week day and month names */
#include "strtoofft.h"
#include "multiif.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "content_encoding.h"
#include "http_proxy.h"
#include "warnless.h"
@@ -77,6 +76,7 @@
#include "pipeline.h"
#include "http2.h"
#include "connect.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -182,7 +182,7 @@ char *Curl_checkheaders(const struct connectdata *conn,
struct Curl_easy *data = conn->data;
for(head = data->set.headers;head; head=head->next) {
- if(Curl_raw_nequal(head->data, thisheader, thislen))
+ if(strncasecompare(head->data, thisheader, thislen))
return head->data;
}
@@ -208,7 +208,7 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
for(head = (conn->bits.proxy && data->set.sep_headers) ?
data->set.proxyheaders : data->set.headers;
head; head=head->next) {
- if(Curl_raw_nequal(head->data, thisheader, thislen))
+ if(strncasecompare(head->data, thisheader, thislen))
return head->data;
}
@@ -288,8 +288,8 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
if(proxy) {
userp = &conn->allocptr.proxyuserpwd;
- user = conn->proxyuser;
- pwd = conn->proxypasswd;
+ user = conn->http_proxy.user;
+ pwd = conn->http_proxy.passwd;
}
else {
userp = &conn->allocptr.userpwd;
@@ -462,7 +462,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
#endif
/* This is not NTLM or many bytes left to send: close */
- connclose(conn, "Mid-auth HTTP and much data left to send");
+ streamclose(conn, "Mid-auth HTTP and much data left to send");
data->req.size = 0; /* don't download any more than 0 bytes */
/* There still is data left to send, but this connection is marked for
@@ -642,7 +642,7 @@ output_auth_headers(struct connectdata *conn,
if(auth) {
infof(data, "%s auth using %s with user '%s'\n",
proxy ? "Proxy" : "Server", auth,
- proxy ? (conn->proxyuser ? conn->proxyuser : "") :
+ proxy ? (conn->http_proxy.user ? conn->http_proxy.user : "") :
(conn->user ? conn->user : ""));
authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
}
@@ -726,7 +726,7 @@ Curl_http_output_auth(struct connectdata *conn,
conn->bits.netrc ||
!data->state.first_host ||
data->set.http_disable_hostname_check_before_authentication ||
- Curl_raw_equal(data->state.first_host, conn->host.name)) {
+ strcasecompare(data->state.first_host, conn->host.name)) {
result = output_auth_headers(conn, authhost, request, path, FALSE);
}
else
@@ -784,23 +784,27 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
while(*auth) {
#ifdef USE_SPNEGO
if(checkprefix("Negotiate", auth)) {
- *availp |= CURLAUTH_NEGOTIATE;
- authp->avail |= CURLAUTH_NEGOTIATE;
-
- if(authp->picked == CURLAUTH_NEGOTIATE) {
- 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;
+ if((authp->avail & CURLAUTH_NEGOTIATE) ||
+ Curl_auth_is_spnego_supported()) {
+ *availp |= CURLAUTH_NEGOTIATE;
+ authp->avail |= CURLAUTH_NEGOTIATE;
+
+ if(authp->picked == CURLAUTH_NEGOTIATE) {
+ 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;
+ }
+ else
+ data->state.authproblem = TRUE;
}
- else
- data->state.authproblem = TRUE;
}
}
}
@@ -809,39 +813,44 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
#ifdef USE_NTLM
/* NTLM support requires the SSL crypto libs */
if(checkprefix("NTLM", auth)) {
- *availp |= CURLAUTH_NTLM;
- authp->avail |= CURLAUTH_NTLM;
- if(authp->picked == CURLAUTH_NTLM ||
- authp->picked == CURLAUTH_NTLM_WB) {
- /* NTLM authentication is picked and activated */
- CURLcode result = Curl_input_ntlm(conn, proxy, auth);
- if(!result) {
- data->state.authproblem = FALSE;
+ if((authp->avail & CURLAUTH_NTLM) ||
+ (authp->avail & CURLAUTH_NTLM_WB) ||
+ Curl_auth_is_ntlm_supported()) {
+ *availp |= CURLAUTH_NTLM;
+ authp->avail |= CURLAUTH_NTLM;
+
+ if(authp->picked == CURLAUTH_NTLM ||
+ authp->picked == CURLAUTH_NTLM_WB) {
+ /* NTLM authentication is picked and activated */
+ CURLcode result = Curl_input_ntlm(conn, proxy, auth);
+ if(!result) {
+ data->state.authproblem = FALSE;
#ifdef NTLM_WB_ENABLED
- if(authp->picked == CURLAUTH_NTLM_WB) {
- *availp &= ~CURLAUTH_NTLM;
- authp->avail &= ~CURLAUTH_NTLM;
- *availp |= CURLAUTH_NTLM_WB;
- authp->avail |= CURLAUTH_NTLM_WB;
-
- /* Get the challenge-message which will be passed to
- * ntlm_auth for generating the type 3 message later */
- while(*auth && ISSPACE(*auth))
- auth++;
- if(checkprefix("NTLM", auth)) {
- auth += strlen("NTLM");
+ if(authp->picked == CURLAUTH_NTLM_WB) {
+ *availp &= ~CURLAUTH_NTLM;
+ authp->avail &= ~CURLAUTH_NTLM;
+ *availp |= CURLAUTH_NTLM_WB;
+ authp->avail |= CURLAUTH_NTLM_WB;
+
+ /* Get the challenge-message which will be passed to
+ * ntlm_auth for generating the type 3 message later */
while(*auth && ISSPACE(*auth))
auth++;
- if(*auth)
- if((conn->challenge_header = strdup(auth)) == NULL)
- return CURLE_OUT_OF_MEMORY;
+ if(checkprefix("NTLM", auth)) {
+ auth += strlen("NTLM");
+ while(*auth && ISSPACE(*auth))
+ auth++;
+ if(*auth)
+ if((conn->challenge_header = strdup(auth)) == NULL)
+ return CURLE_OUT_OF_MEMORY;
+ }
}
- }
#endif
- }
- else {
- infof(data, "Authentication problem. Ignoring this.\n");
- data->state.authproblem = TRUE;
+ }
+ else {
+ infof(data, "Authentication problem. Ignoring this.\n");
+ data->state.authproblem = TRUE;
+ }
}
}
}
@@ -849,18 +858,18 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
#endif
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(checkprefix("Digest", auth)) {
- if((authp->avail & CURLAUTH_DIGEST) != 0) {
+ if((authp->avail & CURLAUTH_DIGEST) != 0)
infof(data, "Ignoring duplicate digest auth header.\n");
- }
- else {
+ else if(Curl_auth_is_digest_supported()) {
CURLcode result;
+
*availp |= CURLAUTH_DIGEST;
authp->avail |= CURLAUTH_DIGEST;
/* We call this function on input Digest headers even if Digest
* authentication isn't activated yet, as we need to store the
- * incoming data from this header in case we are gonna use
- * Digest. */
+ * incoming data from this header in case we are going to use
+ * Digest */
result = Curl_input_digest(conn, proxy, auth);
if(result) {
infof(data, "Authentication problem. Ignoring this.\n");
@@ -1090,7 +1099,9 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
return result;
}
- if((conn->handler->flags & PROTOPT_SSL) && conn->httpversion != 20) {
+ if((conn->handler->flags & PROTOPT_SSL ||
+ conn->http_proxy.proxytype == CURLPROXY_HTTPS)
+ && conn->httpversion != 20) {
/* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
when we speak HTTPS, as if only a fraction of it is sent now, this data
needs to fit into the normal read-callback buffer later on and that
@@ -1247,14 +1258,13 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
if(in->buffer)
/* we have a buffer, enlarge the existing one */
- new_rb = realloc(in->buffer, new_size);
+ new_rb = Curl_saferealloc(in->buffer, new_size);
else
/* create a new buffer */
new_rb = malloc(new_size);
if(!new_rb) {
/* If we failed, we cleanup the whole buffer and return error */
- Curl_safefree(in->buffer);
free(in);
return CURLE_OUT_OF_MEMORY;
}
@@ -1296,7 +1306,7 @@ Curl_compareheader(const char *headerline, /* line to check */
const char *start;
const char *end;
- if(!Curl_raw_nequal(headerline, header, hlen))
+ if(!strncasecompare(headerline, header, hlen))
return FALSE; /* doesn't start with header */
/* pass the header */
@@ -1322,7 +1332,7 @@ Curl_compareheader(const char *headerline, /* line to check */
/* find the content string in the rest of the line */
for(;len>=clen;len--, start++) {
- if(Curl_raw_nequal(start, content, clen))
+ if(strncasecompare(start, content, clen))
return TRUE; /* match! */
}
@@ -1342,10 +1352,13 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
connkeep(conn, "HTTP default");
/* the CONNECT procedure might not have been completed */
- result = Curl_proxy_connect(conn);
+ result = Curl_proxy_connect(conn, FIRSTSOCKET);
if(result)
return result;
+ if(CONNECT_FIRSTSOCKET_PROXY_SSL())
+ return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */
+
if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
/* nothing else to do except wait right now - we're not done here. */
return CURLE_OK;
@@ -1388,50 +1401,16 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done)
return result;
}
-#endif
-#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
- defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \
- defined(USE_MBEDTLS)
-/* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only.
- It should be made to query the generic SSL layer instead. */
static int https_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks)
{
- if(conn->handler->flags & PROTOPT_SSL) {
- struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
-
- if(!numsocks)
- return GETSOCK_BLANK;
-
- if(connssl->connecting_state == ssl_connect_2_writing) {
- /* write mode */
- socks[0] = conn->sock[FIRSTSOCKET];
- return GETSOCK_WRITESOCK(0);
- }
- else if(connssl->connecting_state == ssl_connect_2_reading) {
- /* read mode */
- socks[0] = conn->sock[FIRSTSOCKET];
- return GETSOCK_READSOCK(0);
- }
- }
-
- return CURLE_OK;
-}
-#else
-#ifdef USE_SSL
-static int https_getsock(struct connectdata *conn,
- curl_socket_t *socks,
- int numsocks)
-{
- (void)conn;
- (void)socks;
- (void)numsocks;
+ if(conn->handler->flags & PROTOPT_SSL)
+ return Curl_ssl_getsock(conn, socks, numsocks);
return GETSOCK_BLANK;
}
#endif /* USE_SSL */
-#endif /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL */
/*
* Curl_http_done() gets called after a single HTTP request has been
@@ -1443,9 +1422,8 @@ CURLcode Curl_http_done(struct connectdata *conn,
{
struct Curl_easy *data = conn->data;
struct HTTP *http = data->req.protop;
-#ifdef USE_NGHTTP2
- struct http_conn *httpc = &conn->proto.httpc;
-#endif
+
+ infof(data, "Curl_http_done: called premature == %d\n", premature);
Curl_unencode_cleanup(conn);
@@ -1458,7 +1436,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
* Do not close CONNECT_ONLY connections. */
if((data->req.httpcode != 401) && (data->req.httpcode != 407) &&
!data->set.connect_only)
- connclose(conn, "Negotiate transfer completed");
+ streamclose(conn, "Negotiate transfer completed");
Curl_cleanup_negotiate(data);
}
#endif
@@ -1475,27 +1453,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
http->send_buffer = NULL; /* clear the pointer */
}
-#ifdef USE_NGHTTP2
- if(http->header_recvbuf) {
- DEBUGF(infof(data, "free header_recvbuf!!\n"));
- Curl_add_buffer_free(http->header_recvbuf);
- http->header_recvbuf = NULL; /* clear the pointer */
- Curl_add_buffer_free(http->trailer_recvbuf);
- http->trailer_recvbuf = NULL; /* clear the pointer */
- if(http->push_headers) {
- /* if they weren't used and then freed before */
- for(; http->push_headers_used > 0; --http->push_headers_used) {
- free(http->push_headers[http->push_headers_used - 1]);
- }
- free(http->push_headers);
- http->push_headers = NULL;
- }
- }
- if(http->stream_id) {
- nghttp2_session_set_stream_user_data(httpc->h2, http->stream_id, 0);
- http->stream_id = 0;
- }
-#endif
+ Curl_http2_done(conn, premature);
if(HTTPREQ_POST_FORM == data->set.httpreq) {
data->req.bytecount = http->readbytecount + http->writebytecount;
@@ -1660,6 +1618,10 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
Connection: */
checkprefix("Connection", headers->data))
;
+ else if((conn->httpversion == 20) &&
+ checkprefix("Transfer-Encoding:", headers->data))
+ /* HTTP/2 doesn't support chunked requests */
+ ;
else {
CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
headers->data);
@@ -1946,47 +1908,42 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
#endif
- if(conn->httpversion == 20)
- /* In HTTP2 forbids Transfer-Encoding: chunked */
- ptr = NULL;
+ ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
+ if(ptr) {
+ /* Some kind of TE is requested, check if 'chunked' is chosen */
+ data->req.upload_chunky =
+ Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
+ }
else {
- ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
- if(ptr) {
- /* Some kind of TE is requested, check if 'chunked' is chosen */
- data->req.upload_chunky =
- Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
- }
- else {
- if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
- data->set.upload &&
- (data->state.infilesize == -1)) {
- if(conn->bits.authneg)
- /* don't enable chunked during auth neg */
- ;
- else if(use_http_1_1plus(data, conn)) {
- /* HTTP, upload, unknown file size and not HTTP 1.0 */
- data->req.upload_chunky = TRUE;
- }
- else {
- failf(data, "Chunky upload is not supported by HTTP 1.0");
- return CURLE_UPLOAD_FAILED;
- }
+ if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
+ data->set.upload &&
+ (data->state.infilesize == -1)) {
+ if(conn->bits.authneg)
+ /* don't enable chunked during auth neg */
+ ;
+ else if(use_http_1_1plus(data, conn)) {
+ /* HTTP, upload, unknown file size and not HTTP 1.0 */
+ data->req.upload_chunky = TRUE;
}
else {
- /* else, no chunky upload */
- data->req.upload_chunky = FALSE;
+ failf(data, "Chunky upload is not supported by HTTP 1.0");
+ return CURLE_UPLOAD_FAILED;
}
-
- if(data->req.upload_chunky)
- te = "Transfer-Encoding: chunked\r\n";
}
+ else {
+ /* else, no chunky upload */
+ data->req.upload_chunky = FALSE;
+ }
+
+ if(data->req.upload_chunky)
+ te = "Transfer-Encoding: chunked\r\n";
}
Curl_safefree(conn->allocptr.host);
ptr = Curl_checkheaders(conn, "Host:");
if(ptr && (!data->state.this_is_a_follow ||
- Curl_raw_equal(data->state.first_host, conn->host.name))) {
+ strcasecompare(data->state.first_host, conn->host.name))) {
#if !defined(CURL_DISABLE_COOKIES)
/* If we have a given custom Host: header, we extract the host name in
order to possibly use it for cookie reasons later on. We only allow the
@@ -2305,6 +2262,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
"%s" /* TE: */
"%s" /* accept-encoding */
"%s" /* referer */
+ "%s" /* Proxy-Connection */
"%s",/* transfer-encoding */
ftp_typecode,
@@ -2327,6 +2285,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->allocptr.accept_encoding:"",
(data->change.referer && conn->allocptr.ref)?
conn->allocptr.ref:"" /* Referer: <data> */,
+ (conn->bits.httpproxy &&
+ !conn->bits.tunnel_proxy &&
+ !Curl_checkProxyheaders(conn, "Proxy-Connection:"))?
+ "Proxy-Connection: Keep-Alive\r\n":"",
te
);
@@ -2392,7 +2354,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
co = co->next; /* next cookie please */
}
- Curl_cookie_freelist(store, FALSE); /* free the cookie list */
+ Curl_cookie_freelist(store);
}
if(addcookies && !result) {
if(!count)
@@ -2768,6 +2730,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
}
+ if((conn->httpversion == 20) && data->req.upload_chunky)
+ /* upload_chunky was set above to set up the request in a chunky fashion,
+ but is disabled here again to avoid that the chunked encoded version is
+ actually used when sending the request body over h2 */
+ data->req.upload_chunky = FALSE;
return result;
}
@@ -3040,19 +3007,19 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
#endif /* CURL_DOES_CONVERSIONS */
if(100 <= k->httpcode && 199 >= k->httpcode) {
- /*
- * We have made a HTTP PUT or POST and this is 1.1-lingo
- * that tells us that the server is OK with this and ready
- * to receive the data.
- * However, we'll get more headers now so we must get
- * back into the header-parsing state!
- */
- k->header = TRUE;
- k->headerline = 0; /* restart the header line counter */
-
/* "A user agent MAY ignore unexpected 1xx status responses." */
switch(k->httpcode) {
case 100:
+ /*
+ * We have made a HTTP PUT or POST and this is 1.1-lingo
+ * that tells us that the server is OK with this and ready
+ * to receive the data.
+ * However, we'll get more headers now so we must get
+ * back into the header-parsing state!
+ */
+ k->header = TRUE;
+ k->headerline = 0; /* restart the header line counter */
+
/* if we did wait for this do enable write now! */
if(k->exp100 > EXP100_SEND_DATA) {
k->exp100 = EXP100_SEND_DATA;
@@ -3062,9 +3029,14 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
case 101:
/* Switching Protocols */
if(k->upgr101 == UPGR101_REQUESTED) {
+ /* Switching to HTTP/2 */
infof(data, "Received 101\n");
k->upgr101 = UPGR101_RECEIVED;
+ /* we'll get more headers (HTTP/2 response) */
+ k->header = TRUE;
+ k->headerline = 0; /* restart the header line counter */
+
/* switch to http2 now. The bytes after response headers
are also processed here, otherwise they are lost. */
result = Curl_http2_switched(conn, k->str, *nread);
@@ -3072,8 +3044,16 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
return result;
*nread = 0;
}
+ else {
+ /* Switching to another protocol (e.g. WebSocket) */
+ k->header = FALSE; /* no more header to parse! */
+ }
break;
default:
+ /* the status code 1xx indicates a provisional response, so
+ we'll get another set of headers */
+ k->header = TRUE;
+ k->headerline = 0; /* restart the header line counter */
break;
}
}
@@ -3091,7 +3071,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
signal the end of the document. */
infof(data, "no chunk, no close, no size. Assume close to "
"signal end\n");
- connclose(conn, "HTTP: No end-of-message indicator");
+ streamclose(conn, "HTTP: No end-of-message indicator");
}
}
@@ -3171,12 +3151,21 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* connection for closure after we've read the entire response.
*/
if(!k->upload_done) {
- infof(data, "HTTP error before end of send, stop sending\n");
- connclose(conn, "Stop sending data before everything sent");
- k->upload_done = TRUE;
- k->keepon &= ~KEEP_SEND; /* don't send */
- if(data->state.expect100header)
- k->exp100 = EXP100_FAILED;
+ if(data->set.http_keep_sending_on_error) {
+ infof(data, "HTTP error before end of send, keep sending\n");
+ if(k->exp100 > EXP100_SEND_DATA) {
+ k->exp100 = EXP100_SEND_DATA;
+ k->keepon |= KEEP_SEND;
+ }
+ }
+ else {
+ infof(data, "HTTP error before end of send, stop sending\n");
+ streamclose(conn, "Stop sending data before everything sent");
+ k->upload_done = TRUE;
+ k->keepon &= ~KEEP_SEND; /* don't send */
+ if(data->state.expect100header)
+ k->exp100 = EXP100_FAILED;
+ }
}
break;
@@ -3476,7 +3465,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/* Negative Content-Length is really odd, and we know it
happens for example when older Apache servers send large
files */
- connclose(conn, "negative content-length");
+ streamclose(conn, "negative content-length");
infof(data, "Negative content-length: %" CURL_FORMAT_CURL_OFF_T
", closing after transfer\n", contentlength);
}
@@ -3549,7 +3538,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* the connection will close when this request has been
* served.
*/
- connclose(conn, "Connection: close used");
+ streamclose(conn, "Connection: close used");
}
else if(checkprefix("Transfer-Encoding:", k->p)) {
/* One or more encodings. We check for chunked and/or a compression
diff --git a/lib/http.h b/lib/http.h
index 65290055..9fb669c9 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -168,6 +168,7 @@ struct HTTP {
const uint8_t *pausedata; /* pointer to data received in on_data_chunk */
size_t pauselen; /* the number of bytes left in data */
bool closed; /* TRUE on HTTP2 stream close */
+ bool close_handled; /* TRUE if stream closure is handled by libcurl */
uint32_t error_code; /* HTTP/2 error code */
char *mem; /* points to a buffer in memory to store received data */
diff --git a/lib/http2.c b/lib/http2.c
index efc082dd..2ef17314 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -29,13 +29,13 @@
#include "http.h"
#include "sendf.h"
#include "curl_base64.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "multiif.h"
#include "conncache.h"
#include "url.h"
#include "connect.h"
#include "strtoofft.h"
-
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -59,6 +59,8 @@
#define nghttp2_session_callbacks_set_error_callback(x,y)
#endif
+#define HTTP2_HUGE_WINDOW_SIZE (1 << 30)
+
/*
* Curl_http2_init_state() is called when the easy handle is created and
* allows for HTTP/2 specific init of state.
@@ -92,8 +94,9 @@ static int http2_perform_getsock(const struct connectdata *conn,
because of renegotiation. */
sock[0] = conn->sock[FIRSTSOCKET];
- if(nghttp2_session_want_read(c->h2))
- bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
+ /* in a HTTP/2 connection we can basically always get a frame so we should
+ always be ready for one */
+ bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
if(nghttp2_session_want_write(c->h2))
bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
@@ -150,6 +153,7 @@ void Curl_http2_setup_req(struct Curl_easy *data)
http->pauselen = 0;
http->error_code = NGHTTP2_NO_ERROR;
http->closed = FALSE;
+ http->close_handled = FALSE;
http->mem = data->state.buffer;
http->len = BUFSIZE;
http->memlen = 0;
@@ -184,7 +188,7 @@ const struct Curl_handler Curl_handler_http2 = {
ZERO_NULL, /* readwrite */
PORT_HTTP, /* defport */
CURLPROTO_HTTP, /* protocol */
- PROTOPT_NONE /* flags */
+ PROTOPT_STREAM /* flags */
};
const struct Curl_handler Curl_handler_http2_ssl = {
@@ -204,7 +208,7 @@ const struct Curl_handler Curl_handler_http2_ssl = {
ZERO_NULL, /* readwrite */
PORT_HTTP, /* defport */
CURLPROTO_HTTPS, /* protocol */
- PROTOPT_SSL /* flags */
+ PROTOPT_SSL | PROTOPT_STREAM /* flags */
};
/*
@@ -221,7 +225,8 @@ int Curl_http2_ver(char *p, size_t len)
https://tools.ietf.org/html/rfc7540#page-77
nghttp2_error_code enums are identical.
*/
-const char *Curl_http2_strerror(uint32_t err) {
+const char *Curl_http2_strerror(uint32_t err)
+{
#ifndef NGHTTP2_HAS_HTTP2_STRERROR
const char *str[] = {
"NO_ERROR", /* 0x0 */
@@ -317,7 +322,7 @@ char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
the middle of header, it could be matched in middle of the value,
this is because we do prefix match.*/
if(!h || !GOOD_EASY_HANDLE(h->data) || !header || !header[0] ||
- Curl_raw_equal(header, ":") || strchr(header + 1, ':'))
+ !strcmp(header, ":") || strchr(header + 1, ':'))
return NULL;
else {
struct HTTP *stream = h->data->req.protop;
@@ -488,8 +493,11 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
}
stream = data_s->req.protop;
- if(!stream)
+ if(!stream) {
+ DEBUGF(infof(conn->data, "No proto pointer for stream: %x\n",
+ stream_id));
return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
DEBUGF(infof(data_s, "on_frame_recv() header %x stream %x\n",
frame->hd.type, stream_id));
@@ -547,7 +555,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
/* if we receive data for another handle, wake that up */
if(conn_s->data != data_s)
- Curl_expire(data_s, 1);
+ Curl_expire(data_s, 0);
}
break;
case NGHTTP2_PUSH_PROMISE:
@@ -621,8 +629,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
/* if we receive data for another handle, wake that up */
if(conn->data != data_s)
- Curl_expire(data_s, 1); /* TODO: fix so that this can be set to 0 for
- immediately? */
+ Curl_expire(data_s, 0);
DEBUGF(infof(data_s, "%zu data received for stream %u "
"(%zu left in buffer %p, total %zu)\n",
@@ -837,10 +844,9 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
stream->push_headers_alloc) {
char **headp;
stream->push_headers_alloc *= 2;
- headp = realloc(stream->push_headers,
- stream->push_headers_alloc * sizeof(char *));
+ headp = Curl_saferealloc(stream->push_headers,
+ stream->push_headers_alloc * sizeof(char *));
if(!headp) {
- free(stream->push_headers);
stream->push_headers = NULL;
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
@@ -883,7 +889,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
Curl_add_buffer(stream->header_recvbuf, " \r\n", 3);
/* if we receive data for another handle, wake that up */
if(conn->data != data_s)
- Curl_expire(data_s, 1);
+ Curl_expire(data_s, 0);
DEBUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
stream->status_code, data_s));
@@ -899,7 +905,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
Curl_add_buffer(stream->header_recvbuf, "\r\n", 2);
/* if we receive data for another handle, wake that up */
if(conn->data != data_s)
- Curl_expire(data_s, 1);
+ Curl_expire(data_s, 0);
DEBUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
value));
@@ -941,11 +947,12 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
memcpy(buf, stream->upload_mem, nread);
stream->upload_mem += nread;
stream->upload_len -= nread;
- stream->upload_left -= nread;
+ if(data_s->state.infilesize != -1)
+ stream->upload_left -= nread;
}
if(stream->upload_left == 0)
- *data_flags = 1;
+ *data_flags = NGHTTP2_DATA_FLAG_EOF;
else if(nread == 0)
return NGHTTP2_ERR_DEFERRED;
@@ -961,7 +968,7 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
*/
static nghttp2_settings_entry settings[] = {
{ NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 },
- { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE },
+ { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, HTTP2_HUGE_WINDOW_SIZE },
};
#define H2_BUFSIZE 32768
@@ -979,6 +986,43 @@ static int error_callback(nghttp2_session *session,
}
#endif
+void Curl_http2_done(struct connectdata *conn, bool premature)
+{
+ struct Curl_easy *data = conn->data;
+ struct HTTP *http = data->req.protop;
+ struct http_conn *httpc = &conn->proto.httpc;
+
+ if(http->header_recvbuf) {
+ DEBUGF(infof(data, "free header_recvbuf!!\n"));
+ Curl_add_buffer_free(http->header_recvbuf);
+ http->header_recvbuf = NULL; /* clear the pointer */
+ Curl_add_buffer_free(http->trailer_recvbuf);
+ http->trailer_recvbuf = NULL; /* clear the pointer */
+ if(http->push_headers) {
+ /* if they weren't used and then freed before */
+ for(; http->push_headers_used > 0; --http->push_headers_used) {
+ free(http->push_headers[http->push_headers_used - 1]);
+ }
+ free(http->push_headers);
+ http->push_headers = NULL;
+ }
+ }
+
+ if(premature) {
+ /* RST_STREAM */
+ nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE, http->stream_id,
+ NGHTTP2_STREAM_CLOSED);
+ if(http->stream_id == httpc->pause_stream_id) {
+ infof(data, "stopped the pause stream!\n");
+ httpc->pause_stream_id = 0;
+ }
+ }
+ if(http->stream_id) {
+ nghttp2_session_set_stream_user_data(httpc->h2, http->stream_id, 0);
+ http->stream_id = 0;
+ }
+}
+
/*
* Initialize nghttp2 for a Curl connection
*/
@@ -1091,9 +1135,10 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
/*
* Returns nonzero if current HTTP/2 session should be closed.
*/
-static int should_close_session(struct http_conn *httpc) {
+static int should_close_session(struct http_conn *httpc)
+{
return httpc->drain_total == 0 && !nghttp2_session_want_read(httpc->h2) &&
- !nghttp2_session_want_write(httpc->h2);
+ !nghttp2_session_want_write(httpc->h2);
}
static int h2_session_send(struct Curl_easy *data,
@@ -1107,7 +1152,8 @@ static int h2_session_send(struct Curl_easy *data,
*/
static int h2_process_pending_input(struct Curl_easy *data,
struct http_conn *httpc,
- CURLcode *err) {
+ CURLcode *err)
+{
ssize_t nread;
char *inbuf;
ssize_t rv;
@@ -1155,9 +1201,41 @@ static int h2_process_pending_input(struct Curl_easy *data,
return 0;
}
+/*
+ * Called from transfer.c:done_sending when we stop uploading.
+ */
+CURLcode Curl_http2_done_sending(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ if((conn->handler == &Curl_handler_http2_ssl) ||
+ (conn->handler == &Curl_handler_http2)) {
+ /* make sure this is only attempted for HTTP/2 transfers */
+
+ struct HTTP *stream = conn->data->req.protop;
+
+ if(stream->upload_left) {
+ /* If the stream still thinks there's data left to upload. */
+ struct http_conn *httpc = &conn->proto.httpc;
+ nghttp2_session *h2 = httpc->h2;
+
+ stream->upload_left = 0; /* DONE! */
+
+ /* resume sending here to trigger the callback to get called again so
+ that it can signal EOF to nghttp2 */
+ (void)nghttp2_session_resume_data(h2, stream->stream_id);
+
+ (void)h2_process_pending_input(conn->data, httpc, &result);
+ }
+ }
+ return result;
+}
+
+
static ssize_t http2_handle_stream_close(struct connectdata *conn,
struct Curl_easy *data,
- struct HTTP *stream, CURLcode *err) {
+ struct HTTP *stream, CURLcode *err)
+{
char *trailer_pos, *trailer_end;
CURLcode result;
struct http_conn *httpc = &conn->proto.httpc;
@@ -1178,8 +1256,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
DEBUGASSERT(data->state.drain == 0);
- /* Reset to FALSE to prevent infinite loop in readwrite_data
- function. */
+ /* Reset to FALSE to prevent infinite loop in readwrite_data function. */
stream->closed = FALSE;
if(stream->error_code != NGHTTP2_NO_ERROR) {
failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %d)",
@@ -1216,6 +1293,8 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
}
}
+ stream->close_handled = TRUE;
+
DEBUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n"));
return 0;
}
@@ -1268,10 +1347,6 @@ static int h2_session_send(struct Curl_easy *data,
return nghttp2_session_send(h2);
}
-/*
- * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
- * a regular CURLcode value.
- */
static ssize_t http2_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len, CURLcode *err)
{
@@ -1382,6 +1457,8 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
socket is not read. But it seems that usually streams are
notified with its drain property, and socket is read again
quickly. */
+ DEBUGF(infof(data, "stream %x is paused, pause id: %x\n",
+ stream->stream_id, httpc->pause_stream_id));
*err = CURLE_AGAIN;
return -1;
}
@@ -1497,7 +1574,72 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
#define HEADER_OVERFLOW(x) \
(x.namelen > (uint16_t)-1 || x.valuelen > (uint16_t)-1 - x.namelen)
-/* return number of received (decrypted) bytes */
+/*
+ * Check header memory for the token "trailers".
+ * Parse the tokens as separated by comma and surrounded by whitespace.
+ * Returns TRUE if found or FALSE if not.
+ */
+static bool contains_trailers(const char *p, size_t len)
+{
+ const char *end = p + len;
+ for(;;) {
+ for(; p != end && (*p == ' ' || *p == '\t'); ++p)
+ ;
+ if(p == end || (size_t)(end - p) < sizeof("trailers") - 1)
+ return FALSE;
+ if(strncasecompare("trailers", p, sizeof("trailers") - 1)) {
+ p += sizeof("trailers") - 1;
+ for(; p != end && (*p == ' ' || *p == '\t'); ++p)
+ ;
+ if(p == end || *p == ',')
+ return TRUE;
+ }
+ /* skip to next token */
+ for(; p != end && *p != ','; ++p)
+ ;
+ if(p == end)
+ return FALSE;
+ ++p;
+ }
+}
+
+typedef enum {
+ /* Send header to server */
+ HEADERINST_FORWARD,
+ /* Don't send header to server */
+ HEADERINST_IGNORE,
+ /* Discard header, and replace it with "te: trailers" */
+ HEADERINST_TE_TRAILERS
+} header_instruction;
+
+/* Decides how to treat given header field. */
+static header_instruction inspect_header(const char *name, size_t namelen,
+ const char *value, size_t valuelen) {
+ switch(namelen) {
+ case 2:
+ if(!strncasecompare("te", name, namelen))
+ return HEADERINST_FORWARD;
+
+ return contains_trailers(value, valuelen) ?
+ HEADERINST_TE_TRAILERS : HEADERINST_IGNORE;
+ case 7:
+ return strncasecompare("upgrade", name, namelen) ?
+ HEADERINST_IGNORE : HEADERINST_FORWARD;
+ case 10:
+ return (strncasecompare("connection", name, namelen) ||
+ strncasecompare("keep-alive", name, namelen)) ?
+ HEADERINST_IGNORE : HEADERINST_FORWARD;
+ case 16:
+ return strncasecompare("proxy-connection", name, namelen) ?
+ HEADERINST_IGNORE : HEADERINST_FORWARD;
+ case 17:
+ return strncasecompare("transfer-encoding", name, namelen) ?
+ HEADERINST_IGNORE : HEADERINST_FORWARD;
+ default:
+ return HEADERINST_FORWARD;
+ }
+}
+
static ssize_t http2_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
@@ -1513,7 +1655,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
size_t nheader;
size_t i;
size_t authority_idx;
- char *hdbuf = (char*)mem;
+ char *hdbuf = (char *)mem;
char *end, *line_end;
nghttp2_data_provider data_prd;
int32_t stream_id;
@@ -1525,6 +1667,14 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
DEBUGF(infof(conn->data, "http2_send len=%zu\n", len));
if(stream->stream_id != -1) {
+ if(stream->close_handled) {
+ infof(conn->data, "stream %d closed\n", stream->stream_id);
+ *err = CURLE_HTTP2_STREAM;
+ return -1;
+ }
+ else if(stream->closed) {
+ return http2_handle_stream_close(conn, conn->data, stream, err);
+ }
/* If stream_id != -1, we have dispatched request HEADERS, and now
are going to send or sending request body in DATA frame */
stream->upload_mem = mem;
@@ -1643,7 +1793,6 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
i = 3;
while(i < nheader) {
size_t hlen;
- int skip = 0;
hdbuf = line_end + 2;
@@ -1661,12 +1810,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
goto fail;
hlen = end - hdbuf;
- if(hlen == 10 && Curl_raw_nequal("connection", hdbuf, 10)) {
- /* skip Connection: headers! */
- skip = 1;
- --nheader;
- }
- else if(hlen == 4 && Curl_raw_nequal("host", hdbuf, 4)) {
+ if(hlen == 4 && strncasecompare("host", hdbuf, 4)) {
authority_idx = i;
nva[i].name = (unsigned char *)":authority";
nva[i].namelen = strlen((char *)nva[i].name);
@@ -1679,38 +1823,28 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
while(*hdbuf == ' ' || *hdbuf == '\t')
++hdbuf;
end = line_end;
- if(!skip) {
+
+ switch(inspect_header((const char *)nva[i].name, nva[i].namelen, hdbuf,
+ end - hdbuf)) {
+ case HEADERINST_IGNORE:
+ /* skip header fields prohibited by HTTP/2 specification. */
+ --nheader;
+ continue;
+ case HEADERINST_TE_TRAILERS:
+ nva[i].value = (uint8_t*)"trailers";
+ nva[i].valuelen = sizeof("trailers") - 1;
+ break;
+ default:
nva[i].value = (unsigned char *)hdbuf;
nva[i].valuelen = (size_t)(end - hdbuf);
- nva[i].flags = NGHTTP2_NV_FLAG_NONE;
- if(HEADER_OVERFLOW(nva[i])) {
- failf(conn->data, "Failed sending HTTP request: Header overflow");
- goto fail;
- }
- /* Inspect Content-Length header field and retrieve the request
- entity length so that we can set END_STREAM to the last DATA
- frame. */
- if(nva[i].namelen == 14 &&
- Curl_raw_nequal("content-length", (char*)nva[i].name, 14)) {
- size_t j;
- stream->upload_left = 0;
- if(!nva[i].valuelen)
- goto fail;
- for(j = 0; j < nva[i].valuelen; ++j) {
- if(nva[i].value[j] < '0' || nva[i].value[j] > '9')
- goto fail;
- if(stream->upload_left >= CURL_OFF_T_MAX / 10)
- goto fail;
- stream->upload_left *= 10;
- stream->upload_left += nva[i].value[j] - '0';
- }
- DEBUGF(infof(conn->data,
- "request content-length=%"
- CURL_FORMAT_CURL_OFF_T
- "\n", stream->upload_left));
- }
- ++i;
}
+
+ nva[i].flags = NGHTTP2_NV_FLAG_NONE;
+ if(HEADER_OVERFLOW(nva[i])) {
+ failf(conn->data, "Failed sending HTTP request: Header overflow");
+ goto fail;
+ }
+ ++i;
}
/* :authority must come before non-pseudo header fields */
@@ -1736,6 +1870,10 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
if(nva[i].valuelen > max_acc - acc)
break;
acc += nva[i].valuelen;
+
+ DEBUGF(infof(conn->data, "h2 header: %.*s:%.*s\n",
+ nva[i].namelen, nva[i].name,
+ nva[i].valuelen, nva[i].value));
}
if(i != nheader) {
@@ -1751,6 +1889,12 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
case HTTPREQ_POST:
case HTTPREQ_POST_FORM:
case HTTPREQ_PUT:
+ if(conn->data->state.infilesize != -1)
+ stream->upload_left = conn->data->state.infilesize;
+ else
+ /* data sending without specifying the data amount up front */
+ stream->upload_left = -1; /* unknown, but not zero */
+
data_prd.read_callback = data_source_read_callback;
data_prd.source.ptr = NULL;
stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
@@ -1850,10 +1994,6 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n");
Curl_multi_connchanged(conn->data->multi);
- /* switch on TCP_NODELAY as we need to send off packets without delay for
- maximum throughput */
- Curl_tcpnodelay(conn, conn->sock[FIRSTSOCKET]);
-
return CURLE_OK;
}
@@ -1895,7 +2035,8 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
else {
/* stream ID is unknown at this point */
stream->stream_id = -1;
- rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0);
+ rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, settings,
+ sizeof(settings) / sizeof(settings[0]));
if(rv != 0) {
failf(data, "nghttp2_submit_settings() failed: %s(%d)",
nghttp2_strerror(rv), rv);
@@ -1903,6 +2044,14 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
}
}
+ rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0,
+ HTTP2_HUGE_WINDOW_SIZE);
+ if(rv != 0) {
+ failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
+ nghttp2_strerror(rv), rv);
+ return CURLE_HTTP2;
+ }
+
/* we are going to copy mem to httpc->inbuf. This is required since
mem is part of buffer pointed by stream->mem, and callbacks
called by nghttp2_session_mem_recv() will write stream specific
@@ -1918,7 +2067,8 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
" after upgrade: len=%zu\n",
nread);
- memcpy(httpc->inbuf, mem, nread);
+ if(nread)
+ memcpy(httpc->inbuf, mem, nread);
httpc->inbuflen = nread;
nproc = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)httpc->inbuf,
diff --git a/lib/http2.h b/lib/http2.h
index bedbebf1..89175359 100644
--- a/lib/http2.h
+++ b/lib/http2.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -51,6 +51,8 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
/* called from Curl_http_setup_conn */
void Curl_http2_setup_conn(struct connectdata *conn);
void Curl_http2_setup_req(struct Curl_easy *data);
+void Curl_http2_done(struct connectdata *conn, bool premature);
+CURLcode Curl_http2_done_sending(struct connectdata *conn);
#else /* USE_NGHTTP2 */
#define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
@@ -61,6 +63,8 @@ void Curl_http2_setup_req(struct Curl_easy *data);
#define Curl_http2_setup_req(x)
#define Curl_http2_init_state(x)
#define Curl_http2_init_userset(x)
+#define Curl_http2_done(x,y)
+#define Curl_http2_done_sending(x)
#endif
#endif /* HEADER_CURL_HTTP2_H */
diff --git a/lib/http_digest.c b/lib/http_digest.c
index 97230e79..91b88a38 100644
--- a/lib/http_digest.c
+++ b/lib/http_digest.c
@@ -25,7 +25,7 @@
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
#include "urldata.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "vauth/vauth.h"
#include "http_digest.h"
/* The last 3 #include files should be in this order */
@@ -95,8 +95,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
if(proxy) {
digest = &data->state.proxydigest;
allocuserpwd = &conn->allocptr.proxyuserpwd;
- userp = conn->proxyuser;
- passwdp = conn->proxypasswd;
+ userp = conn->http_proxy.user;
+ passwdp = conn->http_proxy.passwd;
authp = &data->state.authproxy;
}
else {
diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c
index c39d6f36..51375e81 100644
--- a/lib/http_negotiate.c
+++ b/lib/http_negotiate.c
@@ -26,7 +26,6 @@
#include "urldata.h"
#include "sendf.h"
-#include "rawstr.h"
#include "http_negotiate.h"
#include "vauth/vauth.h"
@@ -38,6 +37,7 @@
CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
const char *header)
{
+ CURLcode result;
struct Curl_easy *data = conn->data;
size_t len;
@@ -51,11 +51,11 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
struct negotiatedata *neg_ctx;
if(proxy) {
- userp = conn->proxyuser;
- passwdp = conn->proxypasswd;
+ userp = conn->http_proxy.user;
+ passwdp = conn->http_proxy.passwd;
service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
- host = conn->proxy.name;
+ host = conn->http_proxy.host.name;
neg_ctx = &data->state.proxyneg;
}
else {
@@ -90,8 +90,13 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
}
/* Initilise the security context and decode our challenge */
- return Curl_auth_decode_spnego_message(data, userp, passwdp, service, host,
- header, neg_ctx);
+ result = Curl_auth_decode_spnego_message(data, userp, passwdp, service,
+ host, header, neg_ctx);
+
+ if(result)
+ Curl_auth_spnego_cleanup(neg_ctx);
+
+ return result;
}
CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c
index 935df25d..21c77cd6 100644
--- a/lib/http_ntlm.c
+++ b/lib/http_ntlm.c
@@ -35,7 +35,7 @@
#include "urldata.h"
#include "sendf.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "http_ntlm.h"
#include "curl_ntlm_wb.h"
#include "vauth/vauth.h"
@@ -136,8 +136,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
if(proxy) {
allocuserpwd = &conn->allocptr.proxyuserpwd;
- userp = conn->proxyuser;
- passwdp = conn->proxypasswd;
+ userp = conn->http_proxy.user;
+ passwdp = conn->http_proxy.passwd;
ntlm = &conn->proxyntlm;
authp = &conn->data->state.authproxy;
}
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index c6b05e30..bbe2e8eb 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -31,19 +31,54 @@
#include "http.h"
#include "url.h"
#include "select.h"
-#include "rawstr.h"
#include "progress.h"
#include "non-ascii.h"
#include "connect.h"
#include "curlx.h"
+#include "vtls/vtls.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-CURLcode Curl_proxy_connect(struct connectdata *conn)
+/*
+ * Perform SSL initialization for HTTPS proxy. Sets
+ * proxy_ssl_connected connection bit when complete. Can be
+ * called multiple times.
+ */
+static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex)
{
+#ifdef USE_SSL
+ CURLcode result = CURLE_OK;
+ DEBUGASSERT(conn->http_proxy.proxytype == CURLPROXY_HTTPS);
+ if(!conn->bits.proxy_ssl_connected[sockindex]) {
+ /* perform SSL initialization for this socket */
+ result =
+ Curl_ssl_connect_nonblocking(conn, sockindex,
+ &conn->bits.proxy_ssl_connected[sockindex]);
+ if(result)
+ conn->bits.close = TRUE; /* a failed connection is marked for closure to
+ prevent (bad) re-use or similar */
+ }
+ return result;
+#else
+ (void) conn;
+ (void) sockindex;
+ return CURLE_NOT_BUILT_IN;
+#endif
+}
+
+CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
+{
+ if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
+ const CURLcode result = https_proxy_connect(conn, sockindex);
+ if(result)
+ return result;
+ if(!conn->bits.proxy_ssl_connected[sockindex])
+ return result; /* wait for HTTPS proxy SSL initialization to complete */
+ }
+
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
#ifndef CURL_DISABLE_PROXY
/* for [protocol] tunneled through HTTP proxy */
@@ -69,15 +104,20 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
memset(&http_proxy, 0, sizeof(http_proxy));
conn->data->req.protop = &http_proxy;
connkeep(conn, "HTTP proxy CONNECT");
- if(conn->bits.conn_to_host)
+ if(sockindex == SECONDARYSOCKET)
+ hostname = conn->secondaryhostname;
+ else if(conn->bits.conn_to_host)
hostname = conn->conn_to_host.name;
else
hostname = conn->host.name;
- if(conn->bits.conn_to_port)
+
+ if(sockindex == SECONDARYSOCKET)
+ remote_port = conn->secondary_port;
+ else if(conn->bits.conn_to_port)
remote_port = conn->conn_to_port;
else
remote_port = conn->remote_port;
- result = Curl_proxyCONNECT(conn, FIRSTSOCKET, hostname,
+ result = Curl_proxyCONNECT(conn, sockindex, hostname,
remote_port, FALSE);
conn->data->req.protop = prot_save;
if(CURLE_OK != result)
@@ -114,7 +154,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
curl_off_t cl=0;
bool closeConnection = FALSE;
bool chunked_encoding = FALSE;
- long check;
+ time_t check;
#define SELECT_OK 0
#define SELECT_ERROR 1
@@ -160,8 +200,9 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
if(!result) {
char *host=(char *)"";
+ const char *proxyconn="";
const char *useragent="";
- const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ?
+ const char *http = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ?
"1.0" : "1.1";
bool ipv6_ip = conn->bits.ipv6_ip;
char *hostheader;
@@ -185,6 +226,9 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
}
+ if(!Curl_checkProxyheaders(conn, "Proxy-Connection:"))
+ proxyconn = "Proxy-Connection: Keep-Alive\r\n";
+
if(!Curl_checkProxyheaders(conn, "User-Agent:") &&
data->set.str[STRING_USERAGENT])
useragent = conn->allocptr.uagent;
@@ -194,13 +238,15 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
"CONNECT %s HTTP/%s\r\n"
"%s" /* Host: */
"%s" /* Proxy-Authorization */
- "%s", /* User-Agent */
+ "%s" /* User-Agent */
+ "%s", /* Proxy-Connection */
hostheader,
http,
host,
conn->allocptr.proxyuserpwd?
conn->allocptr.proxyuserpwd:"",
- useragent);
+ useragent,
+ proxyconn);
if(host && *host)
free(host);
@@ -239,7 +285,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
}
if(!blocking) {
- if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
+ if(0 == SOCKET_READABLE(tunnelsocket, 0))
/* return so we'll be called again polling-style */
return CURLE_OK;
else {
@@ -274,8 +320,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
}
/* loop every second at least, less if the timeout is near */
- switch (Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD,
- check<1000L?check:1000)) {
+ switch (SOCKET_READABLE(tunnelsocket, check<1000L?check:1000)) {
case -1: /* select() error, stop reading */
error = SELECT_ERROR;
failf(data, "Proxy CONNECT aborted due to select/poll error");
@@ -568,7 +613,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
free(data->req.newurl);
data->req.newurl = NULL;
/* failure, close this connection to avoid re-use */
- connclose(conn, "proxy CONNECT failure");
+ streamclose(conn, "proxy CONNECT failure");
Curl_closesocket(conn, conn->sock[sockindex]);
conn->sock[sockindex] = CURL_SOCKET_BAD;
}
diff --git a/lib/http_proxy.h b/lib/http_proxy.h
index fd043303..d1f5a7c8 100644
--- a/lib/http_proxy.h
+++ b/lib/http_proxy.h
@@ -32,11 +32,11 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
/* Default proxy timeout in milliseconds */
#define PROXY_TIMEOUT (3600*1000)
-CURLcode Curl_proxy_connect(struct connectdata *conn);
+CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex);
#else
#define Curl_proxyCONNECT(x,y,z,w,v) CURLE_NOT_BUILT_IN
-#define Curl_proxy_connect(x) CURLE_OK
+#define Curl_proxy_connect(x,y) CURLE_OK
#endif
#endif /* HEADER_CURL_HTTP_PROXY_H */
diff --git a/lib/if2ip.c b/lib/if2ip.c
index 2f92b2de..d876615e 100644
--- a/lib/if2ip.c
+++ b/lib/if2ip.c
@@ -51,7 +51,7 @@
#endif
#include "inet_ntop.h"
-#include "strequal.h"
+#include "strcase.h"
#include "if2ip.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -68,7 +68,7 @@ unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
#else
if(sa->sa_family == AF_INET6) {
const struct sockaddr_in6 * sa6 = (const struct sockaddr_in6 *)(void *) sa;
- const unsigned char * b = sa6->sin6_addr.s6_addr;
+ const unsigned char *b = sa6->sin6_addr.s6_addr;
unsigned short w = (unsigned short) ((b[0] << 8) | b[1]);
switch(w & 0xFFC0) {
@@ -102,7 +102,7 @@ bool Curl_if_is_interface_name(const char *interf)
if(getifaddrs(&head) >= 0) {
for(iface=head; iface != NULL; iface=iface->ifa_next) {
- if(curl_strequal(iface->ifa_name, interf)) {
+ if(strcasecompare(iface->ifa_name, interf)) {
result = TRUE;
break;
}
@@ -132,7 +132,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
for(iface = head; iface != NULL; iface=iface->ifa_next) {
if(iface->ifa_addr != NULL) {
if(iface->ifa_addr->sa_family == af) {
- if(curl_strequal(iface->ifa_name, interf)) {
+ if(strcasecompare(iface->ifa_name, interf)) {
void *addr;
char *ip;
char scope[12] = "";
@@ -180,7 +180,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
}
}
else if((res == IF2IP_NOT_FOUND) &&
- curl_strequal(iface->ifa_name, interf)) {
+ strcasecompare(iface->ifa_name, interf)) {
res = IF2IP_AF_NOT_SUPPORTED;
}
}
diff --git a/lib/imap.c b/lib/imap.c
index 123ea3b2..78dc6fa2 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -68,16 +68,15 @@
#include "http.h" /* for HTTP proxy tunnel stuff */
#include "socks.h"
#include "imap.h"
-
#include "strtoofft.h"
-#include "strequal.h"
+#include "strcase.h"
#include "vtls/vtls.h"
#include "connect.h"
#include "strerror.h"
#include "select.h"
#include "multiif.h"
#include "url.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "curl_sasl.h"
#include "warnless.h"
@@ -108,7 +107,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn,
const char *initresp);
static CURLcode imap_continue_authenticate(struct connectdata *conn,
const char *resp);
-static void imap_get_message(char *buffer, char** outptr);
+static void imap_get_message(char *buffer, char **outptr);
/*
* IMAP protocol handler.
@@ -271,7 +270,7 @@ static bool imap_matchresp(const char *line, size_t len, const char *cmd)
/* Does the command name match and is it followed by a space character or at
the end of line? */
- if(line + cmd_len <= end && Curl_raw_nequal(line, cmd, cmd_len) &&
+ if(line + cmd_len <= end && strncasecompare(line, cmd, cmd_len) &&
(line[cmd_len] == ' ' || line + cmd_len + 2 == end))
return TRUE;
@@ -391,10 +390,10 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
*
* Gets the authentication message from the response buffer.
*/
-static void imap_get_message(char *buffer, char** outptr)
+static void imap_get_message(char *buffer, char **outptr)
{
size_t len = 0;
- char* message = NULL;
+ char *message = NULL;
/* Find the start of the message */
for(message = buffer + 2; *message == ' ' || *message == '\t'; message++)
@@ -846,7 +845,7 @@ static CURLcode imap_state_servergreet_resp(struct connectdata *conn,
if(imapcode != 'O') {
failf(data, "Got unexpected imap-server response");
- result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: fix this code */
+ result = CURLE_WEIRD_SERVER_REPLY;
}
else
result = imap_perform_capability(conn);
@@ -1179,7 +1178,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
else {
/* We don't know how to parse this line */
failf(pp->conn->data, "Failed to parse FETCH response.");
- result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: fix this code */
+ result = CURLE_WEIRD_SERVER_REPLY;
}
/* End of DO phase */
@@ -1198,7 +1197,7 @@ static CURLcode imap_state_fetch_final_resp(struct connectdata *conn,
(void)instate; /* No use for this yet */
if(imapcode != 'O')
- result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: Fix error code */
+ result = CURLE_WEIRD_SERVER_REPLY;
else
/* End of DONE phase */
state(conn, IMAP_STOP);
@@ -1275,7 +1274,7 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
/* Was there an error parsing the response line? */
if(imapcode == -1)
- return CURLE_FTP_WEIRD_SERVER_REPLY;
+ return CURLE_WEIRD_SERVER_REPLY;
if(!imapcode)
break;
@@ -1935,7 +1934,7 @@ static CURLcode imap_parse_url_options(struct connectdata *conn)
while(*ptr && *ptr != ';')
ptr++;
- if(strnequal(key, "AUTH=", 5))
+ if(strncasecompare(key, "AUTH=", 5))
result = Curl_sasl_parse_url_auth_option(&imapc->sasl,
value, ptr - value);
else
@@ -2031,28 +2030,28 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
PARTIAL) stripping of the trailing slash character if it is present.
Note: Unknown parameters trigger a URL_MALFORMAT error. */
- if(Curl_raw_equal(name, "UIDVALIDITY") && !imap->uidvalidity) {
+ if(strcasecompare(name, "UIDVALIDITY") && !imap->uidvalidity) {
if(valuelen > 0 && value[valuelen - 1] == '/')
value[valuelen - 1] = '\0';
imap->uidvalidity = value;
value = NULL;
}
- else if(Curl_raw_equal(name, "UID") && !imap->uid) {
+ else if(strcasecompare(name, "UID") && !imap->uid) {
if(valuelen > 0 && value[valuelen - 1] == '/')
value[valuelen - 1] = '\0';
imap->uid = value;
value = NULL;
}
- else if(Curl_raw_equal(name, "SECTION") && !imap->section) {
+ else if(strcasecompare(name, "SECTION") && !imap->section) {
if(valuelen > 0 && value[valuelen - 1] == '/')
value[valuelen - 1] = '\0';
imap->section = value;
value = NULL;
}
- else if(Curl_raw_equal(name, "PARTIAL") && !imap->partial) {
+ else if(strcasecompare(name, "PARTIAL") && !imap->partial) {
if(valuelen > 0 && value[valuelen - 1] == '/')
value[valuelen - 1] = '\0';
diff --git a/lib/inet_ntop.c b/lib/inet_ntop.c
index 416005c0..38311e31 100644
--- a/lib/inet_ntop.c
+++ b/lib/inet_ntop.c
@@ -184,10 +184,10 @@ char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
{
switch (af) {
case AF_INET:
- return inet_ntop4((const unsigned char*)src, buf, size);
+ return inet_ntop4((const unsigned char *)src, buf, size);
#ifdef ENABLE_IPV6
case AF_INET6:
- return inet_ntop6((const unsigned char*)src, buf, size);
+ return inet_ntop6((const unsigned char *)src, buf, size);
#endif
default:
SET_ERRNO(EAFNOSUPPORT);
diff --git a/lib/krb5.c b/lib/krb5.c
index 87ce8ee6..067b0a57 100644
--- a/lib/krb5.c
+++ b/lib/krb5.c
@@ -121,7 +121,7 @@ krb5_encode(void *app_data, const void *from, int length, int level, void **to)
/* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal
* libraries modify the input buffer in gss_seal()
*/
- dec.value = (void*)from;
+ dec.value = (void *)from;
dec.length = length;
maj = gss_seal(&min, *context,
level == PROT_PRIVATE,
@@ -182,7 +182,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
for(;;) {
/* this really shouldn't be repeated here, but can't help it */
if(service == srv_host) {
- result = Curl_ftpsendf(conn, "AUTH GSSAPI");
+ result = Curl_ftpsend(conn, "AUTH GSSAPI");
if(result)
return -2;
@@ -243,16 +243,22 @@ krb5_auth(void *app_data, struct connectdata *conn)
}
if(output_buffer.length != 0) {
+ char *cmd;
+
result = Curl_base64_encode(data, (char *)output_buffer.value,
output_buffer.length, &p, &base64_sz);
if(result) {
Curl_infof(data, "base64-encoding: %s\n",
curl_easy_strerror(result));
- ret = AUTH_CONTINUE;
+ ret = AUTH_ERROR;
break;
}
- result = Curl_ftpsendf(conn, "ADAT %s", p);
+ cmd = aprintf("ADAT %s", p);
+ if(cmd)
+ result = Curl_ftpsend(conn, cmd);
+ else
+ result = CURLE_OUT_OF_MEMORY;
free(p);
diff --git a/lib/ldap.c b/lib/ldap.c
index a1646279..a366e0cd 100644
--- a/lib/ldap.c
+++ b/lib/ldap.c
@@ -69,12 +69,11 @@
#include "escape.h"
#include "progress.h"
#include "transfer.h"
-#include "strequal.h"
+#include "strcase.h"
#include "strtok.h"
#include "curl_ldap.h"
#include "curl_multibyte.h"
#include "curl_base64.h"
-#include "rawstr.h"
#include "connect.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -272,7 +271,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON);
#else
int ldap_option;
- char* ldap_ca = data->set.str[STRING_SSL_CAFILE];
+ char *ldap_ca = conn->ssl_config.CAfile;
#if defined(CURL_HAS_NOVELL_LDAPSDK)
rc = ldapssl_client_init(NULL, NULL);
if(rc != LDAP_SUCCESS) {
@@ -280,11 +279,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
result = CURLE_SSL_CERTPROBLEM;
goto quit;
}
- if(data->set.ssl.verifypeer) {
+ if(conn->ssl_config.verifypeer) {
/* Novell SDK supports DER or BASE64 files. */
int cert_type = LDAPSSL_CERT_FILETYPE_B64;
- if((data->set.str[STRING_CERT_TYPE]) &&
- (Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "DER")))
+ if((data->set.ssl.cert_type) &&
+ (strcasecompare(data->set.ssl.cert_type, "DER")))
cert_type = LDAPSSL_CERT_FILETYPE_DER;
if(!ldap_ca) {
failf(data, "LDAP local: ERROR %s CA cert not set!",
@@ -322,10 +321,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
goto quit;
}
#elif defined(LDAP_OPT_X_TLS)
- if(data->set.ssl.verifypeer) {
+ if(conn->ssl_config.verifypeer) {
/* OpenLDAP SDK supports BASE64 files. */
- if((data->set.str[STRING_CERT_TYPE]) &&
- (!Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "PEM"))) {
+ if((data->set.ssl.cert_type) &&
+ (!strcasecompare(data->set.ssl.cert_type, "PEM"))) {
failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!");
result = CURLE_SSL_CERTPROBLEM;
goto quit;
@@ -708,16 +707,16 @@ static void _ldap_trace (const char *fmt, ...)
*/
static int str2scope (const char *p)
{
- if(strequal(p, "one"))
- return LDAP_SCOPE_ONELEVEL;
- if(strequal(p, "onetree"))
- return LDAP_SCOPE_ONELEVEL;
- if(strequal(p, "base"))
- return LDAP_SCOPE_BASE;
- if(strequal(p, "sub"))
- return LDAP_SCOPE_SUBTREE;
- if(strequal(p, "subtree"))
- return LDAP_SCOPE_SUBTREE;
+ if(strcasecompare(p, "one"))
+ return LDAP_SCOPE_ONELEVEL;
+ if(strcasecompare(p, "onetree"))
+ return LDAP_SCOPE_ONELEVEL;
+ if(strcasecompare(p, "base"))
+ return LDAP_SCOPE_BASE;
+ if(strcasecompare(p, "sub"))
+ return LDAP_SCOPE_SUBTREE;
+ if(strcasecompare(p, "subtree"))
+ return LDAP_SCOPE_SUBTREE;
return (-1);
}
@@ -767,7 +766,7 @@ static bool split_str(char *str, char ***out, size_t *count)
*
* Defined in RFC4516 section 2.
*/
-static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
+static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
{
int rc = LDAP_SUCCESS;
char *path;
@@ -776,9 +775,9 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
size_t i;
if(!conn->data ||
- !conn->data->state.path ||
- conn->data->state.path[0] != '/' ||
- !checkprefix("LDAP", conn->data->change.url))
+ !conn->data->state.path ||
+ conn->data->state.path[0] != '/' ||
+ !checkprefix("LDAP", conn->data->change.url))
return LDAP_INVALID_SYNTAX;
ludp->lud_scope = LDAP_SCOPE_BASE;
@@ -798,12 +797,13 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
if(*p) {
char *dn = p;
char *unescaped;
+ CURLcode result;
LDAP_TRACE (("DN '%s'\n", dn));
/* Unescape the DN */
- unescaped = curl_easy_unescape(conn->data, dn, 0, NULL);
- if(!unescaped) {
+ result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE);
+ if(result) {
rc = LDAP_NO_MEMORY;
goto quit;
@@ -862,12 +862,14 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
for(i = 0; i < count; i++) {
char *unescaped;
+ CURLcode result;
LDAP_TRACE (("attr[%d] '%s'\n", i, attributes[i]));
/* Unescape the attribute */
- unescaped = curl_easy_unescape(conn->data, attributes[i], 0, NULL);
- if(!unescaped) {
+ result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
+ FALSE);
+ if(result) {
free(attributes);
rc = LDAP_NO_MEMORY;
@@ -930,12 +932,13 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
if(*p) {
char *filter = p;
char *unescaped;
+ CURLcode result;
LDAP_TRACE (("filter '%s'\n", filter));
/* Unescape the filter */
- unescaped = curl_easy_unescape(conn->data, filter, 0, NULL);
- if(!unescaped) {
+ result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE);
+ if(result) {
rc = LDAP_NO_MEMORY;
goto quit;
@@ -971,8 +974,8 @@ quit:
return rc;
}
-static int _ldap_url_parse (const struct connectdata *conn,
- LDAPURLDesc **ludpp)
+static int _ldap_url_parse(const struct connectdata *conn,
+ LDAPURLDesc **ludpp)
{
LDAPURLDesc *ludp = calloc(1, sizeof(*ludp));
int rc;
@@ -981,7 +984,7 @@ static int _ldap_url_parse (const struct connectdata *conn,
if(!ludp)
return LDAP_NO_MEMORY;
- rc = _ldap_url_parse2 (conn, ludp);
+ rc = _ldap_url_parse2(conn, ludp);
if(rc != LDAP_SUCCESS) {
_ldap_free_urldesc(ludp);
ludp = NULL;
@@ -990,7 +993,7 @@ static int _ldap_url_parse (const struct connectdata *conn,
return (rc);
}
-static void _ldap_free_urldesc (LDAPURLDesc *ludp)
+static void _ldap_free_urldesc(LDAPURLDesc *ludp)
{
size_t i;
diff --git a/lib/libcurl.rc b/lib/libcurl.rc
index 50b365db..c1efbadc 100644
--- a/lib/libcurl.rc
+++ b/lib/libcurl.rc
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,12 +44,12 @@ BEGIN
BEGIN
BLOCK "040904b0"
BEGIN
- VALUE "CompanyName", "The cURL library, https://curl.haxx.se/\0"
+ VALUE "CompanyName", "The curl library, https://curl.haxx.se/\0"
VALUE "FileDescription", "libcurl Shared Library\0"
VALUE "FileVersion", LIBCURL_VERSION "\0"
VALUE "InternalName", "libcurl\0"
VALUE "OriginalFilename", "libcurl.dll\0"
- VALUE "ProductName", "The cURL library\0"
+ VALUE "ProductName", "The curl library\0"
VALUE "ProductVersion", LIBCURL_VERSION "\0"
VALUE "LegalCopyright", "© " LIBCURL_COPYRIGHT "\0"
VALUE "License", "https://curl.haxx.se/docs/copyright.html\0"
diff --git a/lib/md5.c b/lib/md5.c
index 84adb992..7a1cac90 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -45,7 +45,7 @@ static void MD5_Init(MD5_CTX * ctx)
}
static void MD5_Update(MD5_CTX * ctx,
- const unsigned char * input,
+ const unsigned char *input,
unsigned int inputLen)
{
md5_update(ctx, inputLen, input);
@@ -71,7 +71,7 @@ static void MD5_Init(MD5_CTX * ctx)
}
static void MD5_Update(MD5_CTX * ctx,
- const unsigned char * input,
+ const unsigned char *input,
unsigned int inputLen)
{
gcry_md_write(*ctx, input, inputLen);
@@ -124,7 +124,7 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
CC_MD5_Final(digest, ctx);
}
-#elif defined(_WIN32)
+#elif defined(_WIN32) && !defined(CURL_WINDOWS_APP)
#include <wincrypt.h>
#include "curl_memory.h"
diff --git a/lib/memdebug.c b/lib/memdebug.c
index ccbf461b..15e86616 100644
--- a/lib/memdebug.c
+++ b/lib/memdebug.c
@@ -90,7 +90,7 @@ struct memdebug {
union {
curl_off_t o;
double d;
- void * p;
+ void *p;
} mem[1];
/* I'm hoping this is the thing with the strictest alignment
* requirements. That also means we waste some space :-( */
diff --git a/lib/mk-ca-bundle.pl b/lib/mk-ca-bundle.pl
index 5a1435c5..9574f1db 100755
--- a/lib/mk-ca-bundle.pl
+++ b/lib/mk-ca-bundle.pl
@@ -6,7 +6,7 @@
# * | (__| |_| | _ <| |___
# * \___|\___/|_| \_\_____|
# *
-# * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+# * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
# *
# * This software is licensed as described in the file COPYING, which
# * you should have received as part of this distribution. The terms
@@ -30,11 +30,11 @@
# dependency is the OpenSSL commandline tool for optional text listing.
# Hacked by Guenter Knauf.
#
+use Encode;
use Getopt::Std;
use MIME::Base64;
-use LWP::UserAgent;
use strict;
-use vars qw($opt_b $opt_d $opt_f $opt_h $opt_i $opt_l $opt_n $opt_p $opt_q $opt_s $opt_t $opt_u $opt_v $opt_w);
+use vars qw($opt_b $opt_d $opt_f $opt_h $opt_i $opt_k $opt_l $opt_m $opt_n $opt_p $opt_q $opt_s $opt_t $opt_u $opt_v $opt_w);
use List::Util;
use Text::Wrap;
my $MOD_SHA = "Digest::SHA";
@@ -43,18 +43,19 @@ if ($@) {
$MOD_SHA = "Digest::SHA::PurePerl";
eval "require $MOD_SHA";
}
+eval "require LWP::UserAgent";
my %urls = (
'nss' =>
- 'http://hg.mozilla.org/projects/nss/raw-file/tip/lib/ckfw/builtins/certdata.txt',
+ 'https://hg.mozilla.org/projects/nss/raw-file/tip/lib/ckfw/builtins/certdata.txt',
'central' =>
- 'http://hg.mozilla.org/mozilla-central/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
+ 'https://hg.mozilla.org/mozilla-central/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
'aurora' =>
- 'http://hg.mozilla.org/releases/mozilla-aurora/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
+ 'https://hg.mozilla.org/releases/mozilla-aurora/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
'beta' =>
- 'http://hg.mozilla.org/releases/mozilla-beta/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
+ 'https://hg.mozilla.org/releases/mozilla-beta/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
'release' =>
- 'http://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
+ 'https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
);
$opt_d = 'release';
@@ -62,7 +63,7 @@ $opt_d = 'release';
# If the OpenSSL commandline is not in search path you can configure it here!
my $openssl = 'openssl';
-my $version = '1.25';
+my $version = '1.27';
$opt_w = 76; # default base64 encoded lines length
@@ -109,7 +110,7 @@ my @valid_signature_algorithms = (
$0 =~ s@.*(/|\\)@@;
$Getopt::Std::STANDARD_HELP_VERSION = 1;
-getopts('bd:fhilnp:qs:tuvw:');
+getopts('bd:fhiklmnp:qs:tuvw:');
if(!defined($opt_d)) {
# to make plain "-d" use not cause warnings, and actually still work
@@ -117,7 +118,16 @@ if(!defined($opt_d)) {
}
# Use predefined URL or else custom URL specified on command line.
-my $url = ( defined( $urls{$opt_d} ) ) ? $urls{$opt_d} : $opt_d;
+my $url;
+if(defined($urls{$opt_d})) {
+ $url = $urls{$opt_d};
+ if(!$opt_k && $url !~ /^https:\/\//i) {
+ die "The URL for '$opt_d' is not HTTPS. Use -k to override (insecure).\n";
+ }
+}
+else {
+ $url = $opt_d;
+}
my $curl = `curl -V`;
@@ -128,8 +138,8 @@ if ($opt_i) {
print "Operating System Name : $^O\n";
print "Getopt::Std.pm Version : ${Getopt::Std::VERSION}\n";
print "MIME::Base64.pm Version : ${MIME::Base64::VERSION}\n";
- print "LWP::UserAgent.pm Version : ${LWP::UserAgent::VERSION}\n";
- print "LWP.pm Version : ${LWP::VERSION}\n";
+ print "LWP::UserAgent.pm Version : ${LWP::UserAgent::VERSION}\n" if($LWP::UserAgent::VERSION);
+ print "LWP.pm Version : ${LWP::VERSION}\n" if($LWP::VERSION);
print "Digest::SHA.pm Version : ${Digest::SHA::VERSION}\n" if ($Digest::SHA::VERSION);
print "Digest::SHA::PurePerl.pm Version : ${Digest::SHA::PurePerl::VERSION}\n" if ($Digest::SHA::PurePerl::VERSION);
print ("=" x 78 . "\n");
@@ -139,7 +149,7 @@ sub warning_message() {
if ( $opt_d =~ m/^risk$/i ) { # Long Form Warning and Exit
print "Warning: Use of this script may pose some risk:\n";
print "\n";
- print " 1) Using http is subject to man in the middle attack of certdata content\n";
+ print " 1) If you use HTTP URLs they are subject to a man in the middle attack\n";
print " 2) Default to 'release', but more recent updates may be found in other trees\n";
print " 3) certdata.txt file format may change, lag time to update this script\n";
print " 4) Generally unwise to blindly trust CAs without manual review & verification\n";
@@ -153,14 +163,16 @@ sub warning_message() {
}
sub HELP_MESSAGE() {
- print "Usage:\t${0} [-b] [-d<certdata>] [-f] [-i] [-l] [-n] [-p<purposes:levels>] [-q] [-s<algorithms>] [-t] [-u] [-v] [-w<l>] [<outputfile>]\n";
+ print "Usage:\t${0} [-b] [-d<certdata>] [-f] [-i] [-k] [-l] [-n] [-p<purposes:levels>] [-q] [-s<algorithms>] [-t] [-u] [-v] [-w<l>] [<outputfile>]\n";
print "\t-b\tbackup an existing version of ca-bundle.crt\n";
print "\t-d\tspecify Mozilla tree to pull certdata.txt or custom URL\n";
print "\t\t Valid names are:\n";
print "\t\t ", join( ", ", map { ( $_ =~ m/$opt_d/ ) ? "$_ (default)" : "$_" } sort keys %urls ), "\n";
print "\t-f\tforce rebuild even if certdata.txt is current\n";
print "\t-i\tprint version info about used modules\n";
+ print "\t-k\tallow URLs other than HTTPS, enable HTTP fallback (insecure)\n";
print "\t-l\tprint license info about certdata.txt\n";
+ print "\t-m\tinclude meta data in output\n";
print "\t-n\tno download of certdata.txt (to use existing)\n";
print wrap("\t","\t\t", "-p\tlist of Mozilla trust purposes and levels for certificates to include in output. Takes the form of a comma separated list of purposes, a colon, and a comma separated list of levels. (default: $default_mozilla_trust_purposes:$default_mozilla_trust_levels)"), "\n";
print "\t\t Valid purposes are:\n";
@@ -224,33 +236,34 @@ sub parse_csv_param($$@) {
return @values;
}
-sub sha1 {
+sub sha256 {
my $result;
if ($Digest::SHA::VERSION || $Digest::SHA::PurePerl::VERSION) {
open(FILE, $_[0]) or die "Can't open '$_[0]': $!";
binmode(FILE);
- $result = $MOD_SHA->new(1)->addfile(*FILE)->hexdigest;
+ $result = $MOD_SHA->new(256)->addfile(*FILE)->hexdigest;
close(FILE);
} else {
# Use OpenSSL command if Perl Digest::SHA modules not available
- $result = (split(/ |\r|\n/,`$openssl dgst -sha1 $_[0]`))[1];
+ $result = `"$openssl" dgst -r -sha256 "$_[0]"`;
+ $result =~ s/^([0-9a-f]{64}) .+/$1/is;
}
return $result;
}
-sub oldsha1 {
- my $sha1 = "";
+sub oldhash {
+ my $hash = "";
open(C, "<$_[0]") || return 0;
while(<C>) {
chomp;
- if($_ =~ /^\#\# SHA1: (.*)/) {
- $sha1 = $1;
+ if($_ =~ /^\#\# SHA256: (.*)/) {
+ $hash = $1;
last;
}
}
close(C);
- return $sha1;
+ return $hash;
}
if ( $opt_p !~ m/:/ ) {
@@ -282,39 +295,72 @@ my $stdout = $crt eq '-';
my $resp;
my $fetched;
-my $oldsha1 = oldsha1($crt);
+my $oldhash = oldhash($crt);
-report "SHA1 of old file: $oldsha1";
+report "SHA256 of old file: $oldhash";
-report "Downloading '$txt' ...";
+if(!$opt_n) {
+ report "Downloading $txt ...";
-if($curl && !$opt_n) {
- my $https = $url;
- $https =~ s/^http:/https:/;
- report "Get certdata over HTTPS with curl!";
- my $quiet = $opt_q ? "-s" : "";
- my @out = `curl -w %{response_code} $quiet -O $https`;
- if(@out && $out[0] == 200) {
- $fetched = 1;
- } else {
- report "Failed downloading HTTPS with curl, trying HTTP with LWP";
+ # If we have an HTTPS URL then use curl
+ if($url =~ /^https:\/\//i) {
+ if($curl) {
+ if($curl =~ /^Protocols:.* https( |$)/m) {
+ report "Get certdata with curl!";
+ my $proto = !$opt_k ? "--proto =https" : "";
+ my $quiet = $opt_q ? "-s" : "";
+ my @out = `curl -w %{response_code} $proto $quiet -o "$txt" "$url"`;
+ if(@out && $out[0] == 200) {
+ $fetched = 1;
+ report "Downloaded $txt";
+ }
+ else {
+ report "Failed downloading via HTTPS with curl";
+ if(-e $txt && !unlink($txt)) {
+ report "Failed to remove '$txt': $!";
+ }
+ }
+ }
+ else {
+ report "curl lacks https support";
+ }
+ }
+ else {
+ report "curl not found";
+ }
}
-}
-unless ($fetched || ($opt_n and -e $txt)) {
- my $ua = new LWP::UserAgent(agent => "$0/$version");
- $ua->env_proxy();
- $resp = $ua->mirror($url, $txt);
- if ($resp && $resp->code eq '304') {
- report "Not modified";
- exit 0 if -e $crt && !$opt_f;
- } else {
+ # If nothing was fetched then use LWP
+ if(!$fetched) {
+ if($url =~ /^https:\/\//i) {
+ report "Falling back to HTTP";
+ $url =~ s/^https:\/\//http:\/\//i;
+ }
+ if(!$opt_k) {
+ report "URLs other than HTTPS are disabled by default, to enable use -k";
+ exit 1;
+ }
+ report "Get certdata with LWP!";
+ if(!defined(${LWP::UserAgent::VERSION})) {
+ report "LWP is not available (LWP::UserAgent not found)";
+ exit 1;
+ }
+ my $ua = new LWP::UserAgent(agent => "$0/$version");
+ $ua->env_proxy();
+ $resp = $ua->mirror($url, $txt);
+ if($resp && $resp->code eq '304') {
+ report "Not modified";
+ exit 0 if -e $crt && !$opt_f;
+ }
+ else {
$fetched = 1;
- }
- if( !$resp || $resp->code !~ /^(?:200|304)$/ ) {
+ report "Downloaded $txt";
+ }
+ if(!$resp || $resp->code !~ /^(?:200|304)$/) {
report "Unable to download latest data: "
. ($resp? $resp->code . ' - ' . $resp->message : "LWP failed");
exit 1 if -e $crt || ! -r $txt;
+ }
}
}
@@ -327,14 +373,14 @@ if(!$filedate) {
}
# get the hash from the download file
-my $newsha1= sha1($txt);
+my $newhash= sha256($txt);
-if(!$opt_f && $oldsha1 eq $newsha1) {
+if(!$opt_f && $oldhash eq $newhash) {
report "Downloaded file identical to previous run\'s source file. Exiting";
exit;
}
-report "SHA1 of new file: $newsha1";
+report "SHA256 of new file: $newhash";
my $currentdate = scalar gmtime($filedate);
@@ -348,7 +394,7 @@ print CRT <<EOT;
##
## Bundle of CA Root Certificates
##
-## Certificate data from Mozilla ${datesrc}: ${currentdate}
+## Certificate data from Mozilla ${datesrc}: ${currentdate} GMT
##
## This is a bundle of X.509 certificates of public Certificate Authorities
## (CA). These were automatically extracted from Mozilla's root certificates
@@ -361,7 +407,7 @@ print CRT <<EOT;
## Just configure this file as the SSLCACertificateFile.
##
## Conversion done with mk-ca-bundle.pl version $version.
-## SHA1: $newsha1
+## SHA256: $newhash
##
EOT
@@ -371,6 +417,7 @@ my $caname;
my $certnum = 0;
my $skipnum = 0;
my $start_of_cert = 0;
+my @precert;
open(TXT,"$txt") or die "Couldn't open $txt: $!\n";
while (<TXT>) {
@@ -383,11 +430,15 @@ while (<TXT>) {
last if (/\*\*\*\*\* END LICENSE BLOCK \*\*\*\*\*/);
}
}
- next if /^#|^\s*$/;
- chomp;
- if (/^CVS_ID\s+\"(.*)\"/) {
- print CRT "# $1\n";
+ elsif(/^# (Issuer|Serial Number|Subject|Not Valid Before|Not Valid After |Fingerprint \(MD5\)|Fingerprint \(SHA1\)):/) {
+ push @precert, $_;
+ next;
+ }
+ elsif(/^#|^\s*$/) {
+ undef @precert;
+ next;
}
+ chomp;
# this is a match for the start of a certificate
if (/^CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE/) {
@@ -436,8 +487,8 @@ while (<TXT>) {
. $encoded
. "-----END CERTIFICATE-----\n";
print CRT "\n$caname\n";
-
- my $maxStringLength = length($caname);
+ print CRT @precert if($opt_m);
+ my $maxStringLength = length(decode('UTF-8', $caname, Encode::FB_CROAK));
if ($opt_t) {
foreach my $key (keys %trust_purposes_by_level) {
my $string = $key . ": " . join(", ", @{$trust_purposes_by_level{$key}});
@@ -479,7 +530,9 @@ while (<TXT>) {
$certnum ++;
$start_of_cert = 0;
}
+ undef @precert;
}
+
}
close(TXT) or die "Couldn't close $txt: $!\n";
close(CRT) or die "Couldn't close $crt.~: $!\n";
@@ -495,5 +548,7 @@ unless( $stdout ) {
}
rename "$crt.~", $crt or die "Failed to rename $crt.~ to $crt: $!\n";
}
-unlink $txt if ($opt_u);
+if($opt_u && -e $txt && !unlink($txt)) {
+ report "Failed to remove $txt: $!\n";
+}
report "Done ($certnum CA certs processed, $skipnum skipped).";
diff --git a/lib/mk-ca-bundle.vbs b/lib/mk-ca-bundle.vbs
index b0d94277..a9b983e9 100755
--- a/lib/mk-ca-bundle.vbs
+++ b/lib/mk-ca-bundle.vbs
@@ -26,20 +26,36 @@
'* Hacked by Guenter Knauf
'***************************************************************************
Option Explicit
-Const myVersion = "0.3.9"
+Const myVersion = "0.4.0"
-Const myUrl = "http://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt"
-Const myOpenssl = "openssl.exe"
+Const myUrl = "https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt"
-Const myCdSavF = FALSE ' Flag: save downloaded data to file certdata.txt
+Const myOpenSSL = "openssl.exe"
+Dim myUseOpenSSL
+myUseOpenSSL = TRUE ' Flag: TRUE to use OpenSSL. If TRUE and is not
+ ' found then a warning is shown before continuing.
+
+Const myCdSavF = TRUE ' Flag: save downloaded data to file certdata.txt
Const myCaBakF = TRUE ' Flag: backup existing ca-bundle certificate
Const myAskLiF = TRUE ' Flag: display certdata.txt license agreement
-Const myAskTiF = TRUE ' Flag: ask to include certificate text info
Const myWrapLe = 76 ' Default length of base64 output lines
+' cert info code doesn't work properly with any recent openssl, leave disabled.
+' Also: we want our certificate output by default to be as similar as possible
+' to mk-ca-bundle.pl and setting this TRUE changes the base64 width to
+' OpenSSL's built-in default width, which is not the same as mk-ca-bundle.pl.
+Const myAskTiF = FALSE ' Flag: ask to include certificate text info
+
+'
'******************* Nothing to configure below! *******************
+'
+Const adTypeBinary = 1
+Const adTypeText = 2
+Const adSaveCreateNotExist = 1
+Const adSaveCreateOverWrite = 2
Dim objShell, objNetwork, objFSO, objHttp
-Dim myBase, mySelf, myFh, myTmpFh, myCdData, myCdFile, myCaFile, myTmpName, myBakNum, myOptTxt, i
+Dim myBase, mySelf, myStream, myTmpFh, myCdData, myCdFile
+Dim myCaFile, myTmpName, myBakNum, myOptTxt, i
Set objNetwork = WScript.CreateObject("WScript.Network")
Set objShell = WScript.CreateObject("WScript.Shell")
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
@@ -47,14 +63,60 @@ Set objHttp = WScript.CreateObject("WinHttp.WinHttpRequest.5.1")
If objHttp Is Nothing Then Set objHttp = WScript.CreateObject("WinHttp.WinHttpRequest")
myBase = Left(WScript.ScriptFullName, InstrRev(WScript.ScriptFullName, "\"))
mySelf = Left(WScript.ScriptName, InstrRev(WScript.ScriptName, ".") - 1) & " " & myVersion
+
myCdFile = Mid(myUrl, InstrRev(myUrl, "/") + 1)
myCaFile = "ca-bundle.crt"
-myTmpName = InputBox("Enter output filename:", mySelf, myCaFile)
-If Not (myTmpName = "") Then
- myCaFile = myTmpName
+myTmpName = InputBox("It will take a minute to download and parse the " & _
+ "certificate data." & _
+ vbLf & vbLf & _
+ "Please enter the output filename:", mySelf, myCaFile)
+If (myTmpName = "") Then
+ WScript.Quit 1
+End If
+myCaFile = myTmpName
+If (myCdFile = "") Then
+ MsgBox("URL does not contain filename!"), vbCritical, mySelf
+ WScript.Quit 1
+End If
+
+' Don't use OpenSSL if it's not present.
+If (myUseOpenSSL = TRUE) Then
+ Dim errnum
+
+ On Error Resume Next
+ Call objShell.Run("""" & myOpenSSL & """ version", 0, TRUE)
+ errnum = Err.Number
+ On Error GoTo 0
+
+ If Not (errnum = 0) Then
+ myUseOpenSSL = FALSE
+ MsgBox("OpenSSL was not found so the certificate bundle will not " & _
+ "include the SHA256 hash of the raw certificate data file " & _
+ "that was used to generate the certificates in the bundle. " & _
+ vbLf & vbLf & _
+ "This does not have any effect on the certificate output, " & _
+ "so this script will continue." & _
+ vbLf & vbLf & _
+ "If you want to set a custom location for OpenSSL or disable " & _
+ "this message then edit the variables at the start of the " & _
+ "script."), vbInformation, mySelf
+ End If
+End If
+
+If (myAskTiF = TRUE) And (myUseOpenSSL = TRUE) Then
+ If (6 = objShell.PopUp("Do you want to include text information about " & _
+ "each certificate?" & vbLf & _
+ "(Requires OpenSSL.exe in the current directory " & _
+ "or search path)",, _
+ mySelf, vbQuestion + vbYesNo + vbDefaultButton2)) Then
+ myOptTxt = TRUE
+ Else
+ myOptTxt = FALSE
+ End If
End If
-' Lets ignore SSL invalid cert errors
-objHttp.Option(4) = 256 + 512 + 4096 + 8192
+
+' Uncomment the line below to ignore SSL invalid cert errors
+' objHttp.Option(4) = 256 + 512 + 4096 + 8192
objHttp.SetTimeouts 0, 5000, 10000, 10000
objHttp.Open "GET", myUrl, FALSE
objHttp.setRequestHeader "User-Agent", WScript.ScriptName & "/" & myVersion
@@ -63,15 +125,13 @@ If Not (objHttp.Status = 200) Then
MsgBox("Failed to download '" & myCdFile & "': " & objHttp.Status & " - " & objHttp.StatusText), vbCritical, mySelf
WScript.Quit 1
End If
-' Convert data from ResponseBody instead of using ResponseText because of UTF-8
-myCdData = ConvertBinaryData(objHttp.ResponseBody)
-Set objHttp = Nothing
' Write received data to file if enabled
If (myCdSavF = TRUE) Then
- Set myFh = objFSO.OpenTextFile(myCdFile, 2, TRUE)
- myFh.Write myCdData
- myFh.Close
+ Call SaveBinaryData(myCdFile, objHttp.ResponseBody)
End If
+' Convert data from ResponseBody instead of using ResponseText because of UTF-8
+myCdData = ConvertBinaryToUTF8(objHttp.ResponseBody)
+Set objHttp = Nothing
' Backup exitsing ca-bundle certificate file
If (myCaBakF = TRUE) Then
If objFSO.FileExists(myCaFile) Then
@@ -86,15 +146,7 @@ If (myCaBakF = TRUE) Then
myTmpFh.Move myBakFile
End If
End If
-If (myAskTiF = TRUE) Then
- If (6 = objShell.PopUp("Do you want to include text information about each certificate?" & vbLf & _
- "(requires OpenSSL commandline in current directory or in search path)",, _
- mySelf, vbQuestion + vbYesNo + vbDefaultButton2)) Then
- myOptTxt = TRUE
- Else
- myOptTxt = FALSE
- End If
-End If
+
' Process the received data
Dim myLines, myPattern, myInsideCert, myInsideLicense, myLicenseText, myNumCerts, myNumSkipped
Dim myLabel, myOctets, myData, myPem, myRev, myUntrusted, j
@@ -102,23 +154,33 @@ myNumSkipped = 0
myNumCerts = 0
myData = ""
myLines = Split(myCdData, vbLf, -1)
-Set myFh = objFSO.OpenTextFile(myCaFile, 2, TRUE)
-myFh.Write "##" & vbLf
-myFh.Write "## " & myCaFile & " -- Bundle of CA Root Certificates" & vbLf
-myFh.Write "##" & vbLf
-myFh.Write "## Converted at: " & Now & vbLf
-myFh.Write "##" & vbLf
-myFh.Write "## This is a bundle of X.509 certificates of public Certificate Authorities" & vbLf
-myFh.Write "## (CA). These were automatically extracted from Mozilla's root certificates" & vbLf
-myFh.Write "## file (certdata.txt). This file can be found in the mozilla source tree:" & vbLf
-myFh.Write "## '/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt'" & vbLf
-myFh.Write "##" & vbLf
-myFh.Write "## It contains the certificates in PEM format and therefore" & vbLf
-myFh.Write "## can be directly used with curl / libcurl / php_curl, or with" & vbLf
-myFh.Write "## an Apache+mod_ssl webserver for SSL client authentication." & vbLf
-myFh.Write "## Just configure this file as the SSLCACertificateFile." & vbLf
-myFh.Write "##" & vbLf
-myFh.Write vbLf
+Set myStream = CreateObject("ADODB.Stream")
+myStream.Open
+myStream.Type = adTypeText
+myStream.Charset = "utf-8"
+myStream.WriteText "##" & vbLf & _
+ "## Bundle of CA Root Certificates" & vbLf & _
+ "##" & vbLf & _
+ "## Certificate data from Mozilla as of: " & _
+ ConvertDateToString(LocalDateToUTC(Now)) & " GMT" & vbLf & _
+ "##" & vbLf & _
+ "## This is a bundle of X.509 certificates of public Certificate Authorities" & vbLf & _
+ "## (CA). These were automatically extracted from Mozilla's root certificates" & vbLf & _
+ "## file (certdata.txt). This file can be found in the mozilla source tree:" & vbLf & _
+ "## " & myUrl & vbLf & _
+ "##" & vbLf & _
+ "## It contains the certificates in PEM format and therefore" & vbLf & _
+ "## can be directly used with curl / libcurl / php_curl, or with" & vbLf & _
+ "## an Apache+mod_ssl webserver for SSL client authentication." & vbLf & _
+ "## Just configure this file as the SSLCACertificateFile." & vbLf & _
+ "##" & vbLf & _
+ "## Conversion done with mk-ca-bundle.vbs version " & myVersion & "." & vbLf
+If (myCdSavF = TRUE) And (myUseOpenSSL = TRUE) Then
+ myStream.WriteText "## SHA256: " & FileSHA256(myCdFile) & vbLf
+End If
+myStream.WriteText "##" & vbLf & vbLf
+
+myStream.WriteText vbLf
For i = 0 To UBound(myLines)
If InstrRev(myLines(i), "CKA_LABEL ") Then
myPattern = "^CKA_LABEL\s+[A-Z0-9]+\s+""(.+?)"""
@@ -136,13 +198,13 @@ For i = 0 To UBound(myLines)
If (myUntrusted = TRUE) Then
myNumSkipped = myNumSkipped + 1
Else
- myFh.Write myLabel & vbLf
- myFh.Write String(Len(myLabel), "=") & vbLf
+ myStream.WriteText myLabel & vbLf
+ myStream.WriteText String(Len(myLabel), "=") & vbLf
myPem = "-----BEGIN CERTIFICATE-----" & vbLf & _
Base64Encode(myData) & vbLf & _
"-----END CERTIFICATE-----" & vbLf
If (myOptTxt = FALSE) Then
- myFh.Write myPem & vbLf
+ myStream.WriteText myPem & vbLf
Else
Dim myCmd, myRval, myTmpIn, myTmpOut
myTmpIn = objFSO.GetSpecialFolder(2).Path & "\" & objFSO.GetTempName
@@ -150,8 +212,8 @@ For i = 0 To UBound(myLines)
Set myTmpFh = objFSO.OpenTextFile(myTmpIn, 2, TRUE)
myTmpFh.Write myPem
myTmpFh.Close
- myCmd = myOpenssl & " x509 -md5 -fingerprint -text -inform PEM" & _
- " -in " & myTmpIn & " -out " & myTmpOut
+ myCmd = """" & myOpenSSL & """ x509 -md5 -fingerprint -text " & _
+ "-inform PEM -in " & myTmpIn & " -out " & myTmpOut
myRval = objShell.Run (myCmd, 0, TRUE)
objFSO.DeleteFile myTmpIn, TRUE
If Not (myRval = 0) Then
@@ -160,7 +222,7 @@ For i = 0 To UBound(myLines)
WScript.Quit 3
End If
Set myTmpFh = objFSO.OpenTextFile(myTmpOut, 1)
- myFh.Write myTmpFh.ReadAll & vbLf
+ myStream.WriteText myTmpFh.ReadAll & vbLf
myTmpFh.Close
objFSO.DeleteFile myTmpOut, TRUE
End If
@@ -176,7 +238,7 @@ For i = 0 To UBound(myLines)
If InstrRev(myLines(i), "CVS_ID ") Then
myPattern = "^CVS_ID\s+""(.+?)"""
myRev = RegExprFirst(myPattern, myLines(i))
- myFh.Write "# " & myRev & vbLf & vbLf
+ myStream.WriteText "# " & myRev & vbLf & vbLf
End If
If InstrRev(myLines(i), "CKA_VALUE MULTILINE_OCTAL") Then
myInsideCert = TRUE
@@ -187,7 +249,7 @@ For i = 0 To UBound(myLines)
myInsideLicense = TRUE
End If
If (myInsideLicense = TRUE) Then
- myFh.Write myLines(i) & vbLf
+ myStream.WriteText myLines(i) & vbLf
myLicenseText = myLicenseText & Mid(myLines(i), 2) & vbLf
End If
If InstrRev(myLines(i), "***** END LICENSE BLOCK *****") Then
@@ -196,28 +258,54 @@ For i = 0 To UBound(myLines)
If Not (6 = objShell.PopUp(myLicenseText & vbLf & _
"Do you agree to the license shown above (required to proceed) ?",, _
mySelf, vbQuestion + vbYesNo + vbDefaultButton1)) Then
- myFh.Close
+ myStream.Close
objFSO.DeleteFile myCaFile, TRUE
WScript.Quit 2
End If
End If
End If
Next
-myFh.Close
+
+' To stop the UTF-8 BOM from being written the stream has to be copied and
+' then saved as binary.
+Dim myCopy
+Set myCopy = CreateObject("ADODB.Stream")
+myCopy.Type = adTypeBinary
+myCopy.Open
+myStream.Position = 3 ' Skip UTF-8 BOM
+myStream.CopyTo myCopy
+myCopy.SaveToFile myCaFile, adSaveCreateOverWrite
+myCopy.Close
+myStream.Close
+Set myCopy = Nothing
+Set myStream = Nothing
+
+' Done
objShell.PopUp "Done (" & myNumCerts & " CA certs processed, " & myNumSkipped & _
" untrusted skipped).", 20, mySelf, vbInformation
WScript.Quit 0
-Function ConvertBinaryData(arrBytes)
+Function ConvertBinaryToUTF8(arrBytes)
Dim objStream
Set objStream = CreateObject("ADODB.Stream")
objStream.Open
- objStream.Type = 1
+ objStream.Type = adTypeBinary
objStream.Write arrBytes
objStream.Position = 0
- objStream.Type = 2
- objStream.Charset = "ascii"
- ConvertBinaryData = objStream.ReadText
+ objStream.Type = adTypeText
+ objStream.Charset = "utf-8"
+ ConvertBinaryToUTF8 = objStream.ReadText
+ Set objStream = Nothing
+End Function
+
+Function SaveBinaryData(filename, data)
+ Dim objStream
+ Set objStream = CreateObject("ADODB.Stream")
+ objStream.Type = adTypeBinary
+ objStream.Open
+ objStream.Write data
+ objStream.SaveToFile filename, adSaveCreateOverWrite
+ objStream.Close
Set objStream = Nothing
End Function
@@ -283,4 +371,61 @@ Function MyASC(OneChar)
If OneChar = "" Then MyASC = 0 Else MyASC = Asc(OneChar)
End Function
+' Return the date in the same format as perl to match mk-ca-bundle.pl output:
+' Wed Sep 7 03:12:05 2016
+Function ConvertDateToString(input)
+ Dim output
+ output = WeekDayName(WeekDay(input), TRUE) & " " & _
+ MonthName(Month(input), TRUE) & " "
+ If (Len(Day(input)) = 1) Then
+ output = output & " "
+ End If
+ output = output & _
+ Day(input) & " " & _
+ FormatDateTime(input, vbShortTime) & ":"
+ If (Len(Second(input)) = 1) Then
+ output = output & "0"
+ End If
+ output = output & _
+ Second(input) & " " & _
+ Year(input)
+ ConvertDateToString = output
+End Function
+' Convert local Date to UTC. Microsoft says:
+' Use Win32_ComputerSystem CurrentTimeZone property, because it automatically
+' adjusts the Time Zone bias for daylight saving time; Win32_Time Zone Bias
+' property does not.
+' https://msdn.microsoft.com/en-us/library/windows/desktop/ms696015.aspx
+Function LocalDateToUTC(localdate)
+ Dim item, offset
+ For Each item In GetObject("winmgmts:").InstancesOf("Win32_ComputerSystem")
+ offset = item.CurrentTimeZone ' the offset in minutes
+ Next
+ If (offset < 0) Then
+ LocalDateToUTC = DateAdd("n", ABS(offset), localdate)
+ Else
+ LocalDateToUTC = DateAdd("n", -ABS(offset), localdate)
+ End If
+ 'objShell.PopUp LocalDateToUTC
+End Function
+
+Function FileSHA256(filename)
+ Dim cmd, rval, tmpOut, tmpFh
+ if (myUseOpenSSL = TRUE) Then
+ tmpOut = objFSO.GetSpecialFolder(2).Path & "\" & objFSO.GetTempName
+ cmd = """" & myOpenSSL & """ dgst -r -sha256 -out """ & tmpOut & """ """ & filename & """"
+ rval = objShell.Run(cmd, 0, TRUE)
+ If Not (rval = 0) Then
+ MsgBox("Failed to get sha256 of """ & filename & """ with OpenSSL commandline!"), vbCritical, mySelf
+ objFSO.DeleteFile tmpOut, TRUE
+ WScript.Quit 3
+ End If
+ Set tmpFh = objFSO.OpenTextFile(tmpOut, 1)
+ FileSHA256 = RegExprFirst("^([0-9a-f]{64}) .+", tmpFh.ReadAll)
+ tmpFh.Close
+ objFSO.DeleteFile tmpOut, TRUE
+ Else
+ FileSHA256 = ""
+ End If
+End Function
diff --git a/lib/mprintf.c b/lib/mprintf.c
index 73f854bc..e1ad537f 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -227,10 +227,12 @@ static bool dprintf_IsQualifierNoDollar(const char *fmt)
* Create an index with the type of each parameter entry and its
* value (may vary in size)
*
+ * Returns zero on success.
+ *
******************************************************************/
-static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
- va_list arglist)
+static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
+ va_list arglist)
{
char *fmt = (char *)format;
int param_num = 0;
@@ -301,7 +303,6 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
flags |= FLAGS_ALT;
break;
case '.':
- flags |= FLAGS_PREC;
if('*' == *fmt) {
/* The precision is picked from a specified parameter */
@@ -393,6 +394,10 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
i = this_param - 1;
+ if((i < 0) || (i >= MAX_PARAMETERS))
+ /* out of allowed range */
+ return 1;
+
switch (*fmt) {
case 'S':
flags |= FLAGS_ALT;
@@ -549,7 +554,7 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
}
}
- return max_param;
+ return 0;
}
@@ -587,7 +592,8 @@ static int dprintf_formatf(
char *workend = &work[sizeof(work) - 2];
/* Do the actual %-code parsing */
- dprintf_Pass1(format, vto, endpos, ap_save);
+ if(dprintf_Pass1(format, vto, endpos, ap_save))
+ return -1;
end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1()
created for us */
@@ -992,7 +998,7 @@ int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
info.max = maxlength;
retcode = dprintf_formatf(&info, addbyter, format, ap_save);
- if(info.max) {
+ if((retcode != -1) && info.max) {
/* we terminate this with a zero byte */
if(info.max == info.length)
/* we're at maximum, scrap the last letter */
@@ -1029,16 +1035,19 @@ static int alloc_addbyter(int output, FILE *data)
infop->len =0;
}
else if(infop->len+1 >= infop->alloc) {
- char *newptr;
+ char *newptr = NULL;
+ size_t newsize = infop->alloc*2;
- newptr = realloc(infop->buffer, infop->alloc*2);
+ /* detect wrap-around or other overflow problems */
+ if(newsize > infop->alloc)
+ newptr = realloc(infop->buffer, newsize);
if(!newptr) {
infop->fail = 1;
return -1; /* fail */
}
infop->buffer = newptr;
- infop->alloc *= 2;
+ infop->alloc = newsize;
}
infop->buffer[ infop->len ] = outc;
diff --git a/lib/multi.c b/lib/multi.c
index 8bb93660..950b600c 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -42,6 +42,8 @@
#include "multihandle.h"
#include "pipeline.h"
#include "sigpipe.h"
+#include "vtls/vtls.h"
+#include "connect.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -442,7 +444,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
sockets that time-out or have actions will be dealt with. Since this
handle has no action yet, we make sure it times out to get things to
happen. */
- Curl_expire(data, 1);
+ Curl_expire(data, 0);
/* increase the node-counter */
multi->num_easy++;
@@ -462,6 +464,14 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
handle is added */
memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
+ /* The closure handle only ever has default timeouts set. To improve the
+ state somewhat we clone the timeouts from each added handle so that the
+ closure handle always has the same timeouts as the most recently added
+ easy handle. */
+ multi->closure_handle->set.timeout = data->set.timeout;
+ multi->closure_handle->set.server_response_timeout =
+ data->set.server_response_timeout;
+
update_timer(multi);
return CURLM_OK;
}
@@ -569,12 +579,12 @@ static CURLcode multi_done(struct connectdata **connp,
result = CURLE_ABORTED_BY_CALLBACK;
}
- if((!premature &&
- conn->send_pipe->size + conn->recv_pipe->size != 0 &&
- !data->set.reuse_forbid &&
- !conn->bits.close)) {
+ if(conn->send_pipe->size + conn->recv_pipe->size != 0 &&
+ !data->set.reuse_forbid &&
+ !conn->bits.close) {
/* Stop if pipeline is not empty and we do not have to close
connection. */
+ data->easy_conn = NULL;
DEBUGF(infof(data, "Connection still in use, no more multi_done now!\n"));
return CURLE_OK;
}
@@ -685,7 +695,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
/* If the handle is in a pipeline and has started sending off its
request but not received its response yet, we need to close
connection. */
- connclose(data->easy_conn, "Removed with partial response");
+ streamclose(data->easy_conn, "Removed with partial response");
/* Set connection owner so that the DONE function closes it. We can
safely do this here since connection is killed. */
data->easy_conn->data = easy;
@@ -695,7 +705,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
/* The timer must be shut down before data->multi is set to NULL,
else the timenode will remain in the splay tree after
curl_easy_cleanup is called. */
- Curl_expire(data, 0);
+ Curl_expire_clear(data);
if(data->dns.hostcachetype == HCACHE_MULTI) {
/* stop using the multi handle's DNS cache */
@@ -803,6 +813,11 @@ static int waitconnect_getsock(struct connectdata *conn,
if(!numsocks)
return GETSOCK_BLANK;
+#ifdef USE_SSL
+ if(CONNECT_FIRSTSOCKET_PROXY_SSL())
+ return Curl_ssl_getsock(conn, sock, numsocks);
+#endif
+
for(i=0; i<2; i++) {
if(conn->tempsock[i] != CURL_SOCKET_BAD) {
sock[s] = conn->tempsock[i];
@@ -1291,14 +1306,16 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
CURLMcode rc;
CURLcode result = CURLE_OK;
struct SingleRequest *k;
- long timeout_ms;
+ time_t timeout_ms;
int control;
if(!GOOD_EASY_HANDLE(data))
return CURLM_BAD_EASY_HANDLE;
do {
- bool disconnect_conn = FALSE;
+ /* A "stream" here is a logical stream if the protocol can handle that
+ (HTTP/2), or the full connection for older protocols */
+ bool stream_error = FALSE;
rc = CURLM_OK;
/* Handle the case when the pipe breaks, i.e., the connection
@@ -1376,8 +1393,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* Force connection closed if the connection has indeed been used */
if(data->mstate > CURLM_STATE_DO) {
- connclose(data->easy_conn, "Disconnected with pending data");
- disconnect_conn = TRUE;
+ streamclose(data->easy_conn, "Disconnected with pending data");
+ stream_error = TRUE;
}
result = CURLE_OPERATION_TIMEDOUT;
(void)multi_done(&data->easy_conn, result, TRUE);
@@ -1426,7 +1443,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* Add this handle to the send or pend pipeline */
result = Curl_add_handle_to_pipeline(data, data->easy_conn);
if(result)
- disconnect_conn = TRUE;
+ stream_error = TRUE;
else {
if(async)
/* We're now waiting for an asynchronous name lookup */
@@ -1518,7 +1535,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(result) {
/* failure detected */
- disconnect_conn = TRUE;
+ stream_error = TRUE;
break;
}
}
@@ -1537,7 +1554,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
multistate(data, CURLM_STATE_CONNECT);
}
else if(!result) {
- if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE) {
+ if((data->easy_conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
+ data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
+ (data->easy_conn->tunnel_state[FIRSTSOCKET] != TUNNEL_CONNECT)) {
rc = CURLM_CALL_MULTI_PERFORM;
/* initiate protocol connect phase */
multistate(data, CURLM_STATE_SENDPROTOCONNECT);
@@ -1550,6 +1569,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* awaiting a completion of an asynch TCP connect */
result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected);
if(connected && !result) {
+#ifndef CURL_DISABLE_HTTP
+ if((data->easy_conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
+ !data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
+ (data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)) {
+ multistate(data, CURLM_STATE_WAITPROXYCONNECT);
+ break;
+ }
+#endif
rc = CURLM_CALL_MULTI_PERFORM;
multistate(data, data->easy_conn->bits.tunnel_proxy?
CURLM_STATE_WAITPROXYCONNECT:
@@ -1558,7 +1585,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
else if(result) {
/* failure detected */
/* Just break, the cleaning up is handled all in one place */
- disconnect_conn = TRUE;
+ stream_error = TRUE;
break;
}
break;
@@ -1578,7 +1605,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* failure detected */
Curl_posttransfer(data);
multi_done(&data->easy_conn, result, TRUE);
- disconnect_conn = TRUE;
+ stream_error = TRUE;
}
break;
@@ -1595,7 +1622,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* failure detected */
Curl_posttransfer(data);
multi_done(&data->easy_conn, result, TRUE);
- disconnect_conn = TRUE;
+ stream_error = TRUE;
}
break;
@@ -1670,7 +1697,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(drc) {
/* a failure here pretty much implies an out of memory */
result = drc;
- disconnect_conn = TRUE;
+ stream_error = TRUE;
}
else
retry = (newurl)?TRUE:FALSE;
@@ -1703,7 +1730,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
else {
/* Have error handler disconnect conn if we can't retry */
- disconnect_conn = TRUE;
+ stream_error = TRUE;
free(newurl);
}
}
@@ -1712,7 +1739,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
Curl_posttransfer(data);
if(data->easy_conn)
multi_done(&data->easy_conn, result, FALSE);
- disconnect_conn = TRUE;
+ stream_error = TRUE;
}
}
break;
@@ -1734,7 +1761,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* failure detected */
Curl_posttransfer(data);
multi_done(&data->easy_conn, result, FALSE);
- disconnect_conn = TRUE;
+ stream_error = TRUE;
}
break;
@@ -1763,7 +1790,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* failure detected */
Curl_posttransfer(data);
multi_done(&data->easy_conn, result, FALSE);
- disconnect_conn = TRUE;
+ stream_error = TRUE;
}
break;
@@ -1800,9 +1827,17 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
result = Curl_speedcheck(data, now);
if(( (data->set.max_send_speed == 0) ||
- (data->progress.ulspeed < data->set.max_send_speed)) &&
+ (Curl_pgrsLimitWaitTime(data->progress.uploaded,
+ data->progress.ul_limit_size,
+ data->set.max_send_speed,
+ data->progress.ul_limit_start,
+ now) <= 0)) &&
( (data->set.max_recv_speed == 0) ||
- (data->progress.dlspeed < data->set.max_recv_speed)))
+ (Curl_pgrsLimitWaitTime(data->progress.downloaded,
+ data->progress.dl_limit_size,
+ data->set.max_recv_speed,
+ data->progress.dl_limit_start,
+ now) <= 0)))
multistate(data, CURLM_STATE_PERFORM);
break;
@@ -1810,41 +1845,38 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
{
char *newurl = NULL;
bool retry = FALSE;
+ bool comeback = FALSE;
/* check if over send speed */
- if((data->set.max_send_speed > 0) &&
- (data->progress.ulspeed > data->set.max_send_speed)) {
- int buffersize;
-
- multistate(data, CURLM_STATE_TOOFAST);
-
- /* calculate upload rate-limitation timeout. */
- buffersize = (int)(data->set.buffer_size ?
- data->set.buffer_size : BUFSIZE);
- timeout_ms = Curl_sleep_time(data->set.max_send_speed,
- data->progress.ulspeed, buffersize);
- Curl_expire_latest(data, timeout_ms);
- break;
+ if(data->set.max_send_speed > 0) {
+ timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
+ data->progress.ul_limit_size,
+ data->set.max_send_speed,
+ data->progress.ul_limit_start,
+ now);
+ if(timeout_ms > 0) {
+ multistate(data, CURLM_STATE_TOOFAST);
+ Curl_expire_latest(data, timeout_ms);
+ break;
+ }
}
/* check if over recv speed */
- if((data->set.max_recv_speed > 0) &&
- (data->progress.dlspeed > data->set.max_recv_speed)) {
- int buffersize;
-
- multistate(data, CURLM_STATE_TOOFAST);
-
- /* Calculate download rate-limitation timeout. */
- buffersize = (int)(data->set.buffer_size ?
- data->set.buffer_size : BUFSIZE);
- timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
- data->progress.dlspeed, buffersize);
- Curl_expire_latest(data, timeout_ms);
- break;
+ if(data->set.max_recv_speed > 0) {
+ timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
+ data->progress.dl_limit_size,
+ data->set.max_recv_speed,
+ data->progress.dl_limit_start,
+ now);
+ if(timeout_ms > 0) {
+ multistate(data, CURLM_STATE_TOOFAST);
+ Curl_expire_latest(data, timeout_ms);
+ break;
+ }
}
/* read/write data if it is ready to do so */
- result = Curl_readwrite(data->easy_conn, data, &done);
+ result = Curl_readwrite(data->easy_conn, data, &done, &comeback);
k = &data->req;
@@ -1884,10 +1916,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(!(data->easy_conn->handler->flags & PROTOPT_DUAL) &&
result != CURLE_HTTP2_STREAM)
- connclose(data->easy_conn, "Transfer returned error");
+ streamclose(data->easy_conn, "Transfer returned error");
Curl_posttransfer(data);
- multi_done(&data->easy_conn, result, FALSE);
+ multi_done(&data->easy_conn, result, TRUE);
}
else if(done) {
followtype follow=FOLLOW_NONE;
@@ -1900,7 +1932,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* expire the new receiving pipeline head */
if(data->easy_conn->recv_pipe->head)
- Curl_expire_latest(data->easy_conn->recv_pipe->head->ptr, 1);
+ Curl_expire_latest(data->easy_conn->recv_pipe->head->ptr, 0);
/* Check if we can move pending requests to send pipe */
Curl_multi_process_pending_handles(multi);
@@ -1943,13 +1975,15 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(!result)
newurl = NULL; /* allocation was handed over Curl_follow() */
else
- disconnect_conn = TRUE;
+ stream_error = TRUE;
}
multistate(data, CURLM_STATE_DONE);
rc = CURLM_CALL_MULTI_PERFORM;
}
}
+ else if(comeback)
+ rc = CURLM_CALL_MULTI_PERFORM;
free(newurl);
break;
@@ -2008,7 +2042,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
that could be freed anytime */
data->easy_conn = NULL;
- Curl_expire(data, 0); /* stop all timers */
+ Curl_expire_clear(data); /* stop all timers */
break;
case CURLM_STATE_MSGSENT:
@@ -2042,7 +2076,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
Curl_removeHandleFromPipeline(data, data->easy_conn->send_pipe);
Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
- if(disconnect_conn) {
+ if(stream_error) {
/* Don't attempt to send data over a connection that timed out */
bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
/* disconnect properly */
@@ -2066,7 +2100,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* aborted due to progress callback return code must close the
connection */
result = CURLE_ABORTED_BY_CALLBACK;
- connclose(data->easy_conn, "Aborted by callback");
+ streamclose(data->easy_conn, "Aborted by callback");
/* if not yet in DONE state, go there, otherwise COMPLETED */
multistate(data, (data->mstate < CURLM_STATE_DONE)?
@@ -2160,6 +2194,7 @@ static void close_all_connections(struct Curl_multi *multi)
conn->data->easy_conn = NULL; /* clear the easy handle's connection
pointer */
/* This will remove the connection from the cache */
+ connclose(conn, "kill all");
(void)Curl_disconnect(conn, FALSE);
sigpipe_restore(&pipe_st);
@@ -2467,7 +2502,7 @@ static CURLMcode add_next_timeout(struct timeval now,
timeout in *tv */
for(e = list->head; e;) {
struct curl_llist_element *n = e->next;
- long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
+ time_t diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
if(diff <= 0)
/* remove outdated entry */
Curl_llist_remove(list, e, NULL);
@@ -2745,7 +2780,7 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
/* some time left before expiration */
- *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
+ *timeout_ms = (long)curlx_tvdiff(multi->timetree->key, now);
if(!*timeout_ms)
/*
* Since we only provide millisecond resolution on the returned value
@@ -2852,7 +2887,7 @@ multi_addtimeout(struct curl_llist *timeoutlist,
/* find the correct spot in the list */
for(e = timeoutlist->head; e; e = e->next) {
struct timeval *checktime = e->ptr;
- long diff = curlx_tvdiff(*checktime, *timedup);
+ time_t diff = curlx_tvdiff(*checktime, *timedup);
if(diff > 0)
break;
prev = e;
@@ -2876,92 +2911,59 @@ multi_addtimeout(struct curl_llist *timeoutlist,
* given a number of milliseconds from now to use to set the 'act before
* this'-time for the transfer, to be extracted by curl_multi_timeout()
*
- * Note that the timeout will be added to a queue of timeouts if it defines a
- * moment in time that is later than the current head of queue.
- *
- * Pass zero to clear all timeout values for this handle.
-*/
-void Curl_expire(struct Curl_easy *data, long milli)
+ * The timeout will be added to a queue of timeouts if it defines a moment in
+ * time that is later than the current head of queue.
+ */
+void Curl_expire(struct Curl_easy *data, time_t milli)
{
struct Curl_multi *multi = data->multi;
struct timeval *nowp = &data->state.expiretime;
int rc;
+ struct timeval set;
/* this is only interesting while there is still an associated multi struct
remaining! */
if(!multi)
return;
- if(!milli) {
- /* No timeout, clear the time data. */
- if(nowp->tv_sec || nowp->tv_usec) {
- /* Since this is an cleared time, we must remove the previous entry from
- the splay tree */
- struct curl_llist *list = data->state.timeoutlist;
-
- rc = Curl_splayremovebyaddr(multi->timetree,
- &data->state.timenode,
- &multi->timetree);
- if(rc)
- infof(data, "Internal error clearing splay node = %d\n", rc);
-
- /* flush the timeout list too */
- while(list->size > 0)
- Curl_llist_remove(list, list->tail, NULL);
+ set = Curl_tvnow();
+ set.tv_sec += (long)(milli/1000);
+ set.tv_usec += (milli%1000)*1000;
-#ifdef DEBUGBUILD
- infof(data, "Expire cleared\n");
-#endif
- nowp->tv_sec = 0;
- nowp->tv_usec = 0;
- }
+ if(set.tv_usec >= 1000000) {
+ set.tv_sec++;
+ set.tv_usec -= 1000000;
}
- else {
- struct timeval set;
- set = Curl_tvnow();
- set.tv_sec += milli/1000;
- set.tv_usec += (milli%1000)*1000;
-
- if(set.tv_usec >= 1000000) {
- set.tv_sec++;
- set.tv_usec -= 1000000;
- }
-
- if(nowp->tv_sec || nowp->tv_usec) {
- /* This means that the struct is added as a node in the splay tree.
- Compare if the new time is earlier, and only remove-old/add-new if it
- is. */
- long diff = curlx_tvdiff(set, *nowp);
- if(diff > 0) {
- /* the new expire time was later so just add it to the queue
- and get out */
- multi_addtimeout(data->state.timeoutlist, &set);
- return;
- }
-
- /* the new time is newer than the presently set one, so add the current
- to the queue and update the head */
- multi_addtimeout(data->state.timeoutlist, nowp);
-
- /* Since this is an updated time, we must remove the previous entry from
- the splay tree first and then re-add the new value */
- rc = Curl_splayremovebyaddr(multi->timetree,
- &data->state.timenode,
- &multi->timetree);
- if(rc)
- infof(data, "Internal error removing splay node = %d\n", rc);
+ if(nowp->tv_sec || nowp->tv_usec) {
+ /* This means that the struct is added as a node in the splay tree.
+ Compare if the new time is earlier, and only remove-old/add-new if it
+ is. */
+ time_t diff = curlx_tvdiff(set, *nowp);
+ if(diff > 0) {
+ /* the new expire time was later so just add it to the queue
+ and get out */
+ multi_addtimeout(data->state.timeoutlist, &set);
+ return;
}
- *nowp = set;
- data->state.timenode.payload = data;
- multi->timetree = Curl_splayinsert(*nowp,
- multi->timetree,
- &data->state.timenode);
+ /* the new time is newer than the presently set one, so add the current
+ to the queue and update the head */
+ multi_addtimeout(data->state.timeoutlist, nowp);
+
+ /* Since this is an updated time, we must remove the previous entry from
+ the splay tree first and then re-add the new value */
+ rc = Curl_splayremovebyaddr(multi->timetree,
+ &data->state.timenode,
+ &multi->timetree);
+ if(rc)
+ infof(data, "Internal error removing splay node = %d\n", rc);
}
-#if 0
- Curl_splayprint(multi->timetree, 0, TRUE);
-#endif
+
+ *nowp = set;
+ data->state.timenode.payload = data;
+ multi->timetree = Curl_splayinsert(*nowp, multi->timetree,
+ &data->state.timenode);
}
/*
@@ -2975,14 +2977,14 @@ void Curl_expire(struct Curl_easy *data, long milli)
* time-out period to expire.
*
*/
-void Curl_expire_latest(struct Curl_easy *data, long milli)
+void Curl_expire_latest(struct Curl_easy *data, time_t milli)
{
struct timeval *expire = &data->state.expiretime;
struct timeval set;
set = Curl_tvnow();
- set.tv_sec += milli / 1000;
+ set.tv_sec += (long)(milli / 1000);
set.tv_usec += (milli % 1000) * 1000;
if(set.tv_usec >= 1000000) {
@@ -2994,7 +2996,7 @@ void Curl_expire_latest(struct Curl_easy *data, long milli)
/* This means that the struct is added as a node in the splay tree.
Compare if the new time is earlier, and only remove-old/add-new if it
is. */
- long diff = curlx_tvdiff(set, *expire);
+ time_t diff = curlx_tvdiff(set, *expire);
if(diff > 0)
/* the new expire time was later than the top time, so just skip this */
return;
@@ -3004,6 +3006,49 @@ void Curl_expire_latest(struct Curl_easy *data, long milli)
Curl_expire(data, milli);
}
+
+/*
+ * Curl_expire_clear()
+ *
+ * Clear ALL timeout values for this handle.
+ */
+void Curl_expire_clear(struct Curl_easy *data)
+{
+ struct Curl_multi *multi = data->multi;
+ struct timeval *nowp = &data->state.expiretime;
+ int rc;
+
+ /* this is only interesting while there is still an associated multi struct
+ remaining! */
+ if(!multi)
+ return;
+
+ if(nowp->tv_sec || nowp->tv_usec) {
+ /* Since this is an cleared time, we must remove the previous entry from
+ the splay tree */
+ struct curl_llist *list = data->state.timeoutlist;
+
+ rc = Curl_splayremovebyaddr(multi->timetree,
+ &data->state.timenode,
+ &multi->timetree);
+ if(rc)
+ infof(data, "Internal error clearing splay node = %d\n", rc);
+
+ /* flush the timeout list too */
+ while(list->size > 0)
+ Curl_llist_remove(list, list->tail, NULL);
+
+#ifdef DEBUGBUILD
+ infof(data, "Expire cleared\n");
+#endif
+ nowp->tv_sec = 0;
+ nowp->tv_usec = 0;
+ }
+}
+
+
+
+
CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s,
void *hashp)
{
@@ -3064,7 +3109,7 @@ void Curl_multi_process_pending_handles(struct Curl_multi *multi)
Curl_llist_remove(multi->pending, e, NULL);
/* Make sure that the handle will be processed soonish. */
- Curl_expire_latest(data, 1);
+ Curl_expire_latest(data, 0);
}
e = next; /* operate on next handle */
diff --git a/lib/multihandle.h b/lib/multihandle.h
index c56b6aec..0b78de94 100644
--- a/lib/multihandle.h
+++ b/lib/multihandle.h
@@ -38,7 +38,9 @@ typedef enum {
CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */
CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */
CURLM_STATE_WAITCONNECT, /* 4 - awaiting the TCP connect to finalize */
- CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting proxy CONNECT to finalize */
+ CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting HTTPS proxy SSL initialization
+ to complete and/or proxy CONNECT to
+ finalize */
CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */
CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect
phase */
diff --git a/lib/multiif.h b/lib/multiif.h
index fd2df556..e5de1fc4 100644
--- a/lib/multiif.h
+++ b/lib/multiif.h
@@ -25,8 +25,9 @@
/*
* Prototypes for library-wide functions provided by multi.c
*/
-void Curl_expire(struct Curl_easy *data, long milli);
-void Curl_expire_latest(struct Curl_easy *data, long milli);
+void Curl_expire(struct Curl_easy *data, time_t milli);
+void Curl_expire_clear(struct Curl_easy *data);
+void Curl_expire_latest(struct Curl_easy *data, time_t milli);
bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
void Curl_multi_handlePipeBreak(struct Curl_easy *data);
diff --git a/lib/netrc.c b/lib/netrc.c
index 46f427a2..996711d1 100644
--- a/lib/netrc.c
+++ b/lib/netrc.c
@@ -28,10 +28,8 @@
#include <curl/curl.h>
#include "netrc.h"
-
-#include "strequal.h"
#include "strtok.h"
-#include "rawstr.h"
+#include "strcase.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -130,20 +128,20 @@ int Curl_parsenetrc(const char *host,
switch(state) {
case NOTHING:
- if(Curl_raw_equal("machine", tok)) {
+ if(strcasecompare("machine", tok)) {
/* the next tok is the machine name, this is in itself the
delimiter that starts the stuff entered for this machine,
after this we need to search for 'login' and
'password'. */
state=HOSTFOUND;
}
- else if(Curl_raw_equal("default", tok)) {
+ else if(strcasecompare("default", tok)) {
state=HOSTVALID;
retcode=0; /* we did find our host */
}
break;
case HOSTFOUND:
- if(Curl_raw_equal(host, tok)) {
+ if(strcasecompare(host, tok)) {
/* and yes, this is our host! */
state=HOSTVALID;
retcode=0; /* we did find our host */
@@ -156,7 +154,7 @@ int Curl_parsenetrc(const char *host,
/* we are now parsing sub-keywords concerning "our" host */
if(state_login) {
if(specific_login) {
- state_our_login = Curl_raw_equal(*loginp, tok);
+ state_our_login = strcasecompare(*loginp, tok);
}
else {
free(*loginp);
@@ -179,11 +177,11 @@ int Curl_parsenetrc(const char *host,
}
state_password=0;
}
- else if(Curl_raw_equal("login", tok))
+ else if(strcasecompare("login", tok))
state_login=1;
- else if(Curl_raw_equal("password", tok))
+ else if(strcasecompare("password", tok))
state_password=1;
- else if(Curl_raw_equal("machine", tok)) {
+ else if(strcasecompare("machine", tok)) {
/* ok, there's machine here go => */
state = HOSTFOUND;
state_our_login = FALSE;
diff --git a/lib/non-ascii.c b/lib/non-ascii.c
index ed146180..2f5de4c6 100644
--- a/lib/non-ascii.c
+++ b/lib/non-ascii.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -117,7 +117,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
/* call iconv */
input_ptr = output_ptr = buffer;
in_bytes = out_bytes = length;
- rc = iconv(data->outbound_cd, (const char**)&input_ptr, &in_bytes,
+ rc = iconv(data->outbound_cd, (const char **)&input_ptr, &in_bytes,
&output_ptr, &out_bytes);
if((rc == ICONV_ERROR) || (in_bytes != 0)) {
error = ERRNO;
diff --git a/lib/parsedate.c b/lib/parsedate.c
index 7aad5c25..943f547a 100644
--- a/lib/parsedate.c
+++ b/lib/parsedate.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -80,7 +80,7 @@
#endif
#include <curl/curl.h>
-#include "rawstr.h"
+#include "strcase.h"
#include "warnless.h"
#include "parsedate.h"
@@ -211,7 +211,7 @@ static int checkday(const char *check, size_t len)
else
what = &Curl_wkday[0];
for(i=0; i<7; i++) {
- if(Curl_raw_equal(check, what[0])) {
+ if(strcasecompare(check, what[0])) {
found=TRUE;
break;
}
@@ -228,7 +228,7 @@ static int checkmonth(const char *check)
what = &Curl_month[0];
for(i=0; i<12; i++) {
- if(Curl_raw_equal(check, what[0])) {
+ if(strcasecompare(check, what[0])) {
found=TRUE;
break;
}
@@ -248,7 +248,7 @@ static int checktz(const char *check)
what = tz;
for(i=0; i< sizeof(tz)/sizeof(tz[0]); i++) {
- if(Curl_raw_equal(check, what->name)) {
+ if(strcasecompare(check, what->name)) {
found=TRUE;
break;
}
@@ -386,15 +386,17 @@ static int parsedate(const char *date, time_t *output)
/* a digit */
int val;
char *end;
+ int len=0;
if((secnum == -1) &&
- (3 == sscanf(date, "%02d:%02d:%02d", &hournum, &minnum, &secnum))) {
+ (3 == sscanf(date, "%02d:%02d:%02d%n",
+ &hournum, &minnum, &secnum, &len))) {
/* time stamp! */
- date += 8;
+ date += len;
}
else if((secnum == -1) &&
- (2 == sscanf(date, "%02d:%02d", &hournum, &minnum))) {
+ (2 == sscanf(date, "%02d:%02d%n", &hournum, &minnum, &len))) {
/* time stamp without seconds */
- date += 5;
+ date += len;
secnum = 0;
}
else {
diff --git a/lib/pingpong.c b/lib/pingpong.c
index 92ff84ba..7a993572 100644
--- a/lib/pingpong.c
+++ b/lib/pingpong.c
@@ -44,12 +44,12 @@
/* Returns timeout in ms. 0 or negative number means the timeout has already
triggered */
-long Curl_pp_state_timeout(struct pingpong *pp)
+time_t Curl_pp_state_timeout(struct pingpong *pp)
{
struct connectdata *conn = pp->conn;
struct Curl_easy *data=conn->data;
- long timeout_ms; /* in milliseconds */
- long timeout2_ms; /* in milliseconds */
+ time_t timeout_ms; /* in milliseconds */
+ time_t timeout2_ms; /* in milliseconds */
long response_time= (data->set.server_response_timeout)?
data->set.server_response_timeout: pp->response_time;
@@ -83,8 +83,8 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
struct connectdata *conn = pp->conn;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc;
- long interval_ms;
- long timeout_ms = Curl_pp_state_timeout(pp);
+ time_t interval_ms;
+ time_t timeout_ms = Curl_pp_state_timeout(pp);
struct Curl_easy *data=conn->data;
CURLcode result = CURLE_OK;
@@ -101,14 +101,17 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
else
interval_ms = 0; /* immediate */
- if(Curl_pp_moredata(pp))
+ if(Curl_ssl_data_pending(conn, FIRSTSOCKET))
+ rc = 1;
+ else if(Curl_pp_moredata(pp))
/* We are receiving and there is data in the cache so just read it */
rc = 1;
else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET))
/* We are receiving and there is data ready in the SSL library */
rc = 1;
else
- rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */
+ rc = Curl_socket_check(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */
+ CURL_SOCKET_BAD,
pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */
interval_ms);
diff --git a/lib/pingpong.h b/lib/pingpong.h
index 2f649d5b..500100ae 100644
--- a/lib/pingpong.h
+++ b/lib/pingpong.h
@@ -88,7 +88,7 @@ void Curl_pp_init(struct pingpong *pp);
/* Returns timeout in ms. 0 or negative number means the timeout has already
triggered */
-long Curl_pp_state_timeout(struct pingpong *pp);
+time_t Curl_pp_state_timeout(struct pingpong *pp);
/***********************************************************************
diff --git a/lib/pipeline.c b/lib/pipeline.c
index 0ff82f08..40a5e82d 100644
--- a/lib/pipeline.c
+++ b/lib/pipeline.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2013, Linus Nielsen Feltzing, <linus@haxx.se>
- * Copyright (C) 2013-2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2013-2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@
#include "multiif.h"
#include "pipeline.h"
#include "sendf.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -114,7 +114,7 @@ CURLcode Curl_add_handle_to_pipeline(struct Curl_easy *handle,
if(pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) {
/* this is a new one as head, expire it */
Curl_pipeline_leave_write(conn); /* not in use yet */
- Curl_expire(conn->send_pipe->head->ptr, 1);
+ Curl_expire(conn->send_pipe->head->ptr, 0);
}
#if 0 /* enable for pipeline debugging */
@@ -149,7 +149,7 @@ void Curl_move_handle_from_send_to_recv_pipe(struct Curl_easy *handle,
infof(conn->data, "%p is at send pipe head B!\n",
(void *)conn->send_pipe->head->ptr);
#endif
- Curl_expire(conn->send_pipe->head->ptr, 1);
+ Curl_expire(conn->send_pipe->head->ptr, 0);
}
/* The receiver's list is not really interesting here since either this
@@ -177,7 +177,7 @@ bool Curl_pipeline_site_blacklisted(struct Curl_easy *handle,
struct site_blacklist_entry *site;
site = curr->ptr;
- if(Curl_raw_equal(site->hostname, conn->host.name) &&
+ if(strcasecompare(site->hostname, conn->host.name) &&
site->port == conn->remote_port) {
infof(handle, "Site %s:%d is pipeline blacklisted\n",
conn->host.name, conn->remote_port);
@@ -269,7 +269,7 @@ bool Curl_pipeline_server_blacklisted(struct Curl_easy *handle,
char *bl_server_name;
bl_server_name = curr->ptr;
- if(Curl_raw_nequal(bl_server_name, server_name,
+ if(strncasecompare(bl_server_name, server_name,
strlen(bl_server_name))) {
infof(handle, "Server %s is blacklisted\n", server_name);
return TRUE;
diff --git a/lib/pop3.c b/lib/pop3.c
index 591e877f..9bb691c9 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -70,16 +70,14 @@
#include "http.h" /* for HTTP proxy tunnel stuff */
#include "socks.h"
#include "pop3.h"
-
#include "strtoofft.h"
-#include "strequal.h"
+#include "strcase.h"
#include "vtls/vtls.h"
#include "connect.h"
#include "strerror.h"
#include "select.h"
#include "multiif.h"
#include "url.h"
-#include "rawstr.h"
#include "curl_sasl.h"
#include "curl_md5.h"
#include "warnless.h"
@@ -106,7 +104,7 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn);
static CURLcode pop3_perform_auth(struct connectdata *conn, const char *mech,
const char *initresp);
static CURLcode pop3_continue_auth(struct connectdata *conn, const char *resp);
-static void pop3_get_message(char *buffer, char** outptr);
+static void pop3_get_message(char *buffer, char **outptr);
/*
* POP3 protocol handler.
@@ -292,10 +290,10 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
*
* Gets the authentication message from the response buffer.
*/
-static void pop3_get_message(char *buffer, char** outptr)
+static void pop3_get_message(char *buffer, char **outptr)
{
size_t len = 0;
- char* message = NULL;
+ char *message = NULL;
/* Find the start of the message */
for(message = buffer + 2; *message == ' ' || *message == '\t'; message++)
@@ -663,7 +661,7 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
if(pop3code != '+') {
failf(data, "Got unexpected pop3-server response");
- result = CURLE_FTP_WEIRD_SERVER_REPLY;
+ result = CURLE_WEIRD_SERVER_REPLY;
}
else {
/* Does the server support APOP authentication? */
@@ -1412,11 +1410,11 @@ static CURLcode pop3_parse_url_options(struct connectdata *conn)
while(*ptr && *ptr != ';')
ptr++;
- if(strnequal(key, "AUTH=", 5)) {
+ if(strncasecompare(key, "AUTH=", 5)) {
result = Curl_sasl_parse_url_auth_option(&pop3c->sasl,
value, ptr - value);
- if(result && strnequal(value, "+APOP", ptr - value)) {
+ if(result && strncasecompare(value, "+APOP", ptr - value)) {
pop3c->preftype = POP3_TYPE_APOP;
pop3c->sasl.prefmech = SASL_AUTH_NONE;
result = CURLE_OK;
@@ -1574,7 +1572,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
if(prev) {
/* If the partial match was the CRLF and dot then only write the CRLF
as the server would have inserted the dot */
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char*)POP3_EOB,
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB,
strip_dot ? prev - 1 : prev);
if(result)
diff --git a/lib/progress.c b/lib/progress.c
index 760ca1cc..60627b2a 100644
--- a/lib/progress.c
+++ b/lib/progress.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -216,18 +216,95 @@ void Curl_pgrsStartNow(struct Curl_easy *data)
{
data->progress.speeder_c = 0; /* reset the progress meter display */
data->progress.start = Curl_tvnow();
+ data->progress.ul_limit_start.tv_sec = 0;
+ data->progress.ul_limit_start.tv_usec = 0;
+ data->progress.dl_limit_start.tv_sec = 0;
+ data->progress.dl_limit_start.tv_usec = 0;
/* clear all bits except HIDE and HEADERS_OUT */
data->progress.flags &= PGRS_HIDE|PGRS_HEADERS_OUT;
}
+/*
+ * This is used to handle speed limits, calculating how much milliseconds we
+ * need to wait until we're back under the speed limit, if needed.
+ *
+ * The way it works is by having a "starting point" (time & amount of data
+ * transfered by then) used in the speed computation, to be used instead of the
+ * start of the transfer.
+ * This starting point is regularly moved as transfer goes on, to keep getting
+ * accurate values (instead of average over the entire tranfer).
+ *
+ * This function takes the current amount of data transfered, the amount at the
+ * starting point, the limit (in bytes/s), the time of the starting point and
+ * the current time.
+ *
+ * Returns -1 if no waiting is needed (not enough data transfered since
+ * starting point yet), 0 when no waiting is needed but the starting point
+ * should be reset (to current), or the number of milliseconds to wait to get
+ * back under the speed limit.
+ */
+long Curl_pgrsLimitWaitTime(curl_off_t cursize,
+ curl_off_t startsize,
+ curl_off_t limit,
+ struct timeval start,
+ struct timeval now)
+{
+ curl_off_t size = cursize - startsize;
+ time_t minimum;
+ time_t actual;
+
+ /* we don't have a starting point yet -- return 0 so it gets (re)set */
+ if(start.tv_sec == 0 && start.tv_usec == 0)
+ return 0;
+
+ /* not enough data yet */
+ if(size < limit)
+ return -1;
+
+ minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit);
+ actual = Curl_tvdiff(now, start);
+
+ if(actual < minimum)
+ /* this is a conversion on some systems (64bit time_t => 32bit long) */
+ return (long)(minimum - actual);
+ else
+ return 0;
+}
+
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
{
+ struct timeval now = Curl_tvnow();
+
data->progress.downloaded = size;
+
+ /* download speed limit */
+ if((data->set.max_recv_speed > 0) &&
+ (Curl_pgrsLimitWaitTime(data->progress.downloaded,
+ data->progress.dl_limit_size,
+ data->set.max_recv_speed,
+ data->progress.dl_limit_start,
+ now) == 0)) {
+ data->progress.dl_limit_start = now;
+ data->progress.dl_limit_size = size;
+ }
}
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size)
{
+ struct timeval now = Curl_tvnow();
+
data->progress.uploaded = size;
+
+ /* upload speed limit */
+ if((data->set.max_send_speed > 0) &&
+ (Curl_pgrsLimitWaitTime(data->progress.uploaded,
+ data->progress.ul_limit_size,
+ data->set.max_send_speed,
+ data->progress.ul_limit_start,
+ now) == 0)) {
+ data->progress.ul_limit_start = now;
+ data->progress.ul_limit_size = size;
+ }
}
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size)
@@ -284,9 +361,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
now = Curl_tvnow(); /* what time is it */
/* The time spent so far (from the start) */
- data->progress.timespent =
- (double)(now.tv_sec - data->progress.start.tv_sec) +
- (double)(now.tv_usec - data->progress.start.tv_usec)/1000000.0;
+ data->progress.timespent = curlx_tvdiff_secs(now, data->progress.start);
timespent = (curl_off_t)data->progress.timespent;
/* The average download speed this far */
@@ -300,7 +375,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
(data->progress.timespent>0?data->progress.timespent:1));
/* Calculations done at most once a second, unless end is reached */
- if(data->progress.lastshow != (long)now.tv_sec) {
+ if(data->progress.lastshow != now.tv_sec) {
shownow = TRUE;
data->progress.lastshow = now.tv_sec;
@@ -327,7 +402,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
/* first of all, we don't do this if there's no counted seconds yet */
if(countindex) {
- long span_ms;
+ time_t span_ms;
/* Get the index position to compare with the 'nowindex' position.
Get the oldest entry possible. While we have less than CURR_TIME
diff --git a/lib/progress.h b/lib/progress.h
index a77b7ce5..155ff04f 100644
--- a/lib/progress.h
+++ b/lib/progress.h
@@ -49,7 +49,11 @@ void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
int Curl_pgrsUpdate(struct connectdata *);
void Curl_pgrsResetTimesSizes(struct Curl_easy *data);
void Curl_pgrsTime(struct Curl_easy *data, timerid timer);
-
+long Curl_pgrsLimitWaitTime(curl_off_t cursize,
+ curl_off_t startsize,
+ curl_off_t limit,
+ struct timeval start,
+ struct timeval now);
/* Don't show progress for sizes smaller than: */
#define LEAST_SIZE_PROGRESS BUFSIZE
diff --git a/lib/rand.c b/lib/rand.c
new file mode 100644
index 00000000..0e716a77
--- /dev/null
+++ b/lib/rand.c
@@ -0,0 +1,130 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <fcntl.h>
+
+#include <curl/curl.h>
+#include "vtls/vtls.h"
+#include "sendf.h"
+#include "rand.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
+{
+ unsigned int r;
+ CURLcode result = CURLE_OK;
+ static unsigned int randseed;
+ static bool seeded = FALSE;
+
+#ifdef CURLDEBUG
+ char *force_entropy = getenv("CURL_ENTROPY");
+ if(force_entropy) {
+ if(!seeded) {
+ size_t elen = strlen(force_entropy);
+ size_t clen = sizeof(randseed);
+ size_t min = elen < clen ? elen : clen;
+ memcpy((char *)&randseed, force_entropy, min);
+ seeded = TRUE;
+ }
+ else
+ randseed++;
+ *rnd = randseed;
+ return CURLE_OK;
+ }
+#endif
+
+ /* data may be NULL! */
+ result = Curl_ssl_random(data, (unsigned char *)&rnd, sizeof(rnd));
+ if(result != CURLE_NOT_BUILT_IN)
+ /* only if there is no random funtion in the TLS backend do the non crypto
+ version, otherwise return result */
+ return result;
+
+ /* ---- non-cryptographic version following ---- */
+
+#ifdef RANDOM_FILE
+ if(!seeded) {
+ /* if there's a random file to read a seed from, use it */
+ int fd = open(RANDOM_FILE, O_RDONLY);
+ if(fd > -1) {
+ /* read random data into the randseed variable */
+ ssize_t nread = read(fd, &randseed, sizeof(randseed));
+ if(nread == sizeof(randseed))
+ seeded = TRUE;
+ close(fd);
+ }
+ }
+#endif
+
+ if(!seeded) {
+ struct timeval now = curlx_tvnow();
+ infof(data, "WARNING: Using weak random seed\n");
+ randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec;
+ randseed = randseed * 1103515245 + 12345;
+ randseed = randseed * 1103515245 + 12345;
+ randseed = randseed * 1103515245 + 12345;
+ seeded = TRUE;
+ }
+
+ /* Return an unsigned 32-bit pseudo-random number. */
+ r = randseed = randseed * 1103515245 + 12345;
+ *rnd = (r << 16) | ((r >> 16) & 0xFFFF);
+ return CURLE_OK;
+}
+
+/*
+ * Curl_rand() stores 'num' number of random unsigned integers in the buffer
+ * 'rndptr' points to.
+ *
+ * If libcurl is built without TLS support or with a TLS backend that lacks a
+ * proper random API (Gskit, PolarSSL or mbedTLS), this function will use
+ * "weak" random.
+ *
+ * When built *with* TLS support and a backend that offers strong random, it
+ * will return error if it cannot provide strong random values.
+ *
+ * NOTE: 'data' may be passed in as NULL when coming from external API without
+ * easy handle!
+ *
+ */
+
+CURLcode Curl_rand(struct Curl_easy *data, unsigned int *rndptr,
+ unsigned int num)
+{
+ CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
+ unsigned int i;
+
+ assert(num > 0);
+
+ for(i = 0; i < num; i++) {
+ result = randit(data, rndptr++);
+ if(result)
+ return result;
+ }
+ return result;
+}
diff --git a/lib/rand.h b/lib/rand.h
new file mode 100644
index 00000000..0f898612
--- /dev/null
+++ b/lib/rand.h
@@ -0,0 +1,43 @@
+#ifndef HEADER_CURL_RAND_H
+#define HEADER_CURL_RAND_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Curl_rand() stores 'num' number of random unsigned integers in the buffer
+ * 'rnd' points to.
+ *
+ * If libcurl is built without TLS support or with a TLS backend that lacks a
+ * proper random API (Gskit, PolarSSL or mbedTLS), this function will use
+ * "weak" random.
+ *
+ * When built *with* TLS support and a backend that offers strong random, it
+ * will return error if it cannot provide strong random values.
+ *
+ * NOTE: 'data' may be passed in as NULL when coming from external API without
+ * easy handle!
+ *
+ */
+CURLcode Curl_rand(struct Curl_easy *data, unsigned int *rnd,
+ unsigned int num);
+
+#endif /* HEADER_CURL_RAND_H */
diff --git a/lib/rtsp.c b/lib/rtsp.c
index 27955bc4..5da33d42 100644
--- a/lib/rtsp.c
+++ b/lib/rtsp.c
@@ -33,9 +33,10 @@
#include "url.h"
#include "progress.h"
#include "rtsp.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "select.h"
#include "connect.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -147,7 +148,7 @@ bool Curl_rtsp_connisdead(struct connectdata *check)
int sval;
bool ret_val = TRUE;
- sval = Curl_socket_ready(check->sock[FIRSTSOCKET], CURL_SOCKET_BAD, 0);
+ sval = SOCKET_READABLE(check->sock[FIRSTSOCKET], 0);
if(sval == 0) {
/* timeout */
ret_val = FALSE;
@@ -614,9 +615,9 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
if(rtspc->rtp_buf) {
/* There was some leftover data the last time. Merge buffers */
- char *newptr = realloc(rtspc->rtp_buf, rtspc->rtp_bufsize + *nread);
+ char *newptr = Curl_saferealloc(rtspc->rtp_buf,
+ rtspc->rtp_bufsize + *nread);
if(!newptr) {
- Curl_safefree(rtspc->rtp_buf);
rtspc->rtp_buf = NULL;
rtspc->rtp_bufsize = 0;
return CURLE_OUT_OF_MEMORY;
@@ -796,19 +797,15 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
}
}
else {
- /* If the Session ID is not set, and we find it in a response, then
- set it */
-
- /* The session ID can be an alphanumeric or a 'safe' character
+ /* If the Session ID is not set, and we find it in a response, then set
+ * it.
*
- * RFC 2326 15.1 Base Syntax:
- * safe = "\$" | "-" | "_" | "." | "+"
- * */
+ * Allow any non whitespace content, up to the field seperator or end of
+ * line. RFC 2326 isn't 100% clear on the session ID and for example
+ * gstreamer does url-encoded session ID's not covered by the standard.
+ */
char *end = start;
- while(*end &&
- (ISALNUM(*end) || *end == '-' || *end == '_' || *end == '.' ||
- *end == '+' ||
- (*end == '\\' && *(end + 1) && *(end + 1) == '$' && (++end, 1))))
+ while(*end && *end != ';' && !ISSPACE(*end))
end++;
/* Copy the id substring into a new buffer */
diff --git a/lib/security.c b/lib/security.c
index a0bcaeae..4a8f4443 100644
--- a/lib/security.c
+++ b/lib/security.c
@@ -60,9 +60,9 @@
#include "curl_sec.h"
#include "ftp.h"
#include "sendf.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "warnless.h"
-
+#include "strdup.h"
/* The last #include file should be: */
#include "memdebug.h"
@@ -88,7 +88,8 @@ name_to_level(const char *name)
/* Convert a protocol |level| to its char representation.
We take an int to catch programming mistakes. */
-static char level_to_char(int level) {
+static char level_to_char(int level)
+{
switch(level) {
case PROT_CLEAR:
return 'C';
@@ -122,7 +123,7 @@ static int ftp_send_command(struct connectdata *conn, const char *message, ...)
vsnprintf(print_buffer, sizeof(print_buffer), message, args);
va_end(args);
- if(Curl_ftpsendf(conn, print_buffer)) {
+ if(Curl_ftpsend(conn, print_buffer)) {
ftp_code = -1;
}
else {
@@ -192,15 +193,18 @@ static CURLcode read_data(struct connectdata *conn,
struct krb5buffer *buf)
{
int len;
- void* tmp;
+ void *tmp = NULL;
CURLcode result;
result = socket_read(fd, &len, sizeof(len));
if(result)
return result;
- len = ntohl(len);
- tmp = realloc(buf->data, len);
+ if(len) {
+ /* only realloc if there was a length */
+ len = ntohl(len);
+ tmp = Curl_saferealloc(buf->data, len);
+ }
if(tmp == NULL)
return CURLE_OUT_OF_MEMORY;
@@ -219,7 +223,7 @@ buffer_read(struct krb5buffer *buf, void *data, size_t len)
{
if(buf->size - buf->index < len)
len = buf->size - buf->index;
- memcpy(data, (char*)buf->data + buf->index, len);
+ memcpy(data, (char *)buf->data + buf->index, len);
buf->index += len;
return len;
}
@@ -288,7 +292,7 @@ static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
prot_level = conn->command_prot;
}
bytes = conn->mech->encode(conn->app_data, from, length, prot_level,
- (void**)&buffer);
+ (void **)&buffer);
if(!buffer || bytes <= 0)
return; /* error */
@@ -408,7 +412,7 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer,
static int sec_set_protection_level(struct connectdata *conn)
{
int code;
- char* pbsz;
+ char *pbsz;
static unsigned int buffer_size = 1 << 20; /* 1048576 */
enum protection_level level = conn->request_data_prot;
diff --git a/lib/select.c b/lib/select.c
index abf55d87..03af645e 100644
--- a/lib/select.c
+++ b/lib/select.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -51,15 +51,14 @@
#include "warnless.h"
/* Convenience local macros */
-
-#define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
+#define ELAPSED_MS() (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
int Curl_ack_eintr = 0;
-#define error_not_EINTR (Curl_ack_eintr || error != EINTR)
+#define ERROR_NOT_EINTR(error) (Curl_ack_eintr || error != EINTR)
/*
* Internal function used for waiting a specific amount of ms
- * in Curl_socket_ready() and Curl_poll() when no file descriptor
+ * in Curl_socket_check() and Curl_poll() when no file descriptor
* is provided to wait on, just being used to delay execution.
* WinSock select() and poll() timeout mechanisms need a valid
* socket descriptor in a not null file descriptor set to work.
@@ -109,9 +108,9 @@ int Curl_wait_ms(int timeout_ms)
if(r != -1)
break;
error = SOCKERRNO;
- if(error && error_not_EINTR)
+ if(error && ERROR_NOT_EINTR(error))
break;
- pending_ms = timeout_ms - elapsed_ms;
+ pending_ms = timeout_ms - ELAPSED_MS();
if(pending_ms <= 0) {
r = 0; /* Simulate a "call timed out" case */
break;
@@ -146,7 +145,7 @@ int Curl_wait_ms(int timeout_ms)
int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
curl_socket_t readfd1,
curl_socket_t writefd, /* socket to write to */
- long timeout_ms) /* milliseconds to wait */
+ time_t timeout_ms) /* milliseconds to wait */
{
#ifdef HAVE_POLL_FINE
struct pollfd pfd[3];
@@ -165,6 +164,12 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
int r;
int ret;
+#if SIZEOF_LONG != SIZEOF_INT
+ /* wrap-around precaution */
+ if(timeout_ms >= INT_MAX)
+ timeout_ms = INT_MAX;
+#endif
+
if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
(writefd == CURL_SOCKET_BAD)) {
/* no sockets, just wait */
@@ -213,10 +218,10 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
if(r != -1)
break;
error = SOCKERRNO;
- if(error && error_not_EINTR)
+ if(error && ERROR_NOT_EINTR(error))
break;
if(timeout_ms > 0) {
- pending_ms = (int)(timeout_ms - elapsed_ms);
+ pending_ms = (int)(timeout_ms - ELAPSED_MS());
if(pending_ms <= 0) {
r = 0; /* Simulate a "call timed out" case */
break;
@@ -328,10 +333,10 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
if(r != -1)
break;
error = SOCKERRNO;
- if(error && error_not_EINTR)
+ if(error && ERROR_NOT_EINTR(error))
break;
if(timeout_ms > 0) {
- pending_ms = timeout_ms - elapsed_ms;
+ pending_ms = (int)(timeout_ms - ELAPSED_MS());
if(pending_ms <= 0) {
r = 0; /* Simulate a "call timed out" case */
break;
@@ -434,10 +439,10 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
if(r != -1)
break;
error = SOCKERRNO;
- if(error && error_not_EINTR)
+ if(error && ERROR_NOT_EINTR(error))
break;
if(timeout_ms > 0) {
- pending_ms = timeout_ms - elapsed_ms;
+ pending_ms = (int)(timeout_ms - ELAPSED_MS());
if(pending_ms <= 0) {
r = 0; /* Simulate a "call timed out" case */
break;
@@ -521,10 +526,10 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
if(r != -1)
break;
error = SOCKERRNO;
- if(error && error_not_EINTR)
+ if(error && ERROR_NOT_EINTR(error))
break;
if(timeout_ms > 0) {
- pending_ms = timeout_ms - elapsed_ms;
+ pending_ms = timeout_ms - ELAPSED_MS();
if(pending_ms <= 0) {
r = 0; /* Simulate a "call timed out" case */
break;
diff --git a/lib/select.h b/lib/select.h
index 695bb69c..e247bd9d 100644
--- a/lib/select.h
+++ b/lib/select.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -73,11 +73,12 @@ struct pollfd
int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2,
curl_socket_t writefd,
- long timeout_ms);
+ time_t timeout_ms);
-/* provide the former API internally */
-#define Curl_socket_ready(x,y,z) \
- Curl_socket_check(x, CURL_SOCKET_BAD, y, z)
+#define SOCKET_READABLE(x,z) \
+ Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, z)
+#define SOCKET_WRITABLE(x,z) \
+ Curl_socket_check(CURL_SOCKET_BAD, CURL_SOCKET_BAD, x, z)
int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms);
diff --git a/lib/sendf.c b/lib/sendf.c
index 21017973..4f552e89 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -488,7 +488,7 @@ static CURLcode pausewrite(struct Curl_easy *data,
*/
CURLcode Curl_client_chop_write(struct connectdata *conn,
int type,
- char * ptr,
+ char *ptr,
size_t len)
{
struct Curl_easy *data = conn->data;
diff --git a/lib/setup-os400.h b/lib/setup-os400.h
index e32b72f2..a3c2a7bd 100644
--- a/lib/setup-os400.h
+++ b/lib/setup-os400.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -41,18 +41,18 @@ typedef unsigned long u_int32_t;
#include <qsoasync.h>
#include <gssapi.h>
-extern int Curl_getaddrinfo_a(const char * nodename,
- const char * servname,
- const struct addrinfo * hints,
- struct addrinfo * * res);
+extern int Curl_getaddrinfo_a(const char *nodename,
+ const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res);
#define getaddrinfo Curl_getaddrinfo_a
-extern int Curl_getnameinfo_a(const struct sockaddr * sa,
- curl_socklen_t salen,
- char * nodename, curl_socklen_t nodenamelen,
- char * servname, curl_socklen_t servnamelen,
- int flags);
+extern int Curl_getnameinfo_a(const struct sockaddr *sa,
+ curl_socklen_t salen,
+ char *nodename, curl_socklen_t nodenamelen,
+ char *servname, curl_socklen_t servnamelen,
+ int flags);
#define getnameinfo Curl_getnameinfo_a
@@ -79,7 +79,7 @@ extern int Curl_gsk_secure_soc_init(gsk_handle my_session_handle);
extern int Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle,
GSK_BUF_ID bufID,
- const char * buffer,
+ const char *buffer,
int bufSize);
#define gsk_attribute_set_buffer Curl_gsk_attribute_set_buffer_a
@@ -95,29 +95,29 @@ extern int Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,
extern int Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,
GSK_CALLBACK_ID callBackID,
- void * callBackAreaPtr);
+ void *callBackAreaPtr);
#define gsk_attribute_set_callback Curl_gsk_attribute_set_callback
extern int Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle,
GSK_BUF_ID bufID,
- const char * * buffer,
- int * bufSize);
+ const char **buffer,
+ int *bufSize);
#define gsk_attribute_get_buffer Curl_gsk_attribute_get_buffer_a
extern int Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle,
GSK_ENUM_ID enumID,
- GSK_ENUM_VALUE * enumValue);
+ GSK_ENUM_VALUE *enumValue);
#define gsk_attribute_get_enum Curl_gsk_attribute_get_enum
extern int Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,
GSK_NUM_ID numID,
- int * numValue);
+ int *numValue);
#define gsk_attribute_get_numeric_value Curl_gsk_attribute_get_numeric_value
extern int Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,
GSK_CERT_ID certID,
- const gsk_cert_data_elem * * certDataElem,
- int * certDataElementCount);
+ const gsk_cert_data_elem **certDataElem,
+ int *certDataElementCount);
#define gsk_attribute_get_cert_info Curl_gsk_attribute_get_cert_info
extern int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle,
@@ -125,13 +125,13 @@ extern int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle,
#define gsk_secure_soc_misc Curl_gsk_secure_soc_misc
extern int Curl_gsk_secure_soc_read(gsk_handle my_session_handle,
- char * readBuffer,
- int readBufSize, int * amtRead);
+ char *readBuffer,
+ int readBufSize, int *amtRead);
#define gsk_secure_soc_read Curl_gsk_secure_soc_read
extern int Curl_gsk_secure_soc_write(gsk_handle my_session_handle,
- char * writeBuffer,
- int writeBufSize, int * amtWritten);
+ char *writeBuffer,
+ int writeBufSize, int *amtWritten);
#define gsk_secure_soc_write Curl_gsk_secure_soc_write
extern const char * Curl_gsk_strerror_a(int gsk_return_value);
@@ -202,10 +202,10 @@ extern OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status,
extern int Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen);
extern int Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen);
-extern int Curl_os400_sendto(int sd, char * buffer, int buflen, int flags,
- struct sockaddr * dstaddr, int addrlen);
-extern int Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
- struct sockaddr * fromaddr, int * addrlen);
+extern int Curl_os400_sendto(int sd, char *buffer, int buflen, int flags,
+ struct sockaddr * dstaddr, int addrlen);
+extern int Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags,
+ struct sockaddr *fromaddr, int *addrlen);
#define connect Curl_os400_connect
#define bind Curl_os400_bind
diff --git a/lib/setup-vms.h b/lib/setup-vms.h
index 4b78e0bf..6c454aee 100644
--- a/lib/setup-vms.h
+++ b/lib/setup-vms.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -41,7 +41,7 @@
# endif
#endif
#include <stdlib.h>
- char * decc$getenv(const char * __name);
+char *decc$getenv(const char *__name);
#include <pwd.h>
#include <string.h>
@@ -79,23 +79,24 @@
# if __INITIAL_POINTER_SIZE == 32
/* Translate the path, but only if the path is a VMS file specification */
/* The translation is usually only needed for older versions of VMS */
-static char * vms_translate_path(const char * path) {
-char * unix_path;
-char * test_str;
-
- /* See if the result is in VMS format, if not, we are done */
- /* Assume that this is a PATH, not just some data */
- test_str = strpbrk(path, ":[<^");
- if(test_str == NULL) {
- return (char *)path;
- }
-
- unix_path = decc$translate_vms(path);
-
- if((int)unix_path <= 0) {
- /* We can not translate it, so return the original string */
- return (char *)path;
- }
+static char *vms_translate_path(const char *path)
+{
+ char *unix_path;
+ char *test_str;
+
+ /* See if the result is in VMS format, if not, we are done */
+ /* Assume that this is a PATH, not just some data */
+ test_str = strpbrk(path, ":[<^");
+ if(test_str == NULL) {
+ return (char *)path;
+ }
+
+ unix_path = decc$translate_vms(path);
+
+ if((int)unix_path <= 0) {
+ /* We can not translate it, so return the original string */
+ return (char *)path;
+ }
}
# else
/* VMS translate path is actually not needed on the current 64 bit */
@@ -111,74 +112,74 @@ char * test_str;
# endif
#endif
-static char * vms_getenv(const char * envvar) {
+static char *vms_getenv(const char *envvar)
+{
+ char *result;
+ char *vms_path;
-char * result;
-char * vms_path;
-
- /* first use the DECC getenv() function */
- result = decc$getenv(envvar);
- if(result == NULL) {
- return result;
- }
+ /* first use the DECC getenv() function */
+ result = decc$getenv(envvar);
+ if(result == NULL) {
+ return result;
+ }
- vms_path = result;
- result = vms_translate_path(vms_path);
+ vms_path = result;
+ result = vms_translate_path(vms_path);
- /* note that if you backport this to use VAX C RTL, that the VAX C RTL */
- /* may do a malloc(2048) for each call to getenv(), so you will need */
- /* to add a free(vms_path) */
- /* Do not do a free() for DEC C RTL builds, which should be used for */
- /* VMS 5.5-2 and later, even if using GCC */
+ /* note that if you backport this to use VAX C RTL, that the VAX C RTL */
+ /* may do a malloc(2048) for each call to getenv(), so you will need */
+ /* to add a free(vms_path) */
+ /* Do not do a free() for DEC C RTL builds, which should be used for */
+ /* VMS 5.5-2 and later, even if using GCC */
- return result;
+ return result;
}
static struct passwd vms_passwd_cache;
-static struct passwd * vms_getpwuid(uid_t uid) {
-
-struct passwd * my_passwd;
+static struct passwd * vms_getpwuid(uid_t uid)
+{
+ struct passwd * my_passwd;
/* Hack needed to support 64 bit builds, decc_getpwnam is 32 bit only */
#ifdef __DECC
# if __INITIAL_POINTER_SIZE
-__char_ptr32 unix_path;
+ __char_ptr32 unix_path;
# else
-char * unix_path;
+ char *unix_path;
# endif
#else
-char * unix_path;
+ char *unix_path;
#endif
- my_passwd = decc_getpwuid(uid);
- if(my_passwd == NULL) {
- return my_passwd;
- }
-
- unix_path = vms_translate_path(my_passwd->pw_dir);
-
- if((long)unix_path <= 0) {
- /* We can not translate it, so return the original string */
- return my_passwd;
- }
-
- /* If no changes needed just return it */
- if(unix_path == my_passwd->pw_dir) {
- return my_passwd;
- }
-
- /* Need to copy the structure returned */
- /* Since curl is only using pw_dir, no need to fix up *
- /* the pw_shell when running under Bash */
- vms_passwd_cache.pw_name = my_passwd->pw_name;
- vms_passwd_cache.pw_uid = my_passwd->pw_uid;
- vms_passwd_cache.pw_gid = my_passwd->pw_uid;
- vms_passwd_cache.pw_dir = unix_path;
- vms_passwd_cache.pw_shell = my_passwd->pw_shell;
-
- return &vms_passwd_cache;
+ my_passwd = decc_getpwuid(uid);
+ if(my_passwd == NULL) {
+ return my_passwd;
+ }
+
+ unix_path = vms_translate_path(my_passwd->pw_dir);
+
+ if((long)unix_path <= 0) {
+ /* We can not translate it, so return the original string */
+ return my_passwd;
+ }
+
+ /* If no changes needed just return it */
+ if(unix_path == my_passwd->pw_dir) {
+ return my_passwd;
+ }
+
+ /* Need to copy the structure returned */
+ /* Since curl is only using pw_dir, no need to fix up */
+ /* the pw_shell when running under Bash */
+ vms_passwd_cache.pw_name = my_passwd->pw_name;
+ vms_passwd_cache.pw_uid = my_passwd->pw_uid;
+ vms_passwd_cache.pw_gid = my_passwd->pw_uid;
+ vms_passwd_cache.pw_dir = unix_path;
+ vms_passwd_cache.pw_shell = my_passwd->pw_shell;
+
+ return &vms_passwd_cache;
}
#ifdef __DECC
diff --git a/lib/smb.c b/lib/smb.c
index 56a38c2f..f197fe1c 100644
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
- * Copyright (C) 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -308,8 +308,8 @@ static CURLcode smb_recv_message(struct connectdata *conn, void **msg)
if(smbc->got < sizeof(unsigned int))
return CURLE_OK;
- nbt_size = Curl_read16_be((unsigned char *)(buf + sizeof(unsigned short))) +
- sizeof(unsigned int);
+ nbt_size = Curl_read16_be((const unsigned char *)(buf +
+ sizeof(unsigned short))) + sizeof(unsigned int);
if(smbc->got < nbt_size)
return CURLE_OK;
@@ -320,7 +320,7 @@ static CURLcode smb_recv_message(struct connectdata *conn, void **msg)
if(nbt_size >= msg_size + sizeof(unsigned short)) {
/* Add the byte count */
msg_size += sizeof(unsigned short) +
- Curl_read16_le((unsigned char *)&buf[msg_size]);
+ Curl_read16_le((const unsigned char *)&buf[msg_size]);
if(nbt_size < msg_size)
return CURLE_READ_ERROR;
}
@@ -673,7 +673,7 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
switch(smbc->state) {
case SMB_NEGOTIATE:
- if(h->status) {
+ if(h->status || smbc->got < sizeof(*nrsp) + sizeof(smbc->challenge) - 1) {
connclose(conn, "SMB: negotiation failed");
return CURLE_COULDNT_CONNECT;
}
@@ -712,6 +712,7 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
{
struct smb_request *req = conn->data->req.protop;
struct smb_header *h;
+ struct smb_conn *smbc = &conn->proto.smbc;
enum smb_req_state next_state = SMB_DONE;
unsigned short len;
unsigned short off;
@@ -754,7 +755,7 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
break;
case SMB_OPEN:
- if(h->status) {
+ if(h->status || smbc->got < sizeof(struct smb_nt_create_response)) {
req->result = CURLE_REMOTE_FILE_NOT_FOUND;
next_state = SMB_TREE_DISCONNECT;
break;
@@ -775,17 +776,16 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
break;
case SMB_DOWNLOAD:
- if(h->status) {
+ if(h->status || smbc->got < sizeof(struct smb_header) + 14) {
req->result = CURLE_RECV_ERROR;
next_state = SMB_CLOSE;
break;
}
- len = Curl_read16_le(((unsigned char *) msg) +
+ len = Curl_read16_le(((const unsigned char *) msg) +
sizeof(struct smb_header) + 11);
- off = Curl_read16_le(((unsigned char *) msg) +
+ off = Curl_read16_le(((const unsigned char *) msg) +
sizeof(struct smb_header) + 13);
if(len > 0) {
- struct smb_conn *smbc = &conn->proto.smbc;
if(off + sizeof(unsigned int) + len > smbc->got) {
failf(conn->data, "Invalid input packet");
result = CURLE_RECV_ERROR;
@@ -807,12 +807,12 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
break;
case SMB_UPLOAD:
- if(h->status) {
+ if(h->status || smbc->got < sizeof(struct smb_header) + 6) {
req->result = CURLE_UPLOAD_FAILED;
next_state = SMB_CLOSE;
break;
}
- len = Curl_read16_le(((unsigned char *) msg) +
+ len = Curl_read16_le(((const unsigned char *) msg) +
sizeof(struct smb_header) + 5);
conn->data->req.bytecount += len;
conn->data->req.offset += len;
diff --git a/lib/smtp.c b/lib/smtp.c
index d203b532..ff8e80d6 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -69,16 +69,14 @@
#include "http.h" /* for HTTP proxy tunnel stuff */
#include "socks.h"
#include "smtp.h"
-
#include "strtoofft.h"
-#include "strequal.h"
+#include "strcase.h"
#include "vtls/vtls.h"
#include "connect.h"
#include "strerror.h"
#include "select.h"
#include "multiif.h"
#include "url.h"
-#include "rawstr.h"
#include "curl_gethostname.h"
#include "curl_sasl.h"
#include "warnless.h"
@@ -105,7 +103,7 @@ static CURLcode smtp_parse_custom_request(struct connectdata *conn);
static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech,
const char *initresp);
static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp);
-static void smtp_get_message(char *buffer, char** outptr);
+static void smtp_get_message(char *buffer, char **outptr);
/*
* SMTP protocol handler.
@@ -280,10 +278,10 @@ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
*
* Gets the authentication message from the response buffer.
*/
-static void smtp_get_message(char *buffer, char** outptr)
+static void smtp_get_message(char *buffer, char **outptr)
{
size_t len = 0;
- char* message = NULL;
+ char *message = NULL;
/* Find the start of the message */
for(message = buffer + 4; *message == ' ' || *message == '\t'; message++)
@@ -674,7 +672,7 @@ static CURLcode smtp_state_servergreet_resp(struct connectdata *conn,
if(smtpcode/100 != 2) {
failf(data, "Got unexpected smtp-server response: %d", smtpcode);
- result = CURLE_FTP_WEIRD_SERVER_REPLY;
+ result = CURLE_WEIRD_SERVER_REPLY;
}
else
result = smtp_perform_ehlo(conn);
@@ -1512,7 +1510,7 @@ static CURLcode smtp_parse_url_options(struct connectdata *conn)
while(*ptr && *ptr != ';')
ptr++;
- if(strnequal(key, "AUTH=", 5))
+ if(strncasecompare(key, "AUTH=", 5))
result = Curl_sasl_parse_url_auth_option(&smtpc->sasl,
value, ptr - value);
else
diff --git a/lib/socks.c b/lib/socks.c
index fccb16d4..774fb20b 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -33,7 +33,6 @@
#include "urldata.h"
#include "sendf.h"
-#include "strequal.h"
#include "select.h"
#include "connect.h"
#include "timeval.h"
@@ -58,7 +57,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
ssize_t nread;
ssize_t allread = 0;
int result;
- long timeleft;
+ time_t timeleft;
*n = 0;
for(;;) {
timeleft = Curl_timeleft(conn->data, NULL, TRUE);
@@ -67,7 +66,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
result = CURLE_OPERATION_TIMEDOUT;
break;
}
- if(Curl_socket_ready(sockfd, CURL_SOCKET_BAD, timeleft) <= 0) {
+ if(SOCKET_READABLE(sockfd, timeleft) <= 0) {
result = ~CURLE_OK;
break;
}
@@ -110,9 +109,10 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
const char *hostname,
int remote_port,
int sockindex,
- struct connectdata *conn,
- bool protocol4a)
+ struct connectdata *conn)
{
+ const bool protocol4a =
+ (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
#define SOCKS4REQLEN 262
unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user
id */
@@ -127,6 +127,10 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
return CURLE_OPERATION_TIMEDOUT;
}
+ if(conn->bits.httpproxy)
+ infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n",
+ protocol4a ? "a" : "", hostname, remote_port);
+
(void)curlx_nonblock(sock, FALSE);
infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
@@ -170,24 +174,26 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
hp=dns->addr;
if(hp) {
char buf[64];
- unsigned short ip[4];
Curl_printable_address(hp, buf, sizeof(buf));
- if(4 == sscanf(buf, "%hu.%hu.%hu.%hu",
- &ip[0], &ip[1], &ip[2], &ip[3])) {
- /* Set DSTIP */
- socksreq[4] = (unsigned char)ip[0];
- socksreq[5] = (unsigned char)ip[1];
- socksreq[6] = (unsigned char)ip[2];
- socksreq[7] = (unsigned char)ip[3];
+ if(hp->ai_family == AF_INET) {
+ struct sockaddr_in *saddr_in;
+
+ saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr;
+ socksreq[4] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[0];
+ socksreq[5] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[1];
+ socksreq[6] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[2];
+ socksreq[7] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[3];
+
+ infof(data, "SOCKS4 connect to IPv4 %s (locally resolved)\n", buf);
}
- else
+ else {
hp = NULL; /* fail! */
- infof(data, "SOCKS4 connect to %s (locally resolved)\n", buf);
+ failf(data, "SOCKS4 connection to %s not supported\n", buf);
+ }
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
-
}
if(!hp) {
failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.",
@@ -218,7 +224,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
ssize_t written;
ssize_t hostnamelen = 0;
int packetsize = 9 +
- (int)strlen((char*)socksreq + 8); /* size including NUL */
+ (int)strlen((char *)socksreq + 8); /* size including NUL */
/* If SOCKS4a, set special invalid IP address 0.0.0.x */
if(protocol4a) {
@@ -229,7 +235,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
/* If still enough room in buffer, also append hostname */
hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */
if(packetsize + hostnamelen <= SOCKS4REQLEN)
- strcpy((char*)socksreq + packetsize, hostname);
+ strcpy((char *)socksreq + packetsize, hostname);
else
hostnamelen = 0; /* Flag: hostname did not fit in buffer */
}
@@ -375,11 +381,16 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
CURLcode code;
curl_socket_t sock = conn->sock[sockindex];
struct Curl_easy *data = conn->data;
- long timeout;
- bool socks5_resolve_local = (conn->proxytype == CURLPROXY_SOCKS5)?TRUE:FALSE;
+ time_t timeout;
+ bool socks5_resolve_local =
+ (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
const size_t hostname_len = strlen(hostname);
ssize_t len = 0;
+ if(conn->bits.httpproxy)
+ infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
+ hostname, remote_port);
+
/* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
if(!socks5_resolve_local && hostname_len > 255) {
infof(conn->data, "SOCKS5: server resolving disabled for hostnames of "
@@ -399,7 +410,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
(void)curlx_nonblock(sock, TRUE);
/* wait until socket gets connected */
- result = Curl_socket_ready(CURL_SOCKET_BAD, sock, timeout);
+ result = SOCKET_WRITABLE(sock, timeout);
if(-1 == result) {
failf(conn->data, "SOCKS5: no connection here");
@@ -429,6 +440,8 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
(void)curlx_nonblock(sock, FALSE);
+ infof(data, "SOCKS5 communication to %s:%d\n", hostname, remote_port);
+
code = Curl_write_plain(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]),
&written);
if(code || (written != (2 + (int)socksreq[1]))) {
@@ -438,7 +451,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
(void)curlx_nonblock(sock, TRUE);
- result = Curl_socket_ready(sock, CURL_SOCKET_BAD, timeout);
+ result = SOCKET_READABLE(sock, timeout);
if(-1 == result) {
failf(conn->data, "SOCKS5 nothing to read");
@@ -594,34 +607,41 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
if(dns)
hp=dns->addr;
if(hp) {
- struct sockaddr_in *saddr_in;
-#ifdef ENABLE_IPV6
- struct sockaddr_in6 *saddr_in6;
-#endif
int i;
+ char buf[64];
+ Curl_printable_address(hp, buf, sizeof(buf));
if(hp->ai_family == AF_INET) {
+ struct sockaddr_in *saddr_in;
socksreq[len++] = 1; /* ATYP: IPv4 = 1 */
- saddr_in = (struct sockaddr_in*)(void*)hp->ai_addr;
+ saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr;
for(i = 0; i < 4; i++) {
- socksreq[len++] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[i];
- infof(data, "%d\n", socksreq[len-1]);
+ socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i];
}
+
+ infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", buf);
}
#ifdef ENABLE_IPV6
else if(hp->ai_family == AF_INET6) {
+ struct sockaddr_in6 *saddr_in6;
socksreq[len++] = 4; /* ATYP: IPv6 = 4 */
- saddr_in6 = (struct sockaddr_in6*)(void*)hp->ai_addr;
+ saddr_in6 = (struct sockaddr_in6 *)(void *)hp->ai_addr;
for(i = 0; i < 16; i++) {
- socksreq[len++] = ((unsigned char*)&saddr_in6->sin6_addr.s6_addr)[i];
+ socksreq[len++] =
+ ((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i];
}
+
+ infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", buf);
}
#endif
- else
+ else {
hp = NULL; /* fail! */
+ failf(data, "SOCKS5 connection to %s not supported\n", buf);
+ }
+
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
}
if(!hp) {
@@ -668,39 +688,6 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
"SOCKS5 reply has wrong version, version should be 5.");
return CURLE_COULDNT_CONNECT;
}
- if(socksreq[1] != 0) { /* Anything besides 0 is an error */
- if(socksreq[3] == 1) {
- failf(data,
- "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)",
- (unsigned char)socksreq[4], (unsigned char)socksreq[5],
- (unsigned char)socksreq[6], (unsigned char)socksreq[7],
- (((unsigned char)socksreq[8] << 8) | (unsigned char)socksreq[9]),
- (unsigned char)socksreq[1]);
- }
- else if(socksreq[3] == 3) {
- failf(data,
- "Can't complete SOCKS5 connection to %s:%d. (%d)",
- hostname,
- (((unsigned char)socksreq[8] << 8) | (unsigned char)socksreq[9]),
- (unsigned char)socksreq[1]);
- }
- else if(socksreq[3] == 4) {
- failf(data,
- "Can't complete SOCKS5 connection to %02x%02x:%02x%02x:"
- "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d. (%d)",
- (unsigned char)socksreq[4], (unsigned char)socksreq[5],
- (unsigned char)socksreq[6], (unsigned char)socksreq[7],
- (unsigned char)socksreq[8], (unsigned char)socksreq[9],
- (unsigned char)socksreq[10], (unsigned char)socksreq[11],
- (unsigned char)socksreq[12], (unsigned char)socksreq[13],
- (unsigned char)socksreq[14], (unsigned char)socksreq[15],
- (unsigned char)socksreq[16], (unsigned char)socksreq[17],
- (unsigned char)socksreq[18], (unsigned char)socksreq[19],
- (((unsigned char)socksreq[8] << 8) | (unsigned char)socksreq[9]),
- (unsigned char)socksreq[1]);
- }
- return CURLE_COULDNT_CONNECT;
- }
/* Fix: in general, returned BND.ADDR is variable length parameter by RFC
1928, so the reply packet should be read until the end to avoid errors at
@@ -735,10 +722,9 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
/* decrypt_gssapi_blockread already read the whole packet */
#endif
if(len > 10) {
- len -= 10;
result = Curl_blockread_all(conn, sock, (char *)&socksreq[10],
- len, &actualread);
- if(result || (len != actualread)) {
+ len - 10, &actualread);
+ if(result || ((len - 10) != actualread)) {
failf(data, "Failed to receive SOCKS5 connect request ack.");
return CURLE_COULDNT_CONNECT;
}
@@ -747,6 +733,49 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
}
#endif
+ if(socksreq[1] != 0) { /* Anything besides 0 is an error */
+ if(socksreq[3] == 1) {
+ failf(data,
+ "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ (((unsigned char)socksreq[8] << 8) |
+ (unsigned char)socksreq[9]),
+ (unsigned char)socksreq[1]);
+ }
+ else if(socksreq[3] == 3) {
+ unsigned char port_upper = (unsigned char)socksreq[len - 2];
+ socksreq[len - 2] = 0;
+ failf(data,
+ "Can't complete SOCKS5 connection to %s:%d. (%d)",
+ (char *)&socksreq[5],
+ ((port_upper << 8) |
+ (unsigned char)socksreq[len - 1]),
+ (unsigned char)socksreq[1]);
+ socksreq[len - 2] = port_upper;
+ }
+ else if(socksreq[3] == 4) {
+ failf(data,
+ "Can't complete SOCKS5 connection to %02x%02x:%02x%02x:"
+ "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d. (%d)",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ (unsigned char)socksreq[8], (unsigned char)socksreq[9],
+ (unsigned char)socksreq[10], (unsigned char)socksreq[11],
+ (unsigned char)socksreq[12], (unsigned char)socksreq[13],
+ (unsigned char)socksreq[14], (unsigned char)socksreq[15],
+ (unsigned char)socksreq[16], (unsigned char)socksreq[17],
+ (unsigned char)socksreq[18], (unsigned char)socksreq[19],
+ (((unsigned char)socksreq[20] << 8) |
+ (unsigned char)socksreq[21]),
+ (unsigned char)socksreq[1]);
+ }
+ return CURLE_COULDNT_CONNECT;
+ }
+ else {
+ infof(data, "SOCKS5 request granted.\n");
+ }
+
(void)curlx_nonblock(sock, TRUE);
return CURLE_OK; /* Proxy was successful! */
}
diff --git a/lib/socks.h b/lib/socks.h
index a44ada6b..348707e7 100644
--- a/lib/socks.h
+++ b/lib/socks.h
@@ -25,7 +25,7 @@
#include "curl_setup.h"
#ifdef CURL_DISABLE_PROXY
-#define Curl_SOCKS4(a,b,c,d,e,f) CURLE_NOT_BUILT_IN
+#define Curl_SOCKS4(a,b,c,d,e) CURLE_NOT_BUILT_IN
#define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN
#else
/*
@@ -49,8 +49,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
const char *hostname,
int remote_port,
int sockindex,
- struct connectdata *conn,
- bool protocol4a);
+ struct connectdata *conn);
/*
* This function logs in to a SOCKS5 proxy and sends the specifics to the
diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c
index 369245a6..32d6725c 100644
--- a/lib/socks_gssapi.c
+++ b/lib/socks_gssapi.c
@@ -46,7 +46,7 @@ static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
static int check_gss_err(struct Curl_easy *data,
OM_uint32 major_status,
OM_uint32 minor_status,
- const char* function)
+ const char *function)
{
if(GSS_ERROR(major_status)) {
OM_uint32 maj_stat, min_stat;
@@ -65,7 +65,7 @@ static int check_gss_err(struct Curl_easy *data,
&msg_ctx, &status_string);
if(maj_stat == GSS_S_COMPLETE) {
if(sizeof(buf) > len + status_string.length + 1) {
- strcpy(buf+len, (char*) status_string.value);
+ strcpy(buf+len, (char *) status_string.value);
len += status_string.length;
}
gss_release_buffer(&min_stat, &status_string);
@@ -86,7 +86,7 @@ static int check_gss_err(struct Curl_easy *data,
&msg_ctx, &status_string);
if(maj_stat == GSS_S_COMPLETE) {
if(sizeof(buf) > len + status_string.length)
- strcpy(buf+len, (char*) status_string.value);
+ strcpy(buf+len, (char *) status_string.value);
gss_release_buffer(&min_stat, &status_string);
break;
}
@@ -123,6 +123,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
unsigned char socksreq[4]; /* room for GSS-API exchange header only */
const char *serviceptr = data->set.str[STRING_PROXY_SERVICE_NAME] ?
data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
+ const size_t serviceptr_length = strlen(serviceptr);
/* GSS-API request looks like
* +----+------+-----+----------------+
@@ -134,22 +135,23 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
/* prepare service name */
if(strchr(serviceptr, '/')) {
- service.value = malloc(strlen(serviceptr));
+ service.length = serviceptr_length;
+ service.value = malloc(service.length);
if(!service.value)
return CURLE_OUT_OF_MEMORY;
- service.length = strlen(serviceptr);
memcpy(service.value, serviceptr, service.length);
gss_major_status = gss_import_name(&gss_minor_status, &service,
(gss_OID) GSS_C_NULL_OID, &server);
}
else {
- service.value = malloc(strlen(serviceptr) +strlen(conn->proxy.name)+2);
+ service.value = malloc(serviceptr_length +
+ strlen(conn->socks_proxy.host.name)+2);
if(!service.value)
return CURLE_OUT_OF_MEMORY;
- service.length = strlen(serviceptr) +strlen(conn->proxy.name)+1;
+ service.length = serviceptr_length + strlen(conn->socks_proxy.host.name)+1;
snprintf(service.value, service.length+1, "%s@%s",
- serviceptr, conn->proxy.name);
+ serviceptr, conn->socks_proxy.host.name);
gss_major_status = gss_import_name(&gss_minor_status, &service,
GSS_C_NT_HOSTBASED_SERVICE, &server);
diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c
index 60534903..edc73ad2 100644
--- a/lib/socks_sspi.c
+++ b/lib/socks_sspi.c
@@ -45,7 +45,7 @@
*/
static int check_sspi_err(struct connectdata *conn,
SECURITY_STATUS status,
- const char* function)
+ const char *function)
{
if(status != SEC_E_OK &&
status != SEC_I_COMPLETE_AND_CONTINUE &&
@@ -86,6 +86,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
unsigned char socksreq[4]; /* room for GSS-API exchange header only */
const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
+ const size_t service_length = strlen(service);
/* GSS-API request looks like
* +----+------+-----+----------------+
@@ -102,11 +103,13 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_OUT_OF_MEMORY;
}
else {
- service_name = malloc(strlen(service) + strlen(conn->proxy.name) + 2);
+ service_name = malloc(service_length +
+ strlen(conn->socks_proxy.host.name) + 2);
if(!service_name)
return CURLE_OUT_OF_MEMORY;
- snprintf(service_name, strlen(service) +strlen(conn->proxy.name)+2,
- "%s/%s", service, conn->proxy.name);
+ snprintf(service_name, service_length +
+ strlen(conn->socks_proxy.host.name)+2, "%s/%s",
+ service, conn->socks_proxy.host.name);
}
input_desc.cBuffers = 1;
diff --git a/lib/speedcheck.c b/lib/speedcheck.c
index 13c34af9..bc15d97b 100644
--- a/lib/speedcheck.c
+++ b/lib/speedcheck.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -40,8 +40,8 @@ CURLcode Curl_speedcheck(struct Curl_easy *data,
data->set.low_speed_time &&
(Curl_tvlong(data->state.keeps_speed) != 0) &&
(data->progress.current_speed < data->set.low_speed_limit)) {
- long howlong = Curl_tvdiff(now, data->state.keeps_speed);
- long nextcheck = (data->set.low_speed_time * 1000) - howlong;
+ time_t howlong = Curl_tvdiff(now, data->state.keeps_speed);
+ time_t nextcheck = (data->set.low_speed_time * 1000) - howlong;
/* We are now below the "low speed limit". If we are below it
for "low speed time" seconds we consider that enough reason
diff --git a/lib/ssh.c b/lib/ssh.c
index 7bc31362..04ca39ce 100644
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -71,8 +71,8 @@
#include "url.h"
#include "speedcheck.h"
#include "getinfo.h"
-
-#include "strequal.h"
+#include "strdup.h"
+#include "strcase.h"
#include "vtls/vtls.h"
#include "connect.h"
#include "strerror.h"
@@ -416,12 +416,12 @@ static CURLcode ssh_getworkingpath(struct connectdata *conn,
struct Curl_easy *data = conn->data;
char *real_path = NULL;
char *working_path;
- int working_path_len;
-
- working_path = curl_easy_unescape(data, data->state.path, 0,
- &working_path_len);
- if(!working_path)
- return CURLE_OUT_OF_MEMORY;
+ size_t working_path_len;
+ CURLcode result =
+ Curl_urldecode(data, data->state.path, 0, &working_path,
+ &working_path_len, FALSE);
+ if(result)
+ return result;
/* Check for /~/, indicating relative to the user's home directory */
if(conn->handler->protocol & CURLPROTO_SCP) {
@@ -676,7 +676,7 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn)
* against a known fingerprint, if available.
*/
if(pubkey_md5 && strlen(pubkey_md5) == 32) {
- if(!fingerprint || !strequal(md5buffer, pubkey_md5)) {
+ if(!fingerprint || !strcasecompare(md5buffer, pubkey_md5)) {
if(fingerprint)
failf(data,
"Denied establishing ssh session: mismatch md5 fingerprint. "
@@ -874,7 +874,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
- sshc->passphrase = data->set.str[STRING_KEY_PASSWD];
+ sshc->passphrase = data->set.ssl.key_passwd;
if(!sshc->passphrase)
sshc->passphrase = "";
@@ -1233,7 +1233,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->acceptfail = TRUE;
}
- if(curl_strequal("pwd", cmd)) {
+ if(strcasecompare("pwd", cmd)) {
/* output debug output if that is requested */
char *tmp = aprintf("257 \"%s\" is current directory.\n",
sftp_scp->path);
@@ -1297,9 +1297,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* OpenSSH's sftp program and call the appropriate libssh2
* functions.
*/
- if(curl_strnequal(cmd, "chgrp ", 6) ||
- curl_strnequal(cmd, "chmod ", 6) ||
- curl_strnequal(cmd, "chown ", 6) ) {
+ if(strncasecompare(cmd, "chgrp ", 6) ||
+ strncasecompare(cmd, "chmod ", 6) ||
+ strncasecompare(cmd, "chown ", 6) ) {
/* attribute change */
/* sshc->quote_path1 contains the mode to set */
@@ -1321,8 +1321,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_SFTP_QUOTE_STAT);
break;
}
- else if(curl_strnequal(cmd, "ln ", 3) ||
- curl_strnequal(cmd, "symlink ", 8)) {
+ else if(strncasecompare(cmd, "ln ", 3) ||
+ strncasecompare(cmd, "symlink ", 8)) {
/* symbolic linking */
/* sshc->quote_path1 is the source */
/* get the destination */
@@ -1342,12 +1342,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_SFTP_QUOTE_SYMLINK);
break;
}
- else if(curl_strnequal(cmd, "mkdir ", 6)) {
+ else if(strncasecompare(cmd, "mkdir ", 6)) {
/* create dir */
state(conn, SSH_SFTP_QUOTE_MKDIR);
break;
}
- else if(curl_strnequal(cmd, "rename ", 7)) {
+ else if(strncasecompare(cmd, "rename ", 7)) {
/* rename file */
/* first param is the source path */
/* second param is the dest. path */
@@ -1366,17 +1366,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_SFTP_QUOTE_RENAME);
break;
}
- else if(curl_strnequal(cmd, "rmdir ", 6)) {
+ else if(strncasecompare(cmd, "rmdir ", 6)) {
/* delete dir */
state(conn, SSH_SFTP_QUOTE_RMDIR);
break;
}
- else if(curl_strnequal(cmd, "rm ", 3)) {
+ else if(strncasecompare(cmd, "rm ", 3)) {
state(conn, SSH_SFTP_QUOTE_UNLINK);
break;
}
#ifdef HAS_STATVFS_SUPPORT
- else if(curl_strnequal(cmd, "statvfs ", 8)) {
+ else if(strncasecompare(cmd, "statvfs ", 8)) {
state(conn, SSH_SFTP_QUOTE_STATVFS);
break;
}
@@ -1431,7 +1431,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->acceptfail = TRUE;
}
- if(!curl_strnequal(cmd, "chmod", 5)) {
+ if(!strncasecompare(cmd, "chmod", 5)) {
/* Since chown and chgrp only set owner OR group but libssh2 wants to
* set them both at once, we need to obtain the current ownership
* first. This takes an extra protocol round trip.
@@ -1457,7 +1457,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
/* Now set the new attributes... */
- if(curl_strnequal(cmd, "chgrp", 5)) {
+ if(strncasecompare(cmd, "chgrp", 5)) {
sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
@@ -1471,7 +1471,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
}
- else if(curl_strnequal(cmd, "chmod", 5)) {
+ else if(strncasecompare(cmd, "chmod", 5)) {
sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
/* permissions are octal */
@@ -1486,7 +1486,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
}
- else if(curl_strnequal(cmd, "chown", 5)) {
+ else if(strncasecompare(cmd, "chown", 5)) {
sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
@@ -1895,7 +1895,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* since we don't really wait for anything at this point, we want the
state machine to move on as soon as possible so we set a very short
timeout here */
- Curl_expire(data, 1);
+ Curl_expire(data, 0);
state(conn, SSH_STOP);
}
@@ -2112,9 +2112,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* get room for the filename and extra output */
sshc->readdir_totalLen += 4 + sshc->readdir_len;
- new_readdir_line = realloc(sshc->readdir_line, sshc->readdir_totalLen);
+ new_readdir_line = Curl_saferealloc(sshc->readdir_line,
+ sshc->readdir_totalLen);
if(!new_readdir_line) {
- Curl_safefree(sshc->readdir_line);
+ sshc->readdir_line = NULL;
Curl_safefree(sshc->readdir_filename);
Curl_safefree(sshc->readdir_longentry);
state(conn, SSH_SFTP_CLOSE);
@@ -2860,7 +2861,7 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir)
fd_write = sock;
/* wait for the socket to become ready */
- Curl_socket_ready(fd_read, fd_write,
+ Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
left>1000?1000:left); /* ignore result */
}
#endif
@@ -3109,7 +3110,6 @@ static CURLcode scp_done(struct connectdata *conn, CURLcode status,
}
-/* return number of received (decrypted) bytes */
static ssize_t scp_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
@@ -3134,10 +3134,6 @@ static ssize_t scp_send(struct connectdata *conn, int sockindex,
return nwrite;
}
-/*
- * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
- * a regular CURLcode value.
- */
static ssize_t scp_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len, CURLcode *err)
{
diff --git a/lib/rawstr.c b/lib/strcase.c
index 5665ebd3..ccbaac17 100644
--- a/lib/rawstr.c
+++ b/lib/strcase.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,7 +22,9 @@
#include "curl_setup.h"
-#include "rawstr.h"
+#include <curl/curl.h>
+
+#include "strcase.h"
/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because
its behavior is altered by the current locale. */
@@ -99,9 +101,11 @@ char Curl_raw_toupper(char in)
*
* The function is capable of comparing a-z case insensitively even for
* non-ascii.
+ *
+ * @unittest: 1301
*/
-int Curl_raw_equal(const char *first, const char *second)
+int Curl_strcasecompare(const char *first, const char *second)
{
while(*first && *second) {
if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
@@ -116,7 +120,20 @@ int Curl_raw_equal(const char *first, const char *second)
return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
}
-int Curl_raw_nequal(const char *first, const char *second, size_t max)
+int Curl_safe_strcasecompare(const char *first, const char *second)
+{
+ if(first && second)
+ /* both pointers point to something then compare them */
+ return Curl_strcasecompare(first, second);
+ else
+ /* if both pointers are NULL then treat them as equal */
+ return (NULL == first && NULL == second);
+}
+
+/*
+ * @unittest: 1301
+ */
+int Curl_strncasecompare(const char *first, const char *second, size_t max)
{
while(*first && *second && max) {
if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) {
@@ -146,3 +163,14 @@ void Curl_strntoupper(char *dest, const char *src, size_t n)
*dest++ = Curl_raw_toupper(*src);
} while(*src++ && --n);
}
+
+/* --- public functions --- */
+
+int curl_strequal(const char *first, const char *second)
+{
+ return Curl_strcasecompare(first, second);
+}
+int curl_strnequal(const char *first, const char *second, size_t max)
+{
+ return Curl_strncasecompare(first, second, max);
+}
diff --git a/lib/rawstr.h b/lib/strcase.h
index 4af00f14..ea2abc8b 100644
--- a/lib/rawstr.h
+++ b/lib/strcase.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_RAWSTR_H
-#define HEADER_CURL_RAWSTR_H
+#ifndef HEADER_CURL_STRCASE_H
+#define HEADER_CURL_STRCASE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,23 +25,27 @@
#include <curl/curl.h>
/*
- * Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant
- * to be locale independent and only compare strings we know are safe for
- * this.
+ * Only "raw" case insensitive strings. This is meant to be locale independent
+ * and only compare strings we know are safe for this.
*
* The function is capable of comparing a-z case insensitively even for
* non-ascii.
*/
-int Curl_raw_equal(const char *first, const char *second);
-int Curl_raw_nequal(const char *first, const char *second, size_t max);
+
+#define strcasecompare(a,b) Curl_strcasecompare(a,b)
+#define strncasecompare(a,b,c) Curl_strncasecompare(a,b,c)
+
+int Curl_strcasecompare(const char *first, const char *second);
+int Curl_safe_strcasecompare(const char *first, const char *second);
+int Curl_strncasecompare(const char *first, const char *second, size_t max);
char Curl_raw_toupper(char in);
/* checkprefix() is a shorter version of the above, used when the first
argument is zero-byte terminated */
-#define checkprefix(a,b) Curl_raw_nequal(a,b,strlen(a))
+#define checkprefix(a,b) curl_strnequal(a,b,strlen(a))
void Curl_strntoupper(char *dest, const char *src, size_t n);
+char Curl_raw_toupper(char in);
-#endif /* HEADER_CURL_RAWSTR_H */
-
+#endif /* HEADER_CURL_STRCASE_H */
diff --git a/lib/strdup.c b/lib/strdup.c
index 23f554e5..136b6937 100644
--- a/lib/strdup.c
+++ b/lib/strdup.c
@@ -65,9 +65,9 @@ char *curlx_strdup(const char *str)
* Returns the new pointer or NULL on failure.
*
***************************************************************************/
-char *Curl_memdup(const char *src, size_t length)
+void *Curl_memdup(const void *src, size_t length)
{
- char *buffer = malloc(length);
+ void *buffer = malloc(length);
if(!buffer)
return NULL; /* fail */
@@ -75,3 +75,26 @@ char *Curl_memdup(const char *src, size_t length)
return buffer;
}
+
+/***************************************************************************
+ *
+ * Curl_saferealloc(ptr, size)
+ *
+ * Does a normal realloc(), but will free the data pointer if the realloc
+ * fails. If 'size' is zero, it will free the data and return a failure.
+ *
+ * This convenience function is provided and used to help us avoid a common
+ * mistake pattern when we could pass in a zero, catch the NULL return and end
+ * up free'ing the memory twice.
+ *
+ * Returns the new pointer or NULL on failure.
+ *
+ ***************************************************************************/
+void *Curl_saferealloc(void *ptr, size_t size)
+{
+ void *datap = realloc(ptr, size);
+ if(size && !datap)
+ /* only free 'ptr' if size was non-zero */
+ free(ptr);
+ return datap;
+}
diff --git a/lib/strdup.h b/lib/strdup.h
index 4c48ca41..ae3d5d01 100644
--- a/lib/strdup.h
+++ b/lib/strdup.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,6 +26,7 @@
#ifndef HAVE_STRDUP
extern char *curlx_strdup(const char *str);
#endif
-char *Curl_memdup(const char *src, size_t buffer_length);
+void *Curl_memdup(const void *src, size_t buffer_length);
+void *Curl_saferealloc(void *ptr, size_t size);
#endif /* HEADER_CURL_STRDUP_H */
diff --git a/lib/strequal.c b/lib/strequal.c
deleted file mode 100644
index 01c37844..00000000
--- a/lib/strequal.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-#include "curl_setup.h"
-
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
-#include "strequal.h"
-
-/*
- * @unittest: 1301
- */
-int curl_strequal(const char *first, const char *second)
-{
-#if defined(HAVE_STRCASECMP)
- return !(strcasecmp)(first, second);
-#elif defined(HAVE_STRCMPI)
- return !(strcmpi)(first, second);
-#elif defined(HAVE_STRICMP)
- return !(stricmp)(first, second);
-#else
- while(*first && *second) {
- if(toupper(*first) != toupper(*second)) {
- break;
- }
- first++;
- second++;
- }
- return toupper(*first) == toupper(*second);
-#endif
-}
-
-/*
- * @unittest: 1301
- */
-int curl_strnequal(const char *first, const char *second, size_t max)
-{
-#if defined(HAVE_STRNCASECMP)
- return !strncasecmp(first, second, max);
-#elif defined(HAVE_STRNCMPI)
- return !strncmpi(first, second, max);
-#elif defined(HAVE_STRNICMP)
- return !strnicmp(first, second, max);
-#else
- while(*first && *second && max) {
- if(toupper(*first) != toupper(*second)) {
- break;
- }
- max--;
- first++;
- second++;
- }
- if(0 == max)
- return 1; /* they are equal this far */
-
- return toupper(*first) == toupper(*second);
-#endif
-}
diff --git a/lib/strerror.c b/lib/strerror.c
index 0e268d5e..db50c7d1 100644
--- a/lib/strerror.c
+++ b/lib/strerror.c
@@ -35,8 +35,8 @@
#include <curl/curl.h>
-#ifdef USE_LIBIDN
-#include <idna.h>
+#ifdef USE_LIBIDN2
+#include <idn2.h>
#endif
#ifdef USE_WINDOWS_SSPI
@@ -79,8 +79,8 @@ curl_easy_strerror(CURLcode error)
case CURLE_COULDNT_CONNECT:
return "Couldn't connect to server";
- case CURLE_FTP_WEIRD_SERVER_REPLY:
- return "FTP: weird server reply";
+ case CURLE_WEIRD_SERVER_REPLY:
+ return "Weird server reply";
case CURLE_REMOTE_ACCESS_DENIED:
return "Access denied to remote resource";
@@ -427,7 +427,7 @@ curl_share_strerror(CURLSHcode error)
#ifdef USE_WINSOCK
-/* This function handles most / all (?) Winsock errors cURL is able to produce.
+/* This function handles most / all (?) Winsock errors curl is able to produce.
*/
static const char *
get_winsock_error (int err, char *buf, size_t len)
@@ -726,83 +726,6 @@ const char *Curl_strerror(struct connectdata *conn, int err)
return buf;
}
-#ifdef USE_LIBIDN
-/*
- * Return error-string for libidn status as returned from idna_to_ascii_lz().
- */
-const char *Curl_idn_strerror (struct connectdata *conn, int err)
-{
-#ifdef HAVE_IDNA_STRERROR
- (void)conn;
- return idna_strerror((Idna_rc) err);
-#else
- const char *str;
- char *buf;
- size_t max;
-
- DEBUGASSERT(conn);
-
- buf = conn->syserr_buf;
- max = sizeof(conn->syserr_buf)-1;
- *buf = '\0';
-
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- switch ((Idna_rc)err) {
- case IDNA_SUCCESS:
- str = "No error";
- break;
- case IDNA_STRINGPREP_ERROR:
- str = "Error in string preparation";
- break;
- case IDNA_PUNYCODE_ERROR:
- str = "Error in Punycode operation";
- break;
- case IDNA_CONTAINS_NON_LDH:
- str = "Illegal ASCII characters";
- break;
- case IDNA_CONTAINS_MINUS:
- str = "Contains minus";
- break;
- case IDNA_INVALID_LENGTH:
- str = "Invalid output length";
- break;
- case IDNA_NO_ACE_PREFIX:
- str = "No ACE prefix (\"xn--\")";
- break;
- case IDNA_ROUNDTRIP_VERIFY_ERROR:
- str = "Round trip verify error";
- break;
- case IDNA_CONTAINS_ACE_PREFIX:
- str = "Already have ACE prefix (\"xn--\")";
- break;
- case IDNA_ICONV_ERROR:
- str = "Locale conversion failed";
- break;
- case IDNA_MALLOC_ERROR:
- str = "Allocation failed";
- break;
- case IDNA_DLOPEN_ERROR:
- str = "dlopen() error";
- break;
- default:
- snprintf(buf, max, "error %d", err);
- str = NULL;
- break;
- }
-#else
- if((Idna_rc)err == IDNA_SUCCESS)
- str = "No error";
- else
- str = "Error";
-#endif
- if(str)
- strncpy(buf, str, max);
- buf[max] = '\0';
- return (buf);
-#endif
-}
-#endif /* USE_LIBIDN */
-
#ifdef USE_WINDOWS_SSPI
const char *Curl_sspi_strerror (struct connectdata *conn, int err)
{
diff --git a/lib/strerror.h b/lib/strerror.h
index ae8c96bd..627273eb 100644
--- a/lib/strerror.h
+++ b/lib/strerror.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,7 +26,7 @@
const char *Curl_strerror (struct connectdata *conn, int err);
-#ifdef USE_LIBIDN
+#ifdef USE_LIBIDN2
const char *Curl_idn_strerror (struct connectdata *conn, int err);
#endif
diff --git a/lib/strtoofft.c b/lib/strtoofft.c
index 6d5d2d5c..b854bf4d 100644
--- a/lib/strtoofft.c
+++ b/lib/strtoofft.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -165,7 +165,7 @@ static int get_char(char c, int base)
value = c - 'a' + 10;
}
#else
- const char * cp;
+ const char *cp;
int value;
cp = memchr(valchars, c, 10 + 26 + 26);
diff --git a/lib/system_win32.c b/lib/system_win32.c
index d6a998b2..78737593 100644
--- a/lib/system_win32.c
+++ b/lib/system_win32.c
@@ -83,7 +83,39 @@ bool Curl_verify_windows_version(const unsigned int majorVersion,
{
bool matched = FALSE;
-#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
+#if defined(CURL_WINDOWS_APP)
+ /* We have no way to determine the Windows version from Windows apps,
+ so let's assume we're running on the target Windows version. */
+ const WORD fullVersion = MAKEWORD(minorVersion, majorVersion);
+ const WORD targetVersion = (WORD)_WIN32_WINNT;
+
+ switch(condition) {
+ case VERSION_LESS_THAN:
+ matched = targetVersion < fullVersion;
+ break;
+
+ case VERSION_LESS_THAN_EQUAL:
+ matched = targetVersion <= fullVersion;
+ break;
+
+ case VERSION_EQUAL:
+ matched = targetVersion == fullVersion;
+ break;
+
+ case VERSION_GREATER_THAN_EQUAL:
+ matched = targetVersion >= fullVersion;
+ break;
+
+ case VERSION_GREATER_THAN:
+ matched = targetVersion > fullVersion;
+ break;
+ }
+
+ if(matched && (platform == PLATFORM_WINDOWS)) {
+ /* we're always running on PLATFORM_WINNT */
+ matched = FALSE;
+ }
+#elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
(_WIN32_WINNT < _WIN32_WINNT_WIN2K)
OSVERSIONINFO osver;
@@ -128,7 +160,7 @@ bool Curl_verify_windows_version(const unsigned int majorVersion,
}
/* Verify the platform identifier (if necessary) */
- if(matched && platform != PLATFORM_DONT_CARE) {
+ if(matched) {
switch(platform) {
case PLATFORM_WINDOWS:
if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
@@ -138,6 +170,9 @@ bool Curl_verify_windows_version(const unsigned int majorVersion,
case PLATFORM_WINNT:
if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
matched = FALSE;
+
+ default: /* like platform == PLATFORM_DONT_CARE */
+ break;
}
}
}
diff --git a/lib/telnet.c b/lib/telnet.c
index cc705cfc..ddf3d3b9 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -58,8 +58,7 @@
#include "arpa_telnet.h"
#include "select.h"
-#include "strequal.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "warnless.h"
/* The last 3 #include files should be in this order */
@@ -846,7 +845,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
option_keyword, option_arg) == 2) {
/* Terminal type */
- if(Curl_raw_equal(option_keyword, "TTYPE")) {
+ if(strcasecompare(option_keyword, "TTYPE")) {
strncpy(tn->subopt_ttype, option_arg, 31);
tn->subopt_ttype[31] = 0; /* String termination */
tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
@@ -854,7 +853,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
}
/* Display variable */
- if(Curl_raw_equal(option_keyword, "XDISPLOC")) {
+ if(strcasecompare(option_keyword, "XDISPLOC")) {
strncpy(tn->subopt_xdisploc, option_arg, 127);
tn->subopt_xdisploc[127] = 0; /* String termination */
tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
@@ -862,7 +861,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
}
/* Environment variable */
- if(Curl_raw_equal(option_keyword, "NEW_ENV")) {
+ if(strcasecompare(option_keyword, "NEW_ENV")) {
beg = curl_slist_append(tn->telnet_vars, option_arg);
if(!beg) {
result = CURLE_OUT_OF_MEMORY;
@@ -874,7 +873,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
}
/* Window Size */
- if(Curl_raw_equal(option_keyword, "WS")) {
+ if(strcasecompare(option_keyword, "WS")) {
if(sscanf(option_arg, "%hu%*[xX]%hu",
&tn->subopt_wsx, &tn->subopt_wsy) == 2)
tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES;
@@ -887,7 +886,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
}
/* To take care or not of the 8th bit in data exchange */
- if(Curl_raw_equal(option_keyword, "BINARY")) {
+ if(strcasecompare(option_keyword, "BINARY")) {
binary_option=atoi(option_arg);
if(binary_option!=1) {
tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO;
@@ -1005,7 +1004,7 @@ static void sendsuboption(struct connectdata *conn, int option)
ssize_t bytes_written;
int err;
unsigned short x, y;
- unsigned char*uc1, *uc2;
+ unsigned char *uc1, *uc2;
struct Curl_easy *data = conn->data;
struct TELNET *tn = (struct TELNET *)data->req.protop;
@@ -1021,8 +1020,8 @@ static void sendsuboption(struct connectdata *conn, int option)
/* Window size must be sent according to the 'network order' */
x=htons(tn->subopt_wsx);
y=htons(tn->subopt_wsy);
- uc1 = (unsigned char*)&x;
- uc2 = (unsigned char*)&y;
+ uc1 = (unsigned char *)&x;
+ uc2 = (unsigned char *)&y;
CURL_SB_ACCUM(tn, uc1[0]);
CURL_SB_ACCUM(tn, uc1[1]);
CURL_SB_ACCUM(tn, uc2[0]);
diff --git a/lib/tftp.c b/lib/tftp.c
index d7ff94f7..de99c6ef 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -55,9 +55,10 @@
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "multiif.h"
#include "url.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "speedcheck.h"
#include "select.h"
+#include "escape.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -198,7 +199,7 @@ const struct Curl_handler Curl_handler_tftp = {
static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
{
time_t maxtime, timeout;
- long timeout_ms;
+ time_t timeout_ms;
bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE;
time(&state->start_time);
@@ -484,10 +485,10 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
/* As RFC3617 describes the separator slash is not actually part of the
file name so we skip the always-present first letter of the path
string. */
- filename = curl_easy_unescape(data, &state->conn->data->state.path[1], 0,
- NULL);
- if(!filename)
- return CURLE_OUT_OF_MEMORY;
+ result = Curl_urldecode(data, &state->conn->data->state.path[1], 0,
+ &filename, NULL, FALSE);
+ if(result)
+ return result;
snprintf((char *)state->spacket.data+2,
state->blksize,
@@ -705,6 +706,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
int rblock;
CURLcode result = CURLE_OK;
struct SingleRequest *k = &data->req;
+ int cb; /* Bytes currently read */
switch(event) {
@@ -762,9 +764,20 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
return CURLE_OK;
}
- result = Curl_fillreadbuffer(state->conn, state->blksize, &state->sbytes);
- if(result)
- return result;
+ /* TFTP considers data block size < 512 bytes as an end of session. So
+ * in some cases we must wait for additional data to build full (512 bytes)
+ * data block.
+ * */
+ state->sbytes = 0;
+ state->conn->data->req.upload_fromhere = (char *)state->spacket.data+4;
+ do {
+ result = Curl_fillreadbuffer(state->conn, state->blksize - state->sbytes,
+ &cb);
+ if(result)
+ return result;
+ state->sbytes += cb;
+ state->conn->data->req.upload_fromhere += cb;
+ } while(state->sbytes < state->blksize && cb != 0);
sbytes = sendto(state->sockfd, (void *) state->spacket.data,
4 + state->sbytes, SEND_4TH_ARG,
@@ -1221,7 +1234,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
}
else {
/* no timeouts to handle, check our socket */
- rc = Curl_socket_ready(state->sockfd, CURL_SOCKET_BAD, 0);
+ rc = SOCKET_READABLE(state->sockfd, 0);
if(rc == -1) {
/* bail out */
@@ -1343,7 +1356,7 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
static CURLcode tftp_setup_connection(struct connectdata * conn)
{
struct Curl_easy *data = conn->data;
- char * type;
+ char *type;
char command;
conn->socktype = SOCK_DGRAM; /* UDP datagram based */
diff --git a/lib/timeval.c b/lib/timeval.c
index 629f1c8f..f3b207a3 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -116,7 +116,7 @@ struct timeval curlx_tvnow(void)
* Returns: the time difference in number of milliseconds. For large diffs it
* returns 0x7fffffff on 32bit time_t systems.
*/
-long curlx_tvdiff(struct timeval newer, struct timeval older)
+time_t curlx_tvdiff(struct timeval newer, struct timeval older)
{
#if SIZEOF_TIME_T < 8
/* for 32bit time_t systems, add a precaution to avoid overflow for really
@@ -126,7 +126,7 @@ long curlx_tvdiff(struct timeval newer, struct timeval older)
return 0x7fffffff;
#endif
return (newer.tv_sec-older.tv_sec)*1000+
- (long)(newer.tv_usec-older.tv_usec)/1000;
+ (time_t)(newer.tv_usec-older.tv_usec)/1000;
}
/*
@@ -144,7 +144,7 @@ double curlx_tvdiff_secs(struct timeval newer, struct timeval older)
}
/* return the number of seconds in the given input timeval struct */
-long Curl_tvlong(struct timeval t1)
+time_t Curl_tvlong(struct timeval t1)
{
return t1.tv_sec;
}
diff --git a/lib/timeval.h b/lib/timeval.h
index 50c31a25..09f8b3a2 100644
--- a/lib/timeval.h
+++ b/lib/timeval.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,7 +37,7 @@ struct timeval curlx_tvnow(void);
*
* Returns: the time difference in number of milliseconds.
*/
-long curlx_tvdiff(struct timeval t1, struct timeval t2);
+time_t curlx_tvdiff(struct timeval t1, struct timeval t2);
/*
* Same as curlx_tvdiff but with full usec resolution.
@@ -46,7 +46,7 @@ long curlx_tvdiff(struct timeval t1, struct timeval t2);
*/
double curlx_tvdiff_secs(struct timeval t1, struct timeval t2);
-long Curl_tvlong(struct timeval t1);
+time_t Curl_tvlong(struct timeval t1);
/* These two defines below exist to provide the older API for library
internals only. */
diff --git a/lib/transfer.c b/lib/transfer.c
index f5987feb..052ecc18 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -21,10 +21,7 @@
***************************************************************************/
#include "curl_setup.h"
-
#include "strtoofft.h"
-#include "strequal.h"
-#include "rawstr.h"
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
@@ -75,6 +72,7 @@
#include "multiif.h"
#include "connect.h"
#include "non-ascii.h"
+#include "http2.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -384,11 +382,15 @@ bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc)
* Go ahead and do a read if we have a readable socket or if
* the stream was rewound (in which case we have data in a
* buffer)
+ *
+ * return '*comeback' TRUE if we didn't properly drain the socket so this
+ * function should get called again without select() or similar in between!
*/
static CURLcode readwrite_data(struct Curl_easy *data,
struct connectdata *conn,
struct SingleRequest *k,
- int *didwhat, bool *done)
+ int *didwhat, bool *done,
+ bool *comeback)
{
CURLcode result = CURLE_OK;
ssize_t nread; /* number of bytes read */
@@ -398,6 +400,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
int maxloops = 100;
*done = FALSE;
+ *comeback = FALSE;
/* This is where we loop until we have read everything there is to
read or we get a CURLE_AGAIN */
@@ -529,6 +532,13 @@ static CURLcode readwrite_data(struct Curl_easy *data,
is non-headers. */
if(k->str && !k->header && (nread > 0 || is_empty_data)) {
+ if(data->set.opt_no_body) {
+ /* data arrives although we want none, bail out */
+ streamclose(conn, "ignoring body");
+ *done = TRUE;
+ return CURLE_WEIRD_SERVER_REPLY;
+ }
+
#ifndef CURL_DISABLE_HTTP
if(0 == k->bodywrites && !is_empty_data) {
/* These checks are only made the first time we are about to
@@ -804,6 +814,12 @@ static CURLcode readwrite_data(struct Curl_easy *data,
} while(data_pending(conn) && maxloops--);
+ if(maxloops <= 0) {
+ /* we mark it as read-again-please */
+ conn->cselect_bits = CURL_CSELECT_IN;
+ *comeback = TRUE;
+ }
+
if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) &&
conn->bits.close) {
/* When we've read the entire thing and the close bit is set, the server
@@ -821,6 +837,8 @@ static CURLcode done_sending(struct connectdata *conn,
{
k->keepon &= ~KEEP_SEND; /* we're done writing */
+ Curl_http2_done_sending(conn);
+
if(conn->bits.rewindaftersend) {
CURLcode result = Curl_readrewind(conn);
if(result)
@@ -1029,10 +1047,14 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
/*
* Curl_readwrite() is the low-level function to be called when data is to
* be read and written to/from the connection.
+ *
+ * return '*comeback' TRUE if we didn't properly drain the socket so this
+ * function should get called again without select() or similar in between!
*/
CURLcode Curl_readwrite(struct connectdata *conn,
struct Curl_easy *data,
- bool *done)
+ bool *done,
+ bool *comeback)
{
struct SingleRequest *k = &data->req;
CURLcode result;
@@ -1064,7 +1086,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if(!select_res) /* Call for select()/poll() only, if read/write/error
status is not known. */
- select_res = Curl_socket_ready(fd_read, fd_write, 0);
+ select_res = Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, 0);
if(select_res == CURL_CSELECT_ERR) {
failf(data, "select/poll returned error");
@@ -1077,7 +1099,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if((k->keepon & KEEP_RECV) &&
((select_res & CURL_CSELECT_IN) || conn->bits.stream_was_rewound)) {
- result = readwrite_data(data, conn, k, &didwhat, done);
+ result = readwrite_data(data, conn, k, &didwhat, done, comeback);
if(result || *done)
return result;
}
@@ -1115,7 +1137,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
*/
- long ms = Curl_tvdiff(k->now, k->start100);
+ time_t ms = Curl_tvdiff(k->now, k->start100);
if(ms >= data->set.expect_100_timeout) {
/* we've waited long enough, continue anyway */
k->exp100 = EXP100_SEND_DATA;
@@ -1249,60 +1271,6 @@ int Curl_single_getsock(const struct connectdata *conn,
return bitmap;
}
-/*
- * Determine optimum sleep time based on configured rate, current rate,
- * and packet size.
- * Returns value in milliseconds.
- *
- * The basic idea is to adjust the desired rate up/down in this method
- * based on whether we are running too slow or too fast. Then, calculate
- * how many milliseconds to wait for the next packet to achieve this new
- * rate.
- */
-long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps,
- int pkt_size)
-{
- curl_off_t min_sleep = 0;
- curl_off_t rv = 0;
-
- if(rate_bps == 0)
- return 0;
-
- /* If running faster than about .1% of the desired speed, slow
- * us down a bit. Use shift instead of division as the 0.1%
- * cutoff is arbitrary anyway.
- */
- if(cur_rate_bps > (rate_bps + (rate_bps >> 10))) {
- /* running too fast, decrease target rate by 1/64th of rate */
- rate_bps -= rate_bps >> 6;
- min_sleep = 1;
- }
- else if(cur_rate_bps < (rate_bps - (rate_bps >> 10))) {
- /* running too slow, increase target rate by 1/64th of rate */
- rate_bps += rate_bps >> 6;
- }
-
- /* Determine number of milliseconds to wait until we do
- * the next packet at the adjusted rate. We should wait
- * longer when using larger packets, for instance.
- */
- rv = ((curl_off_t)(pkt_size * 1000) / rate_bps);
-
- /* Catch rounding errors and always slow down at least 1ms if
- * we are running too fast.
- */
- if(rv < min_sleep)
- rv = min_sleep;
-
- /* Bound value to fit in 'long' on 32-bit platform. That's
- * plenty long enough anyway!
- */
- if(rv > 0x7fffffff)
- rv = 0x7fffffff;
-
- return (long)rv;
-}
-
/* Curl_init_CONNECT() gets called each time the handle switches to CONNECT
which means this gets called once for each subsequent redirect etc */
void Curl_init_CONNECT(struct Curl_easy *data)
@@ -1328,7 +1296,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
/* Init the SSL session ID cache here. We do it here since we want to do it
after the *_setopt() calls (that could specify the size of the cache) but
before any transfer takes place. */
- result = Curl_ssl_initsessions(data, data->set.ssl.max_ssl_sessions);
+ result = Curl_ssl_initsessions(data, data->set.general_ssl.max_ssl_sessions);
if(result)
return result;
@@ -1875,13 +1843,12 @@ CURLcode Curl_retry_request(struct connectdata *conn,
return CURLE_OK;
if((data->req.bytecount + data->req.headerbytecount == 0) &&
- conn->bits.reuse &&
- !data->set.opt_no_body &&
- (data->set.rtspreq != RTSPREQ_RECEIVE)) {
- /* We got no data, we attempted to re-use a connection and yet we want a
- "body". This might happen if the connection was left alive when we were
- done using it before, but that was closed when we wanted to read from
- it again. Bad luck. Retry the same request on a fresh connect! */
+ conn->bits.reuse &&
+ (data->set.rtspreq != RTSPREQ_RECEIVE)) {
+ /* We didn't get a single byte when we attempted to re-use a
+ connection. This might happen if the connection was left alive when we
+ were done using it before, but that was closed when we wanted to use it
+ again. Bad luck. Retry the same request on a fresh connect! */
infof(conn->data, "Connection died, retrying a fresh connect\n");
*url = strdup(conn->data->change.url);
if(!*url)
diff --git a/lib/transfer.h b/lib/transfer.h
index 0e253e37..51896726 100644
--- a/lib/transfer.h
+++ b/lib/transfer.h
@@ -40,10 +40,9 @@ typedef enum {
CURLcode Curl_follow(struct Curl_easy *data, char *newurl,
followtype type);
-
-
CURLcode Curl_readwrite(struct connectdata *conn,
- struct Curl_easy *data, bool *done);
+ struct Curl_easy *data, bool *done,
+ bool *comeback);
int Curl_single_getsock(const struct connectdata *conn,
curl_socket_t *socks,
int numsocks);
@@ -65,8 +64,5 @@ Curl_setup_transfer (struct connectdata *data,
curl_off_t *writecountp /* return number of bytes written */
);
-long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps,
- int pkt_size);
-
#endif /* HEADER_CURL_TRANSFER_H */
diff --git a/lib/url.c b/lib/url.c
index e547e5c1..5dee7a77 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -59,24 +59,13 @@
#include <limits.h>
#endif
-#ifdef USE_LIBIDN
-#include <idna.h>
-#include <tld.h>
-#include <stringprep.h>
-#ifdef HAVE_IDN_FREE_H
-#include <idn-free.h>
-#else
-/* prototype from idn-free.h, not provided by libidn 0.4.5's make install! */
-void idn_free (void *ptr);
-#endif
-#ifndef HAVE_IDN_FREE
-/* if idn_free() was not found in this version of libidn use free() instead */
-#define idn_free(x) (free)(x)
-#endif
+#ifdef USE_LIBIDN2
+#include <idn2.h>
+
#elif defined(USE_WIN32_IDN)
/* prototype for curl_win32_idn_to_ascii() */
bool curl_win32_idn_to_ascii(const char *in, char **out);
-#endif /* USE_LIBIDN */
+#endif /* USE_LIBIDN2 */
#include "urldata.h"
#include "netrc.h"
@@ -88,7 +77,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "sendf.h"
#include "progress.h"
#include "cookie.h"
-#include "strequal.h"
+#include "strcase.h"
#include "strerror.h"
#include "escape.h"
#include "strtok.h"
@@ -100,10 +89,10 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "multiif.h"
#include "easyif.h"
#include "speedcheck.h"
-#include "rawstr.h"
#include "warnless.h"
#include "non-ascii.h"
#include "inet_pton.h"
+#include "getinfo.h"
/* And now for the protocols */
#include "ftp.h"
@@ -405,7 +394,7 @@ CURLcode Curl_close(struct Curl_easy *data)
if(!data)
return CURLE_OK;
- Curl_expire(data, 0); /* shut off timers */
+ Curl_expire_clear(data); /* shut off timers */
m = data->multi;
@@ -537,7 +526,7 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
/* Set the default size of the SSL session ID cache */
- set->ssl.max_ssl_sessions = 5;
+ set->general_ssl.max_ssl_sessions = 5;
set->proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */
set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
@@ -551,14 +540,16 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
* libcurl 7.10 introduced SSL verification *by default*! This needs to be
* switched off unless wanted.
*/
- set->ssl.verifypeer = TRUE;
- set->ssl.verifyhost = TRUE;
+ set->ssl.primary.verifypeer = TRUE;
+ set->ssl.primary.verifyhost = TRUE;
#ifdef USE_TLS_SRP
set->ssl.authtype = CURL_TLSAUTH_NONE;
#endif
set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
type */
- set->ssl.sessionid = TRUE; /* session ID caching enabled by default */
+ set->general_ssl.sessionid = TRUE; /* session ID caching enabled by
+ default */
+ set->proxy_ssl = set->ssl;
set->new_file_perms = 0644; /* Default permissions */
set->new_directory_perms = 0755; /* Default permissions */
@@ -581,14 +572,17 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
/* This is our preferred CA cert bundle/path since install time */
#if defined(CURL_CA_BUNDLE)
- result = setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
+ result = setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
if(result)
return result;
#endif
#if defined(CURL_CA_PATH)
- result = setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
+ result = setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
if(result)
return result;
+
+ result = setstropt(&set->str[STRING_SSL_CAPATH_PROXY],
+ (char *) CURL_CA_PATH);
#endif
set->wildcardmatch = FALSE;
@@ -602,6 +596,7 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
set->tcp_keepintvl = 60;
set->tcp_keepidle = 60;
set->tcp_fastopen = FALSE;
+ set->tcp_nodelay = TRUE;
set->ssl_enable_npn = TRUE;
set->ssl_enable_alpn = TRUE;
@@ -657,6 +652,8 @@ CURLcode Curl_open(struct Curl_easy **curl)
Curl_convert_init(data);
+ Curl_initinfo(data);
+
/* most recent connection is not yet defined */
data->state.lastconnect = NULL;
@@ -705,7 +702,12 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
break;
case CURLOPT_SSL_CIPHER_LIST:
/* set a list of cipher we want to use in the SSL connection */
- result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
+ result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_SSL_CIPHER_LIST:
+ /* set a list of cipher we want to use in the SSL connection for proxy */
+ result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
va_arg(param, char *));
break;
@@ -781,6 +783,10 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
*/
data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
+ case CURLOPT_KEEP_SENDING_ON_ERROR:
+ data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
+ break;
case CURLOPT_UPLOAD:
case CURLOPT_PUT:
/*
@@ -907,7 +913,18 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* implementations are lame.
*/
#ifdef USE_SSL
- data->set.ssl.version = va_arg(param, long);
+ data->set.ssl.primary.version = va_arg(param, long);
+#else
+ result = CURLE_UNKNOWN_OPTION;
+#endif
+ break;
+ case CURLOPT_PROXY_SSLVERSION:
+ /*
+ * Set explicit SSL version to try to connect with for proxy, as some SSL
+ * implementations are lame.
+ */
+#ifdef USE_SSL
+ data->set.proxy_ssl.primary.version = va_arg(param, long);
#else
result = CURLE_UNKNOWN_OPTION;
#endif
@@ -1014,7 +1031,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
(data->set.postfieldsize > (curl_off_t)((size_t)-1))))
result = CURLE_OUT_OF_MEMORY;
else {
- char * p;
+ char *p;
(void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
@@ -1225,23 +1242,23 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
if(argptr == NULL)
break;
- if(Curl_raw_equal(argptr, "ALL")) {
+ if(strcasecompare(argptr, "ALL")) {
/* clear all cookies */
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
Curl_cookie_clearall(data->cookies);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
- else if(Curl_raw_equal(argptr, "SESS")) {
+ else if(strcasecompare(argptr, "SESS")) {
/* clear session cookies */
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
Curl_cookie_clearsess(data->cookies);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
- else if(Curl_raw_equal(argptr, "FLUSH")) {
+ else if(strcasecompare(argptr, "FLUSH")) {
/* flush cookies to file, takes care of the locking */
Curl_flush_cookies(data, 0);
}
- else if(Curl_raw_equal(argptr, "RELOAD")) {
+ else if(strcasecompare(argptr, "RELOAD")) {
/* reload cookies from file */
Curl_cookie_loadfiles(data);
break;
@@ -1441,18 +1458,30 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
case CURLOPT_PROXY:
/*
- * Set proxy server:port to use as HTTP proxy.
+ * Set proxy server:port to use as proxy.
*
- * If the proxy is set to "" we explicitly say that we don't want to use a
- * proxy (even though there might be environment variables saying so).
+ * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL)
+ * we explicitly say that we don't want to use a proxy
+ * (even though there might be environment variables saying so).
*
* Setting it to NULL, means no proxy but allows the environment variables
- * to decide for us.
+ * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
*/
result = setstropt(&data->set.str[STRING_PROXY],
va_arg(param, char *));
break;
+ case CURLOPT_SOCKS_PROXY:
+ /*
+ * Set proxy server:port to use as SOCKS proxy.
+ *
+ * If the proxy is set to "" or NULL we explicitly say that we don't want
+ * to use the socks proxy.
+ */
+ result = setstropt(&data->set.str[STRING_SOCKS_PROXY],
+ va_arg(param, char *));
+ break;
+
case CURLOPT_PROXYTYPE:
/*
* Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
@@ -1460,6 +1489,13 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
data->set.proxytype = (curl_proxytype)va_arg(param, long);
break;
+ case CURLOPT_SOCKS_PROXYTYPE:
+ /*
+ * Set proxy type. SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
+ */
+ data->set.socks_proxytype = (curl_proxytype)va_arg(param, long);
+ break;
+
case CURLOPT_PROXY_TRANSFER_MODE:
/*
* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
@@ -1917,35 +1953,70 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
/*
* String that holds file name of the SSL certificate to use
*/
- result = setstropt(&data->set.str[STRING_CERT],
+ result = setstropt(&data->set.str[STRING_CERT_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_SSLCERT:
+ /*
+ * String that holds file name of the SSL certificate to use for proxy
+ */
+ result = setstropt(&data->set.str[STRING_CERT_PROXY],
va_arg(param, char *));
break;
case CURLOPT_SSLCERTTYPE:
/*
* String that holds file type of the SSL certificate to use
*/
- result = setstropt(&data->set.str[STRING_CERT_TYPE],
+ result = setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_SSLCERTTYPE:
+ /*
+ * String that holds file type of the SSL certificate to use for proxy
+ */
+ result = setstropt(&data->set.str[STRING_CERT_TYPE_PROXY],
va_arg(param, char *));
break;
case CURLOPT_SSLKEY:
/*
* String that holds file name of the SSL key to use
*/
- result = setstropt(&data->set.str[STRING_KEY],
+ result = setstropt(&data->set.str[STRING_KEY_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_SSLKEY:
+ /*
+ * String that holds file name of the SSL key to use for proxy
+ */
+ result = setstropt(&data->set.str[STRING_KEY_PROXY],
va_arg(param, char *));
break;
case CURLOPT_SSLKEYTYPE:
/*
* String that holds file type of the SSL key to use
*/
- result = setstropt(&data->set.str[STRING_KEY_TYPE],
+ result = setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_SSLKEYTYPE:
+ /*
+ * String that holds file type of the SSL key to use for proxy
+ */
+ result = setstropt(&data->set.str[STRING_KEY_TYPE_PROXY],
va_arg(param, char *));
break;
case CURLOPT_KEYPASSWD:
/*
* String that holds the SSL or SSH private key password.
*/
- result = setstropt(&data->set.str[STRING_KEY_PASSWD],
+ result = setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_KEYPASSWD:
+ /*
+ * String that holds the SSL private key password for proxy.
+ */
+ result = setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY],
va_arg(param, char *));
break;
case CURLOPT_SSLENGINE:
@@ -2008,7 +2079,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
/*
* Enable peer SSL verifying.
*/
- data->set.ssl.verifypeer = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
+ break;
+ case CURLOPT_PROXY_SSL_VERIFYPEER:
+ /*
+ * Enable peer SSL verifying for proxy.
+ */
+ data->set.proxy_ssl.primary.verifypeer =
+ (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_SSL_VERIFYHOST:
/*
@@ -2026,7 +2105,25 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
return CURLE_BAD_FUNCTION_ARGUMENT;
}
- data->set.ssl.verifyhost = (0 != arg) ? TRUE : FALSE;
+ data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE;
+ break;
+ case CURLOPT_PROXY_SSL_VERIFYHOST:
+ /*
+ * Enable verification of the host name in the peer certificate for proxy
+ */
+ arg = va_arg(param, long);
+
+ /* Obviously people are not reading documentation and too many thought
+ this argument took a boolean when it wasn't and misused it. We thus ban
+ 1 as a sensible input and we warn about its use. Then we only have the
+ 2 action internally stored as TRUE. */
+
+ if(1 == arg) {
+ failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE;
break;
case CURLOPT_SSL_VERIFYSTATUS:
/*
@@ -2037,7 +2134,8 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
break;
}
- data->set.ssl.verifystatus = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
break;
case CURLOPT_SSL_CTX_FUNCTION:
#ifdef have_curlssl_ssl_ctx
@@ -2093,7 +2191,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
/*
* Set CA info for SSL connection. Specify file name of the CA certificate
*/
- result = setstropt(&data->set.str[STRING_SSL_CAFILE],
+ result = setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_CAINFO:
+ /*
+ * Set CA info SSL connection for proxy. Specify file name of the
+ * CA certificate
+ */
+ result = setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
va_arg(param, char *));
break;
case CURLOPT_CAPATH:
@@ -2103,7 +2209,16 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* certificates which have been prepared using openssl c_rehash utility.
*/
/* This does not work on windows. */
- result = setstropt(&data->set.str[STRING_SSL_CAPATH],
+ result = setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_CAPATH:
+ /*
+ * Set CA path info for SSL connection proxy. Specify directory name of the
+ * CA certificates which have been prepared using openssl c_rehash utility.
+ */
+ /* This does not work on windows. */
+ result = setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
va_arg(param, char *));
#else
result = CURLE_NOT_BUILT_IN;
@@ -2114,7 +2229,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* Set CRL file info for SSL connection. Specify file name of the CRL
* to check certificates revocation
*/
- result = setstropt(&data->set.str[STRING_SSL_CRLFILE],
+ result = setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_CRLFILE:
+ /*
+ * Set CRL file info for SSL connection for proxy. Specify file name of the
+ * CRL to check certificates revocation
+ */
+ result = setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY],
va_arg(param, char *));
break;
case CURLOPT_ISSUERCERT:
@@ -2122,7 +2245,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* Set Issuer certificate file
* to check certificates issuer
*/
- result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT],
+ result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
va_arg(param, char *));
break;
case CURLOPT_TELNETOPTIONS:
@@ -2203,7 +2326,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
}
#endif /* CURL_DISABLE_HTTP */
if(data->share->sslsession) {
- data->set.ssl.max_ssl_sessions = data->share->max_ssl_sessions;
+ data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
data->state.session = data->share->sslsession;
}
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
@@ -2238,8 +2361,14 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
case CURLOPT_SSL_OPTIONS:
arg = va_arg(param, long);
- data->set.ssl_enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
- data->set.ssl_no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
+ data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+ data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
+ break;
+
+ case CURLOPT_PROXY_SSL_OPTIONS:
+ arg = va_arg(param, long);
+ data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+ data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
break;
#endif
@@ -2335,7 +2464,8 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
break;
case CURLOPT_SSL_SESSIONID_CACHE:
- data->set.ssl.sessionid = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.general_ssl.sessionid = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
break;
#ifdef USE_LIBSSH2
@@ -2602,23 +2732,43 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
break;
#ifdef USE_TLS_SRP
case CURLOPT_TLSAUTH_USERNAME:
- result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
+ result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
+ if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
break;
+ case CURLOPT_PROXY_TLSAUTH_USERNAME:
+ result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
+ va_arg(param, char *));
+ if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
+ !data->set.proxy_ssl.authtype)
+ data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ break;
case CURLOPT_TLSAUTH_PASSWORD:
- result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
+ result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
+ if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
break;
+ case CURLOPT_PROXY_TLSAUTH_PASSWORD:
+ result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
+ va_arg(param, char *));
+ if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
+ !data->set.proxy_ssl.authtype)
+ data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ break;
case CURLOPT_TLSAUTH_TYPE:
- if(strnequal((char *)va_arg(param, char *), "SRP", strlen("SRP")))
+ if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
data->set.ssl.authtype = CURL_TLSAUTH_SRP;
else
data->set.ssl.authtype = CURL_TLSAUTH_NONE;
break;
+ case CURLOPT_PROXY_TLSAUTH_TYPE:
+ if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
+ data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
+ else
+ data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
+ break;
#endif
case CURLOPT_DNS_SERVERS:
result = Curl_set_dns_servers(data, va_arg(param, char *));
@@ -2775,8 +2925,10 @@ static void conn_free(struct connectdata *conn)
Curl_safefree(conn->passwd);
Curl_safefree(conn->oauth_bearer);
Curl_safefree(conn->options);
- Curl_safefree(conn->proxyuser);
- Curl_safefree(conn->proxypasswd);
+ Curl_safefree(conn->http_proxy.user);
+ Curl_safefree(conn->socks_proxy.user);
+ Curl_safefree(conn->http_proxy.passwd);
+ Curl_safefree(conn->socks_proxy.passwd);
Curl_safefree(conn->allocptr.proxyuserpwd);
Curl_safefree(conn->allocptr.uagent);
Curl_safefree(conn->allocptr.userpwd);
@@ -2790,7 +2942,9 @@ static void conn_free(struct connectdata *conn)
Curl_safefree(conn->trailer);
Curl_safefree(conn->host.rawalloc); /* host name buffer */
Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
- Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */
+ Curl_safefree(conn->secondaryhostname);
+ Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
+ Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
Curl_safefree(conn->master_buffer);
conn_reset_all_postponed_data(conn);
@@ -2802,7 +2956,12 @@ static void conn_free(struct connectdata *conn)
conn->recv_pipe = NULL;
Curl_safefree(conn->localdev);
- Curl_free_ssl_config(&conn->ssl_config);
+ Curl_free_primary_ssl_config(&conn->ssl_config);
+ Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
+
+#ifdef USE_UNIX_SOCKETS
+ Curl_safefree(conn->unix_domain_socket);
+#endif
free(conn); /* free all the connection oriented data */
}
@@ -2829,6 +2988,17 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
return CURLE_OK;
}
+ /*
+ * If this connection isn't marked to force-close, leave it open if there
+ * are other users of it
+ */
+ if(!conn->bits.close &&
+ (conn->send_pipe->size + conn->recv_pipe->size)) {
+ DEBUGF(infof(data, "Curl_disconnect, usecounter: %d\n",
+ conn->send_pipe->size + conn->recv_pipe->size));
+ return CURLE_OK;
+ }
+
if(conn->dns_entry != NULL) {
Curl_resolv_unlock(data, conn->dns_entry);
conn->dns_entry = NULL;
@@ -2852,6 +3022,8 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
free_fixed_hostname(&conn->host);
free_fixed_hostname(&conn->conn_to_host);
free_fixed_hostname(&conn->proxy);
+ free_fixed_hostname(&conn->http_proxy.host);
+ free_fixed_hostname(&conn->socks_proxy.host);
Curl_ssl_close(conn, FIRSTSOCKET);
@@ -2876,7 +3048,7 @@ static bool SocketIsDead(curl_socket_t sock)
int sval;
bool ret_val = TRUE;
- sval = Curl_socket_ready(sock, CURL_SOCKET_BAD, 0);
+ sval = SOCKET_READABLE(sock, 0);
if(sval == 0)
/* timeout */
ret_val = FALSE;
@@ -2892,7 +3064,8 @@ static bool IsPipeliningPossible(const struct Curl_easy *handle,
const struct connectdata *conn)
{
/* If a HTTP protocol and pipelining is enabled */
- if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
+ if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
+ (!conn->bits.protoconnstart || !conn->bits.close)) {
if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
(handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
@@ -3009,8 +3182,8 @@ Curl_oldest_idle_connection(struct Curl_easy *data)
struct curl_hash_iterator iter;
struct curl_llist_element *curr;
struct curl_hash_element *he;
- long highscore=-1;
- long score;
+ time_t highscore=-1;
+ time_t score;
struct timeval now;
struct connectdata *conn_candidate = NULL;
struct connectbundle *bundle;
@@ -3047,6 +3220,21 @@ Curl_oldest_idle_connection(struct Curl_easy *data)
return conn_candidate;
}
+static bool
+proxy_info_matches(const struct proxy_info* data,
+ const struct proxy_info* needle)
+{
+ if((data->proxytype == needle->proxytype) &&
+ (data->port == needle->port) &&
+ Curl_safe_strcasecompare(data->host.name, needle->host.name) &&
+ Curl_safe_strcasecompare(data->user, needle->user) &&
+ Curl_safe_strcasecompare(data->passwd, needle->passwd))
+ return TRUE;
+
+ return FALSE;
+}
+
+
/*
* This function finds the connection in the connection
* bundle that has been unused for the longest time.
@@ -3059,8 +3247,8 @@ find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
struct connectbundle *bundle)
{
struct curl_llist_element *curr;
- long highscore=-1;
- long score;
+ time_t highscore=-1;
+ time_t score;
struct timeval now;
struct connectdata *conn_candidate = NULL;
struct connectdata *conn;
@@ -3142,7 +3330,7 @@ static int call_disconnect_if_dead(struct connectdata *conn,
static void prune_dead_connections(struct Curl_easy *data)
{
struct timeval now = Curl_tvnow();
- long elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
+ time_t elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
if(elapsed >= 1000L) {
Curl_conncache_foreach(data->state.conn_cache, data,
@@ -3267,6 +3455,8 @@ ConnectionExists(struct Curl_easy *data,
pipeLen = check->send_pipe->size + check->recv_pipe->size;
if(canPipeline) {
+ if(check->bits.protoconnstart && check->bits.close)
+ continue;
if(!check->bits.multiplex) {
/* If not multiplexing, make sure the pipe has only GET requests */
@@ -3319,6 +3509,17 @@ ConnectionExists(struct Curl_easy *data,
}
}
+#ifdef USE_UNIX_SOCKETS
+ if(needle->unix_domain_socket) {
+ if(!check->unix_domain_socket)
+ continue;
+ if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
+ continue;
+ }
+ else if(check->unix_domain_socket)
+ continue;
+#endif
+
if((needle->handler->flags&PROTOPT_SSL) !=
(check->handler->flags&PROTOPT_SSL))
/* don't do mixed SSL and non-SSL connections */
@@ -3327,23 +3528,12 @@ ConnectionExists(struct Curl_easy *data,
/* except protocols that have been upgraded via TLS */
continue;
- if(needle->handler->flags&PROTOPT_SSL) {
- if((data->set.ssl.verifypeer != check->verifypeer) ||
- (data->set.ssl.verifyhost != check->verifyhost))
- continue;
- }
-
- if(needle->bits.proxy != check->bits.proxy)
- /* don't do mixed proxy and non-proxy connections */
+ if(needle->bits.httpproxy != check->bits.httpproxy ||
+ needle->bits.socksproxy != check->bits.socksproxy)
continue;
- if(needle->bits.proxy &&
- (needle->proxytype != check->proxytype ||
- needle->bits.httpproxy != check->bits.httpproxy ||
- needle->bits.tunnel_proxy != check->bits.tunnel_proxy ||
- !Curl_raw_equal(needle->proxy.name, check->proxy.name) ||
- needle->port != check->port))
- /* don't mix connections that use different proxies */
+ if(needle->bits.socksproxy && !proxy_info_matches(&needle->socks_proxy,
+ &check->socks_proxy))
continue;
if(needle->bits.conn_to_host != check->bits.conn_to_host)
@@ -3356,6 +3546,33 @@ ConnectionExists(struct Curl_easy *data,
* connections that don't use this feature */
continue;
+ if(needle->bits.httpproxy) {
+ if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
+ continue;
+
+ if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
+ continue;
+
+ if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) {
+ /* use https proxy */
+ if(needle->handler->flags&PROTOPT_SSL) {
+ /* use double layer ssl */
+ if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
+ &check->proxy_ssl_config))
+ continue;
+ if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete)
+ continue;
+ }
+ else {
+ if(!Curl_ssl_config_matches(&needle->ssl_config,
+ &check->ssl_config))
+ continue;
+ if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete)
+ continue;
+ }
+ }
+ }
+
if(!canPipeline && check->inuse)
/* this request can't be pipelined but the checked connection is
already in use so we skip it */
@@ -3375,35 +3592,35 @@ ConnectionExists(struct Curl_easy *data,
*/
if((check->localport != needle->localport) ||
(check->localportrange != needle->localportrange) ||
- !check->localdev ||
- !needle->localdev ||
- strcmp(check->localdev, needle->localdev))
+ (needle->localdev &&
+ (!check->localdev || strcmp(check->localdev, needle->localdev))))
continue;
}
if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
/* This protocol requires credentials per connection,
so verify that we're using the same name and password as well */
- if(!strequal(needle->user, check->user) ||
- !strequal(needle->passwd, check->passwd)) {
+ if(strcmp(needle->user, check->user) ||
+ strcmp(needle->passwd, check->passwd)) {
/* one of them was different */
continue;
}
}
if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) ||
- (needle->bits.httpproxy && needle->bits.tunnel_proxy)) {
+ needle->bits.tunnel_proxy) {
/* The requested connection does not use a HTTP proxy or it uses SSL or
- it is a non-SSL protocol tunneled over the same HTTP proxy name and
- port number */
- if((Curl_raw_equal(needle->handler->scheme, check->handler->scheme) ||
+ it is a non-SSL protocol tunneled or it is a non-SSL protocol which
+ is allowed to be upgraded via TLS */
+
+ if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
(get_protocol_family(check->handler->protocol) ==
needle->handler->protocol && check->tls_upgraded)) &&
- (!needle->bits.conn_to_host || Curl_raw_equal(
+ (!needle->bits.conn_to_host || strcasecompare(
needle->conn_to_host.name, check->conn_to_host.name)) &&
(!needle->bits.conn_to_port ||
needle->conn_to_port == check->conn_to_port) &&
- Curl_raw_equal(needle->host.name, check->host.name) &&
+ strcasecompare(needle->host.name, check->host.name) &&
needle->remote_port == check->remote_port) {
/* The schemes match or the the protocol family is the same and the
previous connection was TLS upgraded, and the hostname and host
@@ -3445,8 +3662,8 @@ ConnectionExists(struct Curl_easy *data,
possible. (Especially we must not reuse the same connection if
partway through a handshake!) */
if(wantNTLMhttp) {
- if(!strequal(needle->user, check->user) ||
- !strequal(needle->passwd, check->passwd))
+ if(strcmp(needle->user, check->user) ||
+ strcmp(needle->passwd, check->passwd))
continue;
}
else if(check->ntlm.state != NTLMSTATE_NONE) {
@@ -3456,12 +3673,13 @@ ConnectionExists(struct Curl_easy *data,
/* Same for Proxy NTLM authentication */
if(wantProxyNTLMhttp) {
- /* Both check->proxyuser and check->proxypasswd can be NULL */
- if(!check->proxyuser || !check->proxypasswd)
+ /* Both check->http_proxy.user and check->http_proxy.passwd can be
+ * NULL */
+ if(!check->http_proxy.user || !check->http_proxy.passwd)
continue;
- if(!strequal(needle->proxyuser, check->proxyuser) ||
- !strequal(needle->proxypasswd, check->proxypasswd))
+ if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
+ strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
continue;
}
else if(check->proxyntlm.state != NTLMSTATE_NONE) {
@@ -3565,51 +3783,48 @@ ConnectionExists(struct Curl_easy *data,
Note: this function's sub-functions call failf()
*/
-CURLcode Curl_connected_proxy(struct connectdata *conn,
- int sockindex)
+CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex)
{
- if(!conn->bits.proxy || sockindex)
- /* this magic only works for the primary socket as the secondary is used
- for FTP only and it has FTP specific magic in ftp.c */
- return CURLE_OK;
+ CURLcode result = CURLE_OK;
- switch(conn->proxytype) {
+ if(conn->bits.socksproxy) {
#ifndef CURL_DISABLE_PROXY
- case CURLPROXY_SOCKS5:
- case CURLPROXY_SOCKS5_HOSTNAME:
- return Curl_SOCKS5(conn->proxyuser, conn->proxypasswd,
- conn->bits.conn_to_host ? conn->conn_to_host.name :
- conn->host.name,
- conn->bits.conn_to_port ? conn->conn_to_port :
- conn->remote_port,
- FIRSTSOCKET, conn);
-
- case CURLPROXY_SOCKS4:
- return Curl_SOCKS4(conn->proxyuser,
- conn->bits.conn_to_host ? conn->conn_to_host.name :
- conn->host.name,
- conn->bits.conn_to_port ? conn->conn_to_port :
- conn->remote_port,
- FIRSTSOCKET, conn, FALSE);
-
- case CURLPROXY_SOCKS4A:
- return Curl_SOCKS4(conn->proxyuser,
- conn->bits.conn_to_host ? conn->conn_to_host.name :
- conn->host.name,
- conn->bits.conn_to_port ? conn->conn_to_port :
- conn->remote_port,
- FIRSTSOCKET, conn, TRUE);
+ const char * const host = conn->bits.conn_to_host ?
+ conn->conn_to_host.name :
+ conn->bits.httpproxy ?
+ conn->http_proxy.host.name :
+ sockindex == SECONDARYSOCKET ?
+ conn->secondaryhostname : conn->host.name;
+ const int port = conn->bits.conn_to_port ? conn->conn_to_port :
+ conn->bits.httpproxy ?
+ (int)conn->http_proxy.port :
+ sockindex == SECONDARYSOCKET ?
+ conn->secondary_port : conn->remote_port;
+ conn->bits.socksproxy_connecting = TRUE;
+ switch(conn->socks_proxy.proxytype) {
+ case CURLPROXY_SOCKS5:
+ case CURLPROXY_SOCKS5_HOSTNAME:
+ result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
+ host, port, sockindex, conn);
+ break;
+ case CURLPROXY_SOCKS4:
+ case CURLPROXY_SOCKS4A:
+ result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
+ conn);
+ break;
+
+ default:
+ failf(conn->data, "unknown proxytype option given");
+ result = CURLE_COULDNT_CONNECT;
+ } /* switch proxytype */
+ conn->bits.socksproxy_connecting = FALSE;
+#else
+ (void)sockindex;
#endif /* CURL_DISABLE_PROXY */
- case CURLPROXY_HTTP:
- case CURLPROXY_HTTP_1_0:
- /* do nothing here. handled later. */
- break;
- default:
- break;
- } /* switch proxytype */
+ }
- return CURLE_OK;
+ return result;
}
/*
@@ -3620,7 +3835,9 @@ void Curl_verboseconnect(struct connectdata *conn)
{
if(conn->data->set.verbose)
infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
- conn->bits.proxy ? conn->proxy.dispname : conn->host.dispname,
+ conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
+ conn->bits.httpproxy ? conn->http_proxy.host.dispname :
+ conn->host.dispname,
conn->ip_addr_str, conn->port, conn->connection_id);
}
#endif
@@ -3710,10 +3927,14 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
if(!conn->bits.protoconnstart) {
- result = Curl_proxy_connect(conn);
+ result = Curl_proxy_connect(conn, FIRSTSOCKET);
if(result)
return result;
+ if(CONNECT_FIRSTSOCKET_PROXY_SSL())
+ /* wait for HTTPS proxy SSL initialization to complete */
+ return CURLE_OK;
+
if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
(conn->tunnel_state[FIRSTSOCKET] != TUNNEL_COMPLETE))
/* when using an HTTP tunnel proxy, await complete tunnel establishment
@@ -3743,7 +3964,7 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
*/
static bool is_ASCII_name(const char *hostname)
{
- const unsigned char *ch = (const unsigned char*)hostname;
+ const unsigned char *ch = (const unsigned char *)hostname;
while(*ch) {
if(*ch++ & 0x80)
@@ -3752,58 +3973,15 @@ static bool is_ASCII_name(const char *hostname)
return TRUE;
}
-#ifdef USE_LIBIDN
-/*
- * Check if characters in hostname is allowed in Top Level Domain.
- */
-static bool tld_check_name(struct Curl_easy *data,
- const char *ace_hostname)
-{
- size_t err_pos;
- char *uc_name = NULL;
- int rc;
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- const char *tld_errmsg = "<no msg>";
-#else
- (void)data;
-#endif
-
- /* Convert (and downcase) ACE-name back into locale's character set */
- rc = idna_to_unicode_lzlz(ace_hostname, &uc_name, 0);
- if(rc != IDNA_SUCCESS)
- return FALSE;
-
- /* Warning: err_pos receives "the decoded character offset rather than the
- byte position in the string." And as of libidn 1.32 that character offset
- is for UTF-8, even if the passed in string is another locale. */
- rc = tld_check_lz(uc_name, &err_pos, NULL);
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
-#ifdef HAVE_TLD_STRERROR
- if(rc != TLD_SUCCESS)
- tld_errmsg = tld_strerror((Tld_rc)rc);
-#endif
- if(rc != TLD_SUCCESS)
- infof(data, "WARNING: TLD check for %s failed; %s\n",
- uc_name, tld_errmsg);
-#endif /* CURL_DISABLE_VERBOSE_STRINGS */
- if(uc_name)
- idn_free(uc_name);
- if(rc != TLD_SUCCESS)
- return FALSE;
-
- return TRUE;
-}
-#endif
-
/*
* Perform any necessary IDN conversion of hostname
*/
-static void fix_hostname(struct Curl_easy *data,
- struct connectdata *conn, struct hostname *host)
+static void fix_hostname(struct connectdata *conn, struct hostname *host)
{
size_t len;
+ struct Curl_easy *data = conn->data;
-#ifndef USE_LIBIDN
+#ifndef USE_LIBIDN2
(void)data;
(void)conn;
#elif defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -3821,25 +3999,18 @@ static void fix_hostname(struct Curl_easy *data,
/* Check name for non-ASCII and convert hostname to ACE form if we can */
if(!is_ASCII_name(host->name)) {
-#ifdef USE_LIBIDN
- if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) {
+#ifdef USE_LIBIDN2
+ if(idn2_check_version(IDN2_VERSION)) {
char *ace_hostname = NULL;
-
- int rc = idna_to_ascii_lz(host->name, &ace_hostname, 0);
- infof(data, "Input domain encoded as `%s'\n",
- stringprep_locale_charset());
- if(rc == IDNA_SUCCESS) {
- /* tld_check_name() displays a warning if the host name contains
- "illegal" characters for this TLD */
- (void)tld_check_name(data, ace_hostname);
-
- host->encalloc = ace_hostname;
+ int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, 0);
+ if(rc == IDN2_OK) {
+ host->encalloc = (char *)ace_hostname;
/* change the name pointer to point to the encoded hostname */
host->name = host->encalloc;
}
else
infof(data, "Failed to convert %s to ACE; %s\n", host->name,
- Curl_idn_strerror(conn, rc));
+ idn2_strerror(rc));
}
#elif defined(USE_WIN32_IDN)
char *ace_hostname = NULL;
@@ -3862,9 +4033,9 @@ static void fix_hostname(struct Curl_easy *data,
*/
static void free_fixed_hostname(struct hostname *host)
{
-#if defined(USE_LIBIDN)
+#if defined(USE_LIBIDN2)
if(host->encalloc) {
- idn_free(host->encalloc); /* must be freed with idn_free() since this was
+ idn2_free(host->encalloc); /* must be freed with idn2_free() since this was
allocated by libidn */
host->encalloc = NULL;
}
@@ -3922,12 +4093,14 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->data = data; /* Setup the association between this connection
and the Curl_easy */
- conn->proxytype = data->set.proxytype; /* type */
+ conn->http_proxy.proxytype = data->set.proxytype;
+ conn->socks_proxy.proxytype = data->set.socks_proxytype;
#ifdef CURL_DISABLE_PROXY
conn->bits.proxy = FALSE;
conn->bits.httpproxy = FALSE;
+ conn->bits.socksproxy = FALSE;
conn->bits.proxy_user_passwd = FALSE;
conn->bits.tunnel_proxy = FALSE;
@@ -3938,11 +4111,20 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->bits.proxy = (data->set.str[STRING_PROXY] &&
*data->set.str[STRING_PROXY]) ? TRUE : FALSE;
conn->bits.httpproxy = (conn->bits.proxy &&
- (conn->proxytype == CURLPROXY_HTTP ||
- conn->proxytype == CURLPROXY_HTTP_1_0)) ?
- TRUE : FALSE;
- conn->bits.proxy_user_passwd = (data->set.str[STRING_PROXYUSERNAME]) ?
- TRUE : FALSE;
+ (conn->http_proxy.proxytype == CURLPROXY_HTTP ||
+ conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 ||
+ conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ?
+ TRUE : FALSE;
+ conn->bits.socksproxy = (conn->bits.proxy &&
+ !conn->bits.httpproxy) ? TRUE : FALSE;
+
+ if(data->set.str[STRING_SOCKS_PROXY] && *data->set.str[STRING_SOCKS_PROXY]) {
+ conn->bits.proxy = TRUE;
+ conn->bits.socksproxy = TRUE;
+ }
+
+ conn->bits.proxy_user_passwd =
+ (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE;
conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
#endif /* CURL_DISABLE_PROXY */
@@ -3951,8 +4133,10 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
- conn->verifypeer = data->set.ssl.verifypeer;
- conn->verifyhost = data->set.ssl.verifyhost;
+ conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
+ conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
+ conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
+ conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
conn->ip_version = data->set.ipver;
@@ -4022,7 +4206,7 @@ static CURLcode findprotocol(struct Curl_easy *data,
variables based on the URL. Now that the handler may be changed later
when the protocol specific setup function is called. */
for(pp = protocols; (p = *pp) != NULL; pp++) {
- if(Curl_raw_equal(p->scheme, protostr)) {
+ if(strcasecompare(p->scheme, protostr)) {
/* Protocol found in table. Check if allowed */
if(!(data->set.allowed_protocols & p->protocol))
/* nope, get out */
@@ -4091,7 +4275,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
************************************************************/
if((2 == sscanf(data->change.url, "%15[^:]:%[^\n]",
protobuf, path)) &&
- Curl_raw_equal(protobuf, "file")) {
+ strcasecompare(protobuf, "file")) {
if(path[0] == '/' && path[1] == '/') {
/* Allow omitted hostname (e.g. file:/<path>). This is not strictly
* speaking a valid file: URL by RFC 1738, but treating file:/<path> as
@@ -4108,33 +4292,38 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
* the URL protocols specified in RFC 1738
*/
if(path[0] != '/') {
- /* the URL included a host name, we ignore host names in file:// URLs
- as the standards don't define what to do with them */
- char *ptr=strchr(path, '/');
- if(ptr) {
- /* there was a slash present
-
- RFC1738 (section 3.1, page 5) says:
-
- The rest of the locator consists of data specific to the scheme,
- and is known as the "url-path". It supplies the details of how the
- specified resource can be accessed. Note that the "/" between the
- host (or port) and the url-path is NOT part of the url-path.
-
- As most agents use file://localhost/foo to get '/foo' although the
- slash preceding foo is a separator and not a slash for the path,
- a URL as file://localhost//foo must be valid as well, to refer to
- the same file with an absolute path.
- */
+ /* the URL includes a host name, it must match "localhost" or
+ "127.0.0.1" to be valid */
+ char *ptr;
+ if(!checkprefix("localhost/", path) &&
+ !checkprefix("127.0.0.1/", path)) {
+ failf(data, "Valid host name with slash missing in URL");
+ return CURLE_URL_MALFORMAT;
+ }
+ ptr = &path[9]; /* now points to the slash after the host */
- if(ptr[1] && ('/' == ptr[1]))
- /* if there was two slashes, we skip the first one as that is then
- used truly as a separator */
- ptr++;
+ /* there was a host name and slash present
- /* This cannot be made with strcpy, as the memory chunks overlap! */
- memmove(path, ptr, strlen(ptr)+1);
- }
+ RFC1738 (section 3.1, page 5) says:
+
+ The rest of the locator consists of data specific to the scheme,
+ and is known as the "url-path". It supplies the details of how the
+ specified resource can be accessed. Note that the "/" between the
+ host (or port) and the url-path is NOT part of the url-path.
+
+ As most agents use file://localhost/foo to get '/foo' although the
+ slash preceding foo is a separator and not a slash for the path,
+ a URL as file://localhost//foo must be valid as well, to refer to
+ the same file with an absolute path.
+ */
+
+ if('/' == ptr[1])
+ /* if there was two slashes, we skip the first one as that is then
+ used truly as a separator */
+ ptr++;
+
+ /* This cannot be made with strcpy, as the memory chunks overlap! */
+ memmove(path, ptr, strlen(ptr)+1);
}
protop = "file"; /* protocol string */
@@ -4145,7 +4334,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
path[0]=0;
rc = sscanf(data->change.url,
- "%15[^\n:]:%3[/]%[^\n/?]%[^\n]",
+ "%15[^\n:]:%3[/]%[^\n/?#]%[^\n]",
protobuf, slashbuf, conn->host.name, path);
if(2 == rc) {
failf(data, "Bad URL");
@@ -4157,7 +4346,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
* The URL was badly formatted, let's try the browser-style _without_
* protocol specified like 'http://'.
*/
- rc = sscanf(data->change.url, "%[^\n/?]%[^\n]", conn->host.name, path);
+ rc = sscanf(data->change.url, "%[^\n/?#]%[^\n]", conn->host.name, path);
if(1 > rc) {
/*
* We couldn't even get this format.
@@ -4262,10 +4451,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
}
/* If the URL is malformatted (missing a '/' after hostname before path) we
- * insert a slash here. The only letter except '/' we accept to start a path
- * is '?'.
+ * insert a slash here. The only letters except '/' that can start a path is
+ * '?' and '#' - as controlled by the two sscanf() patterns above.
*/
- if(path[0] == '?') {
+ if(path[0] != '/') {
/* We need this function to deal with overlapping memory areas. We know
that the memory area 'path' points to is 'urllen' bytes big and that
is bigger than the path. Use +1 to move the zero byte too. */
@@ -4516,7 +4705,7 @@ void Curl_free_request_state(struct Curl_easy *data)
* Checks if the host is in the noproxy list. returns true if it matches
* and therefore the proxy should NOT be used.
****************************************************************/
-static bool check_noproxy(const char* name, const char* no_proxy)
+static bool check_noproxy(const char *name, const char *no_proxy)
{
/* no_proxy=domain1.dom,host.domain2.dom
* (a comma-separated list of hosts which should
@@ -4525,13 +4714,13 @@ static bool check_noproxy(const char* name, const char* no_proxy)
*/
size_t tok_start;
size_t tok_end;
- const char* separator = ", ";
+ const char *separator = ", ";
size_t no_proxy_len;
size_t namelen;
char *endptr;
if(no_proxy && no_proxy[0]) {
- if(Curl_raw_equal("*", no_proxy)) {
+ if(strcasecompare("*", no_proxy)) {
return TRUE;
}
@@ -4569,7 +4758,7 @@ static bool check_noproxy(const char* name, const char* no_proxy)
if((tok_end - tok_start) <= namelen) {
/* Match the last part of the name to the domain we are checking. */
const char *checkn = name + namelen - (tok_end - tok_start);
- if(Curl_raw_nequal(no_proxy + tok_start, checkn,
+ if(strncasecompare(no_proxy + tok_start, checkn,
tok_end - tok_start)) {
if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
/* We either have an exact match, or the previous character is a .
@@ -4648,7 +4837,7 @@ static char *detect_proxy(struct connectdata *conn)
* This can cause 'internal' http/ftp requests to be
* arbitrarily redirected by any external attacker.
*/
- if(!prox && !Curl_raw_equal("http_proxy", proxy_env)) {
+ if(!prox && !strcasecompare("http_proxy", proxy_env)) {
/* There was no lowercase variable, try the uppercase version: */
Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
prox=curl_getenv(proxy_env);
@@ -4679,7 +4868,8 @@ static char *detect_proxy(struct connectdata *conn)
* that may exist registered to the same proxy host.
*/
static CURLcode parse_proxy(struct Curl_easy *data,
- struct connectdata *conn, char *proxy)
+ struct connectdata *conn, char *proxy,
+ curl_proxytype proxytype)
{
char *prox_portno;
char *endofprot;
@@ -4688,6 +4878,10 @@ static CURLcode parse_proxy(struct Curl_easy *data,
char *proxyptr;
char *portptr;
char *atsign;
+ long port = -1;
+ char *proxyuser = NULL;
+ char *proxypasswd = NULL;
+ bool sockstype;
/* We do the proxy host string parsing here. We want the host name and the
* port name. Accept a protocol:// prefix
@@ -4697,64 +4891,41 @@ static CURLcode parse_proxy(struct Curl_easy *data,
endofprot = strstr(proxy, "://");
if(endofprot) {
proxyptr = endofprot+3;
- if(checkprefix("socks5h", proxy))
- conn->proxytype = CURLPROXY_SOCKS5_HOSTNAME;
+ if(checkprefix("https", proxy))
+ proxytype = CURLPROXY_HTTPS;
+ else if(checkprefix("socks5h", proxy))
+ proxytype = CURLPROXY_SOCKS5_HOSTNAME;
else if(checkprefix("socks5", proxy))
- conn->proxytype = CURLPROXY_SOCKS5;
+ proxytype = CURLPROXY_SOCKS5;
else if(checkprefix("socks4a", proxy))
- conn->proxytype = CURLPROXY_SOCKS4A;
+ proxytype = CURLPROXY_SOCKS4A;
else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy))
- conn->proxytype = CURLPROXY_SOCKS4;
- /* Any other xxx:// : change to http proxy */
+ proxytype = CURLPROXY_SOCKS4;
+ else if(checkprefix("http:", proxy))
+ ; /* leave it as HTTP or HTTP/1.0 */
+ else {
+ /* Any other xxx:// reject! */
+ failf(data, "Unsupported proxy scheme for \'%s\'", proxy);
+ return CURLE_COULDNT_CONNECT;
+ }
}
else
proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
+ sockstype = proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
+ proxytype == CURLPROXY_SOCKS5 ||
+ proxytype == CURLPROXY_SOCKS4A ||
+ proxytype == CURLPROXY_SOCKS4;
+
/* Is there a username and password given in this proxy url? */
atsign = strchr(proxyptr, '@');
if(atsign) {
- char *proxyuser = NULL;
- char *proxypasswd = NULL;
CURLcode result =
parse_login_details(proxyptr, atsign - proxyptr,
- &proxyuser, &proxypasswd, NULL);
- if(!result) {
- /* found user and password, rip them out. note that we are
- unescaping them, as there is otherwise no way to have a
- username or password with reserved characters like ':' in
- them. */
- Curl_safefree(conn->proxyuser);
- if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH)
- conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
- else
- conn->proxyuser = strdup("");
-
- if(!conn->proxyuser)
- result = CURLE_OUT_OF_MEMORY;
- else {
- Curl_safefree(conn->proxypasswd);
- if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
- conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
- else
- conn->proxypasswd = strdup("");
-
- if(!conn->proxypasswd)
- result = CURLE_OUT_OF_MEMORY;
- }
-
- if(!result) {
- conn->bits.proxy_user_passwd = TRUE; /* enable it */
- atsign++; /* the right side of the @-letter */
-
- proxyptr = atsign; /* now use this instead */
- }
- }
-
- free(proxyuser);
- free(proxypasswd);
-
+ &proxyuser, &proxypasswd, NULL);
if(result)
return result;
+ proxyptr = atsign + 1;
}
/* start scanning for port number at this point */
@@ -4791,7 +4962,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
prox_portno = strchr(portptr, ':');
if(prox_portno) {
char *endp = NULL;
- long port = 0;
+
*prox_portno = 0x0; /* cut off number from host name */
prox_portno ++;
/* now set the local port number */
@@ -4825,15 +4996,53 @@ static CURLcode parse_proxy(struct Curl_easy *data,
if(data->set.proxyport)
/* None given in the proxy string, then get the default one if it is
given */
- conn->port = data->set.proxyport;
+ port = data->set.proxyport;
}
- /* now, clone the cleaned proxy host name */
- conn->proxy.rawalloc = strdup(proxyptr);
- conn->proxy.name = conn->proxy.rawalloc;
+ if(*proxyptr) {
+ struct proxy_info *proxyinfo =
+ sockstype ? &conn->socks_proxy : &conn->http_proxy;
+ proxyinfo->proxytype = proxytype;
- if(!conn->proxy.rawalloc)
- return CURLE_OUT_OF_MEMORY;
+ if(proxyuser) {
+ /* found user and password, rip them out. note that we are unescaping
+ them, as there is otherwise no way to have a username or password
+ with reserved characters like ':' in them. */
+ Curl_safefree(proxyinfo->user);
+ proxyinfo->user = curl_easy_unescape(data, proxyuser, 0, NULL);
+
+ if(!proxyinfo->user)
+ return CURLE_OUT_OF_MEMORY;
+
+ Curl_safefree(proxyinfo->passwd);
+ if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
+ proxyinfo->passwd = curl_easy_unescape(data, proxypasswd, 0, NULL);
+ else
+ proxyinfo->passwd = strdup("");
+
+ if(!proxyinfo->passwd)
+ return CURLE_OUT_OF_MEMORY;
+
+ conn->bits.proxy_user_passwd = TRUE; /* enable it */
+ }
+
+ if(port >= 0) {
+ proxyinfo->port = port;
+ if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
+ conn->port = port;
+ }
+
+ /* now, clone the cleaned proxy host name */
+ Curl_safefree(proxyinfo->host.rawalloc);
+ proxyinfo->host.rawalloc = strdup(proxyptr);
+ proxyinfo->host.name = proxyinfo->host.rawalloc;
+
+ if(!proxyinfo->host.rawalloc)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ Curl_safefree(proxyuser);
+ Curl_safefree(proxypasswd);
return CURLE_OK;
}
@@ -4846,6 +5055,7 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
{
char proxyuser[MAX_CURL_USER_LENGTH]="";
char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
+ CURLcode result;
if(data->set.str[STRING_PROXYUSERNAME] != NULL) {
strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME],
@@ -4858,15 +5068,12 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
}
- conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
- if(!conn->proxyuser)
- return CURLE_OUT_OF_MEMORY;
-
- conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
- if(!conn->proxypasswd)
- return CURLE_OUT_OF_MEMORY;
-
- return CURLE_OK;
+ result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
+ FALSE);
+ if(!result)
+ result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
+ NULL, FALSE);
+ return result;
}
#endif /* CURL_DISABLE_PROXY */
@@ -4940,9 +5147,8 @@ static CURLcode parse_url_login(struct Curl_easy *data,
conn->bits.user_passwd = TRUE; /* enable user+password */
/* Decode the user */
- newname = curl_easy_unescape(data, userp, 0, NULL);
- if(!newname) {
- result = CURLE_OUT_OF_MEMORY;
+ result = Curl_urldecode(data, userp, 0, &newname, NULL, FALSE);
+ if(result) {
goto out;
}
@@ -4952,9 +5158,9 @@ static CURLcode parse_url_login(struct Curl_easy *data,
if(passwdp) {
/* We have a password in the URL so decode it */
- char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL);
- if(!newpasswd) {
- result = CURLE_OUT_OF_MEMORY;
+ char *newpasswd;
+ result = Curl_urldecode(data, passwdp, 0, &newpasswd, NULL, FALSE);
+ if(result) {
goto out;
}
@@ -4964,9 +5170,9 @@ static CURLcode parse_url_login(struct Curl_easy *data,
if(optionsp) {
/* We have an options list in the URL so decode it */
- char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL);
- if(!newoptions) {
- result = CURLE_OUT_OF_MEMORY;
+ char *newoptions;
+ result = Curl_urldecode(data, optionsp, 0, &newoptions, NULL, FALSE);
+ if(result) {
goto out;
}
@@ -5457,7 +5663,8 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data,
if(!hostname_to_match)
return CURLE_OUT_OF_MEMORY;
hostname_to_match_len = strlen(hostname_to_match);
- host_match = curl_strnequal(ptr, hostname_to_match, hostname_to_match_len);
+ host_match = strncasecompare(ptr, hostname_to_match,
+ hostname_to_match_len);
free(hostname_to_match);
ptr += hostname_to_match_len;
@@ -5551,7 +5758,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
bool *async)
{
CURLcode result=CURLE_OK;
- long timeout_ms = Curl_timeleft(data, NULL, TRUE);
+ time_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
/*************************************************************
* Resolve the name of the server or proxy
@@ -5568,11 +5775,11 @@ static CURLcode resolve_server(struct Curl_easy *data,
struct Curl_dns_entry *hostaddr;
#ifdef USE_UNIX_SOCKETS
- if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
+ if(conn->unix_domain_socket) {
/* Unix domain sockets are local. The host gets ignored, just use the
* specified domain socket address. Do not cache "DNS entries". There is
* no DNS involved and we already have the filesystem path available */
- const char *path = data->set.str[STRING_UNIX_SOCKET_PATH];
+ const char *path = conn->unix_domain_socket;
hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
if(!hostaddr)
@@ -5593,7 +5800,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
}
else
#endif
- if(!conn->proxy.name || !*conn->proxy.name) {
+ if(!conn->bits.proxy) {
struct hostname *connhost;
if(conn->bits.conn_to_host)
connhost = &conn->conn_to_host;
@@ -5625,8 +5832,11 @@ static CURLcode resolve_server(struct Curl_easy *data,
else {
/* This is a proxy that hasn't been resolved yet. */
+ struct hostname * const host = conn->bits.socksproxy ?
+ &conn->socks_proxy.host : &conn->http_proxy.host;
+
/* resolve proxy */
- rc = Curl_resolv_timeout(conn, conn->proxy.name, (int)conn->port,
+ rc = Curl_resolv_timeout(conn, host->name, (int)conn->port,
&hostaddr, timeout_ms);
if(rc == CURLRESOLV_PENDING)
@@ -5636,7 +5846,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
result = CURLE_OPERATION_TIMEDOUT;
else if(!hostaddr) {
- failf(data, "Couldn't resolve proxy '%s'", conn->proxy.dispname);
+ failf(data, "Couldn't resolve proxy '%s'", host->dispname);
result = CURLE_COULDNT_RESOLVE_PROXY;
/* don't return yet, we need to clean up the timeout first */
}
@@ -5656,12 +5866,18 @@ static CURLcode resolve_server(struct Curl_easy *data,
static void reuse_conn(struct connectdata *old_conn,
struct connectdata *conn)
{
+ free_fixed_hostname(&old_conn->http_proxy.host);
+ free_fixed_hostname(&old_conn->socks_proxy.host);
free_fixed_hostname(&old_conn->proxy);
+
+ free(old_conn->http_proxy.host.rawalloc);
+ free(old_conn->socks_proxy.host.rawalloc);
free(old_conn->proxy.rawalloc);
/* free the SSL config struct from this connection struct as this was
allocated in vain and is targeted for destruction */
- Curl_free_ssl_config(&old_conn->ssl_config);
+ Curl_free_primary_ssl_config(&old_conn->ssl_config);
+ Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
conn->data = old_conn->data;
@@ -5681,12 +5897,18 @@ static void reuse_conn(struct connectdata *old_conn,
conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
if(conn->bits.proxy_user_passwd) {
/* use the new proxy user name and proxy password though */
- Curl_safefree(conn->proxyuser);
- Curl_safefree(conn->proxypasswd);
- conn->proxyuser = old_conn->proxyuser;
- conn->proxypasswd = old_conn->proxypasswd;
- old_conn->proxyuser = NULL;
- old_conn->proxypasswd = NULL;
+ Curl_safefree(conn->http_proxy.user);
+ Curl_safefree(conn->socks_proxy.user);
+ Curl_safefree(conn->http_proxy.passwd);
+ Curl_safefree(conn->socks_proxy.passwd);
+ conn->http_proxy.user = old_conn->http_proxy.user;
+ conn->socks_proxy.user = old_conn->socks_proxy.user;
+ conn->http_proxy.passwd = old_conn->http_proxy.passwd;
+ conn->socks_proxy.passwd = old_conn->socks_proxy.passwd;
+ old_conn->http_proxy.user = NULL;
+ old_conn->socks_proxy.user = NULL;
+ old_conn->http_proxy.passwd = NULL;
+ old_conn->socks_proxy.passwd = NULL;
}
/* host can change, when doing keepalive with a proxy or if the case is
@@ -5712,8 +5934,10 @@ static void reuse_conn(struct connectdata *old_conn,
Curl_safefree(old_conn->user);
Curl_safefree(old_conn->passwd);
- Curl_safefree(old_conn->proxyuser);
- Curl_safefree(old_conn->proxypasswd);
+ Curl_safefree(old_conn->http_proxy.user);
+ Curl_safefree(old_conn->socks_proxy.user);
+ Curl_safefree(old_conn->http_proxy.passwd);
+ Curl_safefree(old_conn->socks_proxy.passwd);
Curl_safefree(old_conn->localdev);
Curl_llist_destroy(old_conn->send_pipe, NULL);
@@ -5723,6 +5947,10 @@ static void reuse_conn(struct connectdata *old_conn,
old_conn->recv_pipe = NULL;
Curl_safefree(old_conn->master_buffer);
+
+#ifdef USE_UNIX_SOCKETS
+ Curl_safefree(old_conn->unix_domain_socket);
+#endif
}
/**
@@ -5754,6 +5982,7 @@ static CURLcode create_conn(struct Curl_easy *data,
char *options = NULL;
bool reuse;
char *proxy = NULL;
+ char *socksproxy = NULL;
bool prot_missing = FALSE;
bool connections_available = TRUE;
bool force_reuse = FALSE;
@@ -5920,18 +6149,35 @@ static CURLcode create_conn(struct Curl_easy *data,
}
}
+ if(data->set.str[STRING_SOCKS_PROXY]) {
+ socksproxy = strdup(data->set.str[STRING_SOCKS_PROXY]);
+ /* if global socks proxy is set, this is it */
+ if(NULL == socksproxy) {
+ failf(data, "memory shortage");
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ }
+
if(data->set.str[STRING_NOPROXY] &&
check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) {
- free(proxy); /* proxy is in exception list */
- proxy = NULL;
+ Curl_safefree(proxy);
+ Curl_safefree(socksproxy);
}
- else if(!proxy)
+ else if(!proxy && !socksproxy)
proxy = detect_proxy(conn);
#ifdef USE_UNIX_SOCKETS
- if(proxy && data->set.str[STRING_UNIX_SOCKET_PATH]) {
- free(proxy); /* Unix domain sockets cannot be proxied, so disable it */
- proxy = NULL;
+ if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
+ if(proxy) {
+ free(proxy); /* Unix domain sockets cannot be proxied, so disable it */
+ proxy = NULL;
+ }
+ conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
+ if(conn->unix_domain_socket == NULL) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
}
#endif
@@ -5940,23 +6186,36 @@ static CURLcode create_conn(struct Curl_easy *data,
protocol doesn't work with network */
proxy = NULL;
}
+ if(socksproxy && (!*socksproxy ||
+ (conn->handler->flags & PROTOPT_NONETWORK))) {
+ free(socksproxy); /* Don't bother with an empty socks proxy string or if
+ the protocol doesn't work with network */
+ socksproxy = NULL;
+ }
/***********************************************************************
* If this is supposed to use a proxy, we need to figure out the proxy host
* name, proxy type and port number, so that we can re-use an existing
* connection that may exist registered to the same proxy host.
***********************************************************************/
- if(proxy) {
- result = parse_proxy(data, conn, proxy);
-
- free(proxy); /* parse_proxy copies the proxy string */
- proxy = NULL;
+ if(proxy || socksproxy) {
+ if(proxy) {
+ result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
+ Curl_safefree(proxy); /* parse_proxy copies the proxy string */
+ if(result)
+ goto out;
+ }
- if(result)
- goto out;
+ if(socksproxy) {
+ result = parse_proxy(data, conn, socksproxy,
+ conn->socks_proxy.proxytype);
+ /* parse_proxy copies the socks proxy string */
+ Curl_safefree(socksproxy);
+ if(result)
+ goto out;
+ }
- if((conn->proxytype == CURLPROXY_HTTP) ||
- (conn->proxytype == CURLPROXY_HTTP_1_0)) {
+ if(conn->http_proxy.host.rawalloc) {
#ifdef CURL_DISABLE_HTTP
/* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
result = CURLE_UNSUPPORTED_PROTOCOL;
@@ -5975,12 +6234,34 @@ static CURLcode create_conn(struct Curl_easy *data,
conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
}
- conn->bits.proxy = TRUE;
+
+ if(conn->socks_proxy.host.rawalloc) {
+ if(!conn->http_proxy.host.rawalloc) {
+ /* once a socks proxy */
+ if(!conn->socks_proxy.user) {
+ conn->socks_proxy.user = conn->http_proxy.user;
+ conn->http_proxy.user = NULL;
+ Curl_safefree(conn->socks_proxy.passwd);
+ conn->socks_proxy.passwd = conn->http_proxy.passwd;
+ conn->http_proxy.passwd = NULL;
+ }
+ }
+ conn->bits.socksproxy = TRUE;
+ }
+ else
+ conn->bits.socksproxy = FALSE; /* not a socks proxy */
}
else {
+ conn->bits.socksproxy = FALSE;
+ conn->bits.httpproxy = FALSE;
+ }
+ conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
+
+ if(!conn->bits.proxy) {
/* we aren't using the proxy after all... */
conn->bits.proxy = FALSE;
conn->bits.httpproxy = FALSE;
+ conn->bits.socksproxy = FALSE;
conn->bits.proxy_user_passwd = FALSE;
conn->bits.tunnel_proxy = FALSE;
}
@@ -6021,18 +6302,18 @@ static CURLcode create_conn(struct Curl_easy *data,
/*************************************************************
* IDN-fix the hostnames
*************************************************************/
- fix_hostname(data, conn, &conn->host);
+ fix_hostname(conn, &conn->host);
if(conn->bits.conn_to_host)
- fix_hostname(data, conn, &conn->conn_to_host);
+ fix_hostname(conn, &conn->conn_to_host);
if(conn->proxy.name && *conn->proxy.name)
- fix_hostname(data, conn, &conn->proxy);
+ fix_hostname(conn, &conn->proxy);
/*************************************************************
* Check whether the host and the "connect to host" are equal.
* Do this after the hostnames have been IDN-fixed .
*************************************************************/
if(conn->bits.conn_to_host &&
- Curl_raw_equal(conn->conn_to_host.name, conn->host.name)) {
+ strcasecompare(conn->conn_to_host.name, conn->host.name)) {
conn->bits.conn_to_host = FALSE;
}
@@ -6116,20 +6397,51 @@ static CURLcode create_conn(struct Curl_easy *data,
that will be freed as part of the Curl_easy struct, but all cloned
copies will be separately allocated.
*/
- data->set.ssl.CApath = data->set.str[STRING_SSL_CAPATH];
- data->set.ssl.CAfile = data->set.str[STRING_SSL_CAFILE];
- data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
- data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
- data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
- data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
- data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
- data->set.ssl.clientcert = data->set.str[STRING_CERT];
+ data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG];
+ data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
+ data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG];
+ data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
+ data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
+ data->set.proxy_ssl.primary.random_file =
+ data->set.str[STRING_SSL_RANDOM_FILE];
+ data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
+ data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
+ data->set.ssl.primary.cipher_list =
+ data->set.str[STRING_SSL_CIPHER_LIST_ORIG];
+ data->set.proxy_ssl.primary.cipher_list =
+ data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
+
+ data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
+ data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
+ data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
+ data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
+ data->set.ssl.cert = data->set.str[STRING_CERT_ORIG];
+ data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
+ data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
+ data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
+ data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
+ data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
+ data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
+ data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
+ data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG];
+ data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
+ data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG];
+ data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
#ifdef USE_TLS_SRP
- data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
- data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
+ data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG];
+ data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
+ data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG];
+ data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
#endif
- if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) {
+ if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
+ &conn->ssl_config)) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
+ &conn->proxy_ssl_config)) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
@@ -6186,7 +6498,9 @@ static CURLcode create_conn(struct Curl_easy *data,
infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
conn->connection_id,
conn->bits.proxy?"proxy":"host",
- conn->proxy.name?conn->proxy.dispname:conn->host.dispname);
+ conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
+ conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
+ conn->host.dispname);
}
else {
/* We have decided that we want a new connection. However, we may not
@@ -6317,6 +6631,7 @@ static CURLcode create_conn(struct Curl_easy *data,
free(options);
free(passwd);
free(user);
+ free(socksproxy);
free(proxy);
return result;
}
diff --git a/lib/url.h b/lib/url.h
index 90d9db3c..c1254f5d 100644
--- a/lib/url.h
+++ b/lib/url.h
@@ -76,5 +76,16 @@ CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex);
void Curl_verboseconnect(struct connectdata *conn);
#endif
+#define CONNECT_PROXY_SSL()\
+ (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
+ !conn->bits.proxy_ssl_connected[sockindex])
+
+#define CONNECT_FIRSTSOCKET_PROXY_SSL()\
+ (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
+ !conn->bits.proxy_ssl_connected[FIRSTSOCKET])
+
+#define CONNECT_SECONDARYSOCKET_PROXY_SSL()\
+ (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
+ !conn->bits.proxy_ssl_connected[SECONDARYSOCKET])
#endif /* HEADER_CURL_URL_H */
diff --git a/lib/urldata.h b/lib/urldata.h
index 3cf7ed9b..05f60031 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -316,6 +316,8 @@ struct ssl_connect_data {
#elif defined(USE_GSKIT)
gsk_handle handle;
int iocport;
+ int localfd;
+ int remotefd;
#elif defined(USE_AXTLS)
SSL_CTX* ssl_ctx;
SSL* ssl;
@@ -330,6 +332,7 @@ struct ssl_connect_data {
CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
bool recv_sspi_close_notify; /* true if connection closed by close_notify */
bool recv_connection_closed; /* true if connection closed, regardless how */
+ bool use_alpn; /* true if ALPN is used for this connection */
#elif defined(USE_DARWINSSL)
SSLContextRef ssl_ctx;
curl_socket_t ssl_sockfd;
@@ -340,28 +343,38 @@ struct ssl_connect_data {
#endif
};
-struct ssl_config_data {
+struct ssl_primary_config {
long version; /* what version the client wants to use */
- long certverifyresult; /* result from the certificate verification */
-
bool verifypeer; /* set TRUE if this is desired */
bool verifyhost; /* set TRUE if CN/SAN must match hostname */
bool verifystatus; /* set TRUE if certificate status must be checked */
char *CApath; /* certificate dir (doesn't work on windows) */
char *CAfile; /* certificate to verify peer against */
- const char *CRLfile; /* CRL to check certificate revocation */
- const char *issuercert;/* optional issuer certificate filename */
char *clientcert;
char *random_file; /* path to file containing "random" data */
char *egdsocket; /* path to file containing the EGD daemon socket */
char *cipher_list; /* list of ciphers to use */
- size_t max_ssl_sessions; /* SSL session id cache size */
+};
+
+struct ssl_config_data {
+ struct ssl_primary_config primary;
+ bool enable_beast; /* especially allow this flaw for interoperability's
+ sake*/
+ bool no_revoke; /* disable SSL certificate revocation checks */
+ long certverifyresult; /* result from the certificate verification */
+ char *CRLfile; /* CRL to check certificate revocation */
+ char *issuercert;/* optional issuer certificate filename */
curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
void *fsslctxp; /* parameter for call back */
- bool sessionid; /* cache session IDs or not */
bool certinfo; /* gather lots of certificate info */
bool falsestart;
+ char *cert; /* client certificate file name */
+ char *cert_type; /* format for certificate (default: PEM)*/
+ char *key; /* private key file name */
+ char *key_type; /* format for private key (default: PEM) */
+ char *key_passwd; /* plain text private key password */
+
#ifdef USE_TLS_SRP
char *username; /* TLS username (for, e.g., SRP) */
char *password; /* TLS password (for, e.g., SRP) */
@@ -369,16 +382,22 @@ struct ssl_config_data {
#endif
};
+struct ssl_general_config {
+ bool sessionid; /* cache session IDs or not */
+ size_t max_ssl_sessions; /* SSL session id cache size */
+};
+
/* information stored about one single SSL session */
struct curl_ssl_session {
char *name; /* host name for which this ID was used */
char *conn_to_host; /* host name for the connection (may be NULL) */
+ const char *scheme; /* protocol scheme used */
void *sessionid; /* as returned from the SSL layer */
size_t idsize; /* if known, otherwise 0 */
long age; /* just a number, the higher the more recent */
int remote_port; /* remote port */
int conn_to_port; /* remote port for the connection (may be -1) */
- struct ssl_config_data ssl_config; /* setup for this session */
+ struct ssl_primary_config ssl_config; /* setup for this session */
};
/* Struct used for Digest challenge-response authentication */
@@ -449,7 +468,7 @@ struct ntlmdata {
#else
unsigned int flags;
unsigned char nonce[8];
- void* target_info; /* TargetInfo received in the ntlm type-2 message */
+ void *target_info; /* TargetInfo received in the ntlm type-2 message */
unsigned int target_info_len;
#endif
};
@@ -495,6 +514,7 @@ struct ConnectBits {
that overrides the port in the URL (remote port) */
bool proxy; /* if set, this transfer is done through a proxy - any type */
bool httpproxy; /* if set, this transfer is done through a http proxy */
+ bool socksproxy; /* if set, this transfer is done through a socks proxy */
bool user_passwd; /* do we use user+password for this connection? */
bool proxy_user_passwd; /* user+password for the proxy? */
bool ipv6_ip; /* we communicate with a remote site specified with pure IPv6
@@ -529,6 +549,7 @@ struct ConnectBits {
bool ftp_use_eprt; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out
EPRT doesn't work we disable it for the forthcoming
requests */
+ bool ftp_use_data_ssl; /* Enabled SSL for the data connection */
bool netrc; /* name+password provided by netrc */
bool userpwd_in_url; /* name+password found in url */
bool stream_was_rewound; /* Indicates that the stream was rewound after a
@@ -545,6 +566,9 @@ struct ConnectBits {
bool tcp_fastopen; /* use TCP Fast Open */
bool tls_enable_npn; /* TLS NPN extension? */
bool tls_enable_alpn; /* TLS ALPN extension? */
+ bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy
+ is complete */
+ bool socksproxy_connecting; /* connecting through a socks proxy */
};
struct hostname {
@@ -730,7 +754,7 @@ struct SingleRequest {
*/
struct Curl_handler {
- const char * scheme; /* URL scheme name. */
+ const char *scheme; /* URL scheme name. */
/* Complement to setup_connection_internals(). */
CURLcode (*setup_connection)(struct connectdata *);
@@ -817,6 +841,7 @@ struct Curl_handler {
#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login credentials per
request instead of per connection */
#define PROTOPT_ALPN_NPN (1<<8) /* set ALPN and/or NPN for this */
+#define PROTOPT_STREAM (1<<9) /* a protocol with individual logical streams */
/* return the count of bytes sent, or -1 on error */
typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
@@ -846,6 +871,14 @@ struct postponed_data {
};
#endif /* USE_RECV_BEFORE_SEND_WORKAROUND */
+struct proxy_info {
+ struct hostname host;
+ long port;
+ curl_proxytype proxytype; /* what kind of proxy that is in use */
+ char *user; /* proxy user name string, allocated */
+ char *passwd; /* proxy password string, allocated */
+};
+
/*
* The connectdata struct contains all fields and variables that should be
* unique for an entire connection.
@@ -895,14 +928,20 @@ struct connectdata {
int socktype; /* SOCK_STREAM or SOCK_DGRAM */
struct hostname host;
+ char *secondaryhostname; /* secondary socket host name (ftp) */
struct hostname conn_to_host; /* the host to connect to. valid only if
bits.conn_to_host is set */
struct hostname proxy;
+ struct proxy_info socks_proxy;
+ struct proxy_info http_proxy;
+
long port; /* which port to use locally */
int remote_port; /* the remote port, not the proxy port! */
int conn_to_port; /* the remote port to connect to. valid only if
bits.conn_to_port is set */
+ unsigned short secondary_port; /* secondary socket remote port to connect to
+ (ftp) */
/* 'primary_ip' and 'primary_port' get filled with peer's numerical
ip address and port number whenever an outgoing connection is
@@ -927,10 +966,6 @@ struct connectdata {
char *oauth_bearer; /* bearer token for OAuth 2.0, allocated */
- char *proxyuser; /* proxy user name string, allocated */
- char *proxypasswd; /* proxy password string, allocated */
- curl_proxytype proxytype; /* what kind of proxy that is in use */
-
int httpversion; /* the HTTP version*10 reported by the server */
int rtspversion; /* the RTSP version*10 reported by the server */
@@ -948,7 +983,9 @@ struct connectdata {
struct postponed_data postponed[2]; /* two buffers for two sockets */
#endif /* USE_RECV_BEFORE_SEND_WORKAROUND */
struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */
- struct ssl_config_data ssl_config;
+ struct ssl_connect_data proxy_ssl[2]; /* this is for proxy ssl-stuff */
+ struct ssl_primary_config ssl_config;
+ struct ssl_primary_config proxy_ssl_config;
bool tls_upgraded;
struct ConnectBits bits; /* various state-flags for this connection */
@@ -959,8 +996,8 @@ struct connectdata {
struct timeval connecttime;
/* The two fields below get set in Curl_connecthost */
int num_addr; /* number of addresses to try to connect to */
- long timeoutms_per_addr; /* how long time in milliseconds to spend on
- trying to connect to each IP address */
+ time_t timeoutms_per_addr; /* how long time in milliseconds to spend on
+ trying to connect to each IP address */
const struct Curl_handler *handler; /* Connection's protocol handler */
const struct Curl_handler *given; /* The protocol first given */
@@ -1017,7 +1054,7 @@ struct connectdata {
send on this pipeline */
struct curl_llist *recv_pipe; /* List of handles waiting to read
their responses on this pipeline */
- char* master_buffer; /* The master buffer allocated on-demand;
+ char *master_buffer; /* The master buffer allocated on-demand;
used for pipelining. */
size_t read_pos; /* Current read position in the master buffer */
size_t buf_len; /* Length of the buffer?? */
@@ -1038,8 +1075,8 @@ struct connectdata {
/* used for communication with Samba's winbind daemon helper ntlm_auth */
curl_socket_t ntlm_auth_hlpr_socket;
pid_t ntlm_auth_hlpr_pid;
- char* challenge_header;
- char* response_header;
+ char *challenge_header;
+ char *response_header;
#endif
#endif
@@ -1075,9 +1112,6 @@ struct connectdata {
int socks5_gssapi_enctype;
#endif
- bool verifypeer;
- bool verifyhost;
-
/* When this connection is created, store the conditions for the local end
bind. This is stored before the actual bind and before any connection is
made and will serve the purpose of being used for comparison reasons so
@@ -1096,15 +1130,20 @@ struct connectdata {
struct connectbundle *bundle; /* The bundle we are member of */
int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */
+
+#ifdef USE_UNIX_SOCKETS
+ char *unix_domain_socket;
+#endif
};
/* The end of connectdata. */
/*
* Struct to keep statistical and informational data.
+ * All variables in this struct must be initialized/reset in Curl_initinfo().
*/
struct PureInfo {
- int httpcode; /* Recent HTTP, FTP, or RTSP response code */
+ int httpcode; /* Recent HTTP, FTP, RTSP or SMTP response code */
int httpproxycode; /* response code from proxy when received separate */
int httpversion; /* the http version number X.Y = X*10+Y */
long filetime; /* If requested, this is might get set. Set to -1 if the time
@@ -1135,6 +1174,9 @@ struct PureInfo {
char conn_local_ip[MAX_IPADR_LEN];
long conn_local_port;
+ const char *conn_scheme;
+ unsigned int conn_protocol;
+
struct curl_certinfo certs; /* info about the certs, only populated in
OpenSSL builds. Asked for with
CURLOPT_CERTINFO / CURLINFO_CERTINFO */
@@ -1142,8 +1184,8 @@ struct PureInfo {
struct Progress {
- long lastshow; /* time() of the last displayed progress meter or NULL to
- force redraw at next call */
+ time_t lastshow; /* time() of the last displayed progress meter or NULL to
+ force redraw at next call */
curl_off_t size_dl; /* total expected size */
curl_off_t size_ul; /* total expected size */
curl_off_t downloaded; /* transferred so far */
@@ -1171,6 +1213,14 @@ struct Progress {
struct timeval t_startsingle;
struct timeval t_startop;
struct timeval t_acceptdata;
+
+ /* upload speed limit */
+ struct timeval ul_limit_start;
+ curl_off_t ul_limit_size;
+ /* download speed limit */
+ struct timeval dl_limit_start;
+ curl_off_t dl_limit_size;
+
#define CURR_TIME (5+1) /* 6 entries for 5 seconds */
curl_off_t speeder[ CURR_TIME ];
@@ -1390,8 +1440,10 @@ struct DynamicStatic {
struct Curl_multi; /* declared and used only in multi.c */
enum dupstring {
- STRING_CERT, /* client certificate file name */
- STRING_CERT_TYPE, /* format for certificate (default: PEM)*/
+ STRING_CERT_ORIG, /* client certificate file name */
+ STRING_CERT_PROXY, /* client certificate file name */
+ STRING_CERT_TYPE_ORIG, /* format for certificate (default: PEM)*/
+ STRING_CERT_TYPE_PROXY, /* format for certificate (default: PEM)*/
STRING_COOKIE, /* HTTP cookie string to send */
STRING_COOKIEJAR, /* dump all cookies to this file */
STRING_CUSTOMREQUEST, /* HTTP/FTP/RTSP request/method to use */
@@ -1401,25 +1453,34 @@ enum dupstring {
STRING_FTP_ACCOUNT, /* ftp account data */
STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */
STRING_FTPPORT, /* port to send with the FTP PORT command */
- STRING_KEY, /* private key file name */
- STRING_KEY_PASSWD, /* plain text private key password */
- STRING_KEY_TYPE, /* format for private key (default: PEM) */
+ STRING_KEY_ORIG, /* private key file name */
+ STRING_KEY_PROXY, /* private key file name */
+ STRING_KEY_PASSWD_ORIG, /* plain text private key password */
+ STRING_KEY_PASSWD_PROXY, /* plain text private key password */
+ STRING_KEY_TYPE_ORIG, /* format for private key (default: PEM) */
+ STRING_KEY_TYPE_PROXY, /* format for private key (default: PEM) */
STRING_KRB_LEVEL, /* krb security level */
STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find
$HOME/.netrc */
STRING_PROXY, /* proxy to use */
+ STRING_SOCKS_PROXY, /* socks proxy to use */
STRING_SET_RANGE, /* range, if used */
STRING_SET_REFERER, /* custom string for the HTTP referer field */
STRING_SET_URL, /* what original URL to work on */
- STRING_SSL_CAPATH, /* CA directory name (doesn't work on windows) */
- STRING_SSL_CAFILE, /* certificate file to verify peer against */
+ STRING_SSL_CAPATH_ORIG, /* CA directory name (doesn't work on windows) */
+ STRING_SSL_CAPATH_PROXY, /* CA directory name (doesn't work on windows) */
+ STRING_SSL_CAFILE_ORIG, /* certificate file to verify peer against */
+ STRING_SSL_CAFILE_PROXY, /* certificate file to verify peer against */
STRING_SSL_PINNEDPUBLICKEY, /* public key file to verify peer against */
- STRING_SSL_CIPHER_LIST, /* list of ciphers to use */
+ STRING_SSL_CIPHER_LIST_ORIG, /* list of ciphers to use */
+ STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */
STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */
STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */
STRING_USERAGENT, /* User-Agent string */
- STRING_SSL_CRLFILE, /* crl file to check certificate */
- STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */
+ STRING_SSL_CRLFILE_ORIG, /* crl file to check certificate */
+ STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */
+ STRING_SSL_ISSUERCERT_ORIG, /* issuer cert file to check certificate */
+ STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */
STRING_USERNAME, /* <username>, if used */
STRING_PASSWORD, /* <password>, if used */
STRING_OPTIONS, /* <options>, if used */
@@ -1447,8 +1508,10 @@ enum dupstring {
STRING_MAIL_AUTH,
#ifdef USE_TLS_SRP
- STRING_TLSAUTH_USERNAME, /* TLS auth <username> */
- STRING_TLSAUTH_PASSWORD, /* TLS auth <password> */
+ STRING_TLSAUTH_USERNAME_ORIG, /* TLS auth <username> */
+ STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth <username> */
+ STRING_TLSAUTH_PASSWORD_ORIG, /* TLS auth <password> */
+ STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth <password> */
#endif
STRING_BEARER, /* <bearer>, if used */
#ifdef USE_UNIX_SOCKETS
@@ -1512,10 +1575,10 @@ struct UserDefined {
curl_opensocket_callback fopensocket; /* function for checking/translating
the address and opening the
socket */
- void* opensocket_client;
+ void *opensocket_client;
curl_closesocket_callback fclosesocket; /* function for closing the
socket */
- void* closesocket_client;
+ void *closesocket_client;
void *seek_client; /* pointer to pass to the seek callback */
/* the 3 curl_conv_callback functions below are used on non-ASCII hosts */
@@ -1566,7 +1629,10 @@ struct UserDefined {
long httpversion; /* when non-zero, a specific HTTP version requested to
be used in the library's request(s) */
struct ssl_config_data ssl; /* user defined SSL stuff */
+ struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */
+ struct ssl_general_config general_ssl; /* general user defined SSL stuff */
curl_proxytype proxytype; /* what kind of proxy that is in use */
+ curl_proxytype socks_proxytype; /* what kind of socks proxy that is in use */
long dns_cache_timeout; /* DNS cache timeout */
long buffer_size; /* size of receive buffer to use */
void *private_data; /* application-private data */
@@ -1600,6 +1666,7 @@ struct UserDefined {
bool ftp_use_port; /* use the FTP PORT command */
bool hide_progress; /* don't use the progress meter */
bool http_fail_on_error; /* fail on HTTP error codes >= 400 */
+ bool http_keep_sending_on_error; /* for HTTP status codes >= 300 */
bool http_follow_location; /* follow HTTP redirects */
bool http_transfer_encoding; /* request compressed HTTP transfer-encoding */
bool http_disable_hostname_check_before_authentication;
@@ -1629,9 +1696,6 @@ struct UserDefined {
bool ftp_skip_ip; /* skip the IP address the FTP server passes on to
us */
bool connect_only; /* make connection, let application use the socket */
- bool ssl_enable_beast; /* especially allow this flaw for interoperability's
- sake*/
- bool ssl_no_revoke; /* disable SSL certificate revocation checks */
long ssh_auth_types; /* allowed SSH auth types */
bool http_te_skip; /* pass the raw body data to the user, even when
transfer-encoded (chunked, compressed) */
diff --git a/lib/vauth/cleartext.c b/lib/vauth/cleartext.c
index 4e906bc0..a761ae78 100644
--- a/lib/vauth/cleartext.c
+++ b/lib/vauth/cleartext.c
@@ -33,8 +33,6 @@
#include "curl_md5.h"
#include "warnless.h"
#include "strtok.h"
-#include "strequal.h"
-#include "rawstr.h"
#include "sendf.h"
#include "curl_printf.h"
@@ -68,16 +66,27 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
char *plainauth;
size_t ulen;
size_t plen;
+ size_t plainlen;
+ *outlen = 0;
+ *outptr = NULL;
ulen = strlen(userp);
plen = strlen(passwdp);
- plainauth = malloc(2 * ulen + plen + 2);
- if(!plainauth) {
- *outlen = 0;
- *outptr = NULL;
+ /* Compute binary message length, checking for overflows. */
+ plainlen = 2 * ulen;
+ if(plainlen < ulen)
+ return CURLE_OUT_OF_MEMORY;
+ plainlen += plen;
+ if(plainlen < plen)
+ return CURLE_OUT_OF_MEMORY;
+ plainlen += 2;
+ if(plainlen < 2)
+ return CURLE_OUT_OF_MEMORY;
+
+ plainauth = malloc(plainlen);
+ if(!plainauth)
return CURLE_OUT_OF_MEMORY;
- }
/* Calculate the reply */
memcpy(plainauth, userp, ulen);
@@ -87,8 +96,7 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
memcpy(plainauth + 2 * ulen + 2, passwdp, plen);
/* Base64 encode the reply */
- result = Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr,
- outlen);
+ result = Curl_base64_encode(data, plainauth, plainlen, outptr, outlen);
free(plainauth);
return result;
diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c
index 26ea7b59..7d9200ad 100644
--- a/lib/vauth/digest.c
+++ b/lib/vauth/digest.c
@@ -37,9 +37,10 @@
#include "vtls/vtls.h"
#include "warnless.h"
#include "strtok.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "non-ascii.h" /* included for Curl_convert_... prototypes */
#include "curl_printf.h"
+#include "rand.h"
/* The last #include files should be: */
#include "curl_memory.h"
@@ -59,7 +60,7 @@
what ultimately goes over the network.
*/
#define CURL_OUTPUT_DIGEST_CONV(a, b) \
- result = Curl_convert_to_network(a, (char *)b, strlen((const char*)b)); \
+ result = Curl_convert_to_network(a, (char *)b, strlen((const char *)b)); \
if(result) { \
free(b); \
return result; \
@@ -217,11 +218,11 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value)
token = strtok_r(tmp, ",", &tok_buf);
while(token != NULL) {
- if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH))
+ if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH))
*value |= DIGEST_QOP_VALUE_AUTH;
- else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_INT))
+ else if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH_INT))
*value |= DIGEST_QOP_VALUE_AUTH_INT;
- else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_CONF))
+ else if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH_CONF))
*value |= DIGEST_QOP_VALUE_AUTH_CONF;
token = strtok_r(NULL, ",", &tok_buf);
@@ -306,6 +307,20 @@ static CURLcode auth_decode_digest_md5_message(const char *chlg64,
}
/*
+ * Curl_auth_is_digest_supported()
+ *
+ * This is used to evaluate if DIGEST is supported.
+ *
+ * Parameters: None
+ *
+ * Returns TRUE as DIGEST as handled by libcurl.
+ */
+bool Curl_auth_is_digest_supported(void)
+{
+ return TRUE;
+}
+
+/*
* Curl_auth_create_digest_md5_message()
*
* This is used to generate an already encoded DIGEST-MD5 response message
@@ -373,10 +388,9 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
return CURLE_BAD_CONTENT_ENCODING;
/* Generate 16 bytes of random data */
- entropy[0] = Curl_rand(data);
- entropy[1] = Curl_rand(data);
- entropy[2] = Curl_rand(data);
- entropy[3] = Curl_rand(data);
+ result = Curl_rand(data, &entropy[0], 4);
+ if(result)
+ return result;
/* Convert the random data into a 32 byte hex string */
snprintf(cnonce, sizeof(cnonce), "%08x%08x%08x%08x",
@@ -524,31 +538,31 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
/* Extract a value=content pair */
if(Curl_auth_digest_get_pair(chlg, value, content, &chlg)) {
- if(Curl_raw_equal(value, "nonce")) {
+ if(strcasecompare(value, "nonce")) {
free(digest->nonce);
digest->nonce = strdup(content);
if(!digest->nonce)
return CURLE_OUT_OF_MEMORY;
}
- else if(Curl_raw_equal(value, "stale")) {
- if(Curl_raw_equal(content, "true")) {
+ else if(strcasecompare(value, "stale")) {
+ if(strcasecompare(content, "true")) {
digest->stale = TRUE;
digest->nc = 1; /* we make a new nonce now */
}
}
- else if(Curl_raw_equal(value, "realm")) {
+ else if(strcasecompare(value, "realm")) {
free(digest->realm);
digest->realm = strdup(content);
if(!digest->realm)
return CURLE_OUT_OF_MEMORY;
}
- else if(Curl_raw_equal(value, "opaque")) {
+ else if(strcasecompare(value, "opaque")) {
free(digest->opaque);
digest->opaque = strdup(content);
if(!digest->opaque)
return CURLE_OUT_OF_MEMORY;
}
- else if(Curl_raw_equal(value, "qop")) {
+ else if(strcasecompare(value, "qop")) {
char *tok_buf;
/* Tokenize the list and choose auth if possible, use a temporary
clone of the buffer since strtok_r() ruins it */
@@ -558,10 +572,10 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
token = strtok_r(tmp, ",", &tok_buf);
while(token != NULL) {
- if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH)) {
+ if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH)) {
foundAuth = TRUE;
}
- else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_INT)) {
+ else if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH_INT)) {
foundAuthInt = TRUE;
}
token = strtok_r(NULL, ",", &tok_buf);
@@ -583,15 +597,15 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
return CURLE_OUT_OF_MEMORY;
}
}
- else if(Curl_raw_equal(value, "algorithm")) {
+ else if(strcasecompare(value, "algorithm")) {
free(digest->algorithm);
digest->algorithm = strdup(content);
if(!digest->algorithm)
return CURLE_OUT_OF_MEMORY;
- if(Curl_raw_equal(content, "MD5-sess"))
+ if(strcasecompare(content, "MD5-sess"))
digest->algo = CURLDIGESTALGO_MD5SESS;
- else if(Curl_raw_equal(content, "MD5"))
+ else if(strcasecompare(content, "MD5"))
digest->algo = CURLDIGESTALGO_MD5;
else
return CURLE_BAD_CONTENT_ENCODING;
@@ -670,9 +684,12 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
digest->nc = 1;
if(!digest->cnonce) {
+ unsigned int rnd[4];
+ result = Curl_rand(data, &rnd[0], 4);
+ if(result)
+ return result;
snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x",
- Curl_rand(data), Curl_rand(data),
- Curl_rand(data), Curl_rand(data));
+ rnd[0], rnd[1], rnd[2], rnd[3]);
result = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf),
&cnonce, &cnonce_sz);
@@ -730,7 +747,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
md5this = (unsigned char *) aprintf("%s:%s", request, uripath);
- if(digest->qop && Curl_raw_equal(digest->qop, "auth-int")) {
+ if(digest->qop && strcasecompare(digest->qop, "auth-int")) {
/* We don't support auth-int for PUT or POST at the moment.
TODO: replace md5 of empty string with entity-body for PUT/POST */
unsigned char *md5this2 = (unsigned char *)
@@ -806,7 +823,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
digest->qop,
request_digest);
- if(Curl_raw_equal(digest->qop, "auth"))
+ if(strcasecompare(digest->qop, "auth"))
digest->nc++; /* The nc (from RFC) has to be a 8 hex digit number 0
padded which tells to the server how many times you are
using the same nonce in the qop=auth mode */
diff --git a/lib/vauth/digest_sspi.c b/lib/vauth/digest_sspi.c
index 6a7315eb..b9ceb12a 100644
--- a/lib/vauth/digest_sspi.c
+++ b/lib/vauth/digest_sspi.c
@@ -37,13 +37,34 @@
#include "curl_multibyte.h"
#include "sendf.h"
#include "strdup.h"
-#include "rawstr.h"
+#include "strcase.h"
/* The last #include files should be: */
#include "curl_memory.h"
#include "memdebug.h"
/*
+* Curl_auth_is_digest_supported()
+*
+* This is used to evaluate if DIGEST is supported.
+*
+* Parameters: None
+*
+* Returns TRUE if DIGEST is supported by Windows SSPI.
+*/
+bool Curl_auth_is_digest_supported(void)
+{
+ PSecPkgInfo SecurityPackage;
+ SECURITY_STATUS status;
+
+ /* Query the security package for Digest */
+ status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
+ &SecurityPackage);
+
+ return (status == SEC_E_OK ? TRUE : FALSE);
+}
+
+/*
* Curl_auth_create_digest_md5_message()
*
* This is used to generate an already encoded DIGEST-MD5 response message
@@ -256,7 +277,7 @@ CURLcode Curl_override_sspi_http_realm(const char *chlg,
/* Extract a value=content pair */
if(Curl_auth_digest_get_pair(chlg, value, content, &chlg)) {
- if(Curl_raw_equal(value, "realm")) {
+ if(strcasecompare(value, "realm")) {
/* Setup identity's domain and length */
domain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *) content);
@@ -393,7 +414,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
/* Populate our identity domain */
- if(Curl_override_sspi_http_realm((const char*) digest->input_token,
+ if(Curl_override_sspi_http_realm((const char *) digest->input_token,
&identity))
return CURLE_OUT_OF_MEMORY;
diff --git a/lib/vauth/krb5_gssapi.c b/lib/vauth/krb5_gssapi.c
index 31c8c7da..c754fae4 100644
--- a/lib/vauth/krb5_gssapi.c
+++ b/lib/vauth/krb5_gssapi.c
@@ -42,6 +42,20 @@
#include "memdebug.h"
/*
+ * Curl_auth_is_gssapi_supported()
+ *
+ * This is used to evaluate if GSSAPI (Kerberos V5) is supported.
+ *
+ * Parameters: None
+ *
+ * Returns TRUE if Kerberos V5 is supported by the GSS-API library.
+ */
+bool Curl_auth_is_gssapi_supported(void)
+{
+ return TRUE;
+}
+
+/*
* Curl_auth_create_gssapi_user_message()
*
* This is used to generate an already encoded GSSAPI (Kerberos V5) user token
diff --git a/lib/vauth/krb5_sspi.c b/lib/vauth/krb5_sspi.c
index 08774f6c..151794e6 100644
--- a/lib/vauth/krb5_sspi.c
+++ b/lib/vauth/krb5_sspi.c
@@ -40,6 +40,28 @@
#include "memdebug.h"
/*
+ * Curl_auth_is_gssapi_supported()
+ *
+ * This is used to evaluate if GSSAPI (Kerberos V5) is supported.
+ *
+ * Parameters: None
+ *
+ * Returns TRUE if Kerberos V5 is supported by Windows SSPI.
+ */
+bool Curl_auth_is_gssapi_supported(void)
+{
+ PSecPkgInfo SecurityPackage;
+ SECURITY_STATUS status;
+
+ /* Query the security package for Kerberos */
+ status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *)
+ TEXT(SP_NAME_KERBEROS),
+ &SecurityPackage);
+
+ return (status == SEC_E_OK ? TRUE : FALSE);
+}
+
+/*
* Curl_auth_create_gssapi_user_message()
*
* This is used to generate an already encoded GSSAPI (Kerberos V5) user token
diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c
index c85fe429..b4d345d6 100644
--- a/lib/vauth/ntlm.c
+++ b/lib/vauth/ntlm.c
@@ -41,7 +41,7 @@
#include "curl_gethostname.h"
#include "curl_multibyte.h"
#include "warnless.h"
-
+#include "rand.h"
#include "vtls/vtls.h"
#ifdef USE_NSS
@@ -217,6 +217,20 @@ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
*/
/*
+ * Curl_auth_is_ntlm_supported()
+ *
+ * This is used to evaluate if NTLM is supported.
+ *
+ * Parameters: None
+ *
+ * Returns TRUE as NTLM as handled by libcurl.
+ */
+bool Curl_auth_is_ntlm_supported(void)
+{
+ return TRUE;
+}
+
+/*
* Curl_auth_decode_ntlm_type2_message()
*
* This is used to decode an already encoded NTLM type-2 message. The message
@@ -544,8 +558,9 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
unsigned int entropy[2];
unsigned char ntlmv2hash[0x18];
- entropy[0] = Curl_rand(data);
- entropy[1] = Curl_rand(data);
+ result = Curl_rand(data, &entropy[0], 2);
+ if(result)
+ return result;
result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
if(result)
@@ -584,8 +599,9 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
unsigned int entropy[2];
/* Need to create 8 bytes random data */
- entropy[0] = Curl_rand(data);
- entropy[1] = Curl_rand(data);
+ result = Curl_rand(data, &entropy[0], 2);
+ if(result)
+ return result;
/* 8 bytes random data as challenge in lmresp */
memcpy(lmresp, entropy, 8);
diff --git a/lib/vauth/ntlm_sspi.c b/lib/vauth/ntlm_sspi.c
index 982a9d37..c3305176 100644
--- a/lib/vauth/ntlm_sspi.c
+++ b/lib/vauth/ntlm_sspi.c
@@ -38,6 +38,27 @@
#include "memdebug.h"
/*
+ * Curl_auth_is_ntlm_supported()
+ *
+ * This is used to evaluate if NTLM is supported.
+ *
+ * Parameters: None
+ *
+ * Returns TRUE if NTLM is supported by Windows SSPI.
+ */
+bool Curl_auth_is_ntlm_supported(void)
+{
+ PSecPkgInfo SecurityPackage;
+ SECURITY_STATUS status;
+
+ /* Query the security package for NTLM */
+ status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM),
+ &SecurityPackage);
+
+ return (status == SEC_E_OK ? TRUE : FALSE);
+}
+
+/*
* Curl_auth_create_ntlm_type1_message()
*
* This is used to generate an already encoded NTLM type-1 message ready for
diff --git a/lib/vauth/spnego_gssapi.c b/lib/vauth/spnego_gssapi.c
index b256ee61..8840db8f 100644
--- a/lib/vauth/spnego_gssapi.c
+++ b/lib/vauth/spnego_gssapi.c
@@ -41,6 +41,20 @@
#include "memdebug.h"
/*
+ * Curl_auth_is_spnego_supported()
+ *
+ * This is used to evaluate if SPNEGO (Negotiate) is supported.
+ *
+ * Parameters: None
+ *
+ * Returns TRUE if Negotiate supported by the GSS-API library.
+ */
+bool Curl_auth_is_spnego_supported(void)
+{
+ return TRUE;
+}
+
+/*
* Curl_auth_decode_spnego_message()
*
* This is used to decode an already encoded SPNEGO (Negotiate) challenge
diff --git a/lib/vauth/spnego_sspi.c b/lib/vauth/spnego_sspi.c
index b6176ece..5fa95e2e 100644
--- a/lib/vauth/spnego_sspi.c
+++ b/lib/vauth/spnego_sspi.c
@@ -40,6 +40,28 @@
#include "memdebug.h"
/*
+ * Curl_auth_is_spnego_supported()
+ *
+ * This is used to evaluate if SPNEGO (Negotiate) is supported.
+ *
+ * Parameters: None
+ *
+ * Returns TRUE if Negotiate is supported by Windows SSPI.
+ */
+bool Curl_auth_is_spnego_supported(void)
+{
+ PSecPkgInfo SecurityPackage;
+ SECURITY_STATUS status;
+
+ /* Query the security package for Negotiate */
+ status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *)
+ TEXT(SP_NAME_NEGOTIATE),
+ &SecurityPackage);
+
+ return (status == SEC_E_OK ? TRUE : FALSE);
+}
+
+/*
* Curl_auth_decode_spnego_message()
*
* This is used to decode an already encoded SPNEGO (Negotiate) challenge
@@ -242,15 +264,17 @@ CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data,
/* Base64 encode the already generated response */
result = Curl_base64_encode(data,
- (const char*) nego->output_token,
+ (const char *) nego->output_token,
nego->output_token_length,
outptr, outlen);
if(result)
return result;
- if(!*outptr || !*outlen)
+ if(!*outptr || !*outlen) {
+ free(*outptr);
return CURLE_REMOTE_ACCESS_DENIED;
+ }
return CURLE_OK;
}
diff --git a/lib/vauth/vauth.c b/lib/vauth/vauth.c
index 702e2d4b..b995f34e 100644
--- a/lib/vauth/vauth.c
+++ b/lib/vauth/vauth.c
@@ -104,3 +104,44 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host,
}
#endif /* USE_WINDOWS_SSPI */
+/*
+* Curl_auth_user_contains_domain()
+*
+* This is used to test if the specified user contains a Windows domain name as
+* follows:
+*
+* User\Domain (Down-level Logon Name)
+* User/Domain (curl Down-level format - for compatibility with existing code)
+* User@Domain (User Principal Name)
+*
+* Note: The user name may be empty when using a GSS-API library or Windows SSPI
+* as the user and domain are either obtained from the credientals cache when
+* using GSS-API or via the currently logged in user's credientals when using
+* Windows SSPI.
+*
+* Parameters:
+*
+* user [in] - The user name.
+*
+* Returns TRUE on success; otherwise FALSE.
+*/
+bool Curl_auth_user_contains_domain(const char *user)
+{
+ bool valid = FALSE;
+
+ if(user && *user) {
+ /* Check we have a domain name or UPN present */
+ char *p = strpbrk(user, "\\/@");
+
+ valid = (p != NULL && p > user && p < user + strlen(user) - 1 ? TRUE :
+ FALSE);
+ }
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ else
+ /* User and domain are obtained from the GSS-API credientials cache or the
+ currently logged in user from Windows */
+ valid = TRUE;
+#endif
+
+ return valid;
+}
diff --git a/lib/vauth/vauth.h b/lib/vauth/vauth.h
index 38806ee7..9d61228c 100644
--- a/lib/vauth/vauth.h
+++ b/lib/vauth/vauth.h
@@ -55,6 +55,9 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host,
const char *realm);
#endif
+/* This is used to test if the user contains a Windows domain name */
+bool Curl_auth_user_contains_domain(const char *user);
+
/* This is used to generate a base64 encoded PLAIN cleartext message */
CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
const char *userp,
@@ -83,6 +86,9 @@ CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data,
const char *passwdp,
char **outptr, size_t *outlen);
+/* This is used to evaluate if DIGEST is supported */
+bool Curl_auth_is_digest_supported(void);
+
/* This is used to generate a base64 encoded DIGEST-MD5 response message */
CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
const char *chlg64,
@@ -109,6 +115,9 @@ void Curl_auth_digest_cleanup(struct digestdata *digest);
#endif /* !CURL_DISABLE_CRYPTO_AUTH */
#if defined(USE_NTLM)
+/* This is used to evaluate if NTLM is supported */
+bool Curl_auth_is_ntlm_supported(void);
+
/* This is used to generate a base64 encoded NTLM type-1 message */
CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
const char *passwdp,
@@ -140,6 +149,9 @@ CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data,
const char *bearer,
char **outptr, size_t *outlen);
#if defined(USE_KERBEROS5)
+/* This is used to evaluate if GSSAPI (Kerberos V5) is supported */
+bool Curl_auth_is_gssapi_supported(void);
+
/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) user token
message */
CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
@@ -165,6 +177,9 @@ void Curl_auth_gssapi_cleanup(struct kerberos5data *krb5);
#endif /* USE_KERBEROS5 */
#if defined(USE_SPNEGO)
+/* This is used to evaluate if SPNEGO (Negotiate) is supported */
+bool Curl_auth_is_spnego_supported(void);
+
/* This is used to decode a base64 encoded SPNEGO (Negotiate) challenge
message */
CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
diff --git a/lib/version.c b/lib/version.c
index 12924453..a434a628 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -36,8 +36,8 @@
# include <ares.h>
#endif
-#ifdef USE_LIBIDN
-#include <stringprep.h>
+#ifdef USE_LIBIDN2
+#include <idn2.h>
#endif
#ifdef USE_LIBPSL
@@ -111,9 +111,9 @@ char *curl_version(void)
left -= len;
ptr += len;
#endif
-#ifdef USE_LIBIDN
- if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) {
- len = snprintf(ptr, left, " libidn/%s", stringprep_check_version(NULL));
+#ifdef USE_LIBIDN2
+ if(idn2_check_version(IDN2_VERSION)) {
+ len = snprintf(ptr, left, " libidn2/%s", idn2_check_version(NULL));
left -= len;
ptr += len;
}
@@ -365,10 +365,10 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
version_info.ares_num = aresnum;
}
#endif
-#ifdef USE_LIBIDN
+#ifdef USE_LIBIDN2
/* This returns a version string if we use the given version or later,
otherwise it returns NULL */
- version_info.libidn = stringprep_check_version(LIBIDN_REQUIRED_VERSION);
+ version_info.libidn = idn2_check_version(IDN2_VERSION);
if(version_info.libidn)
version_info.features |= CURL_VERSION_IDN;
#elif defined(USE_WIN32_IDN)
diff --git a/lib/vtls/axtls.c b/lib/vtls/axtls.c
index b6c69ad5..8a5029f7 100644
--- a/lib/vtls/axtls.c
+++ b/lib/vtls/axtls.c
@@ -158,7 +158,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
/* axTLS only supports TLSv1 */
/* check to see if we've been told to use an explicit SSL/TLS version */
- switch(data->set.ssl.version) {
+ switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
break;
@@ -183,17 +183,17 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
conn->ssl[sockindex].ssl = NULL;
/* Load the trusted CA cert bundle file */
- if(data->set.ssl.CAfile) {
- if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
- != SSL_OK) {
+ if(SSL_CONN_CONFIG(CAfile)) {
+ if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT,
+ SSL_CONN_CONFIG(CAfile), NULL) != SSL_OK) {
infof(data, "error reading ca cert file %s \n",
- data->set.ssl.CAfile);
- if(data->set.ssl.verifypeer) {
+ SSL_CONN_CONFIG(CAfile));
+ if(SSL_CONN_CONFIG(verifypeer)) {
return CURLE_SSL_CACERT_BADFILE;
}
}
else
- infof(data, "found certificates in %s\n", data->set.ssl.CAfile);
+ infof(data, "found certificates in %s\n", SSL_CONN_CONFIG(CAfile));
}
/* gtls.c tasks we're skipping for now:
@@ -205,15 +205,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
*/
/* Load client certificate */
- if(data->set.str[STRING_CERT]) {
+ if(SSL_SET_OPTION(cert)) {
i=0;
/* Instead of trying to analyze cert type here, let axTLS try them all. */
while(cert_types[i] != 0) {
ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
- data->set.str[STRING_CERT], NULL);
+ SSL_SET_OPTION(cert), NULL);
if(ssl_fcn_return == SSL_OK) {
infof(data, "successfully read cert file %s \n",
- data->set.str[STRING_CERT]);
+ SSL_SET_OPTION(cert));
break;
}
i++;
@@ -221,7 +221,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
/* Tried all cert types, none worked. */
if(cert_types[i] == 0) {
failf(data, "%s is not x509 or pkcs12 format",
- data->set.str[STRING_CERT]);
+ SSL_SET_OPTION(cert));
return CURLE_SSL_CERTPROBLEM;
}
}
@@ -229,15 +229,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
/* Load client key.
If a pkcs12 file successfully loaded a cert, then there's nothing to do
because the key has already been loaded. */
- if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) {
+ if(SSL_SET_OPTION(key) && cert_types[i] != SSL_OBJ_PKCS12) {
i=0;
/* Instead of trying to analyze key type here, let axTLS try them all. */
while(key_types[i] != 0) {
ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
- data->set.str[STRING_KEY], NULL);
+ SSL_SET_OPTION(key), NULL);
if(ssl_fcn_return == SSL_OK) {
infof(data, "successfully read key file %s \n",
- data->set.str[STRING_KEY]);
+ SSL_SET_OPTION(key));
break;
}
i++;
@@ -245,7 +245,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
/* Tried all key types, none worked. */
if(key_types[i] == 0) {
failf(data, "Failure: %s is not a supported key file",
- data->set.str[STRING_KEY]);
+ SSL_SET_OPTION(key));
return CURLE_SSL_CONNECT_ERROR;
}
}
@@ -256,13 +256,14 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
* 2) setting up callbacks. these seem gnutls specific
*/
- if(conn->ssl_config.sessionid) {
+ if(data->set.general_ssl.sessionid) {
const uint8_t *ssl_sessionid;
size_t ssl_idsize;
/* In axTLS, handshaking happens inside ssl_client_new. */
Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) {
+ if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize,
+ sockindex)) {
/* we got a session id, use it! */
infof (data, "SSL re-using session ID\n");
ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
@@ -291,13 +292,17 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
const char *dns_altname;
int8_t found_subject_alt_names = 0;
int8_t found_subject_alt_name_matching_conn = 0;
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
+ const char * const dispname = SSL_IS_PROXY() ?
+ conn->http_proxy.host.dispname : conn->host.dispname;
/* Here, gtls.c gets the peer certificates and fails out depending on
* settings in "data." axTLS api doesn't have get cert chain fcn, so omit?
*/
/* Verify server's certificate */
- if(data->set.ssl.verifypeer) {
+ if(SSL_CONN_CONFIG(verifypeer)) {
if(ssl_verify_cert(ssl) != SSL_OK) {
Curl_axtls_close(conn, sockindex);
failf(data, "server cert verify failed");
@@ -328,8 +333,8 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
found_subject_alt_names = 1;
infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
- dns_altname, conn->host.name);
- if(Curl_cert_hostcheck(dns_altname, conn->host.name)) {
+ dns_altname, hostname);
+ if(Curl_cert_hostcheck(dns_altname, hostname)) {
found_subject_alt_name_matching_conn = 1;
break;
}
@@ -337,23 +342,21 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
/* RFC2818 checks */
if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
- if(data->set.ssl.verifyhost) {
+ if(SSL_CONN_CONFIG(verifyhost)) {
/* Break connection ! */
Curl_axtls_close(conn, sockindex);
- failf(data, "\tsubjectAltName(s) do not match %s\n",
- conn->host.dispname);
+ failf(data, "\tsubjectAltName(s) do not match %s\n", dispname);
return CURLE_PEER_FAILED_VERIFICATION;
}
else
- infof(data, "\tsubjectAltName(s) do not match %s\n",
- conn->host.dispname);
+ infof(data, "\tsubjectAltName(s) do not match %s\n", dispname);
}
else if(found_subject_alt_names == 0) {
/* Per RFC2818, when no Subject Alt Names were available, examine the peer
CN as a legacy fallback */
peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
if(peer_CN == NULL) {
- if(data->set.ssl.verifyhost) {
+ if(SSL_CONN_CONFIG(verifyhost)) {
Curl_axtls_close(conn, sockindex);
failf(data, "unable to obtain common name from peer certificate");
return CURLE_PEER_FAILED_VERIFICATION;
@@ -362,17 +365,17 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
infof(data, "unable to obtain common name from peer certificate");
}
else {
- if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
- if(data->set.ssl.verifyhost) {
+ if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) {
+ if(SSL_CONN_CONFIG(verifyhost)) {
/* Break connection ! */
Curl_axtls_close(conn, sockindex);
failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
- peer_CN, conn->host.dispname);
+ peer_CN, dispname);
return CURLE_PEER_FAILED_VERIFICATION;
}
else
infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
- peer_CN, conn->host.dispname);
+ peer_CN, dispname);
}
}
}
@@ -383,12 +386,12 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
conn->send[sockindex] = axtls_send;
/* Put our freshly minted SSL session in cache */
- if(conn->ssl_config.sessionid) {
+ if(data->set.general_ssl.sessionid) {
const uint8_t *ssl_sessionid = ssl_get_session_id_size(ssl);
size_t ssl_idsize = ssl_get_session_id(ssl);
Curl_ssl_sessionid_lock(conn);
- if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize)
- != CURLE_OK)
+ if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize,
+ sockindex) != CURLE_OK)
infof (data, "failed to add session to cache\n");
Curl_ssl_sessionid_unlock(conn);
}
@@ -579,8 +582,7 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
*/
if(connssl->ssl) {
- int what = Curl_socket_ready(conn->sock[sockindex],
- CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+ int what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
if(what > 0) {
/* Something to read, let's do it and hope that it is the close
notify alert from the server. buf is managed internally by
diff --git a/lib/vtls/cyassl.c b/lib/vtls/cyassl.c
index 7994b3ea..5570760d 100644
--- a/lib/vtls/cyassl.c
+++ b/lib/vtls/cyassl.c
@@ -55,7 +55,7 @@ and that's a problem since options.h hasn't been included yet. */
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "x509asn1.h"
#include "curl_printf.h"
@@ -118,9 +118,9 @@ static int do_file_type(const char *type)
{
if(!type || !type[0])
return SSL_FILETYPE_PEM;
- if(Curl_raw_equal(type, "PEM"))
+ if(strcasecompare(type, "PEM"))
return SSL_FILETYPE_PEM;
- if(Curl_raw_equal(type, "DER"))
+ if(strcasecompare(type, "DER"))
return SSL_FILETYPE_ASN1;
return -1;
}
@@ -149,7 +149,7 @@ cyassl_connect_step1(struct connectdata *conn,
return CURLE_OK;
/* check to see if we've been told to use an explicit SSL/TLS version */
- switch(data->set.ssl.version) {
+ switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
#if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
@@ -174,12 +174,15 @@ cyassl_connect_step1(struct connectdata *conn,
req_method = TLSv1_2_client_method();
use_sni(TRUE);
break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "CyaSSL: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
case CURL_SSLVERSION_SSLv3:
#ifdef WOLFSSL_ALLOW_SSLV3
req_method = SSLv3_client_method();
use_sni(FALSE);
#else
- failf(data, "No support for SSLv3");
+ failf(data, "CyaSSL does not support SSLv3");
return CURLE_NOT_BUILT_IN;
#endif
break;
@@ -205,7 +208,7 @@ cyassl_connect_step1(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
- switch(data->set.ssl.version) {
+ switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
#if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
@@ -228,18 +231,18 @@ cyassl_connect_step1(struct connectdata *conn,
#ifndef NO_FILESYSTEM
/* load trusted cacert */
- if(data->set.str[STRING_SSL_CAFILE]) {
+ if(SSL_CONN_CONFIG(CAfile)) {
if(1 != SSL_CTX_load_verify_locations(conssl->ctx,
- data->set.str[STRING_SSL_CAFILE],
- data->set.str[STRING_SSL_CAPATH])) {
- if(data->set.ssl.verifypeer) {
+ SSL_CONN_CONFIG(CAfile),
+ SSL_CONN_CONFIG(CApath))) {
+ if(SSL_CONN_CONFIG(verifypeer)) {
/* Fail if we insist on successfully verifying the server. */
failf(data, "error setting certificate verify locations:\n"
" CAfile: %s\n CApath: %s",
- data->set.str[STRING_SSL_CAFILE]?
- data->set.str[STRING_SSL_CAFILE]: "none",
- data->set.str[STRING_SSL_CAPATH]?
- data->set.str[STRING_SSL_CAPATH] : "none");
+ SSL_CONN_CONFIG(CAfile)?
+ SSL_CONN_CONFIG(CAfile): "none",
+ SSL_CONN_CONFIG(CApath)?
+ SSL_CONN_CONFIG(CApath) : "none");
return CURLE_SSL_CACERT_BADFILE;
}
else {
@@ -256,25 +259,25 @@ cyassl_connect_step1(struct connectdata *conn,
infof(data,
" CAfile: %s\n"
" CApath: %s\n",
- data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
+ SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
"none",
- data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
+ SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath):
"none");
}
/* Load the client certificate, and private key */
- if(data->set.str[STRING_CERT] && data->set.str[STRING_KEY]) {
- int file_type = do_file_type(data->set.str[STRING_CERT_TYPE]);
+ if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) {
+ int file_type = do_file_type(SSL_SET_OPTION(cert_type));
- if(SSL_CTX_use_certificate_file(conssl->ctx, data->set.str[STRING_CERT],
+ if(SSL_CTX_use_certificate_file(conssl->ctx, SSL_SET_OPTION(cert),
file_type) != 1) {
failf(data, "unable to use client certificate (no key or wrong pass"
" phrase?)");
return CURLE_SSL_CONNECT_ERROR;
}
- file_type = do_file_type(data->set.str[STRING_KEY_TYPE]);
- if(SSL_CTX_use_PrivateKey_file(conssl->ctx, data->set.str[STRING_KEY],
+ file_type = do_file_type(SSL_SET_OPTION(key_type));
+ if(SSL_CTX_use_PrivateKey_file(conssl->ctx, SSL_SET_OPTION(key),
file_type) != 1) {
failf(data, "unable to set private key");
return CURLE_SSL_CONNECT_ERROR;
@@ -287,7 +290,8 @@ cyassl_connect_step1(struct connectdata *conn,
* anyway. In the latter case the result of the verification is checked with
* SSL_get_verify_result() below. */
SSL_CTX_set_verify(conssl->ctx,
- data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
+ SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER:
+ SSL_VERIFY_NONE,
NULL);
#ifdef HAVE_SNI
@@ -296,13 +300,15 @@ cyassl_connect_step1(struct connectdata *conn,
#ifdef ENABLE_IPV6
struct in6_addr addr6;
#endif
- size_t hostname_len = strlen(conn->host.name);
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
+ size_t hostname_len = strlen(hostname);
if((hostname_len < USHRT_MAX) &&
- (0 == Curl_inet_pton(AF_INET, conn->host.name, &addr4)) &&
+ (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) &&
#ifdef ENABLE_IPV6
- (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr6)) &&
+ (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) &&
#endif
- (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, conn->host.name,
+ (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, hostname,
(unsigned short)hostname_len) != 1)) {
infof(data, "WARNING: failed to configure server name indication (SNI) "
"TLS extension\n");
@@ -331,7 +337,7 @@ cyassl_connect_step1(struct connectdata *conn,
}
}
#ifdef NO_FILESYSTEM
- else if(data->set.ssl.verifypeer) {
+ else if(SSL_CONN_CONFIG(verifypeer)) {
failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built"
" with \"no filesystem\". Either disable peer verification"
" (insecure) or if you are building an application with libcurl you"
@@ -377,11 +383,11 @@ cyassl_connect_step1(struct connectdata *conn,
#endif /* HAVE_ALPN */
/* Check if there's a cached ID we can/should use here! */
- if(conn->ssl_config.sessionid) {
+ if(data->set.general_ssl.sessionid) {
void *ssl_sessionid = NULL;
Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
+ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
/* we got a session id, use it! */
if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
Curl_ssl_sessionid_unlock(conn);
@@ -414,13 +420,17 @@ cyassl_connect_step2(struct connectdata *conn,
int ret = -1;
struct Curl_easy *data = conn->data;
struct ssl_connect_data* conssl = &conn->ssl[sockindex];
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
+ const char * const dispname = SSL_IS_PROXY() ?
+ conn->http_proxy.host.dispname : conn->host.dispname;
conn->recv[sockindex] = cyassl_recv;
conn->send[sockindex] = cyassl_send;
/* Enable RFC2818 checks */
- if(data->set.ssl.verifyhost) {
- ret = CyaSSL_check_domain_name(conssl->handle, conn->host.name);
+ if(SSL_CONN_CONFIG(verifyhost)) {
+ ret = CyaSSL_check_domain_name(conssl->handle, hostname);
if(ret == SSL_FAILURE)
return CURLE_OUT_OF_MEMORY;
}
@@ -444,31 +454,31 @@ cyassl_connect_step2(struct connectdata *conn,
else if(DOMAIN_NAME_MISMATCH == detail) {
#if 1
failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n",
- conn->host.dispname);
+ dispname);
return CURLE_PEER_FAILED_VERIFICATION;
#else
/* When the CyaSSL_check_domain_name() is used and you desire to continue
- * on a DOMAIN_NAME_MISMATCH, i.e. 'data->set.ssl.verifyhost == 0',
+ * on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost == 0',
* CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA error. The only
* way to do this is currently to switch the CyaSSL_check_domain_name()
- * in and out based on the 'data->set.ssl.verifyhost' value. */
- if(data->set.ssl.verifyhost) {
+ * in and out based on the 'conn->ssl_config.verifyhost' value. */
+ if(SSL_CONN_CONFIG(verifyhost)) {
failf(data,
"\tsubject alt name(s) or common name do not match \"%s\"\n",
- conn->host.dispname);
+ dispname);
return CURLE_PEER_FAILED_VERIFICATION;
}
else {
infof(data,
"\tsubject alt name(s) and/or common name do not match \"%s\"\n",
- conn->host.dispname);
+ dispname);
return CURLE_OK;
}
#endif
}
#if LIBCYASSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
else if(ASN_NO_SIGNER_E == detail) {
- if(data->set.ssl.verifypeer) {
+ if(SSL_CONN_CONFIG(verifypeer)) {
failf(data, "\tCA signer not available for verification\n");
return CURLE_SSL_CACERT_BADFILE;
}
@@ -509,7 +519,8 @@ cyassl_connect_step2(struct connectdata *conn,
}
memset(&x509_parsed, 0, sizeof x509_parsed);
- Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len);
+ if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
+ return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
pubkey = &x509_parsed.subjectPublicKeyInfo;
if(!pubkey->header || pubkey->end <= pubkey->header) {
@@ -583,7 +594,7 @@ cyassl_connect_step3(struct connectdata *conn,
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
- if(conn->ssl_config.sessionid) {
+ if(data->set.general_ssl.sessionid) {
bool incache;
SSL_SESSION *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
@@ -591,7 +602,8 @@ cyassl_connect_step3(struct connectdata *conn,
our_ssl_sessionid = SSL_get_session(connssl->handle);
Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
+ incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
+ sockindex));
if(incache) {
if(old_ssl_sessionid != our_ssl_sessionid) {
infof(data, "old SSL session ID is stale, removing\n");
@@ -602,7 +614,7 @@ cyassl_connect_step3(struct connectdata *conn,
if(!incache) {
result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
- 0 /* unknown size */);
+ 0 /* unknown size */, sockindex);
if(result) {
Curl_ssl_sessionid_unlock(conn);
failf(data, "failed to store ssl session");
@@ -803,7 +815,8 @@ cyassl_connect_common(struct connectdata *conn,
curl_socket_t readfd = ssl_connect_2_reading==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
- what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
+ what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
+ nonblocking?0:timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
diff --git a/lib/vtls/darwinssl.c b/lib/vtls/darwinssl.c
index ebb9e307..0602cdbd 100644
--- a/lib/vtls/darwinssl.c
+++ b/lib/vtls/darwinssl.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -197,7 +197,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
do {
length = write(sock,
- (char*)dataPtr + bytesSent,
+ (char *)dataPtr + bytesSent,
dataLen - bytesSent);
} while((length > 0) &&
( (bytesSent += length) < dataLen) );
@@ -219,7 +219,8 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
return ortn;
}
-CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) {
+CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher)
+{
switch (cipher) {
/* SSL version 3.0 */
case SSL_RSA_WITH_NULL_MD5:
@@ -364,7 +365,8 @@ CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) {
return "SSL_NULL_WITH_NULL_NULL";
}
-CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) {
+CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher)
+{
switch(cipher) {
/* TLS 1.0 with AES (RFC 3268) */
case TLS_RSA_WITH_AES_128_CBC_SHA:
@@ -883,14 +885,18 @@ static OSStatus CopyIdentityWithLabel(char *label,
SecIdentityRef *out_cert_and_key)
{
OSStatus status = errSecItemNotFound;
+ CFArrayRef keys_list;
+ CFIndex keys_list_count;
+ CFIndex i;
+ CFStringRef common_name;
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
/* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
kSecClassIdentity was introduced in Lion. If both exist, let's use them
to find the certificate. */
if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) {
- CFTypeRef keys[4];
- CFTypeRef values[4];
+ CFTypeRef keys[5];
+ CFTypeRef values[5];
CFDictionaryRef query_dict;
CFStringRef label_cf = CFStringCreateWithCString(NULL, label,
kCFStringEncodingUTF8);
@@ -900,27 +906,59 @@ static OSStatus CopyIdentityWithLabel(char *label,
keys[0] = kSecClass;
values[1] = kCFBooleanTrue; /* we want a reference */
keys[1] = kSecReturnRef;
- values[2] = kSecMatchLimitOne; /* one is enough, thanks */
+ values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the
+ * label matching below worked correctly */
keys[2] = kSecMatchLimit;
/* identity searches need a SecPolicyRef in order to work */
- values[3] = SecPolicyCreateSSL(false, label_cf);
+ values[3] = SecPolicyCreateSSL(false, NULL);
keys[3] = kSecMatchPolicy;
+ /* match the name of the certificate (doesn't work in macOS 10.12.1) */
+ values[4] = label_cf;
+ keys[4] = kSecAttrLabel;
query_dict = CFDictionaryCreate(NULL, (const void **)keys,
- (const void **)values, 4L,
- &kCFCopyStringDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
+ (const void **)values, 5L,
+ &kCFCopyStringDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
CFRelease(values[3]);
- CFRelease(label_cf);
/* Do we have a match? */
- status = SecItemCopyMatching(query_dict, (CFTypeRef *)out_cert_and_key);
+ status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list);
+
+ /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity,
+ * we need to find the correct identity ourselves */
+ if(status == noErr) {
+ keys_list_count = CFArrayGetCount(keys_list);
+ *out_cert_and_key = NULL;
+ for(i=0; i<keys_list_count; i++) {
+ OSStatus err = noErr;
+ SecCertificateRef cert = NULL;
+ *out_cert_and_key =
+ (SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i);
+ err = SecIdentityCopyCertificate(*out_cert_and_key, &cert);
+ if(err == noErr) {
+ SecCertificateCopyCommonName(cert, &common_name);
+ if(CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) {
+ CFRelease(cert);
+ CFRelease(common_name);
+ status = noErr;
+ break;
+ }
+ CFRelease(common_name);
+ }
+ *out_cert_and_key = NULL;
+ status = 1;
+ CFRelease(cert);
+ }
+ }
+
CFRelease(query_dict);
+ CFRelease(label_cf);
}
else {
#if CURL_SUPPORT_MAC_10_6
/* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */
status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
-#endif /* CURL_SUPPORT_MAC_10_7 */
+#endif /* CURL_SUPPORT_MAC_10_6 */
}
#elif CURL_SUPPORT_MAC_10_6
/* For developers building on older cats, we have no choice but to fall back
@@ -955,7 +993,7 @@ static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
/* Here we go: */
status = SecPKCS12Import(pkcs_data, options, &items);
- if(status == noErr && items && CFArrayGetCount(items)) {
+ if(status == errSecSuccess && items && CFArrayGetCount(items)) {
CFDictionaryRef identity_and_trust = CFArrayGetValueAtIndex(items, 0L);
const void *temp_identity = CFDictionaryGetValue(identity_and_trust,
kSecImportItemIdentity);
@@ -1002,6 +1040,12 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
struct Curl_easy *data = conn->data;
curl_socket_t sockfd = conn->sock[sockindex];
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+ const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+ char * const ssl_cert = SSL_SET_OPTION(cert);
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
+ const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
@@ -1052,40 +1096,46 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
/* check to see if we've been told to use an explicit SSL/TLS version */
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
if(SSLSetProtocolVersionMax != NULL) {
- switch(data->set.ssl.version) {
- default:
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
- break;
- case CURL_SSLVERSION_TLSv1_0:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1);
- break;
- case CURL_SSLVERSION_TLSv1_1:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11);
- break;
- case CURL_SSLVERSION_TLSv1_2:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
- break;
- case CURL_SSLVERSION_SSLv3:
- err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv3");
- return CURLE_SSL_CONNECT_ERROR;
- }
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
- break;
- case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv2");
- return CURLE_SSL_CONNECT_ERROR;
- }
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2);
+ switch(conn->ssl_config.version) {
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1);
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11);
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
+ break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "DarwinSSL: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+ case CURL_SSLVERSION_SSLv3:
+ err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
+ if(err != noErr) {
+ failf(data, "Your version of the OS does not support SSLv3");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
+ break;
+ case CURL_SSLVERSION_SSLv2:
+ err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2);
+ if(err != noErr) {
+ failf(data, "Your version of the OS does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2);
+ break;
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
}
}
else {
@@ -1093,121 +1143,131 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
kSSLProtocolAll,
false);
- switch (data->set.ssl.version) {
- default:
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol1,
- true);
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol11,
- true);
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol12,
- true);
- break;
- case CURL_SSLVERSION_TLSv1_0:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol1,
- true);
- break;
- case CURL_SSLVERSION_TLSv1_1:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol11,
- true);
- break;
- case CURL_SSLVERSION_TLSv1_2:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol12,
- true);
- break;
- case CURL_SSLVERSION_SSLv3:
- err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kSSLProtocol3,
- true);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv3");
- return CURLE_SSL_CONNECT_ERROR;
- }
- break;
- case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kSSLProtocol2,
- true);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv2");
- return CURLE_SSL_CONNECT_ERROR;
- }
- break;
- }
-#endif /* CURL_SUPPORT_MAC_10_8 */
- }
-#else
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
- switch(data->set.ssl.version) {
- default:
+ switch (conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol1,
+ true);
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol11,
+ true);
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol12,
+ true);
+ break;
case CURL_SSLVERSION_TLSv1_0:
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
kTLSProtocol1,
true);
break;
case CURL_SSLVERSION_TLSv1_1:
- failf(data, "Your version of the OS does not support TLSv1.1");
- return CURLE_SSL_CONNECT_ERROR;
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol11,
+ true);
+ break;
case CURL_SSLVERSION_TLSv1_2:
- failf(data, "Your version of the OS does not support TLSv1.2");
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol12,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "DarwinSSL: TLS 1.3 is not yet supported");
return CURLE_SSL_CONNECT_ERROR;
- case CURL_SSLVERSION_SSLv2:
+ case CURL_SSLVERSION_SSLv3:
err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kSSLProtocol2,
+ kSSLProtocol3,
true);
if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv2");
+ failf(data, "Your version of the OS does not support SSLv3");
return CURLE_SSL_CONNECT_ERROR;
}
break;
- case CURL_SSLVERSION_SSLv3:
+ case CURL_SSLVERSION_SSLv2:
err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kSSLProtocol3,
+ kSSLProtocol2,
true);
if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv3");
+ failf(data, "Your version of the OS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
}
break;
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+#endif /* CURL_SUPPORT_MAC_10_8 */
+ }
+#else
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
+ switch(conn->ssl_config.version) {
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ case CURL_SSLVERSION_TLSv1_0:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol1,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ failf(data, "Your version of the OS does not support TLSv1.1");
+ return CURLE_SSL_CONNECT_ERROR;
+ case CURL_SSLVERSION_TLSv1_2:
+ failf(data, "Your version of the OS does not support TLSv1.2");
+ return CURLE_SSL_CONNECT_ERROR;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "Your version of the OS does not support TLSv1.3");
+ return CURLE_SSL_CONNECT_ERROR;
+ case CURL_SSLVERSION_SSLv2:
+ err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocol2,
+ true);
+ if(err != noErr) {
+ failf(data, "Your version of the OS does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ break;
+ case CURL_SSLVERSION_SSLv3:
+ err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocol3,
+ true);
+ if(err != noErr) {
+ failf(data, "Your version of the OS does not support SSLv3");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ break;
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
}
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
- if(data->set.str[STRING_KEY]) {
+ if(SSL_SET_OPTION(key)) {
infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
- "Transport. The private key must be in the Keychain.\n");
+ "Transport. The private key must be in the Keychain.\n");
}
- if(data->set.str[STRING_CERT]) {
+ if(ssl_cert) {
SecIdentityRef cert_and_key = NULL;
- bool is_cert_file = is_file(data->set.str[STRING_CERT]);
+ bool is_cert_file = is_file(ssl_cert);
/* User wants to authenticate with a client cert. Look for it:
If we detect that this is a file on disk, then let's load it.
Otherwise, assume that the user wants to use an identity loaded
from the Keychain. */
if(is_cert_file) {
- if(!data->set.str[STRING_CERT_TYPE])
+ if(!SSL_SET_OPTION(cert_type))
infof(data, "WARNING: SSL: Certificate type not set, assuming "
"PKCS#12 format.\n");
- else if(strncmp(data->set.str[STRING_CERT_TYPE], "P12",
- strlen(data->set.str[STRING_CERT_TYPE])) != 0)
+ else if(strncmp(SSL_SET_OPTION(cert_type), "P12",
+ strlen(SSL_SET_OPTION(cert_type))) != 0)
infof(data, "WARNING: SSL: The Security framework only supports "
"loading identities that are in PKCS#12 format.\n");
- err = CopyIdentityFromPKCS12File(data->set.str[STRING_CERT],
- data->set.str[STRING_KEY_PASSWD], &cert_and_key);
+ err = CopyIdentityFromPKCS12File(ssl_cert,
+ SSL_SET_OPTION(key_passwd), &cert_and_key);
}
else
- err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key);
+ err = CopyIdentityWithLabel(ssl_cert, &cert_and_key);
if(err == noErr) {
SecCertificateRef cert = NULL;
@@ -1246,27 +1306,27 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
else {
switch(err) {
- case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
- failf(data, "SSL: Incorrect password for the certificate \"%s\" "
- "and its private key.", data->set.str[STRING_CERT]);
- break;
- case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
- failf(data, "SSL: Couldn't make sense of the data in the "
- "certificate \"%s\" and its private key.",
- data->set.str[STRING_CERT]);
- break;
- case -25260: /* errSecPassphraseRequired */
- failf(data, "SSL The certificate \"%s\" requires a password.",
- data->set.str[STRING_CERT]);
- break;
- case errSecItemNotFound:
- failf(data, "SSL: Can't find the certificate \"%s\" and its private "
- "key in the Keychain.", data->set.str[STRING_CERT]);
- break;
- default:
- failf(data, "SSL: Can't load the certificate \"%s\" and its private "
- "key: OSStatus %d", data->set.str[STRING_CERT], err);
- break;
+ case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
+ failf(data, "SSL: Incorrect password for the certificate \"%s\" "
+ "and its private key.", ssl_cert);
+ break;
+ case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
+ failf(data, "SSL: Couldn't make sense of the data in the "
+ "certificate \"%s\" and its private key.",
+ ssl_cert);
+ break;
+ case -25260: /* errSecPassphraseRequired */
+ failf(data, "SSL The certificate \"%s\" requires a password.",
+ ssl_cert);
+ break;
+ case errSecItemNotFound:
+ failf(data, "SSL: Can't find the certificate \"%s\" and its private "
+ "key in the Keychain.", ssl_cert);
+ break;
+ default:
+ failf(data, "SSL: Can't load the certificate \"%s\" and its private "
+ "key: OSStatus %d", ssl_cert, err);
+ break;
}
return CURLE_SSL_CERTPROBLEM;
}
@@ -1297,8 +1357,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#else
if(SSLSetSessionOption != NULL) {
#endif /* CURL_BUILD_MAC */
- bool break_on_auth = !data->set.ssl.verifypeer ||
- data->set.str[STRING_SSL_CAFILE];
+ bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile;
err = SSLSetSessionOption(connssl->ssl_ctx,
kSSLSessionOptionBreakOnServerAuth,
break_on_auth);
@@ -1310,7 +1369,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
else {
#if CURL_SUPPORT_MAC_10_8
err = SSLSetEnableCertVerify(connssl->ssl_ctx,
- data->set.ssl.verifypeer?true:false);
+ conn->ssl_config.verifypeer?true:false);
if(err != noErr) {
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
@@ -1319,22 +1378,21 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
#else
err = SSLSetEnableCertVerify(connssl->ssl_ctx,
- data->set.ssl.verifypeer?true:false);
+ conn->ssl_config.verifypeer?true:false);
if(err != noErr) {
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
}
#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
- if(data->set.str[STRING_SSL_CAFILE]) {
- bool is_cert_file = is_file(data->set.str[STRING_SSL_CAFILE]);
+ if(ssl_cafile) {
+ bool is_cert_file = is_file(ssl_cafile);
if(!is_cert_file) {
- failf(data, "SSL: can't load CA certificate file %s",
- data->set.str[STRING_SSL_CAFILE]);
+ failf(data, "SSL: can't load CA certificate file %s", ssl_cafile);
return CURLE_SSL_CACERT_BADFILE;
}
- if(!data->set.ssl.verifypeer) {
+ if(!verifypeer) {
failf(data, "SSL: CA certificate set, but certificate verification "
"is disabled");
return CURLE_SSL_CONNECT_ERROR;
@@ -1344,22 +1402,22 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
/* Configure hostname check. SNI is used if available.
* Both hostname check and SNI require SSLSetPeerDomainName().
* Also: the verifyhost setting influences SNI usage */
- if(data->set.ssl.verifyhost) {
- err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name,
- strlen(conn->host.name));
+ if(conn->ssl_config.verifyhost) {
+ err = SSLSetPeerDomainName(connssl->ssl_ctx, hostname,
+ strlen(hostname));
if(err != noErr) {
infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n",
err);
}
- if((Curl_inet_pton(AF_INET, conn->host.name, &addr))
+ if((Curl_inet_pton(AF_INET, hostname, &addr))
#ifdef ENABLE_IPV6
- || (Curl_inet_pton(AF_INET6, conn->host.name, &addr))
+ || (Curl_inet_pton(AF_INET6, hostname, &addr))
#endif
) {
- infof(data, "WARNING: using IP address, SNI is being disabled by "
- "the OS.\n");
+ infof(data, "WARNING: using IP address, SNI is being disabled by "
+ "the OS.\n");
}
}
@@ -1382,7 +1440,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
running in an affected version of OS X. */
if(darwinver_maj == 12 && darwinver_min <= 3 &&
all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
- continue;
+ continue;
}
#endif /* CURL_BUILD_MAC */
switch(all_ciphers[i]) {
@@ -1438,6 +1496,16 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
/* Disable IDEA: */
case SSL_RSA_WITH_IDEA_CBC_SHA:
case SSL_RSA_WITH_IDEA_CBC_MD5:
+ /* Disable RC4: */
+ case SSL_RSA_WITH_RC4_128_MD5:
+ case SSL_RSA_WITH_RC4_128_SHA:
+ case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */
+ case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/
+ case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */
+ case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */
+ case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */
+ case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */
+ case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */
break;
default: /* enable everything else */
allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
@@ -1464,21 +1532,22 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
/* We want to enable 1/n-1 when using a CBC cipher unless the user
specifically doesn't want us doing that: */
if(SSLSetSessionOption != NULL) {
+ /* TODO s/data->set.ssl.enable_beast/SSL_SET_OPTION(enable_beast)/g */
SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
- !data->set.ssl_enable_beast);
+ !data->set.ssl.enable_beast);
SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionFalseStart,
data->set.ssl.falsestart); /* false start support */
}
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
/* Check if there's a cached ID we can/should use here! */
- if(conn->ssl_config.sessionid) {
+ if(data->set.general_ssl.sessionid) {
char *ssl_sessionid;
size_t ssl_sessionid_len;
Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
- &ssl_sessionid_len)) {
+ &ssl_sessionid_len, sockindex)) {
/* we got a session id, use it! */
err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
Curl_ssl_sessionid_unlock(conn);
@@ -1494,9 +1563,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
else {
CURLcode result;
ssl_sessionid =
- aprintf("%s:%d:%d:%s:%hu", data->set.str[STRING_SSL_CAFILE],
- data->set.ssl.verifypeer, data->set.ssl.verifyhost,
- conn->host.name, conn->remote_port);
+ aprintf("%s:%d:%d:%s:%hu", ssl_cafile,
+ verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
ssl_sessionid_len = strlen(ssl_sessionid);
err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
@@ -1506,7 +1574,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
- result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len);
+ result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len,
+ sockindex);
Curl_ssl_sessionid_unlock(conn);
if(result) {
failf(data, "failed to store ssl session");
@@ -1832,6 +1901,8 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
OSStatus err;
SSLCipherSuite cipher;
SSLProtocol protocol = 0;
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|| ssl_connect_2_reading == connssl->connecting_state
@@ -1850,8 +1921,8 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
/* The below is errSSLServerAuthCompleted; it's not defined in
Leopard's headers */
case -9841:
- if(data->set.str[STRING_SSL_CAFILE]) {
- int res = verify_cert(data->set.str[STRING_SSL_CAFILE], data,
+ if(SSL_CONN_CONFIG(CAfile)) {
+ int res = verify_cert(SSL_CONN_CONFIG(CAfile), data,
connssl->ssl_ctx);
if(res != CURLE_OK)
return res;
@@ -1920,7 +1991,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
return CURLE_SSL_CONNECT_ERROR;
default:
failf(data, "Unknown SSL protocol error in connection to %s:%d",
- conn->host.name, err);
+ hostname, err);
return CURLE_SSL_CONNECT_ERROR;
}
}
@@ -2140,7 +2211,8 @@ darwinssl_connect_common(struct connectdata *conn,
curl_socket_t readfd = ssl_connect_2_reading ==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
- what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
+ what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
+ nonblocking?0:timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -2262,8 +2334,7 @@ int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
rc = 0;
- what = Curl_socket_ready(conn->sock[sockindex],
- CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+ what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
for(;;) {
if(what < 0) {
@@ -2291,7 +2362,7 @@ int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
if(nread <= 0)
break;
- what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0);
+ what = SOCKET_READABLE(conn->sock[sockindex], 0);
}
return rc;
@@ -2380,7 +2451,8 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
(void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum);
}
-bool Curl_darwinssl_false_start(void) {
+bool Curl_darwinssl_false_start(void)
+{
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
if(SSLSetSessionOption != NULL)
return TRUE;
diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
index 55a55ef5..6cac9573 100644
--- a/lib/vtls/gskit.c
+++ b/lib/vtls/gskit.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -72,7 +72,7 @@
#include "vtls.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
-#include "strequal.h"
+#include "strcase.h"
#include "x509asn1.h"
#include "curl_printf.h"
@@ -81,6 +81,10 @@
#include "memdebug.h"
+/* Directions. */
+#define SOS_READ 0x01
+#define SOS_WRITE 0x02
+
/* SSL version flags. */
#define CURL_GSKPROTO_SSLV2 0
#define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2)
@@ -289,10 +293,11 @@ static CURLcode set_callback(struct Curl_easy *data,
}
-static CURLcode set_ciphers(struct Curl_easy *data,
+static CURLcode set_ciphers(struct connectdata *conn,
gsk_handle h, unsigned int *protoflags)
{
- const char *cipherlist = data->set.str[STRING_SSL_CIPHER_LIST];
+ struct Curl_easy *data = conn->data;
+ const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
const char *clp;
const gskit_cipher *ctp;
int i;
@@ -340,7 +345,7 @@ static CURLcode set_ciphers(struct Curl_easy *data,
break;
/* Search the cipher in our table. */
for(ctp = ciphertable; ctp->name; ctp++)
- if(strnequal(ctp->name, clp, l) && !ctp->name[l])
+ if(strncasecompare(ctp->name, clp, l) && !ctp->name[l])
break;
if(!ctp->name) {
failf(data, "Unknown cipher %.*s", l, clp);
@@ -500,17 +505,195 @@ static void close_async_handshake(struct ssl_connect_data *connssl)
connssl->iocport = -1;
}
+/* SSL over SSL
+ * Problems:
+ * 1) GSKit can only perform SSL on an AF_INET or AF_INET6 stream socket. To
+ * pipe an SSL stream into another, it is therefore needed to have a pair
+ * of such communicating sockets and handle the pipelining explicitly.
+ * 2) OS/400 socketpair() is only implemented for domain AF_UNIX, thus cannot
+ * be used to produce the pipeline.
+ * The solution is to simulate socketpair() for AF_INET with low-level API
+ * listen(), bind() and connect().
+ */
+
+static int
+inetsocketpair(int sv[2])
+{
+ int lfd; /* Listening socket. */
+ int sfd; /* Server socket. */
+ int cfd; /* Client socket. */
+ int len;
+ struct sockaddr_in addr1;
+ struct sockaddr_in addr2;
+
+ /* Create listening socket on a local dynamic port. */
+ lfd = socket(AF_INET, SOCK_STREAM, 0);
+ if(lfd < 0)
+ return -1;
+ memset((char *) &addr1, 0, sizeof addr1);
+ addr1.sin_family = AF_INET;
+ addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr1.sin_port = 0;
+ if(bind(lfd, (struct sockaddr *) &addr1, sizeof addr1) ||
+ listen(lfd, 2) < 0) {
+ close(lfd);
+ return -1;
+ }
+
+ /* Get the allocated port. */
+ len = sizeof addr1;
+ if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) {
+ close(lfd);
+ return -1;
+ }
+
+ /* Create the client socket. */
+ cfd = socket(AF_INET, SOCK_STREAM, 0);
+ if(cfd < 0) {
+ close(lfd);
+ return -1;
+ }
+
+ /* Request unblocking connection to the listening socket. */
+ curlx_nonblock(cfd, TRUE);
+ if(connect(cfd, (struct sockaddr *) &addr1, sizeof addr1) < 0 &&
+ errno != EINPROGRESS) {
+ close(lfd);
+ close(cfd);
+ return -1;
+ }
+
+ /* Get the client dynamic port for intrusion check below. */
+ len = sizeof addr2;
+ if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) {
+ close(lfd);
+ close(cfd);
+ return -1;
+ }
+
+ /* Accept the incoming connection and get the server socket. */
+ curlx_nonblock(lfd, TRUE);
+ for(;;) {
+ len = sizeof addr1;
+ sfd = accept(lfd, (struct sockaddr *) &addr1, &len);
+ if(sfd < 0) {
+ close(lfd);
+ close(cfd);
+ return -1;
+ }
-static void close_one(struct ssl_connect_data *conn,
- struct Curl_easy *data)
+ /* Check for possible intrusion from an external process. */
+ if(addr1.sin_addr.s_addr == addr2.sin_addr.s_addr &&
+ addr1.sin_port == addr2.sin_port)
+ break;
+
+ /* Intrusion: reject incoming connection. */
+ close(sfd);
+ }
+
+ /* Done, return sockets and succeed. */
+ close(lfd);
+ curlx_nonblock(cfd, FALSE);
+ sv[0] = cfd;
+ sv[1] = sfd;
+ return 0;
+}
+
+static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
+ int directions)
{
- if(conn->handle) {
- gskit_status(data, gsk_secure_soc_close(&conn->handle),
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex];
+ fd_set fds_read;
+ fd_set fds_write;
+ int n;
+ int m;
+ int i;
+ int ret = 0;
+ struct timeval tv = {0, 0};
+ char buf[CURL_MAX_WRITE_SIZE];
+
+ if(!connssl->use || !connproxyssl->use)
+ return 0; /* No SSL over SSL: OK. */
+
+ FD_ZERO(&fds_read);
+ FD_ZERO(&fds_write);
+ n = -1;
+ if(directions & SOS_READ) {
+ FD_SET(connssl->remotefd, &fds_write);
+ n = connssl->remotefd;
+ }
+ if(directions & SOS_WRITE) {
+ FD_SET(connssl->remotefd, &fds_read);
+ n = connssl->remotefd;
+ FD_SET(conn->sock[sockindex], &fds_write);
+ if(n < conn->sock[sockindex])
+ n = conn->sock[sockindex];
+ }
+ i = select(n + 1, &fds_read, &fds_write, NULL, &tv);
+ if(i < 0)
+ return -1; /* Select error. */
+
+ if(FD_ISSET(connssl->remotefd, &fds_write)) {
+ /* Try getting data from HTTPS proxy and pipe it upstream. */
+ n = 0;
+ i = gsk_secure_soc_read(connproxyssl->handle, buf, sizeof buf, &n);
+ switch(i) {
+ case GSK_OK:
+ if(n) {
+ i = write(connssl->remotefd, buf, n);
+ if(i < 0)
+ return -1;
+ ret = 1;
+ }
+ break;
+ case GSK_OS400_ERROR_TIMED_OUT:
+ case GSK_WOULD_BLOCK:
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ if(FD_ISSET(connssl->remotefd, &fds_read) &&
+ FD_ISSET(conn->sock[sockindex], &fds_write)) {
+ /* Pipe data to HTTPS proxy. */
+ n = read(connssl->remotefd, buf, sizeof buf);
+ if(n < 0)
+ return -1;
+ if(n) {
+ i = gsk_secure_soc_write(connproxyssl->handle, buf, n, &m);
+ if(i != GSK_OK || n != m)
+ return -1;
+ ret = 1;
+ }
+ }
+
+ return ret; /* OK */
+}
+
+
+static void close_one(struct ssl_connect_data *connssl,
+ struct connectdata *conn, int sockindex)
+{
+ if(connssl->handle) {
+ gskit_status(conn->data, gsk_secure_soc_close(&connssl->handle),
"gsk_secure_soc_close()", 0);
- conn->handle = (gsk_handle) NULL;
+ /* Last chance to drain output. */
+ while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
+ ;
+ connssl->handle = (gsk_handle) NULL;
+ if(connssl->localfd >= 0) {
+ close(connssl->localfd);
+ connssl->localfd = -1;
+ }
+ if(connssl->remotefd >= 0) {
+ close(connssl->remotefd);
+ connssl->remotefd = -1;
+ }
}
- if(conn->iocport >= 0)
- close_async_handshake(conn);
+ if(connssl->iocport >= 0)
+ close_async_handshake(connssl);
}
@@ -518,13 +701,18 @@ static ssize_t gskit_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, CURLcode *curlcode)
{
struct Curl_easy *data = conn->data;
- CURLcode cc;
+ CURLcode cc = CURLE_SEND_ERROR;
int written;
- cc = gskit_status(data,
- gsk_secure_soc_write(conn->ssl[sockindex].handle,
- (char *) mem, (int) len, &written),
- "gsk_secure_soc_write()", CURLE_SEND_ERROR);
+ if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
+ cc = gskit_status(data,
+ gsk_secure_soc_write(conn->ssl[sockindex].handle,
+ (char *) mem, (int) len, &written),
+ "gsk_secure_soc_write()", CURLE_SEND_ERROR);
+ if(cc == CURLE_OK)
+ if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0)
+ cc = CURLE_SEND_ERROR;
+ }
if(cc != CURLE_OK) {
*curlcode = cc;
written = -1;
@@ -539,15 +727,23 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
struct Curl_easy *data = conn->data;
int buffsize;
int nread;
- CURLcode cc;
+ CURLcode cc = CURLE_RECV_ERROR;
- buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
- cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
- buf, buffsize, &nread),
- "gsk_secure_soc_read()", CURLE_RECV_ERROR);
- if(cc != CURLE_OK) {
+ if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
+ buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
+ cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
+ buf, buffsize, &nread),
+ "gsk_secure_soc_read()", CURLE_RECV_ERROR);
+ }
+ switch(cc) {
+ case CURLE_OK:
+ break;
+ case CURLE_OPERATION_TIMEDOUT:
+ cc = CURLE_AGAIN;
+ default:
*curlcode = cc;
nread = -1;
+ break;
}
return (ssize_t) nread;
}
@@ -560,18 +756,26 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
gsk_handle envir;
CURLcode result;
int rc;
- char *keyringfile;
- char *keyringpwd;
- char *keyringlabel;
- char *sni;
+ const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
+ const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
+ const char * const keyringlabel = SSL_SET_OPTION(cert);
+ const long int ssl_version = SSL_CONN_CONFIG(version);
+ const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+ const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
+ conn->host.name;
+ const char *sni;
unsigned int protoflags;
long timeout;
Qso_OverlappedIO_t commarea;
+ int sockpair[2];
+ static const int sobufsize = CURL_MAX_WRITE_SIZE;
/* Create SSL environment, start (preferably asynchronous) handshake. */
connssl->handle = (gsk_handle) NULL;
connssl->iocport = -1;
+ connssl->localfd = -1;
+ connssl->remotefd = -1;
/* GSKit supports two ways of specifying an SSL context: either by
* application identifier (that should have been defined at the system
@@ -586,9 +790,6 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
* application identifier mode is tried first, as recommended in IBM doc.
*/
- keyringfile = data->set.str[STRING_SSL_CAFILE];
- keyringpwd = data->set.str[STRING_KEY_PASSWD];
- keyringlabel = data->set.str[STRING_CERT];
envir = (gsk_handle) NULL;
if(keyringlabel && *keyringlabel && !keyringpwd &&
@@ -613,19 +814,36 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
if(result)
return result;
+ /* Establish a pipelining socket pair for SSL over SSL. */
+ if(conn->proxy_ssl[sockindex].use) {
+ if(inetsocketpair(sockpair))
+ return CURLE_SSL_CONNECT_ERROR;
+ connssl->localfd = sockpair[0];
+ connssl->remotefd = sockpair[1];
+ setsockopt(connssl->localfd, SOL_SOCKET, SO_RCVBUF,
+ (void *) sobufsize, sizeof sobufsize);
+ setsockopt(connssl->remotefd, SOL_SOCKET, SO_RCVBUF,
+ (void *) sobufsize, sizeof sobufsize);
+ setsockopt(connssl->localfd, SOL_SOCKET, SO_SNDBUF,
+ (void *) sobufsize, sizeof sobufsize);
+ setsockopt(connssl->remotefd, SOL_SOCKET, SO_SNDBUF,
+ (void *) sobufsize, sizeof sobufsize);
+ curlx_nonblock(connssl->localfd, TRUE);
+ curlx_nonblock(connssl->remotefd, TRUE);
+ }
+
/* Determine which SSL/TLS version should be enabled. */
- protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
- CURL_GSKPROTO_TLSV12_MASK;
- sni = conn->host.name;
- switch (data->set.ssl.version) {
+ sni = hostname;
+ switch (ssl_version) {
case CURL_SSLVERSION_SSLv2:
protoflags = CURL_GSKPROTO_SSLV2_MASK;
- sni = (char *) NULL;
+ sni = NULL;
break;
case CURL_SSLVERSION_SSLv3:
protoflags = CURL_GSKPROTO_SSLV3_MASK;
- sni = (char *) NULL;
+ sni = NULL;
break;
+ case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
protoflags = CURL_GSKPROTO_TLSV10_MASK |
CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
@@ -639,6 +857,12 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
case CURL_SSLVERSION_TLSv1_2:
protoflags = CURL_GSKPROTO_TLSV12_MASK;
break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "GSKit: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
}
/* Process SNI. Ignore if not supported (on OS400 < V7R1). */
@@ -661,9 +885,12 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
(timeout + 999) / 1000);
}
if(!result)
- result = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]);
+ result = set_numeric(data, connssl->handle, GSK_OS400_READ_TIMEOUT, 1);
if(!result)
- result = set_ciphers(data, connssl->handle, &protoflags);
+ result = set_numeric(data, connssl->handle, GSK_FD, connssl->localfd >= 0?
+ connssl->localfd: conn->sock[sockindex]);
+ if(!result)
+ result = set_ciphers(conn, connssl->handle, &protoflags);
if(!protoflags) {
failf(data, "No SSL protocol/cipher combination enabled");
result = CURLE_SSL_CIPHER;
@@ -706,7 +933,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
}
if(!result)
result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
- data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL:
+ verifypeer? GSK_SERVER_AUTH_FULL:
GSK_SERVER_AUTH_PASSTHRU, FALSE);
if(!result) {
@@ -730,6 +957,10 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
else if(errno != ENOBUFS)
result = gskit_status(data, GSK_ERROR_IO,
"QsoCreateIOCompletionPort()", 0);
+ else if(conn->proxy_ssl[sockindex].use) {
+ /* Cannot pipeline while handshaking synchronously. */
+ result = CURLE_SSL_CONNECT_ERROR;
+ }
else {
/* No more completion port available. Use synchronous IO. */
result = gskit_status(data, gsk_secure_soc_init(connssl->handle),
@@ -742,7 +973,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
}
/* Error: rollback. */
- close_one(connssl, data);
+ close_one(connssl, conn, sockindex);
return result;
}
@@ -870,9 +1101,8 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
curl_X509certificate x509;
curl_asn1Element *p;
- if(!cert)
+ if(Curl_parseX509(&x509, cert, certend))
return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
- Curl_parseX509(&x509, cert, certend);
p = &x509.subjectPublicKeyInfo;
result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header);
if(result) {
@@ -913,6 +1143,11 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
result = gskit_connect_step1(conn, sockindex);
}
+ /* Handle handshake pipelining. */
+ if(!result)
+ if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
+ result = CURLE_SSL_CONNECT_ERROR;
+
/* Step 2: check if handshake is over. */
if(!result && connssl->connecting_state == ssl_connect_2) {
/* check allowed time left */
@@ -927,12 +1162,17 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
result = gskit_connect_step2(conn, sockindex, nonblocking);
}
+ /* Handle handshake pipelining. */
+ if(!result)
+ if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
+ result = CURLE_SSL_CONNECT_ERROR;
+
/* Step 3: gather certificate info, verify host. */
if(!result && connssl->connecting_state == ssl_connect_3)
result = gskit_connect_step3(conn, sockindex);
if(result)
- close_one(connssl, data);
+ close_one(connssl, conn, sockindex);
else if(connssl->connecting_state == ssl_connect_done) {
connssl->state = ssl_connection_complete;
connssl->connecting_state = ssl_connect_1;
@@ -976,11 +1216,8 @@ CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
void Curl_gskit_close(struct connectdata *conn, int sockindex)
{
- struct Curl_easy *data = conn->data;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-
- if(connssl->use)
- close_one(connssl, data);
+ close_one(&conn->ssl[sockindex], conn, sockindex);
+ close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
}
@@ -999,10 +1236,10 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
return 0;
- close_one(connssl, data);
+ close_one(connssl, conn, sockindex);
rc = 0;
- what = Curl_socket_ready(conn->sock[sockindex],
- CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+ what = SOCKET_READABLE(conn->sock[sockindex],
+ SSL_SHUTDOWN_TIMEOUT);
for(;;) {
if(what < 0) {
@@ -1031,7 +1268,7 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
if(nread <= 0)
break;
- what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0);
+ what = SOCKET_READABLE(conn->sock[sockindex], 0);
}
return rc;
diff --git a/lib/vtls/gskit.h b/lib/vtls/gskit.h
index 41483cba..e258a29f 100644
--- a/lib/vtls/gskit.h
+++ b/lib/vtls/gskit.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -64,7 +64,7 @@ int Curl_gskit_check_cxn(struct connectdata *cxn);
#define curlssl_version Curl_gskit_version
#define curlssl_check_cxn(x) Curl_gskit_check_cxn(x)
#define curlssl_data_pending(x,y) 0
-#define curlssl_random(x,y,z) -1
+#define curlssl_random(x,y,z) (x=x, y=y, z=z, CURLE_NOT_BUILT_IN)
#endif /* USE_GSKIT */
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index 1c3e6b15..5249dd49 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -52,7 +52,7 @@
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "warnless.h"
#include "x509asn1.h"
#include "curl_printf.h"
@@ -68,7 +68,7 @@
#define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p))
#endif
#ifndef GNUTLS_INT_TO_POINTER_CAST
-#define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i))
+#define GNUTLS_INT_TO_POINTER_CAST(i) ((void *) (long) (i))
#endif
/* Enable GnuTLS debugging by defining GTLSDEBUG */
@@ -171,6 +171,16 @@ static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
return ret;
}
+static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len)
+{
+ return gnutls_record_send((gnutls_session_t) s, buf, len);
+}
+
+static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len)
+{
+ return gnutls_record_recv((gnutls_session_t) s, buf, len);
+}
+
/* Curl_gtls_init()
*
* Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
@@ -251,7 +261,8 @@ out:
return loaded_file;
}
-static void unload_file(gnutls_datum_t data) {
+static void unload_file(gnutls_datum_t data)
+{
free(data.data);
}
@@ -289,7 +300,7 @@ static CURLcode handshake(struct connectdata *conn,
curl_socket_t readfd = ssl_connect_2_reading==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
- what = Curl_socket_ready(readfd, writefd,
+ what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
nonblocking?0:
timeout_ms?timeout_ms:1000);
if(what < 0) {
@@ -356,9 +367,9 @@ static gnutls_x509_crt_fmt_t do_file_type(const char *type)
{
if(!type || !type[0])
return GNUTLS_X509_FMT_PEM;
- if(Curl_raw_equal(type, "PEM"))
+ if(strcasecompare(type, "PEM"))
return GNUTLS_X509_FMT_PEM;
- if(Curl_raw_equal(type, "DER"))
+ if(strcasecompare(type, "DER"))
return GNUTLS_X509_FMT_DER;
return -1;
}
@@ -371,6 +382,9 @@ gtls_connect_step1(struct connectdata *conn,
gnutls_session_t session;
int rc;
bool sni = TRUE; /* default is SNI enabled */
+ void *transport_ptr = NULL;
+ gnutls_push_func gnutls_transport_push = NULL;
+ gnutls_pull_func gnutls_transport_pull = NULL;
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
@@ -397,10 +411,13 @@ gtls_connect_step1(struct connectdata *conn,
requested in the priority string, so treat it specially
*/
#define GNUTLS_SRP "+SRP"
- const char* prioritylist;
+ const char *prioritylist;
const char *err = NULL;
#endif
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
+
if(conn->ssl[sockindex].state == ssl_connection_complete)
/* to make us tolerant against being called more than once for the
same connection */
@@ -409,12 +426,11 @@ gtls_connect_step1(struct connectdata *conn,
if(!gtls_inited)
Curl_gtls_init();
- /* GnuTLS only supports SSLv3 and TLSv1 */
- if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+ if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
failf(data, "GnuTLS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
}
- else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
+ else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)
sni = FALSE; /* SSLv3 has no SNI */
/* allocate a cred struct */
@@ -425,8 +441,8 @@ gtls_connect_step1(struct connectdata *conn,
}
#ifdef USE_TLS_SRP
- if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
- infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
+ if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
+ infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
rc = gnutls_srp_allocate_client_credentials(
&conn->ssl[sockindex].srp_client_cred);
@@ -438,8 +454,8 @@ gtls_connect_step1(struct connectdata *conn,
rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
srp_client_cred,
- data->set.ssl.username,
- data->set.ssl.password);
+ SSL_SET_OPTION(username),
+ SSL_SET_OPTION(password));
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_srp_set_client_cred() failed: %s",
gnutls_strerror(rc));
@@ -448,64 +464,64 @@ gtls_connect_step1(struct connectdata *conn,
}
#endif
- if(data->set.ssl.CAfile) {
+ if(SSL_CONN_CONFIG(CAfile)) {
/* set the trusted CA cert bundle file */
gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
- data->set.ssl.CAfile,
+ SSL_CONN_CONFIG(CAfile),
GNUTLS_X509_FMT_PEM);
if(rc < 0) {
infof(data, "error reading ca cert file %s (%s)\n",
- data->set.ssl.CAfile, gnutls_strerror(rc));
- if(data->set.ssl.verifypeer)
+ SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
+ if(SSL_CONN_CONFIG(verifypeer))
return CURLE_SSL_CACERT_BADFILE;
}
else
- infof(data, "found %d certificates in %s\n",
- rc, data->set.ssl.CAfile);
+ infof(data, "found %d certificates in %s\n", rc,
+ SSL_CONN_CONFIG(CAfile));
}
#ifdef HAS_CAPATH
- if(data->set.ssl.CApath) {
+ if(SSL_CONN_CONFIG(CApath)) {
/* set the trusted CA cert directory */
rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred,
- data->set.ssl.CApath,
- GNUTLS_X509_FMT_PEM);
+ SSL_CONN_CONFIG(CApath),
+ GNUTLS_X509_FMT_PEM);
if(rc < 0) {
infof(data, "error reading ca cert file %s (%s)\n",
- data->set.ssl.CAfile, gnutls_strerror(rc));
- if(data->set.ssl.verifypeer)
+ SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
+ if(SSL_CONN_CONFIG(verifypeer))
return CURLE_SSL_CACERT_BADFILE;
}
else
infof(data, "found %d certificates in %s\n",
- rc, data->set.ssl.CApath);
+ rc, SSL_CONN_CONFIG(CApath));
}
#endif
#ifdef CURL_CA_FALLBACK
/* use system ca certificate store as fallback */
- if(data->set.ssl.verifypeer &&
- !(data->set.ssl.CAfile || data->set.ssl.CApath)) {
+ if(SSL_CONN_CONFIG(verifypeer) &&
+ !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
gnutls_certificate_set_x509_system_trust(conn->ssl[sockindex].cred);
}
#endif
- if(data->set.ssl.CRLfile) {
+ if(SSL_SET_OPTION(CRLfile)) {
/* set the CRL list file */
rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
- data->set.ssl.CRLfile,
+ SSL_SET_OPTION(CRLfile),
GNUTLS_X509_FMT_PEM);
if(rc < 0) {
failf(data, "error reading crl file %s (%s)",
- data->set.ssl.CRLfile, gnutls_strerror(rc));
+ SSL_SET_OPTION(CRLfile), gnutls_strerror(rc));
return CURLE_SSL_CRL_BADFILE;
}
else
infof(data, "found %d CRL in %s\n",
- rc, data->set.ssl.CRLfile);
+ rc, SSL_SET_OPTION(CRLfile));
}
/* Initialize TLS session as a client */
@@ -518,13 +534,13 @@ gtls_connect_step1(struct connectdata *conn,
/* convenient assign */
session = conn->ssl[sockindex].session;
- if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
+ if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
#ifdef ENABLE_IPV6
- (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
+ (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
#endif
sni &&
- (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name,
- strlen(conn->host.name)) < 0))
+ (gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname,
+ strlen(hostname)) < 0))
infof(data, "WARNING: failed to configure server name indication (SNI) "
"TLS extension\n");
@@ -545,13 +561,13 @@ gtls_connect_step1(struct connectdata *conn,
if(rc != GNUTLS_E_SUCCESS)
return CURLE_SSL_CONNECT_ERROR;
- if(data->set.ssl.cipher_list != NULL) {
+ if(SSL_CONN_CONFIG(cipher_list) != NULL) {
failf(data, "can't pass a custom cipher list to older GnuTLS"
" versions");
return CURLE_SSL_CONNECT_ERROR;
}
- switch (data->set.ssl.version) {
+ switch (SSL_CONN_CONFIG(version) {
case CURL_SSLVERSION_SSLv3:
protocol_priority[0] = GNUTLS_SSL3;
break;
@@ -569,12 +585,16 @@ gtls_connect_step1(struct connectdata *conn,
break;
case CURL_SSLVERSION_TLSv1_2:
protocol_priority[0] = GNUTLS_TLS1_2;
- break;
- case CURL_SSLVERSION_SSLv2:
- default:
+ break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "GnuTLS: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+ case CURL_SSLVERSION_SSLv2:
failf(data, "GnuTLS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
- break;
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
}
rc = gnutls_protocol_set_priority(session, protocol_priority);
if(rc != GNUTLS_E_SUCCESS) {
@@ -586,7 +606,7 @@ gtls_connect_step1(struct connectdata *conn,
/* Ensure +SRP comes at the *end* of all relevant strings so that it can be
* removed if a run-time error indicates that SRP is not supported by this
* GnuTLS version */
- switch (data->set.ssl.version) {
+ switch (SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_SSLv3:
prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
sni = false;
@@ -607,11 +627,15 @@ gtls_connect_step1(struct connectdata *conn,
prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
"+VERS-TLS1.2:" GNUTLS_SRP;
break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "GnuTLS: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
case CURL_SSLVERSION_SSLv2:
- default:
failf(data, "GnuTLS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
- break;
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
}
rc = gnutls_priority_set_direct(session, prioritylist, &err);
if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
@@ -661,8 +685,8 @@ gtls_connect_step1(struct connectdata *conn,
}
#endif
- if(data->set.str[STRING_CERT]) {
- if(data->set.str[STRING_KEY_PASSWD]) {
+ if(SSL_SET_OPTION(cert)) {
+ if(SSL_SET_OPTION(key_passwd)) {
#if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
const unsigned int supported_key_encryption_algorithms =
GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
@@ -671,11 +695,11 @@ gtls_connect_step1(struct connectdata *conn,
GNUTLS_PKCS_USE_PBES2_AES_256;
rc = gnutls_certificate_set_x509_key_file2(
conn->ssl[sockindex].cred,
- data->set.str[STRING_CERT],
- data->set.str[STRING_KEY] ?
- data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
- do_file_type(data->set.str[STRING_CERT_TYPE]),
- data->set.str[STRING_KEY_PASSWD],
+ SSL_SET_OPTION(cert),
+ SSL_SET_OPTION(key) ?
+ SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
+ do_file_type(SSL_SET_OPTION(cert_type)),
+ SSL_SET_OPTION(key_passwd),
supported_key_encryption_algorithms);
if(rc != GNUTLS_E_SUCCESS) {
failf(data,
@@ -689,15 +713,14 @@ gtls_connect_step1(struct connectdata *conn,
#endif
}
else {
- rc = gnutls_certificate_set_x509_key_file(
+ if(gnutls_certificate_set_x509_key_file(
conn->ssl[sockindex].cred,
- data->set.str[STRING_CERT],
- data->set.str[STRING_KEY] ?
- data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
- do_file_type(data->set.str[STRING_CERT_TYPE]) );
- if(rc != GNUTLS_E_SUCCESS) {
- failf(data, "error reading X.509 key or certificate file: %s",
- gnutls_strerror(rc));
+ SSL_SET_OPTION(cert),
+ SSL_SET_OPTION(key) ?
+ SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
+ do_file_type(SSL_SET_OPTION(cert_type)) ) !=
+ GNUTLS_E_SUCCESS) {
+ failf(data, "error reading X.509 key or certificate file");
return CURLE_SSL_CONNECT_ERROR;
}
}
@@ -705,7 +728,7 @@ gtls_connect_step1(struct connectdata *conn,
#ifdef USE_TLS_SRP
/* put the credentials to the current session */
- if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
+ if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
conn->ssl[sockindex].srp_client_cred);
if(rc != GNUTLS_E_SUCCESS) {
@@ -724,19 +747,30 @@ gtls_connect_step1(struct connectdata *conn,
}
}
- /* set the connection handle (file descriptor for the socket) */
- gnutls_transport_set_ptr(session,
- GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]));
+ if(conn->proxy_ssl[sockindex].use) {
+ transport_ptr = conn->proxy_ssl[sockindex].session;
+ gnutls_transport_push = Curl_gtls_push_ssl;
+ gnutls_transport_pull = Curl_gtls_pull_ssl;
+ }
+ else {
+ /* file descriptor for the socket */
+ transport_ptr = GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]);
+ gnutls_transport_push = Curl_gtls_push;
+ gnutls_transport_pull = Curl_gtls_pull;
+ }
+
+ /* set the connection handle */
+ gnutls_transport_set_ptr(session, transport_ptr);
/* register callback functions to send and receive data. */
- gnutls_transport_set_push_function(session, Curl_gtls_push);
- gnutls_transport_set_pull_function(session, Curl_gtls_pull);
+ gnutls_transport_set_push_function(session, gnutls_transport_push);
+ gnutls_transport_set_pull_function(session, gnutls_transport_pull);
/* lowat must be set to zero when using custom push and pull functions. */
gnutls_transport_set_lowat(session, 0);
#ifdef HAS_OCSP
- if(data->set.ssl.verifystatus) {
+ if(SSL_CONN_CONFIG(verifystatus)) {
rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
@@ -747,12 +781,12 @@ gtls_connect_step1(struct connectdata *conn,
/* This might be a reconnect, so we check for a session ID in the cache
to speed up things */
- if(conn->ssl_config.sessionid) {
+ if(data->set.general_ssl.sessionid) {
void *ssl_sessionid;
size_t ssl_idsize;
Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
+ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) {
/* we got a session id, use it! */
gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
@@ -847,8 +881,9 @@ gtls_connect_step3(struct connectdata *conn,
gnutls_datum_t proto;
#endif
CURLcode result = CURLE_OK;
-
gnutls_protocol_t version = gnutls_protocol_get_version(session);
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
/* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
@@ -866,13 +901,13 @@ gtls_connect_step3(struct connectdata *conn,
chainp = gnutls_certificate_get_peers(session, &cert_list_size);
if(!chainp) {
- if(data->set.ssl.verifypeer ||
- data->set.ssl.verifyhost ||
- data->set.ssl.issuercert) {
+ if(SSL_CONN_CONFIG(verifypeer) ||
+ SSL_CONN_CONFIG(verifyhost) ||
+ SSL_SET_OPTION(issuercert)) {
#ifdef USE_TLS_SRP
- if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
- && data->set.ssl.username != NULL
- && !data->set.ssl.verifypeer
+ if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
+ && SSL_SET_OPTION(username) != NULL
+ && !SSL_CONN_CONFIG(verifypeer)
&& gnutls_cipher_get(session)) {
/* no peer cert, but auth is ok if we have SRP user and cipher and no
peer verify */
@@ -905,7 +940,7 @@ gtls_connect_step3(struct connectdata *conn,
}
}
- if(data->set.ssl.verifypeer) {
+ if(SSL_CONN_CONFIG(verifypeer)) {
/* This function will try to verify the peer's certificate and return its
status (trusted, invalid etc.). The value of status should be one or
more of the gnutls_certificate_status_t enumerated elements bitwise
@@ -921,10 +956,11 @@ gtls_connect_step3(struct connectdata *conn,
/* verify_status is a bitmask of gnutls_certificate_status bits */
if(verify_status & GNUTLS_CERT_INVALID) {
- if(data->set.ssl.verifypeer) {
+ if(SSL_CONN_CONFIG(verifypeer)) {
failf(data, "server certificate verification failed. CAfile: %s "
- "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
- data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
+ "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
+ "none",
+ SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
return CURLE_SSL_CACERT;
}
else
@@ -937,7 +973,7 @@ gtls_connect_step3(struct connectdata *conn,
infof(data, "\t server certificate verification SKIPPED\n");
#ifdef HAS_OCSP
- if(data->set.ssl.verifystatus) {
+ if(SSL_CONN_CONFIG(verifystatus)) {
if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
gnutls_datum_t status_request;
gnutls_ocsp_resp_t ocsp_resp;
@@ -1049,21 +1085,21 @@ gtls_connect_step3(struct connectdata *conn,
gnutls_x509_crt_t format */
gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
- if(data->set.ssl.issuercert) {
+ if(SSL_SET_OPTION(issuercert)) {
gnutls_x509_crt_init(&x509_issuer);
- issuerp = load_file(data->set.ssl.issuercert);
+ issuerp = load_file(SSL_SET_OPTION(issuercert));
gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
gnutls_x509_crt_deinit(x509_issuer);
unload_file(issuerp);
if(rc <= 0) {
failf(data, "server certificate issuer check failed (IssuerCert: %s)",
- data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
+ SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
gnutls_x509_crt_deinit(x509_cert);
return CURLE_SSL_ISSUER_ERROR;
}
infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
- data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
+ SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
}
size=sizeof(certbuf);
@@ -1082,7 +1118,7 @@ gtls_connect_step3(struct connectdata *conn,
in RFC2818 (HTTPS), which takes into account wildcards, and the subject
alternative name PKIX extension. Returns non zero on success, and zero on
failure. */
- rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);
+ rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
#if GNUTLS_VERSION_NUMBER < 0x030306
/* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
addresses. */
@@ -1098,10 +1134,10 @@ gtls_connect_step3(struct connectdata *conn,
int i;
int ret = 0;
- if(Curl_inet_pton(AF_INET, conn->host.name, addrbuf) > 0)
+ if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
addrlen = 4;
#ifdef ENABLE_IPV6
- else if(Curl_inet_pton(AF_INET6, conn->host.name, addrbuf) > 0)
+ else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
addrlen = 16;
#endif
@@ -1126,15 +1162,18 @@ gtls_connect_step3(struct connectdata *conn,
}
#endif
if(!rc) {
- if(data->set.ssl.verifyhost) {
+ const char * const dispname = SSL_IS_PROXY() ?
+ conn->http_proxy.host.dispname : conn->host.dispname;
+
+ if(SSL_CONN_CONFIG(verifyhost)) {
failf(data, "SSL: certificate subject name (%s) does not match "
- "target host name '%s'", certbuf, conn->host.dispname);
+ "target host name '%s'", certbuf, dispname);
gnutls_x509_crt_deinit(x509_cert);
return CURLE_PEER_FAILED_VERIFICATION;
}
else
infof(data, "\t common name: %s (does not match '%s')\n",
- certbuf, conn->host.dispname);
+ certbuf, dispname);
}
else
infof(data, "\t common name: %s (matched)\n", certbuf);
@@ -1143,7 +1182,7 @@ gtls_connect_step3(struct connectdata *conn,
certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
if(certclock == (time_t)-1) {
- if(data->set.ssl.verifypeer) {
+ if(SSL_CONN_CONFIG(verifypeer)) {
failf(data, "server cert expiration date verify failed");
gnutls_x509_crt_deinit(x509_cert);
return CURLE_SSL_CONNECT_ERROR;
@@ -1153,7 +1192,7 @@ gtls_connect_step3(struct connectdata *conn,
}
else {
if(certclock < time(NULL)) {
- if(data->set.ssl.verifypeer) {
+ if(SSL_CONN_CONFIG(verifypeer)) {
failf(data, "server certificate expiration date has passed.");
gnutls_x509_crt_deinit(x509_cert);
return CURLE_PEER_FAILED_VERIFICATION;
@@ -1168,7 +1207,7 @@ gtls_connect_step3(struct connectdata *conn,
certclock = gnutls_x509_crt_get_activation_time(x509_cert);
if(certclock == (time_t)-1) {
- if(data->set.ssl.verifypeer) {
+ if(SSL_CONN_CONFIG(verifypeer)) {
failf(data, "server cert activation date verify failed");
gnutls_x509_crt_deinit(x509_cert);
return CURLE_SSL_CONNECT_ERROR;
@@ -1178,7 +1217,7 @@ gtls_connect_step3(struct connectdata *conn,
}
else {
if(certclock > time(NULL)) {
- if(data->set.ssl.verifypeer) {
+ if(SSL_CONN_CONFIG(verifypeer)) {
failf(data, "server certificate not activated yet.");
gnutls_x509_crt_deinit(x509_cert);
return CURLE_PEER_FAILED_VERIFICATION;
@@ -1270,7 +1309,7 @@ gtls_connect_step3(struct connectdata *conn,
conn->recv[sockindex] = gtls_recv;
conn->send[sockindex] = gtls_send;
- if(conn->ssl_config.sessionid) {
+ if(data->set.general_ssl.sessionid) {
/* we always unconditionally get the session id here, as even if we
already got it from the cache and asked to use it in the connection, it
might've been rejected and then a new one is in use now and we need to
@@ -1289,7 +1328,8 @@ gtls_connect_step3(struct connectdata *conn,
gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL));
+ incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL,
+ sockindex));
if(incache) {
/* there was one before in the cache, so instead of risking that the
previous one was rejected, we just kill that and store the new */
@@ -1297,7 +1337,8 @@ gtls_connect_step3(struct connectdata *conn,
}
/* store this session id */
- result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize);
+ result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize,
+ sockindex);
Curl_ssl_sessionid_unlock(conn);
if(result) {
free(connect_sessionid);
@@ -1379,6 +1420,20 @@ Curl_gtls_connect(struct connectdata *conn,
return CURLE_OK;
}
+bool Curl_gtls_data_pending(const struct connectdata *conn, int connindex)
+{
+ bool res = FALSE;
+ if(conn->ssl[connindex].session &&
+ 0 != gnutls_record_check_pending(conn->ssl[connindex].session))
+ res = TRUE;
+
+ if(conn->proxy_ssl[connindex].session &&
+ 0 != gnutls_record_check_pending(conn->proxy_ssl[connindex].session))
+ res = TRUE;
+
+ return res;
+}
+
static ssize_t gtls_send(struct connectdata *conn,
int sockindex,
const void *mem,
@@ -1398,29 +1453,29 @@ static ssize_t gtls_send(struct connectdata *conn,
return rc;
}
-static void close_one(struct connectdata *conn,
- int idx)
+static void close_one(struct ssl_connect_data *ssl)
{
- if(conn->ssl[idx].session) {
- gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR);
- gnutls_deinit(conn->ssl[idx].session);
- conn->ssl[idx].session = NULL;
+ if(ssl->session) {
+ gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR);
+ gnutls_deinit(ssl->session);
+ ssl->session = NULL;
}
- if(conn->ssl[idx].cred) {
- gnutls_certificate_free_credentials(conn->ssl[idx].cred);
- conn->ssl[idx].cred = NULL;
+ if(ssl->cred) {
+ gnutls_certificate_free_credentials(ssl->cred);
+ ssl->cred = NULL;
}
#ifdef USE_TLS_SRP
- if(conn->ssl[idx].srp_client_cred) {
- gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred);
- conn->ssl[idx].srp_client_cred = NULL;
+ if(ssl->srp_client_cred) {
+ gnutls_srp_free_client_credentials(ssl->srp_client_cred);
+ ssl->srp_client_cred = NULL;
}
#endif
}
void Curl_gtls_close(struct connectdata *conn, int sockindex)
{
- close_one(conn, sockindex);
+ close_one(&conn->ssl[sockindex]);
+ close_one(&conn->proxy_ssl[sockindex]);
}
/*
@@ -1445,8 +1500,8 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
if(conn->ssl[sockindex].session) {
while(!done) {
- int what = Curl_socket_ready(conn->sock[sockindex],
- CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+ int what = SOCKET_READABLE(conn->sock[sockindex],
+ SSL_SHUTDOWN_TIMEOUT);
if(what > 0) {
/* Something to read, let's do it and hope that it is the close
notify alert from the server */
@@ -1486,8 +1541,8 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
#ifdef USE_TLS_SRP
- if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
- && data->set.ssl.username != NULL)
+ if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
+ && SSL_SET_OPTION(username) != NULL)
gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
#endif
diff --git a/lib/vtls/gtls.h b/lib/vtls/gtls.h
index e0a95a7c..e3d58531 100644
--- a/lib/vtls/gtls.h
+++ b/lib/vtls/gtls.h
@@ -34,6 +34,8 @@ CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex);
CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
int sockindex,
bool *done);
+bool Curl_gtls_data_pending(const struct connectdata *conn,
+ int connindex);
/* close a SSL connection */
void Curl_gtls_close(struct connectdata *conn, int sockindex);
@@ -81,7 +83,7 @@ bool Curl_gtls_cert_status_request(void);
#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
#define curlssl_version Curl_gtls_version
#define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
+#define curlssl_data_pending(x,y) Curl_gtls_data_pending(x,y)
#define curlssl_random(x,y,z) Curl_gtls_random(x,y,z)
#define curlssl_md5sum(a,b,c,d) Curl_gtls_md5sum(a,b,c,d)
#define curlssl_sha256sum(a,b,c,d) Curl_gtls_sha256sum(a,b,c,d)
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index a1e7d236..c428a210 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -31,11 +31,15 @@
#ifdef USE_MBEDTLS
+#include <mbedtls/version.h>
+#if MBEDTLS_VERSION_NUMBER >= 0x02040000
+#include <mbedtls/net_sockets.h>
+#else
#include <mbedtls/net.h>
+#endif
#include <mbedtls/ssl.h>
#include <mbedtls/certs.h>
#include <mbedtls/x509.h>
-#include <mbedtls/version.h>
#include <mbedtls/error.h>
#include <mbedtls/entropy.h>
@@ -50,7 +54,6 @@
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
-#include "rawstr.h"
#include "polarssl_threadlock.h"
/* The last 3 #include files should be in this order */
@@ -160,13 +163,21 @@ mbed_connect_step1(struct connectdata *conn,
{
struct Curl_easy *data = conn->data;
struct ssl_connect_data* connssl = &conn->ssl[sockindex];
+ const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+ const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+ const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
+ char * const ssl_cert = SSL_SET_OPTION(cert);
+ const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
+ const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
int ret = -1;
char errorbuf[128];
errorbuf[0]=0;
/* mbedTLS only supports SSLv3 and TLSv1 */
- if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+ if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
failf(data, "mbedTLS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -202,34 +213,32 @@ mbed_connect_step1(struct connectdata *conn,
/* Load the trusted CA */
mbedtls_x509_crt_init(&connssl->cacert);
- if(data->set.str[STRING_SSL_CAFILE]) {
- ret = mbedtls_x509_crt_parse_file(&connssl->cacert,
- data->set.str[STRING_SSL_CAFILE]);
+ if(ssl_cafile) {
+ ret = mbedtls_x509_crt_parse_file(&connssl->cacert, ssl_cafile);
if(ret<0) {
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
- data->set.str[STRING_SSL_CAFILE], -ret, errorbuf);
+ ssl_cafile, -ret, errorbuf);
- if(data->set.ssl.verifypeer)
+ if(verifypeer)
return CURLE_SSL_CACERT_BADFILE;
}
}
- if(data->set.str[STRING_SSL_CAPATH]) {
- ret = mbedtls_x509_crt_parse_path(&connssl->cacert,
- data->set.str[STRING_SSL_CAPATH]);
+ if(ssl_capath) {
+ ret = mbedtls_x509_crt_parse_path(&connssl->cacert, ssl_capath);
if(ret<0) {
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
- data->set.str[STRING_SSL_CAPATH], -ret, errorbuf);
+ ssl_capath, -ret, errorbuf);
- if(data->set.ssl.verifypeer)
+ if(verifypeer)
return CURLE_SSL_CACERT_BADFILE;
}
}
@@ -237,16 +246,15 @@ mbed_connect_step1(struct connectdata *conn,
/* Load the client certificate */
mbedtls_x509_crt_init(&connssl->clicert);
- if(data->set.str[STRING_CERT]) {
- ret = mbedtls_x509_crt_parse_file(&connssl->clicert,
- data->set.str[STRING_CERT]);
+ if(ssl_cert) {
+ ret = mbedtls_x509_crt_parse_file(&connssl->clicert, ssl_cert);
if(ret) {
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
- data->set.str[STRING_CERT], -ret, errorbuf);
+ ssl_cert, -ret, errorbuf);
return CURLE_SSL_CERTPROBLEM;
}
@@ -255,9 +263,9 @@ mbed_connect_step1(struct connectdata *conn,
/* Load the client private key */
mbedtls_pk_init(&connssl->pk);
- if(data->set.str[STRING_KEY]) {
- ret = mbedtls_pk_parse_keyfile(&connssl->pk, data->set.str[STRING_KEY],
- data->set.str[STRING_KEY_PASSWD]);
+ if(SSL_SET_OPTION(key)) {
+ ret = mbedtls_pk_parse_keyfile(&connssl->pk, SSL_SET_OPTION(key),
+ SSL_SET_OPTION(key_passwd));
if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA))
ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
@@ -266,7 +274,7 @@ mbed_connect_step1(struct connectdata *conn,
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
- data->set.str[STRING_KEY], -ret, errorbuf);
+ SSL_SET_OPTION(key), -ret, errorbuf);
return CURLE_SSL_CERTPROBLEM;
}
@@ -275,23 +283,21 @@ mbed_connect_step1(struct connectdata *conn,
/* Load the CRL */
mbedtls_x509_crl_init(&connssl->crl);
- if(data->set.str[STRING_SSL_CRLFILE]) {
- ret = mbedtls_x509_crl_parse_file(&connssl->crl,
- data->set.str[STRING_SSL_CRLFILE]);
+ if(ssl_crlfile) {
+ ret = mbedtls_x509_crl_parse_file(&connssl->crl, ssl_crlfile);
if(ret) {
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
- data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf);
+ ssl_crlfile, -ret, errorbuf);
return CURLE_SSL_CRL_BADFILE;
}
}
- infof(data, "mbedTLS: Connecting to %s:%d\n",
- conn->host.name, conn->remote_port);
+ infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port);
mbedtls_ssl_config_init(&connssl->config);
@@ -313,7 +319,7 @@ mbed_connect_step1(struct connectdata *conn,
mbedtls_ssl_conf_cert_profile(&connssl->config,
&mbedtls_x509_crt_profile_fr);
- switch(data->set.ssl.version) {
+ switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
@@ -348,8 +354,11 @@ mbed_connect_step1(struct connectdata *conn,
MBEDTLS_SSL_MINOR_VERSION_3);
infof(data, "mbedTLS: Set SSL version to TLS 1.2\n");
break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "mbedTLS: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
default:
- failf(data, "mbedTLS: Unsupported SSL protocol version");
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -366,11 +375,11 @@ mbed_connect_step1(struct connectdata *conn,
mbedtls_ssl_list_ciphersuites());
/* Check if there's a cached ID we can/should use here! */
- if(conn->ssl_config.sessionid) {
+ if(data->set.general_ssl.sessionid) {
void *old_session = NULL;
Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) {
+ if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
ret = mbedtls_ssl_set_session(&connssl->ssl, old_session);
if(ret) {
Curl_ssl_sessionid_unlock(conn);
@@ -386,11 +395,11 @@ mbed_connect_step1(struct connectdata *conn,
&connssl->cacert,
&connssl->crl);
- if(data->set.str[STRING_KEY]) {
+ if(SSL_SET_OPTION(key)) {
mbedtls_ssl_conf_own_cert(&connssl->config,
&connssl->clicert, &connssl->pk);
}
- if(mbedtls_ssl_set_hostname(&connssl->ssl, conn->host.name)) {
+ if(mbedtls_ssl_set_hostname(&connssl->ssl, hostname)) {
/* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and*
the name to set in the SNI extension. So even if curl connects to a
host specified as an IP address, this function must be used. */
@@ -420,7 +429,15 @@ mbed_connect_step1(struct connectdata *conn,
#endif
#ifdef MBEDTLS_DEBUG
+ /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */
mbedtls_ssl_conf_dbg(&connssl->config, mbed_debug, data);
+ /* - 0 No debug
+ * - 1 Error
+ * - 2 State change
+ * - 3 Informational
+ * - 4 Verbose
+ */
+ mbedtls_debug_set_threshold(4);
#endif
connssl->connecting_state = ssl_connect_2;
@@ -438,7 +455,7 @@ mbed_connect_step2(struct connectdata *conn,
const mbedtls_x509_crt *peercert;
#ifdef HAS_ALPN
- const char* next_protocol;
+ const char *next_protocol;
#endif
char errorbuf[128];
@@ -472,7 +489,7 @@ mbed_connect_step2(struct connectdata *conn,
ret = mbedtls_ssl_get_verify_result(&conn->ssl[sockindex].ssl);
- if(ret && data->set.ssl.verifypeer) {
+ if(ret && SSL_CONN_CONFIG(verifypeer)) {
if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
failf(data, "Cert verify failed: BADCERT_EXPIRED");
@@ -599,7 +616,7 @@ mbed_connect_step3(struct connectdata *conn,
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
- if(conn->ssl_config.sessionid) {
+ if(data->set.general_ssl.sessionid) {
int ret;
mbedtls_ssl_session *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
@@ -618,10 +635,10 @@ mbed_connect_step3(struct connectdata *conn,
/* If there's already a matching session in the cache, delete it */
Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL))
+ if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
Curl_ssl_delsessionid(conn, old_ssl_sessionid);
- retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0);
+ retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
Curl_ssl_sessionid_unlock(conn);
if(retcode) {
free(our_ssl_sessionid);
@@ -765,7 +782,8 @@ mbed_connect_common(struct connectdata *conn,
curl_socket_t readfd = ssl_connect_2_reading==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
- what = Curl_socket_ready(readfd, writefd, nonblocking ? 0 : timeout_ms);
+ what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
+ nonblocking ? 0 : timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index ad33f258..91b8e05c 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -34,7 +34,7 @@
#include "formdata.h" /* for the boundary function */
#include "url.h" /* for the ssl config check function */
#include "connect.h"
-#include "strequal.h"
+#include "strcase.h"
#include "select.h"
#include "vtls.h"
#include "llist.h"
@@ -64,7 +64,7 @@
#include <ocsp.h>
#endif
-#include "rawstr.h"
+#include "strcase.h"
#include "warnless.h"
#include "x509asn1.h"
@@ -78,13 +78,12 @@
#define SLOTSIZE 13
PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
-
-PRLock * nss_initlock = NULL;
-PRLock * nss_crllock = NULL;
-struct curl_llist *nss_crl_list = NULL;
-NSSInitContext * nss_context = NULL;
-
-volatile int initialized = 0;
+static PRLock *nss_initlock = NULL;
+static PRLock *nss_crllock = NULL;
+static PRLock *nss_findslot_lock = NULL;
+static struct curl_llist *nss_crl_list = NULL;
+static NSSInitContext *nss_context = NULL;
+static volatile int initialized = 0;
typedef struct {
const char *name;
@@ -150,7 +149,7 @@ static const cipher_s cipherlist[] = {
{"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA},
{"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA},
{"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA},
- {"echde_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA},
+ {"ecdhe_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA},
{"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
{"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA},
{"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
@@ -180,16 +179,35 @@ static const cipher_s cipherlist[] = {
{"ecdhe_rsa_aes_128_gcm_sha_256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
{"ecdh_rsa_aes_128_gcm_sha_256", TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256},
#endif
+#ifdef TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ /* cipher suites using SHA384 */
+ {"rsa_aes_256_gcm_sha_384", TLS_RSA_WITH_AES_256_GCM_SHA384},
+ {"dhe_rsa_aes_256_gcm_sha_384", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
+ {"dhe_dss_aes_256_gcm_sha_384", TLS_DHE_DSS_WITH_AES_256_GCM_SHA384},
+ {"ecdhe_ecdsa_aes_256_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
+ {"ecdhe_rsa_aes_256_sha_384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
+ {"ecdhe_ecdsa_aes_256_gcm_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
+ {"ecdhe_rsa_aes_256_gcm_sha_384", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
+#endif
+#ifdef TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+ /* chacha20-poly1305 cipher suites */
+ {"ecdhe_rsa_chacha20_poly1305_sha_256",
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+ {"ecdhe_ecdsa_chacha20_poly1305_sha_256",
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
+ {"dhe_rsa_chacha20_poly1305_sha_256",
+ TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+#endif
};
-static const char* pem_library = "libnsspem.so";
-SECMODModule* mod = NULL;
+static const char *pem_library = "libnsspem.so";
+static SECMODModule *mod = NULL;
/* NSPR I/O layer we use to detect blocking direction during SSL handshake */
static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER;
static PRIOMethods nspr_io_methods;
-static const char* nss_error_to_name(PRErrorCode code)
+static const char *nss_error_to_name(PRErrorCode code)
{
const char *name = PR_ErrorToName(code);
if(name)
@@ -243,7 +261,7 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model,
found = PR_FALSE;
for(i=0; i<NUM_OF_CIPHERS; i++) {
- if(Curl_raw_equal(cipher, cipherlist[i].name)) {
+ if(strcasecompare(cipher, cipherlist[i].name)) {
cipher_state[i] = PR_TRUE;
found = PR_TRUE;
break;
@@ -319,9 +337,8 @@ static int is_file(const char *filename)
* should be later deallocated using free(). If the OOM failure occurs, we
* return NULL, too.
*/
-static char* dup_nickname(struct Curl_easy *data, enum dupstring cert_kind)
+static char *dup_nickname(struct Curl_easy *data, const char *str)
{
- const char *str = data->set.str[cert_kind];
const char *n;
if(!is_file(str))
@@ -340,6 +357,19 @@ static char* dup_nickname(struct Curl_easy *data, enum dupstring cert_kind)
return NULL;
}
+/* Lock/unlock wrapper for PK11_FindSlotByName() to work around race condition
+ * in nssSlot_IsTokenPresent() causing spurious SEC_ERROR_NO_TOKEN. For more
+ * details, go to <https://bugzilla.mozilla.org/1297397>.
+ */
+static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name)
+{
+ PK11SlotInfo *slot;
+ PR_Lock(nss_initlock);
+ slot = PK11_FindSlotByName(slot_name);
+ PR_Unlock(nss_initlock);
+ return slot;
+}
+
/* Call PK11_CreateGenericObject() with the given obj_class and filename. If
* the call succeeds, append the object handle to the list of objects so that
* the object can be destroyed in Curl_nss_close(). */
@@ -362,7 +392,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
if(!slot_name)
return CURLE_OUT_OF_MEMORY;
- slot = PK11_FindSlotByName(slot_name);
+ slot = nss_find_slot_by_name(slot_name);
free(slot_name);
if(!slot)
return result;
@@ -483,7 +513,7 @@ static CURLcode nss_cache_crl(SECItem *crl_der)
return CURLE_OK;
}
-static CURLcode nss_load_crl(const char* crlfilename)
+static CURLcode nss_load_crl(const char *crlfilename)
{
PRFileDesc *infile;
PRFileInfo info;
@@ -509,7 +539,7 @@ static CURLcode nss_load_crl(const char* crlfilename)
goto fail;
/* place a trailing zero right after the visible data */
- body = (char*)filedata.data;
+ body = (char *)filedata.data;
body[--filedata.len] = '\0';
body = strstr(body, "-----BEGIN");
@@ -554,6 +584,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
SECStatus status;
CURLcode result;
struct ssl_connect_data *ssl = conn->ssl;
+ struct Curl_easy *data = conn->data;
(void)sockindex; /* unused */
@@ -563,7 +594,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
return result;
}
- slot = PK11_FindSlotByName("PEM Token #1");
+ slot = nss_find_slot_by_name("PEM Token #1");
if(!slot)
return CURLE_SSL_CERTPROBLEM;
@@ -571,8 +602,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
PK11_IsPresent(slot);
- status = PK11_Authenticate(slot, PR_TRUE,
- conn->data->set.str[STRING_KEY_PASSWD]);
+ status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd));
PK11_FreeSlot(slot);
return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM;
@@ -633,7 +663,7 @@ static CURLcode cert_stuff(struct connectdata *conn, int sockindex,
return CURLE_OK;
}
-static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg)
+static char *nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg)
{
(void)slot; /* unused */
@@ -651,7 +681,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
struct connectdata *conn = (struct connectdata *)arg;
#ifdef SSL_ENABLE_OCSP_STAPLING
- if(conn->data->set.ssl.verifystatus) {
+ if(SSL_CONN_CONFIG(verifystatus)) {
SECStatus cacheResult;
const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
@@ -677,7 +707,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
}
#endif
- if(!conn->data->set.ssl.verifypeer) {
+ if(!SSL_CONN_CONFIG(verifypeer)) {
infof(conn->data, "skipping SSL peer certificate verification\n");
return SECSuccess;
}
@@ -703,6 +733,11 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) {
switch(state) {
+#if NSSVERNUM >= 0x031a00 /* 3.26.0 */
+ /* used by NSS internally to implement 0-RTT */
+ case SSL_NEXT_PROTO_EARLY_VALUE:
+ /* fall through! */
+#endif
case SSL_NEXT_PROTO_NO_SUPPORT:
case SSL_NEXT_PROTO_NO_OVERLAP:
infof(conn->data, "ALPN/NPN, server did not agree to a protocol\n");
@@ -897,9 +932,12 @@ static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
CERTCertificate *cert;
/* remember the cert verification result */
- data->set.ssl.certverifyresult = err;
+ if(SSL_IS_PROXY())
+ data->set.proxy_ssl.certverifyresult = err;
+ else
+ data->set.ssl.certverifyresult = err;
- if(err == SSL_ERROR_BAD_CERT_DOMAIN && !data->set.ssl.verifyhost)
+ if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost))
/* we are asked not to verify the host name */
return SECSuccess;
@@ -1004,16 +1042,16 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
struct Curl_easy *data = connssl->data;
const char *nickname = connssl->client_nickname;
+ static const char pem_slotname[] = "PEM Token #1";
if(connssl->obj_clicert) {
/* use the cert/key provided by PEM reader */
- static const char pem_slotname[] = "PEM Token #1";
SECItem cert_der = { 0, NULL, 0 };
void *proto_win = SSL_RevealPinArg(sock);
struct CERTCertificateStr *cert;
struct SECKEYPrivateKeyStr *key;
- PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname);
+ PK11SlotInfo *slot = nss_find_slot_by_name(pem_slotname);
if(NULL == slot) {
failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
return SECFailure;
@@ -1069,6 +1107,12 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
if(NULL == nickname)
nickname = "[unknown]";
+ if(!strncmp(nickname, pem_slotname, sizeof(pem_slotname) - 1U)) {
+ failf(data, "NSS: refusing previously loaded certificate from file: %s",
+ nickname);
+ return SECFailure;
+ }
+
if(NULL == *pRetKey) {
failf(data, "NSS: private key not found for certificate: %s", nickname);
return SECFailure;
@@ -1243,6 +1287,7 @@ int Curl_nss_init(void)
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
nss_initlock = PR_NewLock();
nss_crllock = PR_NewLock();
+ nss_findslot_lock = PR_NewLock();
}
/* We will actually initialize NSS later */
@@ -1297,6 +1342,7 @@ void Curl_nss_cleanup(void)
PR_DestroyLock(nss_initlock);
PR_DestroyLock(nss_crllock);
+ PR_DestroyLock(nss_findslot_lock);
nss_initlock = NULL;
initialized = 0;
@@ -1328,36 +1374,55 @@ Curl_nss_check_cxn(struct connectdata *conn)
return -1; /* connection status unknown */
}
+static void nss_close(struct ssl_connect_data *connssl)
+{
+ /* before the cleanup, check whether we are using a client certificate */
+ const bool client_cert = (connssl->client_nickname != NULL)
+ || (connssl->obj_clicert != NULL);
+
+ free(connssl->client_nickname);
+ connssl->client_nickname = NULL;
+
+ /* destroy all NSS objects in order to avoid failure of NSS shutdown */
+ Curl_llist_destroy(connssl->obj_list, NULL);
+ connssl->obj_list = NULL;
+ connssl->obj_clicert = NULL;
+
+ if(connssl->handle) {
+ if(client_cert)
+ /* A server might require different authentication based on the
+ * particular path being requested by the client. To support this
+ * scenario, we must ensure that a connection will never reuse the
+ * authentication data from a previous connection. */
+ SSL_InvalidateSession(connssl->handle);
+
+ PR_Close(connssl->handle);
+ connssl->handle = NULL;
+ }
+}
+
/*
* This function is called when an SSL connection is closed.
*/
void Curl_nss_close(struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex];
- if(connssl->handle) {
+ if(connssl->handle || connssl_proxy->handle) {
/* NSS closes the socket we previously handed to it, so we must mark it
as closed to avoid double close */
fake_sclose(conn->sock[sockindex]);
conn->sock[sockindex] = CURL_SOCKET_BAD;
+ }
- if((connssl->client_nickname != NULL) || (connssl->obj_clicert != NULL))
- /* A server might require different authentication based on the
- * particular path being requested by the client. To support this
- * scenario, we must ensure that a connection will never reuse the
- * authentication data from a previous connection. */
- SSL_InvalidateSession(connssl->handle);
-
- free(connssl->client_nickname);
- connssl->client_nickname = NULL;
- /* destroy all NSS objects in order to avoid failure of NSS shutdown */
- Curl_llist_destroy(connssl->obj_list, NULL);
- connssl->obj_list = NULL;
- connssl->obj_clicert = NULL;
+ if(connssl->handle)
+ /* nss_close(connssl) will transitively close also connssl_proxy->handle
+ if both are used. Clear it to avoid a double close leading to crash. */
+ connssl_proxy->handle = NULL;
- PR_Close(connssl->handle);
- connssl->handle = NULL;
- }
+ nss_close(connssl);
+ nss_close(connssl_proxy);
}
/* return true if NSS can provide error code (and possibly msg) for the
@@ -1398,8 +1463,8 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
int sockindex)
{
struct Curl_easy *data = conn->data;
- const char *cafile = data->set.ssl.CAfile;
- const char *capath = data->set.ssl.CApath;
+ const char *cafile = SSL_CONN_CONFIG(CAfile);
+ const char *capath = SSL_CONN_CONFIG(CApath);
if(cafile) {
CURLcode result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
@@ -1447,13 +1512,22 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
}
static CURLcode nss_init_sslver(SSLVersionRange *sslver,
- struct Curl_easy *data)
+ struct Curl_easy *data,
+ struct connectdata *conn)
{
- switch(data->set.ssl.version) {
- default:
+ switch (SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
+ /* map CURL_SSLVERSION_DEFAULT to NSS default */
+ if(SSL_VersionRangeGetDefault(ssl_variant_stream, sslver) != SECSuccess)
+ return CURLE_SSL_CONNECT_ERROR;
+ /* ... but make sure we use at least TLSv1.0 according to libcurl API */
+ if(sslver->min < SSL_LIBRARY_VERSION_TLS_1_0)
+ sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+ return CURLE_OK;
+
case CURL_SSLVERSION_TLSv1:
sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+ /* TODO: set sslver->max to SSL_LIBRARY_VERSION_TLS_1_3 once stable */
#ifdef SSL_LIBRARY_VERSION_TLS_1_2
sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
#elif defined SSL_LIBRARY_VERSION_TLS_1_1
@@ -1493,6 +1567,18 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver,
return CURLE_OK;
#endif
break;
+
+ case CURL_SSLVERSION_TLSv1_3:
+#ifdef SSL_LIBRARY_VERSION_TLS_1_3
+ sslver->min = SSL_LIBRARY_VERSION_TLS_1_3;
+ sslver->max = SSL_LIBRARY_VERSION_TLS_1_3;
+ return CURLE_OK;
+#endif
+ break;
+
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
}
failf(data, "TLS minor version cannot be set");
@@ -1550,6 +1636,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
curl_socket_t sockfd = conn->sock[sockindex];
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
CURLcode result;
+ bool second_layer = FALSE;
SSLVersionRange sslver = {
SSL_LIBRARY_VERSION_TLS_1_0, /* min */
@@ -1608,18 +1695,18 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
goto error;
/* do not use SSL cache if disabled or we are not going to verify peer */
- ssl_no_cache = (conn->ssl_config.sessionid && data->set.ssl.verifypeer) ?
- PR_FALSE : PR_TRUE;
+ ssl_no_cache = (data->set.general_ssl.sessionid
+ && SSL_CONN_CONFIG(verifypeer)) ? PR_FALSE : PR_TRUE;
if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
goto error;
/* enable/disable the requested SSL version(s) */
- if(nss_init_sslver(&sslver, data) != CURLE_OK)
+ if(nss_init_sslver(&sslver, data, conn) != CURLE_OK)
goto error;
if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
goto error;
- ssl_cbc_random_iv = !data->set.ssl_enable_beast;
+ ssl_cbc_random_iv = !SSL_SET_OPTION(enable_beast);
#ifdef SSL_CBC_RANDOM_IV
/* unless the user explicitly asks to allow the protocol vulnerability, we
use the work-around */
@@ -1631,14 +1718,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n");
#endif
- if(data->set.ssl.cipher_list) {
- if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) {
+ if(SSL_CONN_CONFIG(cipher_list)) {
+ if(set_ciphers(data, model, SSL_CONN_CONFIG(cipher_list)) != SECSuccess) {
result = CURLE_SSL_CIPHER;
goto error;
}
}
- if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost)
+ if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(verifyhost))
infof(data, "warning: ignoring value of ssl.verifyhost\n");
/* bypass the default SSL_AuthCertificate() hook in case we do not want to
@@ -1646,14 +1733,19 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess)
goto error;
- data->set.ssl.certverifyresult=0; /* not checked yet */
+ /* not checked yet */
+ if(SSL_IS_PROXY())
+ data->set.proxy_ssl.certverifyresult = 0;
+ else
+ data->set.ssl.certverifyresult = 0;
+
if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
goto error;
if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
goto error;
- if(data->set.ssl.verifypeer) {
+ if(SSL_CONN_CONFIG(verifypeer)) {
const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
if(rv) {
result = rv;
@@ -1661,24 +1753,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
}
}
- if(data->set.ssl.CRLfile) {
- const CURLcode rv = nss_load_crl(data->set.ssl.CRLfile);
+ if(SSL_SET_OPTION(CRLfile)) {
+ const CURLcode rv = nss_load_crl(SSL_SET_OPTION(CRLfile));
if(rv) {
result = rv;
goto error;
}
- infof(data, " CRLfile: %s\n", data->set.ssl.CRLfile);
+ infof(data, " CRLfile: %s\n", SSL_SET_OPTION(CRLfile));
}
- if(data->set.str[STRING_CERT]) {
- char *nickname = dup_nickname(data, STRING_CERT);
+ if(SSL_SET_OPTION(cert)) {
+ char *nickname = dup_nickname(data, SSL_SET_OPTION(cert));
if(nickname) {
/* we are not going to use libnsspem.so to read the client cert */
connssl->obj_clicert = NULL;
}
else {
- CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
- data->set.str[STRING_KEY]);
+ CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert),
+ SSL_SET_OPTION(key));
if(rv) {
/* failf() is already done in cert_stuff() */
result = rv;
@@ -1698,15 +1790,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
goto error;
}
- /* wrap OS file descriptor by NSPR's file descriptor abstraction */
- nspr_io = PR_ImportTCPSocket(sockfd);
- if(!nspr_io)
- goto error;
+ if(conn->proxy_ssl[sockindex].use) {
+ DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
+ DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL);
+ nspr_io = conn->proxy_ssl[sockindex].handle;
+ second_layer = TRUE;
+ }
+ else {
+ /* wrap OS file descriptor by NSPR's file descriptor abstraction */
+ nspr_io = PR_ImportTCPSocket(sockfd);
+ if(!nspr_io)
+ goto error;
+ }
/* create our own NSPR I/O layer */
nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods);
if(!nspr_io_stub) {
- PR_Close(nspr_io);
+ if(!second_layer)
+ PR_Close(nspr_io);
goto error;
}
@@ -1715,7 +1816,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
/* push our new layer to the NSPR I/O stack */
if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) {
- PR_Close(nspr_io);
+ if(!second_layer)
+ PR_Close(nspr_io);
PR_Close(nspr_io_stub);
goto error;
}
@@ -1723,7 +1825,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
/* import our model socket onto the current I/O stack */
connssl->handle = SSL_ImportFD(model, nspr_io);
if(!connssl->handle) {
- PR_Close(nspr_io);
+ if(!second_layer)
+ PR_Close(nspr_io);
goto error;
}
@@ -1731,12 +1834,12 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
model = NULL;
/* This is the password associated with the cert that we're using */
- if(data->set.str[STRING_KEY_PASSWD]) {
- SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]);
+ if(SSL_SET_OPTION(key_passwd)) {
+ SSL_SetPKCS11PinArg(connssl->handle, SSL_SET_OPTION(key_passwd));
}
#ifdef SSL_ENABLE_OCSP_STAPLING
- if(data->set.ssl.verifystatus) {
+ if(SSL_CONN_CONFIG(verifystatus)) {
if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
!= SECSuccess)
goto error;
@@ -1796,11 +1899,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
goto error;
/* propagate hostname to the TLS layer */
- if(SSL_SetURL(connssl->handle, conn->host.name) != SECSuccess)
+ if(SSL_SetURL(connssl->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name) != SECSuccess)
goto error;
/* prevent NSS from re-using the session for a different hostname */
- if(SSL_SetSockPeerID(connssl->handle, conn->host.name) != SECSuccess)
+ if(SSL_SetSockPeerID(connssl->handle, SSL_IS_PROXY() ?
+ conn->http_proxy.host.name : conn->host.name)
+ != SECSuccess)
goto error;
return CURLE_OK;
@@ -1818,6 +1924,8 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_SSL_CONNECT_ERROR;
PRUint32 timeout;
+ long * const certverifyresult = SSL_IS_PROXY() ?
+ &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
/* check timeout situation */
const long time_left = Curl_timeleft(data, NULL, TRUE);
@@ -1833,9 +1941,9 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
/* blocking direction is updated by nss_update_connecting_state() */
return CURLE_AGAIN;
- else if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
+ else if(*certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
result = CURLE_PEER_FAILED_VERIFICATION;
- else if(conn->data->set.ssl.certverifyresult!=0)
+ else if(*certverifyresult != 0)
result = CURLE_SSL_CACERT;
goto error;
}
@@ -1844,11 +1952,11 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
if(result)
goto error;
- if(data->set.str[STRING_SSL_ISSUERCERT]) {
+ if(SSL_SET_OPTION(issuercert)) {
SECStatus ret = SECFailure;
- char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT);
+ char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert));
if(nickname) {
- /* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */
+ /* we support only nicknames in case of issuercert for now */
ret = check_issuer_cert(connssl->handle, nickname);
free(nickname);
}
@@ -1882,8 +1990,11 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
const bool blocking = (done == NULL);
CURLcode result;
- if(connssl->state == ssl_connection_complete)
+ if(connssl->state == ssl_connection_complete) {
+ if(!blocking)
+ *done = TRUE;
return CURLE_OK;
+ }
if(connssl->connecting_state == ssl_connect_1) {
result = nss_setup_connect(conn, sockindex);
@@ -2070,7 +2181,8 @@ bool Curl_nss_cert_status_request(void)
#endif
}
-bool Curl_nss_false_start(void) {
+bool Curl_nss_false_start(void)
+{
#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
return TRUE;
#else
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 3027ca33..af4afe85 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -46,10 +46,9 @@
#include "openssl.h"
#include "connect.h"
#include "slist.h"
-#include "strequal.h"
#include "select.h"
#include "vtls.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "hostcheck.h"
#include "curl_printf.h"
@@ -95,11 +94,6 @@
#if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
#define HAVE_ERR_REMOVE_THREAD_STATE 1
-#if (OPENSSL_VERSION_NUMBER >= 0x10100004L) && \
- !defined(LIBRESSL_VERSION_NUMBER)
-/* OpenSSL 1.1.0 deprecates the function */
-#define HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED 1
-#endif
#endif
#if !defined(HAVE_SSLV2_CLIENT_METHOD) || \
@@ -110,11 +104,28 @@
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && /* OpenSSL 1.1.0+ */ \
!defined(LIBRESSL_VERSION_NUMBER)
-#define SSLeay_add_ssl_algorithms() SSL_library_init()
#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER
#define HAVE_X509_GET0_EXTENSIONS 1 /* added in 1.1.0 -pre1 */
#define HAVE_OPAQUE_EVP_PKEY 1 /* since 1.1.0 -pre3 */
#define HAVE_OPAQUE_RSA_DSA_DH 1 /* since 1.1.0 -pre5 */
+#define CONST_EXTS const
+#define CONST_ASN1_BIT_STRING const
+#define HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED 1
+#else
+/* For OpenSSL before 1.1.0 */
+#define ASN1_STRING_get0_data(x) ASN1_STRING_data(x)
+#define X509_get0_notBefore(x) X509_get_notBefore(x)
+#define X509_get0_notAfter(x) X509_get_notAfter(x)
+#define CONST_EXTS /* nope */
+#define CONST_ASN1_BIT_STRING /* nope */
+#ifdef LIBRESSL_VERSION_NUMBER
+static unsigned long OpenSSL_version_num(void)
+{
+ return LIBRESSL_VERSION_NUMBER;
+}
+#else
+#define OpenSSL_version_num() SSLeay()
+#endif
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* 1.0.2 or later */ \
@@ -165,39 +176,34 @@ static int passwd_callback(char *buf, int num, int encrypting,
}
/*
- * rand_enough() is a function that returns TRUE if we have seeded the random
- * engine properly. We use some preprocessor magic to provide a seed_enough()
- * macro to use, just to prevent a compiler warning on this function if we
- * pass in an argument that is never used.
+ * rand_enough() returns TRUE if we have seeded the random engine properly.
*/
-
-#ifdef HAVE_RAND_STATUS
-#define seed_enough(x) rand_enough()
static bool rand_enough(void)
{
return (0 != RAND_status()) ? TRUE : FALSE;
}
-#else
-#define seed_enough(x) rand_enough(x)
-static bool rand_enough(int nread)
-{
- /* this is a very silly decision to make */
- return (nread > 500) ? TRUE : FALSE;
-}
-#endif
-static int ossl_seed(struct Curl_easy *data)
+static CURLcode Curl_ossl_seed(struct Curl_easy *data)
{
+ /* we have the "SSL is seeded" boolean static to prevent multiple
+ time-consuming seedings in vain */
+ static bool ssl_seeded = FALSE;
char *buf = data->state.buffer; /* point to the big buffer */
int nread=0;
- /* Q: should we add support for a random file name as a libcurl option?
- A: Yes, it is here */
+ if(ssl_seeded)
+ return CURLE_OK;
+
+ if(rand_enough()) {
+ /* OpenSSL 1.1.0+ will return here */
+ ssl_seeded = TRUE;
+ return CURLE_OK;
+ }
#ifndef RANDOM_FILE
/* if RANDOM_FILE isn't defined, we only perform this if an option tells
us to! */
- if(data->set.ssl.random_file)
+ if(data->set.str[STRING_SSL_RANDOM_FILE])
#define RANDOM_FILE "" /* doesn't matter won't be used */
#endif
{
@@ -206,7 +212,7 @@ static int ossl_seed(struct Curl_easy *data)
data->set.str[STRING_SSL_RANDOM_FILE]:
RANDOM_FILE),
RAND_LOAD_LENGTH);
- if(seed_enough(nread))
+ if(rand_enough())
return nread;
}
@@ -226,7 +232,7 @@ static int ossl_seed(struct Curl_easy *data)
data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET);
if(-1 != ret) {
nread += ret;
- if(seed_enough(nread))
+ if(rand_enough())
return nread;
}
}
@@ -237,9 +243,10 @@ static int ossl_seed(struct Curl_easy *data)
do {
unsigned char randb[64];
int len = sizeof(randb);
- RAND_bytes(randb, len);
+ if(!RAND_bytes(randb, len))
+ break;
RAND_add(randb, len, (len >> 1));
- } while(!RAND_status());
+ } while(!rand_enough());
/* generates a default path for the random seed file */
buf[0]=0; /* blank it first */
@@ -247,25 +254,12 @@ static int ossl_seed(struct Curl_easy *data)
if(buf[0]) {
/* we got a file name to try */
nread += RAND_load_file(buf, RAND_LOAD_LENGTH);
- if(seed_enough(nread))
+ if(rand_enough())
return nread;
}
infof(data, "libcurl is now using a weak random seed!\n");
- return nread;
-}
-
-static void Curl_ossl_seed(struct Curl_easy *data)
-{
- /* we have the "SSL is seeded" boolean static to prevent multiple
- time-consuming seedings in vain */
- static bool ssl_seeded = FALSE;
-
- if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
- data->set.str[STRING_SSL_EGDSOCKET]) {
- ossl_seed(data);
- ssl_seeded = TRUE;
- }
+ return CURLE_SSL_CONNECT_ERROR; /* confusing error code */
}
#ifndef SSL_FILETYPE_ENGINE
@@ -278,13 +272,13 @@ static int do_file_type(const char *type)
{
if(!type || !type[0])
return SSL_FILETYPE_PEM;
- if(Curl_raw_equal(type, "PEM"))
+ if(strcasecompare(type, "PEM"))
return SSL_FILETYPE_PEM;
- if(Curl_raw_equal(type, "DER"))
+ if(strcasecompare(type, "DER"))
return SSL_FILETYPE_ASN1;
- if(Curl_raw_equal(type, "ENG"))
+ if(strcasecompare(type, "ENG"))
return SSL_FILETYPE_ENGINE;
- if(Curl_raw_equal(type, "P12"))
+ if(strcasecompare(type, "P12"))
return SSL_FILETYPE_PKCS12;
return -1;
}
@@ -301,7 +295,7 @@ static int ssl_ui_reader(UI *ui, UI_STRING *uis)
switch(UI_get_string_type(uis)) {
case UIT_PROMPT:
case UIT_VERIFY:
- password = (const char*)UI_get0_user_data(ui);
+ password = (const char *)UI_get0_user_data(ui);
if(password && (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) {
UI_set_result(ui, uis, password);
return 1;
@@ -337,7 +331,8 @@ int cert_stuff(struct connectdata *conn,
char *cert_file,
const char *cert_type,
char *key_file,
- const char *key_type)
+ const char *key_type,
+ char *key_passwd)
{
struct Curl_easy *data = conn->data;
@@ -348,10 +343,9 @@ int cert_stuff(struct connectdata *conn,
X509 *x509;
int cert_done = 0;
- if(data->set.str[STRING_KEY_PASSWD]) {
+ if(key_passwd) {
/* set the password in the callback userdata */
- SSL_CTX_set_default_passwd_cb_userdata(ctx,
- data->set.str[STRING_KEY_PASSWD]);
+ SSL_CTX_set_default_passwd_cb_userdata(ctx, key_passwd);
/* Set passwd callback: */
SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
}
@@ -462,7 +456,7 @@ int cert_stuff(struct connectdata *conn,
PKCS12_PBE_add();
- if(!PKCS12_parse(p12, data->set.str[STRING_KEY_PASSWD], &pri, &x509,
+ if(!PKCS12_parse(p12, key_passwd, &pri, &x509,
&ca)) {
failf(data,
"could not parse PKCS12 file, check password, " OSSL_PACKAGE
@@ -560,7 +554,7 @@ int cert_stuff(struct connectdata *conn,
EVP_PKEY *priv_key = NULL;
if(data->state.engine) {
UI_METHOD *ui_method =
- UI_create_method((char *)"cURL user interface");
+ UI_create_method((char *)"curl user interface");
if(!ui_method) {
failf(data, "unable do create " OSSL_PACKAGE
" user-interface method");
@@ -574,7 +568,7 @@ int cert_stuff(struct connectdata *conn,
priv_key = (EVP_PKEY *)
ENGINE_load_private_key(data->state.engine, key_file,
ui_method,
- data->set.str[STRING_KEY_PASSWD]);
+ key_passwd);
UI_destroy_method(ui_method);
if(!priv_key) {
failf(data, "failed to load private key from crypto engine");
@@ -711,6 +705,10 @@ int Curl_ossl_init(void)
CONF_MFLAGS_DEFAULT_SECTION|
CONF_MFLAGS_IGNORE_MISSING_FILE);
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
+ !defined(LIBRESSL_VERSION_NUMBER)
+ /* OpenSSL 1.1.0+ takes care of initialization itself */
+#else
/* Lets get nice error messages */
SSL_load_error_strings();
@@ -719,6 +717,7 @@ int Curl_ossl_init(void)
return 0;
OpenSSL_add_all_algorithms();
+#endif
return 1;
}
@@ -726,6 +725,11 @@ int Curl_ossl_init(void)
/* Global cleanup */
void Curl_ossl_cleanup(void)
{
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
+ !defined(LIBRESSL_VERSION_NUMBER)
+ /* OpenSSL 1.1 deprecates all these cleanup functions and
+ turns them into no-ops in OpenSSL 1.0 compatibility mode */
+#else
/* Free ciphers and digests lists */
EVP_cleanup();
@@ -734,18 +738,11 @@ void Curl_ossl_cleanup(void)
ENGINE_cleanup();
#endif
-#ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
- /* Free OpenSSL ex_data table */
- CRYPTO_cleanup_all_ex_data();
-#endif
-
/* Free OpenSSL error strings */
ERR_free_strings();
/* Free thread local error state, destroying hash upon zero refcount */
-#ifdef HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED
-
-#elif defined(HAVE_ERR_REMOVE_THREAD_STATE)
+#ifdef HAVE_ERR_REMOVE_THREAD_STATE
ERR_remove_thread_state(NULL);
#else
ERR_remove_state(0);
@@ -757,6 +754,7 @@ void Curl_ossl_cleanup(void)
#ifdef HAVE_SSL_COMP_FREE_COMPRESSION_METHODS
SSL_COMP_free_compression_methods();
#endif
+#endif
}
/*
@@ -901,13 +899,8 @@ struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
}
-/*
- * This function is called when an SSL connection is closed.
- */
-void Curl_ossl_close(struct connectdata *conn, int sockindex)
+static void ossl_close(struct ssl_connect_data *connssl)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-
if(connssl->handle) {
(void)SSL_shutdown(connssl->handle);
SSL_set_connect_state(connssl->handle);
@@ -922,6 +915,15 @@ void Curl_ossl_close(struct connectdata *conn, int sockindex)
}
/*
+ * This function is called when an SSL connection is closed.
+ */
+void Curl_ossl_close(struct connectdata *conn, int sockindex)
+{
+ ossl_close(&conn->ssl[sockindex]);
+ ossl_close(&conn->proxy_ssl[sockindex]);
+}
+
+/*
* This function is called to shut down the SSL layer but keep the
* socket open (CCC - Clear Command Channel)
*/
@@ -949,8 +951,8 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
if(connssl->handle) {
buffsize = (int)sizeof(buf);
while(!done) {
- int what = Curl_socket_ready(conn->sock[sockindex],
- CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+ int what = SOCKET_READABLE(conn->sock[sockindex],
+ SSL_SHUTDOWN_TIMEOUT);
if(what > 0) {
ERR_clear_error();
@@ -1043,6 +1045,14 @@ void Curl_ossl_close_all(struct Curl_easy *data)
#else
(void)data;
#endif
+#if !defined(HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED) && \
+ defined(HAVE_ERR_REMOVE_THREAD_STATE)
+ /* OpenSSL 1.0.1 and 1.0.2 build an error queue that is stored per-thread
+ so we need to clean it here in case the thread will be killed. All OpenSSL
+ code should extract the error in association with the error so clearing
+ this queue here should be harmless at worst. */
+ ERR_remove_thread_state(NULL);
+#endif
}
/* ====================================================== */
@@ -1083,16 +1093,21 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
#endif
CURLcode result = CURLE_OK;
bool dNSName = FALSE; /* if a dNSName field exists in the cert */
+ bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
+ const char * const dispname = SSL_IS_PROXY() ?
+ conn->http_proxy.host.dispname : conn->host.dispname;
#ifdef ENABLE_IPV6
if(conn->bits.ipv6_ip &&
- Curl_inet_pton(AF_INET6, conn->host.name, &addr)) {
+ Curl_inet_pton(AF_INET6, hostname, &addr)) {
target = GEN_IPADD;
addrlen = sizeof(struct in6_addr);
}
else
#endif
- if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) {
+ if(Curl_inet_pton(AF_INET, hostname, &addr)) {
target = GEN_IPADD;
addrlen = sizeof(struct in_addr);
}
@@ -1115,15 +1130,15 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
/* get a handle to alternative name number i */
const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
- /* If a subjectAltName extension of type dNSName is present, that MUST
- be used as the identity. / RFC2818 section 3.1 */
if(check->type == GEN_DNS)
dNSName = TRUE;
+ else if(check->type == GEN_IPADD)
+ iPAddress = TRUE;
/* only check alternatives of the same type the target is */
if(check->type == target) {
/* get data and length */
- const char *altptr = (char *)ASN1_STRING_data(check->d.ia5);
+ const char *altptr = (char *)ASN1_STRING_get0_data(check->d.ia5);
size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5);
switch(target) {
@@ -1141,11 +1156,11 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
if((altlen == strlen(altptr)) &&
/* if this isn't true, there was an embedded zero in the name
string and we cannot match it. */
- Curl_cert_hostcheck(altptr, conn->host.name)) {
+ Curl_cert_hostcheck(altptr, hostname)) {
dnsmatched = TRUE;
infof(data,
" subjectAltName: host \"%s\" matched cert's \"%s\"\n",
- conn->host.dispname, altptr);
+ dispname, altptr);
}
break;
@@ -1156,7 +1171,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
ipmatched = TRUE;
infof(data,
" subjectAltName: host \"%s\" matched cert's IP address!\n",
- conn->host.dispname);
+ dispname);
}
break;
}
@@ -1164,21 +1179,17 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
}
GENERAL_NAMES_free(altnames);
- if(dnsmatched || (!dNSName && ipmatched)) {
- /* count as a match if the dnsname matched or if there was no dnsname
- fields at all AND there was an IP field match */
+ if(dnsmatched || ipmatched)
matched = TRUE;
- }
}
if(matched)
/* an alternative name matched */
;
- else if(dNSName) {
- /* an dNSName field existed, but didn't match and then we MUST fail */
- infof(data, " subjectAltName does not match %s\n", conn->host.dispname);
+ else if(dNSName || iPAddress) {
+ infof(data, " subjectAltName does not match %s\n", dispname);
failf(data, "SSL: no alternative certificate subject name matches "
- "target host name '%s'", conn->host.dispname);
+ "target host name '%s'", dispname);
result = CURLE_PEER_FAILED_VERIFICATION;
}
else {
@@ -1215,7 +1226,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
if(j >= 0) {
peer_CN = OPENSSL_malloc(j+1);
if(peer_CN) {
- memcpy(peer_CN, ASN1_STRING_data(tmp), j);
+ memcpy(peer_CN, ASN1_STRING_get0_data(tmp), j);
peer_CN[j] = '\0';
}
}
@@ -1252,9 +1263,9 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
"SSL: unable to obtain common name from peer certificate");
result = CURLE_PEER_FAILED_VERIFICATION;
}
- else if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
+ else if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) {
failf(data, "SSL: certificate subject name '%s' does not match "
- "target host name '%s'", peer_CN, conn->host.dispname);
+ "target host name '%s'", peer_CN, dispname);
result = CURLE_PEER_FAILED_VERIFICATION;
}
else {
@@ -1529,6 +1540,11 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
verstr = "TLSv1.2";
break;
#endif
+#ifdef TLS1_3_VERSION
+ case TLS1_3_VERSION:
+ verstr = "TLSv1.3";
+ break;
+#endif
case 0:
break;
default:
@@ -1551,7 +1567,7 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
else
tls_rt_name = "";
- msg_type = *(char*)buf;
+ msg_type = *(char *)buf;
msg_name = ssl_msg_type(ssl_ver, msg_type);
txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n",
@@ -1657,6 +1673,10 @@ get_ssl_version_txt(SSL *ssl)
return "";
switch(SSL_version(ssl)) {
+#ifdef TLS1_3_VERSION
+ case TLS1_3_VERSION:
+ return "TLSv1.3";
+#endif
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
case TLS1_2_VERSION:
return "TLSv1.2";
@@ -1691,23 +1711,39 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
struct in_addr addr;
#endif
#endif
+ long * const certverifyresult = SSL_IS_PROXY() ?
+ &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
+ const long int ssl_version = SSL_CONN_CONFIG(version);
+#ifdef USE_TLS_SRP
+ const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype);
+#endif
+ char * const ssl_cert = SSL_SET_OPTION(cert);
+ const char * const ssl_cert_type = SSL_SET_OPTION(cert_type);
+ const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+ const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
+ const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+ const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
/* Make funny stuff to get random input */
- Curl_ossl_seed(data);
+ result = Curl_ossl_seed(data);
+ if(result)
+ return result;
- data->set.ssl.certverifyresult = !X509_V_OK;
+ *certverifyresult = !X509_V_OK;
/* check to see if we've been told to use an explicit SSL/TLS version */
- switch(data->set.ssl.version) {
- default:
+ switch(ssl_version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2:
+ case CURL_SSLVERSION_TLSv1_3:
/* it will be handled later with the context options */
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
!defined(LIBRESSL_VERSION_NUMBER)
@@ -1723,7 +1759,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_NOT_BUILT_IN;
#else
#ifdef USE_TLS_SRP
- if(data->set.ssl.authtype == CURL_TLSAUTH_SRP)
+ if(ssl_authtype == CURL_TLSAUTH_SRP)
return CURLE_SSL_CONNECT_ERROR;
#endif
req_method = SSLv2_client_method();
@@ -1736,13 +1772,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_NOT_BUILT_IN;
#else
#ifdef USE_TLS_SRP
- if(data->set.ssl.authtype == CURL_TLSAUTH_SRP)
+ if(ssl_authtype == CURL_TLSAUTH_SRP)
return CURLE_SSL_CONNECT_ERROR;
#endif
req_method = SSLv3_client_method();
use_sni(FALSE);
break;
#endif
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
}
if(connssl->ctx)
@@ -1821,14 +1860,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
/* unless the user explicitly ask to allow the protocol vulnerability we
use the work-around */
- if(!conn->data->set.ssl_enable_beast)
+ if(!SSL_SET_OPTION(enable_beast))
ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
#endif
- switch(data->set.ssl.version) {
+ switch(ssl_version) {
case CURL_SSLVERSION_SSLv3:
#ifdef USE_TLS_SRP
- if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
+ if(ssl_authtype == CURL_TLSAUTH_SRP) {
infof(data, "Set version TLSv1.x for SRP authorisation\n");
}
#endif
@@ -1837,6 +1876,9 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
ctx_options |= SSL_OP_NO_TLSv1_1;
ctx_options |= SSL_OP_NO_TLSv1_2;
+#ifdef TLS1_3_VERSION
+ ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
#endif
break;
@@ -1852,38 +1894,75 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
ctx_options |= SSL_OP_NO_TLSv1_1;
ctx_options |= SSL_OP_NO_TLSv1_2;
+#ifdef TLS1_3_VERSION
+ ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
#endif
break;
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
case CURL_SSLVERSION_TLSv1_1:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
ctx_options |= SSL_OP_NO_SSLv2;
ctx_options |= SSL_OP_NO_SSLv3;
ctx_options |= SSL_OP_NO_TLSv1;
ctx_options |= SSL_OP_NO_TLSv1_2;
+#ifdef TLS1_3_VERSION
+ ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
break;
+#else
+ failf(data, OSSL_PACKAGE " was built without TLS 1.1 support");
+ return CURLE_NOT_BUILT_IN;
+#endif
case CURL_SSLVERSION_TLSv1_2:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_SSLv3;
+ ctx_options |= SSL_OP_NO_TLSv1;
+ ctx_options |= SSL_OP_NO_TLSv1_1;
+#ifdef TLS1_3_VERSION
+ ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
+ break;
+#else
+ failf(data, OSSL_PACKAGE " was built without TLS 1.2 support");
+ return CURLE_NOT_BUILT_IN;
+#endif
+
+ case CURL_SSLVERSION_TLSv1_3:
+#ifdef TLS1_3_VERSION
+ SSL_CTX_set_max_proto_version(connssl->ctx, TLS1_3_VERSION);
ctx_options |= SSL_OP_NO_SSLv2;
ctx_options |= SSL_OP_NO_SSLv3;
ctx_options |= SSL_OP_NO_TLSv1;
ctx_options |= SSL_OP_NO_TLSv1_1;
+ ctx_options |= SSL_OP_NO_TLSv1_2;
break;
+#else
+ failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
+ return CURLE_NOT_BUILT_IN;
#endif
-#ifndef OPENSSL_NO_SSL2
case CURL_SSLVERSION_SSLv2:
+#ifndef OPENSSL_NO_SSL2
ctx_options |= SSL_OP_NO_SSLv3;
ctx_options |= SSL_OP_NO_TLSv1;
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
ctx_options |= SSL_OP_NO_TLSv1_1;
ctx_options |= SSL_OP_NO_TLSv1_2;
+#ifdef TLS1_3_VERSION
+ ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
#endif
break;
+#else
+ failf(data, OSSL_PACKAGE " was built without SSLv2 support");
+ return CURLE_NOT_BUILT_IN;
#endif
default:
- failf(data, "Unsupported SSL protocol version");
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -1922,19 +2001,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
}
#endif
- if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) {
- if(!cert_stuff(conn,
- connssl->ctx,
- data->set.str[STRING_CERT],
- data->set.str[STRING_CERT_TYPE],
- data->set.str[STRING_KEY],
- data->set.str[STRING_KEY_TYPE])) {
+ if(ssl_cert || ssl_cert_type) {
+ if(!cert_stuff(conn, connssl->ctx, ssl_cert, ssl_cert_type,
+ SSL_SET_OPTION(key), SSL_SET_OPTION(key_type),
+ SSL_SET_OPTION(key_passwd))) {
/* failf() is already done in cert_stuff() */
return CURLE_SSL_CERTPROBLEM;
}
}
- ciphers = data->set.str[STRING_SSL_CIPHER_LIST];
+ ciphers = SSL_CONN_CONFIG(cipher_list);
if(!ciphers)
ciphers = (char *)DEFAULT_CIPHER_SELECTION;
if(!SSL_CTX_set_cipher_list(connssl->ctx, ciphers)) {
@@ -1944,18 +2020,20 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
infof(data, "Cipher selection: %s\n", ciphers);
#ifdef USE_TLS_SRP
- if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
- infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
+ if(ssl_authtype == CURL_TLSAUTH_SRP) {
+ char * const ssl_username = SSL_SET_OPTION(username);
+
+ infof(data, "Using TLS-SRP username: %s\n", ssl_username);
- if(!SSL_CTX_set_srp_username(connssl->ctx, data->set.ssl.username)) {
+ if(!SSL_CTX_set_srp_username(connssl->ctx, ssl_username)) {
failf(data, "Unable to set SRP user name");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
- if(!SSL_CTX_set_srp_password(connssl->ctx, data->set.ssl.password)) {
+ if(!SSL_CTX_set_srp_password(connssl->ctx, SSL_SET_OPTION(password))) {
failf(data, "failed setting SRP password");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
- if(!data->set.str[STRING_SSL_CIPHER_LIST]) {
+ if(!SSL_CONN_CONFIG(cipher_list)) {
infof(data, "Setting cipher list SRP\n");
if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) {
@@ -1965,20 +2043,17 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
}
}
#endif
- if(data->set.str[STRING_SSL_CAFILE] || data->set.str[STRING_SSL_CAPATH]) {
+
+ if(ssl_cafile || ssl_capath) {
/* tell SSL where to find CA certificates that are used to verify
the servers certificate. */
- if(!SSL_CTX_load_verify_locations(connssl->ctx,
- data->set.str[STRING_SSL_CAFILE],
- data->set.str[STRING_SSL_CAPATH])) {
- if(data->set.ssl.verifypeer) {
+ if(!SSL_CTX_load_verify_locations(connssl->ctx, ssl_cafile, ssl_capath)) {
+ if(verifypeer) {
/* Fail if we insist on successfully verifying the server. */
failf(data, "error setting certificate verify locations:\n"
" CAfile: %s\n CApath: %s",
- data->set.str[STRING_SSL_CAFILE]?
- data->set.str[STRING_SSL_CAFILE]: "none",
- data->set.str[STRING_SSL_CAPATH]?
- data->set.str[STRING_SSL_CAPATH] : "none");
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
return CURLE_SSL_CACERT_BADFILE;
}
else {
@@ -1995,29 +2070,25 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
infof(data,
" CAfile: %s\n"
" CApath: %s\n",
- data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
- "none",
- data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
- "none");
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
}
#ifdef CURL_CA_FALLBACK
- else if(data->set.ssl.verifypeer) {
+ else if(verifypeer) {
/* verfying the peer without any CA certificates won't
work so use openssl's built in default as fallback */
SSL_CTX_set_default_verify_paths(connssl->ctx);
}
#endif
- if(data->set.str[STRING_SSL_CRLFILE]) {
+ if(ssl_crlfile) {
/* tell SSL where to find CRL file that is used to check certificate
* revocation */
lookup=X509_STORE_add_lookup(SSL_CTX_get_cert_store(connssl->ctx),
X509_LOOKUP_file());
if(!lookup ||
- (!X509_load_crl_file(lookup, data->set.str[STRING_SSL_CRLFILE],
- X509_FILETYPE_PEM)) ) {
- failf(data, "error loading CRL file: %s",
- data->set.str[STRING_SSL_CRLFILE]);
+ (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
+ failf(data, "error loading CRL file: %s", ssl_crlfile);
return CURLE_SSL_CRL_BADFILE;
}
else {
@@ -2026,9 +2097,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
}
- infof(data,
- " CRLfile: %s\n", data->set.str[STRING_SSL_CRLFILE] ?
- data->set.str[STRING_SSL_CRLFILE]: "none");
+ infof(data, " CRLfile: %s\n", ssl_crlfile);
}
/* Try building a chain using issuers in the trusted store first to avoid
@@ -2039,7 +2108,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest
*/
#if defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS)
- if(data->set.ssl.verifypeer) {
+ if(verifypeer) {
X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
X509_V_FLAG_TRUSTED_FIRST);
}
@@ -2050,8 +2119,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
* anyway. In the latter case the result of the verification is checked with
* SSL_get_verify_result() below. */
SSL_CTX_set_verify(connssl->ctx,
- data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
- NULL);
+ verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
/* give application a chance to interfere with SSL set up. */
if(data->set.ssl.fsslctx) {
@@ -2074,31 +2142,30 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
!defined(OPENSSL_NO_OCSP)
- if(data->set.ssl.verifystatus)
+ if(SSL_CONN_CONFIG(verifystatus))
SSL_set_tlsext_status_type(connssl->handle, TLSEXT_STATUSTYPE_ocsp);
#endif
SSL_set_connect_state(connssl->handle);
connssl->server_cert = 0x0;
-
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
- if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
+ if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
#ifdef ENABLE_IPV6
- (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
+ (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
#endif
sni &&
- !SSL_set_tlsext_host_name(connssl->handle, conn->host.name))
+ !SSL_set_tlsext_host_name(connssl->handle, hostname))
infof(data, "WARNING: failed to configure server name indication (SNI) "
"TLS extension\n");
#endif
/* Check if there's a cached ID we can/should use here! */
- if(conn->ssl_config.sessionid) {
+ if(data->set.general_ssl.sessionid) {
void *ssl_sessionid = NULL;
Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
+ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
/* we got a session id, use it! */
if(!SSL_set_session(connssl->handle, ssl_sessionid)) {
Curl_ssl_sessionid_unlock(conn);
@@ -2112,8 +2179,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
Curl_ssl_sessionid_unlock(conn);
}
- /* pass the raw socket into the SSL layers */
- if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
+ if(conn->proxy_ssl[sockindex].use) {
+ BIO *const bio = BIO_new(BIO_f_ssl());
+ DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
+ DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL);
+ DEBUGASSERT(bio != NULL);
+ BIO_set_ssl(bio, conn->proxy_ssl[sockindex].handle, FALSE);
+ SSL_set_bio(connssl->handle, bio, bio);
+ }
+ else if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
+ /* pass the raw socket into the SSL layers */
failf(data, "SSL: SSL_set_fd failed: %s",
ERR_error_string(ERR_get_error(), NULL));
return CURLE_SSL_CONNECT_ERROR;
@@ -2129,9 +2204,11 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
struct Curl_easy *data = conn->data;
int err;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ long * const certverifyresult = SSL_IS_PROXY() ?
+ &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
- || ssl_connect_2_reading == connssl->connecting_state
- || ssl_connect_2_writing == connssl->connecting_state);
+ || ssl_connect_2_reading == connssl->connecting_state
+ || ssl_connect_2_writing == connssl->connecting_state);
ERR_clear_error();
@@ -2178,6 +2255,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
lerr = SSL_get_verify_result(connssl->handle);
if(lerr != X509_V_OK) {
+ *certverifyresult = lerr;
snprintf(error_buffer, sizeof(error_buffer),
"SSL certificate problem: %s",
X509_verify_cert_error_string(lerr));
@@ -2199,8 +2277,11 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
* the SO_ERROR is also lost.
*/
if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
+ const char * const hostname = SSL_IS_PROXY() ?
+ conn->http_proxy.host.name : conn->host.name;
+ const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
failf(data, "Unknown SSL protocol error in connection to %s:%ld ",
- conn->host.name, conn->remote_port);
+ hostname, port);
return result;
}
@@ -2224,7 +2305,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
* negotiated
*/
if(conn->bits.tls_enable_alpn) {
- const unsigned char* neg_protocol;
+ const unsigned char *neg_protocol;
unsigned int len;
SSL_get0_alpn_selected(connssl->handle, &neg_protocol, &len);
if(len != 0) {
@@ -2309,7 +2390,7 @@ do { \
static int X509V3_ext(struct Curl_easy *data,
int certnum,
- STACK_OF(X509_EXTENSION) *exts)
+ CONST_EXTS STACK_OF(X509_EXTENSION) *exts)
{
int i;
size_t j;
@@ -2391,7 +2472,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
EVP_PKEY *pubkey=NULL;
int j;
char *ptr;
- ASN1_BIT_STRING *psig = NULL;
+ CONST_ASN1_BIT_STRING ASN1_BIT_STRING *psig = NULL;
X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
push_certinfo("Subject", i);
@@ -2411,7 +2492,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
#if defined(HAVE_X509_GET0_SIGNATURE) && defined(HAVE_X509_GET0_EXTENSIONS)
{
- X509_ALGOR *palg = NULL;
+ const X509_ALGOR *palg = NULL;
ASN1_STRING *a = ASN1_STRING_new();
if(a) {
X509_get0_signature(&psig, &palg, x);
@@ -2442,10 +2523,10 @@ static CURLcode get_cert_chain(struct connectdata *conn,
}
#endif
- ASN1_TIME_print(mem, X509_get_notBefore(x));
+ ASN1_TIME_print(mem, X509_get0_notBefore(x));
push_certinfo("Start date", i);
- ASN1_TIME_print(mem, X509_get_notAfter(x));
+ ASN1_TIME_print(mem, X509_get0_notAfter(x));
push_certinfo("Expire date", i);
pubkey = X509_get_pubkey(x);
@@ -2629,7 +2710,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
break; /* failed */
/* https://www.openssl.org/docs/crypto/buffer.html */
- buff1 = temp = OPENSSL_malloc(len1);
+ buff1 = temp = malloc(len1);
if(!buff1)
break; /* failed */
@@ -2652,7 +2733,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
/* https://www.openssl.org/docs/crypto/buffer.html */
if(buff1)
- OPENSSL_free(buff1);
+ free(buff1);
return result;
}
@@ -2677,6 +2758,8 @@ static CURLcode servercert(struct connectdata *conn,
FILE *fp;
char *buffer = data->state.buffer;
const char *ptr;
+ long * const certverifyresult = SSL_IS_PROXY() ?
+ &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
BIO *mem = BIO_new(BIO_s_mem());
if(data->set.ssl.certinfo)
@@ -2692,25 +2775,25 @@ static CURLcode servercert(struct connectdata *conn,
return CURLE_PEER_FAILED_VERIFICATION;
}
- infof(data, "Server certificate:\n");
+ infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server");
rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
buffer, BUFSIZE);
infof(data, " subject: %s\n", rc?"[NONE]":buffer);
- ASN1_TIME_print(mem, X509_get_notBefore(connssl->server_cert));
+ ASN1_TIME_print(mem, X509_get0_notBefore(connssl->server_cert));
len = BIO_get_mem_data(mem, (char **) &ptr);
infof(data, " start date: %.*s\n", len, ptr);
rc = BIO_reset(mem);
- ASN1_TIME_print(mem, X509_get_notAfter(connssl->server_cert));
+ ASN1_TIME_print(mem, X509_get0_notAfter(connssl->server_cert));
len = BIO_get_mem_data(mem, (char **) &ptr);
infof(data, " expire date: %.*s\n", len, ptr);
rc = BIO_reset(mem);
BIO_free(mem);
- if(data->set.ssl.verifyhost) {
+ if(SSL_CONN_CONFIG(verifyhost)) {
result = verifyhost(conn, connssl->server_cert);
if(result) {
X509_free(connssl->server_cert);
@@ -2733,12 +2816,12 @@ static CURLcode servercert(struct connectdata *conn,
deallocating the certificate. */
/* e.g. match issuer name with provided issuer certificate */
- if(data->set.str[STRING_SSL_ISSUERCERT]) {
- fp = fopen(data->set.str[STRING_SSL_ISSUERCERT], FOPEN_READTEXT);
+ if(SSL_SET_OPTION(issuercert)) {
+ fp = fopen(SSL_SET_OPTION(issuercert), FOPEN_READTEXT);
if(!fp) {
if(strict)
failf(data, "SSL: Unable to open issuer cert (%s)",
- data->set.str[STRING_SSL_ISSUERCERT]);
+ SSL_SET_OPTION(issuercert));
X509_free(connssl->server_cert);
connssl->server_cert = NULL;
return CURLE_SSL_ISSUER_ERROR;
@@ -2748,7 +2831,7 @@ static CURLcode servercert(struct connectdata *conn,
if(!issuer) {
if(strict)
failf(data, "SSL: Unable to read issuer cert (%s)",
- data->set.str[STRING_SSL_ISSUERCERT]);
+ SSL_SET_OPTION(issuercert));
X509_free(connssl->server_cert);
X509_free(issuer);
fclose(fp);
@@ -2760,7 +2843,7 @@ static CURLcode servercert(struct connectdata *conn,
if(X509_check_issued(issuer, connssl->server_cert) != X509_V_OK) {
if(strict)
failf(data, "SSL: Certificate issuer check failed (%s)",
- data->set.str[STRING_SSL_ISSUERCERT]);
+ SSL_SET_OPTION(issuercert));
X509_free(connssl->server_cert);
X509_free(issuer);
connssl->server_cert = NULL;
@@ -2768,15 +2851,14 @@ static CURLcode servercert(struct connectdata *conn,
}
infof(data, " SSL certificate issuer check ok (%s)\n",
- data->set.str[STRING_SSL_ISSUERCERT]);
+ SSL_SET_OPTION(issuercert));
X509_free(issuer);
}
- lerr = data->set.ssl.certverifyresult =
- SSL_get_verify_result(connssl->handle);
+ lerr = *certverifyresult = SSL_get_verify_result(connssl->handle);
- if(data->set.ssl.certverifyresult != X509_V_OK) {
- if(data->set.ssl.verifypeer) {
+ if(*certverifyresult != X509_V_OK) {
+ if(SSL_CONN_CONFIG(verifypeer)) {
/* We probably never reach this, because SSL_connect() will fail
and we return earlier if verifypeer is set? */
if(strict)
@@ -2795,7 +2877,7 @@ static CURLcode servercert(struct connectdata *conn,
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
!defined(OPENSSL_NO_OCSP)
- if(data->set.ssl.verifystatus) {
+ if(SSL_CONN_CONFIG(verifystatus)) {
result = verifystatus(conn, connssl);
if(result) {
X509_free(connssl->server_cert);
@@ -2831,7 +2913,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
- if(conn->ssl_config.sessionid) {
+ if(data->set.general_ssl.sessionid) {
bool incache;
SSL_SESSION *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
@@ -2843,7 +2925,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
regardless of its state. */
Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
+ incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
+ sockindex));
if(incache) {
if(old_ssl_sessionid != our_ssl_sessionid) {
infof(data, "old SSL session ID is stale, removing\n");
@@ -2854,7 +2937,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
if(!incache) {
result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
- 0 /* unknown size */);
+ 0 /* unknown size */, sockindex);
if(result) {
Curl_ssl_sessionid_unlock(conn);
failf(data, "failed to store ssl session");
@@ -2878,8 +2961,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
* operations.
*/
- result = servercert(conn, connssl,
- (data->set.ssl.verifypeer || data->set.ssl.verifyhost));
+ result = servercert(conn, connssl, (SSL_CONN_CONFIG(verifypeer) ||
+ SSL_CONN_CONFIG(verifyhost)));
if(!result)
connssl->connecting_state = ssl_connect_done;
@@ -2899,7 +2982,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
- long timeout_ms;
+ time_t timeout_ms;
int what;
/* check if the connection has already been established */
@@ -2945,7 +3028,8 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
curl_socket_t readfd = ssl_connect_2_reading==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
- what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
+ what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
+ nonblocking?0:timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -3026,7 +3110,10 @@ bool Curl_ossl_data_pending(const struct connectdata *conn, int connindex)
{
if(conn->ssl[connindex].handle)
/* SSL is in use */
- return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
+ return (0 != SSL_pending(conn->ssl[connindex].handle) ||
+ (conn->proxy_ssl[connindex].handle &&
+ 0 != SSL_pending(conn->proxy_ssl[connindex].handle))) ?
+ TRUE : FALSE;
else
return FALSE;
}
@@ -3071,8 +3158,18 @@ static ssize_t ossl_send(struct connectdata *conn,
/* A failure in the SSL library occurred, usually a protocol error.
The OpenSSL error queue contains more information on the error. */
sslerror = ERR_get_error();
- failf(conn->data, "SSL_write() error: %s",
- ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
+ if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL &&
+ ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET &&
+ conn->ssl[sockindex].state == ssl_connection_complete &&
+ conn->proxy_ssl[sockindex].state == ssl_connection_complete) {
+ char ver[120];
+ Curl_ossl_version(ver, 120);
+ failf(conn->data, "Error: %s does not support double SSL tunneling.",
+ ver);
+ }
+ else
+ failf(conn->data, "SSL_write() error: %s",
+ ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
*curlcode = CURLE_SEND_ERROR;
return -1;
}
@@ -3142,7 +3239,7 @@ size_t Curl_ossl_version(char *buffer, size_t size)
unsigned long ssleay_value;
sub[2]='\0';
sub[1]='\0';
- ssleay_value=SSLeay();
+ ssleay_value=OpenSSL_version_num();
if(ssleay_value < 0x906000) {
ssleay_value=SSLEAY_VERSION_NUMBER;
sub[0]='\0';
@@ -3177,7 +3274,12 @@ int Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy,
size_t length)
{
if(data) {
- Curl_ossl_seed(data); /* Initiate the seed if not already done */
+ if(Curl_ossl_seed(data)) /* Initiate the seed if not already done */
+ return 1; /* couldn't seed for some reason */
+ }
+ else {
+ if(!rand_enough())
+ return 1;
}
RAND_bytes(entropy, curlx_uztosi(length));
return 0; /* 0 as in no problem */
diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c
index d33f5480..f2f973c5 100644
--- a/lib/vtls/polarssl.c
+++ b/lib/vtls/polarssl.c
@@ -54,7 +54,7 @@
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "polarssl_threadlock.h"
#include "curl_printf.h"
#include "curl_memory.h"
@@ -75,6 +75,11 @@
#define THREADING_SUPPORT
#endif
+#ifndef POLARSSL_ERROR_C
+#define error_strerror(x,y,z)
+#endif /* POLARSSL_ERROR_C */
+
+
#if defined(THREADING_SUPPORT)
static entropy_context entropy;
@@ -96,13 +101,13 @@ static void entropy_init_mutex(entropy_context *ctx)
/* start of entropy_func_mutex() */
static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
{
- int ret;
- /* lock 1 = entropy_func_mutex() */
- Curl_polarsslthreadlock_lock_function(1);
- ret = entropy_func(data, output, len);
- Curl_polarsslthreadlock_unlock_function(1);
+ int ret;
+ /* lock 1 = entropy_func_mutex() */
+ Curl_polarsslthreadlock_lock_function(1);
+ ret = entropy_func(data, output, len);
+ Curl_polarsslthreadlock_unlock_function(1);
- return ret;
+ return ret;
}
/* end of entropy_func_mutex() */
@@ -138,84 +143,70 @@ static Curl_send polarssl_send;
static CURLcode
polarssl_connect_step1(struct connectdata *conn,
- int sockindex)
+ int sockindex)
{
struct Curl_easy *data = conn->data;
struct ssl_connect_data* connssl = &conn->ssl[sockindex];
-
- bool sni = TRUE; /* default is SNI enabled */
+ const char *capath = SSL_CONN_CONFIG(CApath);
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
+ const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
int ret = -1;
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif
char errorbuf[128];
errorbuf[0]=0;
/* PolarSSL only supports SSLv3 and TLSv1 */
- if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+ if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
failf(data, "PolarSSL does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
}
- else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
- sni = FALSE; /* SSLv3 has no SNI */
#ifdef THREADING_SUPPORT
entropy_init_mutex(&entropy);
if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_mutex, &entropy,
NULL, 0)) != 0) {
-#ifdef POLARSSL_ERROR_C
- error_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* POLARSSL_ERROR_C */
- failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
- -ret, errorbuf);
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+ failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
+ -ret, errorbuf);
}
#else
entropy_init(&connssl->entropy);
if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->entropy,
NULL, 0)) != 0) {
-#ifdef POLARSSL_ERROR_C
- error_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* POLARSSL_ERROR_C */
- failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
- -ret, errorbuf);
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+ failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
+ -ret, errorbuf);
}
#endif /* THREADING_SUPPORT */
/* Load the trusted CA */
memset(&connssl->cacert, 0, sizeof(x509_crt));
- if(data->set.str[STRING_SSL_CAFILE]) {
+ if(SSL_CONN_CONFIG(CAfile)) {
ret = x509_crt_parse_file(&connssl->cacert,
- data->set.str[STRING_SSL_CAFILE]);
+ SSL_CONN_CONFIG(CAfile));
if(ret<0) {
-#ifdef POLARSSL_ERROR_C
error_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* POLARSSL_ERROR_C */
failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s",
- data->set.str[STRING_SSL_CAFILE], -ret, errorbuf);
+ SSL_CONN_CONFIG(CAfile), -ret, errorbuf);
- if(data->set.ssl.verifypeer)
+ if(SSL_CONN_CONFIG(verifypeer))
return CURLE_SSL_CACERT_BADFILE;
}
}
- if(data->set.str[STRING_SSL_CAPATH]) {
- ret = x509_crt_parse_path(&connssl->cacert,
- data->set.str[STRING_SSL_CAPATH]);
+ if(capath) {
+ ret = x509_crt_parse_path(&connssl->cacert, capath);
if(ret<0) {
-#ifdef POLARSSL_ERROR_C
error_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* POLARSSL_ERROR_C */
failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s",
- data->set.str[STRING_SSL_CAPATH], -ret, errorbuf);
+ capath, -ret, errorbuf);
- if(data->set.ssl.verifypeer)
+ if(SSL_CONN_CONFIG(verifypeer))
return CURLE_SSL_CACERT_BADFILE;
}
}
@@ -223,27 +214,25 @@ polarssl_connect_step1(struct connectdata *conn,
/* Load the client certificate */
memset(&connssl->clicert, 0, sizeof(x509_crt));
- if(data->set.str[STRING_CERT]) {
+ if(SSL_SET_OPTION(cert)) {
ret = x509_crt_parse_file(&connssl->clicert,
- data->set.str[STRING_CERT]);
+ SSL_SET_OPTION(cert));
if(ret) {
-#ifdef POLARSSL_ERROR_C
error_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* POLARSSL_ERROR_C */
failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s",
- data->set.str[STRING_CERT], -ret, errorbuf);
+ SSL_SET_OPTION(cert), -ret, errorbuf);
return CURLE_SSL_CERTPROBLEM;
}
}
/* Load the client private key */
- if(data->set.str[STRING_KEY]) {
+ if(SSL_SET_OPTION(key)) {
pk_context pk;
pk_init(&pk);
- ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY],
- data->set.str[STRING_KEY_PASSWD]);
+ ret = pk_parse_keyfile(&pk, SSL_SET_OPTION(key),
+ SSL_SET_OPTION(key_passwd));
if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
if(ret == 0)
@@ -253,11 +242,9 @@ polarssl_connect_step1(struct connectdata *conn,
pk_free(&pk);
if(ret) {
-#ifdef POLARSSL_ERROR_C
error_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* POLARSSL_ERROR_C */
failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s",
- data->set.str[STRING_KEY], -ret, errorbuf);
+ SSL_SET_OPTION(key), -ret, errorbuf);
return CURLE_SSL_CERTPROBLEM;
}
@@ -266,31 +253,27 @@ polarssl_connect_step1(struct connectdata *conn,
/* Load the CRL */
memset(&connssl->crl, 0, sizeof(x509_crl));
- if(data->set.str[STRING_SSL_CRLFILE]) {
+ if(SSL_SET_OPTION(CRLfile)) {
ret = x509_crl_parse_file(&connssl->crl,
- data->set.str[STRING_SSL_CRLFILE]);
+ SSL_SET_OPTION(CRLfile));
if(ret) {
-#ifdef POLARSSL_ERROR_C
error_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* POLARSSL_ERROR_C */
failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s",
- data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf);
+ SSL_SET_OPTION(CRLfile), -ret, errorbuf);
return CURLE_SSL_CRL_BADFILE;
}
}
- infof(data, "PolarSSL: Connecting to %s:%d\n",
- conn->host.name, conn->remote_port);
+ infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port);
if(ssl_init(&connssl->ssl)) {
failf(data, "PolarSSL: ssl_init failed");
return CURLE_SSL_CONNECT_ERROR;
}
- switch(data->set.ssl.version) {
- default:
+ switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
@@ -324,6 +307,12 @@ polarssl_connect_step1(struct connectdata *conn,
SSL_MINOR_VERSION_3);
infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n");
break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "PolarSSL: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
}
ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT);
@@ -338,30 +327,31 @@ polarssl_connect_step1(struct connectdata *conn,
ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites());
/* Check if there's a cached ID we can/should use here! */
- if(conn->ssl_config.sessionid) {
+ if(data->set.general_ssl.sessionid) {
void *old_session = NULL;
Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) {
+ if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
ret = ssl_set_session(&connssl->ssl, old_session);
- Curl_ssl_sessionid_unlock(conn);
if(ret) {
+ Curl_ssl_sessionid_unlock(conn);
failf(data, "ssl_set_session returned -0x%x", -ret);
return CURLE_SSL_CONNECT_ERROR;
}
infof(data, "PolarSSL re-using session\n");
}
+ Curl_ssl_sessionid_unlock(conn);
}
ssl_set_ca_chain(&connssl->ssl,
&connssl->cacert,
&connssl->crl,
- conn->host.name);
+ hostname);
ssl_set_own_cert_rsa(&connssl->ssl,
&connssl->clicert, &connssl->rsa);
- if(ssl_set_hostname(&connssl->ssl, conn->host.name)) {
+ if(ssl_set_hostname(&connssl->ssl, hostname)) {
/* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name
to set in the SNI extension. So even if curl connects to a host
specified as an IP address, this function must be used. */
@@ -371,7 +361,7 @@ polarssl_connect_step1(struct connectdata *conn,
#ifdef HAS_ALPN
if(conn->bits.tls_enable_alpn) {
- static const char* protocols[3];
+ static const char *protocols[3];
int cur = 0;
#ifdef USE_NGHTTP2
@@ -401,7 +391,7 @@ polarssl_connect_step1(struct connectdata *conn,
static CURLcode
polarssl_connect_step2(struct connectdata *conn,
- int sockindex)
+ int sockindex)
{
int ret;
struct Curl_easy *data = conn->data;
@@ -429,9 +419,7 @@ polarssl_connect_step2(struct connectdata *conn,
return CURLE_OK;
default:
-#ifdef POLARSSL_ERROR_C
error_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* POLARSSL_ERROR_C */
failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s",
-ret, errorbuf);
return CURLE_SSL_CONNECT_ERROR;
@@ -442,7 +430,7 @@ polarssl_connect_step2(struct connectdata *conn,
ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
- if(ret && data->set.ssl.verifypeer) {
+ if(ret && SSL_CONN_CONFIG(verifypeer)) {
if(ret & BADCERT_EXPIRED)
failf(data, "Cert verify failed: BADCERT_EXPIRED");
@@ -538,9 +526,9 @@ polarssl_connect_step2(struct connectdata *conn,
}
else
#endif
- if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
- }
+ if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) {
+ conn->negnpn = CURL_HTTP_VERSION_1_1;
+ }
}
else
infof(data, "ALPN, server did not agree to a protocol\n");
@@ -555,7 +543,7 @@ polarssl_connect_step2(struct connectdata *conn,
static CURLcode
polarssl_connect_step3(struct connectdata *conn,
- int sockindex)
+ int sockindex)
{
CURLcode retcode = CURLE_OK;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
@@ -563,7 +551,7 @@ polarssl_connect_step3(struct connectdata *conn,
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
- if(conn->ssl_config.sessionid) {
+ if(data->set.general_ssl.sessionid) {
int ret;
ssl_session *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
@@ -582,10 +570,10 @@ polarssl_connect_step3(struct connectdata *conn,
/* If there's already a matching session in the cache, delete it */
Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL))
+ if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
Curl_ssl_delsessionid(conn, old_ssl_sessionid);
- retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0);
+ retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
Curl_ssl_sessionid_unlock(conn);
if(retcode) {
free(our_ssl_sessionid);
@@ -727,7 +715,8 @@ polarssl_connect_common(struct connectdata *conn,
curl_socket_t readfd = ssl_connect_2_reading==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
- what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
+ what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
+ nonblocking?0:timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -786,8 +775,8 @@ polarssl_connect_common(struct connectdata *conn,
CURLcode
Curl_polarssl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+ int sockindex,
+ bool *done)
{
return polarssl_connect_common(conn, sockindex, TRUE, done);
}
@@ -795,7 +784,7 @@ Curl_polarssl_connect_nonblocking(struct connectdata *conn,
CURLcode
Curl_polarssl_connect(struct connectdata *conn,
- int sockindex)
+ int sockindex)
{
CURLcode result;
bool done = FALSE;
diff --git a/lib/vtls/polarssl_threadlock.c b/lib/vtls/polarssl_threadlock.c
index 3b0ebf88..b1eb7b74 100644
--- a/lib/vtls/polarssl_threadlock.c
+++ b/lib/vtls/polarssl_threadlock.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013-2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2013-2016, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
@@ -52,7 +52,7 @@ int Curl_polarsslthreadlock_thread_setup(void)
int i;
int ret;
- mutex_buf = malloc(NUMT * sizeof(POLARSSL_MUTEX_T));
+ mutex_buf = calloc(NUMT * sizeof(POLARSSL_MUTEX_T), 1);
if(!mutex_buf)
return 0; /* error, no number of threads defined */
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index f991ec90..a72753e9 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -123,16 +123,30 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
#endif
TCHAR *host_name;
CURLcode result;
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n",
- conn->host.name, conn->remote_port);
+ hostname, conn->remote_port);
+
+#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. */
+ connssl->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
+ connssl->use_alpn = false;
+#endif
connssl->cred = NULL;
/* check for an existing re-usable credential handle */
- if(conn->ssl_config.sessionid) {
+ if(data->set.general_ssl.sessionid) {
Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL)) {
+ if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) {
connssl->cred = old_cred;
infof(data, "schannel: re-using existing credential handle\n");
@@ -149,7 +163,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
memset(&schannel_cred, 0, sizeof(schannel_cred));
schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
- if(data->set.ssl.verifypeer) {
+ if(conn->ssl_config.verifypeer) {
#ifdef _WIN32_WCE
/* certificate validation on CE doesn't seem to work right; we'll
do it following a more manual process. */
@@ -158,13 +172,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
SCH_CRED_IGNORE_REVOCATION_OFFLINE;
#else
schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
- if(data->set.ssl_no_revoke)
+ /* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */
+ if(data->set.ssl.no_revoke)
schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
SCH_CRED_IGNORE_REVOCATION_OFFLINE;
else
schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
#endif
- if(data->set.ssl_no_revoke)
+ if(data->set.ssl.no_revoke)
infof(data, "schannel: disabled server certificate revocation "
"checks\n");
else
@@ -177,15 +192,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
infof(data, "schannel: disabled server certificate revocation checks\n");
}
- if(!data->set.ssl.verifyhost) {
+ if(!conn->ssl_config.verifyhost) {
schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
infof(data, "schannel: verifyhost setting prevents Schannel from "
"comparing the supplied target name with the subject "
"names in server certificates. Also disables SNI.\n");
}
- switch(data->set.ssl.version) {
- default:
+ switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT |
@@ -201,12 +215,18 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
case CURL_SSLVERSION_TLSv1_2:
schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT;
break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "Schannel: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
case CURL_SSLVERSION_SSLv3:
schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
break;
case CURL_SSLVERSION_SSLv2:
schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT;
break;
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
}
/* allocate memory for the re-usable credential handle */
@@ -241,32 +261,29 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
}
/* Warn if SNI is disabled due to use of an IP address */
- if(Curl_inet_pton(AF_INET, conn->host.name, &addr)
+ if(Curl_inet_pton(AF_INET, hostname, &addr)
#ifdef ENABLE_IPV6
- || Curl_inet_pton(AF_INET6, conn->host.name, &addr6)
+ || Curl_inet_pton(AF_INET6, hostname, &addr6)
#endif
) {
infof(data, "schannel: using IP address, SNI is not supported by OS.\n");
}
#ifdef HAS_ALPN
- /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above */
- if(conn->bits.tls_enable_alpn &&
- Curl_verify_windows_version(6, 3, PLATFORM_WINNT,
- VERSION_GREATER_THAN_EQUAL)) {
+ if(connssl->use_alpn) {
int cur = 0;
int list_start_index = 0;
- unsigned int* extension_len = NULL;
+ unsigned int *extension_len = NULL;
unsigned short* list_len = NULL;
/* The first four bytes will be an unsigned int indicating number
of bytes of data in the rest of the the buffer. */
- extension_len = (unsigned int*)(&alpn_buffer[cur]);
+ extension_len = (unsigned int *)(&alpn_buffer[cur]);
cur += sizeof(unsigned int);
/* The next four bytes are an indicator that this buffer will contain
ALPN data, as opposed to NPN, for example. */
- *(unsigned int*)&alpn_buffer[cur] =
+ *(unsigned int *)&alpn_buffer[cur] =
SecApplicationProtocolNegotiationExt_ALPN;
cur += sizeof(unsigned int);
@@ -324,15 +341,21 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
}
memset(connssl->ctxt, 0, sizeof(struct curl_schannel_ctxt));
- host_name = Curl_convert_UTF8_to_tchar(conn->host.name);
+ host_name = Curl_convert_UTF8_to_tchar(hostname);
if(!host_name)
return CURLE_OUT_OF_MEMORY;
- /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx */
+ /* Schannel InitializeSecurityContext:
+ https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx
+ At the moment we don't pass inbuf unless we're using ALPN since we only
+ use it for that, and Wine (for which we currently disable ALPN) is giving
+ us problems with inbuf regardless. https://github.com/curl/curl/issues/983
+ */
sspi_status = s_pSecFn->InitializeSecurityContext(
- &connssl->cred->cred_handle, NULL, host_name,
- connssl->req_flags, 0, 0, &inbuf_desc, 0, &connssl->ctxt->ctxt_handle,
+ &connssl->cred->cred_handle, NULL, host_name, connssl->req_flags, 0, 0,
+ (connssl->use_alpn ? &inbuf_desc : NULL),
+ 0, &connssl->ctxt->ctxt_handle,
&outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp);
Curl_unicodefree(host_name);
@@ -391,11 +414,13 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
TCHAR *host_name;
CURLcode result;
bool doread;
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n",
- conn->host.name, conn->remote_port);
+ hostname, conn->remote_port);
if(!connssl->cred || !connssl->ctxt)
return CURLE_SSL_CONNECT_ERROR;
@@ -491,7 +516,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer,
connssl->encdata_offset);
- host_name = Curl_convert_UTF8_to_tchar(conn->host.name);
+ host_name = Curl_convert_UTF8_to_tchar(hostname);
if(!host_name)
return CURLE_OUT_OF_MEMORY;
@@ -608,7 +633,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
#ifdef _WIN32_WCE
/* Windows CE doesn't do any server certificate validation.
We have to do it manually. */
- if(data->set.ssl.verifypeer)
+ if(conn->ssl_config.verifypeer)
return verify_certificate(conn, sockindex);
#endif
@@ -623,6 +648,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
SECURITY_STATUS sspi_status = SEC_E_OK;
CERT_CONTEXT *ccert_context = NULL;
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
#ifdef HAS_ALPN
SecPkgContext_ApplicationProtocol alpn_result;
#endif
@@ -630,7 +657,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n",
- conn->host.name, conn->remote_port);
+ hostname, conn->remote_port);
if(!connssl->cred)
return CURLE_SSL_CONNECT_ERROR;
@@ -651,10 +678,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
}
#ifdef HAS_ALPN
- /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above */
- if(conn->bits.tls_enable_alpn &&
- Curl_verify_windows_version(6, 3, PLATFORM_WINNT,
- VERSION_GREATER_THAN_EQUAL)) {
+ if(connssl->use_alpn) {
sspi_status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
SECPKG_ATTR_APPLICATION_PROTOCOL, &alpn_result);
@@ -689,12 +713,13 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
#endif
/* save the current session data for possible re-use */
- if(conn->ssl_config.sessionid) {
+ if(data->set.general_ssl.sessionid) {
bool incache;
struct curl_schannel_cred *old_cred = NULL;
Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL));
+ incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL,
+ sockindex));
if(incache) {
if(old_cred != connssl->cred) {
infof(data, "schannel: old credential handle is stale, removing\n");
@@ -705,7 +730,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
}
if(!incache) {
result = Curl_ssl_addsessionid(conn, (void *)connssl->cred,
- sizeof(struct curl_schannel_cred));
+ sizeof(struct curl_schannel_cred),
+ sockindex);
if(result) {
Curl_ssl_sessionid_unlock(conn);
failf(data, "schannel: failed to store credential handle");
@@ -757,7 +783,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
- long timeout_ms;
+ time_t timeout_ms;
int what;
/* check if the connection has already been established */
@@ -803,7 +829,8 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
curl_socket_t readfd = ssl_connect_2_reading ==
connssl->connecting_state ? sockfd : CURL_SOCKET_BAD;
- what = Curl_socket_ready(readfd, writefd, nonblocking ? 0 : timeout_ms);
+ what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
+ nonblocking ? 0 : timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL/TLS socket, errno: %d", SOCKERRNO);
@@ -944,7 +971,7 @@ schannel_send(struct connectdata *conn, int sockindex,
/* send entire message or fail */
while(len > (size_t)written) {
ssize_t this_write;
- long timeleft;
+ time_t timeleft;
int what;
this_write = 0;
@@ -959,8 +986,7 @@ schannel_send(struct connectdata *conn, int sockindex,
break;
}
- what = Curl_socket_ready(CURL_SOCKET_BAD, conn->sock[sockindex],
- timeleft);
+ what = SOCKET_WRITABLE(conn->sock[sockindex], timeleft);
if(what < 0) {
/* fatal error */
failf(conn->data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -1364,9 +1390,11 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
*/
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
- conn->host.name, conn->remote_port);
+ hostname, conn->remote_port);
if(connssl->cred && connssl->ctxt) {
SecBufferDesc BuffDesc;
@@ -1388,7 +1416,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
failf(data, "schannel: ApplyControlToken failure: %s",
Curl_sspi_strerror(conn, sspi_status));
- host_name = Curl_convert_UTF8_to_tchar(conn->host.name);
+ host_name = Curl_convert_UTF8_to_tchar(hostname);
if(!host_name)
return CURLE_OUT_OF_MEMORY;
@@ -1513,6 +1541,9 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
CURLcode result = CURLE_OK;
CERT_CONTEXT *pCertContextServer = NULL;
const CERT_CHAIN_CONTEXT *pChainContext = NULL;
+ const char * const conn_hostname = SSL_IS_PROXY() ?
+ conn->http_proxy.host.name :
+ conn->host.name;
status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
SECPKG_ATTR_REMOTE_CERT_CONTEXT,
@@ -1534,7 +1565,7 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
NULL,
pCertContextServer->hCertStore,
&ChainPara,
- (data->set.ssl_no_revoke ? 0 :
+ (data->set.ssl.no_revoke ? 0 :
CERT_CHAIN_REVOCATION_CHECK_CHAIN),
NULL,
&pChainContext)) {
@@ -1570,14 +1601,14 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
}
if(result == CURLE_OK) {
- if(data->set.ssl.verifyhost) {
+ if(conn->ssl_config.verifyhost) {
TCHAR cert_hostname_buff[128];
xcharp_u hostname;
xcharp_u cert_hostname;
DWORD len;
cert_hostname.const_tchar_ptr = cert_hostname_buff;
- hostname.tchar_ptr = Curl_convert_UTF8_to_tchar(conn->host.name);
+ hostname.tchar_ptr = Curl_convert_UTF8_to_tchar(conn_hostname);
/* TODO: Fix this for certificates with multiple alternative names.
Right now we're only asking for the first preferred alternative name.
@@ -1595,7 +1626,7 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
128);
if(len > 0 && *cert_hostname.tchar_ptr == '*') {
/* this is a wildcard cert. try matching the last len - 1 chars */
- int hostname_len = strlen(conn->host.name);
+ int hostname_len = strlen(conn_hostname);
cert_hostname.tchar_ptr++;
if(_tcsicmp(cert_hostname.const_tchar_ptr,
hostname.const_tchar_ptr + hostname_len - len + 2) != 0)
@@ -1610,7 +1641,7 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
_cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname.tchar_ptr);
failf(data, "schannel: CertGetNameString() certificate hostname "
"(%s) did not match connection (%s)",
- _cert_hostname, conn->host.name);
+ _cert_hostname, conn_hostname);
Curl_unicodefree(_cert_hostname);
}
Curl_unicodefree(hostname.tchar_ptr);
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index 38637771..e8fd3cf4 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -61,10 +61,11 @@
#include "vtls.h" /* generic SSL protos etc */
#include "slist.h"
#include "sendf.h"
-#include "rawstr.h"
+#include "strcase.h"
#include "url.h"
#include "progress.h"
#include "share.h"
+#include "multiif.h"
#include "timeval.h"
#include "curl_md5.h"
#include "warnless.h"
@@ -80,96 +81,49 @@
(data->share->specifier & \
(1<<CURL_LOCK_DATA_SSL_SESSION)))
-static bool safe_strequal(char* str1, char* str2)
-{
- if(str1 && str2)
- /* both pointers point to something then compare them */
- return (0 != Curl_raw_equal(str1, str2)) ? TRUE : FALSE;
- else
- /* if both pointers are NULL then treat them as equal */
- return (!str1 && !str2) ? TRUE : FALSE;
-}
+#define CLONE_STRING(var) \
+ if(source->var) { \
+ dest->var = strdup(source->var); \
+ if(!dest->var) \
+ return FALSE; \
+ } \
+ else \
+ dest->var = NULL;
bool
-Curl_ssl_config_matches(struct ssl_config_data* data,
- struct ssl_config_data* needle)
+Curl_ssl_config_matches(struct ssl_primary_config* data,
+ struct ssl_primary_config* needle)
{
if((data->version == needle->version) &&
(data->verifypeer == needle->verifypeer) &&
(data->verifyhost == needle->verifyhost) &&
- safe_strequal(data->CApath, needle->CApath) &&
- safe_strequal(data->CAfile, needle->CAfile) &&
- safe_strequal(data->clientcert, needle->clientcert) &&
- safe_strequal(data->random_file, needle->random_file) &&
- safe_strequal(data->egdsocket, needle->egdsocket) &&
- safe_strequal(data->cipher_list, needle->cipher_list))
+ Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
+ Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
+ Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
+ Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list))
return TRUE;
return FALSE;
}
bool
-Curl_clone_ssl_config(struct ssl_config_data *source,
- struct ssl_config_data *dest)
+Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
+ struct ssl_primary_config *dest)
{
- dest->sessionid = source->sessionid;
dest->verifyhost = source->verifyhost;
dest->verifypeer = source->verifypeer;
dest->version = source->version;
- if(source->CAfile) {
- dest->CAfile = strdup(source->CAfile);
- if(!dest->CAfile)
- return FALSE;
- }
- else
- dest->CAfile = NULL;
-
- if(source->CApath) {
- dest->CApath = strdup(source->CApath);
- if(!dest->CApath)
- return FALSE;
- }
- else
- dest->CApath = NULL;
-
- if(source->cipher_list) {
- dest->cipher_list = strdup(source->cipher_list);
- if(!dest->cipher_list)
- return FALSE;
- }
- else
- dest->cipher_list = NULL;
-
- if(source->egdsocket) {
- dest->egdsocket = strdup(source->egdsocket);
- if(!dest->egdsocket)
- return FALSE;
- }
- else
- dest->egdsocket = NULL;
-
- if(source->random_file) {
- dest->random_file = strdup(source->random_file);
- if(!dest->random_file)
- return FALSE;
- }
- else
- dest->random_file = NULL;
-
- if(source->clientcert) {
- dest->clientcert = strdup(source->clientcert);
- if(!dest->clientcert)
- return FALSE;
- dest->sessionid = FALSE;
- }
- else
- dest->clientcert = NULL;
-
+ CLONE_STRING(CAfile);
+ CLONE_STRING(CApath);
+ CLONE_STRING(cipher_list);
+ CLONE_STRING(egdsocket);
+ CLONE_STRING(random_file);
+ CLONE_STRING(clientcert);
return TRUE;
}
-void Curl_free_ssl_config(struct ssl_config_data* sslc)
+void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
{
Curl_safefree(sslc->CAfile);
Curl_safefree(sslc->CApath);
@@ -179,77 +133,6 @@ void Curl_free_ssl_config(struct ssl_config_data* sslc)
Curl_safefree(sslc->clientcert);
}
-
-/*
- * Curl_rand() returns a random unsigned integer, 32bit.
- *
- * This non-SSL function is put here only because this file is the only one
- * with knowledge of what the underlying SSL libraries provide in terms of
- * randomizers.
- *
- * NOTE: 'data' may be passed in as NULL when coming from external API without
- * easy handle!
- *
- */
-
-unsigned int Curl_rand(struct Curl_easy *data)
-{
- unsigned int r = 0;
- static unsigned int randseed;
- static bool seeded = FALSE;
-
-#ifdef CURLDEBUG
- char *force_entropy = getenv("CURL_ENTROPY");
- if(force_entropy) {
- if(!seeded) {
- size_t elen = strlen(force_entropy);
- size_t clen = sizeof(randseed);
- size_t min = elen < clen ? elen : clen;
- memcpy((char *)&randseed, force_entropy, min);
- seeded = TRUE;
- }
- else
- randseed++;
- return randseed;
- }
-#endif
-
- /* data may be NULL! */
- if(!Curl_ssl_random(data, (unsigned char *)&r, sizeof(r)))
- return r;
-
- /* If Curl_ssl_random() returns non-zero it couldn't offer randomness and we
- instead perform a "best effort" */
-
-#ifdef RANDOM_FILE
- if(!seeded) {
- /* if there's a random file to read a seed from, use it */
- int fd = open(RANDOM_FILE, O_RDONLY);
- if(fd > -1) {
- /* read random data into the randseed variable */
- ssize_t nread = read(fd, &randseed, sizeof(randseed));
- if(nread == sizeof(randseed))
- seeded = TRUE;
- close(fd);
- }
- }
-#endif
-
- if(!seeded) {
- struct timeval now = curlx_tvnow();
- infof(data, "WARNING: Using weak random seed\n");
- randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec;
- randseed = randseed * 1103515245 + 12345;
- randseed = randseed * 1103515245 + 12345;
- randseed = randseed * 1103515245 + 12345;
- seeded = TRUE;
- }
-
- /* Return an unsigned 32-bit pseudo-random number. */
- r = randseed = randseed * 1103515245 + 12345;
- return (r << 16) | ((r >> 16) & 0xFFFF);
-}
-
int Curl_ssl_backend(void)
{
return (int)CURL_SSL_BACKEND;
@@ -290,19 +173,42 @@ void Curl_ssl_cleanup(void)
static bool ssl_prefs_check(struct Curl_easy *data)
{
/* check for CURLOPT_SSLVERSION invalid parameter value */
- if((data->set.ssl.version < 0)
- || (data->set.ssl.version >= CURL_SSLVERSION_LAST)) {
+ if((data->set.ssl.primary.version < 0)
+ || (data->set.ssl.primary.version >= CURL_SSLVERSION_LAST)) {
failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION");
return FALSE;
}
return TRUE;
}
+static CURLcode
+ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
+{
+ DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]);
+ if(ssl_connection_complete == conn->ssl[sockindex].state &&
+ !conn->proxy_ssl[sockindex].use) {
+#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_NSS) || \
+ defined(USE_GSKIT)
+ conn->proxy_ssl[sockindex] = conn->ssl[sockindex];
+ memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex]));
+#else
+ return CURLE_NOT_BUILT_IN;
+#endif
+ }
+ return CURLE_OK;
+}
+
CURLcode
Curl_ssl_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
+ if(conn->bits.proxy_ssl_connected[sockindex]) {
+ result = ssl_connect_init_proxy(conn, sockindex);
+ if(result)
+ return result;
+ }
+
if(!ssl_prefs_check(conn->data))
return CURLE_SSL_CONNECT_ERROR;
@@ -323,6 +229,11 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
bool *done)
{
CURLcode result;
+ if(conn->bits.proxy_ssl_connected[sockindex]) {
+ result = ssl_connect_init_proxy(conn, sockindex);
+ if(result)
+ return result;
+ }
if(!ssl_prefs_check(conn->data))
return CURLE_SSL_CONNECT_ERROR;
@@ -365,7 +276,8 @@ void Curl_ssl_sessionid_unlock(struct connectdata *conn)
*/
bool Curl_ssl_getsessionid(struct connectdata *conn,
void **ssl_sessionid,
- size_t *idsize) /* set 0 if unknown */
+ size_t *idsize, /* set 0 if unknown */
+ int sockindex)
{
struct curl_ssl_session *check;
struct Curl_easy *data = conn->data;
@@ -373,11 +285,18 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
long *general_age;
bool no_match = TRUE;
+ const bool isProxy = CONNECT_PROXY_SSL();
+ struct ssl_primary_config * const ssl_config = isProxy ?
+ &conn->proxy_ssl_config :
+ &conn->ssl_config;
+ const char * const name = isProxy ? conn->http_proxy.host.name :
+ conn->host.name;
+ int port = isProxy ? (int)conn->port : conn->remote_port;
*ssl_sessionid = NULL;
- DEBUGASSERT(conn->ssl_config.sessionid);
+ DEBUGASSERT(data->set.general_ssl.sessionid);
- if(!conn->ssl_config.sessionid)
+ if(!data->set.general_ssl.sessionid)
/* session ID re-use is disabled */
return TRUE;
@@ -387,20 +306,21 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
else
general_age = &data->state.sessionage;
- for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) {
+ for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
check = &data->state.session[i];
if(!check->sessionid)
/* not session ID means blank entry */
continue;
- if(Curl_raw_equal(conn->host.name, check->name) &&
+ if(strcasecompare(name, check->name) &&
((!conn->bits.conn_to_host && !check->conn_to_host) ||
- (conn->bits.conn_to_host && check->conn_to_host &&
- Curl_raw_equal(conn->conn_to_host.name, check->conn_to_host))) &&
+ (conn->bits.conn_to_host && check->conn_to_host &&
+ strcasecompare(conn->conn_to_host.name, check->conn_to_host))) &&
((!conn->bits.conn_to_port && check->conn_to_port == -1) ||
- (conn->bits.conn_to_port && check->conn_to_port != -1 &&
- conn->conn_to_port == check->conn_to_port)) &&
- (conn->remote_port == check->remote_port) &&
- Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) {
+ (conn->bits.conn_to_port && check->conn_to_port != -1 &&
+ conn->conn_to_port == check->conn_to_port)) &&
+ (port == check->remote_port) &&
+ strcasecompare(conn->handler->scheme, check->scheme) &&
+ Curl_ssl_config_matches(ssl_config, &check->ssl_config)) {
/* yes, we have a session ID! */
(*general_age)++; /* increase general age */
check->age = *general_age; /* set this as used in this age */
@@ -429,7 +349,7 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session)
session->sessionid = NULL;
session->age = 0; /* fresh */
- Curl_free_ssl_config(&session->ssl_config);
+ Curl_free_primary_ssl_config(&session->ssl_config);
Curl_safefree(session->name);
Curl_safefree(session->conn_to_host);
@@ -444,7 +364,7 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
size_t i;
struct Curl_easy *data=conn->data;
- for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) {
+ for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
struct curl_ssl_session *check = &data->state.session[i];
if(check->sessionid == ssl_sessionid) {
@@ -462,7 +382,8 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
*/
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
void *ssl_sessionid,
- size_t idsize)
+ size_t idsize,
+ int sockindex)
{
size_t i;
struct Curl_easy *data=conn->data; /* the mother of all structs */
@@ -472,10 +393,14 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
char *clone_conn_to_host;
int conn_to_port;
long *general_age;
+ const bool isProxy = CONNECT_PROXY_SSL();
+ struct ssl_primary_config * const ssl_config = isProxy ?
+ &conn->proxy_ssl_config :
+ &conn->ssl_config;
- DEBUGASSERT(conn->ssl_config.sessionid);
+ DEBUGASSERT(data->set.general_ssl.sessionid);
- clone_host = strdup(conn->host.name);
+ clone_host = strdup(isProxy ? conn->http_proxy.host.name : conn->host.name);
if(!clone_host)
return CURLE_OUT_OF_MEMORY; /* bail out */
@@ -506,14 +431,14 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
}
/* find an empty slot for us, or find the oldest */
- for(i = 1; (i < data->set.ssl.max_ssl_sessions) &&
+ for(i = 1; (i < data->set.general_ssl.max_ssl_sessions) &&
data->state.session[i].sessionid; i++) {
if(data->state.session[i].age < oldest_age) {
oldest_age = data->state.session[i].age;
store = &data->state.session[i];
}
}
- if(i == data->set.ssl.max_ssl_sessions)
+ if(i == data->set.general_ssl.max_ssl_sessions)
/* cache is full, we must "kill" the oldest entry! */
Curl_ssl_kill_session(store);
else
@@ -529,9 +454,11 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
store->name = clone_host; /* clone host name */
store->conn_to_host = clone_conn_to_host; /* clone connect to host name */
store->conn_to_port = conn_to_port; /* connect to port number */
- store->remote_port = conn->remote_port; /* port number */
+ /* port number */
+ store->remote_port = isProxy ? (int)conn->port : conn->remote_port;
+ store->scheme = conn->handler->scheme;
- if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) {
+ if(!Curl_clone_primary_ssl_config(ssl_config, &store->ssl_config)) {
store->sessionid = NULL; /* let caller free sessionid */
free(clone_host);
free(clone_conn_to_host);
@@ -547,7 +474,7 @@ void Curl_ssl_close_all(struct Curl_easy *data)
size_t i;
/* kill the session ID cache if not shared */
if(data->state.session && !SSLSESSION_SHARED(data)) {
- for(i = 0; i < data->set.ssl.max_ssl_sessions; i++)
+ for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++)
/* the single-killer function handles empty table slots */
Curl_ssl_kill_session(&data->state.session[i]);
@@ -558,6 +485,43 @@ void Curl_ssl_close_all(struct Curl_easy *data)
curlssl_close_all(data);
}
+#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
+ defined(USE_DARWINSSL) || defined(USE_NSS)
+/* This function is for OpenSSL, GnuTLS, darwinssl, and schannel only. */
+int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
+
+ if(!numsocks)
+ return GETSOCK_BLANK;
+
+ if(connssl->connecting_state == ssl_connect_2_writing) {
+ /* write mode */
+ socks[0] = conn->sock[FIRSTSOCKET];
+ return GETSOCK_WRITESOCK(0);
+ }
+ else if(connssl->connecting_state == ssl_connect_2_reading) {
+ /* read mode */
+ socks[0] = conn->sock[FIRSTSOCKET];
+ return GETSOCK_READSOCK(0);
+ }
+
+ return GETSOCK_BLANK;
+}
+#else
+int Curl_ssl_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ (void)conn;
+ (void)socks;
+ (void)numsocks;
+ return GETSOCK_BLANK;
+}
+/* USE_SSLEAY || USE_GNUTLS || USE_SCHANNEL || USE_DARWINSSL || USE_NSS */
+#endif
+
void Curl_ssl_close(struct connectdata *conn, int sockindex)
{
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
@@ -615,7 +579,7 @@ CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount)
return CURLE_OUT_OF_MEMORY;
/* store the info in the SSL section */
- data->set.ssl.max_ssl_sessions = amount;
+ data->set.general_ssl.max_ssl_sessions = amount;
data->state.session = session;
data->state.sessionage = 1; /* this is brand new */
return CURLE_OK;
@@ -691,9 +655,9 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
const char *value,
size_t valuelen)
{
- struct curl_certinfo * ci = &data->info.certs;
- char * output;
- struct curl_slist * nl;
+ struct curl_certinfo *ci = &data->info.certs;
+ char *output;
+ struct curl_slist *nl;
CURLcode result = CURLE_OK;
size_t labellen = strlen(label);
size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */
@@ -736,11 +700,16 @@ CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data,
return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen);
}
-int Curl_ssl_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
+CURLcode Curl_ssl_random(struct Curl_easy *data,
+ unsigned char *entropy,
+ size_t length)
{
- return curlssl_random(data, entropy, length);
+ int rc = curlssl_random(data, entropy, length);
+ if(rc) {
+ failf(data, "PRNG seeding failed");
+ return CURLE_FAILED_INIT; /* possibly weird return code */
+ }
+ return CURLE_OK;
}
/*
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
index a41ecc32..2aabeda2 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -50,13 +50,24 @@
#define ALPN_HTTP_1_1_LENGTH 8
#define ALPN_HTTP_1_1 "http/1.1"
-bool Curl_ssl_config_matches(struct ssl_config_data* data,
- struct ssl_config_data* needle);
-bool Curl_clone_ssl_config(struct ssl_config_data* source,
- struct ssl_config_data* dest);
-void Curl_free_ssl_config(struct ssl_config_data* sslc);
-
-unsigned int Curl_rand(struct Curl_easy *);
+/* set of helper macros for the backends to access the correct fields. For the
+ proxy or for the remote host - to properly support HTTPS proxy */
+
+#define SSL_IS_PROXY() (CURLPROXY_HTTPS == conn->http_proxy.proxytype && \
+ ssl_connection_complete != conn->proxy_ssl[conn->sock[SECONDARYSOCKET] == \
+ CURL_SOCKET_BAD ? FIRSTSOCKET : SECONDARYSOCKET].state)
+#define SSL_SET_OPTION(var) (SSL_IS_PROXY() ? data->set.proxy_ssl.var : \
+ data->set.ssl.var)
+#define SSL_CONN_CONFIG(var) (SSL_IS_PROXY() ? \
+ conn->proxy_ssl_config.var : conn->ssl_config.var)
+
+bool Curl_ssl_config_matches(struct ssl_primary_config* data,
+ struct ssl_primary_config* needle);
+bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
+ struct ssl_primary_config *dest);
+void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc);
+int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
int Curl_ssl_backend(void);
@@ -87,12 +98,12 @@ int Curl_ssl_check_cxn(struct connectdata *conn);
/* Certificate information list handling. */
void Curl_ssl_free_certinfo(struct Curl_easy *data);
-CURLcode Curl_ssl_init_certinfo(struct Curl_easy * data, int num);
-CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy * data, int certnum,
- const char * label, const char * value,
+CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num);
+CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, int certnum,
+ const char *label, const char *value,
size_t valuelen);
-CURLcode Curl_ssl_push_certinfo(struct Curl_easy * data, int certnum,
- const char * label, const char * value);
+CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, int certnum,
+ const char *label, const char *value);
/* Functions to be used by SSL library adaptation functions */
@@ -116,7 +127,8 @@ void Curl_ssl_sessionid_unlock(struct connectdata *conn);
*/
bool Curl_ssl_getsessionid(struct connectdata *conn,
void **ssl_sessionid,
- size_t *idsize); /* set 0 if unknown */
+ size_t *idsize, /* set 0 if unknown */
+ int sockindex);
/* add a new session ID
* Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
* Caller must ensure that it has properly shared ownership of this sessionid
@@ -124,7 +136,8 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
*/
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
void *ssl_sessionid,
- size_t idsize);
+ size_t idsize,
+ int sockindex);
/* Kill a single session ID entry in the cache
* Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
* This will call engine-specific curlssl_session_free function, which must
@@ -140,10 +153,9 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session);
*/
void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid);
-/* get N random bytes into the buffer, return 0 if a find random is filled
- in */
-int Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer,
- size_t length);
+/* get N random bytes into the buffer */
+CURLcode Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer,
+ size_t length);
CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *md5sum, /* output */
diff --git a/lib/x509asn1.c b/lib/x509asn1.c
index e17bcd92..acd98e49 100644
--- a/lib/x509asn1.c
+++ b/lib/x509asn1.c
@@ -27,7 +27,7 @@
#include <curl/curl.h>
#include "urldata.h"
-#include "strequal.h"
+#include "strcase.h"
#include "hostcheck.h"
#include "vtls/vtls.h"
#include "sendf.h"
@@ -40,6 +40,9 @@
#include "curl_memory.h"
#include "memdebug.h"
+/* For overflow checks. */
+#define CURL_SIZE_T_MAX ((size_t)-1)
+
/* ASN.1 OIDs. */
static const char cnOID[] = "2.5.4.3"; /* Common name. */
@@ -105,8 +108,8 @@ static const curl_OID OIDtable[] = {
*/
-const char * Curl_getASN1Element(curl_asn1Element * elem,
- const char * beg, const char * end)
+const char *Curl_getASN1Element(curl_asn1Element *elem,
+ const char *beg, const char *end)
{
unsigned char b;
unsigned long len;
@@ -116,8 +119,8 @@ const char * Curl_getASN1Element(curl_asn1Element * elem,
ending at `end'.
Returns a pointer in source string after the parsed element, or NULL
if an error occurs. */
-
- if(beg >= end || !*beg)
+ if(!beg || !end || beg >= end || !*beg ||
+ (size_t)(end - beg) > CURL_ASN1_MAX)
return (const char *) NULL;
/* Process header byte. */
@@ -152,7 +155,7 @@ const char * Curl_getASN1Element(curl_asn1Element * elem,
elem->end = beg;
return beg + 1;
}
- else if(beg + b > end)
+ else if((unsigned)b > (size_t)(end - beg))
return (const char *) NULL; /* Does not fit in source. */
else {
/* Get long length. */
@@ -163,28 +166,28 @@ const char * Curl_getASN1Element(curl_asn1Element * elem,
len = (len << 8) | (unsigned char) *beg++;
} while(--b);
}
- if((unsigned long) (end - beg) < len)
+ if(len > (size_t)(end - beg))
return (const char *) NULL; /* Element data does not fit in source. */
elem->beg = beg;
elem->end = beg + len;
return elem->end;
}
-static const curl_OID * searchOID(const char * oid)
+static const curl_OID * searchOID(const char *oid)
{
- const curl_OID * op;
+ const curl_OID *op;
/* Search the null terminated OID or OID identifier in local table.
Return the table entry pointer or NULL if not found. */
for(op = OIDtable; op->numoid; op++)
- if(!strcmp(op->numoid, oid) || curl_strequal(op->textoid, oid))
+ if(!strcmp(op->numoid, oid) || strcasecompare(op->textoid, oid))
return op;
return (const curl_OID *) NULL;
}
-static const char * bool2str(const char * beg, const char * end)
+static const char *bool2str(const char *beg, const char *end)
{
/* Convert an ASN.1 Boolean value into its string representation.
Return the dynamically allocated string, or NULL if source is not an
@@ -195,22 +198,24 @@ static const char * bool2str(const char * beg, const char * end)
return strdup(*beg? "TRUE": "FALSE");
}
-static const char * octet2str(const char * beg, const char * end)
+static const char *octet2str(const char *beg, const char *end)
{
size_t n = end - beg;
- char * buf;
+ char *buf = NULL;
/* Convert an ASN.1 octet string to a printable string.
Return the dynamically allocated string, or NULL if an error occurs. */
- buf = malloc(3 * n + 1);
- if(buf)
- for(n = 0; beg < end; n += 3)
- snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++);
+ if(n <= (CURL_SIZE_T_MAX - 1) / 3) {
+ buf = malloc(3 * n + 1);
+ if(buf)
+ for(n = 0; beg < end; n += 3)
+ snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++);
+ }
return buf;
}
-static const char * bit2str(const char * beg, const char * end)
+static const char *bit2str(const char *beg, const char *end)
{
/* Convert an ASN.1 bit string to a printable string.
Return the dynamically allocated string, or NULL if an error occurs. */
@@ -220,7 +225,7 @@ static const char * bit2str(const char * beg, const char * end)
return octet2str(beg, end);
}
-static const char * int2str(const char * beg, const char * end)
+static const char *int2str(const char *beg, const char *end)
{
long val = 0;
size_t n = end - beg;
@@ -246,14 +251,14 @@ static const char * int2str(const char * beg, const char * end)
}
static ssize_t
-utf8asn1str(char * * to, int type, const char * from, const char * end)
+utf8asn1str(char **to, int type, const char *from, const char *end)
{
size_t inlength = end - from;
int size = 1;
size_t outlength;
int charsize;
unsigned int wc;
- char * buf;
+ char *buf;
/* Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the
destination buffer dynamically. The allocation size will normally be too
@@ -282,6 +287,8 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
if(inlength % size)
return -1; /* Length inconsistent with character size. */
+ if(inlength / size > (CURL_SIZE_T_MAX - 1) / 4)
+ return -1; /* Too big. */
buf = malloc(4 * (inlength / size) + 1);
if(!buf)
return -1; /* Not enough memory. */
@@ -335,9 +342,9 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
return outlength;
}
-static const char * string2str(int type, const char * beg, const char * end)
+static const char *string2str(int type, const char *beg, const char *end)
{
- char * buf;
+ char *buf;
/* Convert an ASN.1 String into its UTF-8 string representation.
Return the dynamically allocated string, or NULL if an error occurs. */
@@ -347,7 +354,7 @@ static const char * string2str(int type, const char * beg, const char * end)
return buf;
}
-static int encodeUint(char * buf, int n, unsigned int x)
+static int encodeUint(char *buf, int n, unsigned int x)
{
int i = 0;
unsigned int y = x / 10;
@@ -367,7 +374,7 @@ static int encodeUint(char * buf, int n, unsigned int x)
return i;
}
-static int encodeOID(char * buf, int n, const char * beg, const char * end)
+static int encodeOID(char *buf, int n, const char *beg, const char *end)
{
int i = 0;
unsigned int x;
@@ -406,9 +413,9 @@ static int encodeOID(char * buf, int n, const char * beg, const char * end)
return i;
}
-static const char * OID2str(const char * beg, const char * end, bool symbolic)
+static const char *OID2str(const char *beg, const char *end, bool symbolic)
{
- char * buf = (char *) NULL;
+ char *buf = (char *) NULL;
const curl_OID * op;
int n;
@@ -436,14 +443,14 @@ static const char * OID2str(const char * beg, const char * end, bool symbolic)
return buf;
}
-static const char * GTime2str(const char * beg, const char * end)
+static const char *GTime2str(const char *beg, const char *end)
{
- const char * tzp;
- const char * fracp;
+ const char *tzp;
+ const char *fracp;
char sec1, sec2;
size_t fracl;
size_t tzl;
- const char * sep = "";
+ const char *sep = "";
/* Convert an ASN.1 Generalized time to a printable string.
Return the dynamically allocated string, or NULL if an error occurs. */
@@ -499,11 +506,11 @@ static const char * GTime2str(const char * beg, const char * end)
sep, tzl, tzp);
}
-static const char * UTime2str(const char * beg, const char * end)
+static const char *UTime2str(const char *beg, const char *end)
{
- const char * tzp;
+ const char *tzp;
size_t tzl;
- const char * sec;
+ const char *sec;
/* Convert an ASN.1 UTC time to a printable string.
Return the dynamically allocated string, or NULL if an error occurs. */
@@ -538,7 +545,7 @@ static const char * UTime2str(const char * beg, const char * end)
tzl, tzp);
}
-const char * Curl_ASN1tostr(curl_asn1Element * elem, int type)
+const char *Curl_ASN1tostr(curl_asn1Element *elem, int type)
{
/* Convert an ASN.1 element to a printable string.
Return the dynamically allocated string, or NULL if an error occurs. */
@@ -581,17 +588,17 @@ const char * Curl_ASN1tostr(curl_asn1Element * elem, int type)
return (const char *) NULL; /* Unsupported. */
}
-static ssize_t encodeDN(char * buf, size_t n, curl_asn1Element * dn)
+static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
{
curl_asn1Element rdn;
curl_asn1Element atv;
curl_asn1Element oid;
curl_asn1Element value;
size_t l = 0;
- const char * p1;
- const char * p2;
- const char * p3;
- const char * str;
+ const char *p1;
+ const char *p2;
+ const char *p3;
+ const char *str;
/* ASCII encode distinguished name at `dn' into the `n'-byte buffer at `buf'.
Return the total string length, even if larger than `n'. */
@@ -647,9 +654,9 @@ static ssize_t encodeDN(char * buf, size_t n, curl_asn1Element * dn)
return l;
}
-const char * Curl_DNtostr(curl_asn1Element * dn)
+const char *Curl_DNtostr(curl_asn1Element *dn)
{
- char * buf = (char *) NULL;
+ char *buf = (char *) NULL;
ssize_t n = encodeDN(buf, 0, dn);
/* Convert an ASN.1 distinguished name into a printable string.
@@ -669,12 +676,12 @@ const char * Curl_DNtostr(curl_asn1Element * dn)
* X509 parser.
*/
-void Curl_parseX509(curl_X509certificate * cert,
- const char * beg, const char * end)
+int Curl_parseX509(curl_X509certificate *cert,
+ const char *beg, const char *end)
{
curl_asn1Element elem;
curl_asn1Element tbsCertificate;
- const char * ccp;
+ const char *ccp;
static const char defaultVersion = 0; /* v1. */
/* ASN.1 parse an X509 certificate into structure subfields.
@@ -686,7 +693,8 @@ void Curl_parseX509(curl_X509certificate * cert,
cert->certificate.end = end;
/* Get the sequence content. */
- Curl_getASN1Element(&elem, beg, end);
+ if(!Curl_getASN1Element(&elem, beg, end))
+ return -1; /* Invalid bounds/size. */
beg = elem.beg;
end = elem.end;
@@ -749,9 +757,10 @@ void Curl_parseX509(curl_X509certificate * cert,
}
if(elem.tag == 3)
Curl_getASN1Element(&cert->extensions, elem.beg, elem.end);
+ return 0;
}
-static size_t copySubstring(char * to, const char * from)
+static size_t copySubstring(char *to, const char *from)
{
size_t i;
@@ -768,8 +777,8 @@ static size_t copySubstring(char * to, const char * from)
return i;
}
-static const char * dumpAlgo(curl_asn1Element * param,
- const char * beg, const char * end)
+static const char *dumpAlgo(curl_asn1Element *param,
+ const char *beg, const char *end)
{
curl_asn1Element oid;
@@ -784,10 +793,10 @@ static const char * dumpAlgo(curl_asn1Element * param,
return OID2str(oid.beg, oid.end, TRUE);
}
-static void do_pubkey_field(struct Curl_easy * data, int certnum,
- const char * label, curl_asn1Element * elem)
+static void do_pubkey_field(struct Curl_easy *data, int certnum,
+ const char *label, curl_asn1Element *elem)
{
- const char * output;
+ const char *output;
/* Generate a certificate information record for the public key. */
@@ -801,14 +810,14 @@ static void do_pubkey_field(struct Curl_easy * data, int certnum,
}
}
-static void do_pubkey(struct Curl_easy * data, int certnum,
- const char * algo, curl_asn1Element * param,
- curl_asn1Element * pubkey)
+static void do_pubkey(struct Curl_easy *data, int certnum,
+ const char *algo, curl_asn1Element *param,
+ curl_asn1Element *pubkey)
{
curl_asn1Element elem;
curl_asn1Element pk;
- const char * p;
- const char * q;
+ const char *p;
+ const char *q;
unsigned long len;
unsigned int i;
@@ -817,7 +826,7 @@ static void do_pubkey(struct Curl_easy * data, int certnum,
/* Get the public key (single element). */
Curl_getASN1Element(&pk, pubkey->beg + 1, pubkey->end);
- if(curl_strequal(algo, "rsaEncryption")) {
+ if(strcasecompare(algo, "rsaEncryption")) {
p = Curl_getASN1Element(&elem, pk.beg, pk.end);
/* Compute key length. */
for(q = elem.beg; !*q && q < elem.end; q++)
@@ -842,7 +851,7 @@ static void do_pubkey(struct Curl_easy * data, int certnum,
Curl_getASN1Element(&elem, p, pk.end);
do_pubkey_field(data, certnum, "rsa(e)", &elem);
}
- else if(curl_strequal(algo, "dsa")) {
+ else if(strcasecompare(algo, "dsa")) {
p = Curl_getASN1Element(&elem, param->beg, param->end);
do_pubkey_field(data, certnum, "dsa(p)", &elem);
p = Curl_getASN1Element(&elem, p, param->end);
@@ -851,7 +860,7 @@ static void do_pubkey(struct Curl_easy * data, int certnum,
do_pubkey_field(data, certnum, "dsa(g)", &elem);
do_pubkey_field(data, certnum, "dsa(pub_key)", &pk);
}
- else if(curl_strequal(algo, "dhpublicnumber")) {
+ else if(strcasecompare(algo, "dhpublicnumber")) {
p = Curl_getASN1Element(&elem, param->beg, param->end);
do_pubkey_field(data, certnum, "dh(p)", &elem);
Curl_getASN1Element(&elem, param->beg, param->end);
@@ -859,24 +868,24 @@ static void do_pubkey(struct Curl_easy * data, int certnum,
do_pubkey_field(data, certnum, "dh(pub_key)", &pk);
}
#if 0 /* Patent-encumbered. */
- else if(curl_strequal(algo, "ecPublicKey")) {
+ else if(strcasecompare(algo, "ecPublicKey")) {
/* Left TODO. */
}
#endif
}
-CURLcode Curl_extract_certinfo(struct connectdata * conn,
+CURLcode Curl_extract_certinfo(struct connectdata *conn,
int certnum,
- const char * beg,
- const char * end)
+ const char *beg,
+ const char *end)
{
curl_X509certificate cert;
- struct Curl_easy * data = conn->data;
+ struct Curl_easy *data = conn->data;
curl_asn1Element param;
- const char * ccp;
- char * cp1;
+ const char *ccp;
+ char *cp1;
size_t cl1;
- char * cp2;
+ char *cp2;
CURLcode result;
unsigned long version;
size_t i;
@@ -889,7 +898,8 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
/* Prepare the certificate information for curl_easy_getinfo(). */
/* Extract the certificate ASN.1 elements. */
- Curl_parseX509(&cert, beg, end);
+ if(Curl_parseX509(&cert, beg, end))
+ return CURLE_OUT_OF_MEMORY;
/* Subject. */
ccp = Curl_DNtostr(&cert.subject);
@@ -1029,12 +1039,12 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
#if defined(USE_GSKIT)
-static const char * checkOID(const char * beg, const char * end,
- const char * oid)
+static const char *checkOID(const char *beg, const char *end,
+ const char *oid)
{
curl_asn1Element e;
- const char * ccp;
- const char * p;
+ const char *ccp;
+ const char *p;
bool matched;
/* Check if first ASN.1 element at `beg' is the given OID.
@@ -1053,21 +1063,26 @@ static const char * checkOID(const char * beg, const char * end,
return matched? ccp: (const char *) NULL;
}
-CURLcode Curl_verifyhost(struct connectdata * conn,
- const char * beg, const char * end)
+CURLcode Curl_verifyhost(struct connectdata *conn,
+ const char *beg, const char *end)
{
- struct Curl_easy * data = conn->data;
+ struct Curl_easy *data = conn->data;
curl_X509certificate cert;
curl_asn1Element dn;
curl_asn1Element elem;
curl_asn1Element ext;
curl_asn1Element name;
- const char * p;
- const char * q;
- char * dnsname;
+ const char *p;
+ const char *q;
+ char *dnsname;
int matched = -1;
size_t addrlen = (size_t) -1;
ssize_t len;
+ const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
+ conn->host.name;
+ const char * const dispname = SSL_IS_PROXY()?
+ conn->http_proxy.host.dispname:
+ conn->host.dispname;
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
@@ -1077,20 +1092,19 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
/* Verify that connection server matches info in X509 certificate at
`beg'..`end'. */
- if(!data->set.ssl.verifyhost)
+ if(!SSL_CONN_CONFIG(verifyhost))
return CURLE_OK;
- if(!beg)
+ if(Curl_parseX509(&cert, beg, end))
return CURLE_PEER_FAILED_VERIFICATION;
- Curl_parseX509(&cert, beg, end);
/* Get the server IP address. */
#ifdef ENABLE_IPV6
- if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, conn->host.name, &addr))
+ if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, hostname, &addr))
addrlen = sizeof(struct in6_addr);
else
#endif
- if(Curl_inet_pton(AF_INET, conn->host.name, &addr))
+ if(Curl_inet_pton(AF_INET, hostname, &addr))
addrlen = sizeof(struct in_addr);
/* Process extensions. */
@@ -1113,7 +1127,7 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING,
name.beg, name.end);
if(len > 0 && (size_t)len == strlen(dnsname))
- matched = Curl_cert_hostcheck(dnsname, conn->host.name);
+ matched = Curl_cert_hostcheck(dnsname, hostname);
else
matched = 0;
free(dnsname);
@@ -1131,12 +1145,12 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
switch (matched) {
case 1:
/* an alternative name matched the server hostname */
- infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname);
+ infof(data, "\t subjectAltName: %s matched\n", dispname);
return CURLE_OK;
case 0:
/* an alternative name field existed, but didn't match and then
we MUST fail */
- infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname);
+ infof(data, "\t subjectAltName does not match %s\n", dispname);
return CURLE_PEER_FAILED_VERIFICATION;
}
@@ -1168,14 +1182,14 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
}
if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */
failf(data, "SSL: illegal cert name field");
- else if(Curl_cert_hostcheck((const char *) dnsname, conn->host.name)) {
+ else if(Curl_cert_hostcheck((const char *) dnsname, hostname)) {
infof(data, "\t common name: %s (matched)\n", dnsname);
free(dnsname);
return CURLE_OK;
}
else
failf(data, "SSL: certificate subject name '%s' does not match "
- "target host name '%s'", dnsname, conn->host.dispname);
+ "target host name '%s'", dnsname, dispname);
free(dnsname);
}
diff --git a/lib/x509asn1.h b/lib/x509asn1.h
index 0f2b9304..ce402979 100644
--- a/lib/x509asn1.h
+++ b/lib/x509asn1.h
@@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,6 +34,9 @@
* Constants.
*/
+/* Largest supported ASN.1 structure. */
+#define CURL_ASN1_MAX ((size_t) 0x40000) /* 256K */
+
/* ASN.1 classes. */
#define CURL_ASN1_UNIVERSAL 0
#define CURL_ASN1_APPLICATION 1
@@ -117,16 +120,15 @@ typedef struct {
* Prototypes.
*/
-const char * Curl_getASN1Element(curl_asn1Element * elem,
- const char * beg, const char * end);
-const char * Curl_ASN1tostr(curl_asn1Element * elem, int type);
-const char * Curl_DNtostr(curl_asn1Element * dn);
-void Curl_parseX509(curl_X509certificate * cert,
- const char * beg, const char * end);
-CURLcode Curl_extract_certinfo(struct connectdata * conn, int certnum,
- const char * beg, const char * end);
-CURLcode Curl_verifyhost(struct connectdata * conn,
- const char * beg, const char * end);
-
+const char *Curl_getASN1Element(curl_asn1Element *elem,
+ const char *beg, const char *end);
+const char *Curl_ASN1tostr(curl_asn1Element *elem, int type);
+const char *Curl_DNtostr(curl_asn1Element *dn);
+int Curl_parseX509(curl_X509certificate *cert,
+ const char *beg, const char *end);
+CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum,
+ const char *beg, const char *end);
+CURLcode Curl_verifyhost(struct connectdata *conn,
+ const char *beg, const char *end);
#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_CYASSL or USE_SCHANNEL */
#endif /* HEADER_CURL_X509ASN1_H */
diff --git a/m4/curl-compilers.m4 b/m4/curl-compilers.m4
index 6ecd3237..3219baf6 100644
--- a/m4/curl-compilers.m4
+++ b/m4/curl-compilers.m4
@@ -64,7 +64,7 @@ AC_DEFUN([CURL_CHECK_COMPILER], [
***
*** Whatever settings are present in CFLAGS will be used for this run.
***
-*** If you wish to help the cURL project to better support your compiler
+*** If you wish to help the curl project to better support your compiler
*** you can report this and the required info on the libcurl development
*** mailing list: https://cool.haxx.se/mailman/listinfo/curl-library/
***
diff --git a/m4/curl-functions.m4 b/m4/curl-functions.m4
index ee7a2521..dde7fe2e 100644
--- a/m4/curl-functions.m4
+++ b/m4/curl-functions.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -4739,12 +4739,15 @@ AC_DEFUN([CURL_CHECK_FUNC_POLL], [
tst_allow_poll="unknown"
#
case $host_os in
- darwin[[123456789]].*|darwin10.*|darwin11.*|darwin12.*|interix*)
+ darwin*|interix*)
dnl poll() does not work on these platforms
dnl Interix: "does provide poll(), but the implementing developer must
dnl have been in a bad mood, because poll() only works on the /proc
dnl filesystem here"
+ dnl macOS: poll() first didn't exist, then was broken until fixed in 10.9
+ dnl only to break again in 10.12.
curl_disallow_poll="yes"
+ tst_compi_poll="no"
;;
esac
#
@@ -4803,11 +4806,27 @@ AC_DEFUN([CURL_CHECK_FUNC_POLL], [
AC_LANG_PROGRAM([[
$curl_includes_stdlib
$curl_includes_poll
+ $curl_includes_time
]],[[
+ /* detect the original poll() breakage */
if(0 != poll(0, 0, 10))
exit(1); /* fail */
- else
- exit(0);
+ else {
+ /* detect the 10.12 poll() breakage */
+ struct timeval before, after;
+ int rc;
+ size_t us;
+
+ gettimeofday(&before, NULL);
+ rc = poll(NULL, 0, 500);
+ gettimeofday(&after, NULL);
+
+ us = (after.tv_sec - before.tv_sec) * 1000000 +
+ (after.tv_usec - before.tv_usec);
+
+ if(us < 400000)
+ exit(1);
+ }
]])
],[
AC_MSG_RESULT([yes])
diff --git a/maketgz b/maketgz
index aede6d0f..8d117e68 100755
--- a/maketgz
+++ b/maketgz
@@ -31,6 +31,11 @@ if [ -z "$version" ]; then
exit
fi
+if [ "xonly" = "x$2" ]; then
+ echo "Setup version number only!"
+ only=1
+fi
+
libversion="$version"
# we make curl the same version as libcurl
@@ -40,25 +45,50 @@ major=`echo $libversion |cut -d. -f1 | sed -e "s/[^0-9]//g"`
minor=`echo $libversion |cut -d. -f2 | sed -e "s/[^0-9]//g"`
patch=`echo $libversion |cut -d. -f3 | cut -d- -f1 | sed -e "s/[^0-9]//g"`
+if test -z "$patch"; then
+ echo "invalid version number? needs to be z.y.z"
+ exit
+fi
+
numeric=`perl -e 'printf("%02x%02x%02x\n", '"$major, $minor, $patch);"`
HEADER=include/curl/curlver.h
CHEADER=src/tool_version.h
+PLIST=lib/libcurl.plist
+
+if test -z "$only"; then
+ ext=".dist"
+ # when not setting up version numbers locally
+ for a in $HEADER $CHEADER $PLIST; do
+ cp $a "$a$ext"
+ done
+ HEADER="$HEADER$ext"
+ CHEADER="$CHEADER$ext"
+ PLIST="$PLIST$ext"
+fi
# requires a date command that knows -u for UTC time zone
datestamp=`LC_TIME=C date -u`
# Replace version number in header file:
-sed -e 's/^#define LIBCURL_VERSION .*/#define LIBCURL_VERSION "'$libversion'"/g' \
+sed -i -e 's/^#define LIBCURL_VERSION .*/#define LIBCURL_VERSION "'$libversion'"/g' \
-e 's/^#define LIBCURL_VERSION_NUM .*/#define LIBCURL_VERSION_NUM 0x'$numeric'/g' \
-e 's/^#define LIBCURL_VERSION_MAJOR .*/#define LIBCURL_VERSION_MAJOR '$major'/g' \
-e 's/^#define LIBCURL_VERSION_MINOR .*/#define LIBCURL_VERSION_MINOR '$minor'/g' \
-e 's/^#define LIBCURL_VERSION_PATCH .*/#define LIBCURL_VERSION_PATCH '$patch'/g' \
-e "s/^#define LIBCURL_TIMESTAMP .*/#define LIBCURL_TIMESTAMP \"$datestamp\"/g" \
- $HEADER >$HEADER.dist
+ $HEADER
# Replace version number in header file:
-sed 's/#define CURL_VERSION .*/#define CURL_VERSION "'$curlversion'"/g' $CHEADER >$CHEADER.dist
+sed -i 's/#define CURL_VERSION .*/#define CURL_VERSION "'$curlversion'"/g' $CHEADER
+
+# Replace version number in plist file:
+sed -i "s/7\.12\.3/$libversion/g" $PLIST
+
+if test -n "$only"; then
+ # done!
+ exit;
+fi
# Generate VC7, VC8, VC9, VC10, VC11, VC12 and VC14 versions from the VC6
# Makefile versions
@@ -68,10 +98,6 @@ for ver in vc7 vc8 vc9 vc10 vc11 vc12 vc14; do
mv lib/Makefile.$ver lib/Makefile.$ver.dist
done
-# Replace version number in plist file:
-PLIST=lib/libcurl.plist
-sed "s/7\.12\.3/$libversion/g" $PLIST > $PLIST.dist
-
echo "curl version $curlversion"
echo "libcurl version $libversion"
echo "libcurl numerical $numeric"
@@ -115,16 +141,7 @@ fi
############################################################################
#
-# Make sure we have updated HTML versions of all man pages:
-#
-echo "make html"
-make -s html
-
-# And the PDF versions
-echo "make pdf"
-make -s pdf
-
-# And the IDE files
+# Update the IDE files
echo "make vc-ide"
make -s vc-ide
diff --git a/packages/AIX/RPM/README b/packages/AIX/RPM/README
index 790beb80..51615ad4 100644
--- a/packages/AIX/RPM/README
+++ b/packages/AIX/RPM/README
@@ -29,5 +29,5 @@ Default is to build with ssl support.
Lastly, the spec file expects the Curl source distribution file to be
in .tar.bz2 format.
-The nifty cURL header of this README is a ripoff of the vms/readme file.
+The nifty curl header of this README is a ripoff of the vms/readme file.
diff --git a/packages/DOS/common.dj b/packages/DOS/common.dj
index 85b611c4..e069ce68 100644
--- a/packages/DOS/common.dj
+++ b/packages/DOS/common.dj
@@ -1,7 +1,7 @@
#
# Common defines for curl (djgpp/Watt-32)
#
-# Assumes you've unpacked cURL with long-file names
+# Assumes you've unpacked curl with long-file names
# I.e use "set LFN=y" before untaring on Win9x/XP.
# Requires sed, yacc, rm and the usual stuff.
#
diff --git a/packages/OS400/README.OS400 b/packages/OS400/README.OS400
index 24cf39e6..e709f40d 100644
--- a/packages/OS400/README.OS400
+++ b/packages/OS400/README.OS400
@@ -76,16 +76,16 @@ options:
CURLOPT_DNS_SERVERS
CURLOPT_EGDSOCKET
CURLOPT_ENCODING
+ CURLOPT_FTPPORT
CURLOPT_FTP_ACCOUNT
CURLOPT_FTP_ALTERNATIVE_TO_USER
- CURLOPT_FTPPORT
CURLOPT_INTERFACE
CURLOPT_ISSUERCERT
CURLOPT_KEYPASSWD
CURLOPT_KRBLEVEL
CURLOPT_LOGIN_OPTIONS
- CURLOPT_MAIL_FROM
CURLOPT_MAIL_AUTH
+ CURLOPT_MAIL_FROM
CURLOPT_NETRC_FILE
CURLOPT_NOPROXY
CURLOPT_PASSWORD
@@ -94,7 +94,19 @@ options:
CURLOPT_PROXYPASSWORD
CURLOPT_PROXYUSERNAME
CURLOPT_PROXYUSERPWD
+ CURLOPT_PROXY_CAINFO
+ CURLOPT_PROXY_CAPATH
+ CURLOPT_PROXY_CRLFILE
+ CURLOPT_PROXY_KEYPASSWD
CURLOPT_PROXY_SERVICE_NAME
+ CURLOPT_PROXY_SSLCERT
+ CURLOPT_PROXY_SSLCERTTYPE
+ CURLOPT_PROXY_SSLKEY
+ CURLOPT_PROXY_SSLKEYTYPE
+ CURLOPT_PROXY_SSL_CIPHER_LIST
+ CURLOPT_PROXY_TLSAUTH_PASSWORD
+ CURLOPT_PROXY_TLSAUTH_TYPE
+ CURLOPT_PROXY_TLSAUTH_USERNAME
CURLOPT_RANDOM_FILE
CURLOPT_RANGE
CURLOPT_REFERER
@@ -103,16 +115,17 @@ options:
CURLOPT_RTSP_TRANSPORT
CURLOPT_SERVICE_NAME
CURLOPT_SOCKS5_GSSAPI_SERVICE
+ CURLOPT_SOCKS_PROXY
CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
CURLOPT_SSH_KNOWNHOSTS
CURLOPT_SSH_PRIVATE_KEYFILE
CURLOPT_SSH_PUBLIC_KEYFILE
CURLOPT_SSLCERT
CURLOPT_SSLCERTTYPE
- CURLOPT_SSL_CIPHER_LIST
CURLOPT_SSLENGINE
CURLOPT_SSLKEY
CURLOPT_SSLKEYTYPE
+ CURLOPT_SSL_CIPHER_LIST
CURLOPT_TLSAUTH_PASSWORD
CURLOPT_TLSAUTH_TYPE
CURLOPT_TLSAUTH_USERNAME
@@ -160,6 +173,7 @@ use:
CURLINFO_PRIMARY_IP
CURLINFO_RTSP_SESSION_ID
CURLINFO_LOCAL_IP
+ CURLINFO_SCHEME
Likewise, the following options are followed by a struct curl_slist * * and a
CCSID.
CURLINFO_SSL_ENGINES
diff --git a/packages/OS400/ccsidcurl.c b/packages/OS400/ccsidcurl.c
index 3b08bef7..60824422 100644
--- a/packages/OS400/ccsidcurl.c
+++ b/packages/OS400/ccsidcurl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -615,7 +615,7 @@ curl_easy_getinfo_ccsid(CURL * curl, CURLINFO info, ...)
struct curl_certinfo * cipf;
struct curl_certinfo * cipt;
- /* WARNING: unlike curl_easy_get_info(), the strings returned by this
+ /* WARNING: unlike curl_easy_getinfo(), the strings returned by this
procedure have to be free'ed. */
data = (struct Curl_easy *) curl;
@@ -1147,16 +1147,16 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
case CURLOPT_DNS_SERVERS:
case CURLOPT_EGDSOCKET:
case CURLOPT_ENCODING:
+ case CURLOPT_FTPPORT:
case CURLOPT_FTP_ACCOUNT:
case CURLOPT_FTP_ALTERNATIVE_TO_USER:
- case CURLOPT_FTPPORT:
case CURLOPT_INTERFACE:
case CURLOPT_ISSUERCERT:
case CURLOPT_KEYPASSWD:
case CURLOPT_KRBLEVEL:
case CURLOPT_LOGIN_OPTIONS:
- case CURLOPT_MAIL_FROM:
case CURLOPT_MAIL_AUTH:
+ case CURLOPT_MAIL_FROM:
case CURLOPT_NETRC_FILE:
case CURLOPT_NOPROXY:
case CURLOPT_PASSWORD:
@@ -1165,7 +1165,19 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
case CURLOPT_PROXYPASSWORD:
case CURLOPT_PROXYUSERNAME:
case CURLOPT_PROXYUSERPWD:
+ case CURLOPT_PROXY_CAINFO:
+ case CURLOPT_PROXY_CAPATH:
+ case CURLOPT_PROXY_CRLFILE:
+ case CURLOPT_PROXY_KEYPASSWD:
case CURLOPT_PROXY_SERVICE_NAME:
+ case CURLOPT_PROXY_SSLCERT:
+ case CURLOPT_PROXY_SSLCERTTYPE:
+ case CURLOPT_PROXY_SSLKEY:
+ case CURLOPT_PROXY_SSLKEYTYPE:
+ case CURLOPT_PROXY_SSL_CIPHER_LIST:
+ case CURLOPT_PROXY_TLSAUTH_PASSWORD:
+ case CURLOPT_PROXY_TLSAUTH_TYPE:
+ case CURLOPT_PROXY_TLSAUTH_USERNAME:
case CURLOPT_RANDOM_FILE:
case CURLOPT_RANGE:
case CURLOPT_REFERER:
@@ -1174,16 +1186,17 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
case CURLOPT_RTSP_TRANSPORT:
case CURLOPT_SERVICE_NAME:
case CURLOPT_SOCKS5_GSSAPI_SERVICE:
+ case CURLOPT_SOCKS_PROXY:
case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
case CURLOPT_SSH_KNOWNHOSTS:
case CURLOPT_SSH_PRIVATE_KEYFILE:
case CURLOPT_SSH_PUBLIC_KEYFILE:
case CURLOPT_SSLCERT:
case CURLOPT_SSLCERTTYPE:
- case CURLOPT_SSL_CIPHER_LIST:
case CURLOPT_SSLENGINE:
case CURLOPT_SSLKEY:
case CURLOPT_SSLKEYTYPE:
+ case CURLOPT_SSL_CIPHER_LIST:
case CURLOPT_TLSAUTH_PASSWORD:
case CURLOPT_TLSAUTH_TYPE:
case CURLOPT_TLSAUTH_USERNAME:
diff --git a/packages/OS400/curl.inc.in b/packages/OS400/curl.inc.in
index 1e8a93dd..c0b0330a 100644
--- a/packages/OS400/curl.inc.in
+++ b/packages/OS400/curl.inc.in
@@ -258,6 +258,8 @@
d c 5
d CURL_SSLVERSION_TLSv1_2...
d c 6
+ d CURL_SSLVERSION_TLSv1_3...
+ d c 7
*
d CURL_TLSAUTH_NONE...
d c 0
@@ -369,6 +371,8 @@
d c 6
d CURLE_COULDNT_CONNECT...
d c 7
+ d CURLE_WEIRD_SERVER_REPLY...
+ d c 8
d CURLE_FTP_WEIRD_SERVER_REPLY...
d c 8
d CURLE_REMOTE_ACCESS_DENIED...
@@ -653,6 +657,8 @@
d c 0
d CURLPROXY_HTTP_1_0...
d c 1
+ d CURLPROXY_HTTPS...
+ d c 2
d CURLPROXY_SOCKS4...
d c 4
d CURLPROXY_SOCKS5...
@@ -1252,6 +1258,44 @@
d c 10243
d CURLOPT_TCP_FASTOPEN...
d c 00244
+ d CURLOPT_KEEP_SENDING_ON_ERROR...
+ d c 00245
+ d CURLOPT_PROXY_CAINFO...
+ d c 10246
+ d CURLOPT_PROXY_CAPATH...
+ d c 10247
+ d CURLOPT_PROXY_SSL_VERIFYPEER...
+ d c 00248
+ d CURLOPT_PROXY_SSL_VERIFYHOST...
+ d c 00249
+ d CURLOPT_PROXY_SSLVERSION...
+ d c 00250
+ d CURLOPT_PROXY_TLSAUTH_USERNAME...
+ d c 10251
+ d CURLOPT_PROXY_TLSAUTH_PASSWORD...
+ d c 10252
+ d CURLOPT_PROXY_TLSAUTH_TYPE...
+ d c 10253
+ d CURLOPT_PROXY_SSLCERT...
+ d c 10254
+ d CURLOPT_PROXY_SSLCERTTYPE...
+ d c 10255
+ d CURLOPT_PROXY_SSLKEY...
+ d c 10256
+ d CURLOPT_PROXY_SSLKEYTYPE...
+ d c 10257
+ d CURLOPT_PROXY_KEYPASSWD...
+ d c 10258
+ d CURLOPT_PROXY_SSL_CIPHER_LIST...
+ d c 10259
+ d CURLOPT_PROXY_CRLFILE...
+ d c 10260
+ d CURLOPT_PROXY_SSL_OPTIONS...
+ d c 00261
+ d CURLOPT_SOCKS_PROXY...
+ d c 10262
+ d CURLOPT_SOCKS_PROXYTYPE...
+ d c 00263
*
/if not defined(CURL_NO_OLDIES)
d CURLOPT_FILE c 10001
@@ -1438,6 +1482,12 @@
d c X'0040002D'
d CURLINFO_HTTP_VERSION... CURLINFO_LONG + 46
d c X'0020002E'
+ d CURLINFO_PROXY_SSL_VERIFYRESULT... CURLINFO_LONG + 47
+ d c X'0020002F'
+ d CURLINFO_PROTOCOL... CURLINFO_LONG + 48
+ d c X'00200030'
+ d CURLINFO_SCHEME... CURLINFO_STRING + 49
+ d c X'00100031'
*
d CURLINFO_HTTP_CODE... Old ...RESPONSE_CODE
d c X'00200002'
diff --git a/packages/Symbian/group/curl.mmp b/packages/Symbian/group/curl.mmp
index 28498ce7..4b304a3d 100644
--- a/packages/Symbian/group/curl.mmp
+++ b/packages/Symbian/group/curl.mmp
@@ -1,5 +1,5 @@
//
-// cURL network retrieval client
+// curl network retrieval client
//
TARGET curl.exe
@@ -49,7 +49,7 @@ SOURCE \
SOURCEPATH ../../../lib
SOURCE \
- rawstr.c nonblock.c
+ strcase.c nonblock.c
USERINCLUDE ../../../src ../../../lib ../../../include/curl
diff --git a/packages/Symbian/group/libcurl.mmp b/packages/Symbian/group/libcurl.mmp
index f74b19b5..6388bbd7 100644
--- a/packages/Symbian/group/libcurl.mmp
+++ b/packages/Symbian/group/libcurl.mmp
@@ -1,5 +1,5 @@
//
-// libcurl.dll cURL network retrieval client library
+// libcurl.dll curl network retrieval client library
//
// Build-time options (uncomment these to enable)
@@ -31,7 +31,7 @@ SOURCE \
http_negotiate.c inet_pton.c strtoofft.c strerror.c amigaos.c \
hostasyn.c hostip4.c hostip6.c hostsyn.c inet_ntop.c parsedate.c \
select.c vtls/gtls.c vtls/vtls.c tftp.c splay.c strdup.c socks.c \
- ssh.c vtls/nss.c rawstr.c curl_addrinfo.c socks_gssapi.c \
+ ssh.c vtls/nss.c strcase.c curl_addrinfo.c socks_gssapi.c \
socks_sspi.c curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c \
pop3.c smtp.c pingpong.c rtsp.c curl_threads.c warnless.c hmac.c \
vtls/polarssl.c curl_rtmp.c openldap.c curl_gethostname.c gopher.c \
diff --git a/packages/Win32/cygwin/README b/packages/Win32/cygwin/README
index a0811de7..60bb5e10 100644
--- a/packages/Win32/cygwin/README
+++ b/packages/Win32/cygwin/README
@@ -12,7 +12,7 @@ Dependencies:
- Cygwin
- OpenSSL 0.9.6b-2+ (*)
- (*) cURL can be built without SSL support, see below for details
+ (*) curl can be built without SSL support, see below for details
Canonical Homepage and Downloads:
@@ -41,7 +41,7 @@ Build Instructions (to recompile from the cygwin source tarball):
(**) LibTool 1.4.2 had a bug related to cygwin's use of ".exe" extensions,
such that "make install" blew up at curl.exe. See this URL for details:
http://mail.gnu.org/pipermail/libtool/2001-September/005549.html
- The copy of ltmain.sh that is distributed with cURL includes this patch.
+ The copy of ltmain.sh that is distributed with curl includes this patch.
As of curl 7.9.1, the official source compiles (under Cygwin) and tests
100% cleanly OOTB (Out Of The Box)
@@ -100,9 +100,9 @@ Packaging Instructions:
requires: cygwin openssl
@ curl-devel
- sdesc: "(lib)cURL headers, static libraries, developer docs and samples"
+ sdesc: "(lib)curl headers, static libraries, developer docs and samples"
ldesc: "curl-devel is the developer-oriented (non-run-time) parts
- of the cURL package. It includes header files, static libraries,
+ of the curl package. It includes header files, static libraries,
example source code snippets, and the libcurl man pages."
category: Web Libs Devel
requires: cygwin openssl curl
@@ -110,5 +110,5 @@ Packaging Instructions:
Cygwin port maintained by:
Kevin Roth <kproth @ users . sourceforge . net>
- Questions about cURL should be directed to curl-users@cool.haxx.se.
+ Questions about curl should be directed to curl-users@cool.haxx.se.
Questions about this cygwin package go to cygwin@cygwin.com.
diff --git a/packages/vms/curlmsg.h b/packages/vms/curlmsg.h
index 2cb32ec1..424a382f 100644
--- a/packages/vms/curlmsg.h
+++ b/packages/vms/curlmsg.h
@@ -57,7 +57,8 @@
#define CURL_COULDNT_RESOLVE_PROXY 251756594
#define CURL_COULDNT_RESOLVE_HOST 251756602
#define CURL_COULDNT_CONNECT 251756610
-#define CURL_FTP_WEIRD_SERVER_REPLY 251756618
+#define CURL_WEIRD_SERVER_REPLY 251756618
+#define CURL_FTP_WEIRD_SERVER_REPLY CURL_WEIRD_SERVER_REPLY
#define CURL_FTP_ACCESS_DENIED 251756626
#define CURL_OBSOLETE10 251756634
#define CURL_FTP_WEIRD_PASS_REPLY 251756642
diff --git a/packages/vms/curlmsg.msg b/packages/vms/curlmsg.msg
index 7fd44835..492657c0 100644
--- a/packages/vms/curlmsg.msg
+++ b/packages/vms/curlmsg.msg
@@ -30,7 +30,7 @@ OBSOLETE4 <obsolete error code>
COULDNT_RESOLVE_PROXY <could not resolve proxy>
COULDNT_RESOLVE_HOST <could not resolve host>
COULDNT_CONNECT <could not connect>
-FTP_WEIRD_SERVER_REPLY <FTP weird server reply>
+WEIRD_SERVER_REPLY <weird server reply>
FTP_ACCESS_DENIED <FTP access denied>
OBSOLETE10 <obsolete error code>
FTP_WEIRD_PASS_REPLY <FTP weird PASS reply>
diff --git a/packages/vms/curlmsg.sdl b/packages/vms/curlmsg.sdl
index e192c075..db5baad6 100644
--- a/packages/vms/curlmsg.sdl
+++ b/packages/vms/curlmsg.sdl
@@ -34,6 +34,7 @@
,"COULDNT_RESOLVE_PROXY" EQUALS %X0F018032 PREFIX "CURL" TAG ""
,"COULDNT_RESOLVE_HOST" EQUALS %X0F01803A PREFIX "CURL" TAG ""
,"COULDNT_CONNECT" EQUALS %X0F018042 PREFIX "CURL" TAG ""
+ ,"WEIRD_SERVER_REPLY" EQUALS %X0F01804A PREFIX "CURL" TAG ""
,"FTP_WEIRD_SERVER_REPLY" EQUALS %X0F01804A PREFIX "CURL" TAG ""
,"FTP_ACCESS_DENIED" EQUALS %X0F018052 PREFIX "CURL" TAG ""
,"OBSOLETE10" EQUALS %X0F01805A PREFIX "CURL" TAG ""
diff --git a/packages/vms/curlmsg_vms.h b/packages/vms/curlmsg_vms.h
index 3aef9cfe..b7ff7a0c 100644
--- a/packages/vms/curlmsg_vms.h
+++ b/packages/vms/curlmsg_vms.h
@@ -59,7 +59,7 @@ static const long vms_cond[] =
CURL_COULDNT_RESOLVE_PROXY,
CURL_COULDNT_RESOLVE_HOST,
CURL_COULDNT_CONNECT,
- CURL_FTP_WEIRD_SERVER_REPLY,
+ CURL_WEIRD_SERVER_REPLY,
CURL_FTP_ACCESS_DENIED,
CURL_OBSOLETE10,
CURL_FTP_WEIRD_PASS_REPLY,
diff --git a/packages/vms/gnv_link_curl.com b/packages/vms/gnv_link_curl.com
index b7e60838..add4be95 100644
--- a/packages/vms/gnv_link_curl.com
+++ b/packages/vms/gnv_link_curl.com
@@ -416,7 +416,7 @@ $ link'ldebug'/exe=[.src]curl.exe/dsf=[.src]curl.dsf -
[.src]curl-tool_urlglob.o, [.src]curl-tool_util.o, -
[.src]curl-tool_vms.o, [.src]curl-tool_writeenv.o, -
[.src]curl-tool_writeout.o, [.src]curl-tool_xattr.o, -
- [.src]curl-strtoofft.o, [.src]curl-strdup.o, [.src]curl-rawstr.o, -
+ [.src]curl-strtoofft.o, [.src]curl-strdup.o, [.src]curl-strcase.o, -
[.src]curl-nonblock.o, gnv_packages_vms:curlmsg.obj,-
sys$input:/opt
gnv$libcurl/share
@@ -428,7 +428,7 @@ $ curl_dsf = "[.src]curl.dsf"
$ curl_main = "[.packages.vms.''arch_name']tool_main.obj"
$ curl_src = "[.packages.vms.''arch_name']curlsrc.olb"
$ curl_lib = "[.packages.vms.''arch_name']curllib.olb"
-$ rawstr = "rawstr"
+$ strcase = "strcase"
$ nonblock = "nonblock"
$ warnless = "warnless"
$!
@@ -436,7 +436,7 @@ $! Extended parse style requires special quoting
$!
$ if (arch_name .nes. "VAX") .and. (parse_style .eqs. "EXTENDED")
$ then
-$ rawstr = """rawstr"""
+$ strcase = """strcase"""
$ nonblock = """nonblock"""
$ warnless = """warnless"""
$ endif
@@ -446,7 +446,7 @@ $ define/user gnv$libcurl 'gnv_libcurl_share'
$ link'ldebug'/exe='curl_exe'/dsf='curl_dsf' -
'curl_main','curl_src'/lib, -
'curl_lib'/library/include=-
- ('rawstr','nonblock','warnless'),-
+ ('strcase','nonblock','warnless'),-
gnv_packages_vms:curlmsg.obj,-
sys$input:/opt
gnv$libcurl/share
diff --git a/packages/vms/readme b/packages/vms/readme
index 1b245805..5f116a55 100644
--- a/packages/vms/readme
+++ b/packages/vms/readme
@@ -83,13 +83,13 @@ curl_startup.com A procedure run at VMS startup to install the
libcurl shared image and to set up the needed
logical names.
-curlmsg.h C header defining cURL status code macros.
+curlmsg.h C header defining curl status code macros.
curlmsg.msg Error message source for curlmsg.h and curlmsg.sdl.
-curlmsg.sdl SDL source defining cURL status code constants.
+curlmsg.sdl SDL source defining curl status code constants.
-curlmsg_vms.h Mapping of cURL status codes to VMS-form codes.
+curlmsg_vms.h Mapping of curl status codes to VMS-form codes.
generate_config_vms_h_curl.com
DCL procedure to generate the curl specific
@@ -115,9 +115,9 @@ gnv_link_curl.com Links the libcurl shared image and then links a curl
macro32_exactcase.patch The patch file needed to modify VAX Macro32 to be
case sensitive and case preserving.
-Makefile.am cURL kit file list for this directory.
+Makefile.am curl kit file list for this directory.
-Makefile.in cURL kit makefile source for this directory.
+Makefile.in curl kit makefile source for this directory.
make_gnv_curl_install.sh
Script to do a make install using GNV after running
diff --git a/packages/vms/vms_eco_level.h b/packages/vms/vms_eco_level.h
index 43534077..354875bb 100644
--- a/packages/vms/vms_eco_level.h
+++ b/packages/vms/vms_eco_level.h
@@ -19,7 +19,7 @@
*/
/* This file should be incremented for each ECO that is kit */
-/* for a specific cURL x.y-z release. */
+/* for a specific curl x.y-z release. */
/* When any part of x.y-z is incremented, the ECO should be set back to 0 */
#ifndef _VMS_ECO_LEVEL_H
diff --git a/projects/README b/projects/README
index f6314379..fee73049 100644
--- a/projects/README
+++ b/projects/README
@@ -4,7 +4,7 @@ Building via IDE Project Files
This document describes how to compile, build and install curl and libcurl
from sources using an IDE based development tool such as Visual Studio.
- Project files are currently available for Visual C++ v6.0 to v12.0. The
+ Project files are currently available for Visual C++ v6.0 to v14.0. The
following directory structure has been used to cater for this:
somedirectory\
@@ -160,17 +160,3 @@ Legacy Windows and SSL
support the legacy handshakes and algorithms used by those versions. If
you will be using curl in one of those earlier versions of Windows you
should choose another SSL backend such as OpenSSL.
-
-TODO
-====
-
- These project files are a recent addition to the curl source code and as such
- are not 100% complete. This is a list of things that are still todo:
-
- * Support zlib
- * Use of static runtime libraries
- * Add the Test Suite components
- * Support for other development IDEs
- * Add PATH environment variables for third-party DLLs
-
- Any additional help would be appreciated ;-) \ No newline at end of file
diff --git a/projects/generate.bat b/projects/generate.bat
index 8209a5dd..fbe3a923 100644
--- a/projects/generate.bat
+++ b/projects/generate.bat
@@ -264,19 +264,18 @@ rem
for /f "delims=" %%r in ('dir /b ..\src\*.rc') do call :element %1 src "%%r" %3
) else if "!var!" == "CURL_SRC_X_C_FILES" (
call :element %1 lib "strtoofft.c" %3
- call :element %1 lib "rawstr.c" %3
call :element %1 lib "nonblock.c" %3
call :element %1 lib "warnless.c" %3
) else if "!var!" == "CURL_SRC_X_H_FILES" (
call :element %1 lib "config-win32.h" %3
call :element %1 lib "curl_setup.h" %3
call :element %1 lib "strtoofft.h" %3
- call :element %1 lib "rawstr.h" %3
call :element %1 lib "nonblock.h" %3
call :element %1 lib "warnless.h" %3
) else if "!var!" == "CURL_LIB_C_FILES" (
for /f "delims=" %%c in ('dir /b ..\lib\*.c') do call :element %1 lib "%%c" %3
) else if "!var!" == "CURL_LIB_H_FILES" (
+ for /f "delims=" %%h in ('dir /b ..\include\curl\*.h') do call :element %1 include\curl "%%h" %3
for /f "delims=" %%h in ('dir /b ..\lib\*.h') do call :element %1 lib "%%h" %3
) else if "!var!" == "CURL_LIB_RC_FILES" (
for /f "delims=" %%r in ('dir /b ..\lib\*.rc') do call :element %1 lib "%%r" %3
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cfcefb39..9bbeb605 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -49,9 +49,9 @@ add_executable(
${CURL_FILES}
)
-source_group("cURLX source files" FILES ${CURLX_CFILES})
-source_group("cURL source files" FILES ${CURL_CFILES})
-source_group("cURL header files" FILES ${CURL_HFILES})
+source_group("curlX source files" FILES ${CURLX_CFILES})
+source_group("curl source files" FILES ${CURL_CFILES})
+source_group("curl header files" FILES ${CURL_HFILES})
include_directories(
${CURL_SOURCE_DIR}/lib # To be able to reach "curl_setup_once.h"
@@ -61,7 +61,7 @@ include_directories(
${CURL_SOURCE_DIR}/src # To be able to reach "tool_hugehelp.h"
)
-#Build cURL executable
+#Build curl executable
target_link_libraries( ${EXE_NAME} libcurl ${CURL_LIBS})
################################################################################
diff --git a/src/Makefile.Watcom b/src/Makefile.Watcom
index f1ddc29f..25cd3bf8 100644
--- a/src/Makefile.Watcom
+++ b/src/Makefile.Watcom
@@ -22,7 +22,7 @@
#***************************************************************************
#
-# Watcom / OpenWatcom / Win32 makefile for cURL.
+# Watcom / OpenWatcom / Win32 makefile for curl.
#
.ERASE
@@ -156,7 +156,7 @@ RESOURCE = $(OBJ_DIR)/curl.res
DIRS = $(OBJ_DIR)
all: tool_hugehelp.c $(DIRS) $(TARGETS) .SYMBOLIC
- @echo Welcome to cURL
+ @echo Welcome to curl
clean: .SYMBOLIC
-rm -f $(OBJS)
diff --git a/src/Makefile.inc b/src/Makefile.inc
index 1aa153c8..2196ffa3 100644
--- a/src/Makefile.inc
+++ b/src/Makefile.inc
@@ -11,14 +11,12 @@
# the official API, but we re-use the code here to avoid duplication.
CURLX_CFILES = \
../lib/strtoofft.c \
- ../lib/rawstr.c \
../lib/nonblock.c \
../lib/warnless.c
CURLX_HFILES = \
../lib/curl_setup.h \
../lib/strtoofft.h \
- ../lib/rawstr.h \
../lib/nonblock.h \
../lib/warnless.h
diff --git a/src/Makefile.netware b/src/Makefile.netware
index 3e4f6546..a927da59 100644
--- a/src/Makefile.netware
+++ b/src/Makefile.netware
@@ -102,7 +102,7 @@ endif
TARGET = curl
VERSION = $(LIBCURL_VERSION)
COPYR = Copyright (C) $(LIBCURL_COPYRIGHT_STR)
-DESCR = cURL $(LIBCURL_VERSION_STR) ($(LIBARCH)) - https://curl.haxx.se
+DESCR = curl $(LIBCURL_VERSION_STR) ($(LIBARCH)) - https://curl.haxx.se
MTSAFE = YES
STACK = 64000
SCREEN = $(TARGET) commandline utility
diff --git a/src/Makefile.vc6 b/src/Makefile.vc6
index ff82a4df..85828ced 100644
--- a/src/Makefile.vc6
+++ b/src/Makefile.vc6
@@ -142,7 +142,7 @@ CFLAGS = $(CFLAGS) /DUSE_WINDOWS_SSPI /I$(WINDOWS_SDK_PATH)\include
RELEASE_OBJS= \
nonblockr.obj \
- rawstrr.obj \
+ strcaser.obj \
strtoofftr.obj \
warnless.obj \
slist_wc.obj \
@@ -188,7 +188,7 @@ RELEASE_OBJS= \
DEBUG_OBJS= \
nonblockd.obj \
- rawstrd.obj \
+ strcased.obj \
strtoofftd.obj \
warnlessd.obj \
slist_wcd.obj \
@@ -363,8 +363,8 @@ debug: $(DEBUG_OBJS)
## Release
nonblockr.obj: ../lib/nonblock.c
$(CCR) $(CFLAGS) /Fo"$@" ../lib/nonblock.c
-rawstrr.obj: ../lib/rawstr.c
- $(CCR) $(CFLAGS) /Fo"$@" ../lib/rawstr.c
+strcaser.obj: ../lib/strcase.c
+ $(CCR) $(CFLAGS) /Fo"$@" ../lib/strcase.c
strtoofftr.obj: ../lib/strtoofft.c
$(CCR) $(CFLAGS) /Fo"$@" ../lib/strtoofft.c
warnless.obj: ../lib/warnless.c
@@ -453,8 +453,8 @@ curlr.res : curl.rc
## Debug
nonblockd.obj: ../lib/nonblock.c
$(CCD) $(CFLAGS) /Fo"$@" ../lib/nonblock.c
-rawstrd.obj: ../lib/rawstr.c
- $(CCD) $(CFLAGS) /Fo"$@" ../lib/rawstr.c
+strcased.obj: ../lib/strcase.c
+ $(CCD) $(CFLAGS) /Fo"$@" ../lib/strcase.c
strtoofftd.obj: ../lib/strtoofft.c
$(CCD) $(CFLAGS) /Fo"$@" ../lib/strtoofft.c
warnlessd.obj: ../lib/warnless.c
diff --git a/src/curl.rc b/src/curl.rc
index 30ae4449..3a2c3a0f 100644
--- a/src/curl.rc
+++ b/src/curl.rc
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,12 +44,12 @@ BEGIN
BEGIN
BLOCK "040904b0"
BEGIN
- VALUE "CompanyName", "cURL, https://curl.haxx.se/\0"
- VALUE "FileDescription", "The cURL executable\0"
+ VALUE "CompanyName", "curl, https://curl.haxx.se/\0"
+ VALUE "FileDescription", "The curl executable\0"
VALUE "FileVersion", CURL_VERSION "\0"
VALUE "InternalName", "curl\0"
VALUE "OriginalFilename", "curl.exe\0"
- VALUE "ProductName", "The cURL executable\0"
+ VALUE "ProductName", "The curl executable\0"
VALUE "ProductVersion", CURL_VERSION "\0"
VALUE "LegalCopyright", "© " CURL_COPYRIGHT "\0"
VALUE "License", "https://curl.haxx.se/docs/copyright.html\0"
diff --git a/src/macos/MACINSTALL.TXT b/src/macos/MACINSTALL.TXT
index 1839ef20..ce4d1dce 100644
--- a/src/macos/MACINSTALL.TXT
+++ b/src/macos/MACINSTALL.TXT
@@ -1 +1 @@
-MACOS (not MACOS X) =================== This is the first attempt at porting cURL to MacOS. http, ftp, dict and telnet seems to work fine, other protocols and advanced features have not been all tested. This port is heavily based on the GUSI library from Matthias Neeracher. GUSI (Grand Unified Socket Interface) is a POSIX/Pthreads/Sockets library bringing some of the comforts of UNIX 98 to traditional MacOS. The latest GUSI release can be downloaded from sourceforge at <http://sourceforge.net/projects/gusi/> I have also written a few functions to help port Unix applications to MacOS. These functions are part of the GUSI Extra library that can be downloaded at <http://perso.wanadoo.fr/ela/resources.html#gusiextra> OpenSSL support is still experimental but I hope to deliver a version including SSL soon. cURL for MacOS requires using the CodeWarrior compiler from Metrowerks. First download GUSI, GUSI Extra and cURL. Access paths have been setup so that GUSI, GUSI Extra and cURL directories should have the same parent directory. Follow the instructions in GUSI Extra "readme.txt" mainly the ones related to SIOUX and GUSI patches. If you do not apply these patches curl will not behave correctly. In the 'curl/src/macos' directory, decode "curl.mcp.xml.sit.hqx" (This is a stuffit binhexed file) From the CodeWarrior IDE, import 'curl/src/macos/curl.xml', adjust the access paths if required. Then you should be able to build: - the libcurl libraries for PPC and 68K. - the curl application (also available for PPC and 68K) which is the command line version of cURL. If the file "tool_hugehelp.c" is missing rename "curl/src/tool_hugehelp.c.cvs" to "tool_hugehelp.c" and make sure its file type is 'TEXT'
+MACOS (not MACOS X) =================== This is the first attempt at porting curl to MacOS. http, ftp, dict and telnet seems to work fine, other protocols and advanced features have not been all tested. This port is heavily based on the GUSI library from Matthias Neeracher. GUSI (Grand Unified Socket Interface) is a POSIX/Pthreads/Sockets library bringing some of the comforts of UNIX 98 to traditional MacOS. The latest GUSI release can be downloaded from sourceforge at <http://sourceforge.net/projects/gusi/> I have also written a few functions to help port Unix applications to MacOS. These functions are part of the GUSI Extra library that can be downloaded at <http://perso.wanadoo.fr/ela/resources.html#gusiextra> OpenSSL support is still experimental but I hope to deliver a version including SSL soon. curl for MacOS requires using the CodeWarrior compiler from Metrowerks. First download GUSI, GUSI Extra and curl. Access paths have been setup so that GUSI, GUSI Extra and curl directories should have the same parent directory. Follow the instructions in GUSI Extra "readme.txt" mainly the ones related to SIOUX and GUSI patches. If you do not apply these patches curl will not behave correctly. In the 'curl/src/macos' directory, decode "curl.mcp.xml.sit.hqx" (This is a stuffit binhexed file) From the CodeWarrior IDE, import 'curl/src/macos/curl.xml', adjust the access paths if required. Then you should be able to build: - the libcurl libraries for PPC and 68K. - the curl application (also available for PPC and 68K) which is the command line version of curl. If the file "tool_hugehelp.c" is missing rename "curl/src/tool_hugehelp.c.cvs" to "tool_hugehelp.c" and make sure its file type is 'TEXT'
diff --git a/src/makefile.amiga b/src/makefile.amiga
index 25449a6d..9f3748b1 100644
--- a/src/makefile.amiga
+++ b/src/makefile.amiga
@@ -1,5 +1,5 @@
#
-# $VER: cURL Makefile for AmigaOS ...
+# $VER: curl Makefile for AmigaOS ...
#
# change the follow to where you have the AmiTCP SDK v4.3 includes:
@@ -19,12 +19,12 @@ include Makefile.inc
OBJS = $(CURL_CFILES:.c=.o) $(CURLX_CFILES:.c=.o)
all: tool_hugehelp.c $(OBJS)
- $(CC) $(CFLAGS) -o cURL $(OBJS) $(LIBS) -Wl,-Map,cURL.map,--cref
+ $(CC) $(CFLAGS) -o curl $(OBJS) $(LIBS) -Wl,-Map,curl.map,--cref
tool_hugehelp.c: $(README) $(MANPAGE) mkhelp.pl
rm -f tool_hugehelp.c
/bin/nroff -man $(MANPAGE) | /bin/perl $(MKHELP) -c $(README) > tool_hugehelp.c
install:
- $(INSTALL) -c cURL /c/cURL
+ $(INSTALL) -c curl /c/curl
diff --git a/src/makefile.dj b/src/makefile.dj
index 6a6c8f95..c3bbc237 100644
--- a/src/makefile.dj
+++ b/src/makefile.dj
@@ -59,7 +59,7 @@ PROGRAM = curl.exe
OBJECTS += $(addprefix $(OBJ_DIR)/, $(CSOURCES:.c=.o))
all: $(OBJ_DIR) $(PROGRAM)
- @echo Welcome to cURL
+ @echo Welcome to curl
$(PROGRAM): $(OBJECTS) ../lib/libcurl.a
$(CC) -o $@ $^ $(LDFLAGS) $(EX_LIBS)
diff --git a/src/tool_cb_dbg.c b/src/tool_cb_dbg.c
index 97a5c92d..221eae67 100644
--- a/src/tool_cb_dbg.c
+++ b/src/tool_cb_dbg.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -73,9 +73,9 @@ int tool_debug_cb(CURL *handle, curl_infotype type,
if(!config->trace_stream) {
/* open for append */
- if(curlx_strequal("-", config->trace_dump))
+ if(!strcmp("-", config->trace_dump))
config->trace_stream = stdout;
- else if(curlx_strequal("%", config->trace_dump))
+ else if(!strcmp("%", config->trace_dump))
/* Ok, this is somewhat hackish but we do it undocumented for now */
config->trace_stream = config->errors; /* aka stderr */
else {
diff --git a/src/tool_cb_hdr.c b/src/tool_cb_hdr.c
index f7d83556..3891b073 100644
--- a/src/tool_cb_hdr.c
+++ b/src/tool_cb_hdr.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
***************************************************************************/
#include "tool_setup.h"
-#include "rawstr.h"
+#include "strcase.h"
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
@@ -47,7 +47,7 @@ size_t tool_header_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
struct OutStruct *heads = hdrcbdata->heads;
const char *str = ptr;
const size_t cb = size * nmemb;
- const char *end = (char*)ptr + cb;
+ const char *end = (char *)ptr + cb;
char *url = NULL;
/*
diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c
index 8b60a91b..5d38fb33 100644
--- a/src/tool_cfgable.c
+++ b/src/tool_cfgable.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -41,6 +41,7 @@ void config_init(struct OperationConfig* config)
CURLPROTO_SMBS);
config->proto_redir_present = FALSE;
config->proto_default = NULL;
+ config->tcp_nodelay = TRUE; /* enabled by default */
}
static void free_config_fields(struct OperationConfig *config)
@@ -67,6 +68,9 @@ static void free_config_fields(struct OperationConfig *config)
Curl_safefree(config->tls_username);
Curl_safefree(config->tls_password);
Curl_safefree(config->tls_authtype);
+ Curl_safefree(config->proxy_tls_username);
+ Curl_safefree(config->proxy_tls_password);
+ Curl_safefree(config->proxy_tls_authtype);
Curl_safefree(config->proxyuserpwd);
Curl_safefree(config->proxy);
@@ -98,15 +102,24 @@ static void free_config_fields(struct OperationConfig *config)
config->url_out = NULL;
Curl_safefree(config->cipher_list);
+ Curl_safefree(config->proxy_cipher_list);
Curl_safefree(config->cert);
+ Curl_safefree(config->proxy_cert);
Curl_safefree(config->cert_type);
+ Curl_safefree(config->proxy_cert_type);
Curl_safefree(config->cacert);
+ Curl_safefree(config->proxy_cacert);
Curl_safefree(config->capath);
+ Curl_safefree(config->proxy_capath);
Curl_safefree(config->crlfile);
Curl_safefree(config->pinnedpubkey);
+ Curl_safefree(config->proxy_crlfile);
Curl_safefree(config->key);
+ Curl_safefree(config->proxy_key);
Curl_safefree(config->key_type);
+ Curl_safefree(config->proxy_key_type);
Curl_safefree(config->key_passwd);
+ Curl_safefree(config->proxy_key_passwd);
Curl_safefree(config->pubkey);
Curl_safefree(config->hostpubmd5);
Curl_safefree(config->engine);
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
index aa98fced..6589d882 100644
--- a/src/tool_cfgable.h
+++ b/src/tool_cfgable.h
@@ -78,6 +78,9 @@ struct OperationConfig {
char *tls_username;
char *tls_password;
char *tls_authtype;
+ char *proxy_tls_username;
+ char *proxy_tls_password;
+ char *proxy_tls_authtype;
char *proxyuserpwd;
char *proxy;
int proxyver; /* set to CURLPROXY_HTTP* define */
@@ -106,15 +109,24 @@ struct OperationConfig {
struct getout *url_get; /* point to the node to fill in URL */
struct getout *url_out; /* point to the node to fill in outfile */
char *cipher_list;
+ char *proxy_cipher_list;
char *cert;
+ char *proxy_cert;
char *cert_type;
+ char *proxy_cert_type;
char *cacert;
+ char *proxy_cacert;
char *capath;
+ char *proxy_capath;
char *crlfile;
+ char *proxy_crlfile;
char *pinnedpubkey;
char *key;
+ char *proxy_key;
char *key_type;
+ char *proxy_key_type;
char *key_passwd;
+ char *proxy_key_passwd;
char *pubkey;
char *hostpubmd5;
char *engine;
@@ -127,6 +139,8 @@ struct OperationConfig {
bool globoff;
bool use_httpget;
bool insecure_ok; /* set TRUE to allow insecure SSL connects */
+ bool proxy_insecure_ok; /* set TRUE to allow insecure SSL connects
+ for proxy */
bool verifystatus;
bool create_dirs;
bool ftp_create_dirs;
@@ -142,6 +156,7 @@ struct OperationConfig {
struct curl_slist *postquote;
struct curl_slist *prequote;
long ssl_version;
+ long proxy_ssl_version;
long ip_version;
curl_TimeCond timecond;
time_t condtime;
@@ -176,6 +191,7 @@ struct OperationConfig {
bool tcp_nodelay;
bool tcp_fastopen;
long req_retry; /* number of retries */
+ bool retry_connrefused; /* set connection refused as a transient error */
long retry_delay; /* delay between retries (in seconds) */
long retry_maxtime; /* maximum time to keep retrying */
@@ -201,7 +217,10 @@ struct OperationConfig {
bool xattr; /* store metadata in extended attributes */
long gssapi_delegation;
bool ssl_allow_beast; /* allow this SSL vulnerability */
+ bool proxy_ssl_allow_beast; /* allow this SSL vulnerability for proxy*/
+
bool ssl_no_revoke; /* disable SSL certificate revocation checks */
+ /*bool proxy_ssl_no_revoke; */
bool use_metalink; /* process given URLs as metalink XML file */
metalinkfile *metalinkfile_list; /* point to the first node */
@@ -238,7 +257,7 @@ struct GlobalConfig {
bool tracetime; /* include timestamp? */
int progressmode; /* CURL_PROGRESS_BAR / CURL_PROGRESS_STATS */
char *libcurl; /* Output libcurl code to this file name */
-
+ bool fail_early; /* exit on first transfer error */
struct OperationConfig *first;
struct OperationConfig *current;
struct OperationConfig *last; /* Always last in the struct */
diff --git a/src/tool_dirhie.c b/src/tool_dirhie.c
index b65db411..23bb2cb4 100644
--- a/src/tool_dirhie.c
+++ b/src/tool_dirhie.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -91,6 +91,14 @@ static void show_dir_errno(FILE *errors, const char *name)
* should create all the dir* automagically
*/
+#ifdef WIN32
+/* systems that may use either or when specifying a path */
+#define PATH_DELIMITERS "\\/"
+#else
+#define PATH_DELIMITERS DIR_CHAR
+#endif
+
+
CURLcode create_dir_hierarchy(const char *outfile, FILE *errors)
{
char *tempdir;
@@ -112,10 +120,12 @@ CURLcode create_dir_hierarchy(const char *outfile, FILE *errors)
}
dirbuildup[0] = '\0';
- tempdir = strtok(outdup, DIR_CHAR);
+ /* Allow strtok() here since this isn't used threaded */
+ /* !checksrc! disable BANNEDFUNC 2 */
+ tempdir = strtok(outdup, PATH_DELIMITERS);
while(tempdir != NULL) {
- tempdir2 = strtok(NULL, DIR_CHAR);
+ tempdir2 = strtok(NULL, PATH_DELIMITERS);
/* since strtok returns a token for the last word even
if not ending with DIR_CHAR, we need to prune it */
if(tempdir2 != NULL) {
@@ -123,7 +133,8 @@ CURLcode create_dir_hierarchy(const char *outfile, FILE *errors)
if(dlen)
snprintf(&dirbuildup[dlen], outlen - dlen, "%s%s", DIR_CHAR, tempdir);
else {
- if(0 != strncmp(outdup, DIR_CHAR, 1))
+ if(outdup == tempdir)
+ /* the output string doesn't start with a separator */
strcpy(dirbuildup, tempdir);
else
snprintf(dirbuildup, outlen, "%s%s", DIR_CHAR, tempdir);
diff --git a/src/tool_doswin.c b/src/tool_doswin.c
index aed657a6..eb3b29c4 100644
--- a/src/tool_doswin.c
+++ b/src/tool_doswin.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -615,7 +615,7 @@ SANITIZEcode rename_if_reserved_dos_device_name(char **const sanitized,
char **__crt0_glob_function(char *arg)
{
(void)arg;
- return (char**)0;
+ return (char **)0;
}
#endif /* MSDOS && (__DJGPP__ || __GO32__) */
diff --git a/src/tool_formparse.c b/src/tool_formparse.c
index de30c526..88352fb1 100644
--- a/src/tool_formparse.c
+++ b/src/tool_formparse.c
@@ -21,7 +21,7 @@
***************************************************************************/
#include "tool_setup.h"
-#include "rawstr.h"
+#include "strcase.h"
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index d60e04c8..3d254e1b 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -21,7 +21,7 @@
***************************************************************************/
#include "tool_setup.h"
-#include "rawstr.h"
+#include "strcase.h"
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
@@ -125,6 +125,7 @@ static const struct LongShort aliases[]= {
{"$e", "proxy-digest", FALSE},
{"$f", "proxy-basic", FALSE},
{"$g", "retry", TRUE},
+ {"$V", "retry-connrefused", FALSE},
{"$h", "retry-delay", TRUE},
{"$i", "retry-max-time", TRUE},
{"$k", "proxy-negotiate", FALSE},
@@ -190,6 +191,7 @@ static const struct LongShort aliases[]= {
{"10", "tlsv1.0", FALSE},
{"11", "tlsv1.1", FALSE},
{"12", "tlsv1.2", FALSE},
+ {"13", "tlsv1.3", FALSE},
{"2", "sslv2", FALSE},
{"3", "sslv3", FALSE},
{"4", "ipv4", FALSE},
@@ -228,7 +230,26 @@ static const struct LongShort aliases[]= {
{"Er", "false-start", FALSE},
{"Es", "ssl-no-revoke", FALSE},
{"Et", "tcp-fastopen", FALSE},
+ {"Eu", "proxy-tlsuser", TRUE},
+ {"Ev", "proxy-tlspassword", TRUE},
+ {"Ew", "proxy-tlsauthtype", TRUE},
+ {"Ex", "proxy-cert", TRUE},
+ {"Ey", "proxy-cert-type", TRUE},
+ {"Ez", "proxy-key", TRUE},
+ {"E0", "proxy-key-type", TRUE},
+ {"E1", "proxy-pass", TRUE},
+ {"E2", "proxy-ciphers", TRUE},
+ {"E3", "proxy-crlfile", TRUE},
+ {"E4", "proxy-ssl-allow-beast", FALSE},
+ {"E5", "login-options", TRUE},
+ {"E6", "proxy-cacert", TRUE},
+ {"E7", "proxy-capath", TRUE},
+ {"E8", "proxy-insecure", FALSE},
+ {"E9", "proxy-tlsv1", FALSE},
+ {"EA", "proxy-sslv2", FALSE},
+ {"EB", "proxy-sslv3", FALSE},
{"f", "fail", FALSE},
+ {"fa", "fail-early", FALSE},
{"F", "form", TRUE},
{"Fs", "form-string", TRUE},
{"g", "globoff", FALSE},
@@ -301,9 +322,12 @@ void parse_cert_parameter(const char *cert_parameter,
if(param_length == 0)
return;
- /* next less trivial: cert_parameter contains no colon nor backslash; this
+ /* next less trivial: cert_parameter starts 'pkcs11:' and thus
+ * looks like a RFC7512 PKCS#11 URI which can be used as-is.
+ * Also if cert_parameter contains no colon nor backslash, this
* means no passphrase was given and no characters escaped */
- if(!strpbrk(cert_parameter, ":\\")) {
+ if(!strncmp(cert_parameter, "pkcs11:", 7) ||
+ !strpbrk(cert_parameter, ":\\")) {
*certname = strdup(cert_parameter);
return;
}
@@ -378,6 +402,20 @@ done:
*certname_place = '\0';
}
+static void
+GetFileAndPassword(char *nextarg, char **file, char **password)
+{
+ char *certname, *passphrase;
+ parse_cert_parameter(nextarg, &certname, &passphrase);
+ Curl_safefree(*file);
+ *file = certname;
+ if(passphrase) {
+ Curl_safefree(*password);
+ *password = passphrase;
+ }
+ cleanarg(nextarg);
+}
+
ParameterError getparameter(char *flag, /* f or -long-flag */
char *nextarg, /* NULL if unset */
bool *usedarg, /* set to TRUE if the arg
@@ -413,10 +451,10 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
}
for(j = 0; j < sizeof(aliases)/sizeof(aliases[0]); j++) {
- if(curlx_strnequal(aliases[j].lname, word, fnam)) {
+ if(curl_strnequal(aliases[j].lname, word, fnam)) {
longopt = TRUE;
numhits++;
- if(curlx_raw_equal(aliases[j].lname, word)) {
+ if(curl_strequal(aliases[j].lname, word)) {
parse = aliases[j].letter;
hit = j;
numhits = 1; /* a single unique hit */
@@ -789,6 +827,9 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
if(err)
return err;
break;
+ case 'V': /* --retry-connrefused */
+ config->retry_connrefused = toggle;
+ break;
case 'h': /* --retry-delay */
err = str2unum(&config->retry_delay, nextarg);
if(err)
@@ -1058,6 +1099,10 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
/* TLS version 1.2 */
config->ssl_version = CURL_SSLVERSION_TLSv1_2;
break;
+ case '3':
+ /* TLS version 1.3 */
+ config->ssl_version = CURL_SSLVERSION_TLSv1_3;
+ break;
}
break;
case '2':
@@ -1106,7 +1151,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
break;
case 'C':
/* This makes us continue an ftp transfer at given position */
- if(!curlx_strequal(nextarg, "-")) {
+ if(strcmp(nextarg, "-")) {
err = str2offset(&config->resume_from, nextarg);
if(err)
return err;
@@ -1150,7 +1195,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
}
if('@' == is_file) {
/* a '@' letter, it means that a file name or - (stdin) follows */
- if(curlx_strequal("-", p)) {
+ if(!strcmp("-", p)) {
file = stdin;
set_binmode(stdin);
}
@@ -1215,7 +1260,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
or - (stdin) follows */
nextarg++; /* pass the @ */
- if(curlx_strequal("-", nextarg)) {
+ if(!strcmp("-", nextarg)) {
file = stdin;
if(subletter == 'b') /* forced data-binary */
set_binmode(stdin);
@@ -1321,6 +1366,9 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
break;
case 'E':
switch(subletter) {
+ case '\0': /* certificate file */
+ GetFileAndPassword(nextarg, &config->cert, &config->key_passwd);
+ break;
case 'a': /* CA info PEM file */
/* CA info PEM file */
GetStr(&config->cacert, nextarg);
@@ -1340,7 +1388,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
break;
case 'f': /* crypto engine */
GetStr(&config->engine, nextarg);
- if(config->engine && curlx_raw_equal(config->engine, "list"))
+ if(config->engine && curl_strequal(config->engine, "list"))
return PARAM_ENGINES_REQUESTED;
break;
case 'g': /* CA info PEM file */
@@ -1374,7 +1422,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
case 'm': /* TLS authentication type */
if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
GetStr(&config->tls_authtype, nextarg);
- if(!strequal(config->tls_authtype, "SRP"))
+ if(!curl_strequal(config->tls_authtype, "SRP"))
return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
}
else
@@ -1411,23 +1459,112 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
config->tcp_fastopen = TRUE;
break;
- default: /* certificate file */
- {
- char *certname, *passphrase;
- parse_cert_parameter(nextarg, &certname, &passphrase);
- Curl_safefree(config->cert);
- config->cert = certname;
- if(passphrase) {
- Curl_safefree(config->key_passwd);
- config->key_passwd = passphrase;
+ case 'u': /* TLS username for proxy */
+ if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
+ GetStr(&config->proxy_tls_username, nextarg);
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+
+ case 'v': /* TLS password for proxy */
+ if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
+ GetStr(&config->proxy_tls_password, nextarg);
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+
+ case 'w': /* TLS authentication type for proxy */
+ if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
+ GetStr(&config->proxy_tls_authtype, nextarg);
+ if(!curl_strequal(config->proxy_tls_authtype, "SRP"))
+ return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
}
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+
+ case 'x': /* certificate file for proxy */
+ GetFileAndPassword(nextarg, &config->proxy_cert,
+ &config->proxy_key_passwd);
+ break;
+
+ case 'y': /* cert file type for proxy */
+ GetStr(&config->proxy_cert_type, nextarg);
+ break;
+
+ case 'z': /* private key file for proxy */
+ GetStr(&config->proxy_key, nextarg);
+ break;
+
+ case '0': /* private key file type for proxy */
+ GetStr(&config->proxy_key_type, nextarg);
+ break;
+
+ case '1': /* private key passphrase for proxy */
+ GetStr(&config->proxy_key_passwd, nextarg);
cleanarg(nextarg);
- }
+ break;
+
+ case '2': /* ciphers for proxy */
+ GetStr(&config->proxy_cipher_list, nextarg);
+ break;
+
+ case '3': /* CRL info PEM file for proxy */
+ /* CRL file */
+ GetStr(&config->proxy_crlfile, nextarg);
+ break;
+
+ case '4': /* no empty SSL fragments for proxy */
+ if(curlinfo->features & CURL_VERSION_SSL)
+ config->proxy_ssl_allow_beast = toggle;
+ break;
+
+ case '5': /* --login-options */
+ GetStr(&config->login_options, nextarg);
+ break;
+
+ case '6': /* CA info PEM file for proxy */
+ /* CA info PEM file */
+ GetStr(&config->proxy_cacert, nextarg);
+ break;
+
+ case '7': /* CA info PEM file for proxy */
+ /* CA cert directory */
+ GetStr(&config->proxy_capath, nextarg);
+ break;
+
+ case '8': /* allow insecure SSL connects for proxy */
+ config->proxy_insecure_ok = toggle;
+ break;
+
+ case '9':
+ /* TLS version 1 for proxy */
+ config->proxy_ssl_version = CURL_SSLVERSION_TLSv1;
+ break;
+
+ case 'A':
+ /* SSL version 2 for proxy */
+ config->proxy_ssl_version = CURL_SSLVERSION_SSLv2;
+ break;
+
+ case 'B':
+ /* SSL version 3 for proxy */
+ config->proxy_ssl_version = CURL_SSLVERSION_SSLv3;
+ break;
+
+ default: /* unknown flag */
+ return PARAM_OPTION_UNKNOWN;
}
break;
case 'f':
- /* fail hard on errors */
- config->failonerror = toggle;
+ switch(subletter) {
+ case 'a': /* --fail-early */
+ global->fail_early = toggle;
+ break;
+ default:
+ /* fail hard on errors */
+ config->failonerror = toggle;
+ }
break;
case 'F':
/* "form data" simulation, this is a little advanced so lets do our best
@@ -1767,7 +1904,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
FILE *file;
const char *fname;
nextarg++; /* pass the @ */
- if(curlx_strequal("-", nextarg)) {
+ if(!strcmp("-", nextarg)) {
fname = "<stdin>";
file = stdin;
}
@@ -1877,7 +2014,7 @@ ParameterError parse_args(struct GlobalConfig *config, int argc,
bool passarg;
char *flag = argv[i];
- if(curlx_strequal("--", argv[i]))
+ if(!strcmp("--", argv[i]))
/* This indicates the end of the flags and thus enables the
following (URL) argument to start with -. */
stillflags = FALSE;
@@ -1933,7 +2070,7 @@ ParameterError parse_args(struct GlobalConfig *config, int argc,
result != PARAM_ENGINES_REQUESTED) {
const char *reason = param2text(result);
- if(orig_opt && !curlx_strequal(":", orig_opt))
+ if(orig_opt && strcmp(":", orig_opt))
helpf(config->errors, "option %s: %s\n", orig_opt, reason);
else
helpf(config->errors, "%s\n", reason);
diff --git a/src/tool_getpass.h b/src/tool_getpass.h
index 95dd7793..f639596f 100644
--- a/src/tool_getpass.h
+++ b/src/tool_getpass.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,7 +30,7 @@
/*
* Returning NULL will abort the continued operation!
*/
-char* getpass_r(const char *prompt, char* buffer, size_t buflen);
+char *getpass_r(const char *prompt, char *buffer, size_t buflen);
#endif
#endif /* HEADER_CURL_TOOL_GETPASS_H */
diff --git a/src/tool_help.c b/src/tool_help.c
index fb428c9c..39a51784 100644
--- a/src/tool_help.c
+++ b/src/tool_help.c
@@ -78,7 +78,7 @@ static const char *const helptext[] = {
" --dns-interface Interface to use for DNS requests",
" --dns-ipv4-addr IPv4 address to use for DNS requests, dot notation",
" --dns-ipv6-addr IPv6 address to use for DNS requests, dot notation",
- " -D, --dump-header FILE Write the headers to FILE",
+ " -D, --dump-header FILE Write the received headers to FILE",
" --egd-file FILE EGD socket path for random data (SSL)",
" --engine ENGINE Crypto engine (use \"--engine list\" for list) (SSL)",
#ifdef USE_ENVIRONMENT
@@ -86,6 +86,7 @@ static const char *const helptext[] = {
#endif
" --expect100-timeout SECONDS How long to wait for 100-continue (H)",
" -f, --fail Fail silently (no output at all) on HTTP errors (H)",
+ " --fail-early Fail on first transfer error, do not continue",
" --false-start Enable TLS False Start.",
" -F, --form CONTENT Specify HTTP multipart POST data (H)",
" --form-string STRING Specify HTTP multipart POST data (H)",
@@ -175,10 +176,36 @@ static const char *const helptext[] = {
" --proxy-anyauth Pick \"any\" proxy authentication method (H)",
" --proxy-basic Use Basic authentication on the proxy (H)",
" --proxy-digest Use Digest authentication on the proxy (H)",
+ " --proxy-cacert FILE "
+ "CA certificate to verify peer against for proxy (SSL)",
+ " --proxy-capath DIR "
+ "CA directory to verify peer against for proxy (SSL)",
+ " --proxy-cert CERT[:PASSWD] "
+ "Client certificate file and password for proxy (SSL)",
+ " --proxy-cert-type TYPE "
+ "Certificate file type (DER/PEM/ENG) for proxy (SSL)",
+ " --proxy-ciphers LIST SSL ciphers to use for proxy (SSL)",
+ " --proxy-crlfile FILE "
+ "Get a CRL list in PEM format from the given file for proxy",
+ " --proxy-insecure "
+ "Allow connections to SSL sites without certs for proxy (H)",
+ " --proxy-key KEY Private key file name for proxy (SSL)",
+ " --proxy-key-type TYPE "
+ "Private key file type for proxy (DER/PEM/ENG) (SSL)",
" --proxy-negotiate "
"Use HTTP Negotiate (SPNEGO) authentication on the proxy (H)",
" --proxy-ntlm Use NTLM authentication on the proxy (H)",
" --proxy-header LINE Pass custom header LINE to proxy (H)",
+ " --proxy-pass PASS Pass phrase for the private key for proxy (SSL)",
+ " --proxy-ssl-allow-beast "
+ "Allow security flaw to improve interop for proxy (SSL)",
+ " --proxy-sslv2 Use SSLv2 for proxy (SSL)",
+ " --proxy-sslv3 Use SSLv3 for proxy (SSL)",
+ " --proxy-tlsv1 Use TLSv1 for proxy (SSL)",
+ " --proxy-tlsuser USER TLS username for proxy",
+ " --proxy-tlspassword STRING TLS password for proxy",
+ " --proxy-tlsauthtype STRING "
+ "TLS authentication type for proxy (default SRP)",
" --proxy-service-name NAME SPNEGO proxy service name",
" --service-name NAME SPNEGO service name",
" -U, --proxy-user USER[:PASSWORD] Proxy user and password",
@@ -198,6 +225,7 @@ static const char *const helptext[] = {
" --resolve HOST:PORT:ADDRESS Force resolve of HOST:PORT to ADDRESS",
" --retry NUM "
"Retry request NUM times if transient problems occur",
+ " --retry-connrefused Retry on connection refused (use with --retry)",
" --retry-delay SECONDS Wait SECONDS between retries",
" --retry-max-time SECONDS Retry only within this period",
" --sasl-ir Enable initial response in SASL authentication",
@@ -232,6 +260,7 @@ static const char *const helptext[] = {
" --tlsv1.0 Use TLSv1.0 (SSL)",
" --tlsv1.1 Use TLSv1.1 (SSL)",
" --tlsv1.2 Use TLSv1.2 (SSL)",
+ " --tlsv1.3 Use TLSv1.3 (SSL)",
" --trace FILE Write a debug trace to FILE",
" --trace-ascii FILE Like --trace, but without hex output",
" --trace-time Add time stamps to trace/verbose output",
diff --git a/src/tool_helpers.c b/src/tool_helpers.c
index fef14596..b5a619b9 100644
--- a/src/tool_helpers.c
+++ b/src/tool_helpers.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
***************************************************************************/
#include "tool_setup.h"
-#include "rawstr.h"
+#include "strcase.h"
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
@@ -35,7 +35,7 @@
#include "memdebug.h" /* keep this as LAST include */
/*
-** Helper functions that are used from more tha one source file.
+** Helper functions that are used from more than one source file.
*/
const char *param2text(int res)
diff --git a/src/tool_libinfo.c b/src/tool_libinfo.c
index 5db85480..d2bf7fb9 100644
--- a/src/tool_libinfo.c
+++ b/src/tool_libinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
***************************************************************************/
#include "tool_setup.h"
-#include "rawstr.h"
+#include "strcase.h"
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
@@ -89,7 +89,7 @@ CURLcode get_libcurl_info(void)
if(curlinfo->protocols) {
for(proto = curlinfo->protocols; *proto; proto++) {
for(p = possibly_built_in; p->proto_name; p++) {
- if(curlx_raw_equal(*proto, p->proto_name)) {
+ if(curl_strequal(*proto, p->proto_name)) {
built_in_protos |= p->proto_pattern;
break;
}
diff --git a/src/tool_metalink.c b/src/tool_metalink.c
index 9a6465e6..f4173562 100644
--- a/src/tool_metalink.c
+++ b/src/tool_metalink.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,6 +24,7 @@
#ifdef USE_METALINK
#include <sys/stat.h>
+#include <stdlib.h>
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
@@ -92,8 +93,6 @@ struct win32_crypto_hash {
# error "Can't compile METALINK support without a crypto library."
#endif
-#include "rawstr.h"
-
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
#include "curlx.h"
@@ -563,18 +562,13 @@ int Curl_digest_final(digest_context *context, unsigned char *result)
static unsigned char hex_to_uint(const char *s)
{
- int v[2];
- int i;
- for(i = 0; i < 2; ++i) {
- v[i] = Curl_raw_toupper(s[i]);
- if('0' <= v[i] && v[i] <= '9') {
- v[i] -= '0';
- }
- else if('A' <= v[i] && v[i] <= 'Z') {
- v[i] -= 'A'-10;
- }
- }
- return (unsigned char)((v[0] << 4) | v[1]);
+ char buf[3];
+ unsigned long val;
+ buf[0] = s[0];
+ buf[1] = s[1];
+ buf[2] = 0;
+ val = strtoul(buf, NULL, 16);
+ return (unsigned char)(val&0xff);
}
/*
@@ -747,7 +741,7 @@ static metalinkfile *new_metalinkfile(metalink_file_t *fileinfo)
++digest_alias) {
metalink_checksum_t **p;
for(p = fileinfo->checksums; *p; ++p) {
- if(Curl_raw_equal(digest_alias->alias_name, (*p)->type) &&
+ if(curl_strequal(digest_alias->alias_name, (*p)->type) &&
check_hex_digest((*p)->hash, digest_alias->digest_def)) {
f->checksum =
new_metalink_checksum_from_hex_digest(digest_alias->digest_def,
@@ -777,10 +771,10 @@ static metalinkfile *new_metalinkfile(metalink_file_t *fileinfo)
metainfo file URL may be appeared in fileinfo->metaurls.
*/
if((*p)->type == NULL ||
- Curl_raw_equal((*p)->type, "http") ||
- Curl_raw_equal((*p)->type, "https") ||
- Curl_raw_equal((*p)->type, "ftp") ||
- Curl_raw_equal((*p)->type, "ftps")) {
+ curl_strequal((*p)->type, "http") ||
+ curl_strequal((*p)->type, "https") ||
+ curl_strequal((*p)->type, "ftp") ||
+ curl_strequal((*p)->type, "ftps")) {
res = new_metalink_resource((*p)->url);
tail->next = res;
tail = res;
@@ -906,7 +900,7 @@ static int check_content_type(const char *content_type, const char *media_type)
if(!*ptr) {
return 0;
}
- return Curl_raw_nequal(ptr, media_type, media_type_len) &&
+ return curl_strnequal(ptr, media_type, media_type_len) &&
(*(ptr+media_type_len) == '\0' || *(ptr+media_type_len) == ' ' ||
*(ptr+media_type_len) == '\t' || *(ptr+media_type_len) == ';');
}
diff --git a/src/tool_operate.c b/src/tool_operate.c
index 2b53c9a8..94d87fec 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -43,7 +43,7 @@
# include <fabdef.h>
#endif
-#include "rawstr.h"
+#include "strcase.h"
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
@@ -143,8 +143,8 @@ static bool is_fatal_error(CURLcode code)
* and CD/DVD images should be either a STREAM_LF format or a fixed format.
*
*/
-static curl_off_t vms_realfilesize(const char * name,
- const struct_stat * stat_buf)
+static curl_off_t vms_realfilesize(const char *name,
+ const struct_stat *stat_buf)
{
char buffer[8192];
curl_off_t count;
@@ -174,8 +174,8 @@ static curl_off_t vms_realfilesize(const char * name,
* if not to call a routine to get the correct size.
*
*/
-static curl_off_t VmsSpecialSize(const char * name,
- const struct_stat * stat_buf)
+static curl_off_t VmsSpecialSize(const char *name,
+ const struct_stat *stat_buf)
{
switch(stat_buf->st_fab_rfm) {
case FAB$C_VAR:
@@ -321,7 +321,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
/* Single header file for all URLs */
if(config->headerfile) {
/* open file for output: */
- if(!curlx_strequal(config->headerfile, "-")) {
+ if(strcmp(config->headerfile, "-")) {
FILE *newfile = fopen(config->headerfile, "wb");
if(!newfile) {
warnf(config->global, "Failed to open %s\n", config->headerfile);
@@ -464,7 +464,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
urlnum = 1; /* without globbing, this is a single URL */
/* if multiple files extracted to stdout, insert separators! */
- separator= ((!outfiles || curlx_strequal(outfiles, "-")) && urlnum > 1);
+ separator= ((!outfiles || !strcmp(outfiles, "-")) && urlnum > 1);
/* Here's looping around each globbed URL */
for(li = 0 ; li < urlnum; li++) {
@@ -534,7 +534,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
}
if(((urlnode->flags&GETOUT_USEREMOTE) ||
- (outfile && !curlx_strequal("-", outfile))) &&
+ (outfile && strcmp("-", outfile))) &&
(metalink || !config->use_metalink)) {
/*
@@ -715,7 +715,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
DEBUGASSERT(infd == STDIN_FILENO);
set_binmode(stdin);
- if(curlx_strequal(uploadfile, ".")) {
+ if(!strcmp(uploadfile, ".")) {
if(curlx_nonblock((curl_socket_t)infd, TRUE) < 0)
warnf(config->global,
"fcntl failed on fd=%d: %s\n", infd, strerror(errno));
@@ -792,14 +792,15 @@ static CURLcode operate_do(struct GlobalConfig *global,
set_binmode(stdout);
}
- if(config->tcp_nodelay)
- my_setopt(curl, CURLOPT_TCP_NODELAY, 1L);
+ if(!config->tcp_nodelay)
+ my_setopt(curl, CURLOPT_TCP_NODELAY, 0L);
if(config->tcp_fastopen)
my_setopt(curl, CURLOPT_TCP_FASTOPEN, 1L);
/* where to store */
my_setopt(curl, CURLOPT_WRITEDATA, &outs);
+ my_setopt(curl, CURLOPT_INTERLEAVEDATA, &outs);
if(metalink || !config->use_metalink)
/* what call to write */
my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb);
@@ -868,8 +869,9 @@ static CURLcode operate_do(struct GlobalConfig *global,
/* new in libcurl 7.10 */
if(config->socksproxy) {
- my_setopt_str(curl, CURLOPT_PROXY, config->socksproxy);
- my_setopt_enum(curl, CURLOPT_PROXYTYPE, (long)config->socksver);
+ my_setopt_str(curl, CURLOPT_SOCKS_PROXY, config->socksproxy);
+ my_setopt_enum(curl, CURLOPT_SOCKS_PROXYTYPE,
+ (long)config->socksver);
}
/* new in libcurl 7.10.6 */
@@ -999,6 +1001,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, CURL_OFF_T_C(0));
my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd);
+ my_setopt_str(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd);
if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
@@ -1016,6 +1019,8 @@ static CURLcode operate_do(struct GlobalConfig *global,
if(config->cacert)
my_setopt_str(curl, CURLOPT_CAINFO, config->cacert);
+ if(config->proxy_cacert)
+ my_setopt_str(curl, CURLOPT_PROXY_CAINFO, config->proxy_cacert);
if(config->capath) {
result = res_setopt_str(curl, CURLOPT_CAPATH, config->capath);
if(result == CURLE_NOT_BUILT_IN) {
@@ -1026,17 +1031,32 @@ static CURLcode operate_do(struct GlobalConfig *global,
else if(result)
goto show_error;
}
+ if(config->proxy_capath)
+ my_setopt_str(curl, CURLOPT_PROXY_CAPATH, config->proxy_capath);
+ else if(config->capath) /* CURLOPT_PROXY_CAPATH default is capath */
+ my_setopt_str(curl, CURLOPT_PROXY_CAPATH, config->capath);
+
if(config->crlfile)
my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile);
+ if(config->proxy_crlfile)
+ my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->proxy_crlfile);
+ else if(config->crlfile) /* CURLOPT_PROXY_CRLFILE default is crlfile */
+ my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->crlfile);
if(config->pinnedpubkey)
my_setopt_str(curl, CURLOPT_PINNEDPUBLICKEY, config->pinnedpubkey);
if(curlinfo->features & CURL_VERSION_SSL) {
my_setopt_str(curl, CURLOPT_SSLCERT, config->cert);
+ my_setopt_str(curl, CURLOPT_PROXY_SSLCERT, config->proxy_cert);
my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
+ my_setopt_str(curl, CURLOPT_PROXY_SSLCERTTYPE,
+ config->proxy_cert_type);
my_setopt_str(curl, CURLOPT_SSLKEY, config->key);
+ my_setopt_str(curl, CURLOPT_PROXY_SSLKEY, config->proxy_key);
my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
+ my_setopt_str(curl, CURLOPT_PROXY_SSLKEYTYPE,
+ config->proxy_key_type);
if(config->insecure_ok) {
my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
@@ -1047,6 +1067,13 @@ static CURLcode operate_do(struct GlobalConfig *global,
/* libcurl default is strict verifyhost -> 2L */
/* my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); */
}
+ if(config->proxy_insecure_ok) {
+ my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0L);
+ my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0L);
+ }
+ else {
+ my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 1L);
+ }
if(config->verifystatus)
my_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L);
@@ -1055,6 +1082,8 @@ static CURLcode operate_do(struct GlobalConfig *global,
my_setopt(curl, CURLOPT_SSL_FALSESTART, 1L);
my_setopt_enum(curl, CURLOPT_SSLVERSION, config->ssl_version);
+ my_setopt_enum(curl, CURLOPT_PROXY_SSLVERSION,
+ config->proxy_ssl_version);
}
if(config->path_as_is)
my_setopt(curl, CURLOPT_PATH_AS_IS, 1L);
@@ -1156,6 +1185,10 @@ static CURLcode operate_do(struct GlobalConfig *global,
if(config->cipher_list)
my_setopt_str(curl, CURLOPT_SSL_CIPHER_LIST, config->cipher_list);
+ if(config->proxy_cipher_list)
+ my_setopt_str(curl, CURLOPT_PROXY_SSL_CIPHER_LIST,
+ config->proxy_cipher_list);
+
/* new in libcurl 7.9.2: */
if(config->disable_epsv)
/* disable it */
@@ -1177,7 +1210,6 @@ static CURLcode operate_do(struct GlobalConfig *global,
result = res_setopt_str(curl, CURLOPT_SSLENGINE, config->engine);
if(result)
goto show_error;
- my_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L);
}
/* new in curl 7.10.7, extended in 7.19.4. Modified to use
@@ -1325,6 +1357,15 @@ static CURLcode operate_do(struct GlobalConfig *global,
if(config->tls_authtype)
my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE,
config->tls_authtype);
+ if(config->proxy_tls_username)
+ my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_USERNAME,
+ config->proxy_tls_username);
+ if(config->proxy_tls_password)
+ my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD,
+ config->proxy_tls_password);
+ if(config->proxy_tls_authtype)
+ my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_TYPE,
+ config->proxy_tls_authtype);
}
/* new in 7.22.0 */
@@ -1340,6 +1381,10 @@ static CURLcode operate_do(struct GlobalConfig *global,
my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS, mask);
}
+ if(config->proxy_ssl_allow_beast)
+ my_setopt(curl, CURLOPT_PROXY_SSL_OPTIONS,
+ (long)CURLSSLOPT_ALLOW_BEAST);
+
if(config->mail_auth)
my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
@@ -1441,6 +1486,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
enum {
RETRY_NO,
RETRY_TIMEOUT,
+ RETRY_CONNREFUSED,
RETRY_HTTP,
RETRY_FTP,
RETRY_LAST /* not used */
@@ -1452,6 +1498,13 @@ static CURLcode operate_do(struct GlobalConfig *global,
(CURLE_FTP_ACCEPT_TIMEOUT == result))
/* retry timeout always */
retry = RETRY_TIMEOUT;
+ else if(config->retry_connrefused &&
+ (CURLE_COULDNT_CONNECT == result)) {
+ long oserrno;
+ curl_easy_getinfo(curl, CURLINFO_OS_ERRNO, &oserrno);
+ if(ECONNREFUSED == oserrno)
+ retry = RETRY_CONNREFUSED;
+ }
else if((CURLE_OK == result) ||
(config->failonerror &&
(CURLE_HTTP_RETURNED_ERROR == result))) {
@@ -1499,7 +1552,11 @@ static CURLcode operate_do(struct GlobalConfig *global,
if(retry) {
static const char * const m[]={
- NULL, "timeout", "HTTP error", "FTP error"
+ NULL,
+ "timeout",
+ "connection refused",
+ "HTTP error",
+ "FTP error"
};
warnf(config->global, "Transient problem: %s "
@@ -1559,7 +1616,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
char *effective_url = NULL;
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url);
if(effective_url &&
- curlx_strnequal(effective_url, "http", 4)) {
+ curl_strnequal(effective_url, "http", 4)) {
/* This was HTTP(S) */
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
if(response != 200 && response != 206) {
@@ -1793,9 +1850,9 @@ static CURLcode operate_do(struct GlobalConfig *global,
urlnode->flags = 0;
/*
- ** Bail out upon critical errors
+ ** Bail out upon critical errors or --fail-early
*/
- if(is_fatal_error(result))
+ if(is_fatal_error(result) || (result && global->fail_early))
goto quit_curl;
} /* for-loop through all URLs */
@@ -1842,8 +1899,8 @@ CURLcode operate(struct GlobalConfig *config, int argc, argv_item_t argv[])
/* Parse .curlrc if necessary */
if((argc == 1) ||
- (!curlx_strequal(argv[1], "-q") &&
- !curlx_strequal(argv[1], "--disable"))) {
+ (!curl_strequal(argv[1], "-q") &&
+ !curl_strequal(argv[1], "--disable"))) {
parseconfig(NULL, config); /* ignore possible failure */
/* If we had no arguments then make sure a url was specified in .curlrc */
diff --git a/src/tool_operhlp.c b/src/tool_operhlp.c
index b43dc954..21b5ffe7 100644
--- a/src/tool_operhlp.c
+++ b/src/tool_operhlp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
***************************************************************************/
#include "tool_setup.h"
-#include "rawstr.h"
+#include "strcase.h"
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
@@ -63,8 +63,8 @@ bool output_expected(const char *url, const char *uploadfile)
bool stdin_upload(const char *uploadfile)
{
- return (curlx_strequal(uploadfile, "-") ||
- curlx_strequal(uploadfile, ".")) ? TRUE : FALSE;
+ return (!strcmp(uploadfile, "-") ||
+ !strcmp(uploadfile, ".")) ? TRUE : FALSE;
}
/*
diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c
index f2e68da5..7de49052 100644
--- a/src/tool_paramhlp.c
+++ b/src/tool_paramhlp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
***************************************************************************/
#include "tool_setup.h"
-#include "rawstr.h"
+#include "strcase.h"
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
@@ -284,6 +284,8 @@ long proto2num(struct OperationConfig *config, long *val, const char *str)
if(!buffer)
return 1;
+ /* Allow strtok() here since this isn't used threaded */
+ /* !checksrc! disable BANNEDFUNC 2 */
for(token = strtok(buffer, sep);
token;
token = strtok(NULL, sep)) {
@@ -310,7 +312,7 @@ long proto2num(struct OperationConfig *config, long *val, const char *str)
}
for(pp=protos; pp->name; pp++) {
- if(curlx_raw_equal(token, pp->name)) {
+ if(curl_strequal(token, pp->name)) {
switch (action) {
case deny:
*val &= ~(pp->bit);
@@ -353,7 +355,7 @@ int check_protocol(const char *str)
if(!str)
return PARAM_REQUIRES_PARAMETER;
for(pp = curlinfo->protocols; *pp; pp++) {
- if(curlx_raw_equal(*pp, str))
+ if(curl_strequal(*pp, str))
return PARAM_OK;
}
return PARAM_LIBCURL_UNSUPPORTED_PROTOCOL;
@@ -464,11 +466,11 @@ ParameterError add2list(struct curl_slist **list, const char *ptr)
int ftpfilemethod(struct OperationConfig *config, const char *str)
{
- if(curlx_raw_equal("singlecwd", str))
+ if(curl_strequal("singlecwd", str))
return CURLFTPMETHOD_SINGLECWD;
- if(curlx_raw_equal("nocwd", str))
+ if(curl_strequal("nocwd", str))
return CURLFTPMETHOD_NOCWD;
- if(curlx_raw_equal("multicwd", str))
+ if(curl_strequal("multicwd", str))
return CURLFTPMETHOD_MULTICWD;
warnf(config->global, "unrecognized ftp file method '%s', using default\n",
@@ -479,9 +481,9 @@ int ftpfilemethod(struct OperationConfig *config, const char *str)
int ftpcccmethod(struct OperationConfig *config, const char *str)
{
- if(curlx_raw_equal("passive", str))
+ if(curl_strequal("passive", str))
return CURLFTPSSL_CCC_PASSIVE;
- if(curlx_raw_equal("active", str))
+ if(curl_strequal("active", str))
return CURLFTPSSL_CCC_ACTIVE;
warnf(config->global, "unrecognized ftp CCC method '%s', using default\n",
@@ -492,11 +494,11 @@ int ftpcccmethod(struct OperationConfig *config, const char *str)
long delegation(struct OperationConfig *config, char *str)
{
- if(curlx_raw_equal("none", str))
+ if(curl_strequal("none", str))
return CURLGSSAPI_DELEGATION_NONE;
- if(curlx_raw_equal("policy", str))
+ if(curl_strequal("policy", str))
return CURLGSSAPI_DELEGATION_POLICY_FLAG;
- if(curlx_raw_equal("always", str))
+ if(curl_strequal("always", str))
return CURLGSSAPI_DELEGATION_FLAG;
warnf(config->global, "unrecognized delegation method '%s', using none\n",
diff --git a/src/tool_setopt.c b/src/tool_setopt.c
index 690ce14a..ad3d3073 100644
--- a/src/tool_setopt.c
+++ b/src/tool_setopt.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -45,6 +45,15 @@
const NameValue setopt_nv_CURLPROXY[] = {
NV(CURLPROXY_HTTP),
NV(CURLPROXY_HTTP_1_0),
+ NV(CURLPROXY_HTTPS),
+ NV(CURLPROXY_SOCKS4),
+ NV(CURLPROXY_SOCKS5),
+ NV(CURLPROXY_SOCKS4A),
+ NV(CURLPROXY_SOCKS5_HOSTNAME),
+ NVEND,
+};
+
+const NameValue setopt_nv_CURL_SOCKS_PROXY[] = {
NV(CURLPROXY_SOCKS4),
NV(CURLPROXY_SOCKS5),
NV(CURLPROXY_SOCKS4A),
@@ -83,6 +92,7 @@ const NameValue setopt_nv_CURL_SSLVERSION[] = {
NV(CURL_SSLVERSION_TLSv1_0),
NV(CURL_SSLVERSION_TLSv1_1),
NV(CURL_SSLVERSION_TLSv1_2),
+ NV(CURL_SSLVERSION_TLSv1_3),
NVEND,
};
@@ -157,6 +167,9 @@ static const NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
NV1(CURLOPT_SSL_VERIFYHOST, 1),
NV1(CURLOPT_SSL_ENABLE_NPN, 1),
NV1(CURLOPT_SSL_ENABLE_ALPN, 1),
+ NV1(CURLOPT_TCP_NODELAY, 1),
+ NV1(CURLOPT_PROXY_SSL_VERIFYPEER, 1),
+ NV1(CURLOPT_PROXY_SSL_VERIFYHOST, 1),
NVEND
};
diff --git a/src/tool_setopt.h b/src/tool_setopt.h
index 7cd38751..fecf24fa 100644
--- a/src/tool_setopt.h
+++ b/src/tool_setopt.h
@@ -47,6 +47,7 @@ typedef struct {
} NameValueUnsigned;
extern const NameValue setopt_nv_CURLPROXY[];
+extern const NameValue setopt_nv_CURL_SOCKS_PROXY[];
extern const NameValue setopt_nv_CURL_HTTP_VERSION[];
extern const NameValue setopt_nv_CURL_SSLVERSION[];
extern const NameValue setopt_nv_CURL_TIMECOND[];
@@ -61,6 +62,7 @@ extern const NameValueUnsigned setopt_nv_CURLAUTH[];
#define setopt_nv_CURLOPT_HTTP_VERSION setopt_nv_CURL_HTTP_VERSION
#define setopt_nv_CURLOPT_HTTPAUTH setopt_nv_CURLAUTH
#define setopt_nv_CURLOPT_SSLVERSION setopt_nv_CURL_SSLVERSION
+#define setopt_nv_CURLOPT_PROXY_SSLVERSION setopt_nv_CURL_SSLVERSION
#define setopt_nv_CURLOPT_TIMECONDITION setopt_nv_CURL_TIMECOND
#define setopt_nv_CURLOPT_FTP_SSL_CCC setopt_nv_CURLFTPSSL_CCC
#define setopt_nv_CURLOPT_USE_SSL setopt_nv_CURLUSESSL
@@ -69,6 +71,7 @@ extern const NameValueUnsigned setopt_nv_CURLAUTH[];
#define setopt_nv_CURLOPT_PROTOCOLS setopt_nv_CURLPROTO
#define setopt_nv_CURLOPT_REDIR_PROTOCOLS setopt_nv_CURLPROTO
#define setopt_nv_CURLOPT_PROXYTYPE setopt_nv_CURLPROXY
+#define setopt_nv_CURLOPT_SOCKS_PROXYTYPE setopt_nv_CURL_SOCKS_PROXY
#define setopt_nv_CURLOPT_PROXYAUTH setopt_nv_CURLAUTH
/* Intercept setopt calls for --libcurl */
diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index a357b8b5..e68e30e8 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -44,7 +44,7 @@ static CURLcode glob_fixed(URLGlob *glob, char *fixed, size_t len)
pat->content.Set.ptr_s = 0;
pat->globindex = -1;
- pat->content.Set.elements = malloc(sizeof(char*));
+ pat->content.Set.elements = malloc(sizeof(char *));
if(!pat->content.Set.elements)
return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
@@ -118,14 +118,14 @@ static CURLcode glob_set(URLGlob *glob, char **patternp,
*buf = '\0';
if(pat->content.Set.elements) {
char **new_arr = realloc(pat->content.Set.elements,
- (pat->content.Set.size + 1) * sizeof(char*));
+ (pat->content.Set.size + 1) * sizeof(char *));
if(!new_arr)
return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
pat->content.Set.elements = new_arr;
}
else
- pat->content.Set.elements = malloc(sizeof(char*));
+ pat->content.Set.elements = malloc(sizeof(char *));
if(!pat->content.Set.elements)
return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
@@ -188,32 +188,39 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
/* character range detected */
char min_c;
char max_c;
+ char end_c;
int step=1;
pat->type = UPTCharRange;
- rc = sscanf(pattern, "%c-%c", &min_c, &max_c);
+ rc = sscanf(pattern, "%c-%c%c", &min_c, &max_c, &end_c);
- if((rc == 2) && (pattern[3] == ':')) {
- char *endp;
- unsigned long lstep;
- errno = 0;
- lstep = strtoul(&pattern[4], &endp, 10);
- if(errno || (*endp != ']'))
- step = -1;
- else {
- pattern = endp+1;
- step = (int)lstep;
- if(step > (max_c - min_c))
+ if(rc == 3) {
+ if(end_c == ':') {
+ char *endp;
+ unsigned long lstep;
+ errno = 0;
+ lstep = strtoul(&pattern[4], &endp, 10);
+ if(errno || &pattern[4] == endp || *endp != ']')
step = -1;
+ else {
+ pattern = endp+1;
+ step = (int)lstep;
+ if(step > (max_c - min_c))
+ step = -1;
+ }
}
+ else if(end_c != ']')
+ /* then this is wrong */
+ rc = 0;
+ else
+ /* end_c == ']' */
+ pattern += 4;
}
- else
- pattern += 4;
*posp += (pattern - *patternp);
- if((rc != 2) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a')) ||
+ if((rc != 3) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a')) ||
(step <= 0) )
/* the pattern is not well-formed */
return GLOBERROR("bad range", *posp, CURLE_URL_MALFORMAT);
@@ -257,6 +264,12 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
endp = NULL;
else {
pattern = endp+1;
+ while(*pattern && ISBLANK(*pattern))
+ pattern++;
+ if(!ISDIGIT(*pattern)) {
+ endp = NULL;
+ goto fail;
+ }
errno = 0;
max_n = strtoul(pattern, &endp, 10);
if(errno || (*endp == ':')) {
@@ -277,6 +290,7 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
}
}
+ fail:
*posp += (pattern - *patternp);
if(!endp || (min_n > max_n) || (step_n > (max_n - min_n)) || !step_n)
@@ -407,7 +421,7 @@ static CURLcode glob_parse(URLGlob *glob, char *pattern,
return res;
}
-CURLcode glob_url(URLGlob** glob, char* url, unsigned long *urlnum,
+CURLcode glob_url(URLGlob **glob, char *url, unsigned long *urlnum,
FILE *error)
{
/*
@@ -424,6 +438,7 @@ CURLcode glob_url(URLGlob** glob, char* url, unsigned long *urlnum,
glob_buffer = malloc(strlen(url) + 1);
if(!glob_buffer)
return CURLE_OUT_OF_MEMORY;
+ glob_buffer[0]=0;
glob_expand = calloc(1, sizeof(URLGlob));
if(!glob_expand) {
@@ -541,20 +556,25 @@ CURLcode glob_next_url(char **globbed, URLGlob *glob)
switch(pat->type) {
case UPTSet:
if(pat->content.Set.elements) {
- len = strlen(pat->content.Set.elements[pat->content.Set.ptr_s]);
snprintf(buf, buflen, "%s",
pat->content.Set.elements[pat->content.Set.ptr_s]);
+ len = strlen(buf);
buf += len;
buflen -= len;
}
break;
case UPTCharRange:
- *buf++ = pat->content.CharRange.ptr_c;
+ if(buflen) {
+ *buf++ = pat->content.CharRange.ptr_c;
+ *buf = '\0';
+ buflen--;
+ }
break;
case UPTNumRange:
- len = snprintf(buf, buflen, "%0*ld",
- pat->content.NumRange.padlength,
- pat->content.NumRange.ptr_n);
+ snprintf(buf, buflen, "%0*ld",
+ pat->content.NumRange.padlength,
+ pat->content.NumRange.ptr_n);
+ len = strlen(buf);
buf += len;
buflen -= len;
break;
@@ -563,7 +583,6 @@ CURLcode glob_next_url(char **globbed, URLGlob *glob)
return CURLE_FAILED_INIT;
}
}
- *buf = '\0';
*globbed = strdup(glob->glob_buffer);
if(!*globbed)
diff --git a/src/tool_urlglob.h b/src/tool_urlglob.h
index c3be948f..82d9d46d 100644
--- a/src/tool_urlglob.h
+++ b/src/tool_urlglob.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -68,9 +68,9 @@ typedef struct {
size_t pos; /* column position of error or 0 */
} URLGlob;
-CURLcode glob_url(URLGlob**, char*, unsigned long *, FILE *);
+CURLcode glob_url(URLGlob**, char *, unsigned long *, FILE *);
CURLcode glob_next_url(char **, URLGlob *);
-CURLcode glob_match_url(char **, char*, URLGlob *);
+CURLcode glob_match_url(char **, char *, URLGlob *);
void glob_cleanup(URLGlob* glob);
#endif /* HEADER_CURL_TOOL_URLGLOB_H */
diff --git a/src/tool_writeenv.c b/src/tool_writeenv.c
index c1bfcbe2..198847ee 100644
--- a/src/tool_writeenv.c
+++ b/src/tool_writeenv.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,7 +33,7 @@
static const struct
{
- const char * name;
+ const char *name;
CURLINFO id;
enum {
writeenv_NONE,
@@ -59,7 +59,7 @@ static const struct
{NULL, 0, writeenv_NONE}
};
-static void internalSetEnv(const char * name, char * value)
+static void internalSetEnv(const char *name, char *value)
{
/* Add your OS-specific code here. */
#ifdef __riscos__
diff --git a/src/tool_writeout.c b/src/tool_writeout.c
index 6e94afe4..3737df80 100644
--- a/src/tool_writeout.c
+++ b/src/tool_writeout.c
@@ -52,12 +52,14 @@ typedef enum {
VAR_FTP_ENTRY_PATH,
VAR_REDIRECT_URL,
VAR_SSL_VERIFY_RESULT,
+ VAR_PROXY_SSL_VERIFY_RESULT,
VAR_EFFECTIVE_FILENAME,
VAR_PRIMARY_IP,
VAR_PRIMARY_PORT,
VAR_LOCAL_IP,
VAR_LOCAL_PORT,
VAR_HTTP_VERSION,
+ VAR_SCHEME,
VAR_NUM_OF_VARS /* must be the last */
} replaceid;
@@ -91,12 +93,14 @@ static const struct variable replacements[]={
{"ftp_entry_path", VAR_FTP_ENTRY_PATH},
{"redirect_url", VAR_REDIRECT_URL},
{"ssl_verify_result", VAR_SSL_VERIFY_RESULT},
+ {"proxy_ssl_verify_result", VAR_PROXY_SSL_VERIFY_RESULT},
{"filename_effective", VAR_EFFECTIVE_FILENAME},
{"remote_ip", VAR_PRIMARY_IP},
{"remote_port", VAR_PRIMARY_PORT},
{"local_ip", VAR_LOCAL_IP},
{"local_port", VAR_LOCAL_PORT},
{"http_version", VAR_HTTP_VERSION},
+ {"scheme", VAR_SCHEME},
{NULL, VAR_NONE}
};
@@ -170,41 +174,41 @@ void ourWriteOut(CURL *curl, struct OutStruct *outs, const char *writeinfo)
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME,
&doubleinfo))
- fprintf(stream, "%.3f", doubleinfo);
+ fprintf(stream, "%.6f", doubleinfo);
break;
case VAR_TOTAL_TIME:
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &doubleinfo))
- fprintf(stream, "%.3f", doubleinfo);
+ fprintf(stream, "%.6f", doubleinfo);
break;
case VAR_NAMELOOKUP_TIME:
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME,
&doubleinfo))
- fprintf(stream, "%.3f", doubleinfo);
+ fprintf(stream, "%.6f", doubleinfo);
break;
case VAR_CONNECT_TIME:
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &doubleinfo))
- fprintf(stream, "%.3f", doubleinfo);
+ fprintf(stream, "%.6f", doubleinfo);
break;
case VAR_APPCONNECT_TIME:
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME,
&doubleinfo))
- fprintf(stream, "%.3f", doubleinfo);
+ fprintf(stream, "%.6f", doubleinfo);
break;
case VAR_PRETRANSFER_TIME:
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME,
&doubleinfo))
- fprintf(stream, "%.3f", doubleinfo);
+ fprintf(stream, "%.6f", doubleinfo);
break;
case VAR_STARTTRANSFER_TIME:
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME,
&doubleinfo))
- fprintf(stream, "%.3f", doubleinfo);
+ fprintf(stream, "%.6f", doubleinfo);
break;
case VAR_SIZE_UPLOAD:
if(CURLE_OK ==
@@ -252,6 +256,12 @@ void ourWriteOut(CURL *curl, struct OutStruct *outs, const char *writeinfo)
&longinfo))
fprintf(stream, "%ld", longinfo);
break;
+ case VAR_PROXY_SSL_VERIFY_RESULT:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_PROXY_SSL_VERIFYRESULT,
+ &longinfo))
+ fprintf(stream, "%ld", longinfo);
+ break;
case VAR_EFFECTIVE_FILENAME:
if(outs->filename)
fprintf(stream, "%s", outs->filename);
@@ -300,6 +310,12 @@ void ourWriteOut(CURL *curl, struct OutStruct *outs, const char *writeinfo)
fprintf(stream, version);
}
break;
+ case VAR_SCHEME:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_SCHEME,
+ &stringp))
+ fprintf(stream, "%s", stringp);
+ break;
default:
break;
}
diff --git a/tests/README b/tests/README
index ae8ff25c..8f52688c 100644
--- a/tests/README
+++ b/tests/README
@@ -4,7 +4,7 @@
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
-The cURL Test Suite
+The curl Test Suite
1. Running
1.1 Requires to run
@@ -43,6 +43,7 @@ The cURL Test Suite
diff (when a test fails, a diff is shown)
stunnel (for HTTPS and FTPS tests)
OpenSSH or SunSSH (for SCP, SFTP and SOCKS4/5 tests)
+ nghttpx (for HTTP/2 tests)
1.2 Port numbers used by test servers
@@ -163,7 +164,7 @@ The cURL Test Suite
1.8 Logs
- All logs are generated in the logs/ subdirectory (it is emptied first in the
+ All logs are generated in the log/ subdirectory (it is emptied first in the
runtests.pl script). Use runtests.pl -k to force it to keep the temporary
files after the test run since successful runs will clean it up otherwise.
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 9c50673c..b8b18e5d 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -44,7 +44,7 @@ test181 test182 test183 test184 test185 test186 test187 test188 test189 \
test190 test191 test192 test193 test194 test195 test196 test197 test198 \
test199 test200 test201 test202 test203 test204 test205 test206 test207 \
test208 test209 test210 test211 test212 test213 test214 test215 test216 \
-test217 test218 test220 test221 test222 test223 test224 test225 \
+test217 test218 test219 test220 test221 test222 test223 test224 test225 \
test226 test227 test228 test229 test231 test233 test234 \
test235 test236 test237 test238 test239 test240 test241 test242 test243 \
test245 test246 test247 test248 test249 test250 test251 test252 \
@@ -120,14 +120,16 @@ test1112 test1113 test1114 test1115 test1116 test1117 test1118 test1119 \
test1120 test1121 test1122 test1123 test1124 test1125 test1126 test1127 \
test1128 test1129 test1130 test1131 test1132 test1133 test1134 test1135 \
test1136 test1137 test1138 test1139 test1140 test1141 test1142 test1143 \
-\
+test1144 \
test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
test1216 test1217 test1218 test1219 \
test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 \
test1228 test1229 test1230 test1231 test1232 test1233 test1234 test1235 \
test1236 test1237 test1238 test1239 test1240 test1241 test1242 test1243 \
-test1244 \
+test1244 test1245 test1246 test1247 \
+\
+test1280 \
\
test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 \
test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \
@@ -156,9 +158,10 @@ test1516 test1517 \
\
test1520 \
\
-test1525 test1526 test1527 test1528 test1529 test1530 test1531 \
+test1525 test1526 test1527 test1528 test1529 test1530 test1531 test1532 \
+test1533 test1534 \
\
-test1600 test1601 test1602 test1603 test1604 \
+test1600 test1601 test1602 test1603 test1604 test1605 \
\
test1700 test1701 test1702 \
\
diff --git a/tests/data/test1001 b/tests/data/test1001
index 60e68a89..91b13203 100644
--- a/tests/data/test1001
+++ b/tests/data/test1001
@@ -89,6 +89,7 @@ Host: %HOSTIP:%HTTPPORT
Content-Range: bytes 2-4/5
User-Agent: curl/7.12.1-CVS (i686-pc-linux-gnu) libcurl/7.12.1-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.6
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 0
GET http://%HOSTIP:%HTTPPORT/1001 HTTP/1.1
@@ -96,6 +97,7 @@ Host: %HOSTIP:%HTTPPORT
Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", uri="/1001", response="6af4d89c952f4dd4cc215a6878dc499d"
Content-Range: bytes 2-4/5
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 3
Expect: 100-continue
diff --git a/tests/data/test1002 b/tests/data/test1002
index 83b87b9e..83cce6e4 100644
--- a/tests/data/test1002
+++ b/tests/data/test1002
@@ -88,6 +88,7 @@ Host: %HOSTIP:%HTTPPORT
Content-Range: bytes 2-4/5
User-Agent: curl/7.12.1-CVS (i686-pc-linux-gnu) libcurl/7.12.1-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.6
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 0
GET http://%HOSTIP:%HTTPPORT/1002.upload1 HTTP/1.1
@@ -95,6 +96,7 @@ Host: %HOSTIP:%HTTPPORT
Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", uri="/1002.upload1", response="198aa9b6acb4b0c71d02a197a5e41f54"
Content-Range: bytes 2-4/5
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 3
Expect: 100-continue
@@ -105,6 +107,7 @@ Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", u
Content-Range: bytes 2-4/5
User-Agent: curl/7.16.1
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 3
Expect: 100-continue
diff --git a/tests/data/test1008 b/tests/data/test1008
index 1dac3956..bcc503e5 100644
--- a/tests/data/test1008
+++ b/tests/data/test1008
@@ -114,10 +114,12 @@ chkhostname curlhost
CONNECT test.remote.example.com.1008:%HTTPPORT HTTP/1.1
Host: test.remote.example.com.1008:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
+Proxy-Connection: Keep-Alive
CONNECT test.remote.example.com.1008:%HTTPPORT HTTP/1.1
Host: test.remote.example.com.1008:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAACeAJ4AWAAAAAAAAAD2AAAACAAIAPYAAAAIAAgA/gAAAAAAAAAAAAAABoKBAL9LNW5+nkyHZRmyFaL/LJ4xMjM0MjIzNGUCyhgQ9hw6eWAT13EbDa0BAQAAAAAAAACAPtXesZ0BMTIzNDIyMzQAAAAAAgAEAEMAQwABABIARQBMAEkAUwBBAEIARQBUAEgABAAYAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAMALABlAGwAaQBzAGEAYgBlAHQAaAAuAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAAAAAAAAAAAdGVzdHVzZXJjdXJsaG9zdA==
+Proxy-Connection: Keep-Alive
GET /path/10080002 HTTP/1.1
User-Agent: curl/7.12.3-CVS (i686-pc-linux-gnu) libcurl/7.12.3-CVS OpenSSL/0.9.6b zlib/1.1.4
diff --git a/tests/data/test1021 b/tests/data/test1021
index 3bd64bdd..3ac9e12e 100644
--- a/tests/data/test1021
+++ b/tests/data/test1021
@@ -119,14 +119,17 @@ chkhostname curlhost
<protocol>
CONNECT test.remote.example.com.1021:%HTTPPORT HTTP/1.1
Host: test.remote.example.com.1021:%HTTPPORT
+Proxy-Connection: Keep-Alive
CONNECT test.remote.example.com.1021:%HTTPPORT HTTP/1.1
Host: test.remote.example.com.1021:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
+Proxy-Connection: Keep-Alive
CONNECT test.remote.example.com.1021:%HTTPPORT HTTP/1.1
Host: test.remote.example.com.1021:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAACeAJ4AWAAAAAAAAAD2AAAACAAIAPYAAAAIAAgA/gAAAAAAAAAAAAAABoKBAL9LNW5+nkyHZRmyFaL/LJ4xMjM0MjIzNGUCyhgQ9hw6eWAT13EbDa0BAQAAAAAAAACAPtXesZ0BMTIzNDIyMzQAAAAAAgAEAEMAQwABABIARQBMAEkAUwBBAEIARQBUAEgABAAYAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAMALABlAGwAaQBzAGEAYgBlAHQAaAAuAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAAAAAAAAAAAdGVzdHVzZXJjdXJsaG9zdA==
+Proxy-Connection: Keep-Alive
GET /path/10210002 HTTP/1.1
User-Agent: curl/7.12.3-CVS (i686-pc-linux-gnu) libcurl/7.12.3-CVS OpenSSL/0.9.6b zlib/1.1.4
diff --git a/tests/data/test1034 b/tests/data/test1034
index f1426849..c4757405 100644
--- a/tests/data/test1034
+++ b/tests/data/test1034
@@ -55,6 +55,7 @@ http://invalid-utf8-â.local/page/1034 -x %HOSTIP:%HTTPPORT
GET http://invalid-utf8-â.local/page/1034 HTTP/1.1
Host: invalid-utf8-â.local
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1035 b/tests/data/test1035
index e1c2af63..20b434c3 100644
--- a/tests/data/test1035
+++ b/tests/data/test1035
@@ -52,6 +52,7 @@ http://too-long-IDN-name-cürl-rüles-la-la-la-dee-da-flooby-nooby.local/page/1035
GET http://too-long-IDN-name-cürl-rüles-la-la-la-dee-da-flooby-nooby.local/page/1035 HTTP/1.1
Host: too-long-IDN-name-cürl-rüles-la-la-la-dee-da-flooby-nooby.local
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1059 b/tests/data/test1059
index ee4e6a78..6820ea67 100644
--- a/tests/data/test1059
+++ b/tests/data/test1059
@@ -51,6 +51,7 @@ ftp://test-number:1059/wanted/page -p -x %HOSTIP:%HTTPPORT
<protocol>
CONNECT test-number:1059 HTTP/1.1
Host: test-number:1059
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1060 b/tests/data/test1060
index 1094792a..e4aea658 100644
--- a/tests/data/test1060
+++ b/tests/data/test1060
@@ -887,10 +887,12 @@ http://test.remote.haxx.se.1060:8990/path/10600002 --proxy http://%HOSTIP:%HTTPP
<protocol>
CONNECT test.remote.haxx.se.1060:8990 HTTP/1.1
Host: test.remote.haxx.se.1060:8990
+Proxy-Connection: Keep-Alive
CONNECT test.remote.haxx.se.1060:8990 HTTP/1.1
Host: test.remote.haxx.se.1060:8990
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.haxx.se.1060:8990", response="e1fbed39c26f4efe284adc0e576ff638"
+Proxy-Connection: Keep-Alive
GET /path/10600002 HTTP/1.1
Host: test.remote.haxx.se.1060:8990
diff --git a/tests/data/test1061 b/tests/data/test1061
index 4f53a87a..a55a2729 100644
--- a/tests/data/test1061
+++ b/tests/data/test1061
@@ -892,10 +892,12 @@ http://test.remote.haxx.se.1061:8990/path/10610002 --proxy http://%HOSTIP:%HTTPP
<protocol>
CONNECT test.remote.haxx.se.1061:8990 HTTP/1.1
Host: test.remote.haxx.se.1061:8990
+Proxy-Connection: Keep-Alive
CONNECT test.remote.haxx.se.1061:8990 HTTP/1.1
Host: test.remote.haxx.se.1061:8990
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.haxx.se.1061:8990", response="4e23449fa93224834299e7282a70472c"
+Proxy-Connection: Keep-Alive
GET /path/10610002 HTTP/1.1
Host: test.remote.haxx.se.1061:8990
diff --git a/tests/data/test1077 b/tests/data/test1077
index e71d7569..a3c90245 100644
--- a/tests/data/test1077
+++ b/tests/data/test1077
@@ -30,6 +30,7 @@ Server: test-server/fake
Content-Type: text/plain
Content-Length: 9
Funny-head: yesyes
+Proxy-Connection: Keep-Alive
contents
</data2>
@@ -62,10 +63,12 @@ FTP over HTTP proxy with downgrade to HTTP 1.0
GET ftp://%HOSTIP:%HTTPPORT/we/want/that/page/1077 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
+Proxy-Connection: Keep-Alive
GET ftp://%HOSTIP:%HTTPPORT/we/want/that/page/10770002 HTTP/1.0
Host: %HOSTIP:%HTTPPORT
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1078 b/tests/data/test1078
index f04bad36..a9bb771b 100644
--- a/tests/data/test1078
+++ b/tests/data/test1078
@@ -56,6 +56,7 @@ HTTP 1.0 CONNECT with proxytunnel and downgrade GET to HTTP/1.0
<proxy>
CONNECT %HOSTIP.1078:%HTTPPORT HTTP/1.0
Host: %HOSTIP.1078:%HTTPPORT
+Proxy-Connection: Keep-Alive
</proxy>
<protocol>
diff --git a/tests/data/test1087 b/tests/data/test1087
index 1fb13cbe..d228976a 100644
--- a/tests/data/test1087
+++ b/tests/data/test1087
@@ -92,15 +92,18 @@ http://first.host.it.is/we/want/that/page/10871000 -x %HOSTIP:%HTTPPORT --user i
GET http://first.host.it.is/we/want/that/page/10871000 HTTP/1.1
Host: first.host.it.is
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://first.host.it.is/we/want/that/page/10871000 HTTP/1.1
Host: first.host.it.is
Authorization: Basic aWFtOm15c2VsZg==
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://goto.second.host.now/10871002 HTTP/1.1
Host: goto.second.host.now
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1088 b/tests/data/test1088
index 9801fff1..a807ce9e 100644
--- a/tests/data/test1088
+++ b/tests/data/test1088
@@ -93,16 +93,19 @@ http://first.host.it.is/we/want/that/page/10881000 -x %HOSTIP:%HTTPPORT --user i
GET http://first.host.it.is/we/want/that/page/10881000 HTTP/1.1
Host: first.host.it.is
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://first.host.it.is/we/want/that/page/10881000 HTTP/1.1
Host: first.host.it.is
Authorization: Basic aWFtOm15c2VsZg==
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://goto.second.host.now/10881002 HTTP/1.1
Host: goto.second.host.now
Authorization: Basic aWFtOm15c2VsZg==
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1092 b/tests/data/test1092
index ce843f00..adef4320 100644
--- a/tests/data/test1092
+++ b/tests/data/test1092
@@ -49,6 +49,7 @@ FTP with type=i over HTTP proxy
GET ftp://%HOSTIP:%HTTPPORT/we/want/that/page/1092;type=i HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1097 b/tests/data/test1097
index 81ea8552..3b733a55 100644
--- a/tests/data/test1097
+++ b/tests/data/test1097
@@ -67,6 +67,7 @@ CONNECT test.a.galaxy.far.far.away.1097:%HTTPPORT HTTP/1.1
Host: test.a.galaxy.far.far.away.1097:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
User-Agent: curl/7.19.5-CVS (i686-pc-linux-gnu) libcurl/7.19.5-CVS OpenSSL/0.9.8g zlib/1.2.3.3 c-ares/1.6.1-CVS libidn/1.12 libssh2/1.0.1_CVS
+Proxy-Connection: Keep-Alive
POST /1097 HTTP/1.1
User-Agent: curl/7.19.5-CVS (i686-pc-linux-gnu) libcurl/7.19.5-CVS OpenSSL/0.9.8g zlib/1.2.3.3 c-ares/1.6.1-CVS libidn/1.12 libssh2/1.0.1_CVS
diff --git a/tests/data/test1098 b/tests/data/test1098
index 70a6f391..98056481 100644
--- a/tests/data/test1098
+++ b/tests/data/test1098
@@ -49,10 +49,12 @@ ftp://ftp-site/moo/1098 ftp://ftp-site/moo/1098 --proxy http://%HOSTIP:%HTTPPORT
GET ftp://ftp-site/moo/1098 HTTP/1.1
Host: ftp-site:21
Accept: */*
+Proxy-Connection: Keep-Alive
GET ftp://ftp-site/moo/1098 HTTP/1.1
Host: ftp-site:21
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
<stdout>
diff --git a/tests/data/test1104 b/tests/data/test1104
index 4df81a1a..21efe3c1 100644
--- a/tests/data/test1104
+++ b/tests/data/test1104
@@ -72,10 +72,12 @@ http://%HOSTIP:%HTTPPORT/want/1104 -L -x %HOSTIP:%HTTPPORT -c log/cookies.jar
GET http://%HOSTIP:%HTTPPORT/want/1104 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://%HOSTIP:%HTTPPORT/want/data/11040002 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
+Proxy-Connection: Keep-Alive
Cookie: test2=true
</protocol>
diff --git a/tests/data/test1106 b/tests/data/test1106
index a2adbbb3..0c6bec17 100644
--- a/tests/data/test1106
+++ b/tests/data/test1106
@@ -50,6 +50,7 @@ ftp://%HOSTIP:23456/1106
GET ftp://%HOSTIP:23456/1106 HTTP/1.1
Host: %HOSTIP:23456
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1135 b/tests/data/test1135
index 960aade8..f7c6a7ae 100644
--- a/tests/data/test1135
+++ b/tests/data/test1135
@@ -58,7 +58,7 @@ CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
CURL_EXTERN void curl_easy_cleanup(CURL *curl);
CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
-CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl);
+CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl);
CURL_EXTERN void curl_easy_reset(CURL *curl);
CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
diff --git a/tests/data/test1141 b/tests/data/test1141
index b0ff038c..9c41d393 100644
--- a/tests/data/test1141
+++ b/tests/data/test1141
@@ -58,10 +58,12 @@ HTTP redirect to http:/// (three slashes!)
GET http://%HOSTIP:%HTTPPORT/want/1141 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://foo.example.com/want/11410001 HTTP/1.1
Host: foo.example.com
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1142 b/tests/data/test1142
index 0ecfbd3c..76c6bdf5 100644
--- a/tests/data/test1142
+++ b/tests/data/test1142
@@ -53,6 +53,7 @@ HTTP redirect to http://// (four slashes!)
GET http://%HOSTIP:%HTTPPORT/want/1142 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
# 3, CURLE_URL_MALFORMAT for the four slashes
diff --git a/tests/data/test1144 b/tests/data/test1144
new file mode 100644
index 00000000..3fb90936
--- /dev/null
+++ b/tests/data/test1144
@@ -0,0 +1,69 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP HEAD
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+No headers at all, just data swsclose
+
+Let's get
+
+a little
+
+so that
+
+we
+
+have
+
+some
+
+test
+
+data to
+
+verify
+</data>
+# make sure no data is written
+<datacheck nonewline="yes">
+
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP HEAD, receive no headers only body
+ </name>
+ <command>
+-I http://%HOSTIP:%HTTPPORT/1144
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+HEAD /1144 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+<errorcode>
+8
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test1213 b/tests/data/test1213
index bc146b01..4f22f0d9 100644
--- a/tests/data/test1213
+++ b/tests/data/test1213
@@ -46,6 +46,7 @@ HTTP with proxy and host-only URL
GET http://we.want.that.site.com.1213/ HTTP/1.1
Host: we.want.that.site.com.1213
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1214 b/tests/data/test1214
index e703f7a9..3eeb3e3a 100644
--- a/tests/data/test1214
+++ b/tests/data/test1214
@@ -46,6 +46,7 @@ HTTP with proxy and URL with ? and no slash separator
GET http://we.want.that.site.com.1214/?moo=foo HTTP/1.1
Host: we.want.that.site.com.1214
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1215 b/tests/data/test1215
index e22591c9..f8c52a9a 100644
--- a/tests/data/test1215
+++ b/tests/data/test1215
@@ -92,12 +92,14 @@ Host: %HOSTIP:%HTTPPORT
Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
User-Agent: curl/7.30.0-DEV
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://%HOSTIP:%HTTPPORT/1215 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAACeAJ4AWAAAAAAAAAD2AAAACAAIAPYAAAAIAAgA/gAAAAAAAAAAAAAABoKBAL9LNW5+nkyHZRmyFaL/LJ4xMjM0MjIzNGUCyhgQ9hw6eWAT13EbDa0BAQAAAAAAAACAPtXesZ0BMTIzNDIyMzQAAAAAAgAEAEMAQwABABIARQBMAEkAUwBBAEIARQBUAEgABAAYAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAMALABlAGwAaQBzAGEAYgBlAHQAaAAuAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAAAAAAAAAAAdGVzdHVzZXJjdXJsaG9zdA==
User-Agent: curl/7.30.0-DEV
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1216 b/tests/data/test1216
index 6e45ac6a..5beda797 100644
--- a/tests/data/test1216
+++ b/tests/data/test1216
@@ -50,11 +50,13 @@ example.fake TRUE /c FALSE 2139150993 moo3 indeed
GET http://example.fake/c/1216 HTTP/1.1
Host: example.fake
Accept: */*
+Proxy-Connection: Keep-Alive
Cookie: moo2=indeed; moo3=indeed
GET http://bexample.fake/c/1216 HTTP/1.1
Host: bexample.fake
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1218 b/tests/data/test1218
index 9c2fc038..e3f1f6d0 100644
--- a/tests/data/test1218
+++ b/tests/data/test1218
@@ -43,15 +43,18 @@ http://example.fake/c/1218 http://example.fake/c/1218 http://bexample.fake/c/121
GET http://example.fake/c/1218 HTTP/1.1
Host: example.fake
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://example.fake/c/1218 HTTP/1.1
Host: example.fake
Accept: */*
+Proxy-Connection: Keep-Alive
Cookie: bug=fixed
GET http://bexample.fake/c/1218 HTTP/1.1
Host: bexample.fake
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1228 b/tests/data/test1228
index d0af517d..a7e56a79 100644
--- a/tests/data/test1228
+++ b/tests/data/test1228
@@ -42,10 +42,12 @@ http://example.fake/hoge/1228 http://example.fake/hogege/ -b nonexisting -x %HOS
GET http://example.fake/hoge/1228 HTTP/1.1
Host: example.fake
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://example.fake/hogege/ HTTP/1.1
Host: example.fake
Accept: */*
+Proxy-Connection: Keep-Alive
Cookie: path1=root
</protocol>
diff --git a/tests/data/test1230 b/tests/data/test1230
index 8ce4c4ee..3c1d3d44 100644
--- a/tests/data/test1230
+++ b/tests/data/test1230
@@ -69,6 +69,7 @@ http://[1234:1234:1234::4ce]:%HTTPPORT/wanted/page/1230 -p -x %HOSTIP:%HTTPPORT
<protocol>
CONNECT [1234:1234:1234::4ce]:%HTTPPORT HTTP/1.1
Host: [1234:1234:1234::4ce]:%HTTPPORT
+Proxy-Connection: Keep-Alive
GET /wanted/page/1230 HTTP/1.1
Host: [1234:1234:1234::4ce]:%HTTPPORT
diff --git a/tests/data/test1232 b/tests/data/test1232
index 1c5bc203..ead43365 100644
--- a/tests/data/test1232
+++ b/tests/data/test1232
@@ -53,10 +53,12 @@ HTTP URL with dotdot removal from path using an HTTP proxy
GET http://test.remote.haxx.se.1232:8990/hej/but/1232?stupid=me/../1232 HTTP/1.1
Host: test.remote.haxx.se.1232:8990
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://test.remote.haxx.se.1232:8990/hej/but/12320001 HTTP/1.1
Host: test.remote.haxx.se.1232:8990
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1241 b/tests/data/test1241
index 5a127326..aaa56886 100644
--- a/tests/data/test1241
+++ b/tests/data/test1241
@@ -52,10 +52,12 @@ HTTP _without_ dotdot removal
GET http://test.remote.haxx.se.1241:8990/../../hej/but/who/../1241?stupid=me/../1241 HTTP/1.1
Host: test.remote.haxx.se.1241:8990
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://test.remote.haxx.se.1241:8990/../../hej/but/who/../12410001 HTTP/1.1
Host: test.remote.haxx.se.1241:8990
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1244 b/tests/data/test1244
index 7912b4ef..d0769ad8 100644
--- a/tests/data/test1244
+++ b/tests/data/test1244
@@ -54,6 +54,7 @@ http://%HOSTIP:%HTTPPORT/1244 -x %HOSTIP:%HTTPPORT --next http://%HOSTIP:%HTTPPO
GET http://%HOSTIP:%HTTPPORT/1244 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1245 b/tests/data/test1245
new file mode 100644
index 00000000..34d6549d
--- /dev/null
+++ b/tests/data/test1245
@@ -0,0 +1,63 @@
+<testcase>
+<info>
+<keywords>
+FTP
+HTTP
+HTTP GET
+--proto
+--proto-redir
+followlocation
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 301 OK swsclose
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+Location: ftp://127.0.0.1:8992/1245
+Connection: close
+
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+ftp
+http
+</server>
+<name>
+--proto deny must override --proto-redir allow
+</name>
+<command>
+--location --proto +all,-ftp --proto-redir -all,+ftp http://%HOSTIP:%HTTPPORT/1245
+</command>
+# The data section doesn't do variable substitution, so we must assert this
+<precheck>
+perl -e "print 'Test requires default test server host and port' if ( '%HOSTIP' ne '127.0.0.1' || '%FTPPORT' ne '8992' );"
+</precheck>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /1245 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+# 1 - Protocol ftp not supported or disabled in libcurl
+<errorcode>
+1
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test1246 b/tests/data/test1246
new file mode 100644
index 00000000..65659292
--- /dev/null
+++ b/tests/data/test1246
@@ -0,0 +1,64 @@
+<testcase>
+<info>
+# verify URL with hostname ending in pound sign
+<keywords>
+HTTP
+HTTP GET
+HTTP proxy
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Content-Length: 6
+Connection: close
+
+-foo-
+</data>
+
+<data1>
+HTTP/1.1 200 OK
+Content-Length: 7
+Connection: close
+
+-cool-
+</data1>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+URL with '#' at end of host name instead of '/'
+ </name>
+ <command>
+--proxy http://%HOSTIP:%HTTPPORT http://test.remote.haxx.se.1246:%HTTPPORT#@127.0.0.1/tricked.html no-scheme-url.com.1246:%HTTPPORT#@127.127.127.127/again.html
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET http://test.remote.haxx.se.1246:%HTTPPORT/ HTTP/1.1
+Host: test.remote.haxx.se.1246:%HTTPPORT
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+GET http://no-scheme-url.com.1246:%HTTPPORT/ HTTP/1.1
+Host: no-scheme-url.com.1246:%HTTPPORT
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1247 b/tests/data/test1247
new file mode 100644
index 00000000..48c5ccdf
--- /dev/null
+++ b/tests/data/test1247
@@ -0,0 +1,38 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+--fail-early
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+ <name>
+--fail-early
+ </name>
+ <command>
+--fail-early h1234://%HOSTIP:%HTTPPORT/1247 http://%HOSTIP:%HTTPPORT/1247
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# Protocol "h1234" not supported or disabled in libcurl
+<errorcode>
+1
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test1280 b/tests/data/test1280
new file mode 100644
index 00000000..15c1e2fd
--- /dev/null
+++ b/tests/data/test1280
@@ -0,0 +1,58 @@
+<testcase>
+<info>
+<keywords>
+globbing
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Content-Length: 6
+Connection: close
+
+bytes
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+simple [a-d] globbing
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/[a-d]/1280
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /a/1280 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+GET /b/1280 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+GET /c/1280 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+GET /d/1280 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1301 b/tests/data/test1301
index 4b6fac8b..8506c000 100644
--- a/tests/data/test1301
+++ b/tests/data/test1301
@@ -2,7 +2,7 @@
<info>
<keywords>
unittest
-curl_strequal
+curl_strcasecompare
</keywords>
</info>
@@ -16,7 +16,7 @@ none
unittest
</features>
<name>
-curl_strequal unit tests
+curl_strcasecompare unit tests
</name>
<tool>
unit1301
diff --git a/tests/data/test1314 b/tests/data/test1314
index 11e128a8..078ada64 100644
--- a/tests/data/test1314
+++ b/tests/data/test1314
@@ -67,10 +67,12 @@ http://firstplace.example.com/want/1314 -L -x http://%HOSTIP:%HTTPPORT
GET http://firstplace.example.com/want/1314 HTTP/1.1
Host: firstplace.example.com
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://somewhere.example.com/reply/1314 HTTP/1.1
Host: somewhere.example.com
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1319 b/tests/data/test1319
index a97da9c4..0520b1b3 100644
--- a/tests/data/test1319
+++ b/tests/data/test1319
@@ -79,6 +79,7 @@ QUIT
CONNECT pop.1319:%POP3PORT HTTP/1.1
Host: pop.1319:%POP3PORT
User-Agent: curl/7.24.0-DEV (i686-pc-linux-gnu) libcurl/7.24.0-DEV OpenSSL/1.0.0e zlib/1.2.3.4 c-ares/1.7.6-DEV libidn/1.23 libssh2/1.4.0_DEV librtmp/2.2e
+Proxy-Connection: Keep-Alive
</proxy>
</verify>
diff --git a/tests/data/test1320 b/tests/data/test1320
index 609f4c2f..7a15f809 100644
--- a/tests/data/test1320
+++ b/tests/data/test1320
@@ -66,6 +66,7 @@ body
CONNECT smtp.1320:%SMTPPORT HTTP/1.1
Host: smtp.1320:%SMTPPORT
User-Agent: curl/7.24.0-DEV (i686-pc-linux-gnu) libcurl/7.24.0-DEV OpenSSL/1.0.0e zlib/1.2.3.4 c-ares/1.7.6-DEV libidn/1.23 libssh2/1.4.0_DEV librtmp/2.2e
+Proxy-Connection: Keep-Alive
</proxy>
</verify>
diff --git a/tests/data/test1321 b/tests/data/test1321
index b5ad277b..266fd882 100644
--- a/tests/data/test1321
+++ b/tests/data/test1321
@@ -75,6 +75,7 @@ A005 LOGOUT
CONNECT imap.1321:%IMAPPORT HTTP/1.1
Host: imap.1321:%IMAPPORT
User-Agent: curl/7.24.0-DEV (i686-pc-linux-gnu) libcurl/7.24.0-DEV OpenSSL/1.0.0e zlib/1.2.3.4 c-ares/1.7.6-DEV libidn/1.23 libssh2/1.4.0_DEV librtmp/2.2e
+Proxy-Connection: Keep-Alive
</proxy>
</verify>
diff --git a/tests/data/test1331 b/tests/data/test1331
index 837ef8dd..3299df46 100644
--- a/tests/data/test1331
+++ b/tests/data/test1331
@@ -75,11 +75,13 @@ HTTP --proxy-anyauth and 407 with cookies
GET http://z.x.com/1331 HTTP/1.1
Host: z.x.com
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://z.x.com/1331 HTTP/1.1
Host: z.x.com
Proxy-Authorization: Basic bXluYW1lOm15cGFzc3dvcmQ=
Accept: */*
+Proxy-Connection: Keep-Alive
Cookie: proxycookie=weirdo
</protocol>
diff --git a/tests/data/test1400 b/tests/data/test1400
index 0ee73702..838fe638 100644
--- a/tests/data/test1400
+++ b/tests/data/test1400
@@ -77,6 +77,7 @@ int main(int argc, char *argv[])
them yourself.
CURLOPT_WRITEDATA set to a objectpointer
+ CURLOPT_INTERLEAVEDATA set to a objectpointer
CURLOPT_WRITEFUNCTION set to a functionpointer
CURLOPT_READDATA set to a objectpointer
CURLOPT_READFUNCTION set to a functionpointer
diff --git a/tests/data/test1401 b/tests/data/test1401
index 602b09ac..1e2b4a77 100644
--- a/tests/data/test1401
+++ b/tests/data/test1401
@@ -96,6 +96,7 @@ int main(int argc, char *argv[])
them yourself.
CURLOPT_WRITEDATA set to a objectpointer
+ CURLOPT_INTERLEAVEDATA set to a objectpointer
CURLOPT_WRITEFUNCTION set to a functionpointer
CURLOPT_READDATA set to a objectpointer
CURLOPT_READFUNCTION set to a functionpointer
diff --git a/tests/data/test1402 b/tests/data/test1402
index 0c2199e3..07c3f491 100644
--- a/tests/data/test1402
+++ b/tests/data/test1402
@@ -84,6 +84,7 @@ int main(int argc, char *argv[])
them yourself.
CURLOPT_WRITEDATA set to a objectpointer
+ CURLOPT_INTERLEAVEDATA set to a objectpointer
CURLOPT_WRITEFUNCTION set to a functionpointer
CURLOPT_READDATA set to a objectpointer
CURLOPT_READFUNCTION set to a functionpointer
diff --git a/tests/data/test1403 b/tests/data/test1403
index 98f238f9..18167b4f 100644
--- a/tests/data/test1403
+++ b/tests/data/test1403
@@ -79,6 +79,7 @@ int main(int argc, char *argv[])
them yourself.
CURLOPT_WRITEDATA set to a objectpointer
+ CURLOPT_INTERLEAVEDATA set to a objectpointer
CURLOPT_WRITEFUNCTION set to a functionpointer
CURLOPT_READDATA set to a objectpointer
CURLOPT_READFUNCTION set to a functionpointer
diff --git a/tests/data/test1404 b/tests/data/test1404
index a159e49d..6f53ca8c 100644
--- a/tests/data/test1404
+++ b/tests/data/test1404
@@ -133,6 +133,7 @@ int main(int argc, char *argv[])
them yourself.
CURLOPT_WRITEDATA set to a objectpointer
+ CURLOPT_INTERLEAVEDATA set to a objectpointer
CURLOPT_WRITEFUNCTION set to a functionpointer
CURLOPT_READDATA set to a objectpointer
CURLOPT_READFUNCTION set to a functionpointer
diff --git a/tests/data/test1405 b/tests/data/test1405
index f223954c..4e8d46d7 100644
--- a/tests/data/test1405
+++ b/tests/data/test1405
@@ -93,6 +93,7 @@ int main(int argc, char *argv[])
them yourself.
CURLOPT_WRITEDATA set to a objectpointer
+ CURLOPT_INTERLEAVEDATA set to a objectpointer
CURLOPT_WRITEFUNCTION set to a functionpointer
CURLOPT_READDATA set to a objectpointer
CURLOPT_READFUNCTION set to a functionpointer
diff --git a/tests/data/test1406 b/tests/data/test1406
index c7e4cd41..0ccb08a7 100644
--- a/tests/data/test1406
+++ b/tests/data/test1406
@@ -88,6 +88,7 @@ int main(int argc, char *argv[])
them yourself.
CURLOPT_WRITEDATA set to a objectpointer
+ CURLOPT_INTERLEAVEDATA set to a objectpointer
CURLOPT_WRITEFUNCTION set to a functionpointer
CURLOPT_READDATA set to a objectpointer
CURLOPT_READFUNCTION set to a functionpointer
diff --git a/tests/data/test1407 b/tests/data/test1407
index 8f8cb2aa..981e4e41 100644
--- a/tests/data/test1407
+++ b/tests/data/test1407
@@ -68,6 +68,7 @@ int main(int argc, char *argv[])
them yourself.
CURLOPT_WRITEDATA set to a objectpointer
+ CURLOPT_INTERLEAVEDATA set to a objectpointer
CURLOPT_WRITEFUNCTION set to a functionpointer
CURLOPT_READDATA set to a objectpointer
CURLOPT_READFUNCTION set to a functionpointer
diff --git a/tests/data/test1415 b/tests/data/test1415
index 37cfb073..56044040 100644
--- a/tests/data/test1415
+++ b/tests/data/test1415
@@ -57,6 +57,7 @@ http://example.com/we/want/1415 -b none -c log/jar1415.txt -x %HOSTIP:%HTTPPORT
GET http://example.com/we/want/1415 HTTP/1.1
Host: example.com
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
diff --git a/tests/data/test1420 b/tests/data/test1420
index 7a868062..a20f8986 100644
--- a/tests/data/test1420
+++ b/tests/data/test1420
@@ -73,6 +73,7 @@ int main(int argc, char *argv[])
them yourself.
CURLOPT_WRITEDATA set to a objectpointer
+ CURLOPT_INTERLEAVEDATA set to a objectpointer
CURLOPT_WRITEFUNCTION set to a functionpointer
CURLOPT_READDATA set to a objectpointer
CURLOPT_READFUNCTION set to a functionpointer
diff --git a/tests/data/test1421 b/tests/data/test1421
index 889c938d..6c59b216 100644
--- a/tests/data/test1421
+++ b/tests/data/test1421
@@ -59,10 +59,12 @@ Content-Length: 6
GET http://test.remote.haxx.se.1421:8990/ HTTP/1.1
Host: test.remote.haxx.se.1421:8990
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://different.remote.haxx.se.1421:8990/ HTTP/1.1
Host: different.remote.haxx.se.1421:8990
Accept: */*
+Proxy-Connection: Keep-Alive
[DISCONNECT]
</protocol>
diff --git a/tests/data/test1428 b/tests/data/test1428
index 60fb8a93..59041ec9 100644
--- a/tests/data/test1428
+++ b/tests/data/test1428
@@ -64,6 +64,7 @@ http://test.1428:%HTTPPORT/we/want/that/page/1428 -p -x %HOSTIP:%PROXYPORT --use
CONNECT test.1428:%HTTPPORT HTTP/1.1
Host: test.1428:%HTTPPORT
User-Agent: curl/7.10.7-pre2 (i686-pc-linux-gnu) libcurl/7.10.7-pre2 OpenSSL/0.9.7a zlib/1.1.3
+Proxy-Connection: Keep-Alive
header-type: proxy
</proxy>
diff --git a/tests/data/test1509 b/tests/data/test1509
index 18eb07f1..b4bfc660 100644
--- a/tests/data/test1509
+++ b/tests/data/test1509
@@ -74,6 +74,7 @@ moo
<proxy>
CONNECT the.old.moo.1509:%HTTPPORT HTTP/1.1
Host: the.old.moo.1509:%HTTPPORT
+Proxy-Connection: Keep-Alive
</proxy>
<protocol>
diff --git a/tests/data/test1525 b/tests/data/test1525
index d8f68838..0560d5c1 100644
--- a/tests/data/test1525
+++ b/tests/data/test1525
@@ -58,6 +58,7 @@ CURLOPT_PROXYHEADER is ignored CURLHEADER_UNIFIED
<proxy>
CONNECT the.old.moo.1525:%HTTPPORT HTTP/1.1
Host: the.old.moo.1525:%HTTPPORT
+Proxy-Connection: Keep-Alive
User-Agent: Http Agent
</proxy>
diff --git a/tests/data/test1526 b/tests/data/test1526
index 9f5d09e6..aa111c89 100644
--- a/tests/data/test1526
+++ b/tests/data/test1526
@@ -58,6 +58,7 @@ CURLOPT_PROXYHEADER: separate host/proxy headers
<proxy>
CONNECT the.old.moo.1526:%HTTPPORT HTTP/1.1
Host: the.old.moo.1526:%HTTPPORT
+Proxy-Connection: Keep-Alive
User-Agent: Proxy Agent
</proxy>
diff --git a/tests/data/test1527 b/tests/data/test1527
index 69ae6e4a..e8d52794 100644
--- a/tests/data/test1527
+++ b/tests/data/test1527
@@ -57,6 +57,7 @@ Check same headers are generated with CURLOPT_HEADEROPT == CURLHEADER_UNIFIED
<proxy>
CONNECT the.old.moo.1527:%HTTPPORT HTTP/1.1
Host: the.old.moo.1527:%HTTPPORT
+Proxy-Connection: Keep-Alive
User-Agent: Http Agent
Expect: 100-continue
diff --git a/tests/data/test1528 b/tests/data/test1528
index e60f6002..876806af 100644
--- a/tests/data/test1528
+++ b/tests/data/test1528
@@ -51,6 +51,7 @@ Separately specified proxy/server headers sent in a proxy GET
GET http://the.old.moo:%HTTPPORT/1528 HTTP/1.1
Host: the.old.moo:%HTTPPORT
Accept: */*
+Proxy-Connection: Keep-Alive
User-Agent: Http Agent
Proxy-User-Agent: Http Agent2
diff --git a/tests/data/test1532 b/tests/data/test1532
new file mode 100644
index 00000000..5b2afc71
--- /dev/null
+++ b/tests/data/test1532
@@ -0,0 +1,49 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.0 200 OK swsclose
+Content-Length: 0
+
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# tool is what to use instead of 'curl'
+<tool>
+lib1532
+</tool>
+<name>
+Test CURLINFO_RESPONSE_CODE
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/1532
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /1532 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+<errorcode>
+0
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test1533 b/tests/data/test1533
new file mode 100644
index 00000000..56518161
--- /dev/null
+++ b/tests/data/test1533
@@ -0,0 +1,74 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+CURLOPT_KEEP_SENDING_ON_ERROR
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<servercmd>
+auth_required
+</servercmd>
+<data nocheck="yes">
+HTTP/1.1 401 Authorization Required
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 15
+
+Early Response
+</data>
+</reply>
+# Client-side
+<client>
+<server>
+http
+</server>
+<tool>
+lib1533
+</tool>
+<name>
+HTTP with CURLOPT_KEEP_SENDING_ON_ERROR and an early error response
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/1533
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+# TEST_ERR_SUCCESS is errorcode 120
+<verify>
+<errorcode>
+120
+</errorcode>
+<protocol nonewline="yes">
+POST /1533 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 3
+Content-Type: application/x-www-form-urlencoded
+
+POST /1533 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 3
+Content-Type: application/x-www-form-urlencoded
+
+POST /1533 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 3
+Content-Type: application/x-www-form-urlencoded
+
+aaaPOST /1533 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 3
+Content-Type: application/x-www-form-urlencoded
+
+aaa
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1534 b/tests/data/test1534
new file mode 100644
index 00000000..f3cd2f0e
--- /dev/null
+++ b/tests/data/test1534
@@ -0,0 +1,50 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.0 200 OK swsclose
+Last-Modified: Thu, 01 Jan 1970 00:00:30 GMT
+Content-Length: 0
+
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# tool is what to use instead of 'curl'
+<tool>
+lib1534
+</tool>
+<name>
+Test CURLINFO_RESPONSE_CODE
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/1534
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /1534 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+<errorcode>
+0
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test16 b/tests/data/test16
index 9d9a9cc1..15f4c7a7 100644
--- a/tests/data/test16
+++ b/tests/data/test16
@@ -45,6 +45,7 @@ GET http://we.want.that.site.com/16 HTTP/1.1
Host: we.want.that.site.com
Proxy-Authorization: Basic ZmFrZUB1c2VyOmxvb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29uZw==
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test1605 b/tests/data/test1605
new file mode 100644
index 00000000..09ef6694
--- /dev/null
+++ b/tests/data/test1605
@@ -0,0 +1,25 @@
+<testcase>
+<info>
+<keywords>
+unittest
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+<features>
+unittest
+</features>
+ <name>
+Test negative data lengths as input to libcurl functions
+ </name>
+<tool>
+unit1605
+</tool>
+</client>
+
+</testcase>
diff --git a/tests/data/test161 b/tests/data/test161
index 04583599..91a3388f 100644
--- a/tests/data/test161
+++ b/tests/data/test161
@@ -32,8 +32,8 @@ ftp://%HOSTIP:%FTPPORT/161
# Verify data after the test has been "shot"
<verify>
-# This gets QUIT sent because CURLE_PARTIAL_FILE does NOT mark the control
-# connection as bad
+# This doesn't send QUIT because of known bug:
+# "7.8 Premature transfer end but healthy control channel"
<protocol>
USER anonymous
PASS ftp@example.com
@@ -42,8 +42,8 @@ EPSV
TYPE I
SIZE 161
RETR 161
-QUIT
</protocol>
+# CURLE_PARTIAL_FILE = 18
<errorcode>
18
</errorcode>
diff --git a/tests/data/test162 b/tests/data/test162
index cc4c82d4..ee2f40aa 100644
--- a/tests/data/test162
+++ b/tests/data/test162
@@ -51,6 +51,7 @@ Host: %HOSTIP:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
User-Agent: curl/7.8.1-pre3 (sparc-sun-solaris2.7) libcurl 7.8.1-pre3 (OpenSSL 0.9.6a) (krb4 enabled)
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
<errorcode>
diff --git a/tests/data/test165 b/tests/data/test165
index b475fdef..6fc0ad2d 100644
--- a/tests/data/test165
+++ b/tests/data/test165
@@ -31,13 +31,14 @@ http
idn
</features>
<setenv>
-CHARSET=ISO8859-1
+CHARSET=UTF-8
+LANG=en_US.UTF-8
</setenv>
<name>
HTTP over proxy with IDN host name
</name>
<command>
-http://www.åäö.se/page/165 -x %HOSTIP:%HTTPPORT
+http://www.åäö.se/page/165 -x %HOSTIP:%HTTPPORT http://www.große.de/page/165
</command>
</client>
@@ -51,6 +52,12 @@ http://www.åäö.se/page/165 -x %HOSTIP:%HTTPPORT
GET http://www.xn--4cab6c.se/page/165 HTTP/1.1
Host: www.xn--4cab6c.se
Accept: */*
+Proxy-Connection: Keep-Alive
+
+GET http://www.xn--groe-xna.de/page/165 HTTP/1.1
+Host: www.xn--groe-xna.de
+Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test167 b/tests/data/test167
index 76f9e5c7..0b14996a 100644
--- a/tests/data/test167
+++ b/tests/data/test167
@@ -65,6 +65,7 @@ Host: data.from.server.requiring.digest.hohoho.com
Proxy-Authorization: Basic Zm9vOmJhcg==
User-Agent: curl/7.12.0-CVS (i686-pc-linux-gnu) libcurl/7.12.0-CVS OpenSSL/0.9.6b zlib/1.1.4 c-ares/1.2.0 libidn/0.4.3
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://data.from.server.requiring.digest.hohoho.com/167 HTTP/1.1
Host: data.from.server.requiring.digest.hohoho.com
@@ -72,6 +73,7 @@ Proxy-Authorization: Basic Zm9vOmJhcg==
Authorization: Digest username="digest", realm="weirdorealm", nonce="12345", uri="/167", response="13c7c02a252cbe1c46d8669898a3be26"
User-Agent: curl/7.12.0-CVS (i686-pc-linux-gnu) libcurl/7.12.0-CVS OpenSSL/0.9.6b zlib/1.1.4 c-ares/1.2.0 libidn/0.4.3
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test168 b/tests/data/test168
index 0f4e0257..20e0b6d9 100644
--- a/tests/data/test168
+++ b/tests/data/test168
@@ -78,12 +78,14 @@ GET http://data.from.server.requiring.digest.hohoho.com/168 HTTP/1.1
Host: data.from.server.requiring.digest.hohoho.com
User-Agent: curl/7.12.0-CVS (i686-pc-linux-gnu) libcurl/7.12.0-CVS OpenSSL/0.9.6b zlib/1.1.4 c-ares/1.2.0 libidn/0.4.3
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://data.from.server.requiring.digest.hohoho.com/168 HTTP/1.1
Host: data.from.server.requiring.digest.hohoho.com
Proxy-Authorization: Digest username="foo", realm="weirdorealm", nonce="12345", uri="/168", response="fb8608e00ad9239a3dedb14bc8575976"
User-Agent: curl/7.12.0-CVS (i686-pc-linux-gnu) libcurl/7.12.0-CVS OpenSSL/0.9.6b zlib/1.1.4 c-ares/1.2.0 libidn/0.4.3
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://data.from.server.requiring.digest.hohoho.com/168 HTTP/1.1
Host: data.from.server.requiring.digest.hohoho.com
@@ -91,6 +93,7 @@ Proxy-Authorization: Digest username="foo", realm="weirdorealm", nonce="12345",
Authorization: Digest username="digest", realm="realmweirdo", nonce="123456", uri="/168", response="ca87f2d768a231e2d637a55698d5c416"
User-Agent: curl/7.12.0-CVS (i686-pc-linux-gnu) libcurl/7.12.0-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.3
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test169 b/tests/data/test169
index be5b4c6d..73ca9bd2 100644
--- a/tests/data/test169
+++ b/tests/data/test169
@@ -108,18 +108,21 @@ Host: data.from.server.requiring.digest.hohoho.com
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
User-Agent: curl/7.12.0-CVS (i686-pc-linux-gnu) libcurl/7.12.0-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.3
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://data.from.server.requiring.digest.hohoho.com/169 HTTP/1.1
Host: data.from.server.requiring.digest.hohoho.com
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAACeAJ4AWAAAAAAAAAD2AAAACAAIAPYAAAAIAAgA/gAAAAAAAAAAAAAABoKBAL9LNW5+nkyHZRmyFaL/LJ4xMjM0MjIzNGUCyhgQ9hw6eWAT13EbDa0BAQAAAAAAAACAPtXesZ0BMTIzNDIyMzQAAAAAAgAEAEMAQwABABIARQBMAEkAUwBBAEIARQBUAEgABAAYAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAMALABlAGwAaQBzAGEAYgBlAHQAaAAuAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAAAAAAAAAAAdGVzdHVzZXJjdXJsaG9zdA==
User-Agent: curl/7.12.0-CVS (i686-pc-linux-gnu) libcurl/7.12.0-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.3
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://data.from.server.requiring.digest.hohoho.com/169 HTTP/1.1
Host: data.from.server.requiring.digest.hohoho.com
Authorization: Digest username="digest", realm="r e a l m", nonce="abcdef", uri="/169", response="95d48591985a03c4b49cb962aa7bd3e6"
User-Agent: curl/7.12.0-CVS (i686-pc-linux-gnu) libcurl/7.12.0-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.3
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test170 b/tests/data/test170
index 48a263f4..8ce7774f 100644
--- a/tests/data/test170
+++ b/tests/data/test170
@@ -40,6 +40,7 @@ Host: a.galaxy.far.far.away
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
User-Agent: curl/7.12.0-CVS (i686-pc-linux-gnu) libcurl/7.12.0-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 libidn/0.4.3
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 0
</protocol>
diff --git a/tests/data/test171 b/tests/data/test171
index 3b9f7ba8..09e48b70 100644
--- a/tests/data/test171
+++ b/tests/data/test171
@@ -44,6 +44,7 @@ HTTP, get cookie with dot prefixed full domain
GET http://z.x.com/171 HTTP/1.1
Host: z.x.com
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
<file name="log/jar171" mode="text">
diff --git a/tests/data/test179 b/tests/data/test179
index 1cd5badf..f8f7811a 100644
--- a/tests/data/test179
+++ b/tests/data/test179
@@ -49,6 +49,7 @@ supertrooper.fake FALSE /c FALSE 2139150993 moo2 indeed
GET http://supertrooper.fake/c/179 HTTP/1.1
Host: supertrooper.fake
Accept: */*
+Proxy-Connection: Keep-Alive
Cookie: moo2=indeed
</protocol>
diff --git a/tests/data/test1800 b/tests/data/test1800
index 96a6c146..0a2bb1f6 100644
--- a/tests/data/test1800
+++ b/tests/data/test1800
@@ -48,7 +48,7 @@ Host: %HOSTIP:%HTTPPORT
Accept: */*
Connection: Upgrade, HTTP2-Settings
Upgrade: %H2CVER
-HTTP2-Settings: AAMAAABkAAQAAP__
+HTTP2-Settings: AAMAAABkAARAAAAA
</protocol>
</verify>
diff --git a/tests/data/test1801 b/tests/data/test1801
index 16ee12d4..9e1900b9 100644
--- a/tests/data/test1801
+++ b/tests/data/test1801
@@ -58,7 +58,7 @@ Host: %HOSTIP:%HTTPPORT
Accept: */*
Connection: Upgrade, HTTP2-Settings
Upgrade: %H2CVER
-HTTP2-Settings: AAMAAABkAAQAAP__
+HTTP2-Settings: AAMAAABkAARAAAAA
</protocol>
# CURLE_HTTP2: Send failure: Broken pipe
diff --git a/tests/data/test183 b/tests/data/test183
index b4471099..f34dc0c9 100644
--- a/tests/data/test183
+++ b/tests/data/test183
@@ -42,11 +42,13 @@ GET http://deathstar.another.galaxy/183 HTTP/1.1
User-Agent: curl/7.12.2-CVS (i686-pc-linux-gnu) libcurl/7.12.2-CVS OpenSSL/0.9.6b zlib/1.1.4 libidn/0.4.6
Host: deathstar.another.galaxy
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://a.galaxy.far.far.away/183 HTTP/1.1
User-Agent: curl/7.12.2-CVS (i686-pc-linux-gnu) libcurl/7.12.2-CVS OpenSSL/0.9.6b zlib/1.1.4 libidn/0.4.6
Host: a.galaxy.far.far.away
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
diff --git a/tests/data/test184 b/tests/data/test184
index 9cadc829..8b09dde2 100644
--- a/tests/data/test184
+++ b/tests/data/test184
@@ -62,10 +62,12 @@ GET http://deathstar.another.galaxy/184 HTTP/1.1
Host: another.visitor.stay.a.while.stay.foreeeeeever
User-Agent: curl/7.12.2-CVS (i686-pc-linux-gnu) libcurl/7.12.2-CVS OpenSSL/0.9.6b zlib/1.1.4 libidn/0.4.6
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://yet.another.host/184 HTTP/1.1
Host: yet.another.host
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
diff --git a/tests/data/test185 b/tests/data/test185
index dbef6e7e..298dd49c 100644
--- a/tests/data/test185
+++ b/tests/data/test185
@@ -62,10 +62,12 @@ GET http://deathstar.another.galaxy/185 HTTP/1.1
Host: another.visitor.stay.a.while.stay.foreeeeeever
User-Agent: curl/7.12.2-CVS (i686-pc-linux-gnu) libcurl/7.12.2-CVS OpenSSL/0.9.6b zlib/1.1.4 libidn/0.4.6
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://deathstar.another.galaxy/go/west/185 HTTP/1.1
Host: another.visitor.stay.a.while.stay.foreeeeeever
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
diff --git a/tests/data/test2045 b/tests/data/test2045
index 3190f803..15647d3e 100644
--- a/tests/data/test2045
+++ b/tests/data/test2045
@@ -19,7 +19,7 @@ In the broken scenario curl would use HTTP to talk to our FTP server. We handle
that by replying with something that both protocols can understand. Our FTP
server allows a custom welcome message, so we use that feature to make an HTTP
reply that contains an FTP reply (think polyglot). In the case of FTP we expect
-curl will return CURLE_FTP_WEIRD_SERVER_REPLY so we test for that return code.
+curl will return CURLE_WEIRD_SERVER_REPLY so we test for that return code.
-->
<servercmd>
REPLY welcome HTTP/1.1 200 OK\r\nContent-Length: 21\r\n\r\n500 Weird FTP Reply
@@ -46,7 +46,7 @@ Set the default protocol to ftp for a schemeless URL
#
# Verify data after the test has been "shot"
<verify>
-# CURLE_FTP_WEIRD_SERVER_REPLY is error code 8
+# CURLE_WEIRD_SERVER_REPLY is error code 8
<errorcode>
8
</errorcode>
diff --git a/tests/data/test2047 b/tests/data/test2047
index a8cca2f4..44229780 100644
--- a/tests/data/test2047
+++ b/tests/data/test2047
@@ -63,10 +63,12 @@ http://åäö.se/2047 -x %HOSTIP:%HTTPPORT -w "%{num_connects}\n%{num_redirects}
GET http://xn--4cab6c.se/2047 HTTP/1.1
Host: xn--4cab6c.se
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://xn--4cab6c.se/20470001 HTTP/1.1
Host: xn--4cab6c.se
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
diff --git a/tests/data/test2048 b/tests/data/test2048
index eb2b1df7..787f584e 100644
--- a/tests/data/test2048
+++ b/tests/data/test2048
@@ -26,7 +26,7 @@ https Server-localhost-sv.pem
pinnedpubkey no-match must fail even when insecure
</name>
<command>
---insecure --cacert %SRCDIR/certs/EdelCurlRoot-ca.crt --pinnedpubkey %SRCDIR/certs/Server-localhost.nn-sv.pub.der https://localhost:%HTTPSPORT/2034
+--insecure --cacert %SRCDIR/certs/EdelCurlRoot-ca.crt --pinnedpubkey %SRCDIR/certs/Server-localhost.nn-sv.pub.der https://localhost:%HTTPSPORT/2048
</command>
</client>
diff --git a/tests/data/test2050 b/tests/data/test2050
index 805e872e..81ef79ff 100644
--- a/tests/data/test2050
+++ b/tests/data/test2050
@@ -64,6 +64,7 @@ http://www.example.com.2050/2050 --connect-to ::connect.example.com.2050:%HTTPPO
<proxy>
CONNECT connect.example.com.2050:%HTTPPORT HTTP/1.1
Host: connect.example.com.2050:%HTTPPORT
+Proxy-Connection: Keep-Alive
</proxy>
<protocol>
diff --git a/tests/data/test206 b/tests/data/test206
index efbc56e0..5f0c8856 100644
--- a/tests/data/test206
+++ b/tests/data/test206
@@ -90,10 +90,12 @@ http://test.remote.haxx.se.206:8990/path/2060002 --proxy http://%HOSTIP:%HTTPPOR
<protocol>
CONNECT test.remote.haxx.se.206:8990 HTTP/1.1
Host: test.remote.haxx.se.206:8990
+Proxy-Connection: Keep-Alive
CONNECT test.remote.haxx.se.206:8990 HTTP/1.1
Host: test.remote.haxx.se.206:8990
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.haxx.se.206:8990", response="003e36decb4dbf6366b3ecb9b87c24ec"
+Proxy-Connection: Keep-Alive
GET /path/2060002 HTTP/1.1
User-Agent: curl/7.12.3-CVS (i686-pc-linux-gnu) libcurl/7.12.3-CVS OpenSSL/0.9.6b zlib/1.1.4
diff --git a/tests/data/test208 b/tests/data/test208
index fb4c0ea1..afb2566b 100644
--- a/tests/data/test208
+++ b/tests/data/test208
@@ -57,6 +57,7 @@ PUT ftp://daniel:mysecret@host.com/we/want/208 HTTP/1.1
Host: host.com:21
Authorization: Basic ZGFuaWVsOm15c2VjcmV0
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 78
Expect: 100-continue
diff --git a/tests/data/test209 b/tests/data/test209
index f868541c..961eba1a 100644
--- a/tests/data/test209
+++ b/tests/data/test209
@@ -104,10 +104,12 @@ chkhostname curlhost
CONNECT test.remote.example.com.209:%HTTPPORT HTTP/1.1
Host: test.remote.example.com.209:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
+Proxy-Connection: Keep-Alive
CONNECT test.remote.example.com.209:%HTTPPORT HTTP/1.1
Host: test.remote.example.com.209:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAACeAJ4AWAAAAAAAAAD2AAAACAAIAPYAAAAIAAgA/gAAAAAAAAAAAAAABoKBAL9LNW5+nkyHZRmyFaL/LJ4xMjM0MjIzNGUCyhgQ9hw6eWAT13EbDa0BAQAAAAAAAACAPtXesZ0BMTIzNDIyMzQAAAAAAgAEAEMAQwABABIARQBMAEkAUwBBAEIARQBUAEgABAAYAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAMALABlAGwAaQBzAGEAYgBlAHQAaAAuAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAAAAAAAAAAAdGVzdHVzZXJjdXJsaG9zdA==
+Proxy-Connection: Keep-Alive
GET /path/2090002 HTTP/1.1
User-Agent: curl/7.12.3-CVS (i686-pc-linux-gnu) libcurl/7.12.3-CVS OpenSSL/0.9.6b zlib/1.1.4
diff --git a/tests/data/test213 b/tests/data/test213
index 7ceed984..edbb6a6f 100644
--- a/tests/data/test213
+++ b/tests/data/test213
@@ -104,10 +104,12 @@ chkhostname curlhost
CONNECT test.remote.example.com.213:%HTTPPORT HTTP/1.0
Host: test.remote.example.com.213:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
+Proxy-Connection: Keep-Alive
CONNECT test.remote.example.com.213:%HTTPPORT HTTP/1.0
Host: test.remote.example.com.213:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAACeAJ4AWAAAAAAAAAD2AAAACAAIAPYAAAAIAAgA/gAAAAAAAAAAAAAABoKBAL9LNW5+nkyHZRmyFaL/LJ4xMjM0MjIzNGUCyhgQ9hw6eWAT13EbDa0BAQAAAAAAAACAPtXesZ0BMTIzNDIyMzQAAAAAAgAEAEMAQwABABIARQBMAEkAUwBBAEIARQBUAEgABAAYAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAMALABlAGwAaQBzAGEAYgBlAHQAaAAuAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAAAAAAAAAAAdGVzdHVzZXJjdXJsaG9zdA==
+Proxy-Connection: Keep-Alive
POST /path/2130002 HTTP/1.1
User-Agent: curl/7.12.3-CVS (i686-pc-linux-gnu) libcurl/7.12.3-CVS OpenSSL/0.9.6b zlib/1.1.4
diff --git a/tests/data/test217 b/tests/data/test217
index 0e0c0add..f10df566 100644
--- a/tests/data/test217
+++ b/tests/data/test217
@@ -44,6 +44,7 @@ http://test.remote.example.com.217:%HTTPPORT/path/2170002 --proxy http://%HOSTIP
<protocol>
CONNECT test.remote.example.com.217:%HTTPPORT HTTP/1.1
Host: test.remote.example.com.217:%HTTPPORT
+Proxy-Connection: Keep-Alive
</protocol>
# CURLE_RECV_ERROR
diff --git a/tests/data/test219 b/tests/data/test219
new file mode 100644
index 00000000..be3f0f3c
--- /dev/null
+++ b/tests/data/test219
@@ -0,0 +1,37 @@
+<testcase>
+<info>
+<keywords>
+proxy
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+<features>
+http
+</features>
+ <name>
+try using proxy with unsupported scheme
+ </name>
+ <command>
+-x foo://%HOSTIP:%HTTPPORT/219 http://%HOSTIP:%HTTPPORT/219
+</command>
+</client>
+
+#
+# Verify after the test has been "shot"
+<verify>
+<errorcode>
+7
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test233 b/tests/data/test233
index 996855d5..b631e52c 100644
--- a/tests/data/test233
+++ b/tests/data/test233
@@ -81,11 +81,13 @@ Host: first.host.it.is
Proxy-Authorization: Basic dGVzdGluZzp0aGlz
Authorization: Basic aWFtOm15c2VsZg==
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://goto.second.host.now/2330002 HTTP/1.1
Host: goto.second.host.now
Proxy-Authorization: Basic dGVzdGluZzp0aGlz
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test234 b/tests/data/test234
index f7da2b95..1d2e05b3 100644
--- a/tests/data/test234
+++ b/tests/data/test234
@@ -83,12 +83,14 @@ Host: first.host.it.is
Proxy-Authorization: Basic dGVzdGluZzp0aGlz
Authorization: Basic aWFtOm15c2VsZg==
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://goto.second.host.now/2340002 HTTP/1.1
Host: goto.second.host.now
Proxy-Authorization: Basic dGVzdGluZzp0aGlz
Authorization: Basic aWFtOm15c2VsZg==
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test239 b/tests/data/test239
index 275c81b3..6b92f07f 100644
--- a/tests/data/test239
+++ b/tests/data/test239
@@ -83,6 +83,7 @@ Host: %HOSTIP:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 0
Content-Type: application/x-www-form-urlencoded
@@ -91,6 +92,7 @@ Host: %HOSTIP:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAACeAJ4AWAAAAAAAAAD2AAAACAAIAPYAAAAIAAgA/gAAAAAAAAAAAAAABoKBAL9LNW5+nkyHZRmyFaL/LJ4xMjM0MjIzNGUCyhgQ9hw6eWAT13EbDa0BAQAAAAAAAACAPtXesZ0BMTIzNDIyMzQAAAAAAgAEAEMAQwABABIARQBMAEkAUwBBAEIARQBUAEgABAAYAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAMALABlAGwAaQBzAGEAYgBlAHQAaAAuAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAAAAAAAAAAAdGVzdHVzZXJjdXJsaG9zdA==
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 6
Content-Type: application/x-www-form-urlencoded
diff --git a/tests/data/test243 b/tests/data/test243
index bc09286e..3496055d 100644
--- a/tests/data/test243
+++ b/tests/data/test243
@@ -103,6 +103,7 @@ POST http://%HOSTIP:%HTTPPORT/243 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 6
Content-Type: application/x-www-form-urlencoded
@@ -111,6 +112,7 @@ Host: %HOSTIP:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 0
Content-Type: application/x-www-form-urlencoded
@@ -119,6 +121,7 @@ Host: %HOSTIP:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAACeAJ4AWAAAAAAAAAD2AAAACAAIAPYAAAAIAAgA/gAAAAAAAAAAAAAABoKBAL9LNW5+nkyHZRmyFaL/LJ4xMjM0MjIzNGUCyhgQ9hw6eWAT13EbDa0BAQAAAAAAAACAPtXesZ0BMTIzNDIyMzQAAAAAAgAEAEMAQwABABIARQBMAEkAUwBBAEIARQBUAEgABAAYAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAMALABlAGwAaQBzAGEAYgBlAHQAaAAuAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAAAAAAAAAAAdGVzdHVzZXJjdXJsaG9zdA==
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 6
Content-Type: application/x-www-form-urlencoded
diff --git a/tests/data/test256 b/tests/data/test256
index 0acd9db1..2b96ecf3 100644
--- a/tests/data/test256
+++ b/tests/data/test256
@@ -51,6 +51,7 @@ Host: %HOSTIP:%HTTPPORT
Proxy-Authorization: Basic ZGFuaWVsOnN0ZW5iZXJn
Range: bytes=78-
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
diff --git a/tests/data/test257 b/tests/data/test257
index 45dcbd55..502448dd 100644
--- a/tests/data/test257
+++ b/tests/data/test257
@@ -92,17 +92,20 @@ Host: supersite.com
Authorization: Basic dXNlcjE6cGFzc3dkMQ==
User-Agent: curl/7.14.0-CVS (i686-pc-linux-gnu) libcurl/7.14.0-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://anotherone.com/2570002 HTTP/1.1
Host: anotherone.com
Authorization: Basic dXNlcjI6cGFzc3dkMg==
User-Agent: curl/7.14.0-CVS (i686-pc-linux-gnu) libcurl/7.14.0-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://athird.com/2570003 HTTP/1.1
Host: athird.com
User-Agent: curl/7.14.0-CVS (i686-pc-linux-gnu) libcurl/7.14.0-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test258 b/tests/data/test258
index 82c6731c..98c34014 100644
--- a/tests/data/test258
+++ b/tests/data/test258
@@ -20,6 +20,7 @@ HTTP/1.1 407 no, tell me who you are first swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Proxy-Authenticate: Digest realm="many secrets", nonce="911"
+Proxy-Connection: close
Content-Length: 0
</data>
@@ -36,6 +37,7 @@ HTTP/1.1 407 no, tell me who you are first swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Proxy-Authenticate: Digest realm="many secrets", nonce="911"
+Proxy-Connection: close
Content-Length: 0
HTTP/1.1 200 A OK
@@ -81,6 +83,7 @@ POST http://remotehost:54321/we/want/258 HTTP/1.1
Host: remotehost:54321
User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 OpenSSL/0.9.7a ipv6 zlib/1.1.3
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 409
Content-Type: multipart/form-data; boundary=----------------------------7c633d5c27ce
@@ -106,6 +109,7 @@ Host: remotehost:54321
User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 OpenSSL/0.9.7a ipv6 zlib/1.1.3
Proxy-Authorization: Digest username="uuuser", realm="many secrets", nonce="911", uri="/we/want/258", response="2501654ca391f0b5c8c12a1da77e34cd"
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 409
Content-Type: multipart/form-data; boundary=----------------------------7c633d5c27ce
diff --git a/tests/data/test259 b/tests/data/test259
index 75b1f531..9532887a 100644
--- a/tests/data/test259
+++ b/tests/data/test259
@@ -79,6 +79,7 @@ POST http://remotehost:54321/we/want/259 HTTP/1.1
Host: remotehost:54321
User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 OpenSSL/0.9.7a ipv6 zlib/1.1.3
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 409
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------7c633d5c27ce
@@ -105,6 +106,7 @@ Host: remotehost:54321
User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 OpenSSL/0.9.7a ipv6 zlib/1.1.3
Proxy-Authorization: Digest username="uuuser", realm="many secrets", nonce="911", uri="/we/want/259", response="b479994d13e60f3aa192a67c5892ddc5"
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 409
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------7c633d5c27ce
diff --git a/tests/data/test263 b/tests/data/test263
index df0ba032..5088141f 100644
--- a/tests/data/test263
+++ b/tests/data/test263
@@ -47,6 +47,7 @@ HTTP-IPv6 GET with proxy specified using IPv6-numerical address
GET http://veryveryremotesite.com/263 HTTP/1.1
Host: veryveryremotesite.com
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test264 b/tests/data/test264
index 1174ca54..f4d171a1 100644
--- a/tests/data/test264
+++ b/tests/data/test264
@@ -42,6 +42,7 @@ GET http://we.want.that.site.com/264 HTTP/1.1
Host: we.want.that.site.com
Proxy-Authorization: Basic ZmFrZTp1c2Vy
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test265 b/tests/data/test265
index 79ab183f..1a162b80 100644
--- a/tests/data/test265
+++ b/tests/data/test265
@@ -107,10 +107,12 @@ chkhostname curlhost
CONNECT test.remote.example.com.265:%HTTPPORT HTTP/1.1
Host: test.remote.example.com.265:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
+Proxy-Connection: Keep-Alive
CONNECT test.remote.example.com.265:%HTTPPORT HTTP/1.1
Host: test.remote.example.com.265:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAACeAJ4AWAAAAAAAAAD2AAAACAAIAPYAAAAIAAgA/gAAAAAAAAAAAAAABoKBAL9LNW5+nkyHZRmyFaL/LJ4xMjM0MjIzNGUCyhgQ9hw6eWAT13EbDa0BAQAAAAAAAACAPtXesZ0BMTIzNDIyMzQAAAAAAgAEAEMAQwABABIARQBMAEkAUwBBAEIARQBUAEgABAAYAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAMALABlAGwAaQBzAGEAYgBlAHQAaAAuAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAAAAAAAAAAAdGVzdHVzZXJjdXJsaG9zdA==
+Proxy-Connection: Keep-Alive
POST /path/2650002 HTTP/1.1
User-Agent: curl/7.12.3-CVS (i686-pc-linux-gnu) libcurl/7.12.3-CVS OpenSSL/0.9.6b zlib/1.1.4
diff --git a/tests/data/test275 b/tests/data/test275
index 60004548..802c4bbc 100644
--- a/tests/data/test275
+++ b/tests/data/test275
@@ -69,6 +69,7 @@ CONNECT remotesite.com.275:%HTTPPORT HTTP/1.1
Host: remotesite.com.275:%HTTPPORT
Proxy-Authorization: Basic eW91YXJlOnlvdXJzZWxm
User-Agent: curl/7.10.7-pre2 (i686-pc-linux-gnu) libcurl/7.10.7-pre2 OpenSSL/0.9.7a zlib/1.1.3
+Proxy-Connection: Keep-Alive
</proxy>
<protocol>
diff --git a/tests/data/test278 b/tests/data/test278
index e6f1ef70..3112264a 100644
--- a/tests/data/test278
+++ b/tests/data/test278
@@ -42,6 +42,7 @@ GET http://we.want.that.site.com/278 HTTP/1.1
Host: we.want.that.site.com
Proxy-Authorization: Basic ZmFrZTo=
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test279 b/tests/data/test279
index 5005daa5..47f8b687 100644
--- a/tests/data/test279
+++ b/tests/data/test279
@@ -43,6 +43,7 @@ GET http://we.want.that.site.com/279 HTTP/1.1
Host: we.want.that.site.com
Proxy-Authorization: Basic ZmFrZTo=
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test287 b/tests/data/test287
index 526446f4..6772e220 100644
--- a/tests/data/test287
+++ b/tests/data/test287
@@ -37,6 +37,7 @@ http://test.remote.example.com.287:%HTTPPORT/path/287 -H "User-Agent: looser/201
<protocol>
CONNECT test.remote.example.com.287:%HTTPPORT HTTP/1.1
Host: test.remote.example.com.287:%HTTPPORT
+Proxy-Connection: Keep-Alive
User-Agent: looser/2007
</protocol>
diff --git a/tests/data/test299 b/tests/data/test299
index a7b77556..4daaea47 100644
--- a/tests/data/test299
+++ b/tests/data/test299
@@ -46,6 +46,7 @@ GET ftp://michal:aybabtu@host.com/we/want/299 HTTP/1.1
Host: host.com:21
Authorization: Basic bWljaGFsOmF5YmFidHU=
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test43 b/tests/data/test43
index dc0dd5fc..e5535bb3 100644
--- a/tests/data/test43
+++ b/tests/data/test43
@@ -67,10 +67,12 @@ http://%HOSTIP:%HTTPPORT/want/43 -L -x %HOSTIP:%HTTPPORT
GET http://%HOSTIP:%HTTPPORT/want/43 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://%HOSTIP:%HTTPPORT/want/data/430002.txt?coolsite=yes HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test5 b/tests/data/test5
index 13314570..b62f1a12 100644
--- a/tests/data/test5
+++ b/tests/data/test5
@@ -43,6 +43,7 @@ http://%HOSTIP:%HTTPPORT/we/want/that/page/5#5 -x %HOSTIP:%HTTPPORT
GET http://%HOSTIP:%HTTPPORT/we/want/that/page/5 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test503 b/tests/data/test503
index f02bac6f..e8dc21e8 100644
--- a/tests/data/test503
+++ b/tests/data/test503
@@ -72,6 +72,7 @@ moo
CONNECT machine.503:%HTTPPORT HTTP/1.1
Host: machine.503:%HTTPPORT
Proxy-Authorization: Basic dGVzdDppbmc=
+Proxy-Connection: Keep-Alive
</proxy>
<protocol>
diff --git a/tests/data/test506 b/tests/data/test506
index f1939fe5..96e690b2 100644
--- a/tests/data/test506
+++ b/tests/data/test506
@@ -41,10 +41,12 @@ Content-Type: text/html
Funny-head: yesyes
Set-Cookie: test4=overwritten4; domain=host.foo.com; expires=Sat May 5 GMT 11:56:27 2035
Set-Cookie: test1=overwritten1; domain=foo.com; expires=Thu Mar 3 GMT 11:56:27 2033
+Set-Cookie: test6=six; domain=.www.host.foo.com; expires=Thu Mar 3 GMT 11:56:27 2033
+Set-Cookie: test6=six_more; expires=Thu Mar 3 GMT 11:56:27 2033
Content-Type: text/html
-Content-Length: 32
+Content-Length: 73
-run 3: overwrite cookie 1 and 4
+run 3: overwrite cookie 1 and 4, set cookie 6 with and without tailmatch
</data3>
</reply>
@@ -166,24 +168,28 @@ lock: cookie [Pigs in space]: 60
unlock: cookie [Pigs in space]: 61
lock: cookie [Pigs in space]: 62
unlock: cookie [Pigs in space]: 63
-run 3: overwrite cookie 1 and 4
-lock: dns [Pigs in space]: 64
-unlock: dns [Pigs in space]: 65
-CLEANUP
+lock: cookie [Pigs in space]: 64
+unlock: cookie [Pigs in space]: 65
lock: cookie [Pigs in space]: 66
unlock: cookie [Pigs in space]: 67
-lock: share [Pigs in space]: 68
-unlock: share [Pigs in space]: 69
+run 3: overwrite cookie 1 and 4, set cookie 6 with and without tailmatch
+lock: dns [Pigs in space]: 68
+unlock: dns [Pigs in space]: 69
+CLEANUP
+lock: cookie [Pigs in space]: 70
+unlock: cookie [Pigs in space]: 71
+lock: share [Pigs in space]: 72
+unlock: share [Pigs in space]: 73
CURLOPT_SHARE
-lock: share [Pigs in space]: 70
-unlock: share [Pigs in space]: 71
+lock: share [Pigs in space]: 74
+unlock: share [Pigs in space]: 75
CURLOPT_COOKIELIST ALL
-lock: cookie [Pigs in space]: 72
-unlock: cookie [Pigs in space]: 73
+lock: cookie [Pigs in space]: 76
+unlock: cookie [Pigs in space]: 77
CURLOPT_COOKIEJAR
CURLOPT_COOKIELIST RELOAD
-lock: cookie [Pigs in space]: 74
-unlock: cookie [Pigs in space]: 75
+lock: cookie [Pigs in space]: 78
+unlock: cookie [Pigs in space]: 79
loaded cookies:
-----------------
.host.foo.com TRUE / FALSE 1896263787 injected yes
@@ -192,19 +198,21 @@ loaded cookies:
.foo.com TRUE / FALSE 1896263787 test3 three
.host.foo.com TRUE / FALSE 2061978987 test4 overwritten4
.host.foo.com TRUE / FALSE 1896263787 test5 five
+ .www.host.foo.com TRUE / FALSE 1993463787 test6 six
+ www.host.foo.com FALSE / FALSE 1993463787 test6 six_more
-----------------
try SHARE_CLEANUP...
-lock: share [Pigs in space]: 76
-unlock: share [Pigs in space]: 77
-SHARE_CLEANUP failed, correct
-CLEANUP
-lock: cookie [Pigs in space]: 78
-unlock: cookie [Pigs in space]: 79
lock: share [Pigs in space]: 80
unlock: share [Pigs in space]: 81
+SHARE_CLEANUP failed, correct
+CLEANUP
+lock: cookie [Pigs in space]: 82
+unlock: cookie [Pigs in space]: 83
+lock: share [Pigs in space]: 84
+unlock: share [Pigs in space]: 85
SHARE_CLEANUP
-lock: share [Pigs in space]: 82
-unlock: share [Pigs in space]: 83
+lock: share [Pigs in space]: 86
+unlock: share [Pigs in space]: 87
GLOBAL_CLEANUP
</stdout>
<stderr>
@@ -221,6 +229,8 @@ http://%HOSTIP:%HTTPPORT/506
.foo.com TRUE / FALSE 1896263787 test3 three
.host.foo.com TRUE / FALSE 2061978987 test4 overwritten4
.host.foo.com TRUE / FALSE 1896263787 test5 five
+.www.host.foo.com TRUE / FALSE 1993463787 test6 six
+www.host.foo.com FALSE / FALSE 1993463787 test6 six_more
</file>
</verify>
</testcase>
diff --git a/tests/data/test517 b/tests/data/test517
index c81a45e0..513634f1 100644
--- a/tests/data/test517
+++ b/tests/data/test517
@@ -116,6 +116,12 @@ nothing
81: 20111323 12:34:56 => -1
82: 20110623 12:34:79 => -1
83: Wed, 31 Dec 2008 23:59:60 GMT => 1230768000
+84: 20110623 12:3 => 1308830580
+85: 20110623 1:3 => 1308790980
+86: 20110623 1:30 => 1308792600
+87: 20110623 12:12:3 => 1308831123
+88: 20110623 01:12:3 => 1308791523
+89: 20110623 01:99:30 => -1
</stdout>
# This test case previously tested an overflow case ("2094 Nov 6 =>
diff --git a/tests/data/test523 b/tests/data/test523
index d021ae3b..9abe0ed2 100644
--- a/tests/data/test523
+++ b/tests/data/test523
@@ -54,6 +54,7 @@ GET HTTP://www.example.com:19999/523 HTTP/1.1
Host: www.example.com:19999
Authorization: Basic eHh4Onl5eQ==
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
<stdout>
diff --git a/tests/data/test540 b/tests/data/test540
index 19a13f19..8decaea9 100644
--- a/tests/data/test540
+++ b/tests/data/test540
@@ -78,16 +78,19 @@ http://test.remote.example.com/path/540 http://%HOSTIP:%HTTPPORT silly:person cu
GET http://test.remote.example.com/path/540 HTTP/1.1
Host: custom.set.host.name
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://test.remote.example.com/path/540 HTTP/1.1
Host: custom.set.host.name
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="/path/540", response="ca507dcf189196b6a5374d3233042261"
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://test.remote.example.com/path/540 HTTP/1.1
Host: custom.set.host.name
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="/path/540", response="ca507dcf189196b6a5374d3233042261"
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test547 b/tests/data/test547
index 7cf3e919..cee22c6f 100644
--- a/tests/data/test547
+++ b/tests/data/test547
@@ -106,6 +106,7 @@ POST http://test.remote.example.com/path/547 HTTP/1.1
Host: test.remote.example.com
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
@@ -115,6 +116,7 @@ Host: test.remote.example.com
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 0
Content-Type: application/x-www-form-urlencoded
@@ -123,6 +125,7 @@ Host: test.remote.example.com
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAACeAJ4AWAAAAAAAAAD2AAAACAAIAPYAAAAIAAgA/gAAAAAAAAAAAAAABoKBAL9LNW5+nkyHZRmyFaL/LJ4xMjM0MjIzNGUCyhgQ9hw6eWAT13EbDa0BAQAAAAAAAACAPtXesZ0BMTIzNDIyMzQAAAAAAgAEAEMAQwABABIARQBMAEkAUwBBAEIARQBUAEgABAAYAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAMALABlAGwAaQBzAGEAYgBlAHQAaAAuAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAAAAAAAAAAAdGVzdHVzZXJjdXJsaG9zdA==
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
diff --git a/tests/data/test548 b/tests/data/test548
index e9d2262b..34cf5e2e 100644
--- a/tests/data/test548
+++ b/tests/data/test548
@@ -106,6 +106,7 @@ POST http://test.remote.example.com/path/548 HTTP/1.1
Host: test.remote.example.com
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
@@ -115,6 +116,7 @@ Host: test.remote.example.com
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 0
Content-Type: application/x-www-form-urlencoded
@@ -123,6 +125,7 @@ Host: test.remote.example.com
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAACeAJ4AWAAAAAAAAAD2AAAACAAIAPYAAAAIAAgA/gAAAAAAAAAAAAAABoKBAL9LNW5+nkyHZRmyFaL/LJ4xMjM0MjIzNGUCyhgQ9hw6eWAT13EbDa0BAQAAAAAAAACAPtXesZ0BMTIzNDIyMzQAAAAAAgAEAEMAQwABABIARQBMAEkAUwBBAEIARQBUAEgABAAYAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAMALABlAGwAaQBzAGEAYgBlAHQAaAAuAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAAAAAAAAAAAdGVzdHVzZXJjdXJsaG9zdA==
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
diff --git a/tests/data/test549 b/tests/data/test549
index 59925ce7..a248edbf 100644
--- a/tests/data/test549
+++ b/tests/data/test549
@@ -55,6 +55,7 @@ ftp://www.example.com/moo/549 http://%HOSTIP:%HTTPPORT
GET ftp://www.example.com/moo/549;type=i HTTP/1.1
Host: www.example.com:21
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
<stdout>
diff --git a/tests/data/test550 b/tests/data/test550
index 9a717ee8..a609aa21 100644
--- a/tests/data/test550
+++ b/tests/data/test550
@@ -55,6 +55,7 @@ ftp://www.example.com/moo/550 http://%HOSTIP:%HTTPPORT ascii
GET ftp://www.example.com/moo/550;type=a HTTP/1.1
Host: www.example.com:21
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
<stdout>
diff --git a/tests/data/test551 b/tests/data/test551
index 6dd01337..ed6aee26 100644
--- a/tests/data/test551
+++ b/tests/data/test551
@@ -81,6 +81,7 @@ http://test.remote.example.com/path/551 http://%HOSTIP:%HTTPPORT s1lly:pers0n
POST http://test.remote.example.com/path/551 HTTP/1.1
Host: test.remote.example.com
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
@@ -89,6 +90,7 @@ POST http://test.remote.example.com/path/551 HTTP/1.1
Host: test.remote.example.com
Proxy-Authorization: Digest username="s1lly", realm="something fun to read", nonce="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", uri="/path/551", response="3325240726fbdaf1e61f3a0dd40b930c"
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
diff --git a/tests/data/test552 b/tests/data/test552
index c20e2049..b44ca345 100644
--- a/tests/data/test552
+++ b/tests/data/test552
Binary files differ
diff --git a/tests/data/test555 b/tests/data/test555
index 6c09e3c1..0f3bb07f 100644
--- a/tests/data/test555
+++ b/tests/data/test555
@@ -115,6 +115,7 @@ POST http://test.remote.example.com/path/555 HTTP/1.1
Host: test.remote.example.com
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
@@ -124,6 +125,7 @@ Host: test.remote.example.com
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 0
Content-Type: application/x-www-form-urlencoded
@@ -132,6 +134,7 @@ Host: test.remote.example.com
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAACeAJ4AWAAAAAAAAAD2AAAACAAIAPYAAAAIAAgA/gAAAAAAAAAAAAAABoKBAL9LNW5+nkyHZRmyFaL/LJ4xMjM0MjIzNGUCyhgQ9hw6eWAT13EbDa0BAQAAAAAAAACAPtXesZ0BMTIzNDIyMzQAAAAAAgAEAEMAQwABABIARQBMAEkAUwBBAEIARQBUAEgABAAYAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAMALABlAGwAaQBzAGEAYgBlAHQAaAAuAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAAAAAAAAAAAdGVzdHVzZXJjdXJsaG9zdA==
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
diff --git a/tests/data/test558 b/tests/data/test558
index a1ac7d47..27457ff4 100644
--- a/tests/data/test558
+++ b/tests/data/test558
@@ -41,8 +41,8 @@ FD connect.c: sclose()
MEM lib558.c: malloc()
MEM lib558.c: free()
MEM escape.c: malloc()
-MEM escape.c: realloc()
-MEM escape.c: realloc()
+MEM strdup.c: realloc()
+MEM strdup.c: realloc()
MEM escape.c: free()
</file>
<stripfile>
diff --git a/tests/data/test561 b/tests/data/test561
index 905e756b..a6188eac 100644
--- a/tests/data/test561
+++ b/tests/data/test561
@@ -56,6 +56,7 @@ FTP RETR with CURLOPT_PROXY_TRANSFER_MODE, ASCII transfer and type=i
GET ftp://www.example.com/moo/561;type=i HTTP/1.1
Host: www.example.com:21
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
<stdout>
diff --git a/tests/data/test563 b/tests/data/test563
index e4c00f50..78515231 100644
--- a/tests/data/test563
+++ b/tests/data/test563
@@ -50,6 +50,7 @@ ftp_proxy=http://%HOSTIP:%HTTPPORT/
GET FTP://%HOSTIP:%FTPPORT/563;type=A HTTP/1.1
Host: %HOSTIP:%FTPPORT
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test590 b/tests/data/test590
index 33417767..55ea4f0e 100644
--- a/tests/data/test590
+++ b/tests/data/test590
@@ -104,18 +104,21 @@ GET http://test.remote.example.com/path/590 HTTP/1.1
Host: test.remote.example.com
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://test.remote.example.com/path/590 HTTP/1.1
Host: test.remote.example.com
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://test.remote.example.com/path/590 HTTP/1.1
Host: test.remote.example.com
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAACeAJ4AWAAAAAAAAAD2AAAAAgACAPYAAAAIAAgA+AAAAAAAAAAAAAAABoKBAB3Hr6SDn3NDNkgebbaP88ExMjM0MjIzNFIW4N7aYT44bAIg1jt2blUBAQAAAAAAAACAPtXesZ0BMTIzNDIyMzQAAAAAAgAEAEMAQwABABIARQBMAEkAUwBBAEIARQBUAEgABAAYAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAMALABlAGwAaQBzAGEAYgBlAHQAaAAuAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAAAAAAAAAAAbWVjdXJsaG9zdA==
User-Agent: curl/7.13.2-CVS (i686-pc-linux-gnu) libcurl/7.13.2-CVS OpenSSL/0.9.7e zlib/1.2.2 libidn/0.5.13
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test63 b/tests/data/test63
index 2a964492..ccc19dd2 100644
--- a/tests/data/test63
+++ b/tests/data/test63
@@ -45,6 +45,7 @@ GET http://we.want.that.site.com/63 HTTP/1.1
Host: we.want.that.site.com
Proxy-Authorization: Basic ZmFrZTp1c2Vy
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test79 b/tests/data/test79
index 55fc2459..b2566e22 100644
--- a/tests/data/test79
+++ b/tests/data/test79
@@ -48,6 +48,7 @@ ftp://%HOSTIP:%HTTPPORT/we/want/that/page/79 -x %HOSTIP:%HTTPPORT
GET ftp://%HOSTIP:%HTTPPORT/we/want/that/page/79 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test80 b/tests/data/test80
index 8a635b45..147a6aa1 100644
--- a/tests/data/test80
+++ b/tests/data/test80
@@ -68,6 +68,7 @@ CONNECT test.80:%HTTPPORT HTTP/1.0
Host: test.80:%HTTPPORT
Proxy-Authorization: Basic eW91YXJlOnlvdXJzZWxm
User-Agent: curl/7.10.7-pre2 (i686-pc-linux-gnu) libcurl/7.10.7-pre2 OpenSSL/0.9.7a zlib/1.1.3
+Proxy-Connection: Keep-Alive
</proxy>
<protocol>
diff --git a/tests/data/test81 b/tests/data/test81
index 53affa05..dc054d29 100644
--- a/tests/data/test81
+++ b/tests/data/test81
@@ -89,12 +89,14 @@ Host: %HOSTIP:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
User-Agent: curl/7.10.6-pre1 (i686-pc-linux-gnu) libcurl/7.10.6-pre1 OpenSSL/0.9.7a ipv6 zlib/1.1.3
Accept: */*
+Proxy-Connection: Keep-Alive
GET http://%HOSTIP:%HTTPPORT/81 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAACeAJ4AWAAAAAAAAAD2AAAACAAIAPYAAAAIAAgA/gAAAAAAAAAAAAAABoKBAL9LNW5+nkyHZRmyFaL/LJ4xMjM0MjIzNGUCyhgQ9hw6eWAT13EbDa0BAQAAAAAAAACAPtXesZ0BMTIzNDIyMzQAAAAAAgAEAEMAQwABABIARQBMAEkAUwBBAEIARQBUAEgABAAYAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAMALABlAGwAaQBzAGEAYgBlAHQAaAAuAGMAYwAuAGkAYwBlAGQAZQB2AC4AbgB1AAAAAAAAAAAAdGVzdHVzZXJjdXJsaG9zdA==
User-Agent: curl/7.10.6-pre1 (i686-pc-linux-gnu) libcurl/7.10.6-pre1 OpenSSL/0.9.7a ipv6 zlib/1.1.3
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test82 b/tests/data/test82
index de3fcbae..8b58f75d 100644
--- a/tests/data/test82
+++ b/tests/data/test82
@@ -49,6 +49,7 @@ Host: %HOSTIP:%HTTPPORT
Proxy-Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
User-Agent: curl/7.10.6-pre1 (i686-pc-linux-gnu) libcurl/7.10.6-pre1 OpenSSL/0.9.7a ipv6 zlib/1.1.3
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test83 b/tests/data/test83
index 4fe8ba34..120bcc6a 100644
--- a/tests/data/test83
+++ b/tests/data/test83
@@ -64,6 +64,7 @@ http://test.83:%HTTPPORT/we/want/that/page/83 -p -x %HOSTIP:%PROXYPORT --user 'i
CONNECT test.83:%HTTPPORT HTTP/1.1
Host: test.83:%HTTPPORT
User-Agent: curl/7.10.7-pre2 (i686-pc-linux-gnu) libcurl/7.10.7-pre2 OpenSSL/0.9.7a zlib/1.1.3
+Proxy-Connection: Keep-Alive
</proxy>
<protocol>
diff --git a/tests/data/test84 b/tests/data/test84
index cf667d67..629dae2f 100644
--- a/tests/data/test84
+++ b/tests/data/test84
@@ -47,6 +47,7 @@ Host: %HOSTIP:%HTTPPORT
Authorization: Basic aWFtOm15c2VsZg==
User-Agent: curl/7.10.7-pre2 (i686-pc-linux-gnu) libcurl/7.10.7-pre2 OpenSSL/0.9.7a zlib/1.1.3
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test85 b/tests/data/test85
index a11363f5..cb5e6e05 100644
--- a/tests/data/test85
+++ b/tests/data/test85
@@ -51,6 +51,7 @@ Proxy-Authorization: Basic dGVzdGluZzp0aGlz
Authorization: Basic aWFtOm15c2VsZg==
User-Agent: curl/7.10.7-pre2 (i686-pc-linux-gnu) libcurl/7.10.7-pre2 OpenSSL/0.9.7a zlib/1.1.3
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test864 b/tests/data/test864
index 9ad98f7e..ebdebd67 100644
--- a/tests/data/test864
+++ b/tests/data/test864
@@ -11,7 +11,7 @@ APOP
<reply>
<servercmd>
CAPA APOP
-REPLY welcome +OK cURL POP3 server ready to serve <1972.987654321\@curl>
+REPLY welcome +OK curl POP3 server ready to serve <1972.987654321\@curl>
</servercmd>
<data>
From: me@somewhere
diff --git a/tests/data/test93 b/tests/data/test93
index 948d29c4..13872483 100644
--- a/tests/data/test93
+++ b/tests/data/test93
@@ -43,6 +43,7 @@ http://%HOSTIP:%HTTPPORT/93 -x %HOSTIP:%HTTPPORT
GET http://%HOSTIP:%HTTPPORT/93 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test94 b/tests/data/test94
index 94c894cb..2f3f4824 100644
--- a/tests/data/test94
+++ b/tests/data/test94
@@ -51,6 +51,7 @@ https://test.anything.really.com:94 --proxy1.0 %HOSTIP:%HTTPPORT
CONNECT test.anything.really.com:94 HTTP/1.0
User-Agent: curl/7.11.0-CVS (i686-pc-linux-gnu) libcurl/7.11.0-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4
Host: test.anything.really.com:94
+Proxy-Connection: Keep-Alive
</protocol>
</verify>
diff --git a/tests/data/test95 b/tests/data/test95
index 2b3e2c22..1cd88aca 100644
--- a/tests/data/test95
+++ b/tests/data/test95
@@ -64,6 +64,7 @@ http://test.95:%HTTPPORT/we/want/that/page/95 -p -x %HOSTIP:%PROXYPORT -d "datat
CONNECT test.95:%HTTPPORT HTTP/1.1
User-Agent: curl/7.10.7-pre2 (i686-pc-linux-gnu) libcurl/7.10.7-pre2 OpenSSL/0.9.7a zlib/1.1.3
Host: test.95:%HTTPPORT
+Proxy-Connection: Keep-Alive
</proxy>
<protocol nonewline="yes">
diff --git a/tests/ftpserver.pl b/tests/ftpserver.pl
index 01a7df86..081298f1 100755
--- a/tests/ftpserver.pl
+++ b/tests/ftpserver.pl
@@ -609,7 +609,7 @@ sub protocolsetup {
' / __| | | | |_) | | '."\r\n",
' | (__| |_| | _ {| |___ '."\r\n",
' \___|\___/|_| \_\_____|'."\r\n",
- '+OK cURL POP3 server ready to serve '."\r\n")
+ '+OK curl POP3 server ready to serve '."\r\n")
);
}
elsif($proto eq 'imap') {
@@ -643,7 +643,7 @@ sub protocolsetup {
' / __| | | | |_) | | '."\r\n",
' | (__| |_| | _ {| |___ '."\r\n",
' \___|\___/|_| \_\_____|'."\r\n",
- '* OK cURL IMAP server ready to serve'."\r\n")
+ '* OK curl IMAP server ready to serve'."\r\n")
);
}
elsif($proto eq 'smtp') {
@@ -1057,7 +1057,7 @@ sub EXPN_smtp {
}
sub QUIT_smtp {
- sendcontrol "221 cURL $smtp_type server signing off\r\n";
+ sendcontrol "221 curl $smtp_type server signing off\r\n";
return 0;
}
@@ -1605,7 +1605,7 @@ sub NOOP_imap {
}
sub LOGOUT_imap {
- sendcontrol "* BYE cURL IMAP server signing off\r\n";
+ sendcontrol "* BYE curl IMAP server signing off\r\n";
sendcontrol "$cmdid OK LOGOUT completed\r\n";
return 0;
@@ -1941,7 +1941,7 @@ sub QUIT_pop3 {
@deleted = ();
}
- sendcontrol "+OK cURL POP3 server signing off\r\n";
+ sendcontrol "+OK curl POP3 server signing off\r\n";
return 0;
}
diff --git a/tests/libtest/CMakeLists.txt b/tests/libtest/CMakeLists.txt
index cc9d7e1f..a7449c37 100644
--- a/tests/libtest/CMakeLists.txt
+++ b/tests/libtest/CMakeLists.txt
@@ -43,6 +43,10 @@ if(NOT WIN32)
# library at (tests)/libtest/.libs/libhostname.so
set_target_properties(hostname PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/.libs)
+ if(HIDES_CURL_PRIVATE_SYMBOLS)
+ set_property(TARGET hostname APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
+ set_property(TARGET hostname APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE})
+ endif()
endif()
# # files used only in some libcurl test programs
diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
index 7ae66d79..c1dc2f58 100644
--- a/tests/libtest/Makefile.inc
+++ b/tests/libtest/Makefile.inc
@@ -23,7 +23,8 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \
lib1500 lib1501 lib1502 lib1503 lib1504 lib1505 lib1506 lib1507 lib1508 \
lib1509 lib1510 lib1511 lib1512 lib1513 lib1514 lib1515 lib1517 \
lib1520 \
- lib1525 lib1526 lib1527 lib1528 lib1529 lib1530 lib1531 \
+ lib1525 lib1526 lib1527 lib1528 lib1529 lib1530 lib1531 lib1532 lib1533 \
+ lib1534 \
lib1900 \
lib2033
@@ -391,6 +392,18 @@ lib1531_SOURCES = lib1531.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1531_LDADD = $(TESTUTIL_LIBS)
lib1531_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1531
+lib1532_SOURCES = lib1532.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1532_LDADD = $(TESTUTIL_LIBS)
+lib1532_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1532
+
+lib1533_SOURCES = lib1533.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1533_LDADD = $(TESTUTIL_LIBS)
+lib1533_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1533
+
+lib1534_SOURCES = lib1534.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1534_LDADD = $(TESTUTIL_LIBS)
+lib1534_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1534
+
lib1900_SOURCES = lib1900.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1900_LDADD = $(TESTUTIL_LIBS)
lib1900_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/tests/libtest/lib1500.c b/tests/libtest/lib1500.c
index f3c49586..73d23a1b 100644
--- a/tests/libtest/lib1500.c
+++ b/tests/libtest/lib1500.c
@@ -29,8 +29,8 @@
int test(char *URL)
{
- CURL* curls = NULL;
- CURLM* multi = NULL;
+ CURL *curls = NULL;
+ CURLM *multi = NULL;
int still_running;
int i = TEST_ERR_FAILURE;
int res = 0;
diff --git a/tests/libtest/lib1502.c b/tests/libtest/lib1502.c
index e4e1a162..bd555cba 100644
--- a/tests/libtest/lib1502.c
+++ b/tests/libtest/lib1502.c
@@ -41,8 +41,8 @@
int test(char *URL)
{
- CURL* easy = NULL;
- CURLM* multi = NULL;
+ CURL *easy = NULL;
+ CURLM *multi = NULL;
int still_running;
int res = 0;
diff --git a/tests/libtest/lib1507.c b/tests/libtest/lib1507.c
index 5a7994eb..7ab30571 100644
--- a/tests/libtest/lib1507.c
+++ b/tests/libtest/lib1507.c
@@ -68,7 +68,7 @@ int test(char *URL)
CURLM *mcurl = NULL;
int still_running = 1;
struct timeval mp_start;
- struct curl_slist* rcpt_list = NULL;
+ struct curl_slist *rcpt_list = NULL;
curl_global_init(CURL_GLOBAL_DEFAULT);
diff --git a/tests/libtest/lib1511.c b/tests/libtest/lib1511.c
index bec31671..e1840e76 100644
--- a/tests/libtest/lib1511.c
+++ b/tests/libtest/lib1511.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,7 +26,7 @@
int test(char *URL)
{
long unmet;
- CURL* curl = NULL;
+ CURL *curl = NULL;
int res = 0;
global_init(CURL_GLOBAL_ALL);
diff --git a/tests/libtest/lib1515.c b/tests/libtest/lib1515.c
index 2fd19bb7..aeaf6b25 100644
--- a/tests/libtest/lib1515.c
+++ b/tests/libtest/lib1515.c
@@ -113,7 +113,7 @@ test_cleanup:
int test(char *URL)
{
- CURLM* multi = NULL;
+ CURLM *multi = NULL;
int res = 0;
char *address = libtest_arg2;
char *port = libtest_arg3;
diff --git a/tests/libtest/lib1532.c b/tests/libtest/lib1532.c
new file mode 100644
index 00000000..4a3ff324
--- /dev/null
+++ b/tests/libtest/lib1532.c
@@ -0,0 +1,80 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "memdebug.h"
+
+/* Test CURLINFO_RESPONSE_CODE */
+
+int test(char *URL)
+{
+ CURL *curl;
+ long httpcode;
+ int res = CURLE_OK;
+
+ global_init(CURL_GLOBAL_ALL);
+
+ easy_init(curl);
+
+ easy_setopt(curl, CURLOPT_URL, URL);
+
+ res = curl_easy_perform(curl);
+ if(res) {
+ fprintf(stderr, "%s:%d curl_easy_perform() failed with code %d (%s)\n",
+ __FILE__, __LINE__, res, curl_easy_strerror(res));
+ goto test_cleanup;
+ }
+
+ res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpcode);
+ if(res) {
+ fprintf(stderr, "%s:%d curl_easy_getinfo() failed with code %d (%s)\n",
+ __FILE__, __LINE__, res, curl_easy_strerror(res));
+ goto test_cleanup;
+ }
+ if(httpcode != 200) {
+ fprintf(stderr, "%s:%d unexpected response code %ld\n",
+ __FILE__, __LINE__, httpcode);
+ res = CURLE_HTTP_RETURNED_ERROR;
+ goto test_cleanup;
+ }
+
+ /* Test for a regression of github bug 1017 (response code does not reset) */
+ curl_easy_reset(curl);
+
+ res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpcode);
+ if(res) {
+ fprintf(stderr, "%s:%d curl_easy_getinfo() failed with code %d (%s)\n",
+ __FILE__, __LINE__, res, curl_easy_strerror(res));
+ goto test_cleanup;
+ }
+ if(httpcode != 0) {
+ fprintf(stderr, "%s:%d curl_easy_reset failed to zero the response code\n"
+ "possible regression of github bug 1017\n", __FILE__, __LINE__);
+ res = CURLE_HTTP_RETURNED_ERROR;
+ goto test_cleanup;
+ }
+
+test_cleanup:
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ return res;
+}
diff --git a/tests/libtest/lib1533.c b/tests/libtest/lib1533.c
new file mode 100644
index 00000000..de403e19
--- /dev/null
+++ b/tests/libtest/lib1533.c
@@ -0,0 +1,199 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * This test sends data with CURLOPT_KEEP_SENDING_ON_ERROR.
+ * The server responds with an early error response.
+ * The test is successful if the connection can be reused for the next request,
+ * because this implies that the data has been sent completely to the server.
+ */
+
+#include "test.h"
+
+#include "memdebug.h"
+
+struct cb_data {
+ CURL *easy_handle;
+ int response_received;
+ int paused;
+ size_t remaining_bytes;
+};
+
+
+static void reset_data(struct cb_data *data, CURL *curl)
+{
+ data->easy_handle = curl;
+ data->response_received = 0;
+ data->paused = 0;
+ data->remaining_bytes = 3;
+}
+
+
+static size_t read_callback(void *ptr, size_t size, size_t nitems,
+ void *userdata)
+{
+ struct cb_data *data = (struct cb_data *)userdata;
+
+ /* wait until the server has sent all response headers */
+ if(data->response_received) {
+ size_t totalsize = nitems * size;
+
+ size_t bytes_to_send = data->remaining_bytes;
+ if(bytes_to_send > totalsize) {
+ bytes_to_send = totalsize;
+ }
+
+ memset(ptr, 'a', bytes_to_send);
+ data->remaining_bytes -= bytes_to_send;
+
+ return bytes_to_send;
+ }
+ else {
+ data->paused = 1;
+ return CURL_READFUNC_PAUSE;
+ }
+}
+
+
+static size_t write_callback(char *ptr, size_t size, size_t nmemb,
+ void *userdata)
+{
+ struct cb_data *data = (struct cb_data *)userdata;
+ size_t totalsize = nmemb * size;
+
+ /* unused parameter */
+ (void)ptr;
+
+ /* all response headers have been received */
+ data->response_received = 1;
+
+ if(data->paused) {
+ /* continue to send request body data */
+ data->paused = 0;
+ curl_easy_pause(data->easy_handle, CURLPAUSE_CONT);
+ }
+
+ return totalsize;
+}
+
+
+static int perform_and_check_connections(CURL *curl, const char *description,
+ long expected_connections)
+{
+ CURLcode res;
+ long connections = 0;
+
+ res = curl_easy_perform(curl);
+ if(res != CURLE_OK) {
+ fprintf(stderr, "curl_easy_perform() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ res = curl_easy_getinfo(curl, CURLINFO_NUM_CONNECTS, &connections);
+ if(res != CURLE_OK) {
+ fprintf(stderr, "curl_easy_getinfo() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ fprintf(stderr, "%s: expected: %ld connections; actual: %ld connections\n",
+ description, expected_connections, connections);
+
+ if(connections != expected_connections) {
+ return TEST_ERR_FAILURE;
+ }
+
+ return TEST_ERR_SUCCESS;
+}
+
+
+int test(char *URL)
+{
+ struct cb_data data;
+ CURL *curl = NULL;
+ CURLcode res = CURLE_FAILED_INIT;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ if((curl = curl_easy_init()) == NULL) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ reset_data(&data, curl);
+
+ test_setopt(curl, CURLOPT_URL, URL);
+ test_setopt(curl, CURLOPT_POST, 1L);
+ test_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
+ (curl_off_t)data.remaining_bytes);
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+ test_setopt(curl, CURLOPT_READFUNCTION, read_callback);
+ test_setopt(curl, CURLOPT_READDATA, &data);
+ test_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
+ test_setopt(curl, CURLOPT_WRITEDATA, &data);
+
+ res = perform_and_check_connections(curl,
+ "First request without CURLOPT_KEEP_SENDING_ON_ERROR", 1);
+ if(res != TEST_ERR_SUCCESS) {
+ goto test_cleanup;
+ }
+
+ reset_data(&data, curl);
+
+ res = perform_and_check_connections(curl,
+ "Second request without CURLOPT_KEEP_SENDING_ON_ERROR", 1);
+ if(res != TEST_ERR_SUCCESS) {
+ goto test_cleanup;
+ }
+
+ test_setopt(curl, CURLOPT_KEEP_SENDING_ON_ERROR, 1L);
+
+ reset_data(&data, curl);
+
+ res = perform_and_check_connections(curl,
+ "First request with CURLOPT_KEEP_SENDING_ON_ERROR", 1);
+ if(res != TEST_ERR_SUCCESS) {
+ goto test_cleanup;
+ }
+
+ reset_data(&data, curl);
+
+ res = perform_and_check_connections(curl,
+ "Second request with CURLOPT_KEEP_SENDING_ON_ERROR", 0);
+ if(res != TEST_ERR_SUCCESS) {
+ goto test_cleanup;
+ }
+
+ res = TEST_ERR_SUCCESS;
+
+test_cleanup:
+
+ curl_easy_cleanup(curl);
+
+ curl_global_cleanup();
+
+ return (int)res;
+}
+
diff --git a/tests/libtest/lib1534.c b/tests/libtest/lib1534.c
new file mode 100644
index 00000000..61e72abb
--- /dev/null
+++ b/tests/libtest/lib1534.c
@@ -0,0 +1,129 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "memdebug.h"
+
+/* Test CURLINFO_FILETIME */
+
+int test(char *URL)
+{
+ CURL *curl, *dupe = NULL;
+ long filetime;
+ int res = CURLE_OK;
+
+ global_init(CURL_GLOBAL_ALL);
+
+ easy_init(curl);
+
+ /* Test that a filetime is properly initialized on curl_easy_init.
+ */
+
+ res = curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
+ if(res) {
+ fprintf(stderr, "%s:%d curl_easy_getinfo() failed with code %d (%s)\n",
+ __FILE__, __LINE__, res, curl_easy_strerror(res));
+ goto test_cleanup;
+ }
+ if(filetime != -1) {
+ fprintf(stderr, "%s:%d filetime init failed; expected -1 but is %ld\n",
+ __FILE__, __LINE__, filetime);
+ res = CURLE_FAILED_INIT;
+ goto test_cleanup;
+ }
+
+ easy_setopt(curl, CURLOPT_URL, URL);
+ easy_setopt(curl, CURLOPT_FILETIME, 1L);
+
+ res = curl_easy_perform(curl);
+ if(res) {
+ fprintf(stderr, "%s:%d curl_easy_perform() failed with code %d (%s)\n",
+ __FILE__, __LINE__, res, curl_easy_strerror(res));
+ goto test_cleanup;
+ }
+
+ /* Test that a filetime is properly set after receiving an HTTP resource.
+ */
+
+ res = curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
+ if(res) {
+ fprintf(stderr, "%s:%d curl_easy_getinfo() failed with code %d (%s)\n",
+ __FILE__, __LINE__, res, curl_easy_strerror(res));
+ goto test_cleanup;
+ }
+ if(filetime != 30) {
+ fprintf(stderr, "%s:%d filetime of http resource is incorrect; "
+ "expected 30 but is %ld\n",
+ __FILE__, __LINE__, filetime);
+ res = CURLE_HTTP_RETURNED_ERROR;
+ goto test_cleanup;
+ }
+
+ /* Test that a filetime is properly initialized on curl_easy_duphandle.
+ */
+
+ dupe = curl_easy_duphandle(curl);
+ if(!dupe) {
+ fprintf(stderr, "%s:%d curl_easy_duphandle() failed\n",
+ __FILE__, __LINE__);
+ res = CURLE_FAILED_INIT;
+ goto test_cleanup;
+ }
+
+ res = curl_easy_getinfo(dupe, CURLINFO_FILETIME, &filetime);
+ if(res) {
+ fprintf(stderr, "%s:%d curl_easy_getinfo() failed with code %d (%s)\n",
+ __FILE__, __LINE__, res, curl_easy_strerror(res));
+ goto test_cleanup;
+ }
+ if(filetime != -1) {
+ fprintf(stderr, "%s:%d filetime init failed; expected -1 but is %ld\n",
+ __FILE__, __LINE__, filetime);
+ res = CURLE_FAILED_INIT;
+ goto test_cleanup;
+ }
+
+
+ /* Test that a filetime is properly initialized on curl_easy_reset.
+ */
+
+ curl_easy_reset(curl);
+
+ res = curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
+ if(res) {
+ fprintf(stderr, "%s:%d curl_easy_getinfo() failed with code %d (%s)\n",
+ __FILE__, __LINE__, res, curl_easy_strerror(res));
+ goto test_cleanup;
+ }
+ if(filetime != -1) {
+ fprintf(stderr, "%s:%d filetime init failed; expected -1 but is %ld\n",
+ __FILE__, __LINE__, filetime);
+ res = CURLE_FAILED_INIT;
+ goto test_cleanup;
+ }
+
+test_cleanup:
+ curl_easy_cleanup(curl);
+ curl_easy_cleanup(dupe);
+ curl_global_cleanup();
+ return res;
+}
diff --git a/tests/libtest/lib507.c b/tests/libtest/lib507.c
index 74879929..ebe897ac 100644
--- a/tests/libtest/lib507.c
+++ b/tests/libtest/lib507.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,8 +29,8 @@
int test(char *URL)
{
- CURL* curls = NULL;
- CURLM* multi = NULL;
+ CURL *curls = NULL;
+ CURLM *multi = NULL;
int still_running;
int i = -1;
int res = 0;
diff --git a/tests/libtest/lib517.c b/tests/libtest/lib517.c
index 2f68ebd2..22162ff1 100644
--- a/tests/libtest/lib517.c
+++ b/tests/libtest/lib517.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -116,6 +116,12 @@ static const char * const dates[]={
"20111323 12:34:56",
"20110623 12:34:79",
"Wed, 31 Dec 2008 23:59:60 GMT", /* leap second */
+ "20110623 12:3",
+ "20110623 1:3",
+ "20110623 1:30",
+ "20110623 12:12:3",
+ "20110623 01:12:3",
+ "20110623 01:99:30",
NULL
};
diff --git a/tests/libtest/lib539.c b/tests/libtest/lib539.c
index 9f0f8fab..ec4ea530 100644
--- a/tests/libtest/lib539.c
+++ b/tests/libtest/lib539.c
@@ -42,7 +42,7 @@ int test(char *URL)
}
/*
- * Begin with cURL set to use a single CWD to the URL's directory.
+ * Begin with curl set to use a single CWD to the URL's directory.
*/
test_setopt(curl, CURLOPT_URL, URL);
test_setopt(curl, CURLOPT_VERBOSE, 1L);
@@ -53,7 +53,7 @@ int test(char *URL)
/*
* Change the FTP_FILEMETHOD option to use full paths rather than a CWD
* command. Alter the URL's path a bit, appending a "./". Use an innocuous
- * QUOTE command, after which cURL will CWD to ftp_conn->entrypath and then
+ * QUOTE command, after which curl will CWD to ftp_conn->entrypath and then
* (on the next call to ftp_statemach_act) find a non-zero ftpconn->dirdepth
* even though no directories are stored in the ftpconn->dirs array (after a
* call to freedirs).
diff --git a/tests/libtest/lib540.c b/tests/libtest/lib540.c
index 9b3b5a40..f5d89c41 100644
--- a/tests/libtest/lib540.c
+++ b/tests/libtest/lib540.c
@@ -48,7 +48,7 @@
CURL *eh[NUM_HANDLES];
-static int init(int num, CURLM *cm, const char* url, const char* userpwd,
+static int init(int num, CURLM *cm, const char *url, const char *userpwd,
struct curl_slist *headers)
{
int res = 0;
@@ -99,7 +99,7 @@ init_failed:
return res; /* failure */
}
-static int loop(int num, CURLM *cm, const char* url, const char* userpwd,
+static int loop(int num, CURLM *cm, const char *url, const char *userpwd,
struct curl_slist *headers)
{
CURLMsg *msg;
diff --git a/tests/libtest/lib543.c b/tests/libtest/lib543.c
index 8fec052d..90aed219 100644
--- a/tests/libtest/lib543.c
+++ b/tests/libtest/lib543.c
@@ -43,7 +43,7 @@ int test(char *URL)
asize = (int)sizeof(a);
- s = curl_easy_escape(easy, (char*)a, asize);
+ s = curl_easy_escape(easy, (char *)a, asize);
if(s)
printf("%s\n", s);
diff --git a/tests/libtest/lib552.c b/tests/libtest/lib552.c
index 9fe4a716..94c93252 100644
--- a/tests/libtest/lib552.c
+++ b/tests/libtest/lib552.c
@@ -147,7 +147,7 @@ static size_t write_callback(void *ptr, size_t size, size_t nmemb,
}
-static curlioerr ioctl_callback(CURL * handle, int cmd, void *clientp)
+static curlioerr ioctl_callback(CURL *handle, int cmd, void *clientp)
{
(void)clientp;
if(cmd == CURLIOCMD_RESTARTREAD) {
diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c
index 5bdb8abe..683ca089 100644
--- a/tests/libtest/lib557.c
+++ b/tests/libtest/lib557.c
@@ -1422,11 +1422,115 @@ static int test_string_formatting(void)
return errors;
}
+static int test_weird_arguments(void)
+{
+ int errors = 0;
+ char buf[256];
+ int rc;
+
+ /* MAX_PARAMETERS is 128, try exact 128! */
+ rc = curl_msnprintf(buf, sizeof(buf),
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 1 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 2 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 3 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 4 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 5 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 6 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 7 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 8 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 9 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 10 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 11 */
+ "%d%d%d%d%d%d%d%d" /* 8 */
+ ,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 1 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 2 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 3 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 4 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 5 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 6 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 7 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 8 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 9 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 10 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 11 */
+ 0, 1, 2, 3, 4, 5, 6, 7); /* 8 */
+
+ if(rc != 128) {
+ printf("curl_mprintf() returned %d and not 128!\n", rc);
+ errors++;
+ }
+
+ errors += string_check(buf,
+ "0123456789" /* 10 */
+ "0123456789" /* 10 1 */
+ "0123456789" /* 10 2 */
+ "0123456789" /* 10 3 */
+ "0123456789" /* 10 4 */
+ "0123456789" /* 10 5 */
+ "0123456789" /* 10 6 */
+ "0123456789" /* 10 7 */
+ "0123456789" /* 10 8 */
+ "0123456789" /* 10 9 */
+ "0123456789" /* 10 10*/
+ "0123456789" /* 10 11 */
+ "01234567" /* 8 */
+ );
+
+ /* MAX_PARAMETERS is 128, try more! */
+ buf[0] = 0;
+ rc = curl_msnprintf(buf, sizeof(buf),
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 1 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 2 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 3 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 4 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 5 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 6 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 7 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 8 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 9 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 10 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 11 */
+ "%d%d%d%d%d%d%d%d%d" /* 9 */
+ ,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 1 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 2 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 3 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 4 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 5 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 6 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 7 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 8 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 9 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 10 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 11 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8); /* 9 */
+
+ if(rc != -1) {
+ printf("curl_mprintf() returned %d and not -1!\n", rc);
+ errors++;
+ }
+
+ errors += string_check(buf, "");
+
+ if(errors)
+ printf("Some curl_mprintf() weird arguments tests failed!\n");
+
+ return errors;
+}
+
+
int test(char *URL)
{
int errors = 0;
(void)URL; /* not used */
+ errors += test_weird_arguments();
+
errors += test_unsigned_short_formatting();
errors += test_signed_short_formatting();
diff --git a/tests/libtest/lib571.c b/tests/libtest/lib571.c
index ad6c366b..32648ad1 100644
--- a/tests/libtest/lib571.c
+++ b/tests/libtest/lib571.c
@@ -50,7 +50,8 @@ static const char *RTP_DATA = "$_1234\n\0asdf";
static int rtp_packet_count = 0;
-static size_t rtp_write(void *ptr, size_t size, size_t nmemb, void *stream) {
+static size_t rtp_write(void *ptr, size_t size, size_t nmemb, void *stream)
+{
char *data = (char *)ptr;
int channel = RTP_PKT_CHANNEL(data);
int message_size;
diff --git a/tests/libtest/lib582.c b/tests/libtest/lib582.c
index 444b416f..eec0455f 100644
--- a/tests/libtest/lib582.c
+++ b/tests/libtest/lib582.c
@@ -145,10 +145,10 @@ static int curlTimerCallback(CURLM *multi, long timeout_ms, void *userp)
/**
* Check for curl completion.
*/
-static int checkForCompletion(CURLM* curl, int* success)
+static int checkForCompletion(CURLM *curl, int *success)
{
int numMessages;
- CURLMsg* message;
+ CURLMsg *message;
int result = 0;
*success = 0;
while((message = curl_multi_info_read(curl, &numMessages)) != NULL) {
diff --git a/tests/libtest/lib583.c b/tests/libtest/lib583.c
index 9af48d28..5b11fab2 100644
--- a/tests/libtest/lib583.c
+++ b/tests/libtest/lib583.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,8 +33,8 @@
int test(char *URL)
{
int stillRunning;
- CURLM* multiHandle = NULL;
- CURL* curl = NULL;
+ CURLM *multiHandle = NULL;
+ CURL *curl = NULL;
int res = 0;
global_init(CURL_GLOBAL_ALL);
diff --git a/tests/libtest/libauthretry.c b/tests/libtest/libauthretry.c
index 994f9de0..065a79d4 100644
--- a/tests/libtest/libauthretry.c
+++ b/tests/libtest/libauthretry.c
@@ -25,7 +25,6 @@
*/
#include "test.h"
-#include "strequal.h"
#include "memdebug.h"
static CURLcode send_request(CURL *curl, const char *url, int seq,
@@ -33,7 +32,7 @@ static CURLcode send_request(CURL *curl, const char *url, int seq,
{
CURLcode res;
size_t len = strlen(url) + 4 + 1;
- char* full_url = malloc(len);
+ char *full_url = malloc(len);
if(!full_url) {
fprintf(stderr, "Not enough memory for full url\n");
return CURLE_OUT_OF_MEMORY;
@@ -72,11 +71,11 @@ static long parse_auth_name(const char *arg)
{
if(!arg)
return CURLAUTH_NONE;
- if(strequal(arg, "basic"))
+ if(curl_strequal(arg, "basic"))
return CURLAUTH_BASIC;
- if(strequal(arg, "digest"))
+ if(curl_strequal(arg, "digest"))
return CURLAUTH_DIGEST;
- if(strequal(arg, "ntlm"))
+ if(curl_strequal(arg, "ntlm"))
return CURLAUTH_NTLM;
return CURLAUTH_NONE;
}
diff --git a/tests/libtest/libntlmconnect.c b/tests/libtest/libntlmconnect.c
index 736222dc..40a837ca 100644
--- a/tests/libtest/libntlmconnect.c
+++ b/tests/libtest/libntlmconnect.c
@@ -37,7 +37,7 @@ static CURL *easy[MAX_EASY_HANDLES];
static curl_socket_t sockets[MAX_EASY_HANDLES];
static int res = 0;
-static size_t callback(char* ptr, size_t size, size_t nmemb, void* data)
+static size_t callback(char *ptr, size_t size, size_t nmemb, void *data)
{
ssize_t idx = ((CURL **) data) - easy;
curl_socket_t sock;
@@ -104,7 +104,7 @@ int test(char *url)
int num_handles = 0;
enum HandleState state = ReadyForNewHandle;
size_t urllen = strlen(url) + 4 + 1;
- char* full_url = malloc(urllen);
+ char *full_url = malloc(urllen);
start_test_timing();
diff --git a/tests/libtest/test.h b/tests/libtest/test.h
index 9647658d..9fd33aa7 100644
--- a/tests/libtest/test.h
+++ b/tests/libtest/test.h
@@ -112,7 +112,7 @@ extern int unitfail;
** label 'test_cleanup' is performed.
**
** Every easy_* and multi_* macros have a res_easy_* and res_multi_* macro
-** counterpart that operates in tha same way with the exception that no
+** counterpart that operates in the same way with the exception that no
** jump takes place in case of failure. res_easy_* and res_multi_* macros
** should be immediately followed by checking if 'res' variable has been
** set.
diff --git a/tests/pathhelp.pm b/tests/pathhelp.pm
index 391ef6c2..10a87aaf 100644
--- a/tests/pathhelp.pm
+++ b/tests/pathhelp.pm
@@ -20,7 +20,7 @@
#
###########################################################################
-# This Perl package helps with path transforming when running cURL tests on
+# This Perl package helps with path transforming when running curl tests on
# Win32 platform with Msys or Cygwin.
# Three main functions 'sys_native_abs_path', 'sys_native_path' and
# 'build_sys_abs_path' autodetect format of given pathnames. Following formats
diff --git a/tests/server/Makefile.inc b/tests/server/Makefile.inc
index 6e81dfdb..c3ea664b 100644
--- a/tests/server/Makefile.inc
+++ b/tests/server/Makefile.inc
@@ -3,7 +3,6 @@ noinst_PROGRAMS = getpart resolve rtspd sockfilt sws tftpd fake_ntlm
CURLX_SRCS = \
../../lib/mprintf.c \
../../lib/nonblock.c \
- ../../lib/strequal.c \
../../lib/strtoofft.c \
../../lib/timeval.c \
../../lib/warnless.c
@@ -11,7 +10,6 @@ CURLX_SRCS = \
CURLX_HDRS = \
../../lib/curlx.h \
../../lib/nonblock.h \
- ../../lib/strequal.h \
../../lib/strtoofft.h \
../../lib/timeval.h \
../../lib/warnless.h
diff --git a/tests/server/rtspd.c b/tests/server/rtspd.c
index 91ef6c62..e759e880 100644
--- a/tests/server/rtspd.c
+++ b/tests/server/rtspd.c
@@ -129,7 +129,7 @@ static void storerequest(char *reqbuf, size_t totalsize);
const char *serverlogfile = DEFAULT_LOGFILE;
-#define RTSPDVERSION "cURL test suite RTSP server/0.1"
+#define RTSPDVERSION "curl test suite RTSP server/0.1"
#define REQUEST_DUMP "log/server.input"
#define RESPONSE_DUMP "log/server.response"
@@ -590,7 +590,7 @@ static int ProcessRequest(struct httprequest *req)
if(got_exit_signal)
return 1; /* done */
- if((req->cl==0) && curlx_strnequal("Content-Length:", line, 15)) {
+ if((req->cl==0) && strncasecompare("Content-Length:", line, 15)) {
/* If we don't ignore content-length, we read it and we read the whole
request including the body before we return. If we've been told to
ignore the content-length, we will return as soon as all headers
@@ -616,7 +616,7 @@ static int ProcessRequest(struct httprequest *req)
logmsg("... but will abort after %zu bytes", req->cl);
break;
}
- else if(curlx_strnequal("Transfer-Encoding: chunked", line,
+ else if(strncasecompare("Transfer-Encoding: chunked", line,
strlen("Transfer-Encoding: chunked"))) {
/* chunked data coming in */
chunked = TRUE;
diff --git a/tests/server/sws.c b/tests/server/sws.c
index 27c86e01..af0904e2 100644
--- a/tests/server/sws.c
+++ b/tests/server/sws.c
@@ -140,7 +140,7 @@ static void storerequest(char *reqbuf, size_t totalsize);
const char *serverlogfile = DEFAULT_LOGFILE;
-#define SWSVERSION "cURL test suite HTTP server/0.1"
+#define SWSVERSION "curl test suite HTTP server/0.1"
#define REQUEST_DUMP "log/server.input"
#define RESPONSE_DUMP "log/server.response"
@@ -697,7 +697,7 @@ static int ProcessRequest(struct httprequest *req)
if(got_exit_signal)
return 1; /* done */
- if((req->cl==0) && curlx_strnequal("Content-Length:", line, 15)) {
+ if((req->cl==0) && strncasecompare("Content-Length:", line, 15)) {
/* If we don't ignore content-length, we read it and we read the whole
request including the body before we return. If we've been told to
ignore the content-length, we will return as soon as all headers
@@ -723,7 +723,7 @@ static int ProcessRequest(struct httprequest *req)
logmsg("... but will abort after %zu bytes", req->cl);
break;
}
- else if(curlx_strnequal("Transfer-Encoding: chunked", line,
+ else if(strncasecompare("Transfer-Encoding: chunked", line,
strlen("Transfer-Encoding: chunked"))) {
/* chunked data coming in */
chunked = TRUE;
@@ -2231,9 +2231,9 @@ int main(int argc, char *argv[])
/* Clear out closed sockets */
for(socket_idx = num_sockets - 1; socket_idx >= 1; --socket_idx) {
if(CURL_SOCKET_BAD == all_sockets[socket_idx]) {
- char* dst = (char *) (all_sockets + socket_idx);
- char* src = (char *) (all_sockets + socket_idx + 1);
- char* end = (char *) (all_sockets + num_sockets);
+ char *dst = (char *) (all_sockets + socket_idx);
+ char *src = (char *) (all_sockets + socket_idx + 1);
+ char *end = (char *) (all_sockets + num_sockets);
memmove(dst, src, end - src);
num_sockets -= 1;
}
diff --git a/tests/server/tftpd.c b/tests/server/tftpd.c
index afc0884e..8a4ed0b1 100644
--- a/tests/server/tftpd.c
+++ b/tests/server/tftpd.c
@@ -15,7 +15,7 @@
*/
/*
- * Copyright (c) 1983 Regents of the University of California.
+ * Copyright (c) 1983, 2016 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1040,10 +1040,10 @@ static int do_tftp(struct testcase *test, struct tftphdr *tp, ssize_t size)
#ifdef USE_WINSOCK
recvtimeout = sizeof(recvtimeoutbak);
getsockopt(peer, SOL_SOCKET, SO_RCVTIMEO,
- (char*)&recvtimeoutbak, (int*)&recvtimeout);
+ (char *)&recvtimeoutbak, (int *)&recvtimeout);
recvtimeout = TIMEOUT*1000;
setsockopt(peer, SOL_SOCKET, SO_RCVTIMEO,
- (const char*)&recvtimeout, sizeof(recvtimeout));
+ (const char *)&recvtimeout, sizeof(recvtimeout));
#endif
if(tp->th_opcode == opcode_WRQ)
@@ -1054,7 +1054,7 @@ static int do_tftp(struct testcase *test, struct tftphdr *tp, ssize_t size)
#ifdef USE_WINSOCK
recvtimeout = recvtimeoutbak;
setsockopt(peer, SOL_SOCKET, SO_RCVTIMEO,
- (const char*)&recvtimeout, sizeof(recvtimeout));
+ (const char *)&recvtimeout, sizeof(recvtimeout));
#endif
return 0;
@@ -1232,19 +1232,17 @@ static void sendtftp(struct testcase *test, struct formats *pf)
{
int size;
ssize_t n;
- /* This is volatile to live through a siglongjmp */
+ /* These are volatile to live through a siglongjmp */
volatile unsigned short sendblock; /* block count */
- struct tftphdr *sdp; /* data buffer */
- struct tftphdr *sap; /* ack buffer */
+ struct tftphdr * volatile sdp = r_init(); /* data buffer */
+ struct tftphdr * const sap = &ackbuf.hdr; /* ack buffer */
sendblock = 1;
#if defined(HAVE_ALARM) && defined(SIGALRM)
mysignal(SIGALRM, timer);
#endif
- sdp = r_init();
- sap = &ackbuf.hdr;
do {
- size = readit(test, &sdp, pf->f_convert);
+ size = readit(test, (struct tftphdr **)&sdp, pf->f_convert);
if(size < 0) {
nak(errno + 100);
return;
diff --git a/tests/server/util.c b/tests/server/util.c
index d9933639..e6547078 100644
--- a/tests/server/util.c
+++ b/tests/server/util.c
@@ -305,3 +305,87 @@ void clear_advisor_read_lock(const char *filename)
logmsg("Error removing lock file %s error: %d %s",
filename, error, strerror(error));
}
+
+
+/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because
+ its behavior is altered by the current locale. */
+static char raw_toupper(char in)
+{
+#if !defined(CURL_DOES_CONVERSIONS)
+ if(in >= 'a' && in <= 'z')
+ return (char)('A' + in - 'a');
+#else
+ switch (in) {
+ case 'a':
+ return 'A';
+ case 'b':
+ return 'B';
+ case 'c':
+ return 'C';
+ case 'd':
+ return 'D';
+ case 'e':
+ return 'E';
+ case 'f':
+ return 'F';
+ case 'g':
+ return 'G';
+ case 'h':
+ return 'H';
+ case 'i':
+ return 'I';
+ case 'j':
+ return 'J';
+ case 'k':
+ return 'K';
+ case 'l':
+ return 'L';
+ case 'm':
+ return 'M';
+ case 'n':
+ return 'N';
+ case 'o':
+ return 'O';
+ case 'p':
+ return 'P';
+ case 'q':
+ return 'Q';
+ case 'r':
+ return 'R';
+ case 's':
+ return 'S';
+ case 't':
+ return 'T';
+ case 'u':
+ return 'U';
+ case 'v':
+ return 'V';
+ case 'w':
+ return 'W';
+ case 'x':
+ return 'X';
+ case 'y':
+ return 'Y';
+ case 'z':
+ return 'Z';
+ }
+#endif
+
+ return in;
+}
+
+int strncasecompare(const char *first, const char *second, size_t max)
+{
+ while(*first && *second && max) {
+ if(raw_toupper(*first) != raw_toupper(*second)) {
+ break;
+ }
+ max--;
+ first++;
+ second++;
+ }
+ if(0 == max)
+ return 1; /* they are equal this far */
+
+ return raw_toupper(*first) == raw_toupper(*second);
+}
diff --git a/tests/server/util.h b/tests/server/util.h
index 2a19a613..c90fcdf3 100644
--- a/tests/server/util.h
+++ b/tests/server/util.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -63,4 +63,6 @@ void set_advisor_read_lock(const char *filename);
void clear_advisor_read_lock(const char *filename);
+int strncasecompare(const char *first, const char *second, size_t max);
+
#endif /* HEADER_CURL_SERVER_UTIL_H */
diff --git a/tests/testcurl.1 b/tests/testcurl.1
index 509f5dcc..ee07d64f 100644
--- a/tests/testcurl.1
+++ b/tests/testcurl.1
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -32,7 +32,7 @@ crontab job or similar at a regular interval. The output is suitable to be
mailed to curl-autocompile@haxx.se to be dealt with automatically (make sure
the subject includes the word "autobuild" as the mail gets silently discarded
otherwise). The most current build status (with a reasonable backlog) will be
-published on the curl site, at https://curl.haxx.se/auto/
+published on the curl site, at https://curl.haxx.se/dev/builds.html
\fIoptions\fP may be omitted. See \fI--setup\fP for what happens then.
@@ -78,13 +78,13 @@ Specify your target environment. Recognized strings include 'vc', 'mingw32',
\&'borland' and 'netware'.
.SH "INITIAL SETUP"
First you make a checkout from git (or you write a script that downloads daily
-snapshots automatically, find inspiration at
-https://curl.haxx.se/auto/autocurl.txt):
+snapshots automatically, find inspiration in
+https://curl.haxx.se/dev/autocurl.txt ):
.nf
$ mkdir daily-curl
$ cd daily-curl
- $ git clone git://github.com/curl/curl.git
+ $ git clone https://github.com/curl/curl.git
.fi
With the curl sources checked out, or downloaded, you can start testing right
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
index e6667988..14589d68 100644
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -40,7 +40,15 @@ foreach(_testfile ${UT_SRC})
set_target_properties(${_testname}
PROPERTIES COMPILE_DEFINITIONS "UNITTESTS")
- add_test(NAME ${_testname}
- COMMAND ${_testname} "http://www.google.com"
- )
+ if(HIDES_CURL_PRIVATE_SYMBOLS)
+ set_target_properties(${_testname}
+ PROPERTIES
+ EXCLUDE_FROM_ALL TRUE
+ EXCLUDE_FROM_DEFAULT_BUILD TRUE
+ )
+ else()
+ add_test(NAME ${_testname}
+ COMMAND ${_testname} "http://www.google.com"
+ )
+ endif()
endforeach()
diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am
index d4987d69..7075f8c3 100644
--- a/tests/unit/Makefile.am
+++ b/tests/unit/Makefile.am
@@ -54,7 +54,7 @@ AM_CPPFLAGS = -I$(top_builddir)/include/curl \
-I$(top_srcdir)/tests/libtest
endif
-EXTRA_DIST = Makefile.inc
+EXTRA_DIST = Makefile.inc CMakeLists.txt
# Prevent LIBS from being used for all link targets
LIBS = $(BLANK_AT_MAKETIME)
diff --git a/tests/unit/Makefile.inc b/tests/unit/Makefile.inc
index c5a15237..e7db96f5 100644
--- a/tests/unit/Makefile.inc
+++ b/tests/unit/Makefile.inc
@@ -7,7 +7,7 @@ UNITFILES = curlcheck.h \
# These are all unit test programs
UNITPROGS = unit1300 unit1301 unit1302 unit1303 unit1304 unit1305 unit1307 \
unit1308 unit1309 unit1330 unit1394 unit1395 unit1396 unit1397 unit1398 \
- unit1600 unit1601 unit1602 unit1603 unit1604
+ unit1600 unit1601 unit1602 unit1603 unit1604 unit1605
unit1300_SOURCES = unit1300.c $(UNITFILES)
unit1300_CPPFLAGS = $(AM_CPPFLAGS)
@@ -72,3 +72,5 @@ unit1603_CPPFLAGS = $(AM_CPPFLAGS)
unit1604_SOURCES = unit1604.c $(UNITFILES)
unit1604_CPPFLAGS = $(AM_CPPFLAGS) $(LIBMETALINK_CPPFLAGS)
+unit1605_SOURCES = unit1605.c $(UNITFILES)
+unit1605_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/tests/unit/unit1301.c b/tests/unit/unit1301.c
index 928076e2..aa861011 100644
--- a/tests/unit/unit1301.c
+++ b/tests/unit/unit1301.c
@@ -21,7 +21,7 @@
***************************************************************************/
#include "curlcheck.h"
-#include "strequal.h"
+#include "strcase.h"
static CURLcode unit_setup(void) {return CURLE_OK;}
static void unit_stop(void) {}
diff --git a/tests/unit/unit1303.c b/tests/unit/unit1303.c
index a4bd5982..c39e147a 100644
--- a/tests/unit/unit1303.c
+++ b/tests/unit/unit1303.c
@@ -69,12 +69,12 @@ struct timetest {
};
UNITTEST_START
+{
+ struct timeval now;
+ long timeout;
+ unsigned int i;
-struct timeval now;
-long timeout;
-unsigned int i;
-
-const struct timetest run[] = {
+ const struct timetest run[] = {
/* both timeouts set, not connecting */
{BASE + 4, 0, 10000, 8000, FALSE, 6000, "6 seconds should be left"},
{BASE + 4, 990000, 10000, 8000, FALSE, 5010, "5010 ms should be left"},
@@ -126,21 +126,20 @@ const struct timetest run[] = {
/* both timeouts set, connecting, connect timeout the longer one */
{BASE + 4, 0, 10000, 12000, TRUE, 6000, "6 seconds should be left"},
-};
-
-/* this is the pretended start time of the transfer */
-data->progress.t_startsingle.tv_sec = BASE;
-data->progress.t_startsingle.tv_usec = 0;
-data->progress.t_startop.tv_sec = BASE;
-data->progress.t_startop.tv_usec = 0;
-
-for(i=0; i < sizeof(run)/sizeof(run[0]); i++) {
- NOW(run[i].now_s, run[i].now_us);
- TIMEOUTS(run[i].timeout_ms, run[i].connecttimeout_ms);
- timeout = Curl_timeleft(data, &now, run[i].connecting);
- if(timeout != run[i].result)
- fail(run[i].comment);
+ };
+
+ /* this is the pretended start time of the transfer */
+ data->progress.t_startsingle.tv_sec = BASE;
+ data->progress.t_startsingle.tv_usec = 0;
+ data->progress.t_startop.tv_sec = BASE;
+ data->progress.t_startop.tv_usec = 0;
+
+ for(i=0; i < sizeof(run)/sizeof(run[0]); i++) {
+ NOW(run[i].now_s, run[i].now_us);
+ TIMEOUTS(run[i].timeout_ms, run[i].connecttimeout_ms);
+ timeout = Curl_timeleft(data, &now, run[i].connecting);
+ if(timeout != run[i].result)
+ fail(run[i].comment);
+ }
}
-
-
UNITTEST_STOP
diff --git a/tests/unit/unit1304.c b/tests/unit/unit1304.c
index 11bba390..83375f55 100644
--- a/tests/unit/unit1304.c
+++ b/tests/unit/unit1304.c
@@ -48,7 +48,7 @@ static void unit_stop(void)
UNITTEST_START
int result;
- static const char* const filename1 = "log/netrc1304";
+ static const char * const filename1 = "log/netrc1304";
memcpy(filename, filename1, strlen(filename1));
/*
diff --git a/tests/unit/unit1308.c b/tests/unit/unit1308.c
index 968bcff2..5c1a0086 100644
--- a/tests/unit/unit1308.c
+++ b/tests/unit/unit1308.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,8 +42,8 @@ static size_t print_httppost_callback(void *arg, const char *buf, size_t len)
UNITTEST_START
int rc;
- struct curl_httppost* post = NULL;
- struct curl_httppost* last = NULL;
+ struct curl_httppost *post = NULL;
+ struct curl_httppost *last = NULL;
size_t total_size = 0;
char buffer[] = "test buffer";
diff --git a/tests/unit/unit1602.c b/tests/unit/unit1602.c
index c67c0a55..5f1ee9f4 100644
--- a/tests/unit/unit1602.c
+++ b/tests/unit/unit1602.c
@@ -32,7 +32,7 @@ static struct curl_hash hash_static;
static void mydtor(void *p)
{
- int *ptr = (int*)p;
+ int *ptr = (int *)p;
free(ptr);
}
diff --git a/tests/unit/unit1604.c b/tests/unit/unit1604.c
index 242be000..5f1ea951 100644
--- a/tests/unit/unit1604.c
+++ b/tests/unit/unit1604.c
@@ -42,7 +42,8 @@ static void unit_stop(void)
#if defined(MSDOS) || defined(WIN32)
-static char *getflagstr(int flags) {
+static char *getflagstr(int flags)
+{
char *buf = malloc(256);
fail_unless(buf, "out of memory");
snprintf(buf, 256, "%s,%s,%s,%s",
@@ -53,7 +54,8 @@ static char *getflagstr(int flags) {
return buf;
}
-static char *getcurlcodestr(int cc) {
+static char *getcurlcodestr(int cc)
+{
char *buf = malloc(256);
fail_unless(buf, "out of memory");
snprintf(buf, 256, "%s (%d)",
diff --git a/lib/strequal.h b/tests/unit/unit1605.c
index ff56df51..c807cb3f 100644
--- a/lib/strequal.h
+++ b/tests/unit/unit1605.c
@@ -1,5 +1,3 @@
-#ifndef HEADER_CURL_STREQUAL_H
-#define HEADER_CURL_STREQUAL_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,11 +19,31 @@
* KIND, either express or implied.
*
***************************************************************************/
+#include "curlcheck.h"
-#include <curl/curl.h>
+#include "llist.h"
-#define strequal(a,b) curl_strequal(a,b)
-#define strnequal(a,b,c) curl_strnequal(a,b,c)
+static CURLcode unit_setup(void)
+{
+ return CURLE_OK;
+}
-#endif /* HEADER_CURL_STREQUAL_H */
+static void unit_stop(void)
+{
+}
+
+UNITTEST_START
+ CURL *easy = curl_easy_init();
+ int len;
+ char *esc;
+
+ esc = curl_easy_escape(easy, "", -1);
+ fail_unless(esc == NULL, "negative string length can't work");
+
+ esc = curl_easy_unescape(easy, "%41%41%41%41", -1, &len);
+ fail_unless(esc == NULL, "negative string length can't work");
+
+ curl_easy_cleanup(easy);
+
+UNITTEST_STOP
diff --git a/winbuild/Makefile.vc b/winbuild/Makefile.vc
index 4f90e4a2..9ef7c145 100644
--- a/winbuild/Makefile.vc
+++ b/winbuild/Makefile.vc
@@ -21,9 +21,11 @@ CFGSET=true
!MESSAGE Libraries can be fetched at http://pecl2.php.net/downloads/php-windows-builds/
!MESSAGE Uncompress them into the deps folder.
!MESSAGE WITH_SSL=<dll or static> - Enable OpenSSL support, DLL or static
+!MESSAGE WITH_NGHTTP2=<dll or static> - Enable HTTP/2 support, DLL or static
!MESSAGE WITH_CARES=<dll or static> - Enable c-ares support, DLL or static
!MESSAGE WITH_ZLIB=<dll or static> - Enable zlib support, DLL or static
!MESSAGE WITH_SSH2=<dll or static> - Enable libSSH2 support, DLL or static
+!MESSAGE WITH_MBEDTLS=<dll or static> - Enable mbedTLS support, DLL or static
!MESSAGE ENABLE_IDN=<yes or no> - Enable use of Windows IDN APIs, defaults to yes
!MESSAGE Requires Windows Vista or later, or installation from:
!MESSAGE https://www.microsoft.com/en-us/download/details.aspx?id=734
@@ -54,7 +56,10 @@ ENABLE_SSPI = $(USE_SSPI)
!ENDIF
# default options
+
!IFNDEF MACHINE
+# Note: nmake magically changes the value of PROCESSOR_ARCHITECTURE from "AMD64"
+# to "x86" when building in a 32 bit build environment on a 64 bit machine.
!IF "$(PROCESSOR_ARCHITECTURE)"=="AMD64"
MACHINE = x64
!ELSE
@@ -87,7 +92,7 @@ USE_SSPI = false
!ENDIF
!IFNDEF ENABLE_WINSSL
-!IFDEF WITH_SSL
+!IF DEFINED(WITH_SSL) || DEFINED(WITH_MBEDTLS)
USE_WINSSL = false
!ELSE
USE_WINSSL = $(USE_SSPI)
@@ -108,6 +113,34 @@ USE_SSL = true
SSL = static
!ENDIF
+!IF "$(ENABLE_NGHTTP2)"=="yes"
+# compatibility bit, WITH_NGHTTP2 is the correct flag
+WITH_NGHTTP2 = dll
+USE_NGHTTP2 = true
+NGHTTP2 = dll
+!ELSEIF "$(WITH_NGHTTP2)"=="dll"
+USE_NGHTTP2 = true
+NGHTTP2 = dll
+!ELSEIF "$(WITH_NGHTTP2)"=="static"
+USE_NGHTTP2 = true
+NGHTTP2 = static
+!ENDIF
+
+!IFNDEF USE_NGHTTP2
+USE_NGHTTP2 = false
+!ENDIF
+
+!IF "$(WITH_MBEDTLS)"=="dll" || "$(WITH_MBEDTLS)"=="static"
+USE_MBEDTLS = true
+MBEDTLS = $(WITH_MBEDTLS)
+!ENDIF
+
+!IF ( "$(USE_SSL)"=="true" && "$(USE_WINSSL)"=="true" ) \
+ || ( "$(USE_SSL)"=="true" && "$(USE_MBEDTLS)"=="true" ) \
+ || ( "$(USE_MBEDTLS)"=="true" && "$(USE_WINSSL)"=="true" )
+!ERROR SSL, MBEDTLS and WINSSL are mutual exclusive options.
+!ENDIF
+
!IF "$(WITH_CARES)"=="dll"
USE_CARES = true
CARES = dll
@@ -150,6 +183,10 @@ CONFIG_NAME_LIB = $(CONFIG_NAME_LIB)-static
CONFIG_NAME_LIB = $(CONFIG_NAME_LIB)-ssl-$(SSL)
!ENDIF
+!IF "$(USE_MBEDTLS)"=="true"
+CONFIG_NAME_LIB = $(CONFIG_NAME_LIB)-mbedtls-$(MBEDTLS)
+!ENDIF
+
!IF "$(USE_CARES)"=="true"
CONFIG_NAME_LIB = $(CONFIG_NAME_LIB)-cares-$(CARES)
!ENDIF
@@ -174,6 +211,10 @@ CONFIG_NAME_LIB = $(CONFIG_NAME_LIB)-sspi
CONFIG_NAME_LIB = $(CONFIG_NAME_LIB)-winssl
!ENDIF
+!IF "$(USE_NGHTTP2)"=="true"
+CONFIG_NAME_LIB = $(CONFIG_NAME_LIB)-nghttp2-$(NGHTTP2)
+!ENDIF
+
!MESSAGE configuration name: $(CONFIG_NAME_LIB)
BUILD_DIR=../builds/$(CONFIG_NAME_LIB)
@@ -197,10 +238,14 @@ $(MODE):
@SET CONFIG_NAME_LIB=$(CONFIG_NAME_LIB)
@SET MACHINE=$(MACHINE)
+ @SET USE_NGHTTP2=$(USE_NGHTTP2)
@SET USE_IDN=$(USE_IDN)
@SET USE_IPV6=$(USE_IPV6)
@SET USE_SSPI=$(USE_SSPI)
@SET USE_WINSSL=$(USE_WINSSL)
+# compatibility bit
+ @SET WITH_NGHTTP2=$(WITH_NGHTTP2)
+
@$(MAKE) /NOLOGO /F MakefileBuild.vc
copy_from_lib:
diff --git a/winbuild/MakefileBuild.vc b/winbuild/MakefileBuild.vc
index 62a5719a..9351440c 100644
--- a/winbuild/MakefileBuild.vc
+++ b/winbuild/MakefileBuild.vc
@@ -47,13 +47,19 @@ CFGSET=FALSE
WINBUILD_DIR=`cd`
ZIP = zip.exe
+# Allow changing C compiler via environment variable CC (default cl.exe)
+# This command macro is not set by default: https://msdn.microsoft.com/en-us/library/ms933742.aspx
+!If "$(CC)" == ""
+CC = cl.exe
+!Endif
+
!IF "$(VC)"=="6"
-CC_NODEBUG = cl.exe /O2 /DNDEBUG
-CC_DEBUG = cl.exe /Od /Gm /Zi /D_DEBUG /GZ
+CC_NODEBUG = $(CC) /O2 /DNDEBUG
+CC_DEBUG = $(CC) /Od /Gm /Zi /D_DEBUG /GZ
CFLAGS = /I. /I../lib /I../include /nologo /W3 /GX /DWIN32 /YX /FD /c /DBUILDING_LIBCURL
!ELSE
-CC_NODEBUG = cl.exe /O2 /DNDEBUG
-CC_DEBUG = cl.exe /Od /D_DEBUG /RTC1 /Z7 /LDd /W3
+CC_NODEBUG = $(CC) /O2 /DNDEBUG
+CC_DEBUG = $(CC) /Od /D_DEBUG /RTC1 /Z7 /LDd /W3
CFLAGS = /I. /I ../lib /I../include /nologo /W3 /EHsc /DWIN32 /FD /c /DBUILDING_LIBCURL
!ENDIF
@@ -117,8 +123,22 @@ USE_SSL = true
SSL = static
!ENDIF
+!IFNDEF USE_NGHTTP2
+USE_NGHTTP2 = false
+!ENDIF
+
!IFDEF USE_SSL
SSL_CFLAGS = /DUSE_OPENSSL /I"$(DEVEL_INCLUDE)/openssl"
+
+!IF "$(USE_NGHTTP2)"=="yes"
+USE_NGHTTP2 = true
+!ENDIF
+
+!IF "$(USE_NGHTTP2)"=="true"
+SSL_CFLAGS = $(SSL_CFLAGS) /DUSE_NGHTTP2
+SSL_LIBS = $(SSL_LIBS) nghttp2.lib
+!ENDIF
+
!ENDIF
!IF "$(WITH_CARES)"=="dll"
@@ -268,20 +288,14 @@ CFGSET = true
!IF "$(DEBUG)"=="yes"
RC_FLAGS = /dDEBUGBUILD=1 /Fo $@ $(LIBCURL_SRC_DIR)\libcurl.rc
-CC = $(CC_DEBUG) $(RTLIB_DEBUG)
-
-CURL_CC = $(CC)
+CURL_CC = $(CC_DEBUG) $(RTLIB_DEBUG)
CURL_RC_FLAGS = /i../include /dDEBUGBUILD=1 /Fo $@ $(CURL_SRC_DIR)\curl.rc
!ELSE
RC_FLAGS = /dDEBUGBUILD=0 /Fo $@ $(LIBCURL_SRC_DIR)\libcurl.rc
-CC = $(CC_NODEBUG) $(RTLIB)
-
-CURL_CC = $(CC)
+CURL_CC = $(CC_NODEBUG) $(RTLIB)
CURL_RC_FLAGS = /i../include /dDEBUGBUILD=0 /Fo $@ $(CURL_SRC_DIR)\curl.rc
!ENDIF
-CURL_CC = $(CURL_CC) $(CURL_CFLAGS)
-
!IF "$(AS_DLL)" == "true"
LNK = $(LNKDLL) $(WIN_LIBS) /out:$(LIB_DIROBJ)\$(TARGET)
@@ -309,7 +323,7 @@ TARGET = $(LIB_NAME_STATIC)
PDB = $(PDB_NAME_STATIC)
!ENDIF
LNK = $(LNKLIB) $(WIN_LIBS) /out:$(LIB_DIROBJ)\$(TARGET)
-CC = $(CC) $(CFLAGS_LIBCURL_STATIC)
+CURL_CC = $(CURL_CC) $(CFLAGS_LIBCURL_STATIC)
# AS_DLL
!ENDIF
@@ -403,6 +417,7 @@ package: $(TARGET)
$(TARGET): $(LIB_OBJS) $(LIB_DIROBJ) $(DISTDIR)
@echo Using SSL: $(USE_SSL)
+ @echo Using NGHTTP2: $(USE_NGHTTP2)
@echo Using c-ares: $(USE_CARES)
@echo Using SSH2: $(USE_SSH2)
@echo Using ZLIB: $(USE_ZLIB)
@@ -449,13 +464,13 @@ $(CURL_DIROBJ):
.SUFFIXES: .c .obj .res
{$(LIBCURL_SRC_DIR)\}.c{$(LIB_DIROBJ)\}.obj:
- $(CC) $(CFLAGS) /Fo"$@" $<
+ $(CURL_CC) $(CFLAGS) /Fo"$@" $<
{$(LIBCURL_SRC_DIR)\vauth\}.c{$(LIB_DIROBJ)\vauth\}.obj:
- $(CC) $(CFLAGS) /Fo"$@" $<
+ $(CURL_CC) $(CFLAGS) /Fo"$@" $<
{$(LIBCURL_SRC_DIR)\vtls\}.c{$(LIB_DIROBJ)\vtls\}.obj:
- $(CC) $(CFLAGS) /Fo"$@" $<
+ $(CURL_CC) $(CFLAGS) /Fo"$@" $<
$(LIB_DIROBJ)\libcurl.res: $(LIBCURL_SRC_DIR)\libcurl.rc
rc $(RC_FLAGS)
@@ -481,7 +496,6 @@ CURL_LIBCURL_LIBNAME=$(LIB_NAME_IMP)
CURL_FROM_LIBCURL=$(CURL_DIROBJ)\tool_hugehelp.obj \
$(CURL_DIROBJ)\nonblock.obj \
- $(CURL_DIROBJ)\rawstr.obj \
$(CURL_DIROBJ)\strtoofft.obj \
$(CURL_DIROBJ)\warnless.obj
@@ -490,14 +504,12 @@ $(PROGRAM_NAME): $(CURL_DIROBJ) $(CURL_FROM_LIBCURL) $(EXE_OBJS)
$(MANIFESTTOOL)
{$(CURL_SRC_DIR)\}.c{$(CURL_DIROBJ)\}.obj:
- $(CC) $(CURL_CFLAGS) /Fo"$@" $<
+ $(CURL_CC) $(CURL_CFLAGS) /Fo"$@" $<
$(CURL_DIROBJ)\tool_hugehelp.obj: $(CURL_SRC_DIR)\tool_hugehelp.c
$(CURL_CC) $(CURL_CFLAGS) /Zm200 /Fo"$@" $(CURL_SRC_DIR)\tool_hugehelp.c
$(CURL_DIROBJ)\nonblock.obj: ../lib/nonblock.c
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/nonblock.c
-$(CURL_DIROBJ)\rawstr.obj: ../lib/rawstr.c
- $(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/rawstr.c
$(CURL_DIROBJ)\strtoofft.obj: ../lib/strtoofft.c
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/strtoofft.c
$(CURL_DIROBJ)\warnless.obj: ../lib/warnless.c