summaryrefslogtreecommitdiffstats
path: root/Utilities
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities')
-rw-r--r--Utilities/GitSetup/config9
-rw-r--r--Utilities/Release/release_cmake.cmake8
-rwxr-xr-xUtilities/Release/release_cmake.sh.in6
-rwxr-xr-xUtilities/Scripts/update-curl.bash2
-rwxr-xr-xUtilities/Scripts/update-libarchive.bash2
-rwxr-xr-xUtilities/SetupForDevelopment.sh5
-rw-r--r--Utilities/Sphinx/conf.py.in4
-rw-r--r--Utilities/Sphinx/templates/layout.html12
-rw-r--r--Utilities/cmcurl/CMake/OtherTests.cmake25
-rw-r--r--Utilities/cmcurl/CMakeLists.txt8
-rw-r--r--Utilities/cmcurl/include/curl/curl.h84
-rw-r--r--Utilities/cmcurl/include/curl/curlver.h8
-rw-r--r--Utilities/cmcurl/include/curl/easy.h4
-rw-r--r--Utilities/cmcurl/include/curl/stdcheaders.h6
-rw-r--r--Utilities/cmcurl/include/curl/typecheck-gcc.h55
-rw-r--r--Utilities/cmcurl/lib/Makefile.inc4
-rw-r--r--Utilities/cmcurl/lib/asyn-ares.c4
-rw-r--r--Utilities/cmcurl/lib/asyn-thread.c24
-rw-r--r--Utilities/cmcurl/lib/conncache.c6
-rw-r--r--Utilities/cmcurl/lib/connect.c98
-rw-r--r--Utilities/cmcurl/lib/connect.h13
-rw-r--r--Utilities/cmcurl/lib/content_encoding.c23
-rw-r--r--Utilities/cmcurl/lib/cookie.c10
-rw-r--r--Utilities/cmcurl/lib/curl_addrinfo.c34
-rw-r--r--Utilities/cmcurl/lib/curl_addrinfo.h2
-rw-r--r--Utilities/cmcurl/lib/curl_endian.c18
-rw-r--r--Utilities/cmcurl/lib/curl_endian.h18
-rw-r--r--Utilities/cmcurl/lib/curl_gethostname.c8
-rw-r--r--Utilities/cmcurl/lib/curl_gssapi.c2
-rw-r--r--Utilities/cmcurl/lib/curl_hmac.h26
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_core.c2
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_wb.c13
-rw-r--r--Utilities/cmcurl/lib/curl_sasl.c20
-rw-r--r--Utilities/cmcurl/lib/curl_sec.h16
-rw-r--r--Utilities/cmcurl/lib/curl_setup.h4
-rw-r--r--Utilities/cmcurl/lib/curl_threads.c5
-rw-r--r--Utilities/cmcurl/lib/curl_threads.h5
-rw-r--r--Utilities/cmcurl/lib/easy.c2
-rw-r--r--Utilities/cmcurl/lib/escape.c9
-rw-r--r--Utilities/cmcurl/lib/file.c2
-rw-r--r--Utilities/cmcurl/lib/formdata.c46
-rw-r--r--Utilities/cmcurl/lib/formdata.h2
-rw-r--r--Utilities/cmcurl/lib/ftp.c196
-rw-r--r--Utilities/cmcurl/lib/ftp.h2
-rw-r--r--Utilities/cmcurl/lib/ftplistparser.c8
-rw-r--r--Utilities/cmcurl/lib/getinfo.c29
-rw-r--r--Utilities/cmcurl/lib/hash.c6
-rw-r--r--Utilities/cmcurl/lib/hash.h15
-rw-r--r--Utilities/cmcurl/lib/hmac.c10
-rw-r--r--Utilities/cmcurl/lib/hostcheck.c9
-rw-r--r--Utilities/cmcurl/lib/hostip.c4
-rw-r--r--Utilities/cmcurl/lib/hostip.h8
-rw-r--r--Utilities/cmcurl/lib/hostip4.c2
-rw-r--r--Utilities/cmcurl/lib/http.c85
-rw-r--r--Utilities/cmcurl/lib/http2.c212
-rw-r--r--Utilities/cmcurl/lib/http2.h8
-rw-r--r--Utilities/cmcurl/lib/http_chunks.c14
-rw-r--r--Utilities/cmcurl/lib/http_digest.c20
-rw-r--r--Utilities/cmcurl/lib/http_negotiate.c16
-rw-r--r--Utilities/cmcurl/lib/http_ntlm.c4
-rw-r--r--Utilities/cmcurl/lib/http_proxy.c529
-rw-r--r--Utilities/cmcurl/lib/http_proxy.h4
-rw-r--r--Utilities/cmcurl/lib/if2ip.c2
-rw-r--r--Utilities/cmcurl/lib/imap.c6
-rw-r--r--Utilities/cmcurl/lib/inet_ntop.c6
-rw-r--r--Utilities/cmcurl/lib/inet_pton.c8
-rw-r--r--Utilities/cmcurl/lib/krb5.c2
-rw-r--r--Utilities/cmcurl/lib/ldap.c46
-rw-r--r--Utilities/cmcurl/lib/md4.c3
-rw-r--r--Utilities/cmcurl/lib/md5.c7
-rw-r--r--Utilities/cmcurl/lib/memdebug.c2
-rw-r--r--Utilities/cmcurl/lib/mprintf.c25
-rw-r--r--Utilities/cmcurl/lib/multi.c38
-rw-r--r--Utilities/cmcurl/lib/multihandle.h4
-rw-r--r--Utilities/cmcurl/lib/multiif.h4
-rw-r--r--Utilities/cmcurl/lib/non-ascii.c4
-rw-r--r--Utilities/cmcurl/lib/nwlib.c10
-rw-r--r--Utilities/cmcurl/lib/nwos.c8
-rw-r--r--Utilities/cmcurl/lib/pingpong.c14
-rw-r--r--Utilities/cmcurl/lib/pingpong.h2
-rw-r--r--Utilities/cmcurl/lib/pop3.c8
-rw-r--r--Utilities/cmcurl/lib/progress.c40
-rw-r--r--Utilities/cmcurl/lib/rand.c130
-rw-r--r--Utilities/cmcurl/lib/rand.h43
-rw-r--r--Utilities/cmcurl/lib/rtsp.c24
-rw-r--r--Utilities/cmcurl/lib/security.c13
-rw-r--r--Utilities/cmcurl/lib/select.c2
-rw-r--r--Utilities/cmcurl/lib/select.h2
-rw-r--r--Utilities/cmcurl/lib/sendf.c21
-rw-r--r--Utilities/cmcurl/lib/sendf.h2
-rw-r--r--Utilities/cmcurl/lib/setup-os400.h52
-rw-r--r--Utilities/cmcurl/lib/setup-vms.h139
-rw-r--r--Utilities/cmcurl/lib/share.h8
-rw-r--r--Utilities/cmcurl/lib/smb.c14
-rw-r--r--Utilities/cmcurl/lib/smtp.c6
-rw-r--r--Utilities/cmcurl/lib/socks.c43
-rw-r--r--Utilities/cmcurl/lib/socks.h5
-rw-r--r--Utilities/cmcurl/lib/socks_gssapi.c24
-rw-r--r--Utilities/cmcurl/lib/socks_sspi.c11
-rw-r--r--Utilities/cmcurl/lib/speedcheck.c6
-rw-r--r--Utilities/cmcurl/lib/ssh.c58
-rw-r--r--Utilities/cmcurl/lib/strcase.c12
-rw-r--r--Utilities/cmcurl/lib/strcase.h1
-rw-r--r--Utilities/cmcurl/lib/strdup.c23
-rw-r--r--Utilities/cmcurl/lib/strdup.h1
-rw-r--r--Utilities/cmcurl/lib/strerror.c32
-rw-r--r--Utilities/cmcurl/lib/strtoofft.c4
-rw-r--r--Utilities/cmcurl/lib/telnet.c23
-rw-r--r--Utilities/cmcurl/lib/tftp.c8
-rw-r--r--Utilities/cmcurl/lib/timeval.c6
-rw-r--r--Utilities/cmcurl/lib/timeval.h6
-rw-r--r--Utilities/cmcurl/lib/transfer.c14
-rw-r--r--Utilities/cmcurl/lib/url.c925
-rw-r--r--Utilities/cmcurl/lib/url.h13
-rw-r--r--Utilities/cmcurl/lib/urldata.h147
-rw-r--r--Utilities/cmcurl/lib/vauth/cleartext.c24
-rw-r--r--Utilities/cmcurl/lib/vauth/digest.c17
-rw-r--r--Utilities/cmcurl/lib/vauth/digest_sspi.c2
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm.c12
-rw-r--r--Utilities/cmcurl/lib/vauth/spnego_sspi.c2
-rw-r--r--Utilities/cmcurl/lib/version.c3
-rw-r--r--Utilities/cmcurl/lib/vtls/axtls.c81
-rw-r--r--Utilities/cmcurl/lib/vtls/cyassl.c105
-rw-r--r--Utilities/cmcurl/lib/vtls/darwinssl.c412
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.c354
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.h7
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.c289
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.h7
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c92
-rw-r--r--Utilities/cmcurl/lib/vtls/nss.c219
-rw-r--r--Utilities/cmcurl/lib/vtls/nssg.h3
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c398
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.h3
-rw-r--r--Utilities/cmcurl/lib/vtls/polarssl.c81
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c144
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.c300
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.h48
-rw-r--r--Utilities/cmcurl/lib/x509asn1.c194
-rw-r--r--Utilities/cmcurl/lib/x509asn1.h26
-rw-r--r--Utilities/cmlibarchive/CMakeLists.txt145
-rw-r--r--Utilities/cmlibarchive/build/cmake/CheckStructMember.cmake43
-rw-r--r--Utilities/cmlibarchive/build/cmake/FindLZMA.cmake48
-rw-r--r--Utilities/cmlibarchive/build/cmake/config.h.in21
-rw-r--r--Utilities/cmlibarchive/build/version2
-rw-r--r--Utilities/cmlibarchive/libarchive/CMakeLists.txt18
-rw-r--r--Utilities/cmlibarchive/libarchive/archive.h20
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_acl.c1639
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_acl_private.h22
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_cryptor.c3
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_digest_private.h1
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry.c234
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry.h91
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry_acl.3335
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry_locale.h10
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry_strmode.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_hmac.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_match.c14
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h5
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h6
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_options.c11
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_platform.h28
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_random.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_rb.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read.c16
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c22
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_append_filter.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c1090
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c135
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk_private.h12
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk_set_standard_lookup.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c59
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_extract2.c3
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_open_filename.c20
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_open_memory.c3
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_private.h3
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c13
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c44
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c194
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c39
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c22
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c15
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c17
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c40
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c13
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c71
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c5
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c281
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c241
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c87
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c158
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_string.c117
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_string.h8
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_string_composition.h2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_util.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_windows.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_windows.h4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write.c8
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c1
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c545
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c588
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c6
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c7
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_open.311
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_open_memory.c3
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c3
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c5
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c14
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c60
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c183
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_shar.c3
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c11
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c9
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c21
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c12
-rw-r--r--Utilities/cmlibarchive/libarchive/config_freebsd.h2
-rw-r--r--Utilities/cmlibarchive/libarchive/libarchive-formats.54
-rw-r--r--Utilities/cmlibarchive/libarchive/tar.511
-rw-r--r--Utilities/cmlibarchive/libarchive/xxhash.c6
-rw-r--r--Utilities/cmlibuv/CMakeLists.txt4
-rw-r--r--Utilities/cmlibuv/include/pthread-barrier.h2
-rw-r--r--Utilities/cmlibuv/include/uv-os390.h3
-rw-r--r--Utilities/cmlibuv/include/uv-unix.h4
-rw-r--r--Utilities/cmlibuv/include/uv-version.h4
-rw-r--r--Utilities/cmlibuv/include/uv-win.h1
-rw-r--r--Utilities/cmlibuv/include/uv.h2
-rw-r--r--Utilities/cmlibuv/src/unix/aix.c86
-rw-r--r--Utilities/cmlibuv/src/unix/atomic-ops.h27
-rw-r--r--Utilities/cmlibuv/src/unix/core.c18
-rw-r--r--Utilities/cmlibuv/src/unix/fs.c69
-rw-r--r--Utilities/cmlibuv/src/unix/internal.h12
-rw-r--r--Utilities/cmlibuv/src/unix/openbsd.c2
-rw-r--r--Utilities/cmlibuv/src/unix/os390-syscalls.c334
-rw-r--r--Utilities/cmlibuv/src/unix/os390-syscalls.h69
-rw-r--r--Utilities/cmlibuv/src/unix/os390.c823
-rw-r--r--Utilities/cmlibuv/src/unix/poll.c4
-rw-r--r--Utilities/cmlibuv/src/unix/process.c4
-rw-r--r--Utilities/cmlibuv/src/unix/proctitle.c6
-rw-r--r--Utilities/cmlibuv/src/unix/pthread-barrier.c3
-rw-r--r--Utilities/cmlibuv/src/unix/signal.c8
-rw-r--r--Utilities/cmlibuv/src/unix/stream.c31
-rw-r--r--Utilities/cmlibuv/src/unix/sunos.c15
-rw-r--r--Utilities/cmlibuv/src/unix/thread.c32
-rw-r--r--Utilities/cmlibuv/src/uv-common.c12
-rw-r--r--Utilities/cmlibuv/src/win/core.c4
-rw-r--r--Utilities/cmlibuv/src/win/error.c1
-rw-r--r--Utilities/cmlibuv/src/win/fs-event.c3
-rw-r--r--Utilities/cmlibuv/src/win/fs.c4
-rw-r--r--Utilities/cmlibuv/src/win/getaddrinfo.c3
-rw-r--r--Utilities/cmlibuv/src/win/process-stdio.c1
-rw-r--r--Utilities/cmlibuv/src/win/process.c2
-rw-r--r--Utilities/cmlibuv/src/win/signal.c118
-rw-r--r--Utilities/cmlibuv/src/win/tty.c91
-rw-r--r--Utilities/cmlibuv/src/win/winapi.h4
263 files changed, 10652 insertions, 4862 deletions
diff --git a/Utilities/GitSetup/config b/Utilities/GitSetup/config
index d69a679..2b4f037 100644
--- a/Utilities/GitSetup/config
+++ b/Utilities/GitSetup/config
@@ -1,9 +1,2 @@
[hooks]
- url = https://cmake.org/cmake.git
-[ssh]
- host = cmake.org
- key = id_git_cmake
- request-url = https://www.kitware.com/Admin/SendPassword.cgi
-[stage]
- url = git://cmake.org/stage/cmake.git
- pushurl = git@cmake.org:stage/cmake.git
+ url = https://gitlab.kitware.com/utils/gitsetup.git
diff --git a/Utilities/Release/release_cmake.cmake b/Utilities/Release/release_cmake.cmake
index 0db89b5..ee1a0dc 100644
--- a/Utilities/Release/release_cmake.cmake
+++ b/Utilities/Release/release_cmake.cmake
@@ -32,9 +32,15 @@ if(NOT DEFINED GIT_COMMAND)
set(GIT_COMMAND git)
endif()
-if(${CMAKE_CREATE_VERSION} MATCHES "^(release|maint|next|nightly)$")
+if(CMAKE_CREATE_VERSION MATCHES "^(master|release)$")
+ set(GIT_FETCH "")
set(GIT_BRANCH origin/${CMAKE_CREATE_VERSION})
+elseif(CMAKE_CREATE_VERSION STREQUAL "nightly")
+ set(nightly stage/master/nightly/latest)
+ set(GIT_FETCH "${GIT_COMMAND} fetch origin refs/${nightly}:refs/remotes/origin/${nightly}")
+ set(GIT_BRANCH origin/${nightly})
else()
+ set(GIT_FETCH "")
set(GIT_BRANCH ${CMAKE_CREATE_VERSION})
endif()
diff --git a/Utilities/Release/release_cmake.sh.in b/Utilities/Release/release_cmake.sh.in
index 1465129..f363b3d 100755
--- a/Utilities/Release/release_cmake.sh.in
+++ b/Utilities/Release/release_cmake.sh.in
@@ -94,13 +94,15 @@ cd @CMAKE_RELEASE_DIRECTORY@
if [ ! -z "@GIT_COMMAND@" ]; then
# clone the repo without creating any source files in the directory
# matching the branch being built (i.e. master CMake-2-8, etc)
- @GIT_COMMAND@ clone -n git://cmake.org/cmake.git @CMAKE_CREATE_VERSION@
- check_exit_value $? "Checkout git cmake source" || exit 1
+ @GIT_COMMAND@ clone -n https://gitlab.kitware.com/cmake/cmake.git @CMAKE_CREATE_VERSION@
+ check_exit_value $? "git clone cmake source" || exit 1
# go into the git directory
cd @CMAKE_CREATE_VERSION@
# run any extra commands if they exist
@GIT_EXTRA@
check_exit_value $? "git extra cmake source" || exit 1
+ @GIT_FETCH@
+ check_exit_value $? "git extra fetch" || exit 1
# now checkout a copy on the local branch working
@GIT_COMMAND@ checkout -b working @GIT_BRANCH@
check_exit_value $? "git checkout" || exit 1
diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index 22d1d8a..9cff7ca 100755
--- a/Utilities/Scripts/update-curl.bash
+++ b/Utilities/Scripts/update-curl.bash
@@ -8,7 +8,7 @@ readonly name="curl"
readonly ownership="Curl Upstream <curl-library@cool.haxx.se>"
readonly subtree="Utilities/cmcurl"
readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-7_51_0"
+readonly tag="curl-7_52_1"
readonly shortlog=false
readonly paths="
CMake/*
diff --git a/Utilities/Scripts/update-libarchive.bash b/Utilities/Scripts/update-libarchive.bash
index 3b42269..41c6a66 100755
--- a/Utilities/Scripts/update-libarchive.bash
+++ b/Utilities/Scripts/update-libarchive.bash
@@ -8,7 +8,7 @@ readonly name="LibArchive"
readonly ownership="LibArchive Upstream <libarchive-discuss@googlegroups.com>"
readonly subtree="Utilities/cmlibarchive"
readonly repo="https://github.com/libarchive/libarchive.git"
-readonly tag="master"
+readonly tag="v3.3.1"
readonly shortlog=false
readonly paths="
CMakeLists.txt
diff --git a/Utilities/SetupForDevelopment.sh b/Utilities/SetupForDevelopment.sh
index 39152bc..ff64a84 100755
--- a/Utilities/SetupForDevelopment.sh
+++ b/Utilities/SetupForDevelopment.sh
@@ -3,9 +3,6 @@
cd "${BASH_SOURCE%/*}/.." &&
Utilities/GitSetup/setup-user && echo &&
Utilities/GitSetup/setup-hooks && echo &&
-Utilities/GitSetup/setup-stage && echo &&
-(Utilities/GitSetup/setup-ssh ||
- echo 'Failed to setup SSH. Run this again to retry.') && echo &&
Utilities/GitSetup/tips
# Rebase master by default
@@ -13,5 +10,5 @@ git config rebase.stat true
git config branch.master.rebase true
# Record the version of this setup so Git/pre-commit can check it.
-SetupForDevelopment_VERSION=1
+SetupForDevelopment_VERSION=2
git config hooks.SetupForDevelopment ${SetupForDevelopment_VERSION}
diff --git a/Utilities/Sphinx/conf.py.in b/Utilities/Sphinx/conf.py.in
index 9581458..e3afc78 100644
--- a/Utilities/Sphinx/conf.py.in
+++ b/Utilities/Sphinx/conf.py.in
@@ -18,7 +18,9 @@ release = '@conf_release@' # full version string
primary_domain = 'cmake'
-exclude_patterns = []
+exclude_patterns = [
+ 'dev', # ignore developer-only documentation
+ ]
extensions = ['cmake']
templates_path = ['@conf_path@/templates']
diff --git a/Utilities/Sphinx/templates/layout.html b/Utilities/Sphinx/templates/layout.html
index 177e044..be2660c 100644
--- a/Utilities/Sphinx/templates/layout.html
+++ b/Utilities/Sphinx/templates/layout.html
@@ -8,10 +8,22 @@
<a href="https://cmake.org/">CMake</a>{{ reldelim1 }}
</li>
<li>
+ {%- if versionswitch is defined %}
+ <span class="version_switch">{{ release }}</span>
+ <a href="{{ pathto(master_doc) }}">{% trans %}Documentation{% endtrans %}</a>{{ reldelim1 }}
+ {%- else %}
<a href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a>{{ reldelim1 }}
+ {%- endif %}
</li>
{% endblock %}
+{% block extrahead %}
+ {% if versionswitch is defined %}
+ <script type="text/javascript" src="{{ pathto('../version_switch.js', 1) }}"></script>
+ {% endif %}
+{{ super() }}
+{% endblock %}
+
{# Put some context in the html title element. Workaround for #}
{# https://bitbucket.org/birkenfeld/sphinx/issue/1492/qthelp-generate-html-title-element-should #}
{% block htmltitle %}
diff --git a/Utilities/cmcurl/CMake/OtherTests.cmake b/Utilities/cmcurl/CMake/OtherTests.cmake
index d599498..3b203c5 100644
--- a/Utilities/cmcurl/CMake/OtherTests.cmake
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 262554d..6a34e8d 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -316,7 +316,7 @@ include (CheckCSourceCompiles)
# On windows preload settings
if(WIN32)
- set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_")
+ set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_=")
include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake)
endif(WIN32)
@@ -801,7 +801,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)
diff --git a/Utilities/cmcurl/include/curl/curl.h b/Utilities/cmcurl/include/curl/curl.h
index aa1034b..daca8d1 100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@ -143,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 */
@@ -270,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;
};
@@ -640,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 7.52.0 */
CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
in 7.10 */
CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
@@ -1206,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
@@ -1704,6 +1706,70 @@ typedef enum {
* 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 pre proxy to use. */
+ CINIT(PRE_PROXY, STRINGPOINT, 262),
+
+ /* The public key in DER form used to validate the proxy public key
+ this option is used only if PROXY_SSL_VERIFYPEER is true */
+ CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -1805,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 */
};
@@ -1839,7 +1906,10 @@ typedef enum {
/* curl_strequal() and curl_strnequal() are subject for removal in a future
- libcurl, see lib/README.curlx for details */
+ libcurl, see lib/README.curlx for details
+
+ !checksrc! disable SPACEBEFOREPAREN 2
+*/
CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
@@ -2209,9 +2279,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
@@ -2372,6 +2445,7 @@ typedef struct {
#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */
#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used
for cookie domain verification */
+#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */
/*
* NAME curl_version_info()
diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h
index 2415d1a..3967ad2 100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/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.51.0"
+#define LIBCURL_VERSION "7.52.1"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 51
-#define LIBCURL_VERSION_PATCH 0
+#define LIBCURL_VERSION_MINOR 52
+#define LIBCURL_VERSION_PATCH 1
/* 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 0x073300
+#define LIBCURL_VERSION_NUM 0x073401
/*
* This is the date and time when the full source package was created. The
diff --git a/Utilities/cmcurl/include/curl/easy.h b/Utilities/cmcurl/include/curl/easy.h
index afc766c..752c504 100644
--- a/Utilities/cmcurl/include/curl/easy.h
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/include/curl/stdcheaders.h b/Utilities/cmcurl/include/curl/stdcheaders.h
index 6f0f7f3..027b6f4 100644
--- a/Utilities/cmcurl/include/curl/stdcheaders.h
+++ b/Utilities/cmcurl/include/curl/stdcheaders.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,8 +24,8 @@
#include <sys/types.h>
-size_t fread (void *, size_t, size_t, FILE *);
-size_t fwrite (const void *, size_t, size_t, FILE *);
+size_t fread(void *, size_t, size_t, FILE *);
+size_t fwrite(const void *, size_t, size_t, FILE *);
int strcasecmp(const char *, const char *);
int strncasecmp(const char *, const char *, size_t);
diff --git a/Utilities/cmcurl/include/curl/typecheck-gcc.h b/Utilities/cmcurl/include/curl/typecheck-gcc.h
index 6ec8bcf..4eb896e 100644
--- a/Utilities/cmcurl/include/curl/typecheck-gcc.h
+++ b/Utilities/cmcurl/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
@@ -40,7 +40,7 @@
*/
#define curl_easy_setopt(handle, option, value) \
__extension__ ({ \
- __typeof__ (option) _curl_opt = option; \
+ __typeof__(option) _curl_opt = option; \
if(__builtin_constant_p(_curl_opt)) { \
if(_curl_is_long_option(_curl_opt)) \
if(!_curl_is_long(value)) \
@@ -110,7 +110,7 @@ __extension__ ({ \
/* FIXME: don't allow const pointers */
#define curl_easy_getinfo(handle, info, arg) \
__extension__ ({ \
- __typeof__ (info) _curl_info = info; \
+ __typeof__(info) _curl_info = info; \
if(__builtin_constant_p(_curl_info)) { \
if(_curl_is_string_info(_curl_info)) \
if(!_curl_is_arr((arg), char *)) \
@@ -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/Utilities/cmcurl/lib/Makefile.inc b/Utilities/cmcurl/lib/Makefile.inc
index 1328cad..19f5800 100644
--- a/Utilities/cmcurl/lib/Makefile.inc
+++ b/Utilities/cmcurl/lib/Makefile.inc
@@ -51,7 +51,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.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
@@ -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/Utilities/cmcurl/lib/asyn-ares.c b/Utilities/cmcurl/lib/asyn-ares.c
index 2aed94f..c038c2a 100644
--- a/Utilities/cmcurl/lib/asyn-ares.c
+++ b/Utilities/cmcurl/lib/asyn-ares.c
@@ -169,7 +169,7 @@ int Curl_resolver_duphandle(void **to, void *from)
return CURLE_OK;
}
-static void destroy_async_data (struct Curl_async *async);
+static void destroy_async_data(struct Curl_async *async);
/*
* Cancel all possibly still on-going resolves for this connection.
@@ -184,7 +184,7 @@ void Curl_resolver_cancel(struct connectdata *conn)
/*
* destroy_async_data() cleans up async resolver data.
*/
-static void destroy_async_data (struct Curl_async *async)
+static void destroy_async_data(struct Curl_async *async)
{
free(async->hostname);
diff --git a/Utilities/cmcurl/lib/asyn-thread.c b/Utilities/cmcurl/lib/asyn-thread.c
index 7cce01a..26a15b1 100644
--- a/Utilities/cmcurl/lib/asyn-thread.c
+++ b/Utilities/cmcurl/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)
{
@@ -263,7 +263,7 @@ static int getaddrinfo_complete(struct connectdata *conn)
* For builds without ARES, but with ENABLE_IPV6, create a resolver thread
* and wait on it.
*/
-static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
+static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
{
struct thread_sync_data *tsd = (struct thread_sync_data*)arg;
struct thread_data *td = tsd->td;
@@ -303,7 +303,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
/*
* gethostbyname_thread() resolves a name and then exits.
*/
-static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
+static unsigned int CURL_STDCALL gethostbyname_thread(void *arg)
{
struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
struct thread_data *td = tsd->td;
@@ -336,7 +336,7 @@ static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
/*
* destroy_async_data() cleans up async resolver data and thread handle.
*/
-static void destroy_async_data (struct Curl_async *async)
+static void destroy_async_data(struct Curl_async *async)
{
if(async->os_specific) {
struct thread_data *td = (struct thread_data*) async->os_specific;
@@ -375,14 +375,14 @@ static void destroy_async_data (struct Curl_async *async)
*
* Returns FALSE in case of failure, otherwise TRUE.
*/
-static bool init_resolve_thread (struct connectdata *conn,
- const char *hostname, int port,
- const struct addrinfo *hints)
+static bool init_resolve_thread(struct connectdata *conn,
+ const char *hostname, int port,
+ const struct addrinfo *hints)
{
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/Utilities/cmcurl/lib/conncache.c b/Utilities/cmcurl/lib/conncache.c
index 01b1b44..d8ef9a5 100644
--- a/Utilities/cmcurl/lib/conncache.c
+++ b/Utilities/cmcurl/lib/conncache.c
@@ -132,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/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c
index 3df34d9..524d885 100644
--- a/Utilities/cmcurl/lib/connect.c
+++ b/Utilities/cmcurl/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 */
@@ -194,7 +194,7 @@ long Curl_timeleft(struct Curl_easy *data,
if(duringconnect && (data->set.connecttimeout > 0))
timeout_set |= 2;
- switch (timeout_set) {
+ switch(timeout_set) {
case 1:
timeout_ms = data->set.timeout;
break;
@@ -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) {
+ 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;
@@ -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 */
@@ -1243,24 +1247,6 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
/* only store this if the caller cares for it */
*connp = c;
sockfd = c->sock[FIRSTSOCKET];
- /* we have a socket connected, let's determine if the server shut down */
- /* determine if ssl */
- if(c->ssl[FIRSTSOCKET].use) {
- /* use the SSL context */
- if(!Curl_ssl_check_cxn(c))
- return CURL_SOCKET_BAD; /* FIN received */
- }
-/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
-#ifdef MSG_PEEK
- else if(sockfd != CURL_SOCKET_BAD) {
- /* use the socket */
- char buf;
- if(recv((RECV_TYPE_ARG1)sockfd, (RECV_TYPE_ARG2)&buf,
- (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
- return CURL_SOCKET_BAD; /* FIN received */
- }
- }
-#endif
}
else
return CURL_SOCKET_BAD;
@@ -1269,6 +1255,33 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
}
/*
+ * Check if a connection seems to be alive.
+ */
+bool Curl_connalive(struct connectdata *conn)
+{
+ /* First determine if ssl */
+ if(conn->ssl[FIRSTSOCKET].use) {
+ /* use the SSL context */
+ if(!Curl_ssl_check_cxn(conn))
+ return false; /* FIN received */
+ }
+/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
+#ifdef MSG_PEEK
+ else if(conn->sock[FIRSTSOCKET] == CURL_SOCKET_BAD)
+ return false;
+ else {
+ /* use the socket */
+ char buf;
+ if(recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
+ (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
+ return false; /* FIN received */
+ }
+ }
+#endif
+ return true;
+}
+
+/*
* Close a socket.
*
* 'conn' can be NULL, beware!
@@ -1391,3 +1404,16 @@ void Curl_conncontrol(struct connectdata *conn,
should assign this bit */
}
}
+
+/* Data received can be cached at various levels, so check them all here. */
+bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
+{
+ int readable;
+
+ if(Curl_ssl_data_pending(conn, sockindex) ||
+ Curl_recv_has_postponed_data(conn, sockindex))
+ return true;
+
+ readable = SOCKET_READABLE(conn->sock[sockindex], 0);
+ return (readable > 0 && (readable & CURL_CSELECT_IN));
+}
diff --git a/Utilities/cmcurl/lib/connect.h b/Utilities/cmcurl/lib/connect.h
index a7cbc9b..5653cb4 100644
--- a/Utilities/cmcurl/lib/connect.h
+++ b/Utilities/cmcurl/lib/connect.h
@@ -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
@@ -52,6 +52,11 @@ long Curl_timeleft(struct Curl_easy *data,
curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
struct connectdata **connp);
+/*
+ * Check if a connection seems to be alive.
+ */
+bool Curl_connalive(struct connectdata *conn);
+
#ifdef USE_WINSOCK
/* When you run a program that uses the Windows Sockets API, you may
experience slow performance when you copy data to a TCP server.
@@ -137,4 +142,6 @@ void Curl_conncontrol(struct connectdata *conn,
#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP)
#endif
+bool Curl_conn_data_pending(struct connectdata *conn, int sockindex);
+
#endif /* HEADER_CURL_CONNECT_H */
diff --git a/Utilities/cmcurl/lib/content_encoding.c b/Utilities/cmcurl/lib/content_encoding.c
index fa36aca..5385058 100644
--- a/Utilities/cmcurl/lib/content_encoding.c
+++ b/Utilities/cmcurl/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
@@ -69,11 +69,11 @@ process_zlib_error(struct connectdata *conn, z_stream *z)
{
struct Curl_easy *data = conn->data;
if(z->msg)
- failf (data, "Error while processing content unencoding: %s",
- z->msg);
+ failf(data, "Error while processing content unencoding: %s",
+ z->msg);
else
- failf (data, "Error while processing content unencoding: "
- "Unknown failure within decompression software.");
+ failf(data, "Error while processing content unencoding: "
+ "Unknown failure within decompression software.");
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -327,14 +327,14 @@ Curl_unencode_gzip_write(struct connectdata *conn,
* can handle the gzip header themselves.
*/
- switch (k->zlib_init) {
+ switch(k->zlib_init) {
/* Skip over gzip header? */
case ZLIB_INIT:
{
/* Initial call state */
ssize_t hlen;
- switch (check_gzip_header((unsigned char *)k->str, nread, &hlen)) {
+ switch(check_gzip_header((unsigned char *)k->str, nread, &hlen)) {
case GZIP_OK:
z->next_in = (Bytef *)k->str + hlen;
z->avail_in = (uInt)(nread - hlen);
@@ -371,18 +371,15 @@ 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 */
memcpy(z->next_in + z->avail_in - nread, k->str, nread);
- switch (check_gzip_header(z->next_in, z->avail_in, &hlen)) {
+ switch(check_gzip_header(z->next_in, z->avail_in, &hlen)) {
case GZIP_OK:
/* This is the zlib stream data */
free(z->next_in);
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c
index 1b3e645..092a226 100644
--- a/Utilities/cmcurl/lib/cookie.c
+++ b/Utilities/cmcurl/lib/cookie.c
@@ -146,12 +146,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 */
@@ -798,8 +798,8 @@ Curl_cookie_add(struct Curl_easy *data,
/* Check if the domain is a Public Suffix and if yes, ignore the cookie.
This needs a libpsl compiled with builtin data. */
if(domain && co->domain && !isip(co->domain)) {
- if(((psl = psl_builtin()) != NULL)
- && !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) {
+ psl = psl_builtin();
+ if(psl && !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) {
infof(data,
"cookie '%s' dropped, domain '%s' must not set cookies for '%s'\n",
co->name, domain, co->domain);
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.c b/Utilities/cmcurl/lib/curl_addrinfo.c
index 35eb2dd..61cdadd 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.c
+++ b/Utilities/cmcurl/lib/curl_addrinfo.c
@@ -146,7 +146,8 @@ Curl_getaddrinfo_ex(const char *nodename,
if((size_t)ai->ai_addrlen < ss_size)
continue;
- if((ca = malloc(sizeof(Curl_addrinfo))) == NULL) {
+ ca = malloc(sizeof(Curl_addrinfo));
+ if(!ca) {
error = EAI_MEMORY;
break;
}
@@ -163,7 +164,8 @@ Curl_getaddrinfo_ex(const char *nodename,
ca->ai_canonname = NULL;
ca->ai_next = NULL;
- if((ca->ai_addr = malloc(ss_size)) == NULL) {
+ ca->ai_addr = malloc(ss_size);
+ if(!ca->ai_addr) {
error = EAI_MEMORY;
free(ca);
break;
@@ -171,7 +173,8 @@ Curl_getaddrinfo_ex(const char *nodename,
memcpy(ca->ai_addr, ai->ai_addr, ss_size);
if(ai->ai_canonname != NULL) {
- if((ca->ai_canonname = strdup(ai->ai_canonname)) == NULL) {
+ ca->ai_canonname = strdup(ai->ai_canonname);
+ if(!ca->ai_canonname) {
error = EAI_MEMORY;
free(ca->ai_addr);
free(ca);
@@ -286,21 +289,24 @@ Curl_he2ai(const struct hostent *he, int port)
size_t ss_size;
#ifdef ENABLE_IPV6
if(he->h_addrtype == AF_INET6)
- ss_size = sizeof (struct sockaddr_in6);
+ ss_size = sizeof(struct sockaddr_in6);
else
#endif
- ss_size = sizeof (struct sockaddr_in);
+ ss_size = sizeof(struct sockaddr_in);
- if((ai = calloc(1, sizeof(Curl_addrinfo))) == NULL) {
+ ai = calloc(1, sizeof(Curl_addrinfo));
+ if(!ai) {
result = CURLE_OUT_OF_MEMORY;
break;
}
- if((ai->ai_canonname = strdup(he->h_name)) == NULL) {
+ ai->ai_canonname = strdup(he->h_name);
+ if(!ai->ai_canonname) {
result = CURLE_OUT_OF_MEMORY;
free(ai);
break;
}
- if((ai->ai_addr = calloc(1, ss_size)) == NULL) {
+ ai->ai_addr = calloc(1, ss_size);
+ if(!ai->ai_addr) {
result = CURLE_OUT_OF_MEMORY;
free(ai->ai_canonname);
free(ai);
@@ -325,7 +331,7 @@ Curl_he2ai(const struct hostent *he, int port)
/* leave the rest of the struct filled with zero */
- switch (ai->ai_family) {
+ switch(ai->ai_family) {
case AF_INET:
addr = (void *)ai->ai_addr; /* storage area for this info */
@@ -475,8 +481,9 @@ Curl_addrinfo *Curl_str2addr(char *address, int port)
/**
* Given a path to a Unix domain socket, return a newly allocated Curl_addrinfo
* struct initialized with this path.
+ * Set '*longpath' to TRUE if the error is a too long path.
*/
-Curl_addrinfo *Curl_unix2addr(const char *path)
+Curl_addrinfo *Curl_unix2addr(const char *path, int *longpath)
{
Curl_addrinfo *ai;
struct sockaddr_un *sa_un;
@@ -485,8 +492,10 @@ Curl_addrinfo *Curl_unix2addr(const char *path)
ai = calloc(1, sizeof(Curl_addrinfo));
if(!ai)
return NULL;
- if((ai->ai_addr = calloc(1, sizeof(struct sockaddr_un))) == NULL) {
+ ai->ai_addr = calloc(1, sizeof(struct sockaddr_un));
+ if(!ai->ai_addr) {
free(ai);
+ *longpath = FALSE;
return NULL;
}
/* sun_path must be able to store the NUL-terminated path */
@@ -494,6 +503,7 @@ Curl_addrinfo *Curl_unix2addr(const char *path)
if(path_len >= sizeof(sa_un->sun_path)) {
free(ai->ai_addr);
free(ai);
+ *longpath = TRUE;
return NULL;
}
@@ -576,7 +586,7 @@ void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port)
struct sockaddr_in6 *addr6;
#endif
for(ca = addrinfo; ca != NULL; ca = ca->ai_next) {
- switch (ca->ai_family) {
+ switch(ca->ai_family) {
case AF_INET:
addr = (void *)ca->ai_addr; /* storage area for this info */
addr->sin_port = htons((unsigned short)port);
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.h b/Utilities/cmcurl/lib/curl_addrinfo.h
index 1a681e6..4f24730 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.h
+++ b/Utilities/cmcurl/lib/curl_addrinfo.h
@@ -80,7 +80,7 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port);
Curl_addrinfo *Curl_str2addr(char *dotted, int port);
#ifdef USE_UNIX_SOCKETS
-Curl_addrinfo *Curl_unix2addr(const char *path);
+Curl_addrinfo *Curl_unix2addr(const char *path, int *longpath);
#endif
#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
diff --git a/Utilities/cmcurl/lib/curl_endian.c b/Utilities/cmcurl/lib/curl_endian.c
index 76deca6..c2d21de 100644
--- a/Utilities/cmcurl/lib/curl_endian.c
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/curl_endian.h b/Utilities/cmcurl/lib/curl_endian.h
index df8398c..8a2b07a 100644
--- a/Utilities/cmcurl/lib/curl_endian.h
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/curl_gethostname.c b/Utilities/cmcurl/lib/curl_gethostname.c
index 2591fd8..8337c72 100644
--- a/Utilities/cmcurl/lib/curl_gethostname.c
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/curl_gssapi.c b/Utilities/cmcurl/lib/curl_gssapi.c
index bf7c766..83f3fa0 100644
--- a/Utilities/cmcurl/lib/curl_gssapi.c
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/curl_hmac.h b/Utilities/cmcurl/lib/curl_hmac.h
index 41703b4..756dc9e 100644
--- a/Utilities/cmcurl/lib/curl_hmac.h
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/curl_ntlm_core.c b/Utilities/cmcurl/lib/curl_ntlm_core.c
index 812a073..73d983c 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.c
@@ -566,7 +566,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
gcry_md_hd_t MD4pw;
gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
gcry_md_write(MD4pw, pw, 2 * len);
- memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH);
+ memcpy(ntbuffer, gcry_md_read(MD4pw, 0), MD4_DIGEST_LENGTH);
gcry_md_close(MD4pw);
#elif defined(USE_MBEDTLS)
mbedtls_md4(pw, 2 * len, ntbuffer);
diff --git a/Utilities/cmcurl/lib/curl_ntlm_wb.c b/Utilities/cmcurl/lib/curl_ntlm_wb.c
index afdea16..6a90e62 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_wb.c
+++ b/Utilities/cmcurl/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"
@@ -156,7 +157,8 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
}
slash = strpbrk(username, "\\/");
if(slash) {
- if((domain = strdup(username)) == NULL)
+ domain = strdup(username);
+ if(!domain)
return CURLE_OUT_OF_MEMORY;
slash = domain + (slash - username);
*slash = '\0';
@@ -293,11 +295,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 +350,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/Utilities/cmcurl/lib/curl_sasl.c b/Utilities/cmcurl/lib/curl_sasl.c
index 6b86962..807f5de 100644
--- a/Utilities/cmcurl/lib/curl_sasl.c
+++ b/Utilities/cmcurl/lib/curl_sasl.c
@@ -262,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 */
@@ -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/Utilities/cmcurl/lib/curl_sec.h b/Utilities/cmcurl/lib/curl_sec.h
index 3f94e14..7bdde26 100644
--- a/Utilities/cmcurl/lib/curl_sec.h
+++ b/Utilities/cmcurl/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
@@ -39,11 +39,11 @@ struct Curl_sec_client_mech {
#define AUTH_ERROR 2
#ifdef HAVE_GSSAPI
-int Curl_sec_read_msg (struct connectdata *conn, char *,
- enum protection_level);
-void Curl_sec_end (struct connectdata *);
-CURLcode Curl_sec_login (struct connectdata *);
-int Curl_sec_request_prot (struct connectdata *conn, const char *level);
+int Curl_sec_read_msg(struct connectdata *conn, char *,
+ enum protection_level);
+void Curl_sec_end(struct connectdata *);
+CURLcode Curl_sec_login(struct connectdata *);
+int Curl_sec_request_prot(struct connectdata *conn, const char *level);
extern struct Curl_sec_client_mech Curl_krb5_client_mech;
#endif
diff --git a/Utilities/cmcurl/lib/curl_setup.h b/Utilities/cmcurl/lib/curl_setup.h
index 4eb17a1..c861e97 100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@ -482,8 +482,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 "/"
diff --git a/Utilities/cmcurl/lib/curl_threads.c b/Utilities/cmcurl/lib/curl_threads.c
index c98d8bb..a78eff5 100644
--- a/Utilities/cmcurl/lib/curl_threads.c
+++ b/Utilities/cmcurl/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,8 @@ 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*),
+/* !checksrc! disable SPACEBEFOREPAREN 1 */
+curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
void *arg)
{
#ifdef _WIN32_WCE
diff --git a/Utilities/cmcurl/lib/curl_threads.h b/Utilities/cmcurl/lib/curl_threads.h
index 8cbac63..9e0d14a 100644
--- a/Utilities/cmcurl/lib/curl_threads.h
+++ b/Utilities/cmcurl/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,8 @@
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
-curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*),
+/* !checksrc! disable SPACEBEFOREPAREN 1 */
+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/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c
index eee1061..1242369 100644
--- a/Utilities/cmcurl/lib/easy.c
+++ b/Utilities/cmcurl/lib/easy.c
@@ -927,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 */
diff --git a/Utilities/cmcurl/lib/escape.c b/Utilities/cmcurl/lib/escape.c
index 6657007..9c811b8 100644
--- a/Utilities/cmcurl/lib/escape.c
+++ b/Utilities/cmcurl/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"
@@ -42,7 +43,7 @@
*/
static bool Curl_isunreserved(unsigned char in)
{
- switch (in) {
+ switch(in) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case 'a': case 'b': case 'c': case 'd': case 'e':
@@ -109,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;
}
diff --git a/Utilities/cmcurl/lib/file.c b/Utilities/cmcurl/lib/file.c
index 272289e..3dbc0f2 100644
--- a/Utilities/cmcurl/lib/file.c
+++ b/Utilities/cmcurl/lib/file.c
@@ -313,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/Utilities/cmcurl/lib/formdata.c b/Utilities/cmcurl/lib/formdata.c
index 785f1a6..abd2da0 100644
--- a/Utilities/cmcurl/lib/formdata.c
+++ b/Utilities/cmcurl/lib/formdata.c
@@ -36,6 +36,7 @@
#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,
@@ -315,7 +316,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
break;
}
- switch (option) {
+ switch(option) {
case CURLFORM_ARRAY:
if(array_state)
/* we don't support an array from within an array */
@@ -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:
@@ -948,8 +949,8 @@ void Curl_formclean(struct FormData **form_ptr)
if(form->type <= FORM_CONTENT)
free(form->line); /* free the line */
free(form); /* free the struct */
-
- } while((form = next) != NULL); /* continue */
+ form = next;
+ } while(form); /* continue */
*form_ptr = NULL;
}
@@ -1030,8 +1031,8 @@ void curl_formfree(struct curl_httppost *form)
free(form->contenttype); /* free the content type */
free(form->showfilename); /* free the faked file name */
free(form); /* free the struct */
-
- } while((form = next) != NULL); /* continue */
+ form = next;
+ } while(form); /* continue */
}
#ifndef HAVE_BASENAME
@@ -1166,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 */
@@ -1373,8 +1374,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
if(result)
break;
}
-
- } while((post = post->next) != NULL); /* for each field */
+ post = post->next;
+ } while(post); /* for each field */
/* end-boundary for everything */
if(!result)
@@ -1426,13 +1427,14 @@ 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;
result = stat(file, &statbuf);
- switch (statbuf.st_fab_rfm) {
+ switch(statbuf.st_fab_rfm) {
case FAB$C_VAR:
case FAB$C_VFC:
case FAB$C_STMCR:
@@ -1569,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/Utilities/cmcurl/lib/formdata.h b/Utilities/cmcurl/lib/formdata.h
index 200470b..69629f6 100644
--- a/Utilities/cmcurl/lib/formdata.h
+++ b/Utilities/cmcurl/lib/formdata.h
@@ -65,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/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c
index 9d0a03c..89c7e40 100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@ -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;
@@ -455,7 +455,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0);
/* see if the connection request is already here */
- switch (result) {
+ switch(result) {
case -1: /* error */
/* let's die here */
failf(data, "Error while waiting for server connect");
@@ -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 (SOCKET_READABLE(sockfd, interval_ms)) {
+ else if(!Curl_conn_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);
@@ -1035,7 +1035,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
if(*string_ftpport == '[') {
/* [ipv6]:port(-range) */
ip_start = string_ftpport + 1;
- if((ip_end = strchr(string_ftpport, ']')) != NULL)
+ ip_end = strchr(string_ftpport, ']');
+ if(ip_end)
strncpy(addr, ip_start, ip_end - ip_start);
}
else
@@ -1043,30 +1044,35 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
if(*string_ftpport == ':') {
/* :port */
ip_end = string_ftpport;
- }
- else if((ip_end = strchr(string_ftpport, ':')) != NULL) {
- /* either ipv6 or (ipv4|domain|interface):port(-range) */
-#ifdef ENABLE_IPV6
- if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
- /* ipv6 */
- port_min = port_max = 0;
- strcpy(addr, string_ftpport);
- ip_end = NULL; /* this got no port ! */
}
- else
+ else {
+ ip_end = strchr(string_ftpport, ':');
+ if(ip_end) {
+ /* either ipv6 or (ipv4|domain|interface):port(-range) */
+#ifdef ENABLE_IPV6
+ if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
+ /* ipv6 */
+ port_min = port_max = 0;
+ strcpy(addr, string_ftpport);
+ ip_end = NULL; /* this got no port ! */
+ }
+ else
#endif
- /* (ipv4|domain|interface):port(-range) */
- strncpy(addr, string_ftpport, ip_end - ip_start);
- }
- else
- /* ipv4|interface */
- strcpy(addr, string_ftpport);
+ /* (ipv4|domain|interface):port(-range) */
+ strncpy(addr, string_ftpport, ip_end - ip_start);
+ }
+ else
+ /* ipv4|interface */
+ strcpy(addr, string_ftpport);
+ }
/* parse the port */
if(ip_end != NULL) {
- if((port_start = strchr(ip_end, ':')) != NULL) {
+ port_start = strchr(ip_end, ':');
+ if(port_start) {
port_min = curlx_ultous(strtoul(port_start+1, NULL, 10));
- if((port_sep = strchr(port_start, '-')) != NULL) {
+ port_sep = strchr(port_start, '-');
+ if(port_sep) {
port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10));
}
else
@@ -1850,84 +1856,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 +1863,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 +1987,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 +1999,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 +2040,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 */
@@ -2763,7 +2692,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 +2740,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 +2782,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 */
@@ -3250,7 +3182,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
ssize_t nread;
int ftpcode;
CURLcode result = CURLE_OK;
- char *path;
+ char *path = NULL;
const char *path_to_use = data->state.path;
if(!ftp)
@@ -3666,10 +3598,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)) {
@@ -3681,6 +3609,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 initial commands.
They are only done to kickstart the do_more state */
@@ -3940,7 +3880,7 @@ static CURLcode wc_statemach(struct connectdata *conn)
struct WildcardData * const wildcard = &(conn->data->wildcard);
CURLcode result = CURLE_OK;
- switch (wildcard->state) {
+ switch(wildcard->state) {
case CURLWC_INIT:
result = init_wc_data(conn);
if(wildcard->state == CURLWC_CLEAN)
@@ -4247,8 +4187,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;
@@ -4568,7 +4508,7 @@ static CURLcode ftp_setup_connection(struct connectdata *conn)
command = Curl_raw_toupper(type[6]);
conn->bits.type_set = TRUE;
- switch (command) {
+ switch(command) {
case 'A': /* ASCII mode */
data->set.prefer_ascii = TRUE;
break;
diff --git a/Utilities/cmcurl/lib/ftp.h b/Utilities/cmcurl/lib/ftp.h
index dbd8567..3bbf262 100644
--- a/Utilities/cmcurl/lib/ftp.h
+++ b/Utilities/cmcurl/lib/ftp.h
@@ -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/Utilities/cmcurl/lib/ftplistparser.c b/Utilities/cmcurl/lib/ftplistparser.c
index 747dbba..f94b31b 100644
--- a/Utilities/cmcurl/lib/ftplistparser.c
+++ b/Utilities/cmcurl/lib/ftplistparser.c
@@ -396,9 +396,9 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
}
}
- switch (parser->os_type) {
+ switch(parser->os_type) {
case OS_TYPE_UNIX:
- switch (parser->state.UNIX.main) {
+ switch(parser->state.UNIX.main) {
case PL_UNIX_TOTALSIZE:
switch(parser->state.UNIX.sub.total_dirsize) {
case PL_UNIX_TOTALSIZE_INIT:
@@ -447,7 +447,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
}
break;
case PL_UNIX_FILETYPE:
- switch (c) {
+ switch(c) {
case '-':
finfo->filetype = CURLFILETYPE_FILE;
break;
@@ -967,7 +967,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
}
break;
case PL_WINNT_FILENAME:
- switch (parser->state.NT.sub.filename) {
+ switch(parser->state.NT.sub.filename) {
case PL_WINNT_FILENAME_PRESPACE:
if(c != ' ') {
parser->item_offset = finfo->b_used -1;
diff --git a/Utilities/cmcurl/lib/getinfo.c b/Utilities/cmcurl/lib/getinfo.c
index 9641d79..a1ce505 100644
--- a/Utilities/cmcurl/lib/getinfo.c
+++ b/Utilities/cmcurl/lib/getinfo.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
@@ -36,8 +36,11 @@
#include "memdebug.h"
/*
- * This is supposed to be called in the beginning of a perform() session and
- * in curl_easy_reset() 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)
{
@@ -75,6 +78,9 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
info->conn_primary_port = 0;
info->conn_local_port = 0;
+ info->conn_scheme = 0;
+ info->conn_protocol = 0;
+
#ifdef USE_SSL
Curl_ssl_free_certinfo(data);
#endif
@@ -83,7 +89,7 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
}
static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
- char **param_charp)
+ const char **param_charp)
{
switch(info) {
case CURLINFO_EFFECTIVE_URL:
@@ -120,6 +126,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;
@@ -157,6 +166,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;
@@ -208,7 +220,7 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
*param_longp = data->state.rtsp_CSeq_recv;
break;
case CURLINFO_HTTP_VERSION:
- switch (data->info.httpversion) {
+ switch(data->info.httpversion) {
case 10:
*param_longp = CURL_HTTP_VERSION_1_0;
break;
@@ -223,6 +235,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;
@@ -379,7 +394,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;
@@ -393,7 +408,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/Utilities/cmcurl/lib/hash.c b/Utilities/cmcurl/lib/hash.c
index 937381b..0655042 100644
--- a/Utilities/cmcurl/lib/hash.c
+++ b/Utilities/cmcurl/lib/hash.c
@@ -135,7 +135,7 @@ Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
{
struct curl_hash_element *he;
struct curl_llist_element *le;
- struct curl_llist *l = FETCH_LIST (h, key, key_len);
+ struct curl_llist *l = FETCH_LIST(h, key, key_len);
for(le = l->head; le; le = le->next) {
he = (struct curl_hash_element *) le->ptr;
@@ -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/Utilities/cmcurl/lib/hash.h b/Utilities/cmcurl/lib/hash.h
index 57a17f0..a5a6cac 100644
--- a/Utilities/cmcurl/lib/hash.h
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/hmac.c b/Utilities/cmcurl/lib/hmac.c
index 3df4715..dae9505 100644
--- a/Utilities/cmcurl/lib/hmac.c
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/hostcheck.c b/Utilities/cmcurl/lib/hostcheck.c
index f545254..cbd0893 100644
--- a/Utilities/cmcurl/lib/hostcheck.c
+++ b/Utilities/cmcurl/lib/hostcheck.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,10 @@
#include "curl_setup.h"
-#if defined(USE_OPENSSL) || defined(USE_AXTLS) || defined(USE_GSKIT)
+#if defined(USE_OPENSSL) \
+ || defined(USE_AXTLS) \
+ || defined(USE_GSKIT) \
+ || (defined(USE_SCHANNEL) && defined(_WIN32_WCE))
/* these backends use functions from this file */
#ifdef HAVE_NETINET_IN_H
@@ -144,4 +147,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
return res;
}
-#endif /* OPENSSL or AXTLS or GSKIT */
+#endif /* OPENSSL, AXTLS, GSKIT or schannel+wince */
diff --git a/Utilities/cmcurl/lib/hostip.c b/Utilities/cmcurl/lib/hostip.c
index 24a922e..fa4bad9 100644
--- a/Utilities/cmcurl/lib/hostip.c
+++ b/Utilities/cmcurl/lib/hostip.c
@@ -172,7 +172,7 @@ Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
const struct in6_addr *ipaddr6;
#endif
- switch (ai->ai_family) {
+ switch(ai->ai_family) {
case AF_INET:
sa4 = (const void *)ai->ai_addr;
ipaddr4 = &sa4->sin_addr;
@@ -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
diff --git a/Utilities/cmcurl/lib/hostip.h b/Utilities/cmcurl/lib/hostip.h
index 9098ee3..1dc4079 100644
--- a/Utilities/cmcurl/lib/hostip.h
+++ b/Utilities/cmcurl/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
/*
@@ -131,7 +131,7 @@ int Curl_mk_dnscache(struct curl_hash *hash);
void Curl_hostcache_prune(struct Curl_easy *data);
/* Return # of adresses in a Curl_addrinfo struct */
-int Curl_num_addresses (const Curl_addrinfo *addr);
+int Curl_num_addresses(const Curl_addrinfo *addr);
#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
@@ -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/Utilities/cmcurl/lib/hostip4.c b/Utilities/cmcurl/lib/hostip4.c
index 15895d7..e459328 100644
--- a/Utilities/cmcurl/lib/hostip4.c
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c
index e7788e7..4c1c07f 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -76,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"
@@ -287,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;
@@ -544,8 +545,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
}
}
if(http_should_fail(conn)) {
- failf (data, "The requested URL returned error: %d",
- data->req.httpcode);
+ failf(data, "The requested URL returned error: %d",
+ data->req.httpcode);
result = CURLE_HTTP_RETURNED_ERROR;
}
@@ -641,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;
}
@@ -839,9 +840,11 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
auth += strlen("NTLM");
while(*auth && ISSPACE(*auth))
auth++;
- if(*auth)
- if((conn->challenge_header = strdup(auth)) == NULL)
+ if(*auth) {
+ conn->challenge_header = strdup(auth);
+ if(!conn->challenge_header)
return CURLE_OUT_OF_MEMORY;
+ }
}
}
#endif
@@ -1098,7 +1101,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
@@ -1255,14 +1260,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;
}
@@ -1350,10 +1354,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;
@@ -1396,50 +1403,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
@@ -2092,7 +2065,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* when doing ftp, append ;type=<a|i> if not present */
char *type = strstr(ppath, ";type=");
if(type && type[6] && type[7] == 0) {
- switch (Curl_raw_toupper(type[6])) {
+ switch(Curl_raw_toupper(type[6])) {
case 'A':
case 'D':
case 'I':
@@ -2328,7 +2301,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
* Free proxyuserpwd for Negotiate/NTLM. Cannot reuse as it is associated
* with the connection and shouldn't be repeated over it either.
*/
- switch (data->state.authproxy.picked) {
+ switch(data->state.authproxy.picked) {
case CURLAUTH_NEGOTIATE:
case CURLAUTH_NTLM:
case CURLAUTH_NTLM_WB:
@@ -2782,7 +2755,7 @@ checkhttpprefix(struct Curl_easy *data,
/* convert from the network encoding using a scratch area */
char *scratch = strdup(s);
if(NULL == scratch) {
- failf (data, "Failed to allocate memory for conversion!");
+ failf(data, "Failed to allocate memory for conversion!");
return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
}
if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
@@ -2820,7 +2793,7 @@ checkrtspprefix(struct Curl_easy *data,
/* convert from the network encoding using a scratch area */
char *scratch = strdup(s);
if(NULL == scratch) {
- failf (data, "Failed to allocate memory for conversion!");
+ failf(data, "Failed to allocate memory for conversion!");
return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
}
if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
@@ -2872,8 +2845,8 @@ static CURLcode header_append(struct Curl_easy *data,
/* The reason to have a max limit for this is to avoid the risk of a bad
server feeding libcurl with a never-ending header that will cause
reallocs infinitely */
- failf (data, "Avoided giant realloc for header (max is %d)!",
- CURL_MAX_HTTP_HEADER);
+ failf(data, "Avoided giant realloc for header (max is %d)!",
+ CURL_MAX_HTTP_HEADER);
return CURLE_OUT_OF_MEMORY;
}
@@ -2881,7 +2854,7 @@ static CURLcode header_append(struct Curl_easy *data,
hbufp_index = k->hbufp - data->state.headerbuff;
newbuff = realloc(data->state.headerbuff, newsize);
if(!newbuff) {
- failf (data, "Failed to alloc memory for big header!");
+ failf(data, "Failed to alloc memory for big header!");
return CURLE_OUT_OF_MEMORY;
}
data->state.headersize=newsize;
@@ -3122,8 +3095,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* up and return an error.
*/
if(http_should_fail(conn)) {
- failf (data, "The requested URL returned error: %d",
- k->httpcode);
+ failf(data, "The requested URL returned error: %d",
+ k->httpcode);
return CURLE_HTTP_RETURNED_ERROR;
}
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c
index cfdb327..4cc17ba 100644
--- a/Utilities/cmcurl/lib/http2.c
+++ b/Utilities/cmcurl/lib/http2.c
@@ -35,7 +35,7 @@
#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,12 @@
#define nghttp2_session_callbacks_set_error_callback(x,y)
#endif
+#if (NGHTTP2_VERSION_NUM >= 0x010c00)
+#define NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE 1
+#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.
@@ -223,7 +229,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 */
@@ -841,10 +848,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;
}
@@ -966,7 +972,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
@@ -1572,6 +1578,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)
+/*
+ * 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)
{
@@ -1587,7 +1659,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;
@@ -1725,7 +1797,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;
@@ -1743,12 +1814,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
goto fail;
hlen = end - hdbuf;
- if(hlen == 10 && strncasecompare("connection", hdbuf, 10)) {
- /* skip Connection: headers! */
- skip = 1;
- --nheader;
- }
- else if(hlen == 4 && strncasecompare("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);
@@ -1761,16 +1827,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;
- }
- ++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 */
@@ -1961,7 +2039,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);
@@ -1969,6 +2048,16 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
}
}
+#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
+ 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;
+ }
+#endif
+
/* 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
@@ -1984,7 +2073,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,
@@ -2024,6 +2114,82 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
return CURLE_OK;
}
+void Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child,
+ bool exclusive)
+{
+ struct Curl_http2_dep **tail;
+ struct Curl_http2_dep *dep = calloc(1, sizeof(struct Curl_http2_dep));
+ dep->data = child;
+
+ if(parent->set.stream_dependents && exclusive) {
+ struct Curl_http2_dep *node = parent->set.stream_dependents;
+ while(node) {
+ node->data->set.stream_depends_on = child;
+ node = node->next;
+ }
+
+ tail = &child->set.stream_dependents;
+ while(*tail)
+ tail = &(*tail)->next;
+
+ DEBUGASSERT(!*tail);
+ *tail = parent->set.stream_dependents;
+ parent->set.stream_dependents = 0;
+ }
+
+ tail = &parent->set.stream_dependents;
+ while(*tail) {
+ (*tail)->data->set.stream_depends_e = FALSE;
+ tail = &(*tail)->next;
+ }
+
+ DEBUGASSERT(!*tail);
+ *tail = dep;
+
+ child->set.stream_depends_on = parent;
+ child->set.stream_depends_e = exclusive;
+}
+
+void Curl_http2_remove_child(struct Curl_easy *parent, struct Curl_easy *child)
+{
+ struct Curl_http2_dep *last = 0;
+ struct Curl_http2_dep *data = parent->set.stream_dependents;
+ DEBUGASSERT(child->set.stream_depends_on == parent);
+
+ while(data && data->data != child) {
+ last = data;
+ data = data->next;
+ }
+
+ DEBUGASSERT(data);
+
+ if(data) {
+ if(last) {
+ last->next = data->next;
+ }
+ else {
+ parent->set.stream_dependents = data->next;
+ }
+ free(data);
+ }
+
+ child->set.stream_depends_on = 0;
+ child->set.stream_depends_e = FALSE;
+}
+
+void Curl_http2_cleanup_dependencies(struct Curl_easy *data)
+{
+ while(data->set.stream_dependents) {
+ struct Curl_easy *tmp = data->set.stream_dependents->data;
+ Curl_http2_remove_child(data, tmp);
+ if(data->set.stream_depends_on)
+ Curl_http2_add_child(data->set.stream_depends_on, tmp, FALSE);
+ }
+
+ if(data->set.stream_depends_on)
+ Curl_http2_remove_child(data->set.stream_depends_on, data);
+}
+
#else /* !USE_NGHTTP2 */
/* Satisfy external references even if http2 is not compiled in. */
diff --git a/Utilities/cmcurl/lib/http2.h b/Utilities/cmcurl/lib/http2.h
index 8917535..f405b3a 100644
--- a/Utilities/cmcurl/lib/http2.h
+++ b/Utilities/cmcurl/lib/http2.h
@@ -53,6 +53,11 @@ 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);
+void Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child,
+ bool exclusive);
+void Curl_http2_remove_child(struct Curl_easy *parent,
+ struct Curl_easy *child);
+void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
#else /* USE_NGHTTP2 */
#define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
@@ -65,6 +70,9 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn);
#define Curl_http2_init_userset(x)
#define Curl_http2_done(x,y)
#define Curl_http2_done_sending(x)
+#define Curl_http2_add_child(x, y, z)
+#define Curl_http2_remove_child(x, y)
+#define Curl_http2_cleanup_dependencies(x)
#endif
#endif /* HEADER_CURL_HTTP2_H */
diff --git a/Utilities/cmcurl/lib/http_chunks.c b/Utilities/cmcurl/lib/http_chunks.c
index ea17109..1bdf697 100644
--- a/Utilities/cmcurl/lib/http_chunks.c
+++ b/Utilities/cmcurl/lib/http_chunks.c
@@ -190,8 +190,8 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
/* Write the data portion available */
#ifdef HAVE_LIBZ
- switch (conn->data->set.http_ce_skip?
- IDENTITY : data->req.auto_decoding) {
+ switch(conn->data->set.http_ce_skip?
+ IDENTITY : data->req.auto_decoding) {
case IDENTITY:
#endif
if(!k->ignorebody) {
@@ -219,10 +219,10 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
break;
default:
- failf (conn->data,
- "Unrecognized content encoding type. "
- "libcurl understands `identity', `deflate' and `gzip' "
- "content encodings.");
+ failf(conn->data,
+ "Unrecognized content encoding type. "
+ "libcurl understands `identity', `deflate' and `gzip' "
+ "content encodings.");
return CHUNKE_BAD_ENCODING;
}
#endif
@@ -360,7 +360,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
const char *Curl_chunked_strerror(CHUNKcode code)
{
- switch (code) {
+ switch(code) {
default:
return "OK";
case CHUNKE_TOO_LONG_HEX:
diff --git a/Utilities/cmcurl/lib/http_digest.c b/Utilities/cmcurl/lib/http_digest.c
index 184d00b..e2d865b 100644
--- a/Utilities/cmcurl/lib/http_digest.c
+++ b/Utilities/cmcurl/lib/http_digest.c
@@ -74,8 +74,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
{
CURLcode result;
struct Curl_easy *data = conn->data;
- unsigned char *path;
- char *tmp;
+ unsigned char *path = NULL;
+ char *tmp = NULL;
char *response;
size_t len;
bool have_chlg;
@@ -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 {
@@ -140,12 +140,14 @@ CURLcode Curl_output_digest(struct connectdata *conn,
http://www.fngtps.com/2006/09/http-authentication
*/
- if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL)) {
- size_t urilen = tmp - (char *)uripath;
-
- path = (unsigned char *) aprintf("%.*s", urilen, uripath);
+ if(authp->iestyle) {
+ tmp = strchr((char *)uripath, '?');
+ if(tmp) {
+ size_t urilen = tmp - (char *)uripath;
+ path = (unsigned char *) aprintf("%.*s", urilen, uripath);
+ }
}
- else
+ if(!tmp)
path = (unsigned char *) strdup((char *) uripath);
if(!path)
diff --git a/Utilities/cmcurl/lib/http_negotiate.c b/Utilities/cmcurl/lib/http_negotiate.c
index eb17ed4..51375e8 100644
--- a/Utilities/cmcurl/lib/http_negotiate.c
+++ b/Utilities/cmcurl/lib/http_negotiate.c
@@ -37,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;
@@ -50,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 {
@@ -89,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/Utilities/cmcurl/lib/http_ntlm.c b/Utilities/cmcurl/lib/http_ntlm.c
index e424040..21c77cd 100644
--- a/Utilities/cmcurl/lib/http_ntlm.c
+++ b/Utilities/cmcurl/lib/http_ntlm.c
@@ -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/Utilities/cmcurl/lib/http_proxy.c b/Utilities/cmcurl/lib/http_proxy.c
index 8f5e9b4..e0213f3 100644
--- a/Utilities/cmcurl/lib/http_proxy.c
+++ b/Utilities/cmcurl/lib/http_proxy.c
@@ -35,14 +35,50 @@
#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 */
@@ -68,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)
@@ -113,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
@@ -161,7 +202,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
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;
@@ -244,7 +285,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
}
if(!blocking) {
- if(0 == SOCKET_READABLE(tunnelsocket, 0))
+ if(!Curl_conn_data_pending(conn, sockindex))
/* return so we'll be called again polling-style */
return CURLE_OK;
else {
@@ -263,13 +304,22 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
char *ptr;
char *line_start;
- ptr=data->state.buffer;
+ ptr = data->state.buffer;
line_start = ptr;
- nread=0;
- perline=0;
+ nread = 0;
+ perline = 0;
+
+ while(nread < BUFSIZE && keepon && !error) {
+ int writetype;
- while((nread<BUFSIZE) && (keepon && !error)) {
+ if(Curl_pgrsUpdate(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
+
+ if(ptr >= &data->state.buffer[BUFSIZE]) {
+ failf(data, "CONNECT response too large!");
+ return CURLE_RECV_ERROR;
+ }
check = Curl_timeleft(data, NULL, TRUE);
if(check <= 0) {
@@ -278,253 +328,233 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
break;
}
- /* loop every second at least, less if the timeout is near */
- 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");
+ /* Read one byte at a time to avoid a race condition. Wait at most one
+ second before looping to ensure continuous pgrsUpdates. */
+ result = Curl_read(conn, tunnelsocket, ptr, 1, &gotbytes);
+ if(result == CURLE_AGAIN) {
+ if(SOCKET_READABLE(tunnelsocket, check<1000L?check:1000) == -1) {
+ error = SELECT_ERROR;
+ failf(data, "Proxy CONNECT aborted due to select/poll error");
+ break;
+ }
+ continue;
+ }
+ else if(result) {
+ keepon = FALSE;
break;
- case 0: /* timeout */
+ }
+ else if(gotbytes <= 0) {
+ if(data->set.proxyauth && data->state.authproxy.avail) {
+ /* proxy auth was requested and there was proxy auth available,
+ then deem this as "mere" proxy disconnect */
+ conn->bits.proxy_connect_closed = TRUE;
+ infof(data, "Proxy CONNECT connection closed\n");
+ }
+ else {
+ error = SELECT_ERROR;
+ failf(data, "Proxy CONNECT aborted");
+ }
+ keepon = FALSE;
break;
- default:
- DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1);
- result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread,
- &gotbytes);
- if(result==CURLE_AGAIN)
- continue; /* go loop yourself */
- else if(result)
- keepon = FALSE;
- else if(gotbytes <= 0) {
- keepon = FALSE;
- if(data->set.proxyauth && data->state.authproxy.avail) {
- /* proxy auth was requested and there was proxy auth available,
- then deem this as "mere" proxy disconnect */
- conn->bits.proxy_connect_closed = TRUE;
- infof(data, "Proxy CONNECT connection closed\n");
- }
- else {
- error = SELECT_ERROR;
- failf(data, "Proxy CONNECT aborted");
+ }
+
+ /* We got a byte of data */
+ nread++;
+
+ if(keepon > TRUE) {
+ /* This means we are currently ignoring a response-body */
+
+ nread = 0; /* make next read start over in the read buffer */
+ ptr = data->state.buffer;
+ if(cl) {
+ /* A Content-Length based body: simply count down the counter
+ and make sure to break out of the loop when we're done! */
+ cl--;
+ if(cl <= 0) {
+ keepon = FALSE;
+ break;
}
}
else {
- /*
- * We got a whole chunk of data, which can be anything from one
- * byte to a set of lines and possibly just a piece of the last
- * line.
- */
- int i;
-
- nread += gotbytes;
-
- if(keepon > TRUE) {
- /* This means we are currently ignoring a response-body */
-
- nread = 0; /* make next read start over in the read buffer */
- ptr=data->state.buffer;
- if(cl) {
- /* A Content-Length based body: simply count down the counter
- and make sure to break out of the loop when we're done! */
- cl -= gotbytes;
- if(cl<=0) {
- keepon = FALSE;
- break;
- }
+ /* chunked-encoded body, so we need to do the chunked dance
+ properly to know when the end of the body is reached */
+ CHUNKcode r;
+ ssize_t tookcareof = 0;
+
+ /* now parse the chunked piece of data so that we can
+ properly tell when the stream ends */
+ r = Curl_httpchunk_read(conn, ptr, 1, &tookcareof);
+ if(r == CHUNKE_STOP) {
+ /* we're done reading chunks! */
+ infof(data, "chunk reading DONE\n");
+ keepon = FALSE;
+ /* we did the full CONNECT treatment, go COMPLETE */
+ conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
+ }
+ }
+ continue;
+ }
+
+ perline++; /* amount of bytes in this line so far */
+
+ /* if this is not the end of a header line then continue */
+ if(*ptr != 0x0a) {
+ ptr++;
+ continue;
+ }
+
+ /* convert from the network encoding */
+ result = Curl_convert_from_network(data, line_start, perline);
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ if(result)
+ return result;
+
+ /* output debug if that is requested */
+ if(data->set.verbose)
+ Curl_debug(data, CURLINFO_HEADER_IN,
+ line_start, (size_t)perline, conn);
+
+ /* send the header to the callback */
+ writetype = CLIENTWRITE_HEADER;
+ if(data->set.include_header)
+ writetype |= CLIENTWRITE_BODY;
+
+ result = Curl_client_write(conn, writetype, line_start, perline);
+
+ data->info.header_size += (long)perline;
+ data->req.headerbytecount += (long)perline;
+
+ if(result)
+ return result;
+
+ /* Newlines are CRLF, so the CR is ignored as the line isn't
+ really terminated until the LF comes. Treat a following CR
+ as end-of-headers as well.*/
+
+ if(('\r' == line_start[0]) ||
+ ('\n' == line_start[0])) {
+ /* end of response-headers from the proxy */
+ nread = 0; /* make next read start over in the read
+ buffer */
+ ptr = data->state.buffer;
+ if((407 == k->httpcode) && !data->state.authproblem) {
+ /* If we get a 407 response code with content length
+ when we have no auth problem, we must ignore the
+ whole response-body */
+ keepon = 2;
+
+ if(cl) {
+ infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T
+ " bytes of response-body\n", cl);
+ }
+ else if(chunked_encoding) {
+ CHUNKcode r;
+
+ infof(data, "Ignore chunked response-body\n");
+
+ /* We set ignorebody true here since the chunked
+ decoder function will acknowledge that. Pay
+ attention so that this is cleared again when this
+ function returns! */
+ k->ignorebody = TRUE;
+
+ if(line_start[1] == '\n') {
+ /* this can only be a LF if the letter at index 0
+ was a CR */
+ line_start++;
}
- else {
- /* chunked-encoded body, so we need to do the chunked dance
- properly to know when the end of the body is reached */
- CHUNKcode r;
- ssize_t tookcareof=0;
-
- /* now parse the chunked piece of data so that we can
- properly tell when the stream ends */
- r = Curl_httpchunk_read(conn, ptr, gotbytes, &tookcareof);
- if(r == CHUNKE_STOP) {
- /* we're done reading chunks! */
- infof(data, "chunk reading DONE\n");
- keepon = FALSE;
- /* we did the full CONNECT treatment, go COMPLETE */
- conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
- }
- else
- infof(data, "Read %zd bytes of chunk, continue\n",
- tookcareof);
+
+ /* now parse the chunked piece of data so that we can
+ properly tell when the stream ends */
+ r = Curl_httpchunk_read(conn, line_start + 1, 1, &gotbytes);
+ if(r == CHUNKE_STOP) {
+ /* we're done reading chunks! */
+ infof(data, "chunk reading DONE\n");
+ keepon = FALSE;
+ /* we did the full CONNECT treatment, go to
+ COMPLETE */
+ conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
}
}
- else
- for(i = 0; i < gotbytes; ptr++, i++) {
- perline++; /* amount of bytes in this line so far */
- if(*ptr == 0x0a) {
- char letter;
- int writetype;
-
- /* convert from the network encoding */
- result = Curl_convert_from_network(data, line_start,
- perline);
- /* Curl_convert_from_network calls failf if unsuccessful */
- if(result)
- return result;
-
- /* output debug if that is requested */
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN,
- line_start, (size_t)perline, conn);
-
- /* send the header to the callback */
- writetype = CLIENTWRITE_HEADER;
- if(data->set.include_header)
- writetype |= CLIENTWRITE_BODY;
-
- result = Curl_client_write(conn, writetype, line_start,
- perline);
-
- data->info.header_size += (long)perline;
- data->req.headerbytecount += (long)perline;
-
- if(result)
- return result;
-
- /* Newlines are CRLF, so the CR is ignored as the line isn't
- really terminated until the LF comes. Treat a following CR
- as end-of-headers as well.*/
-
- if(('\r' == line_start[0]) ||
- ('\n' == line_start[0])) {
- /* end of response-headers from the proxy */
- nread = 0; /* make next read start over in the read
- buffer */
- ptr=data->state.buffer;
- if((407 == k->httpcode) && !data->state.authproblem) {
- /* If we get a 407 response code with content length
- when we have no auth problem, we must ignore the
- whole response-body */
- keepon = 2;
-
- if(cl) {
- infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T
- " bytes of response-body\n", cl);
-
- /* remove the remaining chunk of what we already
- read */
- cl -= (gotbytes - i);
-
- if(cl<=0)
- /* if the whole thing was already read, we are done!
- */
- keepon=FALSE;
- }
- else if(chunked_encoding) {
- CHUNKcode r;
- /* We set ignorebody true here since the chunked
- decoder function will acknowledge that. Pay
- attention so that this is cleared again when this
- function returns! */
- k->ignorebody = TRUE;
- infof(data, "%zd bytes of chunk left\n", gotbytes-i);
-
- if(line_start[1] == '\n') {
- /* this can only be a LF if the letter at index 0
- was a CR */
- line_start++;
- i++;
- }
-
- /* now parse the chunked piece of data so that we can
- properly tell when the stream ends */
- r = Curl_httpchunk_read(conn, line_start+1,
- gotbytes -i, &gotbytes);
- if(r == CHUNKE_STOP) {
- /* we're done reading chunks! */
- infof(data, "chunk reading DONE\n");
- keepon = FALSE;
- /* we did the full CONNECT treatment, go to
- COMPLETE */
- conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
- }
- else
- infof(data, "Read %zd bytes of chunk, continue\n",
- gotbytes);
- }
- else {
- /* without content-length or chunked encoding, we
- can't keep the connection alive since the close is
- the end signal so we bail out at once instead */
- keepon=FALSE;
- }
- }
- else {
- keepon = FALSE;
- if(200 == data->info.httpproxycode) {
- if(gotbytes - (i+1))
- failf(data, "Proxy CONNECT followed by %zd bytes "
- "of opaque data. Data ignored (known bug #39)",
- gotbytes - (i+1));
- }
- }
- /* we did the full CONNECT treatment, go to COMPLETE */
- conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
- break; /* breaks out of for-loop, not switch() */
- }
-
- /* keep a backup of the position we are about to blank */
- letter = line_start[perline];
- line_start[perline]=0; /* zero terminate the buffer */
- if((checkprefix("WWW-Authenticate:", line_start) &&
- (401 == k->httpcode)) ||
- (checkprefix("Proxy-authenticate:", line_start) &&
- (407 == k->httpcode))) {
-
- bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
- char *auth = Curl_copy_header_value(line_start);
- if(!auth)
- return CURLE_OUT_OF_MEMORY;
-
- result = Curl_http_input_auth(conn, proxy, auth);
-
- free(auth);
-
- if(result)
- return result;
- }
- else if(checkprefix("Content-Length:", line_start)) {
- cl = curlx_strtoofft(line_start +
- strlen("Content-Length:"), NULL, 10);
- }
- else if(Curl_compareheader(line_start,
- "Connection:", "close"))
- closeConnection = TRUE;
- else if(Curl_compareheader(line_start,
- "Transfer-Encoding:",
- "chunked")) {
- infof(data, "CONNECT responded chunked\n");
- chunked_encoding = TRUE;
- /* init our chunky engine */
- Curl_httpchunk_init(conn);
- }
- else if(Curl_compareheader(line_start,
- "Proxy-Connection:", "close"))
- closeConnection = TRUE;
- else if(2 == sscanf(line_start, "HTTP/1.%d %d",
- &subversion,
- &k->httpcode)) {
- /* store the HTTP code from the proxy */
- data->info.httpproxycode = k->httpcode;
- }
- /* put back the letter we blanked out before */
- line_start[perline]= letter;
-
- perline=0; /* line starts over here */
- line_start = ptr+1; /* this skips the zero byte we wrote */
- }
- }
+ else {
+ /* without content-length or chunked encoding, we
+ can't keep the connection alive since the close is
+ the end signal so we bail out at once instead */
+ keepon = FALSE;
+ }
}
- break;
- } /* switch */
- if(Curl_pgrsUpdate(conn))
- return CURLE_ABORTED_BY_CALLBACK;
+ else
+ keepon = FALSE;
+ /* we did the full CONNECT treatment, go to COMPLETE */
+ conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
+ continue;
+ }
+
+ line_start[perline] = 0; /* zero terminate the buffer */
+ if((checkprefix("WWW-Authenticate:", line_start) &&
+ (401 == k->httpcode)) ||
+ (checkprefix("Proxy-authenticate:", line_start) &&
+ (407 == k->httpcode))) {
+
+ bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
+ char *auth = Curl_copy_header_value(line_start);
+ if(!auth)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = Curl_http_input_auth(conn, proxy, auth);
+
+ free(auth);
+
+ if(result)
+ return result;
+ }
+ else if(checkprefix("Content-Length:", line_start)) {
+ if(k->httpcode/100 == 2) {
+ /* A server MUST NOT send any Transfer-Encoding or
+ Content-Length header fields in a 2xx (Successful)
+ response to CONNECT. (RFC 7231 section 4.3.6) */
+ failf(data, "Content-Length: in %03d response",
+ k->httpcode);
+ return CURLE_RECV_ERROR;
+ }
+
+ cl = curlx_strtoofft(line_start +
+ strlen("Content-Length:"), NULL, 10);
+ }
+ else if(Curl_compareheader(line_start, "Connection:", "close"))
+ closeConnection = TRUE;
+ else if(Curl_compareheader(line_start,
+ "Transfer-Encoding:",
+ "chunked")) {
+ if(k->httpcode/100 == 2) {
+ /* A server MUST NOT send any Transfer-Encoding or
+ Content-Length header fields in a 2xx (Successful)
+ response to CONNECT. (RFC 7231 section 4.3.6) */
+ failf(data, "Transfer-Encoding: in %03d response", k->httpcode);
+ return CURLE_RECV_ERROR;
+ }
+ infof(data, "CONNECT responded chunked\n");
+ chunked_encoding = TRUE;
+ /* init our chunky engine */
+ Curl_httpchunk_init(conn);
+ }
+ else if(Curl_compareheader(line_start, "Proxy-Connection:", "close"))
+ closeConnection = TRUE;
+ else if(2 == sscanf(line_start, "HTTP/1.%d %d",
+ &subversion,
+ &k->httpcode)) {
+ /* store the HTTP code from the proxy */
+ data->info.httpproxycode = k->httpcode;
+ }
+
+ perline = 0; /* line starts over here */
+ ptr = data->state.buffer;
+ line_start = ptr;
} /* while there's buffer left and loop is requested */
+ if(Curl_pgrsUpdate(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
+
if(error)
return CURLE_RECV_ERROR;
@@ -538,8 +568,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
if(conn->bits.close)
/* the connection has been marked for closure, most likely in the
Curl_http_auth_act() function and thus we can kill it at once
- below
- */
+ below */
closeConnection = TRUE;
}
@@ -600,7 +629,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
data->state.authproxy.done = TRUE;
- infof (data, "Proxy replied OK to CONNECT request\n");
+ infof(data, "Proxy replied OK to CONNECT request\n");
data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */
conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the
document request */
diff --git a/Utilities/cmcurl/lib/http_proxy.h b/Utilities/cmcurl/lib/http_proxy.h
index fd04330..d1f5a7c 100644
--- a/Utilities/cmcurl/lib/http_proxy.h
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/if2ip.c b/Utilities/cmcurl/lib/if2ip.c
index e6faa4b..d876615 100644
--- a/Utilities/cmcurl/lib/if2ip.c
+++ b/Utilities/cmcurl/lib/if2ip.c
@@ -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) {
diff --git a/Utilities/cmcurl/lib/imap.c b/Utilities/cmcurl/lib/imap.c
index 4aa7dcc..78dc6fa 100644
--- a/Utilities/cmcurl/lib/imap.c
+++ b/Utilities/cmcurl/lib/imap.c
@@ -107,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.
@@ -390,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++)
diff --git a/Utilities/cmcurl/lib/inet_ntop.c b/Utilities/cmcurl/lib/inet_ntop.c
index 416005c..9afbdbb 100644
--- a/Utilities/cmcurl/lib/inet_ntop.c
+++ b/Utilities/cmcurl/lib/inet_ntop.c
@@ -182,12 +182,12 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
*/
char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
{
- switch (af) {
+ 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/Utilities/cmcurl/lib/inet_pton.c b/Utilities/cmcurl/lib/inet_pton.c
index cf8b88a..475f44a 100644
--- a/Utilities/cmcurl/lib/inet_pton.c
+++ b/Utilities/cmcurl/lib/inet_pton.c
@@ -65,7 +65,7 @@ static int inet_pton6(const char *src, unsigned char *dst);
int
Curl_inet_pton(int af, const char *src, void *dst)
{
- switch (af) {
+ switch(af) {
case AF_INET:
return (inet_pton4(src, (unsigned char *)dst));
#ifdef ENABLE_IPV6
@@ -103,7 +103,8 @@ inet_pton4(const char *src, unsigned char *dst)
while((ch = *src++) != '\0') {
const char *pch;
- if((pch = strchr(digits, ch)) != NULL) {
+ pch = strchr(digits, ch);
+ if(pch) {
unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
if(saw_digit && *tp == 0)
@@ -169,7 +170,8 @@ inet_pton6(const char *src, unsigned char *dst)
while((ch = *src++) != '\0') {
const char *pch;
- if((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_l), ch);
+ if(!pch)
pch = strchr((xdigits = xdigits_u), ch);
if(pch != NULL) {
val <<= 4;
diff --git a/Utilities/cmcurl/lib/krb5.c b/Utilities/cmcurl/lib/krb5.c
index 5d5c003..067b0a5 100644
--- a/Utilities/cmcurl/lib/krb5.c
+++ b/Utilities/cmcurl/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,
diff --git a/Utilities/cmcurl/lib/ldap.c b/Utilities/cmcurl/lib/ldap.c
index 7dbc1b0..979ce7d 100644
--- a/Utilities/cmcurl/lib/ldap.c
+++ b/Utilities/cmcurl/lib/ldap.c
@@ -109,9 +109,9 @@ typedef struct {
#undef LDAPURLDesc
#define LDAPURLDesc CURL_LDAPURLDesc
-static int _ldap_url_parse (const struct connectdata *conn,
- LDAPURLDesc **ludp);
-static void _ldap_free_urldesc (LDAPURLDesc *ludp);
+static int _ldap_url_parse(const struct connectdata *conn,
+ LDAPURLDesc **ludp);
+static void _ldap_free_urldesc(LDAPURLDesc *ludp);
#undef ldap_free_urldesc
#define ldap_free_urldesc _ldap_free_urldesc
@@ -119,11 +119,11 @@ static void _ldap_free_urldesc (LDAPURLDesc *ludp);
#ifdef DEBUG_LDAP
#define LDAP_TRACE(x) do { \
- _ldap_trace ("%u: ", __LINE__); \
+ _ldap_trace("%u: ", __LINE__); \
_ldap_trace x; \
} WHILE_FALSE
- static void _ldap_trace (const char *fmt, ...);
+ static void _ldap_trace(const char *fmt, ...);
#else
#define LDAP_TRACE(x) Curl_nop_stmt
#endif
@@ -271,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) {
@@ -279,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]) &&
- (strcasecompare(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!",
@@ -321,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]) &&
- (!strcasecompare(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;
@@ -655,7 +655,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
quit:
if(ldapmsg) {
ldap_msgfree(ldapmsg);
- LDAP_TRACE (("Received %d entries\n", num));
+ LDAP_TRACE(("Received %d entries\n", num));
}
if(rc == LDAP_SIZELIMIT_EXCEEDED)
infof(data, "There are more than %d entries\n", num);
@@ -682,7 +682,7 @@ quit:
}
#ifdef DEBUG_LDAP
-static void _ldap_trace (const char *fmt, ...)
+static void _ldap_trace(const char *fmt, ...)
{
static int do_trace = -1;
va_list args;
@@ -694,9 +694,9 @@ static void _ldap_trace (const char *fmt, ...)
if(!do_trace)
return;
- va_start (args, fmt);
- vfprintf (stderr, fmt, args);
- va_end (args);
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
}
#endif
@@ -705,7 +705,7 @@ static void _ldap_trace (const char *fmt, ...)
/*
* Return scope-value for a scope-string.
*/
-static int str2scope (const char *p)
+static int str2scope(const char *p)
{
if(strcasecompare(p, "one"))
return LDAP_SCOPE_ONELEVEL;
@@ -799,7 +799,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
char *unescaped;
CURLcode result;
- LDAP_TRACE (("DN '%s'\n", dn));
+ LDAP_TRACE(("DN '%s'\n", dn));
/* Unescape the DN */
result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE);
@@ -864,7 +864,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
char *unescaped;
CURLcode result;
- LDAP_TRACE (("attr[%d] '%s'\n", i, attributes[i]));
+ LDAP_TRACE(("attr[%d] '%s'\n", i, attributes[i]));
/* Unescape the attribute */
result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
@@ -917,7 +917,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
goto quit;
}
- LDAP_TRACE (("scope %d\n", ludp->lud_scope));
+ LDAP_TRACE(("scope %d\n", ludp->lud_scope));
}
p = q;
@@ -934,7 +934,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
char *unescaped;
CURLcode result;
- LDAP_TRACE (("filter '%s'\n", filter));
+ LDAP_TRACE(("filter '%s'\n", filter));
/* Unescape the filter */
result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE);
@@ -1009,7 +1009,7 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp)
free(ludp->lud_attrs);
}
- free (ludp);
+ free(ludp);
}
#endif /* !HAVE_LDAP_URL_PARSE */
#endif /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */
diff --git a/Utilities/cmcurl/lib/md4.c b/Utilities/cmcurl/lib/md4.c
index 60f73a2..1bdc9f3 100644
--- a/Utilities/cmcurl/lib/md4.c
+++ b/Utilities/cmcurl/lib/md4.c
@@ -213,7 +213,8 @@ static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
unsigned long used, available;
saved_lo = ctx->lo;
- if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+ ctx->lo = (saved_lo + size) & 0x1fffffff;
+ if(ctx->lo < saved_lo)
ctx->hi++;
ctx->hi += (MD4_u32plus)size >> 29;
diff --git a/Utilities/cmcurl/lib/md5.c b/Utilities/cmcurl/lib/md5.c
index f818d32..f2dc16c 100644
--- a/Utilities/cmcurl/lib/md5.c
+++ b/Utilities/cmcurl/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);
@@ -402,7 +402,8 @@ static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
unsigned long used, available;
saved_lo = ctx->lo;
- if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+ ctx->lo = (saved_lo + size) & 0x1fffffff;
+ if(ctx->lo < saved_lo)
ctx->hi++;
ctx->hi += (MD5_u32plus)size >> 29;
diff --git a/Utilities/cmcurl/lib/memdebug.c b/Utilities/cmcurl/lib/memdebug.c
index ccbf461..15e8661 100644
--- a/Utilities/cmcurl/lib/memdebug.c
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/mprintf.c b/Utilities/cmcurl/lib/mprintf.c
index 3cdd41a..4baa1cc 100644
--- a/Utilities/cmcurl/lib/mprintf.c
+++ b/Utilities/cmcurl/lib/mprintf.c
@@ -88,7 +88,8 @@
# define mp_uintmax_t unsigned long
#endif
-#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
+#define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should
+ fit negative DBL_MAX (317 letters) */
#define MAX_PARAMETERS 128 /* lame static limit */
#ifdef __AMIGA__
@@ -299,7 +300,6 @@ static int 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 */
@@ -498,7 +498,7 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
(mp_intmax_t)va_arg(arglist, int);
}
- switch (vto[i].type) {
+ switch(vto[i].type) {
case FORMAT_STRING:
vto[i].data.str = va_arg(arglist, char *);
break;
@@ -688,7 +688,7 @@ static int dprintf_formatf(
is_alt = (p->flags & FLAGS_ALT) ? 1 : 0;
- switch (p->type) {
+ switch(p->type) {
case FORMAT_INT:
num = p->data.num.as_unsigned;
if(p->flags & FLAGS_CHAR) {
@@ -913,12 +913,25 @@ static int dprintf_formatf(
*fptr = 0;
if(width >= 0) {
+ if(width >= (long)sizeof(work))
+ width = sizeof(work)-1;
/* RECURSIVE USAGE */
len = curl_msnprintf(fptr, left, "%ld", width);
fptr += len;
left -= len;
}
if(prec >= 0) {
+ /* for each digit in the integer part, we can have one less
+ precision */
+ size_t maxprec = sizeof(work) - 2;
+ double val = p->data.dnum;
+ while(val >= 10.0) {
+ val /= 10;
+ maxprec--;
+ }
+
+ if(prec > (long)maxprec)
+ prec = (long)maxprec-1;
/* RECURSIVE USAGE */
len = curl_msnprintf(fptr, left, ".%ld", prec);
fptr += len;
@@ -938,7 +951,9 @@ static int dprintf_formatf(
/* NOTE NOTE NOTE!! Not all sprintf implementations return number of
output characters */
(sprintf)(work, formatbuf, p->data.dnum);
-
+#ifdef CURLDEBUG
+ assert(strlen(work) <= sizeof(work));
+#endif
for(fptr=work; *fptr; fptr++)
OUTCHAR(*fptr);
}
diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c
index 2432b15..950b600 100644
--- a/Utilities/cmcurl/lib/multi.c
+++ b/Utilities/cmcurl/lib/multi.c
@@ -42,6 +42,7 @@
#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"
@@ -812,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];
@@ -1300,7 +1306,7 @@ 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))
@@ -1548,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);
@@ -1561,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:
@@ -2486,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);
@@ -2764,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
@@ -2871,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;
@@ -2898,7 +2914,7 @@ multi_addtimeout(struct curl_llist *timeoutlist,
* 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, long milli)
+void Curl_expire(struct Curl_easy *data, time_t milli)
{
struct Curl_multi *multi = data->multi;
struct timeval *nowp = &data->state.expiretime;
@@ -2911,7 +2927,7 @@ void Curl_expire(struct Curl_easy *data, long milli)
return;
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) {
@@ -2923,7 +2939,7 @@ void Curl_expire(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, *nowp);
+ 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 */
@@ -2961,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) {
@@ -2980,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;
diff --git a/Utilities/cmcurl/lib/multihandle.h b/Utilities/cmcurl/lib/multihandle.h
index c56b6ae..0b78de9 100644
--- a/Utilities/cmcurl/lib/multihandle.h
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/multiif.h b/Utilities/cmcurl/lib/multiif.h
index eaff496..e5de1fc 100644
--- a/Utilities/cmcurl/lib/multiif.h
+++ b/Utilities/cmcurl/lib/multiif.h
@@ -25,9 +25,9 @@
/*
* Prototypes for library-wide functions provided by multi.c
*/
-void Curl_expire(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, long milli);
+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/Utilities/cmcurl/lib/non-ascii.c b/Utilities/cmcurl/lib/non-ascii.c
index ed14618..2f5de4c 100644
--- a/Utilities/cmcurl/lib/non-ascii.c
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/nwlib.c b/Utilities/cmcurl/lib/nwlib.c
index 42b6aa0..290cbe3 100644
--- a/Utilities/cmcurl/lib/nwlib.c
+++ b/Utilities/cmcurl/lib/nwlib.c
@@ -184,7 +184,8 @@ int GetOrSetUpData(int id, libdata_t **appData,
*/
NXLock(gLibLock);
- if(!(app_data = (libdata_t *) get_app_data(id))) {
+ app_data = (libdata_t *) get_app_data(id);
+ if(!app_data) {
app_data = malloc(sizeof(libdata_t));
if(app_data) {
@@ -259,7 +260,8 @@ int GetOrSetUpData(int id, libdata_t **appData,
err = ENOMEM;
}
- if((err = NXKeySetValue(key, thread_data))) {
+ err = NXKeySetValue(key, thread_data);
+ if(err) {
free(thread_data->twentybytes);
free(thread_data);
thread_data = (libthreaddata_t *) NULL;
@@ -303,14 +305,14 @@ void DisposeThreadData(void *data)
/* For native CLib-based NLM seems we can do a bit more simple. */
#include <nwthread.h>
-int main (void)
+int main(void)
{
/* initialize any globals here... */
/* do this if any global initializing was done
SynchronizeStart();
*/
- ExitThread (TSR_THREAD, 0);
+ ExitThread(TSR_THREAD, 0);
return 0;
}
diff --git a/Utilities/cmcurl/lib/nwos.c b/Utilities/cmcurl/lib/nwos.c
index 385f9c8..c6c22cc 100644
--- a/Utilities/cmcurl/lib/nwos.c
+++ b/Utilities/cmcurl/lib/nwos.c
@@ -26,7 +26,7 @@
#ifdef __NOVELL_LIBC__
/* For native LibC-based NLM we need to do nothing. */
-int netware_init (void)
+int netware_init(void)
{
return 0;
}
@@ -45,7 +45,7 @@ NETDB_DEFINE_CONTEXT
#include <arpa/inet.h>
NETINET_DEFINE_CONTEXT
-int netware_init (void)
+int netware_init(void)
{
int rc = 0;
unsigned int myHandle = GetNLMHandle();
@@ -72,13 +72,13 @@ int netware_init (void)
}
/* dummy function to satisfy newer prelude */
-int __init_environment (void)
+int __init_environment(void)
{
return 0;
}
/* dummy function to satisfy newer prelude */
-int __deinit_environment (void)
+int __deinit_environment(void)
{
return 0;
}
diff --git a/Utilities/cmcurl/lib/pingpong.c b/Utilities/cmcurl/lib/pingpong.c
index bf2c8fd..7a99357 100644
--- a/Utilities/cmcurl/lib/pingpong.c
+++ b/Utilities/cmcurl/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,7 +101,9 @@ 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))
diff --git a/Utilities/cmcurl/lib/pingpong.h b/Utilities/cmcurl/lib/pingpong.h
index 2f649d5..500100a 100644
--- a/Utilities/cmcurl/lib/pingpong.h
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/pop3.c b/Utilities/cmcurl/lib/pop3.c
index 8486519..9bb691c 100644
--- a/Utilities/cmcurl/lib/pop3.c
+++ b/Utilities/cmcurl/lib/pop3.c
@@ -104,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.
@@ -290,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++)
@@ -1572,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/Utilities/cmcurl/lib/progress.c b/Utilities/cmcurl/lib/progress.c
index 0f67ef2..60627b2 100644
--- a/Utilities/cmcurl/lib/progress.c
+++ b/Utilities/cmcurl/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
@@ -249,24 +249,26 @@ long Curl_pgrsLimitWaitTime(curl_off_t cursize,
struct timeval start,
struct timeval now)
{
- curl_off_t size = cursize - startsize;
- long minimum, actual;
+ 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;
+ /* 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;
+ /* not enough data yet */
+ if(size < limit)
+ return -1;
- minimum = (long) (CURL_OFF_T_C(1000) * size / limit);
- actual = Curl_tvdiff(now, start);
+ minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit);
+ actual = Curl_tvdiff(now, start);
- if(actual < minimum)
- return minimum - actual;
- else
- return 0;
+ 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)
@@ -359,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 */
@@ -375,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;
@@ -402,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/Utilities/cmcurl/lib/rand.c b/Utilities/cmcurl/lib/rand.c
new file mode 100644
index 0000000..a51951c
--- /dev/null
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/rand.h b/Utilities/cmcurl/lib/rand.h
new file mode 100644
index 0000000..0f89861
--- /dev/null
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/rtsp.c b/Utilities/cmcurl/lib/rtsp.c
index d1bad19..65c6c3b 100644
--- a/Utilities/cmcurl/lib/rtsp.c
+++ b/Utilities/cmcurl/lib/rtsp.c
@@ -36,6 +36,7 @@
#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"
@@ -139,7 +140,7 @@ static CURLcode rtsp_setup_connection(struct connectdata *conn)
* want to block the application forever while receiving a stream. Therefore,
* we cannot assume that an RTSP socket is dead just because it is readable.
*
- * Instead, if it is readable, run Curl_getconnectinfo() to peek at the socket
+ * Instead, if it is readable, run Curl_connalive() to peek at the socket
* and distinguish between closed and data.
*/
bool Curl_rtsp_connisdead(struct connectdata *check)
@@ -156,12 +157,9 @@ bool Curl_rtsp_connisdead(struct connectdata *check)
/* socket is in an error state */
ret_val = TRUE;
}
- else if((sval & CURL_CSELECT_IN) && check->data) {
- /* readable with no error. could be closed or could be alive but we can
- only check if we have a proper Curl_easy for the connection */
- curl_socket_t connectinfo = Curl_getconnectinfo(check->data, &check);
- if(connectinfo != CURL_SOCKET_BAD)
- ret_val = FALSE;
+ else if(sval & CURL_CSELECT_IN) {
+ /* readable with no error. could still be closed */
+ ret_val = !Curl_connalive(check);
}
return ret_val;
@@ -488,7 +486,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
* Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM
* with basic and digest, it will be freed anyway by the next request
*/
- Curl_safefree (conn->allocptr.userpwd);
+ Curl_safefree(conn->allocptr.userpwd);
conn->allocptr.userpwd = NULL;
if(result)
@@ -614,9 +612,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;
@@ -736,7 +734,7 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
curl_write_callback writeit;
if(len == 0) {
- failf (data, "Cannot write a 0 size RTP packet.");
+ failf(data, "Cannot write a 0 size RTP packet.");
return CURLE_WRITE_ERROR;
}
@@ -744,12 +742,12 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
wrote = writeit(ptr, 1, len, data->set.rtp_out);
if(CURL_WRITEFUNC_PAUSE == wrote) {
- failf (data, "Cannot pause RTP");
+ failf(data, "Cannot pause RTP");
return CURLE_WRITE_ERROR;
}
if(wrote != len) {
- failf (data, "Failed writing RTP data");
+ failf(data, "Failed writing RTP data");
return CURLE_WRITE_ERROR;
}
diff --git a/Utilities/cmcurl/lib/security.c b/Utilities/cmcurl/lib/security.c
index ff26066..4a8f444 100644
--- a/Utilities/cmcurl/lib/security.c
+++ b/Utilities/cmcurl/lib/security.c
@@ -62,7 +62,7 @@
#include "sendf.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';
@@ -202,7 +203,7 @@ static CURLcode read_data(struct connectdata *conn,
if(len) {
/* only realloc if there was a length */
len = ntohl(len);
- tmp = realloc(buf->data, len);
+ tmp = Curl_saferealloc(buf->data, len);
}
if(tmp == NULL)
return CURLE_OUT_OF_MEMORY;
@@ -222,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;
}
@@ -291,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 */
@@ -411,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/Utilities/cmcurl/lib/select.c b/Utilities/cmcurl/lib/select.c
index d5caa70..6bb0ab1 100644
--- a/Utilities/cmcurl/lib/select.c
+++ b/Utilities/cmcurl/lib/select.c
@@ -145,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];
diff --git a/Utilities/cmcurl/lib/select.h b/Utilities/cmcurl/lib/select.h
index 1d26f49..e247bd9 100644
--- a/Utilities/cmcurl/lib/select.h
+++ b/Utilities/cmcurl/lib/select.h
@@ -73,7 +73,7 @@ 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);
#define SOCKET_READABLE(x,z) \
Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, z)
diff --git a/Utilities/cmcurl/lib/sendf.c b/Utilities/cmcurl/lib/sendf.c
index 2101797..7601697 100644
--- a/Utilities/cmcurl/lib/sendf.c
+++ b/Utilities/cmcurl/lib/sendf.c
@@ -122,6 +122,13 @@ static size_t convert_lineends(struct Curl_easy *data,
#endif /* CURL_DO_LINEEND_CONV */
#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
+bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
+{
+ struct postponed_data * const psnd = &(conn->postponed[sockindex]);
+ return psnd->buffer && psnd->allocated_size &&
+ psnd->recv_size > psnd->recv_processed;
+}
+
static void pre_receive_plain(struct connectdata *conn, int num)
{
const curl_socket_t sockfd = conn->sock[num];
@@ -201,6 +208,12 @@ static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf,
}
#else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
/* Use "do-nothing" macros instead of functions when workaround not used */
+bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
+{
+ (void)conn;
+ (void)sockindex;
+ return false;
+}
#define pre_receive_plain(c,n) do {} WHILE_FALSE
#define get_pre_recved(c,n,b,l) 0
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
@@ -488,7 +501,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;
@@ -571,7 +584,7 @@ CURLcode Curl_client_chop_write(struct connectdata *conn,
return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
if(wrote != chunklen) {
- failf (data, "Failed writing header");
+ failf(data, "Failed writing header");
return CURLE_WRITE_ERROR;
}
}
@@ -692,7 +705,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
}
/* If we come here, it means that there is no data to read from the buffer,
* so we read from the socket */
- bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char));
+ bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof(char));
buffertofill = conn->master_buffer;
}
else {
@@ -796,7 +809,7 @@ int Curl_debug(struct Curl_easy *data, curl_infotype type,
char buffer[160];
const char *t=NULL;
const char *w="Data";
- switch (type) {
+ switch(type) {
case CURLINFO_HEADER_IN:
w = "Header";
/* FALLTHROUGH */
diff --git a/Utilities/cmcurl/lib/sendf.h b/Utilities/cmcurl/lib/sendf.h
index a951a0b..fbe4f99 100644
--- a/Utilities/cmcurl/lib/sendf.h
+++ b/Utilities/cmcurl/lib/sendf.h
@@ -56,6 +56,8 @@ CURLcode Curl_client_chop_write(struct connectdata *conn, int type, char *ptr,
CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
size_t len) WARN_UNUSED_RESULT;
+bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex);
+
/* internal read-function, does plain socket only */
CURLcode Curl_read_plain(curl_socket_t sockfd,
char *buf,
diff --git a/Utilities/cmcurl/lib/setup-os400.h b/Utilities/cmcurl/lib/setup-os400.h
index e32b72f..a3c2a7b 100644
--- a/Utilities/cmcurl/lib/setup-os400.h
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/setup-vms.h b/Utilities/cmcurl/lib/setup-vms.h
index 4b78e0b..6c454ae 100644
--- a/Utilities/cmcurl/lib/setup-vms.h
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/share.h b/Utilities/cmcurl/lib/share.h
index e689ff2..c039a16 100644
--- a/Utilities/cmcurl/lib/share.h
+++ b/Utilities/cmcurl/lib/share.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
@@ -54,8 +54,8 @@ struct Curl_share {
long sessionage;
};
-CURLSHcode Curl_share_lock (struct Curl_easy *, curl_lock_data,
- curl_lock_access);
-CURLSHcode Curl_share_unlock (struct Curl_easy *, curl_lock_data);
+CURLSHcode Curl_share_lock(struct Curl_easy *, curl_lock_data,
+ curl_lock_access);
+CURLSHcode Curl_share_unlock(struct Curl_easy *, curl_lock_data);
#endif /* HEADER_CURL_SHARE_H */
diff --git a/Utilities/cmcurl/lib/smb.c b/Utilities/cmcurl/lib/smb.c
index 7cb0c96..f197fe1 100644
--- a/Utilities/cmcurl/lib/smb.c
+++ b/Utilities/cmcurl/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;
}
@@ -781,9 +781,9 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
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) {
if(off + sizeof(unsigned int) + len > smbc->got) {
@@ -812,7 +812,7 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
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/Utilities/cmcurl/lib/smtp.c b/Utilities/cmcurl/lib/smtp.c
index a4fc2c2..ff8e80d 100644
--- a/Utilities/cmcurl/lib/smtp.c
+++ b/Utilities/cmcurl/lib/smtp.c
@@ -103,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.
@@ -278,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++)
diff --git a/Utilities/cmcurl/lib/socks.c b/Utilities/cmcurl/lib/socks.c
index 742d411..774fb20 100644
--- a/Utilities/cmcurl/lib/socks.c
+++ b/Utilities/cmcurl/lib/socks.c
@@ -57,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);
@@ -109,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 */
@@ -126,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);
@@ -174,11 +179,11 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
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];
+ 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);
}
@@ -219,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) {
@@ -230,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 */
}
@@ -376,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 "
@@ -605,9 +615,9 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
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];
+ socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i];
}
infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", buf);
@@ -617,9 +627,10 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
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);
diff --git a/Utilities/cmcurl/lib/socks.h b/Utilities/cmcurl/lib/socks.h
index a44ada6..348707e 100644
--- a/Utilities/cmcurl/lib/socks.h
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/socks_gssapi.c b/Utilities/cmcurl/lib/socks_gssapi.c
index 369245a..54d0635 100644
--- a/Utilities/cmcurl/lib/socks_gssapi.c
+++ b/Utilities/cmcurl/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);
@@ -290,9 +292,9 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
gss_release_name(&gss_status, &server);
/* Everything is good so far, user was authenticated! */
- gss_major_status = gss_inquire_context (&gss_minor_status, gss_context,
- &gss_client_name, NULL, NULL, NULL,
- NULL, NULL, NULL);
+ gss_major_status = gss_inquire_context(&gss_minor_status, gss_context,
+ &gss_client_name, NULL, NULL, NULL,
+ NULL, NULL, NULL);
if(check_gss_err(data, gss_major_status,
gss_minor_status, "gss_inquire_context")) {
gss_delete_sec_context(&gss_status, &gss_context, NULL);
diff --git a/Utilities/cmcurl/lib/socks_sspi.c b/Utilities/cmcurl/lib/socks_sspi.c
index 6053490..edc73ad 100644
--- a/Utilities/cmcurl/lib/socks_sspi.c
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/speedcheck.c b/Utilities/cmcurl/lib/speedcheck.c
index 13c34af..bc15d97 100644
--- a/Utilities/cmcurl/lib/speedcheck.c
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/ssh.c b/Utilities/cmcurl/lib/ssh.c
index 43c8283..5ed036a 100644
--- a/Utilities/cmcurl/lib/ssh.c
+++ b/Utilities/cmcurl/lib/ssh.c
@@ -71,7 +71,7 @@
#include "url.h"
#include "speedcheck.h"
#include "getinfo.h"
-
+#include "strdup.h"
#include "strcase.h"
#include "vtls/vtls.h"
#include "connect.h"
@@ -239,7 +239,7 @@ kbd_callback(const char *name, int name_len, const char *instruction,
static CURLcode sftp_libssh2_error_to_CURLE(int err)
{
- switch (err) {
+ switch(err) {
case LIBSSH2_FX_OK:
return CURLE_OK;
@@ -271,7 +271,7 @@ static CURLcode sftp_libssh2_error_to_CURLE(int err)
static CURLcode libssh2_session_error_to_CURLE(int err)
{
- switch (err) {
+ switch(err) {
/* Ordered by order of appearance in libssh2.h */
case LIBSSH2_ERROR_NONE:
return CURLE_OK;
@@ -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 || strcmp(md5buffer, pubkey_md5)) {
+ if(!fingerprint || !strcasecompare(md5buffer, pubkey_md5)) {
if(fingerprint)
failf(data,
"Denied establishing ssh session: mismatch md5 fingerprint. "
@@ -782,14 +782,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_AUTH_DONE);
break;
}
- else if((err = libssh2_session_last_errno(sshc->ssh_session)) ==
- LIBSSH2_ERROR_EAGAIN) {
- rc = LIBSSH2_ERROR_EAGAIN;
- break;
- }
else {
- state(conn, SSH_SESSION_FREE);
- sshc->actualcode = libssh2_session_error_to_CURLE(err);
+ err = libssh2_session_last_errno(sshc->ssh_session);
+ if(err == LIBSSH2_ERROR_EAGAIN)
+ rc = LIBSSH2_ERROR_EAGAIN;
+ else {
+ state(conn, SSH_SESSION_FREE);
+ sshc->actualcode = libssh2_session_error_to_CURLE(err);
+ }
break;
}
}
@@ -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 = "";
@@ -1987,12 +1987,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
}
- if((sshc->readdir_filename = malloc(PATH_MAX+1)) == NULL) {
+ sshc->readdir_filename = malloc(PATH_MAX+1);
+ if(!sshc->readdir_filename) {
state(conn, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- if((sshc->readdir_longentry = malloc(PATH_MAX+1)) == NULL) {
+ sshc->readdir_longentry = malloc(PATH_MAX+1);
+ if(!sshc->readdir_longentry) {
Curl_safefree(sshc->readdir_filename);
state(conn, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
@@ -2112,9 +2114,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);
@@ -2651,7 +2654,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
else if(rc < 0) {
infof(data, "Failed to disconnect from libssh2 agent\n");
}
- libssh2_agent_free (sshc->ssh_agent);
+ libssh2_agent_free(sshc->ssh_agent);
sshc->ssh_agent = NULL;
/* NB: there is no need to free identities, they are part of internal
@@ -2788,13 +2791,16 @@ static int ssh_getsock(struct connectdata *conn,
static void ssh_block2waitfor(struct connectdata *conn, bool block)
{
struct ssh_conn *sshc = &conn->proto.sshc;
- int dir;
- if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) {
- /* translate the libssh2 define bits into our own bit defines */
- conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
- ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
+ int dir = 0;
+ if(block) {
+ dir = libssh2_session_block_directions(sshc->ssh_session);
+ if(dir) {
+ /* translate the libssh2 define bits into our own bit defines */
+ conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
+ ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
+ }
}
- else
+ if(!dir)
/* It didn't block or libssh2 didn't reveal in which direction, put back
the original set */
conn->waitfor = sshc->orig_waitfor;
@@ -2860,8 +2866,8 @@ 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_check(fd_read, CURL_SOCKET_BAD, fd_write,
- left>1000?1000:left); /* ignore result */
+ (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
+ left>1000?1000:left); /* ignore result */
}
#endif
@@ -3383,7 +3389,7 @@ get_pathname(const char **cpp, char **path)
static const char *sftp_libssh2_strerror(int err)
{
- switch (err) {
+ switch(err) {
case LIBSSH2_FX_NO_SUCH_FILE:
return "No such file or directory";
diff --git a/Utilities/cmcurl/lib/strcase.c b/Utilities/cmcurl/lib/strcase.c
index 807689e..a750f7b 100644
--- a/Utilities/cmcurl/lib/strcase.c
+++ b/Utilities/cmcurl/lib/strcase.c
@@ -34,7 +34,7 @@ char Curl_raw_toupper(char in)
if(in >= 'a' && in <= 'z')
return (char)('A' + in - 'a');
#else
- switch (in) {
+ switch(in) {
case 'a':
return 'A';
case 'b':
@@ -120,6 +120,16 @@ int Curl_strcasecompare(const char *first, const char *second)
return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
}
+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
*/
diff --git a/Utilities/cmcurl/lib/strcase.h b/Utilities/cmcurl/lib/strcase.h
index bf057b1..ea2abc8 100644
--- a/Utilities/cmcurl/lib/strcase.h
+++ b/Utilities/cmcurl/lib/strcase.h
@@ -36,6 +36,7 @@
#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);
diff --git a/Utilities/cmcurl/lib/strdup.c b/Utilities/cmcurl/lib/strdup.c
index 5a15c2b..136b693 100644
--- a/Utilities/cmcurl/lib/strdup.c
+++ b/Utilities/cmcurl/lib/strdup.c
@@ -75,3 +75,26 @@ void *Curl_memdup(const void *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/Utilities/cmcurl/lib/strdup.h b/Utilities/cmcurl/lib/strdup.h
index c74a3b7..ae3d5d0 100644
--- a/Utilities/cmcurl/lib/strdup.h
+++ b/Utilities/cmcurl/lib/strdup.h
@@ -27,5 +27,6 @@
extern char *curlx_strdup(const char *str);
#endif
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/Utilities/cmcurl/lib/strerror.c b/Utilities/cmcurl/lib/strerror.c
index db50c7d..7e5cde4 100644
--- a/Utilities/cmcurl/lib/strerror.c
+++ b/Utilities/cmcurl/lib/strerror.c
@@ -53,7 +53,7 @@ const char *
curl_easy_strerror(CURLcode error)
{
#ifndef CURL_DISABLE_VERBOSE_STRINGS
- switch (error) {
+ switch(error) {
case CURLE_OK:
return "No error";
@@ -348,7 +348,7 @@ const char *
curl_multi_strerror(CURLMcode error)
{
#ifndef CURL_DISABLE_VERBOSE_STRINGS
- switch (error) {
+ switch(error) {
case CURLM_CALL_MULTI_PERFORM:
return "Please call curl_multi_perform() soon";
@@ -393,7 +393,7 @@ const char *
curl_share_strerror(CURLSHcode error)
{
#ifndef CURL_DISABLE_VERBOSE_STRINGS
- switch (error) {
+ switch(error) {
case CURLSHE_OK:
return "No error";
@@ -435,7 +435,7 @@ get_winsock_error (int err, char *buf, size_t len)
const char *p;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
- switch (err) {
+ switch(err) {
case WSAEINTR:
p = "Call interrupted";
break;
@@ -609,7 +609,7 @@ get_winsock_error (int err, char *buf, size_t len)
else
p = "error";
#endif
- strncpy (buf, p, len);
+ strncpy(buf, p, len);
buf [len-1] = '\0';
return buf;
}
@@ -715,10 +715,12 @@ const char *Curl_strerror(struct connectdata *conn, int err)
buf[max] = '\0'; /* make sure the string is zero terminated */
/* strip trailing '\r\n' or '\n'. */
- if((p = strrchr(buf, '\n')) != NULL && (p - buf) >= 2)
- *p = '\0';
- if((p = strrchr(buf, '\r')) != NULL && (p - buf) >= 1)
- *p = '\0';
+ p = strrchr(buf, '\n');
+ if(p && (p - buf) >= 2)
+ *p = '\0';
+ p = strrchr(buf, '\r');
+ if(p && (p - buf) >= 1)
+ *p = '\0';
if(old_errno != ERRNO)
SET_ERRNO(old_errno);
@@ -750,7 +752,7 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err)
old_errno = ERRNO;
- switch (err) {
+ switch(err) {
case SEC_E_OK:
txt = "No error";
break;
@@ -1035,10 +1037,12 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err)
if(msg_formatted) {
msgbuf[sizeof(msgbuf)-1] = '\0';
/* strip trailing '\r\n' or '\n' */
- if((p = strrchr(msgbuf, '\n')) != NULL && (p - msgbuf) >= 2)
- *p = '\0';
- if((p = strrchr(msgbuf, '\r')) != NULL && (p - msgbuf) >= 1)
- *p = '\0';
+ p = strrchr(msgbuf, '\n');
+ if(p && (p - msgbuf) >= 2)
+ *p = '\0';
+ p = strrchr(msgbuf, '\r');
+ if(p && (p - msgbuf) >= 1)
+ *p = '\0';
msg = msgbuf;
}
if(msg)
diff --git a/Utilities/cmcurl/lib/strtoofft.c b/Utilities/cmcurl/lib/strtoofft.c
index 6d5d2d5..b854bf4 100644
--- a/Utilities/cmcurl/lib/strtoofft.c
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/telnet.c b/Utilities/cmcurl/lib/telnet.c
index c37242d..551af60 100644
--- a/Utilities/cmcurl/lib/telnet.c
+++ b/Utilities/cmcurl/lib/telnet.c
@@ -91,7 +91,7 @@
#ifdef USE_WINSOCK
typedef FARPROC WSOCK2_FUNC;
-static CURLcode check_wsock2 (struct Curl_easy *data);
+static CURLcode check_wsock2(struct Curl_easy *data);
#endif
static
@@ -935,7 +935,7 @@ static void suboption(struct connectdata *conn)
struct TELNET *tn = (struct TELNET *)data->req.protop;
printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2);
- switch (CURL_SB_GET(tn)) {
+ switch(CURL_SB_GET(tn)) {
case CURL_TELOPT_TTYPE:
len = strlen(tn->subopt_ttype) + 4 + 2;
snprintf((char *)temp, sizeof(temp),
@@ -1004,12 +1004,12 @@ 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;
- switch (option) {
+ switch(option) {
case CURL_TELOPT_NAWS:
/* We prepare data to be sent */
CURL_SB_CLEAR(tn);
@@ -1020,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]);
@@ -1087,7 +1087,7 @@ CURLcode telrcv(struct connectdata *conn,
while(count--) {
c = inbuf[in];
- switch (tn->telrcv_state) {
+ switch(tn->telrcv_state) {
case CURL_TS_CR:
tn->telrcv_state = CURL_TS_DATA;
if(c == '\0') {
@@ -1111,7 +1111,7 @@ CURLcode telrcv(struct connectdata *conn,
case CURL_TS_IAC:
process_iac:
DEBUGASSERT(startwrite < 0);
- switch (c) {
+ switch(c) {
case CURL_WILL:
tn->telrcv_state = CURL_TS_WILL;
break;
@@ -1241,7 +1241,7 @@ static CURLcode send_telnet_data(struct connectdata *conn,
struct pollfd pfd[1];
pfd[0].fd = conn->sock[FIRSTSOCKET];
pfd[0].events = POLLOUT;
- switch (Curl_poll(pfd, 1, -1)) {
+ switch(Curl_poll(pfd, 1, -1)) {
case -1: /* error, abort writing */
case 0: /* timeout (will never happen) */
result = CURLE_SEND_ERROR;
@@ -1489,7 +1489,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
events.lNetworkEvents = 0;
if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) {
- if((err = SOCKERRNO) != EINPROGRESS) {
+ err = SOCKERRNO;
+ if(err != EINPROGRESS) {
infof(data, "WSAEnumNetworkEvents failed (%d)", err);
keepon = FALSE;
result = CURLE_READ_ERROR;
@@ -1576,7 +1577,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
}
while(keepon) {
- switch (Curl_poll(pfd, poll_cnt, interval_ms)) {
+ switch(Curl_poll(pfd, poll_cnt, interval_ms)) {
case -1: /* error, stop reading */
keepon = FALSE;
continue;
diff --git a/Utilities/cmcurl/lib/tftp.c b/Utilities/cmcurl/lib/tftp.c
index deee394..f2f8347 100644
--- a/Utilities/cmcurl/lib/tftp.c
+++ b/Utilities/cmcurl/lib/tftp.c
@@ -199,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);
@@ -304,7 +304,7 @@ static unsigned short getrpacketblock(const tftp_packet_t *packet)
static size_t Curl_strnlen(const char *string, size_t maxlen)
{
- const char *end = memchr (string, '\0', maxlen);
+ const char *end = memchr(string, '\0', maxlen);
return end ? (size_t) (end - string) : maxlen;
}
@@ -1356,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 */
@@ -1372,7 +1372,7 @@ static CURLcode tftp_setup_connection(struct connectdata * conn)
*type = 0; /* it was in the middle of the hostname */
command = Curl_raw_toupper(type[6]);
- switch (command) {
+ switch(command) {
case 'A': /* ASCII mode */
case 'N': /* NETASCII mode */
data->set.prefer_ascii = TRUE;
diff --git a/Utilities/cmcurl/lib/timeval.c b/Utilities/cmcurl/lib/timeval.c
index 629f1c8..f3b207a 100644
--- a/Utilities/cmcurl/lib/timeval.c
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/timeval.h b/Utilities/cmcurl/lib/timeval.h
index 50c31a2..09f8b3a 100644
--- a/Utilities/cmcurl/lib/timeval.h
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/transfer.c b/Utilities/cmcurl/lib/transfer.c
index 6245ee4..750fb04 100644
--- a/Utilities/cmcurl/lib/transfer.c
+++ b/Utilities/cmcurl/lib/transfer.c
@@ -741,8 +741,8 @@ static CURLcode readwrite_data(struct Curl_easy *data,
Make sure that ALL_CONTENT_ENCODINGS contains all the
encodings handled here. */
#ifdef HAVE_LIBZ
- switch (conn->data->set.http_ce_skip ?
- IDENTITY : k->auto_decoding) {
+ switch(conn->data->set.http_ce_skip ?
+ IDENTITY : k->auto_decoding) {
case IDENTITY:
#endif
/* This is the default when the server sends no
@@ -775,9 +775,9 @@ static CURLcode readwrite_data(struct Curl_easy *data,
break;
default:
- failf (data, "Unrecognized content encoding type. "
- "libcurl understands `identity', `deflate' and `gzip' "
- "content encodings.");
+ failf(data, "Unrecognized content encoding type. "
+ "libcurl understands `identity', `deflate' and `gzip' "
+ "content encodings.");
result = CURLE_BAD_CONTENT_ENCODING;
break;
}
@@ -1137,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;
@@ -1296,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;
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c
index b997f41..7944d7b 100644
--- a/Utilities/cmcurl/lib/url.c
+++ b/Utilities/cmcurl/lib/url.c
@@ -92,6 +92,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "warnless.h"
#include "non-ascii.h"
#include "inet_pton.h"
+#include "getinfo.h"
/* And now for the protocols */
#include "ftp.h"
@@ -463,6 +464,7 @@ CURLcode Curl_close(struct Curl_easy *data)
/* this destroys the channel and we cannot use it anymore after this */
Curl_resolver_cleanup(data->state.resolver);
+ Curl_http2_cleanup_dependencies(data);
Curl_convert_close(data);
/* No longer a dirty share, if it exists */
@@ -525,9 +527,9 @@ 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->proxyport = 0;
set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
set->httpauth = CURLAUTH_BASIC; /* defaults to basic */
set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
@@ -539,14 +541,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 */
@@ -569,14 +573,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;
@@ -646,6 +653,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;
@@ -694,7 +703,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;
@@ -900,7 +914,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
@@ -1007,7 +1032,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);
@@ -1434,18 +1459,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_PRE_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_PRE_PROXY],
+ va_arg(param, char *));
+ break;
+
case CURLOPT_PROXYTYPE:
/*
* Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
@@ -1457,7 +1494,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
/*
* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
*/
- switch (va_arg(param, long)) {
+ switch(va_arg(param, long)) {
case 0:
data->set.proxy_transfer_mode = FALSE;
break;
@@ -1910,35 +1947,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:
@@ -2001,7 +2073,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:
/*
@@ -2019,7 +2099,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:
/*
@@ -2030,7 +2128,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
@@ -2076,7 +2175,19 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* Set pinned public key for SSL connection.
* Specify file name of the public key in DER format.
*/
- result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+ result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
+ va_arg(param, char *));
+#else
+ result = CURLE_NOT_BUILT_IN;
+#endif
+ break;
+ case CURLOPT_PROXY_PINNEDPUBLICKEY:
+#ifdef have_curlssl_pinnedpubkey /* only by supported backends */
+ /*
+ * Set pinned public key for SSL connection.
+ * Specify file name of the public key in DER format.
+ */
+ result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
va_arg(param, char *));
#else
result = CURLE_NOT_BUILT_IN;
@@ -2086,7 +2197,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:
@@ -2096,7 +2215,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;
@@ -2107,7 +2235,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:
@@ -2115,7 +2251,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:
@@ -2196,7 +2332,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);
@@ -2231,8 +2367,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
@@ -2328,7 +2470,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
@@ -2595,23 +2738,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(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 *));
@@ -2678,9 +2841,11 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
return CURLE_NOT_BUILT_IN;
#else
struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
- if(dep && GOOD_EASY_HANDLE(dep)) {
- data->set.stream_depends_on = dep;
- data->set.stream_depends_e = (option == CURLOPT_STREAM_DEPENDS_E);
+ if(!dep || GOOD_EASY_HANDLE(dep)) {
+ if(data->set.stream_depends_on) {
+ Curl_http2_remove_child(data->set.stream_depends_on, data);
+ }
+ Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E));
}
break;
#endif
@@ -2718,10 +2883,10 @@ static void conn_reset_postponed_data(struct connectdata *conn, int num)
#endif /* DEBUGBUILD */
}
else {
- DEBUGASSERT (psnd->allocated_size == 0);
- DEBUGASSERT (psnd->recv_size == 0);
- DEBUGASSERT (psnd->recv_processed == 0);
- DEBUGASSERT (psnd->bindsock == CURL_SOCKET_BAD);
+ DEBUGASSERT(psnd->allocated_size == 0);
+ DEBUGASSERT(psnd->recv_size == 0);
+ DEBUGASSERT(psnd->recv_processed == 0);
+ DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD);
}
}
@@ -2768,8 +2933,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);
@@ -2783,7 +2950,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);
@@ -2795,7 +2964,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 */
}
@@ -2856,6 +3030,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);
@@ -3014,8 +3190,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;
@@ -3052,6 +3228,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.
@@ -3064,8 +3255,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;
@@ -3147,7 +3338,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,
@@ -3326,6 +3517,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 */
@@ -3334,23 +3536,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 ||
- !strcasecompare(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)
@@ -3363,6 +3554,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 */
@@ -3382,9 +3600,8 @@ 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;
}
@@ -3399,10 +3616,11 @@ ConnectionExists(struct Curl_easy *data,
}
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 */
+ 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)) &&
@@ -3463,12 +3681,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(strcmp(needle->proxyuser, check->proxyuser) ||
- strcmp(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) {
@@ -3572,51 +3791,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;
}
/*
@@ -3627,7 +3843,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
@@ -3717,10 +3935,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
@@ -3750,7 +3972,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)
@@ -3879,12 +4101,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 = CURLPROXY_SOCKS4;
#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;
@@ -3895,11 +4119,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_PRE_PROXY] && *data->set.str[STRING_PRE_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 */
@@ -3908,8 +4141,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;
@@ -3924,7 +4159,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
!conn->master_buffer) {
/* Allocate master_buffer to be used for HTTP/1 pipelining */
- conn->master_buffer = calloc(BUFSIZE, sizeof (char));
+ conn->master_buffer = calloc(BUFSIZE, sizeof(char));
if(!conn->master_buffer)
goto error;
}
@@ -4065,33 +4300,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 */
@@ -4473,7 +4713,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
@@ -4482,7 +4722,7 @@ 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;
@@ -4636,7 +4876,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;
@@ -4645,6 +4886,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
@@ -4654,14 +4899,16 @@ 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;
+ proxytype = CURLPROXY_SOCKS4;
else if(checkprefix("http:", proxy))
; /* leave it as HTTP or HTTP/1.0 */
else {
@@ -4673,54 +4920,28 @@ static CURLcode parse_proxy(struct Curl_easy *data,
else
proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
+#ifndef HTTPS_PROXY_SUPPORT
+ if(proxytype == CURLPROXY_HTTPS) {
+ failf(data, "Unsupported proxy \'%s\'"
+ ", libcurl is built without the HTTPS-proxy support.", proxy);
+ return CURLE_NOT_BUILT_IN;
+ }
+#endif
+
+ 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)
- result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL,
- FALSE);
- else {
- conn->proxyuser = strdup("");
- if(!conn->proxyuser)
- result = CURLE_OUT_OF_MEMORY;
- }
-
- if(!result) {
- Curl_safefree(conn->proxypasswd);
- if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
- result = Curl_urldecode(data, proxypasswd, 0,
- &conn->proxypasswd, NULL, FALSE);
- 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 */
@@ -4757,7 +4978,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 */
@@ -4791,15 +5012,59 @@ 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;
+ else {
+ if(proxytype == CURLPROXY_HTTPS)
+ port = CURL_DEFAULT_HTTPS_PROXY_PORT;
+ else
+ port = CURL_DEFAULT_PROXY_PORT;
+ }
}
- /* 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;
}
@@ -4825,10 +5090,11 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
}
- result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL, FALSE);
+ result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
+ FALSE);
if(!result)
- result = Curl_urldecode(data, proxypasswd, 0, &conn->proxypasswd, NULL,
- FALSE);
+ result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
+ NULL, FALSE);
return result;
}
#endif /* CURL_DISABLE_PROXY */
@@ -5180,11 +5446,16 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
*portptr = '\0'; /* cut off the name there */
conn->remote_port = curlx_ultous(port);
}
- else
+ else {
+ if(rest[0]) {
+ failf(data, "Illegal port number");
+ return CURLE_URL_MALFORMAT;
+ }
/* Browser behavior adaptation. If there's a colon with no digits after,
just cut off the name there which makes us ignore the colon and just
use the default port. Firefox and Chrome both do that. */
*portptr = '\0';
+ }
}
/* only if remote_port was not already parsed off the URL we use the
@@ -5404,6 +5675,9 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data,
int host_match = FALSE;
int port_match = FALSE;
+ *host_result = NULL;
+ *port_result = -1;
+
if(*ptr == ':') {
/* an empty hostname always matches */
host_match = TRUE;
@@ -5466,9 +5740,9 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
{
CURLcode result = CURLE_OK;
char *host = NULL;
- int port = 0;
+ int port = -1;
- while(conn_to_host && !host) {
+ while(conn_to_host && !host && port == -1) {
result = parse_connect_to_string(data, conn, conn_to_host->data,
&host, &port);
if(result)
@@ -5487,7 +5761,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
else {
/* no "connect to host" */
conn->bits.conn_to_host = FALSE;
- free(host);
+ Curl_safefree(host);
}
if(port >= 0) {
@@ -5498,6 +5772,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
else {
/* no "connect to port" */
conn->bits.conn_to_port = FALSE;
+ port = -1;
}
conn_to_host = conn_to_host->next;
@@ -5514,7 +5789,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
@@ -5531,32 +5806,36 @@ 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)
result = CURLE_OUT_OF_MEMORY;
- else if((hostaddr->addr = Curl_unix2addr(path)) != NULL)
- hostaddr->inuse++;
else {
- /* Long paths are not supported for now */
- if(strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) {
- failf(data, "Unix socket path too long: '%s'", path);
- result = CURLE_COULDNT_RESOLVE_HOST;
+ int longpath=0;
+ hostaddr->addr = Curl_unix2addr(path, &longpath);
+ if(hostaddr->addr)
+ hostaddr->inuse++;
+ else {
+ /* Long paths are not supported for now */
+ if(longpath) {
+ failf(data, "Unix socket path too long: '%s'", path);
+ result = CURLE_COULDNT_RESOLVE_HOST;
+ }
+ else
+ result = CURLE_OUT_OF_MEMORY;
+ free(hostaddr);
+ hostaddr = NULL;
}
- else
- result = CURLE_OUT_OF_MEMORY;
- free(hostaddr);
- hostaddr = NULL;
}
}
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;
@@ -5588,8 +5867,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)
@@ -5599,7 +5881,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 */
}
@@ -5619,12 +5901,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;
@@ -5644,12 +5932,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
@@ -5675,8 +5969,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);
@@ -5686,6 +5982,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
}
/**
@@ -5717,6 +6017,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;
@@ -5883,18 +6184,35 @@ static CURLcode create_conn(struct Curl_easy *data,
}
}
+ if(data->set.str[STRING_PRE_PROXY]) {
+ socksproxy = strdup(data->set.str[STRING_PRE_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
@@ -5903,23 +6221,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;
@@ -5938,12 +6269,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;
}
@@ -6079,20 +6432,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;
}
@@ -6149,7 +6533,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
@@ -6280,6 +6666,7 @@ static CURLcode create_conn(struct Curl_easy *data,
free(options);
free(passwd);
free(user);
+ free(socksproxy);
free(proxy);
return result;
}
diff --git a/Utilities/cmcurl/lib/url.h b/Utilities/cmcurl/lib/url.h
index 90d9db3..f13c8e6 100644
--- a/Utilities/cmcurl/lib/url.h
+++ b/Utilities/cmcurl/lib/url.h
@@ -67,6 +67,8 @@ void Curl_getoff_all_pipelines(struct Curl_easy *data,
void Curl_close_connections(struct Curl_easy *data);
#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
+#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless
+ specified */
CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex);
@@ -76,5 +78,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/Utilities/cmcurl/lib/urldata.h b/Utilities/cmcurl/lib/urldata.h
index 7c7bf1b..0271d26 100644
--- a/Utilities/cmcurl/lib/urldata.h
+++ b/Utilities/cmcurl/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;
@@ -341,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) */
@@ -370,6 +382,11 @@ 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 */
@@ -380,7 +397,7 @@ struct curl_ssl_session {
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 */
@@ -451,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
};
@@ -497,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
@@ -531,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
@@ -547,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 {
@@ -732,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 *);
@@ -849,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.
@@ -898,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
@@ -930,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 */
@@ -951,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 */
@@ -962,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 */
@@ -1020,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?? */
@@ -1041,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
@@ -1078,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
@@ -1099,13 +1130,17 @@ 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 reset in Curl_initinfo().
+ * All variables in this struct must be initialized/reset in Curl_initinfo().
*/
struct PureInfo {
int httpcode; /* Recent HTTP, FTP, RTSP or SMTP response code */
@@ -1139,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 */
@@ -1146,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 */
@@ -1242,6 +1280,11 @@ struct auth {
be RFC compliant */
};
+struct Curl_http2_dep {
+ struct Curl_http2_dep *next;
+ struct Curl_easy *data;
+};
+
struct UrlState {
/* Points to the connection cache */
@@ -1402,8 +1445,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 */
@@ -1413,25 +1458,35 @@ 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_PRE_PROXY, /* pre 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_PINNEDPUBLICKEY, /* public key file to verify peer against */
- STRING_SSL_CIPHER_LIST, /* list of ciphers to use */
+ 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_ORIG, /* public key file to verify peer against */
+ STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */
+ 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 */
@@ -1459,8 +1514,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
@@ -1524,10 +1581,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 */
@@ -1578,7 +1635,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 */
@@ -1642,9 +1702,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) */
@@ -1695,6 +1752,8 @@ struct UserDefined {
struct Curl_easy *stream_depends_on;
bool stream_depends_e; /* set or don't set the Exclusive bit */
int stream_weight;
+
+ struct Curl_http2_dep *stream_dependents;
};
struct Names {
diff --git a/Utilities/cmcurl/lib/vauth/cleartext.c b/Utilities/cmcurl/lib/vauth/cleartext.c
index 6df419a..a761ae7 100644
--- a/Utilities/cmcurl/lib/vauth/cleartext.c
+++ b/Utilities/cmcurl/lib/vauth/cleartext.c
@@ -66,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);
@@ -85,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/Utilities/cmcurl/lib/vauth/digest.c b/Utilities/cmcurl/lib/vauth/digest.c
index 0a11a30..7d9200a 100644
--- a/Utilities/cmcurl/lib/vauth/digest.c
+++ b/Utilities/cmcurl/lib/vauth/digest.c
@@ -40,6 +40,7 @@
#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; \
@@ -387,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",
@@ -684,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);
diff --git a/Utilities/cmcurl/lib/vauth/digest_sspi.c b/Utilities/cmcurl/lib/vauth/digest_sspi.c
index 29526fc..b9ceb12 100644
--- a/Utilities/cmcurl/lib/vauth/digest_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/digest_sspi.c
@@ -414,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/Utilities/cmcurl/lib/vauth/ntlm.c b/Utilities/cmcurl/lib/vauth/ntlm.c
index b484a01..b4d345d 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.c
+++ b/Utilities/cmcurl/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
@@ -558,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)
@@ -598,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/Utilities/cmcurl/lib/vauth/spnego_sspi.c b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
index 672b43f..5fa95e2 100644
--- a/Utilities/cmcurl/lib/vauth/spnego_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
@@ -264,7 +264,7 @@ 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);
diff --git a/Utilities/cmcurl/lib/version.c b/Utilities/cmcurl/lib/version.c
index a434a62..3d17768 100644
--- a/Utilities/cmcurl/lib/version.c
+++ b/Utilities/cmcurl/lib/version.c
@@ -324,6 +324,9 @@ static curl_version_info_data version_info = {
#if defined(USE_LIBPSL)
| CURL_VERSION_PSL
#endif
+#if defined(HTTPS_PROXY_SUPPORT)
+ | CURL_VERSION_HTTPS_PROXY
+#endif
,
NULL, /* ssl_version */
0, /* ssl_version_num, this is kept at zero */
diff --git a/Utilities/cmcurl/lib/vtls/axtls.c b/Utilities/cmcurl/lib/vtls/axtls.c
index 85b8bc4..ff4634e 100644
--- a/Utilities/cmcurl/lib/vtls/axtls.c
+++ b/Utilities/cmcurl/lib/vtls/axtls.c
@@ -65,7 +65,7 @@ int Curl_axtls_cleanup(void)
static CURLcode map_error_to_curl(int axtls_err)
{
- switch (axtls_err) {
+ switch(axtls_err) {
case SSL_ERROR_NOT_SUPPORTED:
case SSL_ERROR_INVALID_VERSION:
case -70: /* protocol version alert from server */
@@ -121,7 +121,7 @@ static Curl_send axtls_send;
static void free_ssl_structs(struct ssl_connect_data *connssl)
{
if(connssl->ssl) {
- ssl_free (connssl->ssl);
+ ssl_free(connssl->ssl);
connssl->ssl = NULL;
}
if(connssl->ssl_ctx) {
@@ -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,15 +256,16 @@ 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");
+ infof(data, "SSL re-using session ID\n");
ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
ssl_sessionid, (uint8_t)ssl_idsize);
}
@@ -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,13 +386,13 @@ 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)
- infof (data, "failed to add session to cache\n");
+ 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);
}
@@ -437,7 +440,7 @@ CURLcode Curl_axtls_connect_nonblocking(
return CURLE_OK;
}
}
- infof (conn->data, "handshake completed successfully\n");
+ infof(conn->data, "handshake completed successfully\n");
conn->ssl[sockindex].connecting_state = ssl_connect_3;
}
@@ -503,7 +506,7 @@ Curl_axtls_connect(struct connectdata *conn,
/* TODO: avoid polling */
Curl_wait_ms(10);
}
- infof (conn->data, "handshake completed successfully\n");
+ infof(conn->data, "handshake completed successfully\n");
conn_step = connect_finish(conn, sockindex);
if(conn_step != CURLE_OK) {
diff --git a/Utilities/cmcurl/lib/vtls/cyassl.c b/Utilities/cmcurl/lib/vtls/cyassl.c
index 5d6dbfb..fc4dde4 100644
--- a/Utilities/cmcurl/lib/vtls/cyassl.c
+++ b/Utilities/cmcurl/lib/vtls/cyassl.c
@@ -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);
@@ -391,7 +397,7 @@ cyassl_connect_step1(struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
/* Informational message */
- infof (data, "SSL re-using session ID\n");
+ infof(data, "SSL re-using session ID\n");
}
Curl_ssl_sessionid_unlock(conn);
}
@@ -414,13 +420,20 @@ 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;
+ const char * const pinnedpubkey = SSL_IS_PROXY() ?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
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 +457,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;
}
@@ -487,7 +500,7 @@ cyassl_connect_step2(struct connectdata *conn,
}
}
- if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+ if(pinnedpubkey) {
#ifdef KEEP_PEER_CERT
X509 *x509;
const char *x509_der;
@@ -509,7 +522,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) {
@@ -518,7 +532,7 @@ cyassl_connect_step2(struct connectdata *conn,
}
result = Curl_pin_peer_pubkey(data,
- data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+ pinnedpubkey,
(const unsigned char *)pubkey->header,
(size_t)(pubkey->end - pubkey->header));
if(result) {
@@ -583,7 +597,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 +605,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 +617,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");
@@ -654,11 +669,11 @@ void Curl_cyassl_close(struct connectdata *conn, int sockindex)
if(conssl->handle) {
(void)SSL_shutdown(conssl->handle);
- SSL_free (conssl->handle);
+ SSL_free(conssl->handle);
conssl->handle = NULL;
}
if(conssl->ctx) {
- SSL_CTX_free (conssl->ctx);
+ SSL_CTX_free(conssl->ctx);
conssl->ctx = NULL;
}
}
@@ -740,7 +755,7 @@ int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex)
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
if(connssl->handle) {
- SSL_free (connssl->handle);
+ SSL_free(connssl->handle);
connssl->handle = NULL;
}
return retval;
diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.c b/Utilities/cmcurl/lib/vtls/darwinssl.c
index 66e74f1..a43e391 100644
--- a/Utilities/cmcurl/lib/vtls/darwinssl.c
+++ b/Utilities/cmcurl/lib/vtls/darwinssl.c
@@ -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,8 +219,9 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
return ortn;
}
-CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) {
- switch (cipher) {
+CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher)
+{
+ switch(cipher) {
/* SSL version 3.0 */
case SSL_RSA_WITH_NULL_MD5:
return "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,21 +906,53 @@ 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
@@ -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]) {
@@ -1474,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);
@@ -1504,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);
@@ -1516,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");
@@ -1820,7 +1879,7 @@ static int verify_cert(const char *cafile, struct Curl_easy *data,
return sslerr_to_curlerr(data, ret);
}
- switch (trust_eval) {
+ switch(trust_eval) {
case kSecTrustResultUnspecified:
case kSecTrustResultProceed:
return CURLE_OK;
@@ -1842,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
@@ -1851,7 +1912,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
err = SSLHandshake(connssl->ssl_ctx);
if(err != noErr) {
- switch (err) {
+ switch(err) {
case errSSLWouldBlock: /* they're not done with us yet */
connssl->connecting_state = connssl->ssl_direction ?
ssl_connect_2_writing : ssl_connect_2_reading;
@@ -1860,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;
@@ -1930,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;
}
}
@@ -1941,7 +2002,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
/* Informational message */
(void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher);
(void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol);
- switch (protocol) {
+ switch(protocol) {
case kSSLProtocol2:
infof(data, "SSL 2.0 connection using %s\n",
SSLCipherNameForNumber(cipher));
@@ -2390,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;
@@ -2427,7 +2489,7 @@ static ssize_t darwinssl_send(struct connectdata *conn,
if(connssl->ssl_write_buffered_length) {
/* Write the buffered data: */
err = SSLWrite(connssl->ssl_ctx, NULL, 0UL, &processed);
- switch (err) {
+ switch(err) {
case noErr:
/* processed is always going to be 0 because we didn't write to
the buffer, so return how much was written to the socket */
@@ -2447,7 +2509,7 @@ static ssize_t darwinssl_send(struct connectdata *conn,
/* We've got new data to write: */
err = SSLWrite(connssl->ssl_ctx, mem, len, &processed);
if(err != noErr) {
- switch (err) {
+ switch(err) {
case errSSLWouldBlock:
/* Data was buffered but not sent, we have to tell the caller
to try sending again, and remember how much was buffered */
@@ -2476,7 +2538,7 @@ static ssize_t darwinssl_recv(struct connectdata *conn,
OSStatus err = SSLRead(connssl->ssl_ctx, buf, buffersize, &processed);
if(err != noErr) {
- switch (err) {
+ switch(err) {
case errSSLWouldBlock: /* return how much we read (if anything) */
if(processed)
return (ssize_t)processed;
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index 3b0cfd5..a0d462b 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -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)
@@ -151,7 +155,7 @@ static const gskit_cipher ciphertable[] = {
static bool is_separator(char c)
{
/* Return whether character is a cipher list separator. */
- switch (c) {
+ switch(c) {
case ' ':
case '\t':
case ':':
@@ -167,7 +171,7 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc,
const char *procname, CURLcode defcode)
{
/* Process GSKit status and map it to a CURLcode. */
- switch (rc) {
+ switch(rc) {
case GSK_OK:
case GSK_OS400_ASYNCHRONOUS_SOC_INIT:
return CURLE_OK;
@@ -190,7 +194,7 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc,
case GSK_OS400_ERROR_NOT_REGISTERED:
break;
case GSK_ERROR_IO:
- switch (errno) {
+ switch(errno) {
case ENOMEM:
return CURLE_OUT_OF_MEMORY;
default:
@@ -211,7 +215,7 @@ static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
{
int rc = gsk_attribute_set_enum(h, id, value);
- switch (rc) {
+ switch(rc) {
case GSK_OK:
return CURLE_OK;
case GSK_ERROR_IO:
@@ -233,7 +237,7 @@ static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
{
int rc = gsk_attribute_set_buffer(h, id, buffer, 0);
- switch (rc) {
+ switch(rc) {
case GSK_OK:
return CURLE_OK;
case GSK_ERROR_IO:
@@ -255,7 +259,7 @@ static CURLcode set_numeric(struct Curl_easy *data,
{
int rc = gsk_attribute_set_numeric_value(h, id, value);
- switch (rc) {
+ switch(rc) {
case GSK_OK:
return CURLE_OK;
case GSK_ERROR_IO:
@@ -275,7 +279,7 @@ static CURLcode set_callback(struct Curl_easy *data,
{
int rc = gsk_attribute_set_callback(h, id, info);
- switch (rc) {
+ switch(rc) {
case GSK_OK:
return CURLE_OK;
case GSK_ERROR_IO:
@@ -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);
@@ -448,7 +453,7 @@ static CURLcode init_environment(struct Curl_easy *data,
/* Creates the GSKit environment. */
rc = gsk_environment_open(&h);
- switch (rc) {
+ switch(rc) {
case GSK_OK:
break;
case GSK_INSUFFICIENT_STORAGE:
@@ -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;
}
@@ -765,7 +996,7 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
timeout_ms = 0;
stmv.tv_sec = timeout_ms / 1000;
stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000;
- switch (QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
+ switch(QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
case 1: /* Operation complete. */
break;
case -1: /* An error occurred: handshake still in progress. */
@@ -822,7 +1053,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
infof(data, "Server certificate:\n");
p = cdev;
for(i = 0; i++ < cdec; p++)
- switch (p->cert_data_id) {
+ switch(p->cert_data_id) {
case CERT_BODY_DER:
cert = p->cert_data_p;
certend = cert + cdev->cert_data_l;
@@ -865,14 +1096,14 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
}
/* Check pinned public key. */
- ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+ ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
if(!result && ptr) {
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 +1144,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 +1163,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 +1217,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,7 +1237,7 @@ 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 = SOCKET_READABLE(conn->sock[sockindex],
SSL_SHUTDOWN_TIMEOUT);
diff --git a/Utilities/cmcurl/lib/vtls/gskit.h b/Utilities/cmcurl/lib/vtls/gskit.h
index 41483cb..2297592 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.h
+++ b/Utilities/cmcurl/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
@@ -41,6 +41,9 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex);
size_t Curl_gskit_version(char *buffer, size_t size);
int Curl_gskit_check_cxn(struct connectdata *cxn);
+/* Support HTTPS-proxy */
+/* TODO: add '#define HTTPS_PROXY_SUPPORT 1' and fix test #1014 (if need) */
+
/* Set the API backend definition to GSKit */
#define CURL_SSL_BACKEND CURLSSLBACKEND_GSKIT
@@ -64,7 +67,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/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index 5c87c7f..0e308cb 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -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
@@ -225,14 +235,15 @@ static void showtime(struct Curl_easy *data,
infof(data, "%s\n", data->state.buffer);
}
-static gnutls_datum_t load_file (const char *file)
+static gnutls_datum_t load_file(const char *file)
{
FILE *f;
gnutls_datum_t loaded_file = { NULL, 0 };
long filelen;
void *ptr;
- if(!(f = fopen(file, "rb")))
+ f = fopen(file, "rb");
+ if(!f)
return loaded_file;
if(fseek(f, 0, SEEK_END) != 0
|| (filelen = ftell(f)) < 0
@@ -251,7 +262,8 @@ out:
return loaded_file;
}
-static void unload_file(gnutls_datum_t data) {
+static void unload_file(gnutls_datum_t data)
+{
free(data.data);
}
@@ -371,6 +383,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 +412,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 +427,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 +442,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 +455,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 +465,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 +535,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 +562,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 +586,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 +607,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 +628,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 +686,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 +696,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 +714,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 +729,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 +748,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,17 +782,17 @@ 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);
/* Informational message */
- infof (data, "SSL re-using session ID\n");
+ infof(data, "SSL re-using session ID\n");
}
Curl_ssl_sessionid_unlock(conn);
}
@@ -847,8 +882,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 +902,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 +941,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 +957,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 +974,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 +1086,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 +1119,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 +1135,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 +1163,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 +1183,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 +1193,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 +1208,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 +1218,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;
@@ -1190,7 +1230,8 @@ gtls_connect_step3(struct connectdata *conn,
infof(data, "\t server certificate activation date OK\n");
}
- ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+ ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
if(ptr) {
result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
if(result != CURLE_OK) {
@@ -1270,7 +1311,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 +1330,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 +1339,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);
@@ -1332,7 +1375,7 @@ gtls_connect_common(struct connectdata *conn,
/* Initiate the connection, if not already done */
if(ssl_connect_1==connssl->connecting_state) {
- rc = gtls_connect_step1 (conn, sockindex);
+ rc = gtls_connect_step1(conn, sockindex);
if(rc)
return rc;
}
@@ -1379,6 +1422,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 +1455,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]);
}
/*
@@ -1486,8 +1543,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
@@ -1597,7 +1654,7 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */
gcry_md_hd_t MD5pw;
gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
gcry_md_write(MD5pw, tmp, tmplen);
- memcpy(md5sum, gcry_md_read (MD5pw, 0), md5len);
+ memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len);
gcry_md_close(MD5pw);
#endif
}
@@ -1616,7 +1673,7 @@ void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
gcry_md_hd_t SHA256pw;
gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
gcry_md_write(SHA256pw, tmp, tmplen);
- memcpy(sha256sum, gcry_md_read (SHA256pw, 0), sha256len);
+ memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
gcry_md_close(SHA256pw);
#endif
}
diff --git a/Utilities/cmcurl/lib/vtls/gtls.h b/Utilities/cmcurl/lib/vtls/gtls.h
index e0a95a7..6531201 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.h
+++ b/Utilities/cmcurl/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);
@@ -55,6 +57,9 @@ void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
bool Curl_gtls_cert_status_request(void);
+/* Support HTTPS-proxy */
+#define HTTPS_PROXY_SUPPORT 1
+
/* Set the API backend definition to GnuTLS */
#define CURL_SSL_BACKEND CURLSSLBACKEND_GNUTLS
@@ -81,7 +86,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/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index 24249dd..8bcaddd 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/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>
@@ -159,13 +163,20 @@ 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;
}
@@ -201,34 +212,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;
}
}
@@ -236,16 +245,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;
}
@@ -254,9 +262,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;
@@ -265,7 +273,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;
}
@@ -274,23 +282,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);
@@ -312,7 +318,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,
@@ -347,8 +353,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;
}
@@ -365,11 +374,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);
@@ -385,11 +394,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. */
@@ -443,9 +452,12 @@ mbed_connect_step2(struct connectdata *conn,
struct Curl_easy *data = conn->data;
struct ssl_connect_data* connssl = &conn->ssl[sockindex];
const mbedtls_x509_crt *peercert;
+ const char * const pinnedpubkey = SSL_IS_PROXY() ?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
#ifdef HAS_ALPN
- const char* next_protocol;
+ const char *next_protocol;
#endif
char errorbuf[128];
@@ -479,7 +491,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");
@@ -514,7 +526,7 @@ mbed_connect_step2(struct connectdata *conn,
free(buffer);
}
- if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+ if(pinnedpubkey) {
int size;
CURLcode result;
mbedtls_x509_crt *p;
@@ -553,7 +565,7 @@ mbed_connect_step2(struct connectdata *conn,
/* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
result = Curl_pin_peer_pubkey(data,
- data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+ pinnedpubkey,
&pubkey[PUB_DER_MAX_BYTES - size], size);
if(result) {
mbedtls_x509_crt_free(p);
@@ -606,7 +618,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;
@@ -625,10 +637,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);
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index dff1575..ba8d582 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -200,14 +200,14 @@ static const cipher_s cipherlist[] = {
#endif
};
-static const char* pem_library = "libnsspem.so";
-static 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)
@@ -254,7 +254,8 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model,
while((*cipher) && (ISSPACE(*cipher)))
++cipher;
- if((cipher_list = strchr(cipher, ','))) {
+ cipher_list = strchr(cipher, ',');
+ if(cipher_list) {
*cipher_list++ = '\0';
}
@@ -337,9 +338,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))
@@ -514,7 +514,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;
@@ -540,7 +540,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");
@@ -585,6 +585,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 */
@@ -602,8 +603,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;
@@ -664,7 +664,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 */
@@ -682,7 +682,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);
@@ -708,7 +708,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;
}
@@ -734,6 +734,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");
@@ -928,9 +933,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;
@@ -1367,36 +1375,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
@@ -1437,8 +1464,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);
@@ -1486,13 +1513,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
@@ -1532,6 +1568,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");
@@ -1589,6 +1637,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 */
@@ -1647,18 +1696,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 */
@@ -1670,14 +1719,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
@@ -1685,14 +1734,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;
@@ -1700,24 +1754,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;
@@ -1737,15 +1791,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;
}
@@ -1754,7 +1817,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;
}
@@ -1762,7 +1826,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;
}
@@ -1770,12 +1835,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;
@@ -1835,11 +1900,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;
@@ -1857,6 +1925,12 @@ 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;
+ const char * const pinnedpubkey = SSL_IS_PROXY() ?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+
/* check timeout situation */
const long time_left = Curl_timeleft(data, NULL, TRUE);
@@ -1872,9 +1946,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;
}
@@ -1883,11 +1957,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);
}
@@ -1902,7 +1976,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
}
}
- result = cmp_peer_pubkey(connssl, data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
+ result = cmp_peer_pubkey(connssl, pinnedpubkey);
if(result)
/* status already printed */
goto error;
@@ -2112,7 +2186,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/Utilities/cmcurl/lib/vtls/nssg.h b/Utilities/cmcurl/lib/vtls/nssg.h
index ac67e6a..fd94003 100644
--- a/Utilities/cmcurl/lib/vtls/nssg.h
+++ b/Utilities/cmcurl/lib/vtls/nssg.h
@@ -65,6 +65,9 @@ bool Curl_nss_cert_status_request(void);
bool Curl_nss_false_start(void);
+/* Support HTTPS-proxy */
+#define HTTPS_PROXY_SUPPORT 1
+
/* Set the API backend definition to NSS */
#define CURL_SSL_BACKEND CURLSSLBACKEND_NSS
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index c040928..d92e713 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -176,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
{
@@ -217,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;
}
@@ -237,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;
}
}
@@ -248,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 */
@@ -258,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
@@ -312,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;
@@ -348,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;
@@ -359,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);
}
@@ -473,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
@@ -571,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");
@@ -585,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");
@@ -916,27 +899,31 @@ 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);
- SSL_free (connssl->handle);
+ SSL_free(connssl->handle);
connssl->handle = NULL;
}
if(connssl->ctx) {
- SSL_CTX_free (connssl->ctx);
+ SSL_CTX_free(connssl->ctx);
connssl->ctx = NULL;
}
}
/*
+ * 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)
*/
@@ -1031,7 +1018,7 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
#endif
}
- SSL_free (connssl->handle);
+ SSL_free(connssl->handle);
connssl->handle = NULL;
}
return retval;
@@ -1107,16 +1094,20 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
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);
}
@@ -1165,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;
@@ -1180,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;
}
@@ -1196,9 +1187,9 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
/* an alternative name matched */
;
else if(dNSName || iPAddress) {
- infof(data, " subjectAltName does not match %s\n", conn->host.dispname);
+ 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 {
@@ -1272,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 {
@@ -1425,7 +1416,7 @@ static const char *ssl_msg_type(int ssl_ver, int msg)
{
#ifdef SSL2_VERSION_MAJOR
if(ssl_ver == SSL2_VERSION_MAJOR) {
- switch (msg) {
+ switch(msg) {
case SSL2_MT_ERROR:
return "Error";
case SSL2_MT_CLIENT_HELLO:
@@ -1449,7 +1440,7 @@ static const char *ssl_msg_type(int ssl_ver, int msg)
else
#endif
if(ssl_ver == SSL3_VERSION_MAJOR) {
- switch (msg) {
+ switch(msg) {
case SSL3_MT_HELLO_REQUEST:
return "Hello request";
case SSL3_MT_CLIENT_HELLO:
@@ -1549,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:
@@ -1571,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",
@@ -1677,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";
@@ -1711,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)
@@ -1743,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();
@@ -1756,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)
@@ -1841,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
@@ -1857,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;
@@ -1872,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;
}
@@ -1942,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)) {
@@ -1964,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")) {
@@ -1985,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 {
@@ -2015,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 {
@@ -2046,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
@@ -2059,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);
}
@@ -2070,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) {
@@ -2094,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);
@@ -2127,13 +2174,21 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_SSL_CONNECT_ERROR;
}
/* Informational message */
- infof (data, "SSL re-using session ID\n");
+ infof(data, "SSL re-using session ID\n");
}
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;
@@ -2149,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();
@@ -2198,7 +2255,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
lerr = SSL_get_verify_result(connssl->handle);
if(lerr != X509_V_OK) {
- data->set.ssl.certverifyresult = lerr;
+ *certverifyresult = lerr;
snprintf(error_buffer, sizeof(error_buffer),
"SSL certificate problem: %s",
X509_verify_cert_error_string(lerr));
@@ -2220,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;
}
@@ -2245,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) {
@@ -2276,7 +2336,8 @@ static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
{
int i, ilen;
- if((ilen = (int)len) < 0)
+ ilen = (int)len;
+ if(ilen < 0)
return 1; /* buffer too big */
i = i2t_ASN1_OBJECT(buf, ilen, a);
@@ -2698,6 +2759,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)
@@ -2713,7 +2776,7 @@ 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);
@@ -2731,7 +2794,7 @@ static CURLcode servercert(struct connectdata *conn,
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);
@@ -2754,12 +2817,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;
@@ -2769,7 +2832,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);
@@ -2781,7 +2844,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;
@@ -2789,15 +2852,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)
@@ -2816,7 +2878,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);
@@ -2830,7 +2892,8 @@ static CURLcode servercert(struct connectdata *conn,
/* when not strict, we don't bother about the verify cert problems */
result = CURLE_OK;
- ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+ ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
if(!result && ptr) {
result = pkp_pin_peer_pubkey(data, connssl->server_cert, ptr);
if(result)
@@ -2852,7 +2915,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;
@@ -2864,7 +2927,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");
@@ -2875,7 +2939,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");
@@ -2899,8 +2963,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;
@@ -2920,7 +2984,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 */
@@ -3048,7 +3112,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;
}
@@ -3093,8 +3160,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;
}
@@ -3178,7 +3255,7 @@ size_t Curl_ossl_version(char *buffer, size_t size)
sub[0] = 'z';
}
else {
- sub[0]=(char)(((ssleay_value>>4)&0xff) + 'a' -1);
+ sub[0] = (char) (minor_ver + 'a' - 1);
}
}
else
@@ -3199,7 +3276,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/Utilities/cmcurl/lib/vtls/openssl.h b/Utilities/cmcurl/lib/vtls/openssl.h
index ee18e71..cff1e90 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.h
+++ b/Utilities/cmcurl/lib/vtls/openssl.h
@@ -79,6 +79,9 @@ void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
bool Curl_ossl_cert_status_request(void);
+/* Support HTTPS-proxy */
+#define HTTPS_PROXY_SUPPORT 1
+
/* Set the API backend definition to OpenSSL */
#define CURL_SSL_BACKEND CURLSSLBACKEND_OPENSSL
diff --git a/Utilities/cmcurl/lib/vtls/polarssl.c b/Utilities/cmcurl/lib/vtls/polarssl.c
index 18b564e..4bba3e3 100644
--- a/Utilities/cmcurl/lib/vtls/polarssl.c
+++ b/Utilities/cmcurl/lib/vtls/polarssl.c
@@ -147,12 +147,16 @@ polarssl_connect_step1(struct connectdata *conn,
{
struct Curl_easy *data = conn->data;
struct ssl_connect_data* connssl = &conn->ssl[sockindex];
+ 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;
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;
}
@@ -180,30 +184,29 @@ polarssl_connect_step1(struct connectdata *conn,
/* 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) {
error_strerror(ret, errorbuf, sizeof(errorbuf));
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) {
error_strerror(ret, errorbuf, sizeof(errorbuf));
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;
}
}
@@ -211,25 +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) {
error_strerror(ret, errorbuf, sizeof(errorbuf));
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)
@@ -241,7 +244,7 @@ polarssl_connect_step1(struct connectdata *conn,
if(ret) {
error_strerror(ret, errorbuf, sizeof(errorbuf));
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;
}
@@ -250,29 +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) {
error_strerror(ret, errorbuf, sizeof(errorbuf));
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,
@@ -306,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);
@@ -320,11 +327,11 @@ 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);
if(ret) {
Curl_ssl_sessionid_unlock(conn);
@@ -339,12 +346,12 @@ polarssl_connect_step1(struct connectdata *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. */
@@ -354,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
@@ -390,6 +397,10 @@ polarssl_connect_step2(struct connectdata *conn,
struct Curl_easy *data = conn->data;
struct ssl_connect_data* connssl = &conn->ssl[sockindex];
char buffer[1024];
+ const char * const pinnedpubkey = SSL_IS_PROXY() ?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+
char errorbuf[128];
errorbuf[0] = 0;
@@ -423,7 +434,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");
@@ -451,7 +462,7 @@ polarssl_connect_step2(struct connectdata *conn,
}
/* adapted from mbedtls.c */
- if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+ if(pinnedpubkey) {
int size;
CURLcode result;
x509_crt *p;
@@ -493,7 +504,7 @@ polarssl_connect_step2(struct connectdata *conn,
/* pk_write_pubkey_der writes data at the end of the buffer. */
result = Curl_pin_peer_pubkey(data,
- data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+ pinnedpubkey,
&pubkey[PUB_DER_MAX_BYTES - size], size);
if(result) {
x509_crt_free(p);
@@ -544,7 +555,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;
@@ -563,10 +574,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);
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index f731eeb..ac8b705 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -59,6 +59,7 @@
#include "x509asn1.h"
#include "curl_printf.h"
#include "system_win32.h"
+#include "hostcheck.h"
/* The last #include file should be: */
#include "curl_memory.h"
@@ -123,9 +124,11 @@ 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.
@@ -142,9 +145,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
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");
@@ -161,7 +164,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. */
@@ -170,13 +173,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
@@ -189,15 +193,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 |
@@ -213,12 +216,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 */
@@ -253,9 +262,9 @@ 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");
@@ -265,17 +274,17 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
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);
@@ -333,7 +342,7 @@ 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;
@@ -406,11 +415,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;
@@ -506,7 +517,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;
@@ -623,7 +634,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
@@ -638,6 +649,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
@@ -645,7 +658,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;
@@ -701,12 +714,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");
@@ -717,7 +731,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");
@@ -769,7 +784,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 */
@@ -957,7 +972,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;
@@ -1376,9 +1391,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;
@@ -1400,7 +1417,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;
@@ -1525,6 +1542,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,
@@ -1546,7 +1566,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)) {
@@ -1582,15 +1602,10 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
}
if(result == CURLE_OK) {
- if(data->set.ssl.verifyhost) {
- TCHAR cert_hostname_buff[128];
- xcharp_u hostname;
- xcharp_u cert_hostname;
+ if(conn->ssl_config.verifyhost) {
+ TCHAR cert_hostname_buff[256];
DWORD len;
- cert_hostname.const_tchar_ptr = cert_hostname_buff;
- hostname.tchar_ptr = Curl_convert_UTF8_to_tchar(conn->host.name);
-
/* TODO: Fix this for certificates with multiple alternative names.
Right now we're only asking for the first preferred alternative name.
Instead we'd need to do all via CERT_NAME_SEARCH_ALL_NAMES_FLAG
@@ -1601,31 +1616,50 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
*/
len = CertGetNameString(pCertContextServer,
CERT_NAME_DNS_TYPE,
- 0,
+ CERT_NAME_DISABLE_IE4_UTF8_FLAG,
NULL,
- cert_hostname.tchar_ptr,
- 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);
- cert_hostname.tchar_ptr++;
- if(_tcsicmp(cert_hostname.const_tchar_ptr,
- hostname.const_tchar_ptr + hostname_len - len + 2) != 0)
- result = CURLE_PEER_FAILED_VERIFICATION;
+ cert_hostname_buff,
+ 256);
+ if(len > 0) {
+ const char *cert_hostname;
+
+ /* Comparing the cert name and the connection hostname encoded as UTF-8
+ * is acceptable since both values are assumed to use ASCII
+ * (or some equivalent) encoding
+ */
+ cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname_buff);
+ if(!cert_hostname) {
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ else{
+ int match_result;
+
+ match_result = Curl_cert_hostcheck(cert_hostname, conn->host.name);
+ if(match_result == CURL_HOST_MATCH) {
+ infof(data,
+ "schannel: connection hostname (%s) validated "
+ "against certificate name (%s)\n",
+ conn->host.name,
+ cert_hostname);
+ result = CURLE_OK;
+ }
+ else{
+ failf(data,
+ "schannel: connection hostname (%s) "
+ "does not match certificate name (%s)",
+ conn->host.name,
+ cert_hostname);
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ Curl_unicodefree(cert_hostname);
+ }
}
- else if(len == 0 || _tcsicmp(hostname.const_tchar_ptr,
- cert_hostname.const_tchar_ptr) != 0) {
+ else {
+ failf(data,
+ "schannel: CertGetNameString did not provide any "
+ "certificate name information");
result = CURLE_PEER_FAILED_VERIFICATION;
}
- if(result == CURLE_PEER_FAILED_VERIFICATION) {
- char *_cert_hostname;
- _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);
- Curl_unicodefree(_cert_hostname);
- }
- Curl_unicodefree(hostname.tchar_ptr);
}
}
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index 56a8823..b808e1c 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -65,6 +65,7 @@
#include "url.h"
#include "progress.h"
#include "share.h"
+#include "multiif.h"
#include "timeval.h"
#include "curl_md5.h"
#include "warnless.h"
@@ -80,94 +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 != strcasecompare(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->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);
@@ -177,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;
@@ -288,19 +173,41 @@ 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(HTTPS_PROXY_SUPPORT)
+ 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;
@@ -321,6 +228,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;
@@ -363,7 +275,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;
@@ -371,11 +284,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;
@@ -385,21 +305,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(strcasecompare(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 &&
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) &&
+ (port == check->remote_port) &&
strcasecompare(conn->handler->scheme, check->scheme) &&
- Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) {
+ 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 */
@@ -428,7 +348,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);
@@ -443,7 +363,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) {
@@ -461,7 +381,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 */
@@ -471,10 +392,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 */
@@ -505,14 +430,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
@@ -528,10 +453,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 +473,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 +484,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 +578,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 +654,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 +699,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/Utilities/cmcurl/lib/vtls/vtls.h b/Utilities/cmcurl/lib/vtls/vtls.h
index a41ecc3..2aabeda 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.h
+++ b/Utilities/cmcurl/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/Utilities/cmcurl/lib/x509asn1.c b/Utilities/cmcurl/lib/x509asn1.c
index 74a511b..c4bc7c1 100644
--- a/Utilities/cmcurl/lib/x509asn1.c
+++ b/Utilities/cmcurl/lib/x509asn1.c
@@ -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,16 +166,16 @@ 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. */
@@ -184,7 +187,7 @@ static const curl_OID * searchOID(const char * oid)
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
@@ -262,7 +267,7 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
string length. */
*to = (char *) NULL;
- switch (type) {
+ switch(type) {
case CURL_ASN1_BMP_STRING:
size = 2;
break;
@@ -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. */
@@ -295,7 +302,7 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
else {
for(outlength = 0; from < end;) {
wc = 0;
- switch (size) {
+ switch(size) {
case 4:
wc = (wc << 8) | *(const unsigned char *) from++;
wc = (wc << 8) | *(const unsigned char *) from++;
@@ -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. */
@@ -453,7 +460,7 @@ static const char * GTime2str(const char * beg, const char * end)
/* Get seconds digits. */
sec1 = '0';
- switch (fracp - beg - 12) {
+ switch(fracp - beg - 12) {
case 0:
sec2 = '0';
break;
@@ -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. */
@@ -512,7 +519,7 @@ static const char * UTime2str(const char * beg, const char * end)
;
/* Get the seconds. */
sec = beg + 10;
- switch (tzp - sec) {
+ switch(tzp - sec) {
case 0:
sec = "00";
case 2:
@@ -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. */
@@ -549,7 +556,7 @@ const char * Curl_ASN1tostr(curl_asn1Element * elem, int type)
if(!type)
type = elem->tag; /* Type not forced: use element tag as type. */
- switch (type) {
+ switch(type) {
case CURL_ASN1_BOOLEAN:
return bool2str(elem->beg, elem->end);
case CURL_ASN1_INTEGER:
@@ -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;
@@ -865,18 +874,18 @@ static void do_pubkey(struct Curl_easy * data, int certnum,
#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. */
@@ -1108,12 +1122,12 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
/* Check all GeneralNames. */
for(q = elem.beg; matched != 1 && q < elem.end;) {
q = Curl_getASN1Element(&name, q, elem.end);
- switch (name.tag) {
+ switch(name.tag) {
case 2: /* DNS name. */
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);
@@ -1128,15 +1142,15 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
}
}
- switch (matched) {
+ 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/Utilities/cmcurl/lib/x509asn1.h b/Utilities/cmcurl/lib/x509asn1.h
index 0f2b930..ce40297 100644
--- a/Utilities/cmcurl/lib/x509asn1.h
+++ b/Utilities/cmcurl/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/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt
index 09bef51..bfe6b13 100644
--- a/Utilities/cmlibarchive/CMakeLists.txt
+++ b/Utilities/cmlibarchive/CMakeLists.txt
@@ -17,13 +17,13 @@ SET(CMAKE_MACOSX_RPATH ON)
#
FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/build/version _version)
STRING(REGEX REPLACE
- "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]?$" "\\1" _major ${_version})
+ "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]*$" "\\1" _major ${_version})
STRING(REGEX REPLACE
- "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]?$" "\\1" _minor ${_version})
+ "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]*$" "\\1" _minor ${_version})
STRING(REGEX REPLACE
- "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]?$" "\\1" _revision ${_version})
+ "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]*$" "\\1" _revision ${_version})
STRING(REGEX REPLACE
- "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]?)$" "\\1" _quality ${_version})
+ "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]*)$" "\\1" _quality ${_version})
SET(_version_number ${_major}${_minor}${_revision})
STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_minor ${_minor})
STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_revision ${_revision})
@@ -71,13 +71,15 @@ include(CTest)
OPTION(ENABLE_NETTLE "Enable use of Nettle" ON)
OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON)
-OPTION(ENABLE_LZMA "Enable the use of the system found LZMA library if found" ON)
-OPTION(ENABLE_ZLIB "Enable the use of the system found ZLIB library if found" ON)
-OPTION(ENABLE_BZip2 "Enable the use of the system found BZip2 library if found" ON)
-OPTION(ENABLE_LIBXML2 "Enable the use of the system found libxml2 library if found" ON)
-OPTION(ENABLE_EXPAT "Enable the use of the system found EXPAT library if found" ON)
-OPTION(ENABLE_PCREPOSIX "Enable the use of the system found PCREPOSIX library if found" ON)
-OPTION(ENABLE_LibGCC "Enable the use of the system found LibGCC library if found" ON)
+OPTION(ENABLE_LZO "Enable the use of the system LZO library if found" OFF)
+OPTION(ENABLE_LZMA "Enable the use of the system LZMA library if found" ON)
+
+OPTION(ENABLE_ZLIB "Enable the use of the system ZLIB library if found" ON)
+OPTION(ENABLE_BZip2 "Enable the use of the system BZip2 library if found" ON)
+OPTION(ENABLE_LIBXML2 "Enable the use of the system libxml2 library if found" ON)
+OPTION(ENABLE_EXPAT "Enable the use of the system EXPAT library if found" ON)
+OPTION(ENABLE_PCREPOSIX "Enable the use of the system PCREPOSIX library if found" ON)
+OPTION(ENABLE_LibGCC "Enable the use of the system LibGCC library if found" ON)
# CNG is used for encrypt/decrypt Zip archives on Windows.
OPTION(ENABLE_CNG "Enable the use of CNG(Crypto Next Generation)" ON)
@@ -107,7 +109,7 @@ INCLUDE(CheckHeaderDirent)
INCLUDE(CheckIncludeFile)
INCLUDE(CheckIncludeFiles)
INCLUDE(CheckLibraryExists)
-INCLUDE(CheckStructMember)
+INCLUDE(CheckStructHasMember)
INCLUDE(CheckSymbolExists)
INCLUDE(CheckTypeExists)
INCLUDE(CheckTypeSize)
@@ -285,21 +287,20 @@ MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARIES)
# Find LZMA
#
IF(ENABLE_LZMA)
- FIND_PACKAGE(LZMA)
+ FIND_PACKAGE(LibLZMA)
ELSE()
- SET(LZMA_FOUND FALSE) # Override cached value
- SET(LZMADEC_FOUND FALSE) # Override cached value
+ SET(LIBZMA_FOUND FALSE) # Override cached value
ENDIF()
-IF(LZMA_FOUND)
+IF(LIBLZMA_FOUND)
SET(HAVE_LIBLZMA 1)
SET(HAVE_LZMA_H 1)
- INCLUDE_DIRECTORIES(${LZMA_INCLUDE_DIR})
- LIST(APPEND ADDITIONAL_LIBS ${LZMA_LIBRARIES})
+ INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS})
+ LIST(APPEND ADDITIONAL_LIBS ${LIBLZMA_LIBRARIES})
IF(CMAKE_USE_SYSTEM_LIBLZMA)
# Test if a macro is needed for the library.
TRY_MACRO_FOR_LIBRARY(
- "${LZMA_INCLUDE_DIR}" "${LZMA_LIBRARIES}"
+ "${LIBLZMA_INCLUDE_DIRS}" "${LIBLZMA_LIBRARIES}"
COMPILES
"#include <lzma.h>\nint main() {return (int)lzma_version_number(); }"
"WITHOUT_LZMA_API_STATIC;LZMA_API_STATIC")
@@ -309,27 +310,26 @@ IF(LZMA_FOUND)
ELSE()
ADD_DEFINITIONS(-DLZMA_API_STATIC)
ENDIF()
-ELSEIF(LZMADEC_FOUND)
- SET(HAVE_LIBLZMADEC 1)
- SET(HAVE_LZMADEC_H 1)
- INCLUDE_DIRECTORIES(${LZMADEC_INCLUDE_DIR})
- LIST(APPEND ADDITIONAL_LIBS ${LZMADEC_LIBRARIES})
-ELSE(LZMA_FOUND)
+ELSE(LIBLZMA_FOUND)
# LZMA not found and will not be used.
-ENDIF(LZMA_FOUND)
+ENDIF(LIBLZMA_FOUND)
IF(0) # CMake does not need LZO2 support in libarchive
#
# Find LZO2
#
-IF (LZO2_INCLUDE_DIR)
- # Already in cache, be silent
- SET(LZO2_FIND_QUIETLY TRUE)
-ENDIF (LZO2_INCLUDE_DIR)
-
-FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h)
-FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2)
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR)
+IF(ENABLE_LZO)
+ IF (LZO2_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(LZO2_FIND_QUIETLY TRUE)
+ ENDIF (LZO2_INCLUDE_DIR)
+
+ FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h)
+ FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2)
+ INCLUDE(FindPackageHandleStandardArgs)
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR)
+ELSE(ENABLE_LZO)
+ SET(LIBZMA_FOUND FALSE) # Override cached value
+ENDIF(ENABLE_LZO)
IF(LZO2_FOUND)
SET(HAVE_LIBLZO2 1)
SET(HAVE_LZO_LZOCONF_H 1)
@@ -415,6 +415,11 @@ LA_CHECK_INCLUDE_FILE("limits.h" HAVE_LIMITS_H)
LA_CHECK_INCLUDE_FILE("linux/types.h" HAVE_LINUX_TYPES_H)
LA_CHECK_INCLUDE_FILE("linux/fiemap.h" HAVE_LINUX_FIEMAP_H)
LA_CHECK_INCLUDE_FILE("linux/fs.h" HAVE_LINUX_FS_H)
+
+CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
+#include <linux/fs.h>
+int main(void) { return FS_IOC_GETFLAGS; }" HAVE_WORKING_FS_IOC_GETFLAGS)
+
LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H)
LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H)
LA_CHECK_INCLUDE_FILE("memory.h" HAVE_MEMORY_H)
@@ -459,7 +464,7 @@ IF(ENABLE_CNG)
ELSE(ENABLE_CNG)
UNSET(HAVE_BCRYPT_H CACHE)
ENDIF(ENABLE_CNG)
-# Following files need windwos.h, so we should test it after windows.h test.
+# Following files need windows.h, so we should test it after windows.h test.
LA_CHECK_INCLUDE_FILE("wincrypt.h" HAVE_WINCRYPT_H)
LA_CHECK_INCLUDE_FILE("winioctl.h" HAVE_WINIOCTL_H)
@@ -1005,6 +1010,14 @@ CHECK_FUNCTION_EXISTS(wmemmove HAVE_WMEMMOVE)
CMAKE_POP_CHECK_STATE() # Restore the state of the variables
+CHECK_C_SOURCE_COMPILES(
+ "#include <sys/types.h>\n#include <sys/mount.h>\nint main(void) { struct vfsconf v; return sizeof(v);}"
+ HAVE_STRUCT_VFSCONF)
+
+CHECK_C_SOURCE_COMPILES(
+ "#include <sys/types.h>\n#include <sys/mount.h>\nint main(void) { struct xvfsconf v; return sizeof(v);}"
+ HAVE_STRUCT_XVFSCONF)
+
# Make sure we have the POSIX version of readdir_r, not the
# older 2-argument version.
CHECK_C_SOURCE_COMPILES(
@@ -1030,6 +1043,10 @@ CHECK_C_SOURCE_COMPILES(
"#include <sys/sysmacros.h>\nint main() { return major(256); }"
MAJOR_IN_SYSMACROS)
+CHECK_C_SOURCE_COMPILES(
+ "#include <lzma.h>\n#if LZMA_VERSION < 50020000\n#error unsupported\n#endif\nint main(void){lzma_stream_encoder_mt(0, 0); return 0;}"
+ HAVE_LZMA_STREAM_ENCODER_MT)
+
IF(HAVE_STRERROR_R)
SET(HAVE_DECL_STRERROR_R 1)
ENDIF(HAVE_STRERROR_R)
@@ -1063,47 +1080,47 @@ CHECK_SYMBOL_EXISTS(SSIZE_MAX "limits.h" HAVE_DECL_SSIZE_MAX)
# Check struct members
#
# Check for tm_gmtoff in struct tm
-CHECK_STRUCT_MEMBER("struct tm" tm_gmtoff
+CHECK_STRUCT_HAS_MEMBER("struct tm" tm_gmtoff
"time.h" HAVE_STRUCT_TM_TM_GMTOFF)
-CHECK_STRUCT_MEMBER("struct tm" __tm_gmtoff
+CHECK_STRUCT_HAS_MEMBER("struct tm" __tm_gmtoff
"time.h" HAVE_STRUCT_TM___TM_GMTOFF)
# Check for f_namemax in struct statfs
-CHECK_STRUCT_MEMBER("struct statfs" f_namemax
+CHECK_STRUCT_HAS_MEMBER("struct statfs" f_namemax
"sys/param.h;sys/mount.h" HAVE_STRUCT_STATFS_F_NAMEMAX)
# Check for birthtime in struct stat
-CHECK_STRUCT_MEMBER("struct stat" st_birthtime
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtime
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIME)
# Check for high-resolution timestamps in struct stat
-CHECK_STRUCT_MEMBER("struct stat" st_birthtimespec.tv_nsec
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtimespec.tv_nsec
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
-CHECK_STRUCT_MEMBER("struct stat" st_mtimespec.tv_nsec
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
-CHECK_STRUCT_MEMBER("struct stat" st_mtim.tv_nsec
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
-CHECK_STRUCT_MEMBER("struct stat" st_mtime_n
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_n
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_N)
-CHECK_STRUCT_MEMBER("struct stat" st_umtime
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_umtime
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_UMTIME)
-CHECK_STRUCT_MEMBER("struct stat" st_mtime_usec
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_usec
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_USEC)
# Check for block size support in struct stat
-CHECK_STRUCT_MEMBER("struct stat" st_blksize
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_blksize
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BLKSIZE)
# Check for st_flags in struct stat (BSD fflags)
-CHECK_STRUCT_MEMBER("struct stat" st_flags
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_flags
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_FLAGS)
IF(HAVE_SYS_STATVFS_H)
- CHECK_STRUCT_MEMBER("struct statvfs" f_iosize
+ CHECK_STRUCT_HAS_MEMBER("struct statvfs" f_iosize
"sys/types.h;sys/statvfs.h" HAVE_STRUCT_STATVFS_F_IOSIZE)
ENDIF()
#
#
-CHECK_STRUCT_MEMBER("struct tm" tm_sec
+CHECK_STRUCT_HAS_MEMBER("struct tm" tm_sec
"sys/types.h;sys/time.h;time.h" TIME_WITH_SYS_TIME)
#
@@ -1323,16 +1340,36 @@ IF(ENABLE_ACL)
# test for specific permissions in a permset.) Linux uses the obvious
# name, FreeBSD adds _np to mark it as "non-Posix extension."
# Test for both as a double-check that we really have POSIX-style ACL support.
+ CHECK_FUNCTION_EXISTS(acl_get_fd_np HAVE_ACL_GET_FD_NP)
CHECK_FUNCTION_EXISTS(acl_get_perm HAVE_ACL_GET_PERM)
CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP)
CHECK_FUNCTION_EXISTS(acl_get_link HAVE_ACL_GET_LINK)
CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP)
CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP)
CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP)
+ CHECK_SYMBOL_EXISTS(ACL_TYPE_NFS4 "${INCLUDES}" HAVE_ACL_TYPE_NFS4)
# MacOS has an acl.h that isn't POSIX. It can be detected by
# checking for ACL_USER
CHECK_SYMBOL_EXISTS(ACL_USER "${INCLUDES}" HAVE_ACL_USER)
+ CHECK_C_SOURCE_COMPILES("#include <sys/types.h>
+#include <sys/acl.h>
+int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_ACL_TYPE_EXTENDED)
+
+ # Solaris and derivates ACLs
+ CHECK_LIBRARY_EXISTS(sec "acl_get" "" HAVE_LIBSEC)
+ IF(HAVE_LIBSEC)
+ SET(CMAKE_REQUIRED_LIBRARIES "sec")
+ FIND_LIBRARY(SEC_LIBRARY NAMES sec)
+ LIST(APPEND ADDITIONAL_LIBS ${SEC_LIBRARY})
+ ENDIF(HAVE_LIBSEC)
+ #
+ CHECK_TYPE_EXISTS(aclent_t "${INCLUDES}" HAVE_ACLENT_T)
+ CHECK_TYPE_EXISTS(ace_t "${INCLUDES}" HAVE_ACE_T)
+ CHECK_FUNCTION_EXISTS(acl_get HAVE_FACL_GET)
+ CHECK_FUNCTION_EXISTS(facl_get HAVE_FACL_GET)
+ CHECK_FUNCTION_EXISTS(acl_set HAVE_FACL_SET)
+ CHECK_FUNCTION_EXISTS(facl_set HAVE_FACL_SET)
ELSE(ENABLE_ACL)
# If someone runs cmake, then disables ACL support, we need
# to forcibly override the cached values for these.
@@ -1347,7 +1384,15 @@ ELSE(ENABLE_ACL)
SET(HAVE_ACL_SET_FD FALSE)
SET(HAVE_ACL_SET_FD_NP FALSE)
SET(HAVE_ACL_SET_FILE FALSE)
+ SET(HAVE_ACL_TYPE_NFS4 FALSE)
SET(HAVE_ACL_USER FALSE)
+ SET(HAVE_ACL_TYPE_EXTENDED FALSE)
+ SET(HAVE_ACL_GET FALSE)
+ SET(HAVE_ACLENT_T FALSE)
+ SET(HAVE_ACE_T FALSE)
+ SET(HAVE_FACL_GET FALSE)
+ SET(HAVE_ACL_SET FALSE)
+ SET(HAVE_FACL_SET FALSE)
ENDIF(ENABLE_ACL)
#
diff --git a/Utilities/cmlibarchive/build/cmake/CheckStructMember.cmake b/Utilities/cmlibarchive/build/cmake/CheckStructMember.cmake
deleted file mode 100644
index 05ddb3a..0000000
--- a/Utilities/cmlibarchive/build/cmake/CheckStructMember.cmake
+++ /dev/null
@@ -1,43 +0,0 @@
-# - Check if the given struct or class has the specified member variable
-# CHECK_STRUCT_MEMBER (STRUCT MEMBER HEADER VARIABLE)
-#
-# STRUCT - the name of the struct or class you are interested in
-# MEMBER - the member which existence you want to check
-# HEADER - the header(s) where the prototype should be declared
-# VARIABLE - variable to store the result
-#
-# The following variables may be set before calling this macro to
-# modify the way the check is run:
-#
-# CMAKE_REQUIRED_FLAGS = string of compile command line flags
-# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
-# CMAKE_REQUIRED_INCLUDES = list of include directories
-
-# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
-#
-# Redistribution and use is allowed according to the terms of the BSD license.
-# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
-
-
-INCLUDE(CheckCSourceCompiles)
-
-MACRO (CHECK_STRUCT_MEMBER _STRUCT _MEMBER _HEADER _RESULT)
- SET(_INCLUDE_FILES)
- FOREACH (it ${_HEADER})
- SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
- ENDFOREACH (it)
-
- SET(_CHECK_STRUCT_MEMBER_SOURCE_CODE "
-${_INCLUDE_FILES}
-int main()
-{
- static ${_STRUCT} tmp;
- if (sizeof(tmp.${_MEMBER}))
- return 0;
- return 0;
-}
-")
- CHECK_C_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT})
-
-ENDMACRO (CHECK_STRUCT_MEMBER)
-
diff --git a/Utilities/cmlibarchive/build/cmake/FindLZMA.cmake b/Utilities/cmlibarchive/build/cmake/FindLZMA.cmake
deleted file mode 100644
index 0b46b2c..0000000
--- a/Utilities/cmlibarchive/build/cmake/FindLZMA.cmake
+++ /dev/null
@@ -1,48 +0,0 @@
-# - Find lzma and lzmadec
-# Find the native LZMA includes and library
-#
-# LZMA_INCLUDE_DIR - where to find lzma.h, etc.
-# LZMA_LIBRARIES - List of libraries when using liblzma.
-# LZMA_FOUND - True if liblzma found.
-# LZMADEC_INCLUDE_DIR - where to find lzmadec.h, etc.
-# LZMADEC_LIBRARIES - List of libraries when using liblzmadec.
-# LZMADEC_FOUND - True if liblzmadec found.
-
-IF (LZMA_INCLUDE_DIR)
- # Already in cache, be silent
- SET(LZMA_FIND_QUIETLY TRUE)
-ENDIF (LZMA_INCLUDE_DIR)
-
-FIND_PATH(LZMA_INCLUDE_DIR lzma.h)
-FIND_LIBRARY(LZMA_LIBRARY NAMES lzma liblzma)
-
-# handle the QUIETLY and REQUIRED arguments and set LZMA_FOUND to TRUE if
-# all listed variables are TRUE
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZMA DEFAULT_MSG LZMA_LIBRARY LZMA_INCLUDE_DIR)
-
-IF(LZMA_FOUND)
- SET( LZMA_LIBRARIES ${LZMA_LIBRARY} )
-ELSE(LZMA_FOUND)
- SET( LZMA_LIBRARIES )
-
- IF (LZMADEC_INCLUDE_DIR)
- # Already in cache, be silent
- SET(LZMADEC_FIND_QUIETLY TRUE)
- ENDIF (LZMADEC_INCLUDE_DIR)
-
- FIND_PATH(LZMADEC_INCLUDE_DIR lzmadec.h)
- FIND_LIBRARY(LZMADEC_LIBRARY NAMES lzmadec )
-
- # handle the QUIETLY and REQUIRED arguments and set LZMADEC_FOUND to TRUE if
- # all listed variables are TRUE
- INCLUDE(FindPackageHandleStandardArgs)
- FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZMADEC DEFAULT_MSG LZMADEC_LIBRARY
- LZMADEC_INCLUDE_DIR)
-
- IF(LZMADEC_FOUND)
- SET( LZMADEC_LIBRARIES ${LZMADEC_LIBRARY} )
- ELSE(LZMADEC_FOUND)
- SET( LZMADEC_LIBRARIES )
- ENDIF(LZMADEC_FOUND)
-ENDIF(LZMA_FOUND)
diff --git a/Utilities/cmlibarchive/build/cmake/config.h.in b/Utilities/cmlibarchive/build/cmake/config.h.in
index 9843875..55e04b9 100644
--- a/Utilities/cmlibarchive/build/cmake/config.h.in
+++ b/Utilities/cmlibarchive/build/cmake/config.h.in
@@ -296,6 +296,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the `acl_create_entry' function. */
#cmakedefine HAVE_ACL_CREATE_ENTRY 1
+/* Define to 1 if you have the `acl_get_fd_np' function. */
+#cmakedefine HAVE_ACL_GET_FD_NP 1
+
/* Define to 1 if you have the `acl_get_link' function. */
#cmakedefine HAVE_ACL_GET_LINK 1
@@ -326,6 +329,12 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the `acl_set_file' function. */
#cmakedefine HAVE_ACL_SET_FILE 1
+/* True for FreeBSD with NFSv4 ACL support */
+#cmakedefine HAVE_ACL_TYPE_NFS4 1
+
+/* True for MacOS ACL support */
+#cmakedefine HAVE_ACL_TYPE_EXTENDED 1
+
/* True for systems with POSIX ACL support */
#cmakedefine HAVE_ACL_USER 1
@@ -727,6 +736,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <lzma.h> header file. */
#cmakedefine HAVE_LZMA_H 1
+/* Define to 1 if you have a working `lzma_stream_encoder_mt' function. */
+#cmakedefine HAVE_LZMA_STREAM_ENCODER_MT 1
+
/* Define to 1 if you have the <lzo/lzo1x.h> header file. */
#cmakedefine HAVE_LZO_LZO1X_H 1
@@ -929,6 +941,12 @@ typedef uint64_t uintmax_t;
/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */
#cmakedefine HAVE_STRUCT_TM___TM_GMTOFF 1
+/* Define to 1 if you have `struct vfsconf'. */
+#cmakedefine HAVE_STRUCT_VFSCONF 1
+
+/* Define to 1 if you have `struct xvfsconf'. */
+#cmakedefine HAVE_STRUCT_XVFSCONF 1
+
/* Define to 1 if you have the `symlink' function. */
#cmakedefine HAVE_SYMLINK 1
@@ -1087,6 +1105,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have a working EXT2_IOC_GETFLAGS */
#cmakedefine HAVE_WORKING_EXT2_IOC_GETFLAGS 1
+/* Define to 1 if you have a working FS_IOC_GETFLAGS */
+#cmakedefine HAVE_WORKING_FS_IOC_GETFLAGS 1
+
/* Define to 1 if you have the <zlib.h> header file. */
#cmakedefine HAVE_ZLIB_H 1
diff --git a/Utilities/cmlibarchive/build/version b/Utilities/cmlibarchive/build/version
index f293156..ef83457 100644
--- a/Utilities/cmlibarchive/build/version
+++ b/Utilities/cmlibarchive/build/version
@@ -1 +1 @@
-3002001
+3003001
diff --git a/Utilities/cmlibarchive/libarchive/CMakeLists.txt b/Utilities/cmlibarchive/libarchive/CMakeLists.txt
index eaa7b20..d412c80 100644
--- a/Utilities/cmlibarchive/libarchive/CMakeLists.txt
+++ b/Utilities/cmlibarchive/libarchive/CMakeLists.txt
@@ -168,15 +168,33 @@ SET(libarchive_MANS
archive_entry_time.3
archive_read.3
archive_read_add_passphrase.3
+ archive_read_data.3
archive_read_disk.3
+ archive_read_extract.3
+ archive_read_filter.3
+ archive_read_format.3
+ archive_read_free.3
+ archive_read_header.3
+ archive_read_new.3
+ archive_read_open.3
archive_read_set_options.3
archive_util.3
archive_write.3
+ archive_write_blocksize.3
+ archive_write_data.3
archive_write_disk.3
+ archive_write_filter.3
+ archive_write_finish_entry.3
+ archive_write_format.3
+ archive_write_free.3
+ archive_write_header.3
+ archive_write_new.3
+ archive_write_open.3
archive_write_set_options.3
archive_write_set_passphrase.3
cpio.5
libarchive.3
+ libarchive_changes.3
libarchive_internals.3
libarchive-formats.5
mtree.5
diff --git a/Utilities/cmlibarchive/libarchive/archive.h b/Utilities/cmlibarchive/libarchive/archive.h
index 3b5104b..cfb5c48 100644
--- a/Utilities/cmlibarchive/libarchive/archive.h
+++ b/Utilities/cmlibarchive/libarchive/archive.h
@@ -36,7 +36,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define ARCHIVE_VERSION_NUMBER 3002001
+#define ARCHIVE_VERSION_NUMBER 3003001
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -152,7 +152,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.2.1"
+#define ARCHIVE_VERSION_ONLY_STRING "3.3.1"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
@@ -370,7 +370,7 @@ typedef const char *archive_passphrase_callback(struct archive *,
* 4) Repeatedly call archive_read_next_header to get information about
* successive archive entries. Call archive_read_data to extract
* data for entries of interest.
- * 5) Call archive_read_finish to end processing.
+ * 5) Call archive_read_free to end processing.
*/
__LA_DECL struct archive *archive_read_new(void);
@@ -559,7 +559,7 @@ __LA_DECL la_int64_t archive_read_header_position(struct archive *);
* we cannot say whether there are encrypted entries, then
* ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
* In general, this function will return values below zero when the
- * reader is uncertain or totally uncapable of encryption support.
+ * reader is uncertain or totally incapable of encryption support.
* When this function returns 0 you can be sure that the reader
* supports encryption detection but no encrypted entries have
* been found yet.
@@ -981,12 +981,12 @@ __LA_DECL int archive_read_disk_can_descend(struct archive *);
__LA_DECL int archive_read_disk_current_filesystem(struct archive *);
__LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *);
__LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *);
-/* Request that the access time of the entry visited by travesal be restored. */
+/* Request that the access time of the entry visited by traversal be restored. */
__LA_DECL int archive_read_disk_set_atime_restored(struct archive *);
/*
* Set behavior. The "flags" argument selects optional behavior.
*/
-/* Request that the access time of the entry visited by travesal be restored.
+/* Request that the access time of the entry visited by traversal be restored.
* This is the same as archive_read_disk_set_atime_restored. */
#define ARCHIVE_READDISK_RESTORE_ATIME (0x0001)
/* Default: Do not skip an entry which has nodump flags. */
@@ -998,6 +998,10 @@ __LA_DECL int archive_read_disk_set_atime_restored(struct archive *);
#define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008)
/* Default: Xattrs are read from disk. */
#define ARCHIVE_READDISK_NO_XATTR (0x0010)
+/* Default: ACLs are read from disk. */
+#define ARCHIVE_READDISK_NO_ACL (0x0020)
+/* Default: File flags are read from disk. */
+#define ARCHIVE_READDISK_NO_FFLAGS (0x0040)
__LA_DECL int archive_read_disk_set_behavior(struct archive *,
int flags);
@@ -1121,7 +1125,7 @@ __LA_DECL int archive_match_time_excluded(struct archive *,
/*
* Flags to tell a matching type of time stamps. These are used for
- * following functinos.
+ * following functions.
*/
/* Time flag: mtime to be tested. */
#define ARCHIVE_MATCH_MTIME (0x0100)
@@ -1141,7 +1145,7 @@ __LA_DECL int archive_match_include_date(struct archive *, int _flag,
const char *_datestr);
__LA_DECL int archive_match_include_date_w(struct archive *, int _flag,
const wchar_t *_datestr);
-/* Set inclusion time by a particluar file. */
+/* Set inclusion time by a particular file. */
__LA_DECL int archive_match_include_file_time(struct archive *,
int _flag, const char *_pathname);
__LA_DECL int archive_match_include_file_time_w(struct archive *,
diff --git a/Utilities/cmlibarchive/libarchive/archive_acl.c b/Utilities/cmlibarchive/libarchive/archive_acl.c
index bf4b610..b8b6b63 100644
--- a/Utilities/cmlibarchive/libarchive/archive_acl.c
+++ b/Utilities/cmlibarchive/libarchive/archive_acl.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003-2010 Tim Kientzle
+ * Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -55,25 +56,77 @@ static struct archive_acl_entry *acl_new_entry(struct archive_acl *acl,
static int archive_acl_add_entry_len_l(struct archive_acl *acl,
int type, int permset, int tag, int id, const char *name,
size_t len, struct archive_string_conv *sc);
+static int archive_acl_text_want_type(struct archive_acl *acl, int flags);
+static ssize_t archive_acl_text_len(struct archive_acl *acl, int want_type,
+ int flags, int wide, struct archive *a,
+ struct archive_string_conv *sc);
static int isint_w(const wchar_t *start, const wchar_t *end, int *result);
static int ismode_w(const wchar_t *start, const wchar_t *end, int *result);
+static int is_nfs4_flags_w(const wchar_t *start, const wchar_t *end,
+ int *result);
+static int is_nfs4_perms_w(const wchar_t *start, const wchar_t *end,
+ int *result);
static void next_field_w(const wchar_t **wp, const wchar_t **start,
const wchar_t **end, wchar_t *sep);
-static int prefix_w(const wchar_t *start, const wchar_t *end,
- const wchar_t *test);
-static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
- const wchar_t *wname, int perm, int id);
+static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
+ int tag, int flags, const wchar_t *wname, int perm, int id);
static void append_id_w(wchar_t **wp, int id);
static int isint(const char *start, const char *end, int *result);
static int ismode(const char *start, const char *end, int *result);
+static int is_nfs4_flags(const char *start, const char *end,
+ int *result);
+static int is_nfs4_perms(const char *start, const char *end,
+ int *result);
static void next_field(const char **p, const char **start,
const char **end, char *sep);
-static int prefix_c(const char *start, const char *end,
- const char *test);
-static void append_entry(char **p, const char *prefix, int tag,
- const char *name, int perm, int id);
+static void append_entry(char **p, const char *prefix, int type,
+ int tag, int flags, const char *name, int perm, int id);
static void append_id(char **p, int id);
+static const struct {
+ const int perm;
+ const char c;
+ const wchar_t wc;
+} nfsv4_acl_perm_map[] = {
+ { ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, 'r',
+ L'r' },
+ { ARCHIVE_ENTRY_ACL_WRITE_DATA | ARCHIVE_ENTRY_ACL_ADD_FILE, 'w',
+ L'w' },
+ { ARCHIVE_ENTRY_ACL_EXECUTE, 'x', L'x' },
+ { ARCHIVE_ENTRY_ACL_APPEND_DATA | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY,
+ 'p', L'p' },
+ { ARCHIVE_ENTRY_ACL_DELETE, 'd', L'd' },
+ { ARCHIVE_ENTRY_ACL_DELETE_CHILD, 'D', L'D' },
+ { ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, 'a', L'a' },
+ { ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, 'A', L'A' },
+ { ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, 'R', L'R' },
+ { ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, 'W', L'W' },
+ { ARCHIVE_ENTRY_ACL_READ_ACL, 'c', L'c' },
+ { ARCHIVE_ENTRY_ACL_WRITE_ACL, 'C', L'C' },
+ { ARCHIVE_ENTRY_ACL_WRITE_OWNER, 'o', L'o' },
+ { ARCHIVE_ENTRY_ACL_SYNCHRONIZE, 's', L's' }
+};
+
+static const int nfsv4_acl_perm_map_size = (int)(sizeof(nfsv4_acl_perm_map) /
+ sizeof(nfsv4_acl_perm_map[0]));
+
+static const struct {
+ const int perm;
+ const char c;
+ const wchar_t wc;
+} nfsv4_acl_flag_map[] = {
+ { ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, 'f', L'f' },
+ { ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, 'd', L'd' },
+ { ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, 'i', L'i' },
+ { ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, 'n', L'n' },
+ { ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, 'S', L'S' },
+ { ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, 'F', L'F' },
+ { ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, 'I', L'I' }
+};
+
+static const int nfsv4_acl_flag_map_size = (int)(sizeof(nfsv4_acl_flag_map) /
+ sizeof(nfsv4_acl_flag_map[0]));
+
void
archive_acl_clear(struct archive_acl *acl)
{
@@ -94,6 +147,7 @@ archive_acl_clear(struct archive_acl *acl)
acl->acl_text = NULL;
}
acl->acl_p = NULL;
+ acl->acl_types = 0;
acl->acl_state = 0; /* Not counting. */
}
@@ -279,23 +333,31 @@ acl_new_entry(struct archive_acl *acl,
acl->acl_text = NULL;
}
- /* If there's a matching entry already in the list, overwrite it. */
+ /*
+ * If there's a matching entry already in the list, overwrite it.
+ * NFSv4 entries may be repeated and are not overwritten.
+ *
+ * TODO: compare names of no id is provided (needs more rework)
+ */
ap = acl->acl_head;
aq = NULL;
while (ap != NULL) {
- if (ap->type == type && ap->tag == tag && ap->id == id) {
- ap->permset = permset;
- return (ap);
+ if (((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) &&
+ ap->type == type && ap->tag == tag && ap->id == id) {
+ if (id != -1 || (tag != ARCHIVE_ENTRY_ACL_USER &&
+ tag != ARCHIVE_ENTRY_ACL_GROUP)) {
+ ap->permset = permset;
+ return (ap);
+ }
}
aq = ap;
ap = ap->next;
}
/* Add a new entry to the end of the list. */
- ap = (struct archive_acl_entry *)malloc(sizeof(*ap));
+ ap = (struct archive_acl_entry *)calloc(1, sizeof(*ap));
if (ap == NULL)
return (NULL);
- memset(ap, 0, sizeof(*ap));
if (aq == NULL)
acl->acl_head = ap;
else
@@ -331,6 +393,15 @@ archive_acl_count(struct archive_acl *acl, int want_type)
}
/*
+ * Return a bitmask of stored ACL types in an ACL list
+ */
+int
+archive_acl_types(struct archive_acl *acl)
+{
+ return (acl->acl_types);
+}
+
+/*
* Prepare for reading entries from the ACL data. Returns a count
* of entries matching "want_type", or zero if there are no
* non-extended ACL entries of that type.
@@ -366,8 +437,8 @@ archive_acl_reset(struct archive_acl *acl, int want_type)
* standard permissions and include them in the returned list.
*/
int
-archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, int *type,
- int *permset, int *tag, int *id, const char **name)
+archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type,
+ int *type, int *permset, int *tag, int *id, const char **name)
{
*name = NULL;
*id = -1;
@@ -432,130 +503,273 @@ archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, int
}
/*
- * Generate a text version of the ACL. The flags parameter controls
- * the style of the generated ACL.
+ * Determine what type of ACL do we want
*/
-const wchar_t *
-archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags)
+static int
+archive_acl_text_want_type(struct archive_acl *acl, int flags)
{
- int count;
- size_t length;
- const wchar_t *wname;
- const wchar_t *prefix;
- wchar_t separator;
- struct archive_acl_entry *ap;
- int id, r;
- wchar_t *wp;
+ int want_type;
- if (acl->acl_text_w != NULL) {
- free (acl->acl_text_w);
- acl->acl_text_w = NULL;
+ /* Check if ACL is NFSv4 */
+ if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ /* NFSv4 should never mix with POSIX.1e */
+ if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0)
+ return (0);
+ else
+ return (ARCHIVE_ENTRY_ACL_TYPE_NFS4);
}
- separator = L',';
+ /* Now deal with POSIX.1e ACLs */
+
+ want_type = 0;
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
+ want_type |= ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
+ want_type |= ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+
+ /* By default we want both access and default ACLs */
+ if (want_type == 0)
+ return (ARCHIVE_ENTRY_ACL_TYPE_POSIX1E);
+
+ return (want_type);
+}
+
+/*
+ * Calculate ACL text string length
+ */
+static ssize_t
+archive_acl_text_len(struct archive_acl *acl, int want_type, int flags,
+ int wide, struct archive *a, struct archive_string_conv *sc) {
+ struct archive_acl_entry *ap;
+ const char *name;
+ const wchar_t *wname;
+ int count, idlen, tmp, r;
+ ssize_t length;
+ size_t len;
+
count = 0;
length = 0;
- ap = acl->acl_head;
- while (ap != NULL) {
- if ((ap->type & flags) != 0) {
- count++;
- if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) &&
- (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT))
- length += 8; /* "default:" */
- length += 5; /* tag name */
- length += 1; /* colon */
- r = archive_mstring_get_wcs(a, &ap->name, &wname);
- if (r == 0 && wname != NULL)
- length += wcslen(wname);
- else if (r < 0 && errno == ENOMEM)
- return (NULL);
- else
- length += sizeof(uid_t) * 3 + 1;
- length ++; /* colon */
+ for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
+ if ((ap->type & want_type) == 0)
+ continue;
+ /*
+ * Filemode-mapping ACL entries are stored exclusively in
+ * ap->mode so they should not be in the list
+ */
+ if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS)
+ && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ
+ || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ
+ || ap->tag == ARCHIVE_ENTRY_ACL_OTHER))
+ continue;
+ count++;
+ if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0
+ && (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
+ length += 8; /* "default:" */
+ switch (ap->tag) {
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ length += 6; /* "owner@" */
+ break;
+ }
+ /* FALLTHROUGH */
+ case ARCHIVE_ENTRY_ACL_USER:
+ case ARCHIVE_ENTRY_ACL_MASK:
+ length += 4; /* "user", "mask" */
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ length += 6; /* "group@" */
+ break;
+ }
+ /* FALLTHROUGH */
+ case ARCHIVE_ENTRY_ACL_GROUP:
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ length += 5; /* "group", "other" */
+ break;
+ case ARCHIVE_ENTRY_ACL_EVERYONE:
+ length += 9; /* "everyone@" */
+ break;
+ }
+ length += 1; /* colon after tag */
+ if (ap->tag == ARCHIVE_ENTRY_ACL_USER ||
+ ap->tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ if (wide) {
+ r = archive_mstring_get_wcs(a, &ap->name,
+ &wname);
+ if (r == 0 && wname != NULL)
+ length += wcslen(wname);
+ else if (r < 0 && errno == ENOMEM)
+ return (0);
+ else
+ length += sizeof(uid_t) * 3 + 1;
+ } else {
+ r = archive_mstring_get_mbs_l(&ap->name, &name,
+ &len, sc);
+ if (r != 0)
+ return (0);
+ if (len > 0 && name != NULL)
+ length += len;
+ else
+ length += sizeof(uid_t) * 3 + 1;
+ }
+ length += 1; /* colon after user or group name */
+ } else if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4)
+ length += 1; /* 2nd colon empty user,group or other */
+
+ if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0)
+ && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0)
+ && (ap->tag == ARCHIVE_ENTRY_ACL_OTHER
+ || ap->tag == ARCHIVE_ENTRY_ACL_MASK)) {
+ /* Solaris has no colon after other: and mask: */
+ length = length - 1;
+ }
+
+ if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ /* rwxpdDaARWcCos:fdinSFI:deny */
+ length += 27;
+ if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DENY) == 0)
+ length += 1; /* allow, alarm, audit */
+ } else
length += 3; /* rwx */
+
+ if ((ap->tag == ARCHIVE_ENTRY_ACL_USER ||
+ ap->tag == ARCHIVE_ENTRY_ACL_GROUP) &&
+ (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) {
length += 1; /* colon */
- length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1;
- length ++; /* newline */
+ /* ID digit count */
+ idlen = 1;
+ tmp = ap->id;
+ while (tmp > 9) {
+ tmp = tmp / 10;
+ idlen++;
+ }
+ length += idlen;
}
- ap = ap->next;
+ length ++; /* entry separator */
}
- if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) {
- length += 10; /* "user::rwx\n" */
- length += 11; /* "group::rwx\n" */
- length += 11; /* "other::rwx\n" */
- }
+ /* Add filemode-mapping access entries to the length */
+ if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+ if ((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) {
+ /* "user::rwx\ngroup::rwx\nother:rwx\n" */
+ length += 31;
+ } else {
+ /* "user::rwx\ngroup::rwx\nother::rwx\n" */
+ length += 32;
+ }
+ } else if (count == 0)
+ return (0);
+
+ /* The terminating character is included in count */
+ return (length);
+}
+
+/*
+ * Generate a wide text version of the ACL. The flags parameter controls
+ * the type and style of the generated ACL.
+ */
+wchar_t *
+archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags,
+ struct archive *a)
+{
+ int count;
+ ssize_t length;
+ size_t len;
+ const wchar_t *wname;
+ const wchar_t *prefix;
+ wchar_t separator;
+ struct archive_acl_entry *ap;
+ int id, r, want_type;
+ wchar_t *wp, *ws;
+
+ want_type = archive_acl_text_want_type(acl, flags);
+
+ /* Both NFSv4 and POSIX.1 types found */
+ if (want_type == 0)
+ return (NULL);
+
+ if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)
+ flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
+
+ length = archive_acl_text_len(acl, want_type, flags, 1, a, NULL);
- if (count == 0)
+ if (length == 0)
return (NULL);
+ if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA)
+ separator = L',';
+ else
+ separator = L'\n';
+
/* Now, allocate the string and actually populate it. */
- wp = acl->acl_text_w = (wchar_t *)malloc(length * sizeof(wchar_t));
- if (wp == NULL)
+ wp = ws = (wchar_t *)malloc(length * sizeof(wchar_t));
+ if (wp == NULL) {
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (NULL);
+ }
count = 0;
- if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
- append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL,
+
+ if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+ append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+ ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL,
acl->mode & 0700, -1);
- *wp++ = ',';
- append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL,
+ *wp++ = separator;
+ append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+ ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL,
acl->mode & 0070, -1);
- *wp++ = ',';
- append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL,
+ *wp++ = separator;
+ append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+ ARCHIVE_ENTRY_ACL_OTHER, flags, NULL,
acl->mode & 0007, -1);
count += 3;
-
- ap = acl->acl_head;
- while (ap != NULL) {
- if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
- r = archive_mstring_get_wcs(a, &ap->name, &wname);
- if (r == 0) {
- *wp++ = separator;
- if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
- id = ap->id;
- else
- id = -1;
- append_entry_w(&wp, NULL, ap->tag, wname,
- ap->permset, id);
- count++;
- } else if (r < 0 && errno == ENOMEM)
- return (NULL);
- }
- ap = ap->next;
- }
}
-
- if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) {
- if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT)
+ for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
+ if ((ap->type & want_type) == 0)
+ continue;
+ /*
+ * Filemode-mapping ACL entries are stored exclusively in
+ * ap->mode so they should not be in the list
+ */
+ if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS)
+ && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ
+ || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ
+ || ap->tag == ARCHIVE_ENTRY_ACL_OTHER))
+ continue;
+ if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT &&
+ (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
prefix = L"default:";
else
prefix = NULL;
- ap = acl->acl_head;
- count = 0;
- while (ap != NULL) {
- if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) {
- r = archive_mstring_get_wcs(a, &ap->name, &wname);
- if (r == 0) {
- if (count > 0)
- *wp++ = separator;
- if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
- id = ap->id;
- else
- id = -1;
- append_entry_w(&wp, prefix, ap->tag,
- wname, ap->permset, id);
- count ++;
- } else if (r < 0 && errno == ENOMEM)
- return (NULL);
- }
- ap = ap->next;
- }
+ r = archive_mstring_get_wcs(a, &ap->name, &wname);
+ if (r == 0) {
+ if (count > 0)
+ *wp++ = separator;
+ if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
+ id = ap->id;
+ else
+ id = -1;
+ append_entry_w(&wp, prefix, ap->type, ap->tag, flags,
+ wname, ap->permset, id);
+ count++;
+ } else if (r < 0 && errno == ENOMEM)
+ return (NULL);
}
- return (acl->acl_text_w);
-}
+ /* Add terminating character */
+ *wp++ = L'\0';
+
+ len = wcslen(ws);
+ if ((ssize_t)len > (length - 1))
+ __archive_errx(1, "Buffer overrun");
+
+ if (text_len != NULL)
+ *text_len = len;
+
+ return (ws);
+}
static void
append_id_w(wchar_t **wp, int id)
@@ -568,9 +782,11 @@ append_id_w(wchar_t **wp, int id)
}
static void
-append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
- const wchar_t *wname, int perm, int id)
+append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
+ int tag, int flags, const wchar_t *wname, int perm, int id)
{
+ int i;
+
if (prefix != NULL) {
wcscpy(*wp, prefix);
*wp += wcslen(*wp);
@@ -579,6 +795,10 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
case ARCHIVE_ENTRY_ACL_USER_OBJ:
wname = NULL;
id = -1;
+ if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ wcscpy(*wp, L"owner@");
+ break;
+ }
/* FALLTHROUGH */
case ARCHIVE_ENTRY_ACL_USER:
wcscpy(*wp, L"user");
@@ -586,6 +806,10 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
wname = NULL;
id = -1;
+ if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ wcscpy(*wp, L"group@");
+ break;
+ }
/* FALLTHROUGH */
case ARCHIVE_ENTRY_ACL_GROUP:
wcscpy(*wp, L"group");
@@ -600,153 +824,184 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
wname = NULL;
id = -1;
break;
+ case ARCHIVE_ENTRY_ACL_EVERYONE:
+ wcscpy(*wp, L"everyone@");
+ wname = NULL;
+ id = -1;
+ break;
}
*wp += wcslen(*wp);
*(*wp)++ = L':';
- if (wname != NULL) {
- wcscpy(*wp, wname);
+ if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) ||
+ tag == ARCHIVE_ENTRY_ACL_USER ||
+ tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ if (wname != NULL) {
+ wcscpy(*wp, wname);
+ *wp += wcslen(*wp);
+ } else if (tag == ARCHIVE_ENTRY_ACL_USER
+ || tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ append_id_w(wp, id);
+ if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0)
+ id = -1;
+ }
+ /* Solaris style has no second colon after other and mask */
+ if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0)
+ || (tag != ARCHIVE_ENTRY_ACL_OTHER
+ && tag != ARCHIVE_ENTRY_ACL_MASK))
+ *(*wp)++ = L':';
+ }
+ if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
+ /* POSIX.1e ACL perms */
+ *(*wp)++ = (perm & 0444) ? L'r' : L'-';
+ *(*wp)++ = (perm & 0222) ? L'w' : L'-';
+ *(*wp)++ = (perm & 0111) ? L'x' : L'-';
+ } else {
+ /* NFSv4 ACL perms */
+ for (i = 0; i < nfsv4_acl_perm_map_size; i++) {
+ if (perm & nfsv4_acl_perm_map[i].perm)
+ *(*wp)++ = nfsv4_acl_perm_map[i].wc;
+ else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
+ *(*wp)++ = L'-';
+ }
+ *(*wp)++ = L':';
+ for (i = 0; i < nfsv4_acl_flag_map_size; i++) {
+ if (perm & nfsv4_acl_flag_map[i].perm)
+ *(*wp)++ = nfsv4_acl_flag_map[i].wc;
+ else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
+ *(*wp)++ = L'-';
+ }
+ *(*wp)++ = L':';
+ switch (type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
+ wcscpy(*wp, L"allow");
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DENY:
+ wcscpy(*wp, L"deny");
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
+ wcscpy(*wp, L"audit");
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
+ wcscpy(*wp, L"alarm");
+ break;
+ default:
+ break;
+ }
*wp += wcslen(*wp);
- } else if (tag == ARCHIVE_ENTRY_ACL_USER
- || tag == ARCHIVE_ENTRY_ACL_GROUP) {
- append_id_w(wp, id);
- id = -1;
}
- *(*wp)++ = L':';
- *(*wp)++ = (perm & 0444) ? L'r' : L'-';
- *(*wp)++ = (perm & 0222) ? L'w' : L'-';
- *(*wp)++ = (perm & 0111) ? L'x' : L'-';
if (id != -1) {
*(*wp)++ = L':';
append_id_w(wp, id);
}
- **wp = L'\0';
}
-int
-archive_acl_text_l(struct archive_acl *acl, int flags,
- const char **acl_text, size_t *acl_text_len,
+/*
+ * Generate a text version of the ACL. The flags parameter controls
+ * the type and style of the generated ACL.
+ */
+char *
+archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags,
struct archive_string_conv *sc)
{
int count;
- size_t length;
+ ssize_t length;
+ size_t len;
const char *name;
const char *prefix;
char separator;
struct archive_acl_entry *ap;
- size_t len;
- int id, r;
- char *p;
+ int id, r, want_type;
+ char *p, *s;
- if (acl->acl_text != NULL) {
- free (acl->acl_text);
- acl->acl_text = NULL;
- }
+ want_type = archive_acl_text_want_type(acl, flags);
- *acl_text = NULL;
- if (acl_text_len != NULL)
- *acl_text_len = 0;
- separator = ',';
- count = 0;
- length = 0;
- ap = acl->acl_head;
- while (ap != NULL) {
- if ((ap->type & flags) != 0) {
- count++;
- if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) &&
- (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT))
- length += 8; /* "default:" */
- length += 5; /* tag name */
- length += 1; /* colon */
- r = archive_mstring_get_mbs_l(
- &ap->name, &name, &len, sc);
- if (r != 0)
- return (-1);
- if (len > 0 && name != NULL)
- length += len;
- else
- length += sizeof(uid_t) * 3 + 1;
- length ++; /* colon */
- length += 3; /* rwx */
- length += 1; /* colon */
- length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1;
- length ++; /* newline */
- }
- ap = ap->next;
- }
+ /* Both NFSv4 and POSIX.1 types found */
+ if (want_type == 0)
+ return (NULL);
- if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) {
- length += 10; /* "user::rwx\n" */
- length += 11; /* "group::rwx\n" */
- length += 11; /* "other::rwx\n" */
- }
+ if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)
+ flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
- if (count == 0)
- return (0);
+ length = archive_acl_text_len(acl, want_type, flags, 0, NULL, sc);
+
+ if (length == 0)
+ return (NULL);
+
+ if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA)
+ separator = ',';
+ else
+ separator = '\n';
/* Now, allocate the string and actually populate it. */
- p = acl->acl_text = (char *)malloc(length);
- if (p == NULL)
- return (-1);
+ p = s = (char *)malloc(length * sizeof(char));
+ if (p == NULL) {
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
+ return (NULL);
+ }
count = 0;
- if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
- append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL,
+
+ if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+ append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+ ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL,
acl->mode & 0700, -1);
- *p++ = ',';
- append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL,
+ *p++ = separator;
+ append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+ ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL,
acl->mode & 0070, -1);
- *p++ = ',';
- append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL,
+ *p++ = separator;
+ append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+ ARCHIVE_ENTRY_ACL_OTHER, flags, NULL,
acl->mode & 0007, -1);
count += 3;
-
- for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
- if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) == 0)
- continue;
- r = archive_mstring_get_mbs_l(
- &ap->name, &name, &len, sc);
- if (r != 0)
- return (-1);
- *p++ = separator;
- if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
- id = ap->id;
- else
- id = -1;
- append_entry(&p, NULL, ap->tag, name,
- ap->permset, id);
- count++;
- }
}
-
- if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) {
- if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT)
+ for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
+ if ((ap->type & want_type) == 0)
+ continue;
+ /*
+ * Filemode-mapping ACL entries are stored exclusively in
+ * ap->mode so they should not be in the list
+ */
+ if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS)
+ && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ
+ || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ
+ || ap->tag == ARCHIVE_ENTRY_ACL_OTHER))
+ continue;
+ if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT &&
+ (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
prefix = "default:";
else
prefix = NULL;
- count = 0;
- for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
- if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) == 0)
- continue;
- r = archive_mstring_get_mbs_l(
- &ap->name, &name, &len, sc);
- if (r != 0)
- return (-1);
- if (count > 0)
- *p++ = separator;
- if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
- id = ap->id;
- else
- id = -1;
- append_entry(&p, prefix, ap->tag,
- name, ap->permset, id);
- count ++;
+ r = archive_mstring_get_mbs_l(
+ &ap->name, &name, &len, sc);
+ if (r != 0)
+ return (NULL);
+ if (count > 0)
+ *p++ = separator;
+ if (name == NULL ||
+ (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)) {
+ id = ap->id;
+ } else {
+ id = -1;
}
+ append_entry(&p, prefix, ap->type, ap->tag, flags, name,
+ ap->permset, id);
+ count++;
}
- *acl_text = acl->acl_text;
- if (acl_text_len != NULL)
- *acl_text_len = strlen(acl->acl_text);
- return (0);
+ /* Add terminating character */
+ *p++ = '\0';
+
+ len = strlen(s);
+
+ if ((ssize_t)len > (length - 1))
+ __archive_errx(1, "Buffer overrun");
+
+ if (text_len != NULL)
+ *text_len = len;
+
+ return (s);
}
static void
@@ -760,9 +1015,11 @@ append_id(char **p, int id)
}
static void
-append_entry(char **p, const char *prefix, int tag,
- const char *name, int perm, int id)
+append_entry(char **p, const char *prefix, int type,
+ int tag, int flags, const char *name, int perm, int id)
{
+ int i;
+
if (prefix != NULL) {
strcpy(*p, prefix);
*p += strlen(*p);
@@ -771,6 +1028,10 @@ append_entry(char **p, const char *prefix, int tag,
case ARCHIVE_ENTRY_ACL_USER_OBJ:
name = NULL;
id = -1;
+ if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ strcpy(*p, "owner@");
+ break;
+ }
/* FALLTHROUGH */
case ARCHIVE_ENTRY_ACL_USER:
strcpy(*p, "user");
@@ -778,6 +1039,10 @@ append_entry(char **p, const char *prefix, int tag,
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
name = NULL;
id = -1;
+ if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ strcpy(*p, "group@");
+ break;
+ }
/* FALLTHROUGH */
case ARCHIVE_ENTRY_ACL_GROUP:
strcpy(*p, "group");
@@ -792,48 +1057,120 @@ append_entry(char **p, const char *prefix, int tag,
name = NULL;
id = -1;
break;
+ case ARCHIVE_ENTRY_ACL_EVERYONE:
+ strcpy(*p, "everyone@");
+ name = NULL;
+ id = -1;
+ break;
}
*p += strlen(*p);
*(*p)++ = ':';
- if (name != NULL) {
- strcpy(*p, name);
+ if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) ||
+ tag == ARCHIVE_ENTRY_ACL_USER ||
+ tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ if (name != NULL) {
+ strcpy(*p, name);
+ *p += strlen(*p);
+ } else if (tag == ARCHIVE_ENTRY_ACL_USER
+ || tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ append_id(p, id);
+ if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0)
+ id = -1;
+ }
+ /* Solaris style has no second colon after other and mask */
+ if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0)
+ || (tag != ARCHIVE_ENTRY_ACL_OTHER
+ && tag != ARCHIVE_ENTRY_ACL_MASK))
+ *(*p)++ = ':';
+ }
+ if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
+ /* POSIX.1e ACL perms */
+ *(*p)++ = (perm & 0444) ? 'r' : '-';
+ *(*p)++ = (perm & 0222) ? 'w' : '-';
+ *(*p)++ = (perm & 0111) ? 'x' : '-';
+ } else {
+ /* NFSv4 ACL perms */
+ for (i = 0; i < nfsv4_acl_perm_map_size; i++) {
+ if (perm & nfsv4_acl_perm_map[i].perm)
+ *(*p)++ = nfsv4_acl_perm_map[i].c;
+ else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
+ *(*p)++ = '-';
+ }
+ *(*p)++ = ':';
+ for (i = 0; i < nfsv4_acl_flag_map_size; i++) {
+ if (perm & nfsv4_acl_flag_map[i].perm)
+ *(*p)++ = nfsv4_acl_flag_map[i].c;
+ else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
+ *(*p)++ = '-';
+ }
+ *(*p)++ = ':';
+ switch (type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
+ strcpy(*p, "allow");
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DENY:
+ strcpy(*p, "deny");
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
+ strcpy(*p, "audit");
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
+ strcpy(*p, "alarm");
+ break;
+ }
*p += strlen(*p);
- } else if (tag == ARCHIVE_ENTRY_ACL_USER
- || tag == ARCHIVE_ENTRY_ACL_GROUP) {
- append_id(p, id);
- id = -1;
}
- *(*p)++ = ':';
- *(*p)++ = (perm & 0444) ? 'r' : '-';
- *(*p)++ = (perm & 0222) ? 'w' : '-';
- *(*p)++ = (perm & 0111) ? 'x' : '-';
if (id != -1) {
*(*p)++ = ':';
append_id(p, id);
}
- **p = '\0';
}
/*
- * Parse a textual ACL. This automatically recognizes and supports
- * extensions described above. The 'type' argument is used to
- * indicate the type that should be used for any entries not
- * explicitly marked as "default:".
+ * Parse a wide ACL text string.
+ *
+ * The want_type argument may be one of the following:
+ * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - text is a POSIX.1e ACL of type ACCESS
+ * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - text is a POSIX.1e ACL of type DEFAULT
+ * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - text is as a NFSv4 ACL
+ *
+ * POSIX.1e ACL entries prefixed with "default:" are treated as
+ * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is ARCHIVE_ENTRY_ACL_TYPE_NFS4
*/
int
-archive_acl_parse_w(struct archive_acl *acl,
- const wchar_t *text, int default_type)
+archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text,
+ int want_type)
{
struct {
const wchar_t *start;
const wchar_t *end;
- } field[4], name;
+ } field[6], name;
+
+ const wchar_t *s, *st;
- int fields, n;
- int type, tag, permset, id;
+ int numfields, fields, n, r, sol, ret;
+ int type, types, tag, permset, id;
+ size_t len;
wchar_t sep;
- while (text != NULL && *text != L'\0') {
+ ret = ARCHIVE_OK;
+ types = 0;
+
+ switch (want_type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
+ want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+ case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+ numfields = 5;
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
+ numfields = 6;
+ break;
+ default:
+ return (ARCHIVE_FATAL);
+ }
+
+ while (text != NULL && *text != L'\0') {
/*
* Parse the fields out of the next entry,
* advance 'text' to start of next entry.
@@ -842,7 +1179,7 @@ archive_acl_parse_w(struct archive_acl *acl,
do {
const wchar_t *start, *end;
next_field_w(&text, &start, &end, &sep);
- if (fields < 4) {
+ if (fields < numfields) {
field[fields].start = start;
field[fields].end = end;
}
@@ -850,78 +1187,210 @@ archive_acl_parse_w(struct archive_acl *acl,
} while (sep == L':');
/* Set remaining fields to blank. */
- for (n = fields; n < 4; ++n)
+ for (n = fields; n < numfields; ++n)
field[n].start = field[n].end = NULL;
- /* Check for a numeric ID in field 1 or 3. */
- id = -1;
- isint_w(field[1].start, field[1].end, &id);
- /* Field 3 is optional. */
- if (id == -1 && fields > 3)
- isint_w(field[3].start, field[3].end, &id);
-
- /*
- * Solaris extension: "defaultuser::rwx" is the
- * default ACL corresponding to "user::rwx", etc.
- */
- if (field[0].end - field[0].start > 7
- && wmemcmp(field[0].start, L"default", 7) == 0) {
- type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
- field[0].start += 7;
- } else
- type = default_type;
+ if (field[0].start != NULL && *(field[0].start) == L'#') {
+ /* Comment, skip entry */
+ continue;
+ }
+ n = 0;
+ sol = 0;
+ id = -1;
+ permset = 0;
name.start = name.end = NULL;
- if (prefix_w(field[0].start, field[0].end, L"user")) {
- if (!ismode_w(field[2].start, field[2].end, &permset))
- return (ARCHIVE_WARN);
- if (id != -1 || field[1].start < field[1].end) {
- tag = ARCHIVE_ENTRY_ACL_USER;
- name = field[1];
+
+ if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ /* POSIX.1e ACLs */
+ /*
+ * Default keyword "default:user::rwx"
+ * if found, we have one more field
+ *
+ * We also support old Solaris extension:
+ * "defaultuser::rwx" is the default ACL corresponding
+ * to "user::rwx", etc. valid only for first field
+ */
+ s = field[0].start;
+ len = field[0].end - field[0].start;
+ if (*s == L'd' && (len == 1 || (len >= 7
+ && wmemcmp((s + 1), L"efault", 6) == 0))) {
+ type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+ if (len > 7)
+ field[0].start += 7;
+ else
+ n = 1;
} else
- tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
- } else if (prefix_w(field[0].start, field[0].end, L"group")) {
- if (!ismode_w(field[2].start, field[2].end, &permset))
- return (ARCHIVE_WARN);
- if (id != -1 || field[1].start < field[1].end) {
- tag = ARCHIVE_ENTRY_ACL_GROUP;
+ type = want_type;
+
+ /* Check for a numeric ID in field n+1 or n+3. */
+ isint_w(field[n + 1].start, field[n + 1].end, &id);
+ /* Field n+3 is optional. */
+ if (id == -1 && fields > n+3)
+ isint_w(field[n + 3].start, field[n + 3].end,
+ &id);
+
+ tag = 0;
+ s = field[n].start;
+ st = field[n].start + 1;
+ len = field[n].end - field[n].start;
+
+ switch (*s) {
+ case L'u':
+ if (len == 1 || (len == 4
+ && wmemcmp(st, L"ser", 3) == 0))
+ tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ break;
+ case L'g':
+ if (len == 1 || (len == 5
+ && wmemcmp(st, L"roup", 4) == 0))
+ tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ break;
+ case L'o':
+ if (len == 1 || (len == 5
+ && wmemcmp(st, L"ther", 4) == 0))
+ tag = ARCHIVE_ENTRY_ACL_OTHER;
+ break;
+ case L'm':
+ if (len == 1 || (len == 4
+ && wmemcmp(st, L"ask", 3) == 0))
+ tag = ARCHIVE_ENTRY_ACL_MASK;
+ break;
+ default:
+ break;
+ }
+
+ switch (tag) {
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ case ARCHIVE_ENTRY_ACL_MASK:
+ if (fields == (n + 2)
+ && field[n + 1].start < field[n + 1].end
+ && ismode_w(field[n + 1].start,
+ field[n + 1].end, &permset)) {
+ /* This is Solaris-style "other:rwx" */
+ sol = 1;
+ } else if (fields == (n + 3) &&
+ field[n + 1].start < field[n + 1].end) {
+ /* Invalid mask or other field */
+ ret = ARCHIVE_WARN;
+ continue;
+ }
+ break;
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ if (id != -1 ||
+ field[n + 1].start < field[n + 1].end) {
+ name = field[n + 1];
+ if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
+ tag = ARCHIVE_ENTRY_ACL_USER;
+ else
+ tag = ARCHIVE_ENTRY_ACL_GROUP;
+ }
+ break;
+ default:
+ /* Invalid tag, skip entry */
+ ret = ARCHIVE_WARN;
+ continue;
+ }
+
+ /*
+ * Without "default:" we expect mode in field 2
+ * Exception: Solaris other and mask fields
+ */
+ if (permset == 0 && !ismode_w(field[n + 2 - sol].start,
+ field[n + 2 - sol].end, &permset)) {
+ /* Invalid mode, skip entry */
+ ret = ARCHIVE_WARN;
+ continue;
+ }
+ } else {
+ /* NFS4 ACLs */
+ s = field[0].start;
+ len = field[0].end - field[0].start;
+ tag = 0;
+
+ switch (len) {
+ case 4:
+ if (wmemcmp(s, L"user", 4) == 0)
+ tag = ARCHIVE_ENTRY_ACL_USER;
+ break;
+ case 5:
+ if (wmemcmp(s, L"group", 5) == 0)
+ tag = ARCHIVE_ENTRY_ACL_GROUP;
+ break;
+ case 6:
+ if (wmemcmp(s, L"owner@", 6) == 0)
+ tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ else if (wmemcmp(s, L"group@", len) == 0)
+ tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ break;
+ case 9:
+ if (wmemcmp(s, L"everyone@", 9) == 0)
+ tag = ARCHIVE_ENTRY_ACL_EVERYONE;
+ default:
+ break;
+ }
+
+ if (tag == 0) {
+ /* Invalid tag, skip entry */
+ ret = ARCHIVE_WARN;
+ continue;
+ } else if (tag == ARCHIVE_ENTRY_ACL_USER ||
+ tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ n = 1;
name = field[1];
+ isint_w(name.start, name.end, &id);
} else
- tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
- } else if (prefix_w(field[0].start, field[0].end, L"other")) {
- if (fields == 2
- && field[1].start < field[1].end
- && ismode_w(field[1].start, field[1].end, &permset)) {
- /* This is Solaris-style "other:rwx" */
- } else if (fields == 3
- && field[1].start == field[1].end
- && field[2].start < field[2].end
- && ismode_w(field[2].start, field[2].end, &permset)) {
- /* This is FreeBSD-style "other::rwx" */
- } else
- return (ARCHIVE_WARN);
- tag = ARCHIVE_ENTRY_ACL_OTHER;
- } else if (prefix_w(field[0].start, field[0].end, L"mask")) {
- if (fields == 2
- && field[1].start < field[1].end
- && ismode_w(field[1].start, field[1].end, &permset)) {
- /* This is Solaris-style "mask:rwx" */
- } else if (fields == 3
- && field[1].start == field[1].end
- && field[2].start < field[2].end
- && ismode_w(field[2].start, field[2].end, &permset)) {
- /* This is FreeBSD-style "mask::rwx" */
- } else
- return (ARCHIVE_WARN);
- tag = ARCHIVE_ENTRY_ACL_MASK;
- } else
- return (ARCHIVE_WARN);
+ n = 0;
+
+ if (!is_nfs4_perms_w(field[1 + n].start,
+ field[1 + n].end, &permset)) {
+ /* Invalid NFSv4 perms, skip entry */
+ ret = ARCHIVE_WARN;
+ continue;
+ }
+ if (!is_nfs4_flags_w(field[2 + n].start,
+ field[2 + n].end, &permset)) {
+ /* Invalid NFSv4 flags, skip entry */
+ ret = ARCHIVE_WARN;
+ continue;
+ }
+ s = field[3 + n].start;
+ len = field[3 + n].end - field[3 + n].start;
+ type = 0;
+ if (len == 4) {
+ if (wmemcmp(s, L"deny", 4) == 0)
+ type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+ } else if (len == 5) {
+ if (wmemcmp(s, L"allow", 5) == 0)
+ type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+ else if (wmemcmp(s, L"audit", 5) == 0)
+ type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
+ else if (wmemcmp(s, L"alarm", 5) == 0)
+ type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
+ }
+ if (type == 0) {
+ /* Invalid entry type, skip entry */
+ ret = ARCHIVE_WARN;
+ continue;
+ }
+ isint_w(field[4 + n].start, field[4 + n].end, &id);
+ }
/* Add entry to the internal list. */
- archive_acl_add_entry_w_len(acl, type, permset,
+ r = archive_acl_add_entry_w_len(acl, type, permset,
tag, id, name.start, name.end - name.start);
+ if (r < ARCHIVE_WARN)
+ return (r);
+ if (r != ARCHIVE_OK)
+ ret = ARCHIVE_WARN;
+ types |= type;
}
- return (ARCHIVE_OK);
+
+ /* Reset ACL */
+ archive_acl_reset(acl, types);
+
+ return (ret);
}
/*
@@ -967,16 +1436,122 @@ ismode_w(const wchar_t *start, const wchar_t *end, int *permset)
*permset = 0;
while (p < end) {
switch (*p++) {
- case 'r': case 'R':
+ case L'r': case L'R':
*permset |= ARCHIVE_ENTRY_ACL_READ;
break;
- case 'w': case 'W':
+ case L'w': case L'W':
*permset |= ARCHIVE_ENTRY_ACL_WRITE;
break;
- case 'x': case 'X':
+ case L'x': case L'X':
*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
break;
- case '-':
+ case L'-':
+ break;
+ default:
+ return (0);
+ }
+ }
+ return (1);
+}
+
+/*
+ * Parse a string as a NFS4 ACL permission field.
+ * Returns true if the string is non-empty and consists only of NFS4 ACL
+ * permission characters, false otherwise
+ */
+static int
+is_nfs4_perms_w(const wchar_t *start, const wchar_t *end, int *permset)
+{
+ const wchar_t *p = start;
+
+ while (p < end) {
+ switch (*p++) {
+ case L'r':
+ *permset |= ARCHIVE_ENTRY_ACL_READ_DATA;
+ break;
+ case L'w':
+ *permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA;
+ break;
+ case L'x':
+ *permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
+ break;
+ case L'p':
+ *permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA;
+ break;
+ case L'D':
+ *permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD;
+ break;
+ case L'd':
+ *permset |= ARCHIVE_ENTRY_ACL_DELETE;
+ break;
+ case L'a':
+ *permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES;
+ break;
+ case L'A':
+ *permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES;
+ break;
+ case L'R':
+ *permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS;
+ break;
+ case L'W':
+ *permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS;
+ break;
+ case L'c':
+ *permset |= ARCHIVE_ENTRY_ACL_READ_ACL;
+ break;
+ case L'C':
+ *permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL;
+ break;
+ case L'o':
+ *permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER;
+ break;
+ case L's':
+ *permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
+ break;
+ case L'-':
+ break;
+ default:
+ return(0);
+ }
+ }
+ return (1);
+}
+
+/*
+ * Parse a string as a NFS4 ACL flags field.
+ * Returns true if the string is non-empty and consists only of NFS4 ACL
+ * flag characters, false otherwise
+ */
+static int
+is_nfs4_flags_w(const wchar_t *start, const wchar_t *end, int *permset)
+{
+ const wchar_t *p = start;
+
+ while (p < end) {
+ switch(*p++) {
+ case L'f':
+ *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT;
+ break;
+ case L'd':
+ *permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT;
+ break;
+ case L'i':
+ *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY;
+ break;
+ case L'n':
+ *permset |=
+ ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT;
+ break;
+ case L'S':
+ *permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS;
+ break;
+ case L'F':
+ *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS;
+ break;
+ case L'I':
+ *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED;
+ break;
+ case L'-':
break;
default:
return (0);
@@ -1023,46 +1598,48 @@ next_field_w(const wchar_t **wp, const wchar_t **start,
}
/*
- * Return true if the characters [start...end) are a prefix of 'test'.
- * This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc.
- */
-static int
-prefix_w(const wchar_t *start, const wchar_t *end, const wchar_t *test)
-{
- if (start == end)
- return (0);
-
- if (*start++ != *test++)
- return (0);
-
- while (start < end && *start++ == *test++)
- ;
-
- if (start < end)
- return (0);
-
- return (1);
-}
-
-/*
- * Parse a textual ACL. This automatically recognizes and supports
- * extensions described above. The 'type' argument is used to
- * indicate the type that should be used for any entries not
- * explicitly marked as "default:".
+ * Parse an ACL text string.
+ *
+ * The want_type argument may be one of the following:
+ * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - text is a POSIX.1e ACL of type ACCESS
+ * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - text is a POSIX.1e ACL of type DEFAULT
+ * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - text is as a NFSv4 ACL
+ *
+ * POSIX.1e ACL entries prefixed with "default:" are treated as
+ * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is ARCHIVE_ENTRY_ACL_TYPE_NFS4
*/
int
-archive_acl_parse_l(struct archive_acl *acl,
- const char *text, int default_type, struct archive_string_conv *sc)
+archive_acl_from_text_l(struct archive_acl *acl, const char *text,
+ int want_type, struct archive_string_conv *sc)
{
struct {
const char *start;
const char *end;
- } field[4], name;
+ } field[6], name;
- int fields, n, r, ret = ARCHIVE_OK;
- int type, tag, permset, id;
+ const char *s, *st;
+ int numfields, fields, n, r, sol, ret;
+ int type, types, tag, permset, id;
+ size_t len;
char sep;
+ switch (want_type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
+ want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+ case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+ numfields = 5;
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
+ numfields = 6;
+ break;
+ default:
+ return (ARCHIVE_FATAL);
+ }
+
+ ret = ARCHIVE_OK;
+ types = 0;
+
while (text != NULL && *text != '\0') {
/*
* Parse the fields out of the next entry,
@@ -1072,7 +1649,7 @@ archive_acl_parse_l(struct archive_acl *acl,
do {
const char *start, *end;
next_field(&text, &start, &end, &sep);
- if (fields < 4) {
+ if (fields < numfields) {
field[fields].start = start;
field[fields].end = end;
}
@@ -1080,72 +1657,197 @@ archive_acl_parse_l(struct archive_acl *acl,
} while (sep == ':');
/* Set remaining fields to blank. */
- for (n = fields; n < 4; ++n)
+ for (n = fields; n < numfields; ++n)
field[n].start = field[n].end = NULL;
- /* Check for a numeric ID in field 1 or 3. */
- id = -1;
- isint(field[1].start, field[1].end, &id);
- /* Field 3 is optional. */
- if (id == -1 && fields > 3)
- isint(field[3].start, field[3].end, &id);
-
- /*
- * Solaris extension: "defaultuser::rwx" is the
- * default ACL corresponding to "user::rwx", etc.
- */
- if (field[0].end - field[0].start > 7
- && memcmp(field[0].start, "default", 7) == 0) {
- type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
- field[0].start += 7;
- } else
- type = default_type;
+ if (field[0].start != NULL && *(field[0].start) == '#') {
+ /* Comment, skip entry */
+ continue;
+ }
+ n = 0;
+ sol = 0;
+ id = -1;
+ permset = 0;
name.start = name.end = NULL;
- if (prefix_c(field[0].start, field[0].end, "user")) {
- if (!ismode(field[2].start, field[2].end, &permset))
- return (ARCHIVE_WARN);
- if (id != -1 || field[1].start < field[1].end) {
- tag = ARCHIVE_ENTRY_ACL_USER;
- name = field[1];
+
+ if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ /* POSIX.1e ACLs */
+ /*
+ * Default keyword "default:user::rwx"
+ * if found, we have one more field
+ *
+ * We also support old Solaris extension:
+ * "defaultuser::rwx" is the default ACL corresponding
+ * to "user::rwx", etc. valid only for first field
+ */
+ s = field[0].start;
+ len = field[0].end - field[0].start;
+ if (*s == 'd' && (len == 1 || (len >= 7
+ && memcmp((s + 1), "efault", 6) == 0))) {
+ type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+ if (len > 7)
+ field[0].start += 7;
+ else
+ n = 1;
} else
- tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
- } else if (prefix_c(field[0].start, field[0].end, "group")) {
- if (!ismode(field[2].start, field[2].end, &permset))
- return (ARCHIVE_WARN);
- if (id != -1 || field[1].start < field[1].end) {
- tag = ARCHIVE_ENTRY_ACL_GROUP;
+ type = want_type;
+
+ /* Check for a numeric ID in field n+1 or n+3. */
+ isint(field[n + 1].start, field[n + 1].end, &id);
+ /* Field n+3 is optional. */
+ if (id == -1 && fields > (n + 3))
+ isint(field[n + 3].start, field[n + 3].end,
+ &id);
+
+ tag = 0;
+ s = field[n].start;
+ st = field[n].start + 1;
+ len = field[n].end - field[n].start;
+
+ switch (*s) {
+ case 'u':
+ if (len == 1 || (len == 4
+ && memcmp(st, "ser", 3) == 0))
+ tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ break;
+ case 'g':
+ if (len == 1 || (len == 5
+ && memcmp(st, "roup", 4) == 0))
+ tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ break;
+ case 'o':
+ if (len == 1 || (len == 5
+ && memcmp(st, "ther", 4) == 0))
+ tag = ARCHIVE_ENTRY_ACL_OTHER;
+ break;
+ case 'm':
+ if (len == 1 || (len == 4
+ && memcmp(st, "ask", 3) == 0))
+ tag = ARCHIVE_ENTRY_ACL_MASK;
+ break;
+ default:
+ break;
+ }
+
+ switch (tag) {
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ case ARCHIVE_ENTRY_ACL_MASK:
+ if (fields == (n + 2)
+ && field[n + 1].start < field[n + 1].end
+ && ismode(field[n + 1].start,
+ field[n + 1].end, &permset)) {
+ /* This is Solaris-style "other:rwx" */
+ sol = 1;
+ } else if (fields == (n + 3) &&
+ field[n + 1].start < field[n + 1].end) {
+ /* Invalid mask or other field */
+ ret = ARCHIVE_WARN;
+ continue;
+ }
+ break;
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ if (id != -1 ||
+ field[n + 1].start < field[n + 1].end) {
+ name = field[n + 1];
+ if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
+ tag = ARCHIVE_ENTRY_ACL_USER;
+ else
+ tag = ARCHIVE_ENTRY_ACL_GROUP;
+ }
+ break;
+ default:
+ /* Invalid tag, skip entry */
+ ret = ARCHIVE_WARN;
+ continue;
+ }
+
+ /*
+ * Without "default:" we expect mode in field 3
+ * Exception: Solaris other and mask fields
+ */
+ if (permset == 0 && !ismode(field[n + 2 - sol].start,
+ field[n + 2 - sol].end, &permset)) {
+ /* Invalid mode, skip entry */
+ ret = ARCHIVE_WARN;
+ continue;
+ }
+ } else {
+ /* NFS4 ACLs */
+ s = field[0].start;
+ len = field[0].end - field[0].start;
+ tag = 0;
+
+ switch (len) {
+ case 4:
+ if (memcmp(s, "user", 4) == 0)
+ tag = ARCHIVE_ENTRY_ACL_USER;
+ break;
+ case 5:
+ if (memcmp(s, "group", 5) == 0)
+ tag = ARCHIVE_ENTRY_ACL_GROUP;
+ break;
+ case 6:
+ if (memcmp(s, "owner@", 6) == 0)
+ tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ else if (memcmp(s, "group@", 6) == 0)
+ tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ break;
+ case 9:
+ if (memcmp(s, "everyone@", 9) == 0)
+ tag = ARCHIVE_ENTRY_ACL_EVERYONE;
+ break;
+ default:
+ break;
+ }
+
+ if (tag == 0) {
+ /* Invalid tag, skip entry */
+ ret = ARCHIVE_WARN;
+ continue;
+ } else if (tag == ARCHIVE_ENTRY_ACL_USER ||
+ tag == ARCHIVE_ENTRY_ACL_GROUP) {
+ n = 1;
name = field[1];
+ isint(name.start, name.end, &id);
} else
- tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
- } else if (prefix_c(field[0].start, field[0].end, "other")) {
- if (fields == 2
- && field[1].start < field[1].end
- && ismode(field[1].start, field[1].end, &permset)) {
- /* This is Solaris-style "other:rwx" */
- } else if (fields == 3
- && field[1].start == field[1].end
- && field[2].start < field[2].end
- && ismode(field[2].start, field[2].end, &permset)) {
- /* This is FreeBSD-style "other::rwx" */
- } else
- return (ARCHIVE_WARN);
- tag = ARCHIVE_ENTRY_ACL_OTHER;
- } else if (prefix_c(field[0].start, field[0].end, "mask")) {
- if (fields == 2
- && field[1].start < field[1].end
- && ismode(field[1].start, field[1].end, &permset)) {
- /* This is Solaris-style "mask:rwx" */
- } else if (fields == 3
- && field[1].start == field[1].end
- && field[2].start < field[2].end
- && ismode(field[2].start, field[2].end, &permset)) {
- /* This is FreeBSD-style "mask::rwx" */
- } else
- return (ARCHIVE_WARN);
- tag = ARCHIVE_ENTRY_ACL_MASK;
- } else
- return (ARCHIVE_WARN);
+ n = 0;
+
+ if (!is_nfs4_perms(field[1 + n].start,
+ field[1 + n].end, &permset)) {
+ /* Invalid NFSv4 perms, skip entry */
+ ret = ARCHIVE_WARN;
+ continue;
+ }
+ if (!is_nfs4_flags(field[2 + n].start,
+ field[2 + n].end, &permset)) {
+ /* Invalid NFSv4 flags, skip entry */
+ ret = ARCHIVE_WARN;
+ continue;
+ }
+ s = field[3 + n].start;
+ len = field[3 + n].end - field[3 + n].start;
+ type = 0;
+ if (len == 4) {
+ if (memcmp(s, "deny", 4) == 0)
+ type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+ } else if (len == 5) {
+ if (memcmp(s, "allow", 5) == 0)
+ type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+ else if (memcmp(s, "audit", 5) == 0)
+ type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
+ else if (memcmp(s, "alarm", 5) == 0)
+ type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
+ }
+ if (type == 0) {
+ /* Invalid entry type, skip entry */
+ ret = ARCHIVE_WARN;
+ continue;
+ }
+ isint(field[4 + n].start, field[4 + n].end,
+ &id);
+ }
/* Add entry to the internal list. */
r = archive_acl_add_entry_len_l(acl, type, permset,
@@ -1154,7 +1856,12 @@ archive_acl_parse_l(struct archive_acl *acl,
return (r);
if (r != ARCHIVE_OK)
ret = ARCHIVE_WARN;
+ types |= type;
}
+
+ /* Reset ACL */
+ archive_acl_reset(acl, types);
+
return (ret);
}
@@ -1220,6 +1927,112 @@ ismode(const char *start, const char *end, int *permset)
}
/*
+ * Parse a string as a NFS4 ACL permission field.
+ * Returns true if the string is non-empty and consists only of NFS4 ACL
+ * permission characters, false otherwise
+ */
+static int
+is_nfs4_perms(const char *start, const char *end, int *permset)
+{
+ const char *p = start;
+
+ while (p < end) {
+ switch (*p++) {
+ case 'r':
+ *permset |= ARCHIVE_ENTRY_ACL_READ_DATA;
+ break;
+ case 'w':
+ *permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA;
+ break;
+ case 'x':
+ *permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
+ break;
+ case 'p':
+ *permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA;
+ break;
+ case 'D':
+ *permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD;
+ break;
+ case 'd':
+ *permset |= ARCHIVE_ENTRY_ACL_DELETE;
+ break;
+ case 'a':
+ *permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES;
+ break;
+ case 'A':
+ *permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES;
+ break;
+ case 'R':
+ *permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS;
+ break;
+ case 'W':
+ *permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS;
+ break;
+ case 'c':
+ *permset |= ARCHIVE_ENTRY_ACL_READ_ACL;
+ break;
+ case 'C':
+ *permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL;
+ break;
+ case 'o':
+ *permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER;
+ break;
+ case 's':
+ *permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
+ break;
+ case '-':
+ break;
+ default:
+ return(0);
+ }
+ }
+ return (1);
+}
+
+/*
+ * Parse a string as a NFS4 ACL flags field.
+ * Returns true if the string is non-empty and consists only of NFS4 ACL
+ * flag characters, false otherwise
+ */
+static int
+is_nfs4_flags(const char *start, const char *end, int *permset)
+{
+ const char *p = start;
+
+ while (p < end) {
+ switch(*p++) {
+ case 'f':
+ *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT;
+ break;
+ case 'd':
+ *permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT;
+ break;
+ case 'i':
+ *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY;
+ break;
+ case 'n':
+ *permset |=
+ ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT;
+ break;
+ case 'S':
+ *permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS;
+ break;
+ case 'F':
+ *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS;
+ break;
+ case 'I':
+ *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED;
+ break;
+ case '-':
+ break;
+ default:
+ return (0);
+ }
+ }
+ return (1);
+}
+
+/*
* Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]". *wp is updated
* to point to just after the separator. *start points to the first
* character of the matched text and *end just after the last
@@ -1254,25 +2067,3 @@ next_field(const char **p, const char **start,
if (**p != '\0')
(*p)++;
}
-
-/*
- * Return true if the characters [start...end) are a prefix of 'test'.
- * This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc.
- */
-static int
-prefix_c(const char *start, const char *end, const char *test)
-{
- if (start == end)
- return (0);
-
- if (*start++ != *test++)
- return (0);
-
- while (start < end && *start++ == *test++)
- ;
-
- if (start < end)
- return (0);
-
- return (1);
-}
diff --git a/Utilities/cmlibarchive/libarchive/archive_acl_private.h b/Utilities/cmlibarchive/libarchive/archive_acl_private.h
index 1421adb..ef0b023 100644
--- a/Utilities/cmlibarchive/libarchive/archive_acl_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_acl_private.h
@@ -56,6 +56,7 @@ struct archive_acl {
void archive_acl_clear(struct archive_acl *);
void archive_acl_copy(struct archive_acl *, struct archive_acl *);
int archive_acl_count(struct archive_acl *, int);
+int archive_acl_types(struct archive_acl *);
int archive_acl_reset(struct archive_acl *, int);
int archive_acl_next(struct archive *, struct archive_acl *, int,
int *, int *, int *, int *, const char **);
@@ -66,22 +67,17 @@ int archive_acl_add_entry_w_len(struct archive_acl *,
int archive_acl_add_entry_len(struct archive_acl *,
int, int, int, int, const char *, size_t);
-const wchar_t *archive_acl_text_w(struct archive *, struct archive_acl *, int);
-int archive_acl_text_l(struct archive_acl *, int, const char **, size_t *,
+wchar_t *archive_acl_to_text_w(struct archive_acl *, ssize_t *, int,
+ struct archive *);
+char *archive_acl_to_text_l(struct archive_acl *, ssize_t *, int,
struct archive_string_conv *);
/*
- * Private ACL parser. This is private because it handles some
- * very weird formats that clients should not be messing with.
- * Clients should only deal with their platform-native formats.
- * Because of the need to support many formats cleanly, new arguments
- * are likely to get added on a regular basis. Clients who try to use
- * this interface are likely to be surprised when it changes.
+ * ACL text parser.
*/
-int archive_acl_parse_w(struct archive_acl *,
- const wchar_t *, int /* type */);
-int archive_acl_parse_l(struct archive_acl *,
- const char *, int /* type */,
- struct archive_string_conv *);
+int archive_acl_from_text_w(struct archive_acl *, const wchar_t * /* wtext */,
+ int /* type */);
+int archive_acl_from_text_l(struct archive_acl *, const char * /* text */,
+ int /* type */, struct archive_string_conv *);
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
diff --git a/Utilities/cmlibarchive/libarchive/archive_cryptor.c b/Utilities/cmlibarchive/libarchive/archive_cryptor.c
index 2a51dfe..ced52fd 100644
--- a/Utilities/cmlibarchive/libarchive/archive_cryptor.c
+++ b/Utilities/cmlibarchive/libarchive/archive_cryptor.c
@@ -302,7 +302,8 @@ aes_ctr_release(archive_crypto_ctx *ctx)
static int
aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
{
- ctx->ctx = EVP_CIPHER_CTX_new();
+ if ((ctx->ctx = EVP_CIPHER_CTX_new()) == NULL)
+ return -1;
switch (key_len) {
case 16: ctx->type = EVP_aes_128_ecb(); break;
diff --git a/Utilities/cmlibarchive/libarchive/archive_digest_private.h b/Utilities/cmlibarchive/libarchive/archive_digest_private.h
index b58ffb3..b4fd6ca 100644
--- a/Utilities/cmlibarchive/libarchive/archive_digest_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_digest_private.h
@@ -143,6 +143,7 @@
defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA512_WIN)
+#include <windows.h>
#include <wincrypt.h>
typedef struct {
int valid;
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.c b/Utilities/cmlibarchive/libarchive/archive_entry.c
index 4ac1966..10eff11 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry.c
+++ b/Utilities/cmlibarchive/libarchive/archive_entry.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -248,10 +249,9 @@ archive_entry_new2(struct archive *a)
{
struct archive_entry *entry;
- entry = (struct archive_entry *)malloc(sizeof(*entry));
+ entry = (struct archive_entry *)calloc(1, sizeof(*entry));
if (entry == NULL)
return (NULL);
- memset(entry, 0, sizeof(*entry));
entry->archive = a;
return (entry);
}
@@ -1442,6 +1442,15 @@ archive_entry_acl_add_entry_w(struct archive_entry *entry,
}
/*
+ * Return a bitmask of ACL types in an archive entry ACL list
+ */
+int
+archive_entry_acl_types(struct archive_entry *entry)
+{
+ return (archive_acl_types(&entry->acl));
+}
+
+/*
* Return a count of entries matching "want_type".
*/
int
@@ -1478,34 +1487,121 @@ archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
}
/*
- * Generate a text version of the ACL. The flags parameter controls
+ * Generate a text version of the ACL. The flags parameter controls
* the style of the generated ACL.
*/
+wchar_t *
+archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len,
+ int flags)
+{
+ return (archive_acl_to_text_w(&entry->acl, len, flags,
+ entry->archive));
+}
+
+char *
+archive_entry_acl_to_text(struct archive_entry *entry, ssize_t *len,
+ int flags)
+{
+ return (archive_acl_to_text_l(&entry->acl, len, flags, NULL));
+}
+
+char *
+_archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len,
+ int flags, struct archive_string_conv *sc)
+{
+ return (archive_acl_to_text_l(&entry->acl, len, flags, sc));
+}
+
+/*
+ * ACL text parser.
+ */
+int
+archive_entry_acl_from_text_w(struct archive_entry *entry,
+ const wchar_t *wtext, int type)
+{
+ return (archive_acl_from_text_w(&entry->acl, wtext, type));
+}
+
+int
+archive_entry_acl_from_text(struct archive_entry *entry,
+ const char *text, int type)
+{
+ return (archive_acl_from_text_l(&entry->acl, text, type, NULL));
+}
+
+int
+_archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text,
+ int type, struct archive_string_conv *sc)
+{
+ return (archive_acl_from_text_l(&entry->acl, text, type, sc));
+}
+
+/* Deprecated */
+static int
+archive_entry_acl_text_compat(int *flags)
+{
+ if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0)
+ return (1);
+
+ /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */
+ if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0)
+ *flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID;
+
+ /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */
+ if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
+ *flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
+
+ *flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA;
+
+ return (0);
+}
+
+/* Deprecated */
const wchar_t *
archive_entry_acl_text_w(struct archive_entry *entry, int flags)
{
- const wchar_t *r;
- r = archive_acl_text_w(entry->archive, &entry->acl, flags);
- if (r == NULL && errno == ENOMEM)
- __archive_errx(1, "No memory");
- return (r);
+ if (entry->acl.acl_text_w != NULL) {
+ free(entry->acl.acl_text_w);
+ entry->acl.acl_text_w = NULL;
+ }
+ if (archive_entry_acl_text_compat(&flags) == 0)
+ entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl,
+ NULL, flags, entry->archive);
+ return (entry->acl.acl_text_w);
}
+/* Deprecated */
const char *
archive_entry_acl_text(struct archive_entry *entry, int flags)
{
- const char *p;
- if (archive_acl_text_l(&entry->acl, flags, &p, NULL, NULL) != 0
- && errno == ENOMEM)
- __archive_errx(1, "No memory");
- return (p);
+ if (entry->acl.acl_text != NULL) {
+ free(entry->acl.acl_text);
+ entry->acl.acl_text = NULL;
+ }
+ if (archive_entry_acl_text_compat(&flags) == 0)
+ entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL,
+ flags, NULL);
+
+ return (entry->acl.acl_text);
}
+/* Deprecated */
int
_archive_entry_acl_text_l(struct archive_entry *entry, int flags,
const char **acl_text, size_t *len, struct archive_string_conv *sc)
{
- return (archive_acl_text_l(&entry->acl, flags, acl_text, len, sc));
+ if (entry->acl.acl_text != NULL) {
+ free(entry->acl.acl_text);
+ entry->acl.acl_text = NULL;
+ }
+
+ if (archive_entry_acl_text_compat(&flags) == 0)
+ entry->acl.acl_text = archive_acl_to_text_l(&entry->acl,
+ (ssize_t *)len, flags, sc);
+
+ *acl_text = entry->acl.acl_text;
+
+ return (0);
}
/*
@@ -1553,7 +1649,10 @@ static struct flag {
{ "nosappnd", L"nosappnd", SF_APPEND, 0 },
{ "nosappend", L"nosappend", SF_APPEND, 0 },
#endif
-#ifdef EXT2_APPEND_FL /* 'a' */
+#if defined(FS_APPEND_FL) /* 'a' */
+ { "nosappnd", L"nosappnd", FS_APPEND_FL, 0 },
+ { "nosappend", L"nosappend", FS_APPEND_FL, 0 },
+#elif defined(EXT2_APPEND_FL) /* 'a' */
{ "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0 },
{ "nosappend", L"nosappend", EXT2_APPEND_FL, 0 },
#endif
@@ -1566,7 +1665,11 @@ static struct flag {
{ "noschange", L"noschange", SF_IMMUTABLE, 0 },
{ "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0 },
#endif
-#ifdef EXT2_IMMUTABLE_FL /* 'i' */
+#if defined(FS_IMMUTABLE_FL) /* 'i' */
+ { "noschg", L"noschg", FS_IMMUTABLE_FL, 0 },
+ { "noschange", L"noschange", FS_IMMUTABLE_FL, 0 },
+ { "nosimmutable", L"nosimmutable", FS_IMMUTABLE_FL, 0 },
+#elif defined(EXT2_IMMUTABLE_FL) /* 'i' */
{ "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0 },
{ "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0 },
{ "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0 },
@@ -1590,7 +1693,9 @@ static struct flag {
#ifdef UF_NODUMP
{ "nodump", L"nodump", 0, UF_NODUMP},
#endif
-#ifdef EXT2_NODUMP_FL /* 'd' */
+#if defined(FS_NODUMP_FL) /* 'd' */
+ { "nodump", L"nodump", 0, FS_NODUMP_FL},
+#elif defined(EXT2_NODUMP_FL) /* 'd' */
{ "nodump", L"nodump", 0, EXT2_NODUMP_FL},
#endif
#ifdef UF_OPAQUE
@@ -1603,65 +1708,124 @@ static struct flag {
#ifdef UF_COMPRESSED
{ "nocompressed",L"nocompressed", UF_COMPRESSED, 0 },
#endif
-#ifdef EXT2_UNRM_FL
+#if defined(FS_UNRM_FL)
+ { "nouunlink", L"nouunlink", FS_UNRM_FL, 0},
+#elif defined(EXT2_UNRM_FL)
{ "nouunlink", L"nouunlink", EXT2_UNRM_FL, 0},
#endif
-#ifdef EXT2_BTREE_FL
+#if defined(FS_BTREE_FL)
+ { "nobtree", L"nobtree", FS_BTREE_FL, 0 },
+#elif defined(EXT2_BTREE_FL)
{ "nobtree", L"nobtree", EXT2_BTREE_FL, 0 },
#endif
-#ifdef EXT2_ECOMPR_FL
+#if defined(FS_ECOMPR_FL)
+ { "nocomperr", L"nocomperr", FS_ECOMPR_FL, 0 },
+#elif defined(EXT2_ECOMPR_FL)
{ "nocomperr", L"nocomperr", EXT2_ECOMPR_FL, 0 },
#endif
-#ifdef EXT2_COMPR_FL /* 'c' */
+#if defined(FS_COMPR_FL) /* 'c' */
+ { "nocompress", L"nocompress", FS_COMPR_FL, 0 },
+#elif defined(EXT2_COMPR_FL) /* 'c' */
{ "nocompress", L"nocompress", EXT2_COMPR_FL, 0 },
#endif
-#ifdef EXT2_NOATIME_FL /* 'A' */
+#if defined(FS_NOATIME_FL) /* 'A' */
+ { "noatime", L"noatime", 0, FS_NOATIME_FL},
+#elif defined(EXT2_NOATIME_FL) /* 'A' */
{ "noatime", L"noatime", 0, EXT2_NOATIME_FL},
#endif
-#ifdef EXT2_DIRTY_FL
+#if defined(FS_DIRTY_FL)
+ { "nocompdirty",L"nocompdirty", FS_DIRTY_FL, 0},
+#elif defined(EXT2_DIRTY_FL)
{ "nocompdirty",L"nocompdirty", EXT2_DIRTY_FL, 0},
#endif
-#ifdef EXT2_COMPRBLK_FL
-#ifdef EXT2_NOCOMPR_FL
+#if defined(FS_COMPRBLK_FL)
+#if defined(FS_NOCOMPR_FL)
+ { "nocomprblk", L"nocomprblk", FS_COMPRBLK_FL, FS_NOCOMPR_FL},
+#else
+ { "nocomprblk", L"nocomprblk", FS_COMPRBLK_FL, 0},
+#endif
+#elif defined(EXT2_COMPRBLK_FL)
+#if defined(EXT2_NOCOMPR_FL)
{ "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, EXT2_NOCOMPR_FL},
#else
{ "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, 0},
#endif
#endif
-#ifdef EXT2_DIRSYNC_FL
+#if defined(FS_DIRSYNC_FL)
+ { "nodirsync", L"nodirsync", FS_DIRSYNC_FL, 0},
+#elif defined(EXT2_DIRSYNC_FL)
{ "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0},
#endif
-#ifdef EXT2_INDEX_FL
+#if defined(FS_INDEX_FL)
+ { "nohashidx", L"nohashidx", FS_INDEX_FL, 0},
+#elif defined(EXT2_INDEX_FL)
{ "nohashidx", L"nohashidx", EXT2_INDEX_FL, 0},
#endif
-#ifdef EXT2_IMAGIC_FL
+#if defined(FS_IMAGIC_FL)
+ { "noimagic", L"noimagic", FS_IMAGIC_FL, 0},
+#elif defined(EXT2_IMAGIC_FL)
{ "noimagic", L"noimagic", EXT2_IMAGIC_FL, 0},
#endif
-#ifdef EXT3_JOURNAL_DATA_FL
+#if defined(FS_JOURNAL_DATA_FL)
+ { "nojournal", L"nojournal", FS_JOURNAL_DATA_FL, 0},
+#elif defined(EXT3_JOURNAL_DATA_FL)
{ "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0},
#endif
-#ifdef EXT2_SECRM_FL
+#if defined(FS_SECRM_FL)
+ { "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL, 0},
+#elif defined(EXT2_SECRM_FL)
{ "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0},
#endif
-#ifdef EXT2_SYNC_FL
+#if defined(FS_SYNC_FL)
+ { "nosync", L"nosync", FS_SYNC_FL, 0},
+#elif defined(EXT2_SYNC_FL)
{ "nosync", L"nosync", EXT2_SYNC_FL, 0},
#endif
-#ifdef EXT2_NOTAIL_FL
+#if defined(FS_NOTAIL_FL)
+ { "notail", L"notail", 0, FS_NOTAIL_FL},
+#elif defined(EXT2_NOTAIL_FL)
{ "notail", L"notail", 0, EXT2_NOTAIL_FL},
#endif
-#ifdef EXT2_TOPDIR_FL
+#if defined(FS_TOPDIR_FL)
+ { "notopdir", L"notopdir", FS_TOPDIR_FL, 0},
+#elif defined(EXT2_TOPDIR_FL)
{ "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0},
#endif
-#ifdef EXT2_RESERVED_FL
+#ifdef FS_ENCRYPT_FL
+ { "noencrypt", L"noencrypt", FS_ENCRYPT_FL, 0},
+#endif
+#ifdef FS_HUGE_FILE_FL
+ { "nohugefile", L"nohugefile", FS_HUGE_FILE_FL, 0},
+#endif
+#ifdef FS_EXTENT_FL
+ { "noextent", L"noextent", FS_EXTENT_FL, 0},
+#endif
+#ifdef FS_EA_INODE_FL
+ { "noeainode", L"noeainode", FS_EA_INODE_FL, 0},
+#endif
+#ifdef FS_EOFBLOCKS_FL
+ { "noeofblocks",L"noeofblocks", FS_EOFBLOCKS_FL, 0},
+#endif
+#ifdef FS_NOCOW_FL
+ { "nocow", L"nocow", FS_NOCOW_FL, 0},
+#endif
+#ifdef FS_INLINE_DATA_FL
+ { "noinlinedata",L"noinlinedata", FS_INLINE_DATA_FL, 0},
+#endif
+#ifdef FS_PROJINHERIT_FL
+ { "noprojinherit",L"noprojinherit", FS_PROJINHERIT_FL, 0},
+#endif
+#if defined(FS_RESERVED_FL)
+ { "noreserved", L"noreserved", FS_RESERVED_FL, 0},
+#elif defined(EXT2_RESERVED_FL)
{ "noreserved", L"noreserved", EXT2_RESERVED_FL, 0},
#endif
-
{ NULL, NULL, 0, 0 }
};
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.h b/Utilities/cmlibarchive/libarchive/archive_entry.h
index 81cd425..6e0225b 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry.h
+++ b/Utilities/cmlibarchive/libarchive/archive_entry.h
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003-2008 Tim Kientzle
+ * Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +30,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
-#define ARCHIVE_VERSION_NUMBER 3002001
+#define ARCHIVE_VERSION_NUMBER 3003001
/*
* Note: archive_entry.h is for use outside of libarchive; the
@@ -65,6 +66,27 @@ typedef int64_t la_int64_t;
# endif
#endif
+/* The la_ssize_t should match the type used in 'struct stat' */
+#if !defined(__LA_SSIZE_T_DEFINED)
+/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */
+# if ARCHIVE_VERSION_NUMBER < 4000000
+#define __LA_SSIZE_T la_ssize_t
+# endif
+#define __LA_SSIZE_T_DEFINED
+# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
+# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
+typedef ssize_t la_ssize_t;
+# elif defined(_WIN64)
+typedef __int64 la_ssize_t;
+# else
+typedef long la_ssize_t;
+# endif
+# else
+# include <unistd.h> /* ssize_t */
+typedef ssize_t la_ssize_t;
+# endif
+#endif
+
/* Get a suitable definition for mode_t */
#if ARCHIVE_VERSION_NUMBER >= 3999000
/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */
@@ -104,6 +126,9 @@ typedef int64_t la_int64_t;
# define __LA_DECL
#endif
+/* CMake uses some deprecated APIs to build with old libarchive versions. */
+#define __LA_DEPRECATED
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -420,6 +445,7 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi
/*
* Inheritance values (NFS4 ACLs only); included in permset.
*/
+#define ARCHIVE_ENTRY_ACL_ENTRY_INHERITED 0x01000000
#define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000
#define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000
#define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000
@@ -433,15 +459,16 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi
| ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \
| ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \
| ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \
- | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS)
+ | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS \
+ | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED)
/* We need to be able to specify combinations of these. */
-#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 256 /* POSIX.1e only */
-#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 512 /* POSIX.1e only */
-#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 1024 /* NFS4 only */
-#define ARCHIVE_ENTRY_ACL_TYPE_DENY 2048 /* NFS4 only */
-#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 4096 /* NFS4 only */
-#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 8192 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 0x00000100 /* POSIX.1e only */
+#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 0x00000200 /* POSIX.1e only */
+#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 0x00000400 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_DENY 0x00000800 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 0x00001000 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 0x00002000 /* NFS4 only */
#define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \
| ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)
#define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \
@@ -492,21 +519,51 @@ __LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type
* Construct a text-format ACL. The flags argument is a bitmask that
* can include any of the following:
*
+ * Flags only for archive entries with POSIX.1e ACL:
* ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries.
* ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries.
- * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - Include NFS4 entries.
- * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
- * each ACL entry. ('star' introduced this for POSIX.1e, this flag
- * also applies to NFS4.)
* ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each
- * default ACL entry, as used in old Solaris ACLs.
+ * default ACL entry.
+ * ARCHIVE_ENTRY_ACL_STYLE_SOLARIS - Output only one colon after "other" and
+ * "mask" entries.
+ *
+ * Flags only for archive entries with NFSv4 ACL:
+ * ARCHIVE_ENTRY_ACL_STYLE_COMPACT - Do not output the minus character for
+ * unset permissions and flags in NFSv4 ACL permission and flag fields
+ *
+ * Flags for for archive entries with POSIX.1e ACL or NFSv4 ACL:
+ * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
+ * each ACL entry.
+ * ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA - Separate entries with comma
+ * instead of newline.
*/
-#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024
-#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048
+#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 0x00000001
+#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 0x00000002
+#define ARCHIVE_ENTRY_ACL_STYLE_SOLARIS 0x00000004
+#define ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA 0x00000008
+#define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010
+
+__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *,
+ la_ssize_t * /* len */, int /* flags */);
+__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *,
+ la_ssize_t * /* len */, int /* flags */);
+__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *,
+ const wchar_t * /* wtext */, int /* type */);
+__LA_DECL int archive_entry_acl_from_text(struct archive_entry *,
+ const char * /* text */, int /* type */);
+
+/* Deprecated constants */
+#define OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024
+#define OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048
+
+/* Deprecated functions */
__LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *,
- int /* flags */);
+ int /* flags */) __LA_DEPRECATED;
__LA_DECL const char *archive_entry_acl_text(struct archive_entry *,
- int /* flags */);
+ int /* flags */) __LA_DEPRECATED;
+
+/* Return bitmask of ACL types in an archive entry */
+__LA_DECL int archive_entry_acl_types(struct archive_entry *);
/* Return a count of entries matching 'want_type' */
__LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */);
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_acl.3 b/Utilities/cmlibarchive/libarchive/archive_entry_acl.3
index 5aff996..c5115f7 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_acl.3
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_acl.3
@@ -1,4 +1,5 @@
.\" Copyright (c) 2010 Joerg Sonnenberger
+.\" Copyright (c) 2016 Martin Matuska
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -22,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd February 2, 2012
+.Dd February 15, 2017
.Dt ARCHIVE_ENTRY_ACL 3
.Os
.Sh NAME
@@ -30,10 +31,14 @@
.Nm archive_entry_acl_add_entry_w ,
.Nm archive_entry_acl_clear ,
.Nm archive_entry_acl_count ,
+.Nm archive_entry_acl_from_text ,
+.Nm archive_entry_acl_from_text_w,
.Nm archive_entry_acl_next ,
.Nm archive_entry_acl_next_w ,
.Nm archive_entry_acl_reset ,
-.Nm archive_entry_acl_text_w
+.Nm archive_entry_acl_to_text ,
+.Nm archive_entry_acl_to_text_w ,
+.Nm archive_entry_acl_types
.Nd functions for manipulating Access Control Lists in archive entry descriptions
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
@@ -62,6 +67,18 @@ Streaming Archive Library (libarchive, -larchive)
.Ft int
.Fn archive_entry_acl_count "struct archive_entry *a" "int type"
.Ft int
+.Fo archive_entry_acl_from_text
+.Fa "struct archive_entry *a"
+.Fa "const char *text"
+.Fa "int type"
+.Fc
+.Ft int
+.Fo archive_entry_acl_from_text_w
+.Fa "struct archive_entry *a"
+.Fa "const wchar_t *text"
+.Fa "int type"
+.Fc
+.Ft int
.Fo archive_entry_acl_next
.Fa "struct archive_entry *a"
.Fa "int type"
@@ -83,31 +100,48 @@ Streaming Archive Library (libarchive, -larchive)
.Fc
.Ft int
.Fn archive_entry_acl_reset "struct archive_entry *a" "int type"
-.Ft const wchar_t *
-.Fn archive_entry_acl_text_w "struct archive_entry *a" "int flags"
+.Ft char *
+.Fo archive_entry_acl_to_text
+.Fa "struct archive_entry *a"
+.Fa "ssize_t *len_p"
+.Fa "int flags"
+.Fc
+.Ft wchar_t *
+.Fo archive_entry_acl_to_text_w
+.Fa "struct archive_entry *a"
+.Fa "ssize_t *len_p"
+.Fa "int flags"
+.Fc
+.Ft int
+.Fn archive_entry_acl_types "struct archive_entry *a"
.\" enum?
.Sh DESCRIPTION
-An
-.Dq Access Control List
-is a generalisation of the classic Unix permission system.
+The
+.Dq Access Control Lists (ACLs)
+extend the standard Unix perssion model.
The ACL interface of
.Nm libarchive
-is derived from the POSIX.1e draft, but restricted to simplify dealing
-with practical implementations in various Operating Systems and archive formats.
-.Pp
-An ACL consists of a number of independent entries.
+supports both POSIX.1e and NFSv4 style ACLs. Use of ACLs is restricted by
+various levels of ACL support in operating systems, file systems and archive
+formats.
+.Ss POSIX.1e Access Control Lists
+A POSIX.1e ACL consists of a number of independent entries.
Each entry specifies the permission set as bitmask of basic permissions.
-Valid permissions are:
+Valid permissions in the
+.Fa permset
+are:
.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_EXECUTE"
-.It Dv ARCHIVE_ENTRY_ACL_EXECUTE
-.It Dv ARCHIVE_ENTRY_ACL_WRITE
-.It Dv ARCHIVE_ENTRY_ACL_READ
+.It Dv ARCHIVE_ENTRY_ACL_READ ( Sy r )
+.It Dv ARCHIVE_ENTRY_ACL_WRITE ( Sy w )
+.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x )
.El
The permissions correspond to the normal Unix permissions.
.Pp
-The tag specifies the principal to which the permission applies.
+The
+.Fa tag
+specifies the principal to which the permission applies.
Valid values are:
-.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
+.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
.It Dv ARCHIVE_ENTRY_ACL_USER
The user specified by the name field.
.It Dv ARCHIVE_ENTRY_ACL_USER_OBJ
@@ -119,8 +153,9 @@ The group who owns the file.
.It Dv ARCHIVE_ENTRY_ACL_MASK
The maximum permissions to be obtained via group permissions.
.It Dv ARCHIVE_ENTRY_ACL_OTHER
-Any principal who doesn't have a user or group entry.
+Any principal who is not file owner or a member of the owning group.
.El
+.Pp
The principals
.Dv ARCHIVE_ENTRY_ACL_USER_OBJ ,
.Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ
@@ -129,19 +164,123 @@ and
are equivalent to user, group and other in the classic Unix permission
model and specify non-extended ACL entries.
.Pp
-All files have an access ACL
+All files with have an access ACL
.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS .
This specifies the permissions required for access to the file itself.
Directories have an additional ACL
.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT ,
which controls the initial access ACL for newly created directory entries.
+.Ss NFSv4 Access Control Lists
+A NFSv4 ACL consists of multiple individual entries called Access Control
+Entries (ACEs).
+.Pp
+There are four possible types of a NFSv4 ACE:
+.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYE_ALLOW"
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW
+Allow principal to perform actions requiring given permissions.
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY
+Prevent principal from performing actions requiring given permissions.
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT
+Log access attempts by principal which require given permissions.
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM
+Trigger a system alarm on access attempts by principal which require given
+permissions.
+.El
+.Pp
+The
+.Fa tag
+specifies the principal to which the permission applies.
+Valid values are:
+.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
+.It Dv ARCHIVE_ENTRY_ACL_USER
+The user specified by the name field.
+.It Dv ARCHIVE_ENTRY_ACL_USER_OBJ
+The owner of the file.
+.It Dv ARCHIVE_ENTRY_ACL_GROUP
+The group specied by the name field.
+.It Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ
+The group who owns the file.
+.It Dv ARCHIVE_ENTRY_ACL_EVERYONE
+Any principal who is not file owner or a member of the owning group.
+.El
+.Pp
+Entries with the
+.Dv ARCHIVE_ENTRY_ACL_USER
+or
+.Dv ARCHIVE_ENTRY_ACL_GROUP
+tag store the user and group name in the
+.Fa name
+string and optionally the user or group ID in the
+.Fa qualifier
+integer.
+.Pp
+NFSv4 ACE permissions and flags are stored in the same
+.Fa permset
+bitfield. Some permissions share the same constant and permission character but
+have different effect on directories than on files. The following ACE
+permissions are supported:
+.Bl -tag -offset indent -compact -width ARCHIV
+.It Dv ARCHIVE_ENTRY_ACL_READ_DATA ( Sy r )
+Read data (file).
+.It Dv ARCHIVE_ENTRY_ACL_LIST_DIRECTORY ( Sy r )
+List entries (directory).
+.It ARCHIVE_ENTRY_ACL_WRITE_DATA ( Sy w )
+Write data (file).
+.It ARCHIVE_ENTRY_ACL_ADD_FILE ( Sy w )
+Create files (directory).
+.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x )
+Execute file or change into a directory.
+.It Dv ARCHIVE_ENTRY_ACL_APPEND_DATA ( Sy p )
+Append data (file).
+.It Dv ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY ( Sy p )
+Create subdirectories (directory).
+.It Dv ARCHIVE_ENTRY_ACL_DELETE_CHILD ( Sy D )
+Remove files and subdirectories inside a directory.
+.It Dv ARCHIVE_ENTRY_ACL_DELETE ( Sy d )
+Remove file or directory.
+.It Dv ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES ( Sy a )
+Read file or directory attributes.
+.It Dv ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES ( Sy A )
+Write file or directory attributes.
+.It Dv ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS ( Sy R )
+Read named file or directory attributes.
+.It Dv ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS ( Sy W )
+Write named file or directory attributes.
+.It Dv ARCHIVE_ENTRY_ACL_READ_ACL ( Sy c )
+Read file or directory ACL.
+.It Dv ARCHIVE_ENTRY_ACL_WRITE_ACL ( Sy C )
+Write file or directory ACL.
+.It Dv ARCHIVE_ENTRY_ACL_WRITE_OWNER ( Sy o )
+Change owner of a file or directory.
+.It Dv ARCHIVE_ENTRY_ACL_SYNCHRONIZE ( Sy s )
+Use synchronous I/O.
+.El
.Pp
+The following NFSv4 ACL inheritance flags are supported:
+.Bl -tag -offset indent -compact -width ARCHIV
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT ( Sy f )
+Inherit parent directory ACE to files.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT ( Sy d )
+Inherit parent directory ACE to subdirectories.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY ( Sy i )
+Only inherit, do not apply the permission on the directory itself.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT ( Sy n )
+Do not propagate inherit flags. Only first-level entries inherit ACLs.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS ( Sy S )
+Trigger alarm or audit on succesful access.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS ( Sy F )
+Trigger alarm or audit on failed access.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERITED ( Sy I )
+Mark that ACE was inherited.
+.El
+.Ss Functions
.Fn archive_entry_acl_add_entry
and
.Fn archive_entry_acl_add_entry_w
add a single ACL entry.
For the access ACL and non-extended principals, the classic Unix permissions
-are updated.
+are updated. An archive enry cannot contain both POSIX.1e and NFSv4 ACL
+entries.
.Pp
.Fn archive_entry_acl_clear
removes all ACL entries and resets the enumeration pointer.
@@ -150,14 +289,58 @@ removes all ACL entries and resets the enumeration pointer.
counts the ACL entries that have the given type mask.
.Fa type
can be the bitwise-or of
-.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
-and
-.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT .
-If
+.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT"
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+.El
+for POSIX.1e ACLs and
+.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_ALLOW"
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM
+.El
+for NFSv4 ACLs. For POSIX.1e ACLs if
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
is included and at least one extended ACL entry is found,
the three non-extened ACLs are added.
.Pp
+.Fn archive_entry_acl_from_text
+and
+.Fn archive_entry_acl_from_text_w
+add new
+.Pq or merge with existing
+ACL entries from
+.Pq wide
+text. The argument
+.Fa type
+may take one of the following values:
+.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT"
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4
+.El
+Supports all formats that can be created with
+.Fn archive_entry_acl_to_text
+or respective
+.Fn archive_entry_acl_to_text_w .
+Existing ACL entries are preserved. To get a clean new ACL from text
+.Fn archive_entry_acl_clear
+must be called first. Entries prefixed with
+.Dq default:
+are treated as
+.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+unless
+.Fa type
+is
+.Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4 .
+Invalid entries, non-parseable ACL entries and entries beginning with
+the
+.Sq #
+character
+.Pq comments
+are skipped.
+.Pp
.Fn archive_entry_acl_next
and
.Fn archive_entry_acl_next_w
@@ -179,29 +362,81 @@ or set using
Otherwise, the function returns the same value as
.Fn archive_entry_acl_count .
.Pp
-.Fn archive_entry_acl_text_w
-converts the ACL entries for the given type mask into a wide string.
-In addition to the normal type flags,
-.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
+.Fn archive_entry_acl_to_text
and
-.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
-can be specified to further customize the result.
-The returned long string is valid until the next call to
-.Fn archive_entry_acl_clear ,
-.Fn archive_entry_acl_add_entry ,
-.Fn archive_entry_acl_add_entry_w
+.Fn archive_entry_acl_to_text_w
+convert the ACL entries for the given type into a
+.Pq wide
+string of ACL entries separated by newline. If the the pointer
+.Fa len_p
+is not NULL, then the function shall return the length of the string
+.Pq not including the NULL terminator
+in the location pointed to by
+.Fa len_p .
+The
+.Fa flag
+argument is a bitwise-or.
+.Pp
+The following flags are effective only on POSIX.1e ACL:
+.Bl -tag -offset indent -compact -width ARCHIV
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+Output access ACLs.
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+Output POSIX.1e default ACLs.
+.It Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
+Prefix each default ACL entry with the word
+.Dq default: .
+.It Dv ARCHIVE_ENTRY_ACL_STYLE_SOLARIS
+The mask and other ACLs don not contain a double colon.
+.El
+.Pp
+The following flags are effecive only on NFSv4 ACL:
+.Bl -tag -offset indent -compact -width ARCHIV
+.It Dv ARCHIVE_ENTRY_ACL_STYLE_COMPACT
+Do not output minus characters for unset permissions and flags in NFSv4 ACL
+permission and flag fields.
+.El
+.Pp
+The following flags are effective on both POSIX.1e and NFSv4 ACL:
+.Bl -tag -offset indent -compact -width ARCHIV
+.It Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
+Add an additional colon-separated field containing the user or group id.
+.It Dv ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA
+Separate ACL entries with comma instead of newline.
+.El
+.Pp
+If the archive entry contains NFSv4 ACLs, all types of NFSv4 ACLs are returned.
+It the entry contains POSIX.1e ACLs and none of the flags
+.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
or
-.Fn archive_entry_acl_text_w .
+.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+are specified, both access and default entries are returned and default entries
+are prefixed with
+.Dq default: .
+.Pp
+.Fn archive_entry_acl_types
+get ACL entry types contained in an archive entry's ACL. As POSIX.1e and NFSv4
+ACL entries cannot be mixed, this function is a very efficient way to detect if
+an ACL already contains POSIX.1e or NFSv4 ACL entries.
.Sh RETURN VALUES
.Fn archive_entry_acl_count
and
.Fn archive_entry_acl_reset
returns the number of ACL entries that match the given type mask.
-If the type mask includes
+For POSIX.1e ACLS if the type mask includes
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
and at least one extended ACL entry exists, the three classic Unix
permissions are counted.
.Pp
+.Fn archive_entry_acl_from_text
+and
+.Fn archive_entry_acl_from_text_w
+return
+.Dv ARCHIVE_OK
+if all entries were successfully parsed and
+.Dv ARCHIVE_WARN
+if one or more entries were invalid or non-parseable.
+.Pp
.Fn archive_entry_acl_next
and
.Fn archive_entry_acl_next_w
@@ -216,20 +451,16 @@ if
.Fn archive_entry_acl_reset
has not been called first.
.Pp
-.Fn archive_entry_text_w
-returns a wide string representation of the ACL entrise matching the
-given type mask.
-The returned long string is valid until the next call to
-.Fn archive_entry_acl_clear ,
-.Fn archive_entry_acl_add_entry ,
-.Fn archive_entry_acl_add_entry_w
-or
-.Fn archive_entry_acl_text_w .
+.Fn archive_entry_acl_to_text
+returns a string representing the ACL entries matching the given type and
+flags on success or NULL on error.
+.Pp
+.Fn archive_entry_acl_to_text_w
+returns a wide string representing the ACL entries matching the given type
+and flags on success or NULL on error.
+.Pp
+.Fn archive_entry_acl_types
+returns a bitmask of ACL entry types or 0 if archive entry has no ACL entries.
.Sh SEE ALSO
-.Xr archive_entry 3
-.Xr libarchive 3 ,
-.Sh BUGS
-.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
-and
-.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
-are not documented.
+.Xr archive_entry 3 ,
+.Xr libarchive 3
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_locale.h b/Utilities/cmlibarchive/libarchive/archive_entry_locale.h
index 02e024a..44550c5 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_locale.h
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_locale.h
@@ -63,9 +63,13 @@ int _archive_entry_uname_l(struct archive_entry *,
const char **, size_t *, struct archive_string_conv *);
#define archive_entry_acl_text_l _archive_entry_acl_text_l
int _archive_entry_acl_text_l(struct archive_entry *, int,
- const char **, size_t *, struct archive_string_conv *);
-
-
+const char **, size_t *, struct archive_string_conv *) __LA_DEPRECATED;
+#define archive_entry_acl_to_text_l _archive_entry_acl_to_text_l
+char *_archive_entry_acl_to_text_l(struct archive_entry *, ssize_t *, int,
+ struct archive_string_conv *);
+#define archive_entry_acl_from_text_l _archive_entry_acl_from_text_l
+int _archive_entry_acl_from_text_l(struct archive_entry *, const char* text,
+ int type, struct archive_string_conv *);
#define archive_entry_copy_gname_l _archive_entry_copy_gname_l
int _archive_entry_copy_gname_l(struct archive_entry *,
const char *, size_t, struct archive_string_conv *);
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_strmode.c b/Utilities/cmlibarchive/libarchive/archive_entry_strmode.c
index 16cb3f7..af2517a 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_strmode.c
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_strmode.c
@@ -80,7 +80,7 @@ archive_entry_strmode(struct archive_entry *entry)
if (mode & 0001) bp[9] = 't';
else bp[9] = 'T';
}
- if (archive_entry_acl_count(entry, ARCHIVE_ENTRY_ACL_TYPE_ACCESS))
+ if (archive_entry_acl_types(entry) != 0)
bp[10] = '+';
return (bp);
diff --git a/Utilities/cmlibarchive/libarchive/archive_hmac.c b/Utilities/cmlibarchive/libarchive/archive_hmac.c
index 1e0ae28..f299655 100644
--- a/Utilities/cmlibarchive/libarchive/archive_hmac.c
+++ b/Utilities/cmlibarchive/libarchive/archive_hmac.c
@@ -76,6 +76,10 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
+#ifndef BCRYPT_HASH_REUSABLE_FLAG
+# define BCRYPT_HASH_REUSABLE_FLAG 0x00000020
+#endif
+
static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
{
diff --git a/Utilities/cmlibarchive/libarchive/archive_match.c b/Utilities/cmlibarchive/libarchive/archive_match.c
index 4c41bad..be72066 100644
--- a/Utilities/cmlibarchive/libarchive/archive_match.c
+++ b/Utilities/cmlibarchive/libarchive/archive_match.c
@@ -471,7 +471,7 @@ archive_match_path_excluded(struct archive *_a,
}
/*
- * Utilty functions to get statistic information for inclusion patterns.
+ * Utility functions to get statistic information for inclusion patterns.
*/
int
archive_match_path_unmatched_inclusions(struct archive *_a)
@@ -655,7 +655,7 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
}
}
- /* If something error happend, report it immediately. */
+ /* If an error occurred, report it immediately. */
if (r < ARCHIVE_OK) {
archive_copy_error(&(a->archive), ar);
archive_read_free(ar);
@@ -1270,7 +1270,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
#endif /* _WIN32 && !__CYGWIN__ */
/*
- * Call back funtions for archive_rb.
+ * Call back functions for archive_rb.
*/
static int
cmp_node_mbs(const struct archive_rb_node *n1,
@@ -1405,7 +1405,7 @@ add_entry(struct archive_match *a, int flag,
&(a->exclusion_tree), pathname);
/*
- * We always overwrite comparison condision.
+ * We always overwrite comparison condition.
* If you do not want to overwrite it, you should not
* call archive_match_exclude_entry(). We cannot know
* what behavior you really expect since overwriting
@@ -1481,7 +1481,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
if (nsec == a->older_ctime_nsec &&
(a->older_ctime_filter & ARCHIVE_MATCH_EQUAL)
== 0)
- return (1); /* Eeual, skip it. */
+ return (1); /* Equal, skip it. */
}
}
if (a->newer_mtime_filter) {
@@ -1513,7 +1513,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
}
}
- /* If there is no excluson list, include the file. */
+ /* If there is no exclusion list, include the file. */
if (a->exclusion_entry_list.count == 0)
return (0);
@@ -1700,7 +1700,7 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
break;
}
- /* Add oowner id. */
+ /* Add owner id. */
if (i == ids->count)
ids->ids[ids->count++] = id;
else if (ids->ids[i] != id) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h b/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h
index 0e97e27..43a3ccc 100644
--- a/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h
@@ -33,10 +33,7 @@
#include <string.h> /* memset */
static inline EVP_MD_CTX *EVP_MD_CTX_new(void)
{
- EVP_MD_CTX *ctx = (EVP_MD_CTX *)malloc(sizeof(EVP_MD_CTX));
- if (ctx != NULL) {
- memset(ctx, 0, sizeof(*ctx));
- }
+ EVP_MD_CTX *ctx = (EVP_MD_CTX *)calloc(1, sizeof(EVP_MD_CTX));
return ctx;
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h b/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h
index d4ae0d1..2deeb5f 100644
--- a/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h
@@ -33,11 +33,7 @@
#include <string.h> /* memset */
static inline HMAC_CTX *HMAC_CTX_new(void)
{
- HMAC_CTX *ctx = (HMAC_CTX *)malloc(sizeof(HMAC_CTX));
- if (ctx != NULL) {
- memset(ctx, 0, sizeof(*ctx));
- HMAC_CTX_init(ctx);
- }
+ HMAC_CTX *ctx = (HMAC_CTX *)calloc(1, sizeof(HMAC_CTX));
return ctx;
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_options.c b/Utilities/cmlibarchive/libarchive/archive_options.c
index dbf3e80..6496025 100644
--- a/Utilities/cmlibarchive/libarchive/archive_options.c
+++ b/Utilities/cmlibarchive/libarchive/archive_options.c
@@ -26,6 +26,10 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
#include "archive_options_private.h"
static const char *
@@ -105,8 +109,11 @@ _archive_set_options(struct archive *a, const char *options,
if (options == NULL || options[0] == '\0')
return ARCHIVE_OK;
- data = (char *)malloc(strlen(options) + 1);
- strcpy(data, options);
+ if ((data = strdup(options)) == NULL) {
+ archive_set_error(a,
+ ENOMEM, "Out of memory adding file to list");
+ return (ARCHIVE_FATAL);
+ }
s = (const char *)data;
do {
diff --git a/Utilities/cmlibarchive/libarchive/archive_platform.h b/Utilities/cmlibarchive/libarchive/archive_platform.h
index 08a384c..47d144b 100644
--- a/Utilities/cmlibarchive/libarchive/archive_platform.h
+++ b/Utilities/cmlibarchive/libarchive/archive_platform.h
@@ -152,8 +152,25 @@
* acl_set_file(), and ACL_USER, we assume it has the rest of the
* POSIX.1e draft functions used in archive_read_extract.c.
*/
-#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE && HAVE_ACL_USER
+#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE
+#if HAVE_ACL_USER
#define HAVE_POSIX_ACL 1
+#elif HAVE_ACL_TYPE_EXTENDED
+#define HAVE_DARWIN_ACL 1
+#endif
+#endif
+
+/*
+ * If this platform has <sys/acl.h>, acl_get(), facl_get(), acl_set(),
+ * facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions
+ */
+#if HAVE_SYS_ACL_H && HAVE_ACL_GET && HAVE_FACL_GET && HAVE_ACL_SET && HAVE_FACL_SET && HAVE_ACLENT_T && HAVE_ACE_T
+#define HAVE_SUN_ACL 1
+#endif
+
+/* Define if platform supports NFSv4 ACLs */
+#if (HAVE_POSIX_ACL && HAVE_ACL_TYPE_NFS4) || HAVE_SUN_ACL || HAVE_DARWIN_ACL
+#define HAVE_NFS4_ACL 1
#endif
/*
@@ -164,6 +181,15 @@
#define CAN_RESTORE_METADATA_FD
#endif
+/*
+ * glibc 2.24 deprecates readdir_r
+ */
+#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24))
+#define USE_READDIR_R 1
+#else
+#undef USE_READDIR_R
+#endif
+
/* Set up defaults for internal error codes. */
#ifndef ARCHIVE_ERRNO_FILE_FORMAT
#if HAVE_EFTYPE
diff --git a/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h b/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h
index 3a6b9eb..06c99e8 100644
--- a/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h
@@ -19,7 +19,7 @@ If you need the compatibility with original PPMd var.H, you can use external Ran
#define PPMD7_MAX_ORDER 64
#define PPMD7_MIN_MEM_SIZE (1 << 11)
-#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3)
+#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFFu - 12 * 3)
struct CPpmd7_Context_;
diff --git a/Utilities/cmlibarchive/libarchive/archive_random.c b/Utilities/cmlibarchive/libarchive/archive_random.c
index fcea6c6..90ee7c6 100644
--- a/Utilities/cmlibarchive/libarchive/archive_random.c
+++ b/Utilities/cmlibarchive/libarchive/archive_random.c
@@ -80,7 +80,7 @@ archive_random(void *buf, size_t nbytes)
success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT);
- if (!success && GetLastError() == NTE_BAD_KEYSET) {
+ if (!success && GetLastError() == (DWORD)NTE_BAD_KEYSET) {
success = CryptAcquireContext(&hProv, NULL, NULL,
PROV_RSA_FULL, CRYPT_NEWKEYSET);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_rb.c b/Utilities/cmlibarchive/libarchive/archive_rb.c
index 5b5da20..cf58ac3 100644
--- a/Utilities/cmlibarchive/libarchive/archive_rb.c
+++ b/Utilities/cmlibarchive/libarchive/archive_rb.c
@@ -312,7 +312,7 @@ __archive_rb_tree_insert_rebalance(struct archive_rb_tree *rbt,
father = RB_FATHER(self);
if (RB_BLACK_P(father)) {
/*
- * If our greatgrandpa is black, we're done.
+ * If our great-grandpa is black, we're done.
*/
return;
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read.c b/Utilities/cmlibarchive/libarchive/archive_read.c
index 0bbacc8..d1feceb 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read.c 201157 2009-12-29 05:30:2
static int choose_filters(struct archive_read *);
static int choose_format(struct archive_read *);
+static int close_filters(struct archive_read *);
static struct archive_vtable *archive_read_vtable(void);
static int64_t _archive_filter_bytes(struct archive *, int);
static int _archive_filter_code(struct archive *, int);
@@ -528,7 +529,7 @@ archive_read_open1(struct archive *_a)
{
slot = choose_format(a);
if (slot < 0) {
- __archive_read_close_filters(a);
+ close_filters(a);
a->archive.state = ARCHIVE_STATE_FATAL;
return (ARCHIVE_FATAL);
}
@@ -582,7 +583,6 @@ choose_filters(struct archive_read *a)
/* Verify the filter by asking it for some data. */
__archive_read_filter_ahead(a->filter, 1, &avail);
if (avail < 0) {
- __archive_read_close_filters(a);
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
@@ -601,7 +601,6 @@ choose_filters(struct archive_read *a)
a->filter = filter;
r = (best_bidder->init)(a->filter);
if (r != ARCHIVE_OK) {
- __archive_read_close_filters(a);
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
@@ -765,7 +764,7 @@ archive_read_header_position(struct archive *_a)
* we cannot say whether there are encrypted entries, then
* ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
* In general, this function will return values below zero when the
- * reader is uncertain or totally uncapable of encryption support.
+ * reader is uncertain or totally incapable of encryption support.
* When this function returns 0 you can be sure that the reader
* supports encryption detection but no encrypted entries have
* been found yet.
@@ -986,8 +985,8 @@ _archive_read_data_block(struct archive *_a,
return (a->format->read_data)(a, buff, size, offset);
}
-int
-__archive_read_close_filters(struct archive_read *a)
+static int
+close_filters(struct archive_read *a)
{
struct archive_read_filter *f = a->filter;
int r = ARCHIVE_OK;
@@ -1010,6 +1009,9 @@ __archive_read_close_filters(struct archive_read *a)
void
__archive_read_free_filters(struct archive_read *a)
{
+ /* Make sure filters are closed and their buffers are freed */
+ close_filters(a);
+
while (a->filter != NULL) {
struct archive_read_filter *t = a->filter->upstream;
free(a->filter);
@@ -1052,7 +1054,7 @@ _archive_read_close(struct archive *_a)
/* TODO: Clean up the formatters. */
/* Release the filter objects. */
- r1 = __archive_read_close_filters(a);
+ r1 = close_filters(a);
if (r1 < r)
r = r1;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c b/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c
index f67f1eb..cf821b5 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c
@@ -125,7 +125,7 @@ void
__archive_read_reset_passphrase(struct archive_read *a)
{
- a->passphrases.candiate = -1;
+ a->passphrases.candidate = -1;
}
/*
@@ -137,31 +137,31 @@ __archive_read_next_passphrase(struct archive_read *a)
struct archive_read_passphrase *p;
const char *passphrase;
- if (a->passphrases.candiate < 0) {
+ if (a->passphrases.candidate < 0) {
/* Count out how many passphrases we have. */
int cnt = 0;
for (p = a->passphrases.first; p != NULL; p = p->next)
cnt++;
- a->passphrases.candiate = cnt;
+ a->passphrases.candidate = cnt;
p = a->passphrases.first;
- } else if (a->passphrases.candiate > 1) {
+ } else if (a->passphrases.candidate > 1) {
/* Rotate a passphrase list. */
- a->passphrases.candiate--;
+ a->passphrases.candidate--;
p = remove_passphrases_from_head(a);
add_passphrase_to_tail(a, p);
- /* Pick a new passphrase candiate up. */
+ /* Pick a new passphrase candidate up. */
p = a->passphrases.first;
- } else if (a->passphrases.candiate == 1) {
- /* This case is that all cadiates failed to decryption. */
- a->passphrases.candiate = 0;
+ } else if (a->passphrases.candidate == 1) {
+ /* This case is that all candidates failed to decrypt. */
+ a->passphrases.candidate = 0;
if (a->passphrases.first->next != NULL) {
/* Rotate a passphrase list. */
p = remove_passphrases_from_head(a);
add_passphrase_to_tail(a, p);
}
p = NULL;
- } else /* There is no passphrase candaite. */
+ } else /* There is no passphrase candidate. */
p = NULL;
if (p != NULL)
@@ -177,7 +177,7 @@ __archive_read_next_passphrase(struct archive_read *a)
if (p == NULL)
return (NULL);
insert_passphrase_to_head(a, p);
- a->passphrases.candiate = 1;
+ a->passphrases.candidate = 1;
}
} else
passphrase = NULL;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c b/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c
index 3a0d4d6..5e4d163 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c
@@ -133,7 +133,6 @@ archive_read_append_filter(struct archive *_a, int code)
a->filter = filter;
r2 = (bidder->init)(a->filter);
if (r2 != ARCHIVE_OK) {
- __archive_read_close_filters(a);
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
@@ -191,7 +190,6 @@ archive_read_append_filter_program_signature(struct archive *_a,
a->filter = filter;
r = (bidder->init)(a->filter);
if (r != ARCHIVE_OK) {
- __archive_read_close_filters(a);
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk.3 b/Utilities/cmlibarchive/libarchive/archive_read_disk.3
index 525dc59..2a5c130 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk.3
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 2, 2012
+.Dd December 30, 2016
.Dt ARCHIVE_READ_DISK 3
.Os
.Sh NAME
@@ -54,9 +54,9 @@ Streaming Archive Library (libarchive, -larchive)
.Fn archive_read_disk_set_symlink_physical "struct archive *"
.Ft int
.Fn archive_read_disk_set_symlink_hybrid "struct archive *"
-.Ft int
+.Ft const char *
.Fn archive_read_disk_gname "struct archive *" "gid_t"
-.Ft int
+.Ft const char *
.Fn archive_read_disk_uname "struct archive *" "uid_t"
.Ft int
.Fo archive_read_disk_set_gname_lookup
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c
index 74fe353..b2f1d17 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c
@@ -1,6 +1,7 @@
/*-
* Copyright (c) 2003-2009 Tim Kientzle
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
+ * Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,6 +38,11 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#ifdef HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif
+#ifdef HAVE_DARWIN_ACL
+#include <membership.h>
+#include <grp.h>
+#include <pwd.h>
+#endif
#ifdef HAVE_SYS_EXTATTR_H
#include <sys/extattr.h>
#endif
@@ -117,6 +123,15 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#define ACL_GET_PERM acl_get_perm_np
#endif
+/* NFSv4 platform ACL type */
+#if HAVE_SUN_ACL
+#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACE_T
+#elif HAVE_DARWIN_ACL
+#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_EXTENDED
+#elif HAVE_ACL_TYPE_NFS4
+#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_NFS4
+#endif
+
static int setup_acls(struct archive_read_disk *,
struct archive_entry *, int *fd);
static int setup_mac_metadata(struct archive_read_disk *,
@@ -125,6 +140,10 @@ static int setup_xattrs(struct archive_read_disk *,
struct archive_entry *, int *fd);
static int setup_sparse(struct archive_read_disk *,
struct archive_entry *, int *fd);
+#if defined(HAVE_LINUX_FIEMAP_H)
+static int setup_sparse_fiemap(struct archive_read_disk *,
+ struct archive_entry *, int *fd);
+#endif
int
archive_read_disk_entry_from_file(struct archive *_a,
@@ -184,15 +203,17 @@ archive_read_disk_entry_from_file(struct archive *_a,
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
/* On FreeBSD, we get flags for free with the stat. */
/* TODO: Does this belong in copy_stat()? */
- if (st->st_flags != 0)
+ if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && st->st_flags != 0)
archive_entry_set_fflags(entry, st->st_flags, 0);
#endif
-#if defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+#if (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+ (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
/* Linux requires an extra ioctl to pull the flags. Although
* this is an extra step, it has a nice side-effect: We get an
* open file descriptor which we can use in the subsequent lookups. */
- if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
+ if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 &&
+ (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
if (fd < 0) {
if (a->tree != NULL)
fd = a->open_on_current_dir(a->tree, path,
@@ -204,7 +225,13 @@ archive_read_disk_entry_from_file(struct archive *_a,
}
if (fd >= 0) {
int stflags;
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
+ r = ioctl(fd,
+#if defined(FS_IOC_GETFLAGS)
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
+ &stflags);
if (r == 0 && stflags != 0)
archive_entry_set_fflags(entry, stflags, 0);
}
@@ -250,13 +277,15 @@ archive_read_disk_entry_from_file(struct archive *_a,
}
#endif /* HAVE_READLINK || HAVE_READLINKAT */
- r = setup_acls(a, entry, &fd);
- if (!a->suppress_xattr) {
+ r = 0;
+ if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0)
+ r = setup_acls(a, entry, &fd);
+ if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) {
r1 = setup_xattrs(a, entry, &fd);
if (r1 < r)
r = r1;
}
- if (a->enable_copyfile) {
+ if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) {
r1 = setup_mac_metadata(a, entry, &fd);
if (r1 < r)
r = r1;
@@ -302,20 +331,17 @@ setup_mac_metadata(struct archive_read_disk *a,
name = archive_entry_sourcepath(entry);
if (name == NULL)
name = archive_entry_pathname(entry);
+ else if (a->tree != NULL && a->tree_enter_working_dir(a->tree) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Can't change dir to read extended attributes");
+ return (ARCHIVE_FAILED);
+ }
if (name == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Can't open file to read extended attributes: No name");
return (ARCHIVE_WARN);
}
- if (a->tree != NULL) {
- if (a->tree_enter_working_dir(a->tree) != 0) {
- archive_set_error(&a->archive, errno,
- "Couldn't change dir");
- return (ARCHIVE_FAILED);
- }
- }
-
/* Short-circuit if there's nothing to do. */
have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
if (have_attrs == -1) {
@@ -400,34 +426,87 @@ setup_mac_metadata(struct archive_read_disk *a,
}
#endif
+#if HAVE_DARWIN_ACL
+static int translate_guid(struct archive *, acl_entry_t,
+ int *, int *, const char **);
-#ifdef HAVE_POSIX_ACL
+static void add_trivial_nfs4_acl(struct archive_entry *);
+#endif
+
+#if HAVE_SUN_ACL
+static int
+sun_acl_is_trivial(acl_t *, mode_t, int *trivialp);
+#endif
+
+#if HAVE_POSIX_ACL || HAVE_NFS4_ACL
static int translate_acl(struct archive_read_disk *a,
- struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
+ struct archive_entry *entry,
+#if HAVE_SUN_ACL
+ acl_t *acl,
+#else
+ acl_t acl,
+#endif
+ int archive_entry_acl_type);
static int
setup_acls(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
{
const char *accpath;
- acl_t acl;
-#if HAVE_ACL_IS_TRIVIAL_NP
- int r;
+#if HAVE_SUN_ACL
+ acl_t *acl;
+#else
+ acl_t acl;
#endif
+ int r;
- accpath = archive_entry_sourcepath(entry);
- if (accpath == NULL)
- accpath = archive_entry_pathname(entry);
+ accpath = NULL;
+
+#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_ACL_GET_FD_NP
+ if (*fd < 0)
+#else
+ /* For default ACLs on Linux we need reachable accpath */
+ if (*fd < 0 || S_ISDIR(archive_entry_mode(entry)))
+#endif
+ {
+ accpath = archive_entry_sourcepath(entry);
+ if (accpath == NULL || (a->tree != NULL &&
+ a->tree_enter_working_dir(a->tree) != 0))
+ accpath = archive_entry_pathname(entry);
+ if (accpath == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Couldn't determine file path to read ACLs");
+ return (ARCHIVE_WARN);
+ }
+ if (a->tree != NULL &&
+#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_ACL_GET_FD_NP
+ *fd < 0 &&
+#endif
+ (a->follow_symlinks ||
+ archive_entry_filetype(entry) != AE_IFLNK)) {
+ *fd = a->open_on_current_dir(a->tree,
+ accpath, O_RDONLY | O_NONBLOCK);
+ }
+ }
archive_entry_acl_clear(entry);
-#ifdef ACL_TYPE_NFS4
- /* Try NFS4 ACL first. */
+ acl = NULL;
+
+#if HAVE_NFS4_ACL
+ /* Try NFSv4 ACL first. */
if (*fd >= 0)
+#if HAVE_SUN_ACL
+ /* Solaris reads both POSIX.1e and NFSv4 ACL here */
+ facl_get(*fd, 0, &acl);
+#elif HAVE_ACL_GET_FD_NP
+ acl = acl_get_fd_np(*fd, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
+#else
acl = acl_get_fd(*fd);
+#endif
#if HAVE_ACL_GET_LINK_NP
else if (!a->follow_symlinks)
- acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
+ acl = acl_get_link_np(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
#else
else if ((!a->follow_symlinks)
&& (archive_entry_filetype(entry) == AE_IFLNK))
@@ -436,21 +515,62 @@ setup_acls(struct archive_read_disk *a,
acl = NULL;
#endif
else
- acl = acl_get_file(accpath, ACL_TYPE_NFS4);
-#if HAVE_ACL_IS_TRIVIAL_NP
+#if HAVE_SUN_ACL
+ /* Solaris reads both POSIX.1e and NFSv4 ACLs here */
+ acl_get(accpath, 0, &acl);
+#else
+ acl = acl_get_file(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
+#endif
+
+
+#if HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL
/* Ignore "trivial" ACLs that just mirror the file mode. */
- acl_is_trivial_np(acl, &r);
- if (r) {
- acl_free(acl);
- acl = NULL;
- }
+ if (acl != NULL) {
+#if HAVE_SUN_ACL
+ if (sun_acl_is_trivial(acl, archive_entry_mode(entry),
+ &r) == 0 && r == 1)
+#elif HAVE_ACL_IS_TRIVIAL_NP
+ if (acl_is_trivial_np(acl, &r) == 0 && r == 1)
#endif
+ {
+ acl_free(acl);
+ acl = NULL;
+ /*
+ * Simultaneous NFSv4 and POSIX.1e ACLs for the same
+ * entry are not allowed, so we should return here
+ */
+ return (ARCHIVE_OK);
+ }
+ }
+#endif /* HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL */
if (acl != NULL) {
- translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
+ r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
acl_free(acl);
- return (ARCHIVE_OK);
- }
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't translate "
+#if !HAVE_SUN_ACL
+ "NFSv4 "
+#endif
+ "ACLs");
+ }
+#if HAVE_DARWIN_ACL
+ /*
+ * Because Mac OS doesn't support owner@, group@ and everyone@
+ * ACLs we need to add NFSv4 ACLs mirroring the file mode to
+ * the archive entry. Otherwise extraction on non-Mac platforms
+ * would lead to an invalid file mode.
+ */
+ if ((archive_entry_acl_types(entry) &
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
+ add_trivial_nfs4_acl(entry);
#endif
+ return (r);
+ }
+#endif /* HAVE_NFS4_ACL */
+
+#if HAVE_POSIX_ACL
+ /* This code path is skipped on MacOS and Solaris */
/* Retrieve access ACL from file. */
if (*fd >= 0)
@@ -467,88 +587,609 @@ setup_acls(struct archive_read_disk *a,
#endif
else
acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
+
+#if HAVE_ACL_IS_TRIVIAL_NP
+ /* Ignore "trivial" ACLs that just mirror the file mode. */
+ if (acl != NULL && acl_is_trivial_np(acl, &r) == 0) {
+ if (r) {
+ acl_free(acl);
+ acl = NULL;
+ }
+ }
+#endif
+
if (acl != NULL) {
- translate_acl(a, entry, acl,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
+ r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
acl_free(acl);
+ acl = NULL;
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't translate access ACLs");
+ return (r);
+ }
}
/* Only directories can have default ACLs. */
if (S_ISDIR(archive_entry_mode(entry))) {
+#if HAVE_ACL_GET_FD_NP
+ if (*fd >= 0)
+ acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
+ else
+#endif
acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
if (acl != NULL) {
- translate_acl(a, entry, acl,
+ r = translate_acl(a, entry, acl,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
acl_free(acl);
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't translate default ACLs");
+ return (r);
+ }
}
}
+#endif /* HAVE_POSIX_ACL */
return (ARCHIVE_OK);
}
/*
- * Translate system ACL into libarchive internal structure.
+ * Translate system ACL permissions into libarchive internal structure
*/
-
-static struct {
- int archive_perm;
- int platform_perm;
+static const struct {
+ const int archive_perm;
+ const int platform_perm;
} acl_perm_map[] = {
- {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
- {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
- {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
-#ifdef ACL_TYPE_NFS4
- {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
- {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
- {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
- {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
- {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
- {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
- {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
- {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
- {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
- {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
- {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
- {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
- {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
- {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
- {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
- {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+#if HAVE_SUN_ACL /* Solaris NFSv4 ACL permissions */
+ {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
+ {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
+ {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
+ {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
+ {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
+ {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
+ {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
+ {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
+ {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
+#elif HAVE_DARWIN_ACL /* MacOS ACL permissions */
+ {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
+ {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
+ {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
+ {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+ {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
+ {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
+ {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
+ {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
+ {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
+ {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
+ {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+#else /* POSIX.1e ACL permissions */
+ {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+ {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
+ {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
+#if HAVE_ACL_TYPE_NFS4 /* FreeBSD NFSv4 ACL permissions */
+ {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
+ {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
+ {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
+ {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
+ {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
+ {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
+ {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
+ {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
#endif
+#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
};
-#ifdef ACL_TYPE_NFS4
-static struct {
- int archive_inherit;
- int platform_inherit;
+#if HAVE_NFS4_ACL
+/*
+ * Translate system NFSv4 inheritance flags into libarchive internal structure
+ */
+static const struct {
+ const int archive_inherit;
+ const int platform_inherit;
} acl_inherit_map[] = {
- {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
+#if HAVE_SUN_ACL /* Solaris ACL inheritance flags */
+ {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
+ {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
+#elif HAVE_DARWIN_ACL /* MacOS NFSv4 inheritance flags */
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
+ {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
+#else /* FreeBSD NFSv4 ACL inheritance flags */
+ {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
- {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
+ {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
+ {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
+#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
};
-#endif
+#endif /* HAVE_NFS4_ACL */
+
+#if HAVE_DARWIN_ACL
+static int translate_guid(struct archive *a, acl_entry_t acl_entry,
+ int *ae_id, int *ae_tag, const char **ae_name)
+{
+ void *q;
+ uid_t ugid;
+ int r, idtype;
+ struct passwd *pwd;
+ struct group *grp;
+
+ q = acl_get_qualifier(acl_entry);
+ if (q == NULL)
+ return (1);
+ r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype);
+ if (r != 0) {
+ acl_free(q);
+ return (1);
+ }
+ if (idtype == ID_TYPE_UID) {
+ *ae_tag = ARCHIVE_ENTRY_ACL_USER;
+ pwd = getpwuuid(q);
+ if (pwd == NULL) {
+ *ae_id = ugid;
+ *ae_name = NULL;
+ } else {
+ *ae_id = pwd->pw_uid;
+ *ae_name = archive_read_disk_uname(a, *ae_id);
+ }
+ } else if (idtype == ID_TYPE_GID) {
+ *ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+ grp = getgruuid(q);
+ if (grp == NULL) {
+ *ae_id = ugid;
+ *ae_name = NULL;
+ } else {
+ *ae_id = grp->gr_gid;
+ *ae_name = archive_read_disk_gname(a, *ae_id);
+ }
+ } else
+ r = 1;
+
+ acl_free(q);
+ return (r);
+}
+
+/*
+ * Add trivial NFSv4 ACL entries from mode
+ */
+static void
+add_trivial_nfs4_acl(struct archive_entry *entry)
+{
+ mode_t mode;
+ int i;
+ const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA;
+ const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA |
+ ARCHIVE_ENTRY_ACL_APPEND_DATA;
+ const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE;
+ const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_READ_ACL |
+ ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
+ const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
+ ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
+ ARCHIVE_ENTRY_ACL_WRITE_ACL |
+ ARCHIVE_ENTRY_ACL_WRITE_OWNER;
+
+ struct {
+ const int type;
+ const int tag;
+ int permset;
+ } tacl_entry[] = {
+ {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
+ {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
+ {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0},
+ {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset},
+ {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset},
+ {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset}
+ };
+
+ mode = archive_entry_mode(entry);
+
+ /* Permissions for everyone@ */
+ if (mode & 0004)
+ tacl_entry[5].permset |= rperm;
+ if (mode & 0002)
+ tacl_entry[5].permset |= wperm;
+ if (mode & 0001)
+ tacl_entry[5].permset |= eperm;
+
+ /* Permissions for group@ */
+ if (mode & 0040)
+ tacl_entry[4].permset |= rperm;
+ else if (mode & 0004)
+ tacl_entry[2].permset |= rperm;
+ if (mode & 0020)
+ tacl_entry[4].permset |= wperm;
+ else if (mode & 0002)
+ tacl_entry[2].permset |= wperm;
+ if (mode & 0010)
+ tacl_entry[4].permset |= eperm;
+ else if (mode & 0001)
+ tacl_entry[2].permset |= eperm;
+
+ /* Permissions for owner@ */
+ if (mode & 0400) {
+ tacl_entry[3].permset |= rperm;
+ if (!(mode & 0040) && (mode & 0004))
+ tacl_entry[0].permset |= rperm;
+ } else if ((mode & 0040) || (mode & 0004))
+ tacl_entry[1].permset |= rperm;
+ if (mode & 0200) {
+ tacl_entry[3].permset |= wperm;
+ if (!(mode & 0020) && (mode & 0002))
+ tacl_entry[0].permset |= wperm;
+ } else if ((mode & 0020) || (mode & 0002))
+ tacl_entry[1].permset |= wperm;
+ if (mode & 0100) {
+ tacl_entry[3].permset |= eperm;
+ if (!(mode & 0010) && (mode & 0001))
+ tacl_entry[0].permset |= eperm;
+ } else if ((mode & 0010) || (mode & 0001))
+ tacl_entry[1].permset |= eperm;
+
+ for (i = 0; i < 6; i++) {
+ if (tacl_entry[i].permset != 0) {
+ archive_entry_acl_add_entry(entry,
+ tacl_entry[i].type, tacl_entry[i].permset,
+ tacl_entry[i].tag, -1, NULL);
+ }
+ }
+
+ return;
+}
+#elif HAVE_SUN_ACL
+/*
+ * Check if acl is trivial
+ * This is a FreeBSD acl_is_trivial_np() implementation for Solaris
+ */
+static int
+sun_acl_is_trivial(acl_t *acl, mode_t mode, int *trivialp)
+{
+ int i, p;
+ const uint32_t rperm = ACE_READ_DATA;
+ const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA;
+ const uint32_t eperm = ACE_EXECUTE;
+ const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
+ ACE_READ_ACL | ACE_SYNCHRONIZE;
+ const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES |
+ ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER;
+
+ ace_t *ace;
+ ace_t tace[6];
+
+ if (acl == NULL || trivialp == NULL)
+ return (-1);
+
+ *trivialp = 0;
+
+ /* ACL_IS_TRIVIAL flag must be set for both POSIX.1e and NFSv4 ACLs */
+ if ((acl->acl_flags & ACL_IS_TRIVIAL) == 0)
+ return (0);
+
+ /*
+ * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with
+ * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries,
+ * including mask.
+ */
+ if (acl->acl_type == ACLENT_T) {
+ if (acl->acl_cnt == 4)
+ *trivialp = 1;
+ return (0);
+ }
+
+ if (acl->acl_type != ACE_T || acl->acl_entry_size != sizeof(ace_t))
+ return (-1);
+
+ /*
+ * Continue with checking NFSv4 ACLs
+ *
+ * Create list of trivial ace's to be compared
+ */
+
+ /* owner@ allow pre */
+ tace[0].a_flags = ACE_OWNER;
+ tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ tace[0].a_access_mask = 0;
+
+ /* owner@ deny */
+ tace[1].a_flags = ACE_OWNER;
+ tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
+ tace[1].a_access_mask = 0;
+
+ /* group@ deny */
+ tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
+ tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
+ tace[2].a_access_mask = 0;
+
+ /* owner@ allow */
+ tace[3].a_flags = ACE_OWNER;
+ tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ tace[3].a_access_mask = ownset;
+
+ /* group@ allow */
+ tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
+ tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ tace[4].a_access_mask = pubset;
+
+ /* everyone@ allow */
+ tace[5].a_flags = ACE_EVERYONE;
+ tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ tace[5].a_access_mask = pubset;
+
+ /* Permissions for everyone@ */
+ if (mode & 0004)
+ tace[5].a_access_mask |= rperm;
+ if (mode & 0002)
+ tace[5].a_access_mask |= wperm;
+ if (mode & 0001)
+ tace[5].a_access_mask |= eperm;
+
+ /* Permissions for group@ */
+ if (mode & 0040)
+ tace[4].a_access_mask |= rperm;
+ else if (mode & 0004)
+ tace[2].a_access_mask |= rperm;
+ if (mode & 0020)
+ tace[4].a_access_mask |= wperm;
+ else if (mode & 0002)
+ tace[2].a_access_mask |= wperm;
+ if (mode & 0010)
+ tace[4].a_access_mask |= eperm;
+ else if (mode & 0001)
+ tace[2].a_access_mask |= eperm;
+
+ /* Permissions for owner@ */
+ if (mode & 0400) {
+ tace[3].a_access_mask |= rperm;
+ if (!(mode & 0040) && (mode & 0004))
+ tace[0].a_access_mask |= rperm;
+ } else if ((mode & 0040) || (mode & 0004))
+ tace[1].a_access_mask |= rperm;
+ if (mode & 0200) {
+ tace[3].a_access_mask |= wperm;
+ if (!(mode & 0020) && (mode & 0002))
+ tace[0].a_access_mask |= wperm;
+ } else if ((mode & 0020) || (mode & 0002))
+ tace[1].a_access_mask |= wperm;
+ if (mode & 0100) {
+ tace[3].a_access_mask |= eperm;
+ if (!(mode & 0010) && (mode & 0001))
+ tace[0].a_access_mask |= eperm;
+ } else if ((mode & 0010) || (mode & 0001))
+ tace[1].a_access_mask |= eperm;
+
+ /* Check if the acl count matches */
+ p = 3;
+ for (i = 0; i < 3; i++) {
+ if (tace[i].a_access_mask != 0)
+ p++;
+ }
+ if (acl->acl_cnt != p)
+ return (0);
+
+ p = 0;
+ for (i = 0; i < 6; i++) {
+ if (tace[i].a_access_mask != 0) {
+ ace = &((ace_t *)acl->acl_aclp)[p];
+ /*
+ * Illumos added ACE_DELETE_CHILD to write perms for
+ * directories. We have to check against that, too.
+ */
+ if (ace->a_flags != tace[i].a_flags ||
+ ace->a_type != tace[i].a_type ||
+ (ace->a_access_mask != tace[i].a_access_mask &&
+ ((acl->acl_flags & ACL_IS_DIR) == 0 ||
+ (tace[i].a_access_mask & wperm) == 0 ||
+ ace->a_access_mask !=
+ (tace[i].a_access_mask | ACE_DELETE_CHILD))))
+ return (0);
+ p++;
+ }
+ }
+
+ *trivialp = 1;
+ return (0);
+}
+#endif /* HAVE_SUN_ACL */
+
+#if HAVE_SUN_ACL
+/*
+ * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL
+ */
+static int
+translate_acl(struct archive_read_disk *a,
+ struct archive_entry *entry, acl_t *acl, int default_entry_acl_type)
+{
+ int e, i;
+ int ae_id, ae_tag, ae_perm;
+ int entry_acl_type;
+ const char *ae_name;
+ aclent_t *aclent;
+ ace_t *ace;
+
+ (void)default_entry_acl_type;
+
+ if (acl->acl_cnt <= 0)
+ return (ARCHIVE_OK);
+
+ for (e = 0; e < acl->acl_cnt; e++) {
+ ae_name = NULL;
+ ae_tag = 0;
+ ae_perm = 0;
+
+ if (acl->acl_type == ACE_T) {
+ ace = &((ace_t *)acl->acl_aclp)[e];
+ ae_id = ace->a_who;
+
+ switch(ace->a_type) {
+ case ACE_ACCESS_ALLOWED_ACE_TYPE:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+ break;
+ case ACE_ACCESS_DENIED_ACE_TYPE:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+ break;
+ case ACE_SYSTEM_AUDIT_ACE_TYPE:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ break;
+ case ACE_SYSTEM_ALARM_ACE_TYPE:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
+ break;
+ default:
+ /* Unknown entry type, skip */
+ continue;
+ }
+
+ if ((ace->a_flags & ACE_OWNER) != 0)
+ ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ else if ((ace->a_flags & ACE_GROUP) != 0)
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ else if ((ace->a_flags & ACE_EVERYONE) != 0)
+ ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
+ else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) {
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+ ae_name = archive_read_disk_gname(&a->archive,
+ ae_id);
+ } else {
+ ae_tag = ARCHIVE_ENTRY_ACL_USER;
+ ae_name = archive_read_disk_uname(&a->archive,
+ ae_id);
+ }
+
+ for (i = 0; i < (int)(sizeof(acl_inherit_map) /
+ sizeof(acl_inherit_map[0])); ++i) {
+ if ((ace->a_flags &
+ acl_inherit_map[i].platform_inherit) != 0)
+ ae_perm |=
+ acl_inherit_map[i].archive_inherit;
+ }
+
+ for (i = 0; i < (int)(sizeof(acl_perm_map) /
+ sizeof(acl_perm_map[0])); ++i) {
+ if ((ace->a_access_mask &
+ acl_perm_map[i].platform_perm) != 0)
+ ae_perm |=
+ acl_perm_map[i].archive_perm;
+ }
+ } else {
+ aclent = &((aclent_t *)acl->acl_aclp)[e];
+ if ((aclent->a_type & ACL_DEFAULT) != 0)
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+ else
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ ae_id = aclent->a_id;
+
+ switch(aclent->a_type) {
+ case DEF_USER:
+ case USER:
+ ae_name = archive_read_disk_uname(&a->archive,
+ ae_id);
+ ae_tag = ARCHIVE_ENTRY_ACL_USER;
+ break;
+ case DEF_GROUP:
+ case GROUP:
+ ae_name = archive_read_disk_gname(&a->archive,
+ ae_id);
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+ break;
+ case DEF_CLASS_OBJ:
+ case CLASS_OBJ:
+ ae_tag = ARCHIVE_ENTRY_ACL_MASK;
+ break;
+ case DEF_USER_OBJ:
+ case USER_OBJ:
+ ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+ break;
+ case DEF_GROUP_OBJ:
+ case GROUP_OBJ:
+ ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+ break;
+ case DEF_OTHER_OBJ:
+ case OTHER_OBJ:
+ ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
+ break;
+ default:
+ /* Unknown tag type, skip */
+ continue;
+ }
+
+ if ((aclent->a_perm & 1) != 0)
+ ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE;
+ if ((aclent->a_perm & 2) != 0)
+ ae_perm |= ARCHIVE_ENTRY_ACL_WRITE;
+ if ((aclent->a_perm & 4) != 0)
+ ae_perm |= ARCHIVE_ENTRY_ACL_READ;
+ } /* default_entry_acl_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4 */
+
+ archive_entry_acl_add_entry(entry, entry_acl_type,
+ ae_perm, ae_tag, ae_id, ae_name);
+ }
+ return (ARCHIVE_OK);
+}
+#else /* !HAVE_SUN_ACL */
+/*
+ * Translate POSIX.1e (Linux), FreeBSD (both POSIX.1e and NFSv4) and
+ * MacOS (NFSv4 only) ACLs into libarchive internal structure
+ */
static int
translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
{
acl_tag_t acl_tag;
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4
acl_entry_type_t acl_type;
+ int brand;
+#endif
+#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
acl_flagset_t acl_flagset;
- int brand, r;
#endif
acl_entry_t acl_entry;
acl_permset_t acl_permset;
int i, entry_acl_type;
- int s, ae_id, ae_tag, ae_perm;
+ int r, s, ae_id, ae_tag, ae_perm;
+#if !HAVE_DARWIN_ACL
+ void *q;
+#endif
const char *ae_name;
-
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4
// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
// Make sure the "brand" on this ACL is consistent
// with the default_entry_acl_type bits provided.
- acl_get_brand_np(acl, &brand);
+ if (acl_get_brand_np(acl, &brand) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to read ACL brand");
+ return (ARCHIVE_WARN);
+ }
switch (brand) {
case ACL_BRAND_POSIX:
switch (default_entry_acl_type) {
@@ -556,40 +1197,67 @@ translate_acl(struct archive_read_disk *a,
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
break;
default:
- // XXX set warning message?
- return ARCHIVE_FAILED;
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Invalid ACL entry type for POSIX.1e ACL");
+ return (ARCHIVE_WARN);
}
break;
case ACL_BRAND_NFS4:
if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
- // XXX set warning message?
- return ARCHIVE_FAILED;
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Invalid ACL entry type for NFSv4 ACL");
+ return (ARCHIVE_WARN);
}
break;
default:
- // XXX set warning message?
- return ARCHIVE_FAILED;
- break;
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Unknown ACL brand");
+ return (ARCHIVE_WARN);
}
#endif
-
s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
- while (s == 1) {
+ if (s == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get first ACL entry");
+ return (ARCHIVE_WARN);
+ }
+
+#if HAVE_DARWIN_ACL
+ while (s == 0)
+#else /* FreeBSD, Linux */
+ while (s == 1)
+#endif
+ {
ae_id = -1;
ae_name = NULL;
ae_perm = 0;
- acl_get_tag_type(acl_entry, &acl_tag);
+ if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get ACL tag type");
+ return (ARCHIVE_WARN);
+ }
switch (acl_tag) {
+#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
case ACL_USER:
- ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
- ae_name = archive_read_disk_uname(&a->archive, ae_id);
+ q = acl_get_qualifier(acl_entry);
+ if (q != NULL) {
+ ae_id = (int)*(uid_t *)q;
+ acl_free(q);
+ ae_name = archive_read_disk_uname(&a->archive,
+ ae_id);
+ }
ae_tag = ARCHIVE_ENTRY_ACL_USER;
break;
case ACL_GROUP:
- ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry);
- ae_name = archive_read_disk_gname(&a->archive, ae_id);
+ q = acl_get_qualifier(acl_entry);
+ if (q != NULL) {
+ ae_id = (int)*(gid_t *)q;
+ acl_free(q);
+ ae_name = archive_read_disk_gname(&a->archive,
+ ae_id);
+ }
ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
break;
case ACL_MASK:
@@ -604,24 +1272,52 @@ translate_acl(struct archive_read_disk *a,
case ACL_OTHER:
ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
break;
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4
case ACL_EVERYONE:
ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
break;
#endif
+#else /* HAVE_DARWIN_ACL */
+ case ACL_EXTENDED_ALLOW:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+ r = translate_guid(&a->archive, acl_entry, &ae_id,
+ &ae_tag, &ae_name);
+ break;
+ case ACL_EXTENDED_DENY:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+ r = translate_guid(&a->archive, acl_entry, &ae_id,
+ &ae_tag, &ae_name);
+ break;
+#endif /* HAVE_DARWIN_ACL */
default:
/* Skip types that libarchive can't support. */
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
continue;
}
- // XXX acl type maps to allow/deny/audit/YYYY bits
- // XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
- // non-NFSv4 ACLs
+#if HAVE_DARWIN_ACL
+ /* Skip if translate_guid() above failed */
+ if (r != 0) {
+ s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
+ continue;
+ }
+#endif
+
+#if !HAVE_DARWIN_ACL
+ // XXX acl_type maps to allow/deny/audit/YYYY bits
entry_acl_type = default_entry_acl_type;
-#ifdef ACL_TYPE_NFS4
- r = acl_get_entry_type_np(acl_entry, &acl_type);
- if (r == 0) {
+#endif
+#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
+ if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+#if HAVE_ACL_TYPE_NFS4
+ /*
+ * acl_get_entry_type_np() fails with non-NFSv4 ACLs
+ */
+ if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
+ archive_set_error(&a->archive, errno, "Failed "
+ "to get ACL type from a NFSv4 ACL entry");
+ return (ARCHIVE_WARN);
+ }
switch (acl_type) {
case ACL_ENTRY_TYPE_ALLOW:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
@@ -635,29 +1331,54 @@ translate_acl(struct archive_read_disk *a,
case ACL_ENTRY_TYPE_ALARM:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
break;
+ default:
+ archive_set_error(&a->archive, errno,
+ "Invalid NFSv4 ACL entry type");
+ return (ARCHIVE_WARN);
}
- }
-
- /*
- * Libarchive stores "flag" (NFSv4 inheritance bits)
- * in the ae_perm bitmap.
- */
- acl_get_flagset_np(acl_entry, &acl_flagset);
- for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
- if (acl_get_flag_np(acl_flagset,
- acl_inherit_map[i].platform_inherit))
- ae_perm |= acl_inherit_map[i].archive_inherit;
+#endif /* HAVE_ACL_TYPE_NFS4 */
- }
-#endif
+ /*
+ * Libarchive stores "flag" (NFSv4 inheritance bits)
+ * in the ae_perm bitmap.
+ *
+ * acl_get_flagset_np() fails with non-NFSv4 ACLs
+ */
+ if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get flagset from a NFSv4 ACL entry");
+ return (ARCHIVE_WARN);
+ }
+ for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
+ r = acl_get_flag_np(acl_flagset,
+ acl_inherit_map[i].platform_inherit);
+ if (r == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to check flag in a NFSv4 "
+ "ACL flagset");
+ return (ARCHIVE_WARN);
+ } else if (r)
+ ae_perm |= acl_inherit_map[i].archive_inherit;
+ }
+ }
+#endif /* HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL */
- acl_get_permset(acl_entry, &acl_permset);
+ if (acl_get_permset(acl_entry, &acl_permset) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get ACL permission set");
+ return (ARCHIVE_WARN);
+ }
for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
/*
* acl_get_perm() is spelled differently on different
* platforms; see above.
*/
- if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm))
+ r = ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm);
+ if (r == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to check permission in an ACL permission set");
+ return (ARCHIVE_WARN);
+ } else if (r)
ae_perm |= acl_perm_map[i].archive_perm;
}
@@ -666,10 +1387,18 @@ translate_acl(struct archive_read_disk *a,
ae_id, ae_name);
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
+#if !HAVE_DARWIN_ACL
+ if (s == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get next ACL entry");
+ return (ARCHIVE_WARN);
+ }
+#endif
}
return (ARCHIVE_OK);
}
-#else
+#endif /* !HAVE_SUN_ACL */
+#else /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */
static int
setup_acls(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
@@ -679,7 +1408,7 @@ setup_acls(struct archive_read_disk *a,
(void)fd; /* UNUSED */
return (ARCHIVE_OK);
}
-#endif
+#endif /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */
#if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \
HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \
@@ -699,15 +1428,10 @@ setup_acls(struct archive_read_disk *a,
static int
setup_xattr(struct archive_read_disk *a,
- struct archive_entry *entry, const char *name, int fd)
+ struct archive_entry *entry, const char *name, int fd, const char *accpath)
{
ssize_t size;
void *value = NULL;
- const char *accpath;
-
- accpath = archive_entry_sourcepath(entry);
- if (accpath == NULL)
- accpath = archive_entry_pathname(entry);
#if HAVE_FGETXATTR
if (fd >= 0)
@@ -772,21 +1496,23 @@ setup_xattrs(struct archive_read_disk *a,
const char *path;
ssize_t list_size;
- path = archive_entry_sourcepath(entry);
- if (path == NULL)
- path = archive_entry_pathname(entry);
+ path = NULL;
- if (*fd < 0 && a->tree != NULL) {
- if (a->follow_symlinks ||
- archive_entry_filetype(entry) != AE_IFLNK)
- *fd = a->open_on_current_dir(a->tree, path,
- O_RDONLY | O_NONBLOCK);
- if (*fd < 0) {
- if (a->tree_enter_working_dir(a->tree) != 0) {
- archive_set_error(&a->archive, errno,
- "Couldn't access %s", path);
- return (ARCHIVE_FAILED);
- }
+ if (*fd < 0) {
+ path = archive_entry_sourcepath(entry);
+ if (path == NULL || (a->tree != NULL &&
+ a->tree_enter_working_dir(a->tree) != 0))
+ path = archive_entry_pathname(entry);
+ if (path == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Couldn't determine file path to read "
+ "extended attributes");
+ return (ARCHIVE_WARN);
+ }
+ if (a->tree != NULL && (a->follow_symlinks ||
+ archive_entry_filetype(entry) != AE_IFLNK)) {
+ *fd = a->open_on_current_dir(a->tree,
+ path, O_RDONLY | O_NONBLOCK);
}
}
@@ -849,7 +1575,7 @@ setup_xattrs(struct archive_read_disk *a,
if (strncmp(p, "system.", 7) == 0 ||
strncmp(p, "xfsroot.", 8) == 0)
continue;
- setup_xattr(a, entry, p, *fd);
+ setup_xattr(a, entry, p, *fd, path);
}
free(list);
@@ -870,19 +1596,16 @@ setup_xattrs(struct archive_read_disk *a,
*/
static int
setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
- int namespace, const char *name, const char *fullname, int fd);
+ int namespace, const char *name, const char *fullname, int fd,
+ const char *path);
static int
setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
- int namespace, const char *name, const char *fullname, int fd)
+ int namespace, const char *name, const char *fullname, int fd,
+ const char *accpath)
{
ssize_t size;
void *value = NULL;
- const char *accpath;
-
- accpath = archive_entry_sourcepath(entry);
- if (accpath == NULL)
- accpath = archive_entry_pathname(entry);
if (fd >= 0)
size = extattr_get_fd(fd, namespace, name, NULL, 0);
@@ -932,21 +1655,23 @@ setup_xattrs(struct archive_read_disk *a,
const char *path;
int namespace = EXTATTR_NAMESPACE_USER;
- path = archive_entry_sourcepath(entry);
- if (path == NULL)
- path = archive_entry_pathname(entry);
+ path = NULL;
- if (*fd < 0 && a->tree != NULL) {
- if (a->follow_symlinks ||
- archive_entry_filetype(entry) != AE_IFLNK)
- *fd = a->open_on_current_dir(a->tree, path,
- O_RDONLY | O_NONBLOCK);
- if (*fd < 0) {
- if (a->tree_enter_working_dir(a->tree) != 0) {
- archive_set_error(&a->archive, errno,
- "Couldn't access %s", path);
- return (ARCHIVE_FAILED);
- }
+ if (*fd < 0) {
+ path = archive_entry_sourcepath(entry);
+ if (path == NULL || (a->tree != NULL &&
+ a->tree_enter_working_dir(a->tree) != 0))
+ path = archive_entry_pathname(entry);
+ if (path == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Couldn't determine file path to read "
+ "extended attributes");
+ return (ARCHIVE_WARN);
+ }
+ if (a->tree != NULL && (a->follow_symlinks ||
+ archive_entry_filetype(entry) != AE_IFLNK)) {
+ *fd = a->open_on_current_dir(a->tree,
+ path, O_RDONLY | O_NONBLOCK);
}
}
@@ -996,7 +1721,7 @@ setup_xattrs(struct archive_read_disk *a,
name = buff + strlen(buff);
memcpy(name, p + 1, len);
name[len] = '\0';
- setup_xattr(a, entry, namespace, name, buff, *fd);
+ setup_xattr(a, entry, namespace, name, buff, *fd, path);
p += 1 + len;
}
@@ -1024,7 +1749,7 @@ setup_xattrs(struct archive_read_disk *a,
#if defined(HAVE_LINUX_FIEMAP_H)
/*
- * Linux sparse interface.
+ * Linux FIEMAP sparse interface.
*
* The FIEMAP ioctl returns an "extent" for each physical allocation
* on disk. We need to process those to generate a more compact list
@@ -1039,7 +1764,7 @@ setup_xattrs(struct archive_read_disk *a,
*/
static int
-setup_sparse(struct archive_read_disk *a,
+setup_sparse_fiemap(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
{
char buff[4096];
@@ -1090,8 +1815,8 @@ setup_sparse(struct archive_read_disk *a,
if (r < 0) {
/* When something error happens, it is better we
* should return ARCHIVE_OK because an earlier
- * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
- goto exit_setup_sparse;
+ * version(<2.6.28) cannot perform FS_IOC_FIEMAP. */
+ goto exit_setup_sparse_fiemap;
}
if (fm->fm_mapped_extents == 0) {
if (iters == 0) {
@@ -1126,14 +1851,24 @@ setup_sparse(struct archive_read_disk *a,
} else
break;
}
-exit_setup_sparse:
+exit_setup_sparse_fiemap:
return (exit_sts);
}
-#elif defined(SEEK_HOLE) && defined(SEEK_DATA) && defined(_PC_MIN_HOLE_SIZE)
+#if !defined(SEEK_HOLE) || !defined(SEEK_DATA)
+static int
+setup_sparse(struct archive_read_disk *a,
+ struct archive_entry *entry, int *fd)
+{
+ return setup_sparse_fiemap(a, entry, fd);
+}
+#endif
+#endif /* defined(HAVE_LINUX_FIEMAP_H) */
+
+#if defined(SEEK_HOLE) && defined(SEEK_DATA)
/*
- * FreeBSD and Solaris sparse interface.
+ * SEEK_HOLE sparse interface (FreeBSD, Linux, Solaris)
*/
static int
@@ -1141,8 +1876,8 @@ setup_sparse(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
{
int64_t size;
- off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */
- off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */
+ off_t initial_off;
+ off_t off_s, off_e;
int exit_sts = ARCHIVE_OK;
int check_fully_sparse = 0;
@@ -1168,8 +1903,10 @@ setup_sparse(struct archive_read_disk *a,
}
if (*fd >= 0) {
+#ifdef _PC_MIN_HOLE_SIZE
if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0)
return (ARCHIVE_OK);
+#endif
initial_off = lseek(*fd, 0, SEEK_CUR);
if (initial_off != 0)
lseek(*fd, 0, SEEK_SET);
@@ -1180,8 +1917,10 @@ setup_sparse(struct archive_read_disk *a,
if (path == NULL)
path = archive_entry_pathname(entry);
+#ifdef _PC_MIN_HOLE_SIZE
if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
return (ARCHIVE_OK);
+#endif
*fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
if (*fd < 0) {
archive_set_error(&a->archive, errno,
@@ -1192,6 +1931,19 @@ setup_sparse(struct archive_read_disk *a,
initial_off = 0;
}
+#ifndef _PC_MIN_HOLE_SIZE
+ /* Check if the underlying filesystem supports seek hole */
+ off_s = lseek(*fd, 0, SEEK_HOLE);
+ if (off_s < 0)
+#if defined(HAVE_LINUX_FIEMAP_H)
+ return setup_sparse_fiemap(a, entry, fd);
+#else
+ goto exit_setup_sparse;
+#endif
+ else if (off_s > 0)
+ lseek(*fd, 0, SEEK_SET);
+#endif
+
off_s = 0;
size = archive_entry_size(entry);
while (off_s < size) {
@@ -1223,7 +1975,7 @@ setup_sparse(struct archive_read_disk *a,
goto exit_setup_sparse;
}
if (off_s == 0 && off_e == size)
- break;/* This is not spase. */
+ break;/* This is not sparse. */
archive_entry_sparse_add_entry(entry, off_s,
off_e - off_s);
off_s = off_e;
@@ -1241,7 +1993,7 @@ exit_setup_sparse:
return (exit_sts);
}
-#else
+#elif !defined(HAVE_LINUX_FIEMAP_H)
/*
* Generic (stub) sparse support.
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
index 22a1f14..6961ae6 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
@@ -165,7 +165,7 @@ struct filesystem {
int synthetic;
int remote;
int noatime;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
size_t name_max;
#endif
long incr_xfer_size;
@@ -200,7 +200,7 @@ struct tree {
DIR *d;
#define INVALID_DIR_HANDLE NULL
struct dirent *de;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
struct dirent *dirent;
size_t dirent_allocated;
#endif
@@ -244,7 +244,7 @@ struct tree {
int initial_filesystem_id;
int current_filesystem_id;
int max_filesystem_id;
- int allocated_filesytem;
+ int allocated_filesystem;
int entry_fd;
int entry_eof;
@@ -465,8 +465,7 @@ archive_read_disk_new(void)
a->entry = archive_entry_new2(&a->archive);
a->lookup_uname = trivial_lookup_uname;
a->lookup_gname = trivial_lookup_gname;
- a->enable_copyfile = 1;
- a->traverse_mount_points = 1;
+ a->flags = ARCHIVE_READDISK_MAC_COPYFILE;
a->open_on_current_dir = open_on_current_dir;
a->tree_current_dir_fd = tree_current_dir_fd;
a->tree_enter_working_dir = tree_enter_working_dir;
@@ -563,25 +562,19 @@ archive_read_disk_set_symlink_hybrid(struct archive *_a)
int
archive_read_disk_set_atime_restored(struct archive *_a)
{
-#ifndef HAVE_UTIMES
- static int warning_done = 0;
-#endif
struct archive_read_disk *a = (struct archive_read_disk *)_a;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime");
#ifdef HAVE_UTIMES
- a->restore_time = 1;
+ a->flags |= ARCHIVE_READDISK_RESTORE_ATIME;
if (a->tree != NULL)
a->tree->flags |= needsRestoreTimes;
return (ARCHIVE_OK);
#else
- if (warning_done)
- /* Warning was already emitted; suppress further warnings. */
- return (ARCHIVE_OK);
-
+ /* Display warning and unset flag */
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot restore access time on this system");
- warning_done = 1;
+ a->flags &= ~ARCHIVE_READDISK_RESTORE_ATIME;
return (ARCHIVE_WARN);
#endif
}
@@ -595,29 +588,14 @@ archive_read_disk_set_behavior(struct archive *_a, int flags)
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
+ a->flags = flags;
+
if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
r = archive_read_disk_set_atime_restored(_a);
else {
- a->restore_time = 0;
if (a->tree != NULL)
a->tree->flags &= ~needsRestoreTimes;
}
- if (flags & ARCHIVE_READDISK_HONOR_NODUMP)
- a->honor_nodump = 1;
- else
- a->honor_nodump = 0;
- if (flags & ARCHIVE_READDISK_MAC_COPYFILE)
- a->enable_copyfile = 1;
- else
- a->enable_copyfile = 0;
- if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS)
- a->traverse_mount_points = 0;
- else
- a->traverse_mount_points = 1;
- if (flags & ARCHIVE_READDISK_NO_XATTR)
- a->suppress_xattr = 1;
- else
- a->suppress_xattr = 0;
return (r);
}
@@ -675,7 +653,7 @@ setup_suitable_read_buffer(struct archive_read_disk *a)
asize = cf->min_xfer_size;
/* Increase a buffer size up to 64K bytes in
- * a proper incremant size. */
+ * a proper increment size. */
while (asize < 1024*64)
asize += incr;
/* Take a margin to adjust to the filesystem
@@ -918,7 +896,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
} while (lst == NULL);
#ifdef __APPLE__
- if (a->enable_copyfile) {
+ if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) {
/* If we're using copyfile(), ignore "._XXX" files. */
const char *bname = strrchr(tree_current_path(t), '/');
if (bname == NULL)
@@ -938,7 +916,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
r = archive_match_path_excluded(a->matching, entry);
if (r < 0) {
archive_set_error(&(a->archive), errno,
- "Faild : %s", archive_error_string(a->matching));
+ "Failed : %s", archive_error_string(a->matching));
return (r);
}
if (r) {
@@ -989,7 +967,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
}
if (t->initial_filesystem_id == -1)
t->initial_filesystem_id = t->current_filesystem_id;
- if (!a->traverse_mount_points) {
+ if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) {
if (t->initial_filesystem_id != t->current_filesystem_id)
descend = 0;
}
@@ -999,12 +977,14 @@ next_entry(struct archive_read_disk *a, struct tree *t,
* Honor nodump flag.
* If the file is marked with nodump flag, do not return this entry.
*/
- if (a->honor_nodump) {
+ if (a->flags & ARCHIVE_READDISK_HONOR_NODUMP) {
#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
if (st->st_flags & UF_NODUMP)
return (ARCHIVE_RETRY);
-#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) &&\
- defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+#elif (defined(FS_IOC_GETFLAGS) && defined(FS_NODUMP_FL) && \
+ defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+ (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) && \
+ defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) {
int stflags;
@@ -1013,9 +993,18 @@ next_entry(struct archive_read_disk *a, struct tree *t,
O_RDONLY | O_NONBLOCK | O_CLOEXEC);
__archive_ensure_cloexec_flag(t->entry_fd);
if (t->entry_fd >= 0) {
- r = ioctl(t->entry_fd, EXT2_IOC_GETFLAGS,
+ r = ioctl(t->entry_fd,
+#ifdef FS_IOC_GETFLAGS
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
&stflags);
+#ifdef FS_NODUMP_FL
+ if (r == 0 && (stflags & FS_NODUMP_FL) != 0)
+#else
if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0)
+#endif
return (ARCHIVE_RETRY);
}
}
@@ -1026,7 +1015,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
/* Save the times to be restored. This must be in before
* calling archive_read_disk_descend() or any chance of it,
- * especially, invokng a callback. */
+ * especially, invoking a callback. */
t->restore_time.mtime = archive_entry_mtime(entry);
t->restore_time.mtime_nsec = archive_entry_mtime_nsec(entry);
t->restore_time.atime = archive_entry_atime(entry);
@@ -1041,7 +1030,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
r = archive_match_time_excluded(a->matching, entry);
if (r < 0) {
archive_set_error(&(a->archive), errno,
- "Faild : %s", archive_error_string(a->matching));
+ "Failed : %s", archive_error_string(a->matching));
return (r);
}
if (r) {
@@ -1067,7 +1056,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
r = archive_match_owner_excluded(a->matching, entry);
if (r < 0) {
archive_set_error(&(a->archive), errno,
- "Faild : %s", archive_error_string(a->matching));
+ "Failed : %s", archive_error_string(a->matching));
return (r);
}
if (r) {
@@ -1340,10 +1329,11 @@ _archive_read_disk_open(struct archive *_a, const char *pathname)
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (a->tree != NULL)
- a->tree = tree_reopen(a->tree, pathname, a->restore_time);
+ a->tree = tree_reopen(a->tree, pathname,
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
else
a->tree = tree_open(pathname, a->symlink_mode,
- a->restore_time);
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
if (a->tree == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate tar data");
@@ -1382,7 +1372,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
for (i = 0; i < t->max_filesystem_id; i++) {
if (t->filesystem_table[i].dev == dev) {
- /* There is the filesytem ID we've already generated. */
+ /* There is the filesystem ID we've already generated. */
t->current_filesystem_id = i;
t->current_filesystem = &(t->filesystem_table[i]);
return (ARCHIVE_OK);
@@ -1390,10 +1380,10 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
}
/*
- * This is the new filesytem which we have to generate a new ID for.
+ * This is the new filesystem which we have to generate a new ID for.
*/
fid = t->max_filesystem_id++;
- if (t->max_filesystem_id > t->allocated_filesytem) {
+ if (t->max_filesystem_id > t->allocated_filesystem) {
size_t s;
void *p;
@@ -1406,7 +1396,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
return (ARCHIVE_FATAL);
}
t->filesystem_table = (struct filesystem *)p;
- t->allocated_filesytem = s;
+ t->allocated_filesystem = s;
}
t->current_filesystem_id = fid;
t->current_filesystem = &(t->filesystem_table[fid]);
@@ -1504,7 +1494,20 @@ setup_current_filesystem(struct archive_read_disk *a)
struct tree *t = a->tree;
struct statfs sfs;
#if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC)
+/* TODO: configure should set GETVFSBYNAME_ARG_TYPE to make
+ * this accurate; some platforms have both and we need the one that's
+ * used by getvfsbyname()
+ *
+ * Then the following would become:
+ * #if defined(GETVFSBYNAME_ARG_TYPE)
+ * GETVFSBYNAME_ARG_TYPE vfc;
+ * #endif
+ */
+# if defined(HAVE_STRUCT_XVFSCONF)
struct xvfsconf vfc;
+# else
+ struct vfsconf vfc;
+# endif
#endif
int r, xr = 0;
#if !defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
@@ -1579,7 +1582,7 @@ setup_current_filesystem(struct archive_read_disk *a)
#endif
t->current_filesystem->noatime = 0;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
/* Set maximum filename length. */
#if defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
t->current_filesystem->name_max = sfs.f_namemax;
@@ -1602,7 +1605,7 @@ setup_current_filesystem(struct archive_read_disk *a)
else
t->current_filesystem->name_max = nm;
#endif
-#endif /* HAVE_READDIR_R */
+#endif /* USE_READDIR_R */
return (ARCHIVE_OK);
}
@@ -1643,7 +1646,7 @@ setup_current_filesystem(struct archive_read_disk *a)
archive_set_error(&a->archive, errno, "statvfs failed");
return (ARCHIVE_FAILED);
} else if (xr == 1) {
- /* Usuall come here unless NetBSD supports _PC_REC_XFER_ALIGN
+ /* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN
* for pathconf() function. */
t->current_filesystem->xfer_align = sfs.f_frsize;
t->current_filesystem->max_xfer_size = -1;
@@ -1804,7 +1807,7 @@ setup_current_filesystem(struct archive_read_disk *a)
#endif
t->current_filesystem->noatime = 0;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
/* Set maximum filename length. */
t->current_filesystem->name_max = sfs.f_namelen;
#endif
@@ -1888,7 +1891,7 @@ setup_current_filesystem(struct archive_read_disk *a)
#endif
t->current_filesystem->noatime = 0;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
/* Set maximum filename length. */
t->current_filesystem->name_max = sfs.f_namemax;
#endif
@@ -1905,7 +1908,7 @@ static int
setup_current_filesystem(struct archive_read_disk *a)
{
struct tree *t = a->tree;
-#if defined(_PC_NAME_MAX) && defined(HAVE_READDIR_R)
+#if defined(_PC_NAME_MAX) && defined(USE_READDIR_R)
long nm;
#endif
t->current_filesystem->synthetic = -1;/* Not supported */
@@ -1917,7 +1920,7 @@ setup_current_filesystem(struct archive_read_disk *a)
t->current_filesystem->min_xfer_size = -1;
t->current_filesystem->incr_xfer_size = -1;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
/* Set maximum filename length. */
# if defined(_PC_NAME_MAX)
if (tree_current_is_symblic_link_target(t)) {
@@ -1931,7 +1934,7 @@ setup_current_filesystem(struct archive_read_disk *a)
if (nm == -1)
# endif /* _PC_NAME_MAX */
/*
- * Some sysmtes (HP-UX or others?) incorrectly defined
+ * Some systems (HP-UX or others?) incorrectly defined
* NAME_MAX macro to be a smaller value.
*/
# if defined(NAME_MAX) && NAME_MAX >= 255
@@ -1945,7 +1948,7 @@ setup_current_filesystem(struct archive_read_disk *a)
else
t->current_filesystem->name_max = nm;
# endif /* _PC_NAME_MAX */
-#endif /* HAVE_READDIR_R */
+#endif /* USE_READDIR_R */
return (ARCHIVE_OK);
}
@@ -2050,8 +2053,7 @@ tree_push(struct tree *t, const char *path, int filesystem_id,
{
struct tree_entry *te;
- te = malloc(sizeof(*te));
- memset(te, 0, sizeof(*te));
+ te = calloc(1, sizeof(*te));
te->next = t->stack;
te->parent = t->current;
if (te->parent)
@@ -2109,9 +2111,8 @@ tree_open(const char *path, int symlink_mode, int restore_time)
{
struct tree *t;
- if ((t = malloc(sizeof(*t))) == NULL)
+ if ((t = calloc(1, sizeof(*t))) == NULL)
return (NULL);
- memset(t, 0, sizeof(*t));
archive_string_init(&t->path);
archive_string_ensure(&t->path, 31);
t->initial_symlink_mode = symlink_mode;
@@ -2121,7 +2122,7 @@ tree_open(const char *path, int symlink_mode, int restore_time)
static struct tree *
tree_reopen(struct tree *t, const char *path, int restore_time)
{
- t->flags = (restore_time)?needsRestoreTimes:0;
+ t->flags = (restore_time != 0)?needsRestoreTimes:0;
t->flags |= onInitialDir;
t->visit_type = 0;
t->tree_errno = 0;
@@ -2353,7 +2354,7 @@ tree_dir_next_posix(struct tree *t)
size_t namelen;
if (t->d == NULL) {
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
size_t dirent_size;
#endif
@@ -2374,7 +2375,7 @@ tree_dir_next_posix(struct tree *t)
t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
return (t->visit_type);
}
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
dirent_size = offsetof(struct dirent, d_name) +
t->filesystem_table[t->current->filesystem_id].name_max + 1;
if (t->dirent == NULL || t->dirent_allocated < dirent_size) {
@@ -2391,11 +2392,11 @@ tree_dir_next_posix(struct tree *t)
}
t->dirent_allocated = dirent_size;
}
-#endif /* HAVE_READDIR_R */
+#endif /* USE_READDIR_R */
}
for (;;) {
errno = 0;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
r = readdir_r(t->d, t->dirent, &t->de);
#ifdef _AIX
/* Note: According to the man page, return value 9 indicates
@@ -2647,7 +2648,7 @@ tree_free(struct tree *t)
if (t == NULL)
return;
archive_string_free(&t->path);
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
free(t->dirent);
#endif
free(t->sparse_list);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h b/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h
index 2569321..b5a8328 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h
@@ -63,16 +63,8 @@ struct archive_read_disk {
int (*tree_current_dir_fd)(struct tree*);
int (*tree_enter_working_dir)(struct tree*);
- /* Set 1 if users request to restore atime . */
- int restore_time;
- /* Set 1 if users request to honor nodump flag . */
- int honor_nodump;
- /* Set 1 if users request to enable mac copyfile. */
- int enable_copyfile;
- /* Set 1 if users request to traverse mount points. */
- int traverse_mount_points;
- /* Set 1 if users want to suppress xattr information. */
- int suppress_xattr;
+ /* Bitfield with ARCHIVE_READDISK_* tunables */
+ int flags;
const char * (*lookup_gname)(void *private, int64_t gid);
void (*cleanup_gname)(void *private);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_set_standard_lookup.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_set_standard_lookup.c
index d6b2d55..c7fd247 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_set_standard_lookup.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_set_standard_lookup.c
@@ -232,6 +232,7 @@ static const char *
lookup_uname_helper(struct name_cache *cache, id_t id)
{
struct passwd *result;
+ (void)cache; /* UNUSED */
result = getpwuid((uid_t)id);
@@ -298,6 +299,7 @@ static const char *
lookup_gname_helper(struct name_cache *cache, id_t id)
{
struct group *result;
+ (void)cache; /* UNUSED */
result = getgrgid((gid_t)id);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c
index 566d264..3b90330 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c
@@ -168,7 +168,7 @@ struct tree {
int initial_filesystem_id;
int current_filesystem_id;
int max_filesystem_id;
- int allocated_filesytem;
+ int allocated_filesystem;
HANDLE entry_fh;
int entry_eof;
@@ -389,18 +389,16 @@ archive_read_disk_new(void)
{
struct archive_read_disk *a;
- a = (struct archive_read_disk *)malloc(sizeof(*a));
+ a = (struct archive_read_disk *)calloc(1, sizeof(*a));
if (a == NULL)
return (NULL);
- memset(a, 0, sizeof(*a));
a->archive.magic = ARCHIVE_READ_DISK_MAGIC;
a->archive.state = ARCHIVE_STATE_NEW;
a->archive.vtable = archive_read_disk_vtable();
a->entry = archive_entry_new2(&a->archive);
a->lookup_uname = trivial_lookup_uname;
a->lookup_gname = trivial_lookup_gname;
- a->enable_copyfile = 1;
- a->traverse_mount_points = 1;
+ a->flags = ARCHIVE_READDISK_MAC_COPYFILE;
return (&a->archive);
}
@@ -496,7 +494,7 @@ archive_read_disk_set_atime_restored(struct archive *_a)
struct archive_read_disk *a = (struct archive_read_disk *)_a;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime");
- a->restore_time = 1;
+ a->flags |= ARCHIVE_READDISK_RESTORE_ATIME;
if (a->tree != NULL)
a->tree->flags |= needsRestoreTimes;
return (ARCHIVE_OK);
@@ -511,25 +509,14 @@ archive_read_disk_set_behavior(struct archive *_a, int flags)
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
+ a->flags = flags;
+
if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
r = archive_read_disk_set_atime_restored(_a);
else {
- a->restore_time = 0;
if (a->tree != NULL)
a->tree->flags &= ~needsRestoreTimes;
}
- if (flags & ARCHIVE_READDISK_HONOR_NODUMP)
- a->honor_nodump = 1;
- else
- a->honor_nodump = 0;
- if (flags & ARCHIVE_READDISK_MAC_COPYFILE)
- a->enable_copyfile = 1;
- else
- a->enable_copyfile = 0;
- if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS)
- a->traverse_mount_points = 0;
- else
- a->traverse_mount_points = 1;
return (r);
}
@@ -803,7 +790,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
r = archive_match_path_excluded(a->matching, entry);
if (r < 0) {
archive_set_error(&(a->archive), errno,
- "Faild : %s", archive_error_string(a->matching));
+ "Failed : %s", archive_error_string(a->matching));
return (r);
}
if (r) {
@@ -853,7 +840,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
}
if (t->initial_filesystem_id == -1)
t->initial_filesystem_id = t->current_filesystem_id;
- if (!a->traverse_mount_points) {
+ if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) {
if (t->initial_filesystem_id != t->current_filesystem_id)
return (ARCHIVE_RETRY);
}
@@ -863,7 +850,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
/* Save the times to be restored. This must be in before
* calling archive_read_disk_descend() or any chance of it,
- * especially, invokng a callback. */
+ * especially, invoking a callback. */
t->restore_time.lastWriteTime = st->ftLastWriteTime;
t->restore_time.lastAccessTime = st->ftLastAccessTime;
t->restore_time.filetype = archive_entry_filetype(entry);
@@ -875,7 +862,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
r = archive_match_time_excluded(a->matching, entry);
if (r < 0) {
archive_set_error(&(a->archive), errno,
- "Faild : %s", archive_error_string(a->matching));
+ "Failed : %s", archive_error_string(a->matching));
return (r);
}
if (r) {
@@ -901,7 +888,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
r = archive_match_owner_excluded(a->matching, entry);
if (r < 0) {
archive_set_error(&(a->archive), errno,
- "Faild : %s", archive_error_string(a->matching));
+ "Failed : %s", archive_error_string(a->matching));
return (r);
}
if (r) {
@@ -1220,9 +1207,11 @@ _archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname)
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (a->tree != NULL)
- a->tree = tree_reopen(a->tree, pathname, a->restore_time);
+ a->tree = tree_reopen(a->tree, pathname,
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
else
- a->tree = tree_open(pathname, a->symlink_mode, a->restore_time);
+ a->tree = tree_open(pathname, a->symlink_mode,
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
if (a->tree == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate directory traversal data");
@@ -1261,7 +1250,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
for (i = 0; i < t->max_filesystem_id; i++) {
if (t->filesystem_table[i].dev == dev) {
- /* There is the filesytem ID we've already generated. */
+ /* There is the filesystem ID we've already generated. */
t->current_filesystem_id = i;
t->current_filesystem = &(t->filesystem_table[i]);
return (ARCHIVE_OK);
@@ -1269,10 +1258,10 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
}
/*
- * There is a new filesytem, we generate a new ID for.
+ * There is a new filesystem, we generate a new ID for.
*/
fid = t->max_filesystem_id++;
- if (t->max_filesystem_id > t->allocated_filesytem) {
+ if (t->max_filesystem_id > t->allocated_filesystem) {
size_t s;
void *p;
@@ -1285,7 +1274,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
return (ARCHIVE_FATAL);
}
t->filesystem_table = (struct filesystem *)p;
- t->allocated_filesytem = (int)s;
+ t->allocated_filesystem = (int)s;
}
t->current_filesystem_id = fid;
t->current_filesystem = &(t->filesystem_table[fid]);
@@ -1402,7 +1391,7 @@ close_and_restore_time(HANDLE h, struct tree *t, struct restore_time *rt)
if (h == INVALID_HANDLE_VALUE && AE_IFLNK == rt->filetype)
return (0);
- /* Close a file descritor.
+ /* Close a file descriptor.
* It will not be used for SetFileTime() because it has been opened
* by a read only mode.
*/
@@ -1437,8 +1426,7 @@ tree_push(struct tree *t, const wchar_t *path, const wchar_t *full_path,
{
struct tree_entry *te;
- te = malloc(sizeof(*te));
- memset(te, 0, sizeof(*te));
+ te = calloc(1, sizeof(*te));
te->next = t->stack;
te->parent = t->current;
if (te->parent)
@@ -1507,8 +1495,7 @@ tree_open(const wchar_t *path, int symlink_mode, int restore_time)
{
struct tree *t;
- t = malloc(sizeof(*t));
- memset(t, 0, sizeof(*t));
+ t = calloc(1, sizeof(*t));
archive_string_init(&(t->full_path));
archive_string_init(&t->path);
archive_wstring_ensure(&t->path, 15);
@@ -1522,7 +1509,7 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time)
struct archive_wstring ws;
wchar_t *pathname, *p, *base;
- t->flags = (restore_time)?needsRestoreTimes:0;
+ t->flags = (restore_time != 0)?needsRestoreTimes:0;
t->visit_type = 0;
t->tree_errno = 0;
t->full_path_dir_length = 0;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_extract2.c b/Utilities/cmlibarchive/libarchive/archive_read_extract2.c
index 7b2c126..4febd8c 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_extract2.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_extract2.c
@@ -52,12 +52,11 @@ struct archive_read_extract *
__archive_read_get_extract(struct archive_read *a)
{
if (a->extract == NULL) {
- a->extract = (struct archive_read_extract *)malloc(sizeof(*a->extract));
+ a->extract = (struct archive_read_extract *)calloc(1, sizeof(*a->extract));
if (a->extract == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't extract");
return (NULL);
}
- memset(a->extract, 0, sizeof(*a->extract));
a->cleanup_archive_extract = archive_read_extract_cleanup;
}
return (a->extract);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c b/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c
index 5611aa8..86635e2 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c
@@ -222,7 +222,7 @@ file_open(struct archive *a, void *client_data)
void *buffer;
const char *filename = NULL;
const wchar_t *wfilename = NULL;
- int fd;
+ int fd = -1;
int is_disk_like = 0;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
off_t mediasize = 0; /* FreeBSD-specific, so off_t okay here. */
@@ -277,7 +277,7 @@ file_open(struct archive *a, void *client_data)
#else
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unexpedted operation in archive_read_open_filename");
- return (ARCHIVE_FATAL);
+ goto fail;
#endif
}
if (fstat(fd, &st) != 0) {
@@ -287,7 +287,7 @@ file_open(struct archive *a, void *client_data)
else
archive_set_error(a, errno, "Can't stat '%s'",
filename);
- return (ARCHIVE_FATAL);
+ goto fail;
}
/*
@@ -356,11 +356,9 @@ file_open(struct archive *a, void *client_data)
mine->block_size = new_block_size;
}
buffer = malloc(mine->block_size);
- if (mine == NULL || buffer == NULL) {
+ if (buffer == NULL) {
archive_set_error(a, ENOMEM, "No memory");
- free(mine);
- free(buffer);
- return (ARCHIVE_FATAL);
+ goto fail;
}
mine->buffer = buffer;
mine->fd = fd;
@@ -372,6 +370,14 @@ file_open(struct archive *a, void *client_data)
mine->use_lseek = 1;
return (ARCHIVE_OK);
+fail:
+ /*
+ * Don't close file descriptors not opened or ones pointing referring
+ * to `FNT_STDIN`.
+ */
+ if (fd != -1 && fd != 0)
+ close(fd);
+ return (ARCHIVE_FATAL);
}
static ssize_t
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c b/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c
index ff935a7..311be47 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c
@@ -70,12 +70,11 @@ archive_read_open_memory2(struct archive *a, const void *buff,
{
struct read_memory_data *mine;
- mine = (struct read_memory_data *)malloc(sizeof(*mine));
+ mine = (struct read_memory_data *)calloc(1, sizeof(*mine));
if (mine == NULL) {
archive_set_error(a, ENOMEM, "No memory");
return (ARCHIVE_FATAL);
}
- memset(mine, 0, sizeof(*mine));
mine->start = mine->p = (const unsigned char *)buff;
mine->end = mine->start + size;
mine->read_size = read_size;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_private.h b/Utilities/cmlibarchive/libarchive/archive_read_private.h
index 9b61a53..78546dc 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_read_private.h
@@ -221,7 +221,7 @@ struct archive_read {
struct {
struct archive_read_passphrase *first;
struct archive_read_passphrase **last;
- int candiate;
+ int candidate;
archive_passphrase_callback *callback;
void *client_data;
} passphrases;
@@ -252,7 +252,6 @@ int64_t __archive_read_consume(struct archive_read *, int64_t);
int64_t __archive_read_filter_consume(struct archive_read_filter *, int64_t);
int __archive_read_program(struct archive_read_filter *, const char *);
void __archive_read_free_filters(struct archive_read *);
-int __archive_read_close_filters(struct archive_read *);
struct archive_read_extract *__archive_read_get_extract(struct archive_read *);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c
index e877917..663e2d3 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c
@@ -180,7 +180,7 @@ lz4_reader_bid(struct archive_read_filter_bidder *self,
return (0);
bits_checked += 8;
BD = buffer[5];
- /* A block maximum size shuld be more than 3. */
+ /* A block maximum size should be more than 3. */
if (((BD & 0x70) >> 4) < 4)
return (0);
/* Reserved bits must be "0". */
@@ -417,7 +417,7 @@ lz4_filter_read_descriptor(struct archive_read_filter *self)
/* Reserved bits must be zero. */
if (bd & 0x8f)
goto malformed_error;
- /* Get a maxinum block size. */
+ /* Get a maximum block size. */
switch (read_buf[1] >> 4) {
case 4: /* 64 KB */
state->flags.block_maximum_size = 64 * 1024;
@@ -595,7 +595,7 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p)
#endif
}
- /* Check if an error happend in decompression process. */
+ /* Check if an error occurred in the decompression process. */
if (uncompressed_size < 0) {
archive_set_error(&(self->archive->archive),
ARCHIVE_ERRNO_MISC, "lz4 decompression failed");
@@ -627,7 +627,7 @@ lz4_filter_read_default_stream(struct archive_read_filter *self, const void **p)
if (state->stage == SELECT_STREAM) {
state->stage = READ_DEFAULT_STREAM;
- /* First, read a desciprtor. */
+ /* First, read a descriptor. */
if((ret = lz4_filter_read_descriptor(self)) != ARCHIVE_OK)
return (ret);
state->stage = READ_DEFAULT_BLOCK;
@@ -706,6 +706,11 @@ lz4_filter_read_legacy_stream(struct archive_read_filter *self, const void **p)
/* Make sure we have a whole block. */
read_buf = __archive_read_filter_ahead(self->upstream,
4 + compressed, NULL);
+ if (read_buf == NULL) {
+ archive_set_error(&(self->archive->archive),
+ ARCHIVE_ERRNO_MISC, "truncated lz4 input");
+ return (ARCHIVE_FATAL);
+ }
ret = LZ4_decompress_safe(read_buf + 4, state->out_block,
compressed, (int)state->out_block_size);
if (ret < 0) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c
index 23c18c7..4356b82 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c
@@ -436,7 +436,7 @@ lzop_filter_read(struct archive_read_filter *self, const void **p)
}
/*
- * Drive lzo uncompresison.
+ * Drive lzo uncompression.
*/
out_size = (lzo_uint)state->uncompressed_size;
r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size,
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c
index 66dc2f4..b8bf128 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c
@@ -430,6 +430,7 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd)
&state->child_stdout);
if (child == -1) {
free(state->out_buf);
+ archive_string_free(&state->description);
free(state);
archive_set_error(&self->archive->archive, EINVAL,
"Can't initialize filter; unable to run program \"%s\"",
@@ -441,6 +442,7 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd)
if (state->child == NULL) {
child_stop(self, state);
free(state->out_buf);
+ archive_string_free(&state->description);
free(state);
archive_set_error(&self->archive->archive, EINVAL,
"Can't initialize filter; unable to run program \"%s\"",
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c
index 787a619..6412979 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c
@@ -312,6 +312,7 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self,
avail -= len;
if (l == 6) {
+ /* "begin " */
if (!uuchar[*b])
return (0);
/* Get a length of decoded bytes. */
@@ -319,30 +320,14 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self,
if (l > 45)
/* Normally, maximum length is 45(character 'M'). */
return (0);
- while (l && len-nl > 0) {
- if (l > 0) {
- if (!uuchar[*b++])
- return (0);
- if (!uuchar[*b++])
- return (0);
- len -= 2;
- --l;
- }
- if (l > 0) {
- if (!uuchar[*b++])
- return (0);
- --len;
- --l;
- }
- if (l > 0) {
- if (!uuchar[*b++])
- return (0);
- --len;
- --l;
- }
+ if (l > len - nl)
+ return (0); /* Line too short. */
+ while (l) {
+ if (!uuchar[*b++])
+ return (0);
+ --len;
+ --l;
}
- if (len-nl < 0)
- return (0);
if (len-nl == 1 &&
(uuchar[*b] || /* Check sum. */
(*b >= 'a' && *b <= 'z'))) {/* Padding data(MINIX). */
@@ -352,8 +337,8 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self,
b += nl;
if (avail && uuchar[*b])
return (firstline+30);
- }
- if (l == 13) {
+ } else if (l == 13) {
+ /* "begin-base64 " */
while (len-nl > 0) {
if (!base64[*b++])
return (0);
@@ -510,6 +495,13 @@ read_more:
}
llen = len;
if ((nl == 0) && (uudecode->state != ST_UUEND)) {
+ if (total == 0 && ravail <= 0) {
+ /* There is nothing more to read, fail */
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Missing format data");
+ return (ARCHIVE_FATAL);
+ }
/*
* Save remaining data which does not contain
* NL('\n','\r').
@@ -566,7 +558,7 @@ read_more:
"Insufficient compressed data");
return (ARCHIVE_FATAL);
}
- /* Get length of undecoded bytes of curent line. */
+ /* Get length of undecoded bytes of current line. */
l = UUDECODE(*b++);
body--;
if (l > body) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c
index 8f48273..a188186 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c
@@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$");
#endif
#if HAVE_LZMA_H
#include <cm_lzma.h>
-#elif HAVE_LZMADEC_H
-#include <lzmadec.h>
#endif
#include "archive.h"
@@ -82,19 +80,6 @@ static ssize_t xz_filter_read(struct archive_read_filter *, const void **);
static int xz_filter_close(struct archive_read_filter *);
static int xz_lzma_bidder_init(struct archive_read_filter *);
-#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
-
-struct private_data {
- lzmadec_stream stream;
- unsigned char *out_block;
- size_t out_block_size;
- int64_t total_out;
- char eof; /* True = found end of compressed data. */
-};
-
-/* Lzma-only filter */
-static ssize_t lzma_filter_read(struct archive_read_filter *, const void **);
-static int lzma_filter_close(struct archive_read_filter *);
#endif
/*
@@ -178,8 +163,6 @@ archive_read_support_filter_lzma(struct archive *_a)
bidder->free = NULL;
#if HAVE_LZMA_H && HAVE_LIBLZMA
return (ARCHIVE_OK);
-#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
- return (ARCHIVE_OK);
#else
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
"Using external lzma program for lzma decompression");
@@ -310,7 +293,7 @@ lzma_bidder_bid(struct archive_read_filter_bidder *self,
/* Second through fifth bytes are dictionary size, stored in
* little-endian order. The minimum dictionary size is
* 1 << 12(4KiB) which the lzma of LZMA SDK uses with option
- * -d12 and the maxinam dictionary size is 1 << 27(128MiB)
+ * -d12 and the maximum dictionary size is 1 << 27(128MiB)
* which the one uses with option -d27.
* NOTE: A comment of LZMA SDK source code says this dictionary
* range is from 1 << 12 to 1 << 30. */
@@ -601,9 +584,7 @@ lzip_init(struct archive_read_filter *self)
return (ARCHIVE_FATAL);
}
ret = lzma_raw_decoder(&(state->stream), filters);
-#if LZMA_VERSION < 50010000
free(filters[0].options);
-#endif
if (ret != LZMA_OK) {
set_error(self, ret);
return (ARCHIVE_FATAL);
@@ -763,175 +744,6 @@ xz_filter_close(struct archive_read_filter *self)
#else
-#if HAVE_LZMADEC_H && HAVE_LIBLZMADEC
-
-/*
- * If we have the older liblzmadec library, then we can handle
- * LZMA streams but not XZ streams.
- */
-
-/*
- * Setup the callbacks.
- */
-static int
-lzma_bidder_init(struct archive_read_filter *self)
-{
- static const size_t out_block_size = 64 * 1024;
- void *out_block;
- struct private_data *state;
- ssize_t ret, avail_in;
-
- self->code = ARCHIVE_FILTER_LZMA;
- self->name = "lzma";
-
- state = (struct private_data *)calloc(sizeof(*state), 1);
- out_block = (unsigned char *)malloc(out_block_size);
- if (state == NULL || out_block == NULL) {
- archive_set_error(&self->archive->archive, ENOMEM,
- "Can't allocate data for lzma decompression");
- free(out_block);
- free(state);
- return (ARCHIVE_FATAL);
- }
-
- self->data = state;
- state->out_block_size = out_block_size;
- state->out_block = out_block;
- self->read = lzma_filter_read;
- self->skip = NULL; /* not supported */
- self->close = lzma_filter_close;
-
- /* Prime the lzma library with 18 bytes of input. */
- state->stream.next_in = (unsigned char *)(uintptr_t)
- __archive_read_filter_ahead(self->upstream, 18, &avail_in);
- if (state->stream.next_in == NULL)
- return (ARCHIVE_FATAL);
- state->stream.avail_in = avail_in;
- state->stream.next_out = state->out_block;
- state->stream.avail_out = state->out_block_size;
-
- /* Initialize compression library. */
- ret = lzmadec_init(&(state->stream));
- __archive_read_filter_consume(self->upstream,
- avail_in - state->stream.avail_in);
- if (ret == LZMADEC_OK)
- return (ARCHIVE_OK);
-
- /* Library setup failed: Clean up. */
- archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
- "Internal error initializing lzma library");
-
- /* Override the error message if we know what really went wrong. */
- switch (ret) {
- case LZMADEC_HEADER_ERROR:
- archive_set_error(&self->archive->archive,
- ARCHIVE_ERRNO_MISC,
- "Internal error initializing compression library: "
- "invalid header");
- break;
- case LZMADEC_MEM_ERROR:
- archive_set_error(&self->archive->archive, ENOMEM,
- "Internal error initializing compression library: "
- "out of memory");
- break;
- }
-
- free(state->out_block);
- free(state);
- self->data = NULL;
- return (ARCHIVE_FATAL);
-}
-
-/*
- * Return the next block of decompressed data.
- */
-static ssize_t
-lzma_filter_read(struct archive_read_filter *self, const void **p)
-{
- struct private_data *state;
- size_t decompressed;
- ssize_t avail_in, ret;
-
- state = (struct private_data *)self->data;
-
- /* Empty our output buffer. */
- state->stream.next_out = state->out_block;
- state->stream.avail_out = state->out_block_size;
-
- /* Try to fill the output buffer. */
- while (state->stream.avail_out > 0 && !state->eof) {
- state->stream.next_in = (unsigned char *)(uintptr_t)
- __archive_read_filter_ahead(self->upstream, 1, &avail_in);
- if (state->stream.next_in == NULL && avail_in < 0) {
- archive_set_error(&self->archive->archive,
- ARCHIVE_ERRNO_MISC,
- "truncated lzma input");
- return (ARCHIVE_FATAL);
- }
- state->stream.avail_in = avail_in;
-
- /* Decompress as much as we can in one pass. */
- ret = lzmadec_decode(&(state->stream), avail_in == 0);
- switch (ret) {
- case LZMADEC_STREAM_END: /* Found end of stream. */
- state->eof = 1;
- /* FALL THROUGH */
- case LZMADEC_OK: /* Decompressor made some progress. */
- __archive_read_filter_consume(self->upstream,
- avail_in - state->stream.avail_in);
- break;
- case LZMADEC_BUF_ERROR: /* Insufficient input data? */
- archive_set_error(&self->archive->archive,
- ARCHIVE_ERRNO_MISC,
- "Insufficient compressed data");
- return (ARCHIVE_FATAL);
- default:
- /* Return an error. */
- archive_set_error(&self->archive->archive,
- ARCHIVE_ERRNO_MISC,
- "Lzma decompression failed");
- return (ARCHIVE_FATAL);
- }
- }
-
- decompressed = state->stream.next_out - state->out_block;
- state->total_out += decompressed;
- if (decompressed == 0)
- *p = NULL;
- else
- *p = state->out_block;
- return (decompressed);
-}
-
-/*
- * Clean up the decompressor.
- */
-static int
-lzma_filter_close(struct archive_read_filter *self)
-{
- struct private_data *state;
- int ret;
-
- state = (struct private_data *)self->data;
- ret = ARCHIVE_OK;
- switch (lzmadec_end(&(state->stream))) {
- case LZMADEC_OK:
- break;
- default:
- archive_set_error(&(self->archive->archive),
- ARCHIVE_ERRNO_MISC,
- "Failed to clean up %s compressor",
- self->archive->archive.compression_name);
- ret = ARCHIVE_FATAL;
- }
-
- free(state->out_block);
- free(state);
- return (ret);
-}
-
-#else
-
/*
*
* If we have no suitable library on this system, we can't actually do
@@ -953,9 +765,6 @@ lzma_bidder_init(struct archive_read_filter *self)
return (r);
}
-#endif /* HAVE_LZMADEC_H */
-
-
static int
xz_bidder_init(struct archive_read_filter *self)
{
@@ -984,5 +793,4 @@ lzip_bidder_init(struct archive_read_filter *self)
return (r);
}
-
#endif /* HAVE_LZMA_H */
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
index a33ea4f..96774f4 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
@@ -213,7 +213,7 @@ struct _7zip {
int header_is_encoded;
uint64_t header_bytes_remaining;
unsigned long header_crc32;
- /* Header offset to check that reading pointes of the file contens
+ /* Header offset to check that reading points of the file contents
* will not exceed the header. */
uint64_t header_offset;
/* Base offset of the archive file for a seek in case reading SFX. */
@@ -263,22 +263,22 @@ struct _7zip {
/*
* Decompressor controllers.
*/
- /* Decording LZMA1 and LZMA2 data. */
+ /* Decoding LZMA1 and LZMA2 data. */
#ifdef HAVE_LZMA_H
lzma_stream lzstream;
int lzstream_valid;
#endif
- /* Decording bzip2 data. */
+ /* Decoding bzip2 data. */
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
bz_stream bzstream;
int bzstream_valid;
#endif
- /* Decording deflate data. */
+ /* Decoding deflate data. */
#ifdef HAVE_ZLIB_H
z_stream stream;
int stream_valid;
#endif
- /* Decording PPMd data. */
+ /* Decoding PPMd data. */
int ppmd7_stat;
CPpmd7 ppmd7_context;
CPpmd7z_RangeDec range_dec;
@@ -552,7 +552,7 @@ skip_sfx(struct archive_read *a, ssize_t bytes_avail)
/*
* If bytes_avail > SFX_MIN_ADDR we do not have to call
* __archive_read_seek() at this time since we have
- * alredy had enough data.
+ * already had enough data.
*/
if (bytes_avail > SFX_MIN_ADDR)
__archive_read_consume(a, SFX_MIN_ADDR);
@@ -760,7 +760,7 @@ archive_read_format_7zip_read_header(struct archive_read *a,
symsize += size;
}
if (symsize == 0) {
- /* If there is no synname, handle it as a regular
+ /* If there is no symname, handle it as a regular
* file. */
zip_entry->mode &= ~AE_IFMT;
zip_entry->mode |= AE_IFREG;
@@ -1056,10 +1056,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
#endif
{
lzma_options_delta delta_opt;
- lzma_filter filters[LZMA_FILTERS_MAX];
-#if LZMA_VERSION < 50010000
- lzma_filter *ff;
-#endif
+ lzma_filter filters[LZMA_FILTERS_MAX], *ff;
int fi = 0;
if (zip->lzstream_valid) {
@@ -1144,9 +1141,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
else
filters[fi].id = LZMA_FILTER_LZMA1;
filters[fi].options = NULL;
-#if LZMA_VERSION < 50010000
ff = &filters[fi];
-#endif
r = lzma_properties_decode(&filters[fi], NULL,
coder1->properties, (size_t)coder1->propertiesSize);
if (r != LZMA_OK) {
@@ -1158,9 +1153,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
filters[fi].id = LZMA_VLI_UNKNOWN;
filters[fi].options = NULL;
r = lzma_raw_decoder(&(zip->lzstream), filters);
-#if LZMA_VERSION < 50010000
free(ff->options);
-#endif
if (r != LZMA_OK) {
set_error(a, r);
return (ARCHIVE_FAILED);
@@ -2431,6 +2424,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
switch (type) {
case kEmptyStream:
+ if (h->emptyStreamBools != NULL)
+ return (-1);
h->emptyStreamBools = calloc((size_t)zip->numFiles,
sizeof(*h->emptyStreamBools));
if (h->emptyStreamBools == NULL)
@@ -2451,6 +2446,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
return (-1);
break;
}
+ if (h->emptyFileBools != NULL)
+ return (-1);
h->emptyFileBools = calloc(empty_streams,
sizeof(*h->emptyFileBools));
if (h->emptyFileBools == NULL)
@@ -2465,6 +2462,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
return (-1);
break;
}
+ if (h->antiBools != NULL)
+ return (-1);
h->antiBools = calloc(empty_streams,
sizeof(*h->antiBools));
if (h->antiBools == NULL)
@@ -2491,6 +2490,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
if ((ll & 1) || ll < zip->numFiles * 4)
return (-1);
+ if (zip->entry_names != NULL)
+ return (-1);
zip->entry_names = malloc(ll);
if (zip->entry_names == NULL)
return (-1);
@@ -2543,6 +2544,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
if ((p = header_bytes(a, 2)) == NULL)
return (-1);
allAreDefined = *p;
+ if (h->attrBools != NULL)
+ return (-1);
h->attrBools = calloc((size_t)zip->numFiles,
sizeof(*h->attrBools));
if (h->attrBools == NULL)
@@ -3285,7 +3288,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size,
return (r);
/*
- * Skip the bytes we alrady has skipped in skip_stream().
+ * Skip the bytes we already has skipped in skip_stream().
*/
while (skip_bytes) {
ssize_t skipped;
@@ -3503,7 +3506,7 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
return (ARCHIVE_FATAL);
}
- /* Allocate memory for the decorded data of a sub
+ /* Allocate memory for the decoded data of a sub
* stream. */
b[i] = malloc((size_t)zip->folder_outbytes_remaining);
if (b[i] == NULL) {
@@ -3588,7 +3591,7 @@ skip_stream(struct archive_read *a, size_t skip_bytes)
if (zip->folder_index == 0) {
/*
* Optimization for a list mode.
- * Avoid unncecessary decoding operations.
+ * Avoid unnecessary decoding operations.
*/
zip->si.ci.folders[zip->entry->folderIndex].skipped_bytes
+= skip_bytes;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c
index 4b5b66b..b6b9fc3 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c
@@ -104,13 +104,12 @@ archive_read_support_format_ar(struct archive *_a)
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
ARCHIVE_STATE_NEW, "archive_read_support_format_ar");
- ar = (struct ar *)malloc(sizeof(*ar));
+ ar = (struct ar *)calloc(1, sizeof(*ar));
if (ar == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate ar data");
return (ARCHIVE_FATAL);
}
- memset(ar, 0, sizeof(*ar));
ar->strtab = NULL;
r = __archive_read_register_format(a,
@@ -260,7 +259,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
archive_entry_set_filetype(entry, AE_IFREG);
/* Get the size of the filename table. */
number = ar_atol10(h + AR_size_offset, AR_size_size);
- if (number > SIZE_MAX) {
+ if (number > SIZE_MAX || number > 1024 * 1024 * 1024) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Filename table too large");
return (ARCHIVE_FATAL);
@@ -316,7 +315,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
* If we can't look up the real name, warn and return
* the entry with the wrong name.
*/
- if (ar->strtab == NULL || number > ar->strtab_size) {
+ if (ar->strtab == NULL || number >= ar->strtab_size) {
archive_set_error(&a->archive, EINVAL,
"Can't find long filename for GNU/SVR4 archive entry");
archive_entry_copy_pathname(entry, filename);
@@ -342,16 +341,19 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
/* Parse the size of the name, adjust the file size. */
number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3);
- bsd_name_length = (size_t)number;
- /* Guard against the filename + trailing NUL
- * overflowing a size_t and against the filename size
- * being larger than the entire entry. */
- if (number > (uint64_t)(bsd_name_length + 1)
- || (int64_t)bsd_name_length > ar->entry_bytes_remaining) {
+ /* Sanity check the filename length:
+ * = Must be <= SIZE_MAX - 1
+ * = Must be <= 1MB
+ * = Cannot be bigger than the entire entry
+ */
+ if (number > SIZE_MAX - 1
+ || number > 1024 * 1024
+ || (int64_t)number > ar->entry_bytes_remaining) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Bad input file size");
return (ARCHIVE_FATAL);
}
+ bsd_name_length = (size_t)number;
ar->entry_bytes_remaining -= bsd_name_length;
/* Adjust file size reported to client. */
archive_entry_set_size(entry, ar->entry_bytes_remaining);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c
index 6356963..20eb157 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c
@@ -67,7 +67,7 @@ struct lzx_dec {
/* The length how many bytes we can copy decoded code from
* the window. */
int copy_len;
- /* Translation reversal for x86 proccessor CALL byte sequence(E8).
+ /* Translation reversal for x86 processor CALL byte sequence(E8).
* This is used for LZX only. */
uint32_t translation_size;
char translation;
@@ -645,12 +645,13 @@ cab_read_header(struct archive_read *a)
cab = (struct cab *)(a->format->data);
if (cab->found_header == 0 &&
p[0] == 'M' && p[1] == 'Z') {
- /* This is an executable? Must be self-extracting... */
+ /* This is an executable? Must be self-extracting... */
err = cab_skip_sfx(a);
if (err < ARCHIVE_WARN)
return (err);
- if ((p = __archive_read_ahead(a, sizeof(*p), NULL)) == NULL)
+ /* Re-read header after processing the SFX. */
+ if ((p = __archive_read_ahead(a, 42, NULL)) == NULL)
return (truncated_error(a));
}
@@ -1494,6 +1495,8 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
/* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */
if (mszip > 0) {
+ if (bytes_avail <= 0)
+ goto nomszip;
if (bytes_avail <= mszip) {
if (mszip == 2) {
if (cab->stream.next_in[0] != 0x43)
@@ -1554,7 +1557,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
/*
* Note: I suspect there is a bug in makecab.exe because, in rare
* case, compressed bytes are still remaining regardless we have
- * gotten all uncompressed bytes, which size is recoded in CFDATA,
+ * gotten all uncompressed bytes, which size is recorded in CFDATA,
* as much as we need, and we have to use the garbage so as to
* correctly compute the sum of CFDATA accordingly.
*/
@@ -1741,7 +1744,7 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail)
}
/*
- * Translation reversal of x86 proccessor CALL byte sequence(E8).
+ * Translation reversal of x86 processor CALL byte sequence(E8).
*/
lzx_translation(&cab->xstrm, cab->uncompressed_buffer,
cfdata->uncompressed_size,
@@ -2270,7 +2273,7 @@ static int
lzx_br_fillup(struct lzx_stream *strm, struct lzx_br *br)
{
/*
- * x86 proccessor family can read misaligned data without an access error.
+ * x86 processor family can read misaligned data without an access error.
*/
int n = CACHE_BITS - br->cache_avail;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c
index b09db0e..ffd4a85 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c
@@ -326,7 +326,7 @@ archive_read_format_cpio_options(struct archive_read *a,
cpio = (struct cpio *)(a->format->data);
if (strcmp(key, "compat-2x") == 0) {
- /* Handle filnames as libarchive 2.x */
+ /* Handle filenames as libarchive 2.x */
cpio->init_default_conversion = (val != NULL)?1:0;
return (ARCHIVE_OK);
} else if (strcmp(key, "hdrcharset") == 0) {
@@ -356,7 +356,7 @@ archive_read_format_cpio_read_header(struct archive_read *a,
struct archive_entry *entry)
{
struct cpio *cpio;
- const void *h;
+ const void *h, *hl;
struct archive_string_conv *sconv;
size_t namelength;
size_t name_pad;
@@ -406,11 +406,11 @@ archive_read_format_cpio_read_header(struct archive_read *a,
"Rejecting malformed cpio archive: symlink contents exceed 1 megabyte");
return (ARCHIVE_FATAL);
}
- h = __archive_read_ahead(a,
+ hl = __archive_read_ahead(a,
(size_t)cpio->entry_bytes_remaining, NULL);
- if (h == NULL)
+ if (hl == NULL)
return (ARCHIVE_FATAL);
- if (archive_entry_copy_symlink_l(entry, (const char *)h,
+ if (archive_entry_copy_symlink_l(entry, (const char *)hl,
(size_t)cpio->entry_bytes_remaining, sconv) != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
@@ -434,7 +434,8 @@ archive_read_format_cpio_read_header(struct archive_read *a,
* header. XXX */
/* Compare name to "TRAILER!!!" to test for end-of-archive. */
- if (namelength == 11 && strcmp((const char *)h, "TRAILER!!!") == 0) {
+ if (namelength == 11 && strncmp((const char *)h, "TRAILER!!!",
+ 11) == 0) {
/* TODO: Store file location of start of block. */
archive_clear_error(&a->archive);
return (ARCHIVE_EOF);
@@ -814,8 +815,8 @@ header_odc(struct archive_read *a, struct cpio *cpio,
* NOTE: if a filename suffix is ".z", it is the file gziped by afio.
* it would be nice that we can show uncompressed file size and we can
* uncompressed file contents automatically, unfortunately we have nothing
- * to get a uncompressed file size while reading each header. it means
- * we also cannot uncompressed file contens under the our framework.
+ * to get a uncompressed file size while reading each header. It means
+ * we also cannot uncompress file contents under our framework.
*/
static int
header_afiol(struct archive_read *a, struct cpio *cpio,
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
index c19614a..3541330 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
@@ -322,7 +322,7 @@ struct iso9660 {
struct archive_string pathname;
char seenRockridge; /* Set true if RR extensions are used. */
- char seenSUSP; /* Set true if SUSP is beging used. */
+ char seenSUSP; /* Set true if SUSP is being used. */
char seenJoliet;
unsigned char suspOffset;
@@ -374,7 +374,7 @@ struct iso9660 {
size_t utf16be_path_len;
unsigned char *utf16be_previous_path;
size_t utf16be_previous_path_len;
- /* Null buufer used in bidder to improve its performance. */
+ /* Null buffer used in bidder to improve its performance. */
unsigned char null[2048];
};
@@ -1199,7 +1199,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
archive_string_conversion_from_charset(
&(a->archive), "UTF-16BE", 1);
if (iso9660->sconv_utf16be == NULL)
- /* Coundn't allocate memory */
+ /* Couldn't allocate memory */
return (ARCHIVE_FATAL);
}
if (iso9660->utf16be_path == NULL) {
@@ -1864,7 +1864,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
if ((file->utf16be_name = malloc(name_len)) == NULL) {
archive_set_error(&a->archive, ENOMEM,
"No memory for file name");
- return (NULL);
+ goto fail;
}
memcpy(file->utf16be_name, p, name_len);
file->utf16be_bytes = name_len;
@@ -1943,10 +1943,8 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
file->symlink_continues = 0;
rr_start += iso9660->suspOffset;
r = parse_rockridge(a, file, rr_start, rr_end);
- if (r != ARCHIVE_OK) {
- free(file);
- return (NULL);
- }
+ if (r != ARCHIVE_OK)
+ goto fail;
/*
* A file size of symbolic link files in ISO images
* made by makefs is not zero and its location is
@@ -1990,7 +1988,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Invalid Rockridge RE");
- return (NULL);
+ goto fail;
}
/*
* Sanity check: file does not have "CL" extension.
@@ -1999,7 +1997,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Invalid Rockridge RE and CL");
- return (NULL);
+ goto fail;
}
/*
* Sanity check: The file type must be a directory.
@@ -2008,7 +2006,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Invalid Rockridge RE");
- return (NULL);
+ goto fail;
}
} else if (parent != NULL && parent->rr_moved)
file->rr_moved_has_re_only = 0;
@@ -2022,7 +2020,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Invalid Rockridge CL");
- return (NULL);
+ goto fail;
}
/*
* Sanity check: The file type must be a regular file.
@@ -2031,7 +2029,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Invalid Rockridge CL");
- return (NULL);
+ goto fail;
}
parent->subdirs++;
/* Overwrite an offset and a number of this "CL" entry
@@ -2049,7 +2047,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Invalid Rockridge CL");
- return (NULL);
+ goto fail;
}
}
if (file->cl_offset == file->offset ||
@@ -2057,7 +2055,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Invalid Rockridge CL");
- return (NULL);
+ goto fail;
}
}
}
@@ -2088,6 +2086,10 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
#endif
register_file(iso9660, file);
return (file);
+fail:
+ archive_string_free(&file->name);
+ free(file);
+ return (NULL);
}
static int
@@ -2407,7 +2409,7 @@ read_CE(struct archive_read *a, struct iso9660 *iso9660)
return (ARCHIVE_FATAL);
} while (heap->cnt &&
heap->reqs[0].offset == iso9660->current_position);
- /* NOTE: Do not move this consume's code to fron of
+ /* NOTE: Do not move this consume's code to front of
* do-while loop. Registration of nested CE extension
* might cause error because of current position. */
__archive_read_consume(a, step);
@@ -2729,7 +2731,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
if (file == NULL) {
/*
* If directory entries all which are descendant of
- * rr_moved are stil remaning, expose their.
+ * rr_moved are still remaining, expose their.
*/
if (iso9660->re_files.first != NULL &&
iso9660->rr_moved != NULL &&
@@ -2852,7 +2854,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
empty_files.last = &empty_files.first;
/* Collect files which has the same file serial number.
* Peek pending_files so that file which number is different
- * is not put bak. */
+ * is not put back. */
while (iso9660->pending_files.used > 0 &&
(iso9660->pending_files.files[0]->number == -1 ||
iso9660->pending_files.files[0]->number == number)) {
@@ -2860,7 +2862,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
/* This file has the same offset
* but it's wrong offset which empty files
* and symlink files have.
- * NOTE: This wrong offse was recorded by
+ * NOTE: This wrong offset was recorded by
* old mkisofs utility. If ISO images is
* created by latest mkisofs, this does not
* happen.
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c
index eff02d8..ebd7f2c 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c
@@ -924,6 +924,9 @@ lha_read_file_header_1(struct archive_read *a, struct lha *lha)
/* Get a real compressed file size. */
lha->compsize -= extdsize - 2;
+ if (lha->compsize < 0)
+ goto invalid; /* Invalid compressed file size */
+
if (sum_calculated != headersum) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"LHa header sum error");
@@ -1711,14 +1714,18 @@ lha_crc16(uint16_t crc, const void *pp, size_t len)
*/
for (;len >= 8; len -= 8) {
/* This if statement expects compiler optimization will
- * remove the stament which will not be executed. */
+ * remove the statement which will not be executed. */
+#undef bswap16
#ifndef __has_builtin
# define __has_builtin(x) 0
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1400 /* Visual Studio */
# define bswap16(x) _byteswap_ushort(x)
-#elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8) \
- || (defined(__clang__) && __has_builtin(__builtin_bswap16))
+#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4)
+/* GCC 4.8 and later has __builtin_bswap16() */
+# define bswap16(x) __builtin_bswap16(x)
+#elif defined(__clang__) && __has_builtin(__builtin_bswap16)
+/* All clang versions have __builtin_bswap16() */
# define bswap16(x) __builtin_bswap16(x)
#else
# define bswap16(x) ((((x) >> 8) & 0xff) | ((x) << 8))
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c
index 8c3be9a..4231ff5 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c
@@ -75,6 +75,8 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
#define MTREE_HAS_OPTIONAL 0x0800
#define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */
+#define MTREE_HASHTABLE_SIZE 1024
+
struct mtree_option {
struct mtree_option *next;
char *value;
@@ -86,6 +88,8 @@ struct mtree_entry {
char *name;
char full;
char used;
+ unsigned int name_hash;
+ struct mtree_entry *hashtable_next;
};
struct mtree {
@@ -98,6 +102,7 @@ struct mtree {
const char *archive_format_name;
struct mtree_entry *entries;
struct mtree_entry *this_entry;
+ struct mtree_entry *entry_hashtable[MTREE_HASHTABLE_SIZE];
struct archive_string current_dir;
struct archive_string contents_name;
@@ -110,6 +115,7 @@ struct mtree {
static int bid_keycmp(const char *, const char *, ssize_t);
static int cleanup(struct archive_read *);
static int detect_form(struct archive_read *, int *);
+static unsigned int hash(const char *);
static int mtree_bid(struct archive_read *, int);
static int parse_file(struct archive_read *, struct archive_entry *,
struct mtree *, struct mtree_entry *, int *);
@@ -223,13 +229,12 @@ archive_read_support_format_mtree(struct archive *_a)
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
ARCHIVE_STATE_NEW, "archive_read_support_format_mtree");
- mtree = (struct mtree *)malloc(sizeof(*mtree));
+ mtree = (struct mtree *)calloc(1, sizeof(*mtree));
if (mtree == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate mtree data");
return (ARCHIVE_FATAL);
}
- memset(mtree, 0, sizeof(*mtree));
mtree->fd = -1;
r = __archive_read_register_format(a, mtree, "mtree",
@@ -301,6 +306,15 @@ get_line_size(const char *b, ssize_t avail, ssize_t *nlsize)
return (avail);
}
+/*
+ * <---------------- ravail --------------------->
+ * <-- diff ------> <--- avail ----------------->
+ * <---- len ----------->
+ * | Previous lines | line being parsed nl extra |
+ * ^
+ * b
+ *
+ */
static ssize_t
next_line(struct archive_read *a,
const char **b, ssize_t *avail, ssize_t *ravail, ssize_t *nl)
@@ -339,7 +353,7 @@ next_line(struct archive_read *a,
*b += diff;
*avail -= diff;
tested = len;/* Skip some bytes we already determinated. */
- len = get_line_size(*b, *avail, nl);
+ len = get_line_size(*b + len, *avail - len, nl);
if (len >= 0)
len += tested;
}
@@ -701,13 +715,13 @@ detect_form(struct archive_read *a, int *is_form_d)
}
} else
break;
- } else if (strncmp(p, "/set", 4) == 0) {
+ } else if (len > 4 && strncmp(p, "/set", 4) == 0) {
if (bid_keyword_list(p+4, len-4, 0, 0) <= 0)
break;
/* This line continues. */
if (p[len-nl-1] == '\\')
multiline = 2;
- } else if (strncmp(p, "/unset", 6) == 0) {
+ } else if (len > 6 && strncmp(p, "/unset", 6) == 0) {
if (bid_keyword_list(p+6, len-6, 1, 0) <= 0)
break;
/* This line continues. */
@@ -853,11 +867,12 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
struct mtree_option **global, const char *line, ssize_t line_len,
struct mtree_entry **last_entry, int is_form_d)
{
- struct mtree_entry *entry;
+ struct mtree_entry *entry, *ht_iter;
struct mtree_option *iter;
const char *next, *eq, *name, *end;
size_t name_len, len;
int r, i;
+ unsigned int ht_idx;
if ((entry = malloc(sizeof(*entry))) == NULL) {
archive_set_error(&a->archive, errno, "Can't allocate memory");
@@ -868,6 +883,8 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
entry->name = NULL;
entry->used = 0;
entry->full = 0;
+ entry->name_hash = 0;
+ entry->hashtable_next = NULL;
/* Add this entry to list. */
if (*last_entry == NULL)
@@ -920,6 +937,16 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
memcpy(entry->name, name, name_len);
entry->name[name_len] = '\0';
parse_escapes(entry->name, entry);
+ entry->name_hash = hash(entry->name);
+
+ ht_idx = entry->name_hash % MTREE_HASHTABLE_SIZE;
+ if ((ht_iter = mtree->entry_hashtable[ht_idx]) != NULL) {
+ while (ht_iter->hashtable_next)
+ ht_iter = ht_iter->hashtable_next;
+ ht_iter->hashtable_next = entry;
+ } else {
+ mtree->entry_hashtable[ht_idx] = entry;
+ }
for (iter = *global; iter != NULL; iter = iter->next) {
r = add_option(a, &entry->options, iter->value,
@@ -992,11 +1019,11 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
if (*p != '/') {
r = process_add_entry(a, mtree, &global, p, len,
&last_entry, is_form_d);
- } else if (strncmp(p, "/set", 4) == 0) {
+ } else if (len > 4 && strncmp(p, "/set", 4) == 0) {
if (p[4] != ' ' && p[4] != '\t')
break;
r = process_global_set(a, &global, p);
- } else if (strncmp(p, "/unset", 6) == 0) {
+ } else if (len > 6 && strncmp(p, "/unset", 6) == 0) {
if (p[6] != ' ' && p[6] != '\t')
break;
r = process_global_unset(a, &global, p);
@@ -1113,9 +1140,10 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
* with pathname canonicalization, which is a very
* tricky subject.)
*/
- for (mp = mentry->next; mp != NULL; mp = mp->next) {
+ for (mp = mentry->hashtable_next; mp != NULL; mp = mp->hashtable_next) {
if (mp->full && !mp->used
- && strcmp(mentry->name, mp->name) == 0) {
+ && mentry->name_hash == mp->name_hash
+ && strcmp(mentry->name, mp->name) == 0) {
/* Later lines override earlier ones. */
mp->used = 1;
r1 = parse_line(a, entry, mtree, mp,
@@ -1580,8 +1608,11 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
if (*val == '.') {
++val;
ns = (long)mtree_atol10(&val);
- } else
- ns = 0;
+ if (ns < 0)
+ ns = 0;
+ else if (ns > 999999999)
+ ns = 999999999;
+ }
if (m > my_time_t_max)
m = my_time_t_max;
else if (m < my_time_t_min)
@@ -1991,3 +2022,19 @@ readline(struct archive_read *a, struct mtree *mtree, char **start,
find_off = u - mtree->line.s;
}
}
+
+static unsigned int
+hash(const char *p)
+{
+ /* A 32-bit version of Peter Weinberger's (PJW) hash algorithm,
+ as used by ELF for hashing function names. */
+ unsigned g, h = 0;
+ while (*p != '\0') {
+ h = (h << 4) + *p++;
+ if ((g = h & 0xF0000000) != 0) {
+ h ^= g >> 24;
+ h &= 0x0FFFFFFF;
+ }
+ }
+ return h;
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
index fc8153f..658d49d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
@@ -647,13 +647,12 @@ archive_read_support_format_rar(struct archive *_a)
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
"archive_read_support_format_rar");
- rar = (struct rar *)malloc(sizeof(*rar));
+ rar = (struct rar *)calloc(sizeof(*rar), 1);
if (rar == NULL)
{
archive_set_error(&a->archive, ENOMEM, "Can't allocate rar data");
return (ARCHIVE_FATAL);
}
- memset(rar, 0, sizeof(*rar));
/*
* Until enough data has been read, we cannot tell about
@@ -907,7 +906,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
sizeof(rar->reserved2));
}
- /* Main header is password encrytped, so we cannot read any
+ /* Main header is password encrypted, so we cannot read any
file names or any other info about files from the header. */
if (rar->main_flags & MHD_PASSWORD)
{
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
index b0521a6..bd7f13d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
@@ -1,6 +1,7 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2011-2012 Michihiro NAKAJIMA
+ * Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -136,6 +137,7 @@ struct tar {
int64_t entry_padding;
int64_t entry_bytes_unconsumed;
int64_t realsize;
+ int sparse_allowed;
struct sparse_block *sparse_list;
struct sparse_block *sparse_last;
int64_t sparse_offset;
@@ -202,9 +204,14 @@ static int archive_read_format_tar_read_header(struct archive_read *,
struct archive_entry *);
static int checksum(struct archive_read *, const void *);
static int pax_attribute(struct archive_read *, struct tar *,
- struct archive_entry *, const char *key, const char *value);
+ struct archive_entry *, const char *key, const char *value,
+ size_t value_length);
+static int pax_attribute_acl(struct archive_read *, struct tar *,
+ struct archive_entry *, const char *, int);
+static int pax_attribute_xattr(struct archive_entry *, const char *,
+ const char *);
static int pax_header(struct archive_read *, struct tar *,
- struct archive_entry *, char *attr);
+ struct archive_entry *, struct archive_string *);
static void pax_time(const char *, int64_t *sec, long *nanos);
static ssize_t readline(struct archive_read *, struct tar *, const char **,
ssize_t limit, size_t *);
@@ -293,6 +300,57 @@ archive_read_format_tar_cleanup(struct archive_read *a)
return (ARCHIVE_OK);
}
+/*
+ * Validate number field
+ *
+ * This has to be pretty lenient in order to accommodate the enormous
+ * variety of tar writers in the world:
+ * = POSIX (IEEE Std 1003.1-1988) ustar requires octal values with leading
+ * zeros and allows fields to be terminated with space or null characters
+ * = Many writers use different termination (in particular, libarchive
+ * omits terminator bytes to squeeze one or two more digits)
+ * = Many writers pad with space and omit leading zeros
+ * = GNU tar and star write base-256 values if numbers are too
+ * big to be represented in octal
+ *
+ * Examples of specific tar headers that we should support:
+ * = Perl Archive::Tar terminates uid, gid, devminor and devmajor with two
+ * null bytes, pads size with spaces and other numeric fields with zeroes
+ * = plexus-archiver prior to 2.6.3 (before switching to commons-compress)
+ * may have uid and gid fields filled with spaces without any octal digits
+ * at all and pads all numeric fields with spaces
+ *
+ * This should tolerate all variants in use. It will reject a field
+ * where the writer just left garbage after a trailing NUL.
+ */
+static int
+validate_number_field(const char* p_field, size_t i_size)
+{
+ unsigned char marker = (unsigned char)p_field[0];
+ if (marker == 128 || marker == 255 || marker == 0) {
+ /* Base-256 marker, there's nothing we can check. */
+ return 1;
+ } else {
+ /* Must be octal */
+ size_t i = 0;
+ /* Skip any leading spaces */
+ while (i < i_size && p_field[i] == ' ') {
+ ++i;
+ }
+ /* Skip octal digits. */
+ while (i < i_size && p_field[i] >= '0' && p_field[i] <= '7') {
+ ++i;
+ }
+ /* Any remaining characters must be space or NUL padding. */
+ while (i < i_size) {
+ if (p_field[i] != ' ' && p_field[i] != 0) {
+ return 0;
+ }
+ ++i;
+ }
+ return 1;
+ }
+}
static int
archive_read_format_tar_bid(struct archive_read *a, int best_bid)
@@ -345,23 +403,19 @@ archive_read_format_tar_bid(struct archive_read *a, int best_bid)
return (0);
bid += 2; /* 6 bits of variation in an 8-bit field leaves 2 bits. */
- /* Sanity check: Look at first byte of mode field. */
- switch (255 & (unsigned)header->mode[0]) {
- case 0: case 255:
- /* Base-256 value: No further verification possible! */
- break;
- case ' ': /* Not recommended, but not illegal, either. */
- break;
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- /* Octal Value. */
- /* TODO: Check format of remainder of this field. */
- break;
- default:
- /* Not a valid mode; bail out here. */
- return (0);
+ /*
+ * Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields.
+ */
+ if (bid > 0 && (
+ validate_number_field(header->mode, sizeof(header->mode)) == 0
+ || validate_number_field(header->uid, sizeof(header->uid)) == 0
+ || validate_number_field(header->gid, sizeof(header->gid)) == 0
+ || validate_number_field(header->mtime, sizeof(header->mtime)) == 0
+ || validate_number_field(header->size, sizeof(header->size)) == 0
+ || validate_number_field(header->rdevmajor, sizeof(header->rdevmajor)) == 0
+ || validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0)) {
+ bid = 0;
}
- /* TODO: Sanity test uid/gid/size/mtime/rdevmajor/rdevminor fields. */
return (bid);
}
@@ -375,7 +429,7 @@ archive_read_format_tar_options(struct archive_read *a,
tar = (struct tar *)(a->format->data);
if (strcmp(key, "compat-2x") == 0) {
- /* Handle UTF-8 filnames as libarchive 2.x */
+ /* Handle UTF-8 filenames as libarchive 2.x */
tar->compat_2x = (val != NULL && val[0] != 0);
tar->init_default_conversion = tar->compat_2x;
return (ARCHIVE_OK);
@@ -793,9 +847,9 @@ tar_read_header(struct archive_read *a, struct tar *tar,
tar->sparse_gnu_pending = 0;
/* Read initial sparse map. */
bytes_read = gnu_sparse_10_read(a, tar, unconsumed);
- tar->entry_bytes_remaining -= bytes_read;
if (bytes_read < 0)
return ((int)bytes_read);
+ tar->entry_bytes_remaining -= bytes_read;
} else {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
@@ -890,7 +944,7 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
{
const struct archive_entry_header_ustar *header;
size_t size;
- int err;
+ int err, acl_type;
int64_t type;
char *acl, *p;
@@ -935,11 +989,12 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
switch ((int)type & ~0777777) {
case 01000000:
/* POSIX.1e ACL */
+ acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
break;
case 03000000:
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Solaris NFSv4 ACLs not supported");
- return (ARCHIVE_WARN);
+ /* NFSv4 ACL */
+ acl_type = ARCHIVE_ENTRY_ACL_TYPE_NFS4;
+ break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Malformed Solaris ACL attribute (unsupported type %o)",
@@ -968,8 +1023,8 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
return (ARCHIVE_FATAL);
}
archive_strncpy(&(tar->localname), acl, p - acl);
- err = archive_acl_parse_l(archive_entry_acl(entry),
- tar->localname.s, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, tar->sconv_acl);
+ err = archive_acl_from_text_l(archive_entry_acl(entry),
+ tar->localname.s, acl_type, tar->sconv_acl);
if (err != ARCHIVE_OK) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
@@ -1128,8 +1183,15 @@ header_common(struct archive_read *a, struct tar *tar,
if (tar->entry_bytes_remaining < 0) {
tar->entry_bytes_remaining = 0;
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Tar entry has negative size?");
- err = ARCHIVE_WARN;
+ "Tar entry has negative size");
+ return (ARCHIVE_FATAL);
+ }
+ if (tar->entry_bytes_remaining == INT64_MAX) {
+ /* Note: tar_atol returns INT64_MAX on overflow */
+ tar->entry_bytes_remaining = 0;
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Tar entry size overflow");
+ return (ARCHIVE_FATAL);
}
tar->realsize = tar->entry_bytes_remaining;
archive_entry_set_size(entry, tar->entry_bytes_remaining);
@@ -1264,6 +1326,14 @@ header_common(struct archive_read *a, struct tar *tar,
* sparse information in the extended area.
*/
/* FALLTHROUGH */
+ case '0':
+ /*
+ * Enable sparse file "read" support only for regular
+ * files and explicit GNU sparse files. However, we
+ * don't allow non-standard file types to be sparse.
+ */
+ tar->sparse_allowed = 1;
+ /* FALLTHROUGH */
default: /* Regular file and non-standard types */
/*
* Per POSIX: non-recognized types should always be
@@ -1415,7 +1485,7 @@ header_pax_extensions(struct archive_read *a, struct tar *tar,
* and then skip any fields in the standard header that were
* defined in the pax header.
*/
- err2 = pax_header(a, tar, entry, tar->pax_header.s);
+ err2 = pax_header(a, tar, entry, &tar->pax_header);
err = err_combine(err, err2);
tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining);
return (err);
@@ -1496,16 +1566,17 @@ header_ustar(struct archive_read *a, struct tar *tar,
*/
static int
pax_header(struct archive_read *a, struct tar *tar,
- struct archive_entry *entry, char *attr)
+ struct archive_entry *entry, struct archive_string *in_as)
{
- size_t attr_length, l, line_length;
+ size_t attr_length, l, line_length, value_length;
char *p;
char *key, *value;
struct archive_string *as;
struct archive_string_conv *sconv;
int err, err2;
+ char *attr = in_as->s;
- attr_length = strlen(attr);
+ attr_length = in_as->length;
tar->pax_hdrcharset_binary = 0;
archive_string_empty(&(tar->entry_gname));
archive_string_empty(&(tar->entry_linkpath));
@@ -1570,11 +1641,13 @@ pax_header(struct archive_read *a, struct tar *tar,
}
*p = '\0';
- /* Identify null-terminated 'value' portion. */
value = p + 1;
+ /* Some values may be binary data */
+ value_length = attr + line_length - 1 - value;
+
/* Identify this attribute and set it in the entry. */
- err2 = pax_attribute(a, tar, entry, key, value);
+ err2 = pax_attribute(a, tar, entry, key, value, value_length);
if (err2 == ARCHIVE_FATAL)
return (err2);
err = err_combine(err, err2);
@@ -1695,6 +1768,66 @@ pax_attribute_xattr(struct archive_entry *entry,
return 0;
}
+static int
+pax_attribute_schily_xattr(struct archive_entry *entry,
+ const char *name, const char *value, size_t value_length)
+{
+ if (strlen(name) < 14 || (memcmp(name, "SCHILY.xattr.", 13)) != 0)
+ return 1;
+
+ name += 13;
+
+ archive_entry_xattr_add_entry(entry, name, value, value_length);
+
+ return 0;
+}
+
+static int
+pax_attribute_acl(struct archive_read *a, struct tar *tar,
+ struct archive_entry *entry, const char *value, int type)
+{
+ int r;
+ const char* errstr;
+
+ switch (type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+ errstr = "SCHILY.acl.access";
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+ errstr = "SCHILY.acl.default";
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
+ errstr = "SCHILY.acl.ace";
+ break;
+ default:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Unknown ACL type: %d", type);
+ return(ARCHIVE_FATAL);
+ }
+
+ if (tar->sconv_acl == NULL) {
+ tar->sconv_acl =
+ archive_string_conversion_from_charset(
+ &(a->archive), "UTF-8", 1);
+ if (tar->sconv_acl == NULL)
+ return (ARCHIVE_FATAL);
+ }
+
+ r = archive_acl_from_text_l(archive_entry_acl(entry), value, type,
+ tar->sconv_acl);
+ if (r != ARCHIVE_OK) {
+ if (r == ARCHIVE_FATAL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "%s %s", "Can't allocate memory for ",
+ errstr);
+ return (r);
+ }
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC, "%s %s", "Parse error: ", errstr);
+ }
+ return (r);
+}
+
/*
* Parse a single key=value attribute. key/value pointers are
* assumed to point into reasonably long-lived storage.
@@ -1710,7 +1843,7 @@ pax_attribute_xattr(struct archive_entry *entry,
*/
static int
pax_attribute(struct archive_read *a, struct tar *tar,
- struct archive_entry *entry, const char *key, const char *value)
+ struct archive_entry *entry, const char *key, const char *value, size_t value_length)
{
int64_t s;
long n;
@@ -1721,6 +1854,14 @@ pax_attribute(struct archive_read *a, struct tar *tar,
* NULL pointer to strlen(). */
switch (key[0]) {
case 'G':
+ /* Reject GNU.sparse.* headers on non-regular files. */
+ if (strncmp(key, "GNU.sparse", 10) == 0 &&
+ !tar->sparse_allowed) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Non-regular file cannot be sparse");
+ return (ARCHIVE_FATAL);
+ }
+
/* GNU "0.0" sparse pax format. */
if (strcmp(key, "GNU.sparse.numblocks") == 0) {
tar->sparse_offset = -1;
@@ -1803,53 +1944,20 @@ pax_attribute(struct archive_read *a, struct tar *tar,
case 'S':
/* We support some keys used by the "star" archiver */
if (strcmp(key, "SCHILY.acl.access") == 0) {
- if (tar->sconv_acl == NULL) {
- tar->sconv_acl =
- archive_string_conversion_from_charset(
- &(a->archive), "UTF-8", 1);
- if (tar->sconv_acl == NULL)
- return (ARCHIVE_FATAL);
- }
-
- r = archive_acl_parse_l(archive_entry_acl(entry),
- value, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
- tar->sconv_acl);
- if (r != ARCHIVE_OK) {
- err = r;
- if (err == ARCHIVE_FATAL) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate memory for "
- "SCHILY.acl.access");
- return (err);
- }
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_MISC,
- "Parse error: SCHILY.acl.access");
- }
+ r = pax_attribute_acl(a, tar, entry, value,
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
+ if (r == ARCHIVE_FATAL)
+ return (r);
} else if (strcmp(key, "SCHILY.acl.default") == 0) {
- if (tar->sconv_acl == NULL) {
- tar->sconv_acl =
- archive_string_conversion_from_charset(
- &(a->archive), "UTF-8", 1);
- if (tar->sconv_acl == NULL)
- return (ARCHIVE_FATAL);
- }
-
- r = archive_acl_parse_l(archive_entry_acl(entry),
- value, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
- tar->sconv_acl);
- if (r != ARCHIVE_OK) {
- err = r;
- if (err == ARCHIVE_FATAL) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate memory for "
- "SCHILY.acl.default");
- return (err);
- }
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_MISC,
- "Parse error: SCHILY.acl.default");
- }
+ r = pax_attribute_acl(a, tar, entry, value,
+ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
+ if (r == ARCHIVE_FATAL)
+ return (r);
+ } else if (strcmp(key, "SCHILY.acl.ace") == 0) {
+ r = pax_attribute_acl(a, tar, entry, value,
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4);
+ if (r == ARCHIVE_FATAL)
+ return (r);
} else if (strcmp(key, "SCHILY.devmajor") == 0) {
archive_entry_set_rdevmajor(entry,
(dev_t)tar_atol10(value, strlen(value)));
@@ -1870,6 +1978,9 @@ pax_attribute(struct archive_read *a, struct tar *tar,
} else if (strcmp(key, "SCHILY.realsize") == 0) {
tar->realsize = tar_atol10(value, strlen(value));
archive_entry_set_size(entry, tar->realsize);
+ } else if (strncmp(key, "SCHILY.xattr.", 13) == 0) {
+ pax_attribute_schily_xattr(entry, key, value,
+ value_length);
} else if (strcmp(key, "SUN.holesdata") == 0) {
/* A Solaris extension for sparse. */
r = solaris_sparse_parse(a, tar, entry, value);
@@ -2116,12 +2227,11 @@ gnu_add_sparse_entry(struct archive_read *a, struct tar *tar,
{
struct sparse_block *p;
- p = (struct sparse_block *)malloc(sizeof(*p));
+ p = (struct sparse_block *)calloc(1, sizeof(*p));
if (p == NULL) {
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
- memset(p, 0, sizeof(*p));
if (tar->sparse_last != NULL)
tar->sparse_last->next = p;
else
@@ -2377,6 +2487,9 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
tar_flush_unconsumed(a, unconsumed);
bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining);
to_skip = 0x1ff & -bytes_read;
+ /* Fail if tar->entry_bytes_remaing would get negative */
+ if (to_skip > remaining)
+ return (ARCHIVE_FATAL);
if (to_skip != __archive_read_consume(a, to_skip))
return (ARCHIVE_FATAL);
return ((ssize_t)(bytes_read + to_skip));
@@ -2472,7 +2585,7 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base)
last_digit_limit = INT64_MAX % base;
/* the pointer will not be dereferenced if char_cnt is zero
- * due to the way the && operator is evaulated.
+ * due to the way the && operator is evaluated.
*/
while (char_cnt != 0 && (*p == ' ' || *p == '\t')) {
p++;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c
index 46a59ea..b162465 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c
@@ -88,7 +88,7 @@ typedef enum {
WT_RVIS,
/* conversion, unsupported */
WT_CONV,
- /* continutation, unsupported at the moment */
+ /* continuation, unsupported at the moment */
WT_CONT,
/* invalid type */
LAST_WT
@@ -134,8 +134,8 @@ static ssize_t _warc_rdlen(const char *buf, size_t bsz);
static time_t _warc_rdrtm(const char *buf, size_t bsz);
static time_t _warc_rdmtm(const char *buf, size_t bsz);
static const char *_warc_find_eoh(const char *buf, size_t bsz);
+static const char *_warc_find_eol(const char *buf, size_t bsz);
-
int
archive_read_support_format_warc(struct archive *_a)
{
@@ -146,12 +146,11 @@ archive_read_support_format_warc(struct archive *_a)
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
ARCHIVE_STATE_NEW, "archive_read_support_format_warc");
- if ((w = malloc(sizeof(*w))) == NULL) {
+ if ((w = calloc(1, sizeof(*w))) == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate warc data");
return (ARCHIVE_FATAL);
}
- memset(w, 0, sizeof(*w));
r = __archive_read_register_format(
a, w, "warc",
@@ -199,8 +198,8 @@ _warc_bid(struct archive_read *a, int best_bid)
/* otherwise snarf the record's version number */
ver = _warc_rdver(hdr, nrd);
- if (ver == 0U || ver > 10000U) {
- /* oh oh oh, best not to wager ... */
+ if (ver < 1200U || ver > 10000U) {
+ /* we only support WARC 0.12 to 1.0 */
return -1;
}
@@ -255,23 +254,32 @@ start_over:
&a->archive, ARCHIVE_ERRNO_MISC,
"Bad record header");
return (ARCHIVE_FATAL);
- } else if ((ver = _warc_rdver(buf, eoh - buf)) > 10000U) {
- /* nawww, I wish they promised backward compatibility
- * anyhoo, in their infinite wisdom the 28500 guys might
- * come up with something we can't possibly handle so
- * best end things here */
+ }
+ ver = _warc_rdver(buf, eoh - buf);
+ /* we currently support WARC 0.12 to 1.0 */
+ if (ver == 0U) {
archive_set_error(
&a->archive, ARCHIVE_ERRNO_MISC,
- "Unsupported record version");
+ "Invalid record version");
return (ARCHIVE_FATAL);
- } else if ((cntlen = _warc_rdlen(buf, eoh - buf)) < 0) {
+ } else if (ver < 1200U || ver > 10000U) {
+ archive_set_error(
+ &a->archive, ARCHIVE_ERRNO_MISC,
+ "Unsupported record version: %u.%u",
+ ver / 10000, (ver % 10000) / 100);
+ return (ARCHIVE_FATAL);
+ }
+ cntlen = _warc_rdlen(buf, eoh - buf);
+ if (cntlen < 0) {
/* nightmare! the specs say content-length is mandatory
* so I don't feel overly bad stopping the reader here */
archive_set_error(
&a->archive, EINVAL,
"Bad content length");
return (ARCHIVE_FATAL);
- } else if ((rtime = _warc_rdrtm(buf, eoh - buf)) == (time_t)-1) {
+ }
+ rtime = _warc_rdrtm(buf, eoh - buf);
+ if (rtime == (time_t)-1) {
/* record time is mandatory as per WARC/1.0,
* so just barf here, fast and loud */
archive_set_error(
@@ -285,7 +293,7 @@ start_over:
if (ver != w->pver) {
/* stringify this entry's version */
archive_string_sprintf(&w->sver,
- "WARC/%u.%u", ver / 10000, ver % 10000);
+ "WARC/%u.%u", ver / 10000, (ver % 10000) / 100);
/* remember the version */
w->pver = ver;
}
@@ -318,7 +326,7 @@ start_over:
}
memcpy(w->pool.str, fnam.str, fnam.len);
w->pool.str[fnam.len] = '\0';
- /* let noone else know about the pool, it's a secret, shhh */
+ /* let no one else know about the pool, it's a secret, shhh */
fnam.str = w->pool.str;
/* snarf mtime or deduce from rtime
@@ -535,7 +543,8 @@ xstrpisotime(const char *s, char **endptr)
/* as a courtesy to our callers, and since this is a non-standard
* routine, we skip leading whitespace */
- for (; isspace(*s); s++);
+ while (*s == ' ' || *s == '\t')
+ ++s;
/* read year */
if ((tm.tm_year = strtoi_lim(s, &s, 1583, 4095)) < 0 || *s++ != '-') {
@@ -562,7 +571,7 @@ xstrpisotime(const char *s, char **endptr)
goto out;
}
- /* massage TM to fulfill some of POSIX' contraints */
+ /* massage TM to fulfill some of POSIX' constraints */
tm.tm_year -= 1900;
tm.tm_mon--;
@@ -577,51 +586,43 @@ out:
}
static unsigned int
-_warc_rdver(const char buf[10], size_t bsz)
+_warc_rdver(const char *buf, size_t bsz)
{
static const char magic[] = "WARC/";
- unsigned int ver;
-
- (void)bsz; /* UNUSED */
+ const char *c;
+ unsigned int ver = 0U;
+ unsigned int end = 0U;
- if (memcmp(buf, magic, sizeof(magic) - 1U) != 0) {
- /* nope */
- return 99999U;
+ if (bsz < 12 || memcmp(buf, magic, sizeof(magic) - 1U) != 0) {
+ /* buffer too small or invalid magic */
+ return ver;
}
/* looks good so far, read the version number for a laugh */
buf += sizeof(magic) - 1U;
- /* most common case gets a quick-check here */
- if (memcmp(buf, "1.0\r\n", 5U) == 0) {
- ver = 10000U;
- } else {
- switch (*buf) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- if (buf[1U] == '.') {
- char *on;
-
- /* set up major version */
- ver = (buf[0U] - '0') * 10000U;
- /* minor version, anyone? */
- ver += (strtol(buf + 2U, &on, 10)) * 100U;
- /* don't parse anything else */
- if (on > buf + 2U) {
- break;
- }
- }
- /* FALLTHROUGH */
- case '9':
- default:
- /* just make the version ridiculously high */
- ver = 999999U;
- break;
+
+ if (isdigit(buf[0U]) && (buf[1U] == '.') && isdigit(buf[2U])) {
+ /* we support a maximum of 2 digits in the minor version */
+ if (isdigit(buf[3U]))
+ end = 1U;
+ /* set up major version */
+ ver = (buf[0U] - '0') * 10000U;
+ /* set up minor version */
+ if (end == 1U) {
+ ver += (buf[2U] - '0') * 1000U;
+ ver += (buf[3U] - '0') * 100U;
+ } else
+ ver += (buf[2U] - '0') * 100U;
+ /*
+ * WARC below version 0.12 has a space-separated header
+ * WARC 0.12 and above terminates the version with a CRLF
+ */
+ c = buf + 3U + end;
+ if (ver >= 1200U) {
+ if (memcmp(c, "\r\n", 2U) != 0)
+ ver = 0U;
+ } else if (ver < 1200U) {
+ if (*c != ' ' && *c != '\t')
+ ver = 0U;
}
}
return ver;
@@ -631,32 +632,27 @@ static unsigned int
_warc_rdtyp(const char *buf, size_t bsz)
{
static const char _key[] = "\r\nWARC-Type:";
- const char *const eob = buf + bsz;
- const char *val;
+ const char *val, *eol;
if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
/* no bother */
return WT_NONE;
}
+ val += sizeof(_key) - 1U;
+ if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
+ /* no end of line */
+ return WT_NONE;
+ }
+
/* overread whitespace */
- for (val += sizeof(_key) - 1U; val < eob && isspace(*val); val++);
-
- if (val + 8U > eob) {
- ;
- } else if (memcmp(val, "resource", 8U) == 0) {
- return WT_RSRC;
- } else if (memcmp(val, "warcinfo", 8U) == 0) {
- return WT_INFO;
- } else if (memcmp(val, "metadata", 8U) == 0) {
- return WT_META;
- } else if (memcmp(val, "request", 7U) == 0) {
- return WT_REQ;
- } else if (memcmp(val, "response", 8U) == 0) {
- return WT_RSP;
- } else if (memcmp(val, "conversi", 8U) == 0) {
- return WT_CONV;
- } else if (memcmp(val, "continua", 8U) == 0) {
- return WT_CONT;
+ while (val < eol && (*val == ' ' || *val == '\t'))
+ ++val;
+
+ if (val + 8U == eol) {
+ if (memcmp(val, "resource", 8U) == 0)
+ return WT_RSRC;
+ else if (memcmp(val, "response", 8U) == 0)
+ return WT_RSP;
}
return WT_NONE;
}
@@ -665,10 +661,7 @@ static warc_string_t
_warc_rduri(const char *buf, size_t bsz)
{
static const char _key[] = "\r\nWARC-Target-URI:";
- const char *const eob = buf + bsz;
- const char *val;
- const char *uri;
- const char *eol;
+ const char *val, *uri, *eol, *p;
warc_string_t res = {0U, NULL};
if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
@@ -676,23 +669,33 @@ _warc_rduri(const char *buf, size_t bsz)
return res;
}
/* overread whitespace */
- for (val += sizeof(_key) - 1U; val < eob && isspace(*val); val++);
+ val += sizeof(_key) - 1U;
+ if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
+ /* no end of line */
+ return res;
+ }
+
+ while (val < eol && (*val == ' ' || *val == '\t'))
+ ++val;
/* overread URL designators */
- if ((uri = xmemmem(val, eob - val, "://", 3U)) == NULL) {
+ if ((uri = xmemmem(val, eol - val, "://", 3U)) == NULL) {
/* not touching that! */
return res;
- } else if ((eol = memchr(uri, '\n', eob - uri)) == NULL) {
- /* no end of line? :O */
- return res;
}
- /* massage uri to point to after :// */
+ /* spaces inside uri are not allowed, CRLF should follow */
+ for (p = val; p < eol; p++) {
+ if (isspace(*p))
+ return res;
+ }
+
+ /* there must be at least space for ftp */
+ if (uri < (val + 3U))
+ return res;
+
+ /* move uri to point to after :// */
uri += 3U;
- /* also massage eol to point to the first whitespace
- * after the last non-whitespace character before
- * the end of the line */
- for (; eol > uri && isspace(eol[-1]); eol--);
/* now then, inspect the URI */
if (memcmp(val, "file", 4U) == 0) {
@@ -715,7 +718,7 @@ static ssize_t
_warc_rdlen(const char *buf, size_t bsz)
{
static const char _key[] = "\r\nContent-Length:";
- const char *val;
+ const char *val, *eol;
char *on = NULL;
long int len;
@@ -723,14 +726,24 @@ _warc_rdlen(const char *buf, size_t bsz)
/* no bother */
return -1;
}
-
- /* strtol kindly overreads whitespace for us, so use that */
val += sizeof(_key) - 1U;
+ if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
+ /* no end of line */
+ return -1;
+ }
+
+ /* skip leading whitespace */
+ while (val < eol && (*val == ' ' || *val == '\t'))
+ val++;
+ /* there must be at least one digit */
+ if (!isdigit(*val))
+ return -1;
len = strtol(val, &on, 10);
- if (on == NULL || !isspace(*on)) {
- /* hm, can we trust that number? Best not. */
+ if (on != eol) {
+ /* line must end here */
return -1;
}
+
return (size_t)len;
}
@@ -738,7 +751,7 @@ static time_t
_warc_rdrtm(const char *buf, size_t bsz)
{
static const char _key[] = "\r\nWARC-Date:";
- const char *val;
+ const char *val, *eol;
char *on = NULL;
time_t res;
@@ -746,13 +759,17 @@ _warc_rdrtm(const char *buf, size_t bsz)
/* no bother */
return (time_t)-1;
}
+ val += sizeof(_key) - 1U;
+ if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) {
+ /* no end of line */
+ return -1;
+ }
/* xstrpisotime() kindly overreads whitespace for us, so use that */
- val += sizeof(_key) - 1U;
res = xstrpisotime(val, &on);
- if (on == NULL || !isspace(*on)) {
- /* hm, can we trust that number? Best not. */
- return (time_t)-1;
+ if (on != eol) {
+ /* line must end here */
+ return -1;
}
return res;
}
@@ -761,7 +778,7 @@ static time_t
_warc_rdmtm(const char *buf, size_t bsz)
{
static const char _key[] = "\r\nLast-Modified:";
- const char *val;
+ const char *val, *eol;
char *on = NULL;
time_t res;
@@ -769,13 +786,17 @@ _warc_rdmtm(const char *buf, size_t bsz)
/* no bother */
return (time_t)-1;
}
+ val += sizeof(_key) - 1U;
+ if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) {
+ /* no end of line */
+ return -1;
+ }
/* xstrpisotime() kindly overreads whitespace for us, so use that */
- val += sizeof(_key) - 1U;
res = xstrpisotime(val, &on);
- if (on == NULL || !isspace(*on)) {
- /* hm, can we trust that number? Best not. */
- return (time_t)-1;
+ if (on != eol) {
+ /* line must end here */
+ return -1;
}
return res;
}
@@ -792,4 +813,12 @@ _warc_find_eoh(const char *buf, size_t bsz)
return hit;
}
+static const char*
+_warc_find_eol(const char *buf, size_t bsz)
+{
+ static const char _marker[] = "\r\n";
+ const char *hit = xmemmem(buf, bsz, _marker, sizeof(_marker) - 1U);
+
+ return hit;
+}
/* archive_read_support_format_warc.c ends here */
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
index ec623c6..eeac1c8 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
@@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$");
#endif
#if HAVE_LZMA_H
#include <cm_lzma.h>
-#elif HAVE_LZMADEC_H
-#include <lzmadec.h>
#endif
#ifdef HAVE_ZLIB_H
#include <cm_zlib.h>
@@ -334,9 +332,6 @@ struct xar {
#if HAVE_LZMA_H && HAVE_LIBLZMA
lzma_stream lzstream;
int lzstream_valid;
-#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
- lzmadec_stream lzstream;
- int lzstream_valid;
#endif
/*
* For Checksum data.
@@ -399,6 +394,7 @@ static void checksum_update(struct archive_read *, const void *,
size_t, const void *, size_t);
static int checksum_final(struct archive_read *, const void *,
size_t, const void *, size_t);
+static void checksum_cleanup(struct archive_read *);
static int decompression_init(struct archive_read *, enum enctype);
static int decompress(struct archive_read *, const void **,
size_t *, const void *, size_t *);
@@ -928,6 +924,7 @@ xar_cleanup(struct archive_read *a)
int r;
xar = (struct xar *)(a->format->data);
+ checksum_cleanup(a);
r = decompression_cleanup(a);
hdlink = xar->hdlink_list;
while (hdlink != NULL) {
@@ -938,6 +935,7 @@ xar_cleanup(struct archive_read *a)
}
for (i = 0; i < xar->file_queue.used; i++)
file_free(xar->file_queue.files[i]);
+ free(xar->file_queue.files);
while (xar->unknowntags != NULL) {
struct unknown_tag *tag;
@@ -1526,34 +1524,6 @@ decompression_init(struct archive_read *a, enum enctype encoding)
xar->lzstream.total_in = 0;
xar->lzstream.total_out = 0;
break;
-#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC)
- case LZMA:
- if (xar->lzstream_valid)
- lzmadec_end(&(xar->lzstream));
- r = lzmadec_init(&(xar->lzstream));
- if (r != LZMADEC_OK) {
- switch (r) {
- case LZMADEC_HEADER_ERROR:
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_MISC,
- "Internal error initializing "
- "compression library: "
- "invalid header");
- break;
- case LZMADEC_MEM_ERROR:
- archive_set_error(&a->archive,
- ENOMEM,
- "Internal error initializing "
- "compression library: "
- "out of memory");
- break;
- }
- return (ARCHIVE_FATAL);
- }
- xar->lzstream_valid = 1;
- xar->lzstream.total_in = 0;
- xar->lzstream.total_out = 0;
- break;
#endif
/*
* Unsupported compression.
@@ -1563,9 +1533,7 @@ decompression_init(struct archive_read *a, enum enctype encoding)
case BZIP2:
#endif
#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA)
-#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC)
case LZMA:
-#endif
case XZ:
#endif
switch (xar->entry_encoding) {
@@ -1685,46 +1653,12 @@ decompress(struct archive_read *a, const void **buff, size_t *outbytes,
*used = avail_in - xar->lzstream.avail_in;
*outbytes = avail_out - xar->lzstream.avail_out;
break;
-#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC)
- case LZMA:
- xar->lzstream.next_in = (unsigned char *)(uintptr_t)b;
- xar->lzstream.avail_in = avail_in;
- xar->lzstream.next_out = (unsigned char *)outbuff;
- xar->lzstream.avail_out = avail_out;
- r = lzmadec_decode(&(xar->lzstream), 0);
- switch (r) {
- case LZMADEC_STREAM_END: /* Found end of stream. */
- switch (lzmadec_end(&(xar->lzstream))) {
- case LZMADEC_OK:
- break;
- default:
- archive_set_error(&(a->archive),
- ARCHIVE_ERRNO_MISC,
- "Failed to clean up lzmadec decompressor");
- return (ARCHIVE_FATAL);
- }
- xar->lzstream_valid = 0;
- /* FALLTHROUGH */
- case LZMADEC_OK: /* Decompressor made some progress. */
- break;
- default:
- archive_set_error(&(a->archive),
- ARCHIVE_ERRNO_MISC,
- "lzmadec decompression failed(%d)",
- r);
- return (ARCHIVE_FATAL);
- }
- *used = avail_in - xar->lzstream.avail_in;
- *outbytes = avail_out - xar->lzstream.avail_out;
- break;
#endif
#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
case BZIP2:
#endif
#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA)
-#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC)
case LZMA:
-#endif
case XZ:
#endif
case NONE:
@@ -1788,6 +1722,16 @@ decompression_cleanup(struct archive_read *a)
}
static void
+checksum_cleanup(struct archive_read *a) {
+ struct xar *xar;
+
+ xar = (struct xar *)(a->format->data);
+
+ _checksum_final(&(xar->a_sumwrk), NULL, 0);
+ _checksum_final(&(xar->e_sumwrk), NULL, 0);
+}
+
+static void
xmlattr_cleanup(struct xmlattr_list *list)
{
struct xmlattr *attr, *next;
@@ -3116,7 +3060,7 @@ xml2_read_cb(void *context, char *buffer, int len)
struct xar *xar;
const void *d;
size_t outbytes;
- size_t used;
+ size_t used = 0;
int r;
a = (struct archive_read *)context;
@@ -3240,6 +3184,9 @@ expat_xmlattr_setup(struct archive_read *a,
value = strdup(atts[1]);
if (attr == NULL || name == NULL || value == NULL) {
archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ free(attr);
+ free(name);
+ free(value);
return (ARCHIVE_FATAL);
}
attr->name = name;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
index c50ba84..e56bd63 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
@@ -199,7 +199,7 @@ struct zip {
struct trad_enc_ctx tctx;
char tctx_valid;
- /* WinZip AES decyption. */
+ /* WinZip AES decryption. */
/* Contexts used for AES decryption. */
archive_crypto_ctx cctx;
char cctx_valid;
@@ -242,7 +242,7 @@ trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c)
}
static uint8_t
-trad_enc_decypt_byte(struct trad_enc_ctx *ctx)
+trad_enc_decrypt_byte(struct trad_enc_ctx *ctx)
{
unsigned temp = ctx->keys[2] | 2;
return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff;
@@ -257,7 +257,7 @@ trad_enc_decrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in,
max = (unsigned)((in_len < out_len)? in_len: out_len);
for (i = 0; i < max; i++) {
- uint8_t t = in[i] ^ trad_enc_decypt_byte(ctx);
+ uint8_t t = in[i] ^ trad_enc_decrypt_byte(ctx);
out[i] = t;
trad_enc_update_keys(ctx, t);
}
@@ -418,18 +418,30 @@ zip_time(const char *p)
* id1+size1+data1 + id2+size2+data2 ...
* triplets. id and size are 2 bytes each.
*/
-static void
-process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
+static int
+process_extra(struct archive_read *a, const char *p, size_t extra_length, struct zip_entry* zip_entry)
{
unsigned offset = 0;
- while (offset < extra_length - 4) {
+ if (extra_length == 0) {
+ return ARCHIVE_OK;
+ }
+
+ if (extra_length < 4) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Too-small extra data: Need at least 4 bytes, but only found %d bytes", (int)extra_length);
+ return ARCHIVE_FAILED;
+ }
+ while (offset <= extra_length - 4) {
unsigned short headerid = archive_le16dec(p + offset);
unsigned short datasize = archive_le16dec(p + offset + 2);
offset += 4;
if (offset + datasize > extra_length) {
- break;
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Extra data overflow: Need %d bytes but only found %d bytes",
+ (int)datasize, (int)(extra_length - offset));
+ return ARCHIVE_FAILED;
}
#ifdef DEBUG
fprintf(stderr, "Header id 0x%04x, length %d\n",
@@ -440,26 +452,38 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
/* Zip64 extended information extra field. */
zip_entry->flags |= LA_USED_ZIP64;
if (zip_entry->uncompressed_size == 0xffffffff) {
- if (datasize < 8)
- break;
- zip_entry->uncompressed_size =
- archive_le64dec(p + offset);
+ uint64_t t = 0;
+ if (datasize < 8
+ || (t = archive_le64dec(p + offset)) > INT64_MAX) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Malformed 64-bit uncompressed size");
+ return ARCHIVE_FAILED;
+ }
+ zip_entry->uncompressed_size = t;
offset += 8;
datasize -= 8;
}
if (zip_entry->compressed_size == 0xffffffff) {
- if (datasize < 8)
- break;
- zip_entry->compressed_size =
- archive_le64dec(p + offset);
+ uint64_t t = 0;
+ if (datasize < 8
+ || (t = archive_le64dec(p + offset)) > INT64_MAX) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Malformed 64-bit compressed size");
+ return ARCHIVE_FAILED;
+ }
+ zip_entry->compressed_size = t;
offset += 8;
datasize -= 8;
}
if (zip_entry->local_header_offset == 0xffffffff) {
- if (datasize < 8)
- break;
- zip_entry->local_header_offset =
- archive_le64dec(p + offset);
+ uint64_t t = 0;
+ if (datasize < 8
+ || (t = archive_le64dec(p + offset)) > INT64_MAX) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Malformed 64-bit local header offset");
+ return ARCHIVE_FAILED;
+ }
+ zip_entry->local_header_offset = t;
offset += 8;
datasize -= 8;
}
@@ -698,7 +722,7 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
break;
}
case 0x9901:
- /* WinZIp AES extra data field. */
+ /* WinZip AES extra data field. */
if (p[offset + 2] == 'A' && p[offset + 3] == 'E') {
/* Vendor version. */
zip_entry->aes_extra.vendor =
@@ -715,13 +739,13 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
}
offset += datasize;
}
-#ifdef DEBUG
- if (offset != extra_length)
- {
- fprintf(stderr,
- "Extra data field contents do not match reported size!\n");
+ if (offset != extra_length) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Malformed extra data: Consumed %d bytes of %d bytes",
+ (int)offset, (int)extra_length);
+ return ARCHIVE_FAILED;
}
-#endif
+ return ARCHIVE_OK;
}
/*
@@ -840,7 +864,9 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
- process_extra(h, extra_length, zip_entry);
+ if (ARCHIVE_OK != process_extra(a, h, extra_length, zip_entry)) {
+ return ARCHIVE_FATAL;
+ }
__archive_read_consume(a, extra_length);
/* Work around a bug in Info-Zip: When reading from a pipe, it
@@ -850,29 +876,33 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
zip_entry->mode |= AE_IFREG;
}
- if ((zip_entry->mode & AE_IFMT) == 0) {
- /* Especially in streaming mode, we can end up
- here without having seen proper mode information.
- Guess from the filename. */
+ /* If the mode is totally empty, set some sane default. */
+ if (zip_entry->mode == 0) {
+ zip_entry->mode |= 0664;
+ }
+
+ /* Make sure that entries with a trailing '/' are marked as directories
+ * even if the External File Attributes contains bogus values. If this
+ * is not a directory and there is no type, assume regularfile. */
+ if ((zip_entry->mode & AE_IFMT) != AE_IFDIR) {
+ int has_slash;
+
wp = archive_entry_pathname_w(entry);
if (wp != NULL) {
len = wcslen(wp);
- if (len > 0 && wp[len - 1] == L'/')
- zip_entry->mode |= AE_IFDIR;
- else
- zip_entry->mode |= AE_IFREG;
+ has_slash = len > 0 && wp[len - 1] == L'/';
} else {
cp = archive_entry_pathname(entry);
len = (cp != NULL)?strlen(cp):0;
- if (len > 0 && cp[len - 1] == '/')
- zip_entry->mode |= AE_IFDIR;
- else
- zip_entry->mode |= AE_IFREG;
+ has_slash = len > 0 && cp[len - 1] == '/';
}
- if (zip_entry->mode == AE_IFDIR) {
- zip_entry->mode |= 0775;
- } else if (zip_entry->mode == AE_IFREG) {
- zip_entry->mode |= 0664;
+ /* Correct file type as needed. */
+ if (has_slash) {
+ zip_entry->mode &= ~AE_IFMT;
+ zip_entry->mode |= AE_IFDIR;
+ zip_entry->mode |= 0111;
+ } else if ((zip_entry->mode & AE_IFMT) == 0) {
+ zip_entry->mode |= AE_IFREG;
}
}
@@ -887,6 +917,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
archive_wstrcat(&s, wp);
archive_wstrappend_wchar(&s, L'/');
archive_entry_copy_pathname_w(entry, s.s);
+ archive_wstring_free(&s);
}
} else {
cp = archive_entry_pathname(entry);
@@ -897,6 +928,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
archive_strcat(&s, cp);
archive_strappend_char(&s, '/');
archive_entry_set_pathname(entry, s.s);
+ archive_string_free(&s);
}
}
}
@@ -1136,11 +1168,18 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
|| (zip->hctx_valid
&& zip->entry->aes_extra.vendor == AES_VENDOR_AE_2))) {
if (zip->entry->flags & LA_USED_ZIP64) {
+ uint64_t compressed, uncompressed;
zip->entry->crc32 = archive_le32dec(p + 4);
- zip->entry->compressed_size =
- archive_le64dec(p + 8);
- zip->entry->uncompressed_size =
- archive_le64dec(p + 16);
+ compressed = archive_le64dec(p + 8);
+ uncompressed = archive_le64dec(p + 16);
+ if (compressed > INT64_MAX || uncompressed > INT64_MAX) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Overflow of 64-bit file sizes");
+ return ARCHIVE_FAILED;
+ }
+ zip->entry->compressed_size = compressed;
+ zip->entry->uncompressed_size = uncompressed;
zip->unconsumed = 24;
} else {
zip->entry->crc32 = archive_le32dec(p + 4);
@@ -1293,7 +1332,7 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
&& bytes_avail > zip->entry_bytes_remaining) {
bytes_avail = (ssize_t)zip->entry_bytes_remaining;
}
- if (bytes_avail <= 0) {
+ if (bytes_avail < 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file body");
return (ARCHIVE_FATAL);
@@ -1417,9 +1456,18 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
zip->unconsumed = 4;
}
if (zip->entry->flags & LA_USED_ZIP64) {
+ uint64_t compressed, uncompressed;
zip->entry->crc32 = archive_le32dec(p);
- zip->entry->compressed_size = archive_le64dec(p + 4);
- zip->entry->uncompressed_size = archive_le64dec(p + 12);
+ compressed = archive_le64dec(p + 4);
+ uncompressed = archive_le64dec(p + 12);
+ if (compressed > INT64_MAX || uncompressed > INT64_MAX) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Overflow of 64-bit file sizes");
+ return ARCHIVE_FAILED;
+ }
+ zip->entry->compressed_size = compressed;
+ zip->entry->uncompressed_size = uncompressed;
zip->unconsumed += 20;
} else {
zip->entry->crc32 = archive_le32dec(p);
@@ -1500,7 +1548,7 @@ read_decryption_header(struct archive_read *a)
case 0x6720:/* Blowfish */
case 0x6721:/* Twofish */
case 0x6801:/* RC4 */
- /* Suuported encryption algorithm. */
+ /* Supported encryption algorithm. */
break;
default:
archive_set_error(&a->archive,
@@ -1609,7 +1657,7 @@ read_decryption_header(struct archive_read *a)
__archive_read_consume(a, 4);
/*return (ARCHIVE_OK);
- * This is not fully implemnted yet.*/
+ * This is not fully implemented yet.*/
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Encrypted file is unsupported");
return (ARCHIVE_FAILED);
@@ -1691,7 +1739,7 @@ init_traditional_PKWARE_decryption(struct archive_read *a)
}
/*
- * Initialize ctx for Traditional PKWARE Decyption.
+ * Initialize ctx for Traditional PKWARE Decryption.
*/
r = trad_enc_init(&zip->tctx, passphrase, strlen(passphrase),
p, ENC_HEADER_SIZE, &crcchk);
@@ -2691,7 +2739,9 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
"Truncated ZIP file header");
return ARCHIVE_FATAL;
}
- process_extra(p + filename_length, extra_length, zip_entry);
+ if (ARCHIVE_OK != process_extra(a, p + filename_length, extra_length, zip_entry)) {
+ return ARCHIVE_FATAL;
+ }
/*
* Mac resource fork files are stored under the
diff --git a/Utilities/cmlibarchive/libarchive/archive_string.c b/Utilities/cmlibarchive/libarchive/archive_string.c
index 282c58e..592ead2 100644
--- a/Utilities/cmlibarchive/libarchive/archive_string.c
+++ b/Utilities/cmlibarchive/libarchive/archive_string.c
@@ -219,6 +219,12 @@ archive_wstring_append(struct archive_wstring *as, const wchar_t *p, size_t s)
return (as);
}
+struct archive_string *
+archive_array_append(struct archive_string *as, const char *p, size_t s)
+{
+ return archive_string_append(as, p, s);
+}
+
void
archive_string_concat(struct archive_string *dest, struct archive_string *src)
{
@@ -559,7 +565,8 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
}
if (count == 0 && length != 0)
ret = -1;
- } while (0);
+ break;
+ } while (1);
}
dest->length += count;
dest->s[dest->length] = L'\0';
@@ -596,7 +603,7 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest,
wcs = dest->s + dest->length;
/*
* We cannot use mbsrtowcs/mbstowcs here because those may convert
- * extra MBS when strlen(p) > len and one wide character consis of
+ * extra MBS when strlen(p) > len and one wide character consists of
* multi bytes.
*/
while (*mbs && mbs_length > 0) {
@@ -1247,7 +1254,7 @@ create_sconv_object(const char *fc, const char *tc,
sc->cd = iconv_open(tc, fc);
if (sc->cd == (iconv_t)-1 && (sc->flag & SCONV_BEST_EFFORT)) {
/*
- * Unfortunaly, all of iconv implements do support
+ * Unfortunately, all of iconv implements do support
* "CP932" character-set, so we should use "SJIS"
* instead if iconv_open failed.
*/
@@ -1260,7 +1267,7 @@ create_sconv_object(const char *fc, const char *tc,
/*
* archive_mstring on Windows directly convert multi-bytes
* into archive_wstring in order not to depend on locale
- * so that you can do a I18N programing. This will be
+ * so that you can do a I18N programming. This will be
* used only in archive_mstring_copy_mbs_len_l so far.
*/
if (flag & SCONV_FROM_CHARSET) {
@@ -1725,7 +1732,7 @@ archive_string_conversion_from_charset(struct archive *a, const char *charset,
* in tar or zip files. But mbstowcs/wcstombs(CRT) usually use CP_ACP
* unless you use setlocale(LC_ALL, ".OCP")(specify CP_OEMCP).
* So we should make a string conversion between CP_ACP and CP_OEMCP
- * for compatibillty.
+ * for compatibility.
*/
#if defined(_WIN32) && !defined(__CYGWIN__)
struct archive_string_conv *
@@ -1826,7 +1833,7 @@ archive_string_conversion_set_opt(struct archive_string_conv *sc, int opt)
* A filename in UTF-8 was made with libarchive 2.x in a wrong
* assumption that wchar_t was Unicode.
* This option enables simulating the assumption in order to read
- * that filname correctly.
+ * that filename correctly.
*/
case SCONV_SET_OPT_UTF8_LIBARCHIVE2X:
#if (defined(_WIN32) && !defined(__CYGWIN__)) \
@@ -1938,12 +1945,19 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
struct archive_string_conv *sc)
{
const void *s;
- size_t length;
+ size_t length = 0;
int i, r = 0, r2;
+ if (_p != NULL && n > 0) {
+ if (sc != NULL && (sc->flag & SCONV_FROM_UTF16))
+ length = utf16nbytes(_p, n);
+ else
+ length = mbsnbytes(_p, n);
+ }
+
/* We must allocate memory even if there is no data for conversion
* or copy. This simulates archive_string_append behavior. */
- if (_p == NULL || n == 0) {
+ if (length == 0) {
int tn = 1;
if (sc != NULL && (sc->flag & SCONV_TO_UTF16))
tn = 2;
@@ -1959,16 +1973,11 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
* If sc is NULL, we just make a copy.
*/
if (sc == NULL) {
- length = mbsnbytes(_p, n);
if (archive_string_append(as, _p, length) == NULL)
return (-1);/* No memory */
return (0);
}
- if (sc->flag & SCONV_FROM_UTF16)
- length = utf16nbytes(_p, n);
- else
- length = mbsnbytes(_p, n);
s = _p;
i = 0;
if (sc->nconverter > 1) {
@@ -1991,7 +2000,7 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
#if HAVE_ICONV
/*
- * Return -1 if conversion failes.
+ * Return -1 if conversion fails.
*/
static int
iconv_strncat_in_locale(struct archive_string *as, const void *_p,
@@ -2093,7 +2102,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
/*
* Translate a string from a some CodePage to an another CodePage by
- * Windows APIs, and copy the result. Return -1 if conversion failes.
+ * Windows APIs, and copy the result. Return -1 if conversion fails.
*/
static int
strncat_in_codepage(struct archive_string *as,
@@ -2217,7 +2226,7 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p,
/*
* If a character is ASCII, this just copies it. If not, this
- * assigns '?' charater instead but in UTF-8 locale this assigns
+ * assigns '?' character instead but in UTF-8 locale this assigns
* byte sequence 0xEF 0xBD 0xBD, which are code point U+FFFD,
* a Replacement Character in Unicode.
*/
@@ -2297,7 +2306,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
return (0); /* Standard: return 0 for end-of-string. */
cnt = utf8_count[ch];
- /* Invalide sequence or there are not plenty bytes. */
+ /* Invalid sequence or there are not plenty bytes. */
if ((int)n < cnt) {
cnt = (int)n;
for (i = 1; i < cnt; i++) {
@@ -2378,7 +2387,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
goto invalid_sequence;
}
- /* The code point larger than 0x10FFFF is not leagal
+ /* The code point larger than 0x10FFFF is not legal
* Unicode values. */
if (wc > UNICODE_MAX)
goto invalid_sequence;
@@ -2396,7 +2405,7 @@ utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
int cnt;
cnt = _utf8_to_unicode(pwc, s, n);
- /* Any of Surrogate pair is not leagal Unicode values. */
+ /* Any of Surrogate pair is not legal Unicode values. */
if (cnt == 3 && IS_SURROGATE_PAIR_LA(*pwc))
return (-3);
return (cnt);
@@ -2457,7 +2466,7 @@ invalid_sequence:
/*
* Convert a Unicode code point to a single UTF-8 sequence.
*
- * NOTE:This function does not check if the Unicode is leagal or not.
+ * NOTE:This function does not check if the Unicode is legal or not.
* Please you definitely check it before calling this.
*/
static size_t
@@ -2551,9 +2560,9 @@ utf16_to_unicode(uint32_t *pwc, const char *s, size_t n, int be)
/*
* Surrogate pair values(0xd800 through 0xdfff) are only
- * used by UTF-16, so, after above culculation, the code
+ * used by UTF-16, so, after above calculation, the code
* must not be surrogate values, and Unicode has no codes
- * larger than 0x10ffff. Thus, those are not leagal Unicode
+ * larger than 0x10ffff. Thus, those are not legal Unicode
* values.
*/
if (IS_SURROGATE_PAIR_LA(uc) || uc > UNICODE_MAX) {
@@ -2900,7 +2909,7 @@ get_nfc(uint32_t uc, uint32_t uc2)
/*
* Normalize UTF-8/UTF-16BE characters to Form C and copy the result.
*
- * TODO: Convert composition exclusions,which are never converted
+ * TODO: Convert composition exclusions, which are never converted
* from NFC,NFD,NFKC and NFKD, to Form C.
*/
static int
@@ -3434,7 +3443,7 @@ strncat_from_utf8_libarchive2(struct archive_string *as,
}
/*
- * As libarchie 2.x, translates the UTF-8 characters into
+ * As libarchive 2.x, translates the UTF-8 characters into
* wide-characters in the assumption that WCS is Unicode.
*/
if (n < 0) {
@@ -3473,7 +3482,7 @@ strncat_from_utf8_libarchive2(struct archive_string *as,
/*
* Convert a UTF-16BE/LE string to current locale and copy the result.
- * Return -1 if conversion failes.
+ * Return -1 if conversion fails.
*/
static int
win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
@@ -3552,18 +3561,19 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
ll = WideCharToMultiByte(sc->to_cp, 0,
(LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size,
NULL, &defchar);
- if (ll == 0 &&
- GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
- /* Need more buffer for MBS. */
- ll = WideCharToMultiByte(sc->to_cp, 0,
- (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
- if (archive_string_ensure(as, ll +1) == NULL)
- return (-1);
- mbs = as->s + as->length;
- mbs_size = as->buffer_length - as->length -1;
- continue;
+ /* Exit loop if we succeeded */
+ if (ll != 0 ||
+ GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ break;
}
- } while (0);
+ /* Else expand buffer and loop to try again. */
+ ll = WideCharToMultiByte(sc->to_cp, 0,
+ (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
+ if (archive_string_ensure(as, ll +1) == NULL)
+ return (-1);
+ mbs = as->s + as->length;
+ mbs_size = as->buffer_length - as->length -1;
+ } while (1);
archive_string_free(&tmp);
as->length += ll;
as->s[as->length] = '\0';
@@ -3596,7 +3606,7 @@ is_big_endian(void)
/*
* Convert a current locale string to UTF-16BE/LE and copy the result.
- * Return -1 if conversion failes.
+ * Return -1 if conversion fails.
*/
static int
win_strncat_to_utf16(struct archive_string *as16, const void *_p,
@@ -3634,19 +3644,20 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p,
do {
count = MultiByteToWideChar(sc->from_cp,
MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1);
- if (count == 0 &&
- GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
- /* Need more buffer for UTF-16 string */
- count = MultiByteToWideChar(sc->from_cp,
- MB_PRECOMPOSED, s, (int)length, NULL, 0);
- if (archive_string_ensure(as16, (count +1) * 2)
- == NULL)
- return (-1);
- u16 = as16->s + as16->length;
- avail = as16->buffer_length - 2;
- continue;
+ /* Exit loop if we succeeded */
+ if (count != 0 ||
+ GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ break;
}
- } while (0);
+ /* Expand buffer and try again */
+ count = MultiByteToWideChar(sc->from_cp,
+ MB_PRECOMPOSED, s, (int)length, NULL, 0);
+ if (archive_string_ensure(as16, (count +1) * 2)
+ == NULL)
+ return (-1);
+ u16 = as16->s + as16->length;
+ avail = as16->buffer_length - 2;
+ } while (1);
as16->length += count * 2;
as16->s[as16->length] = 0;
as16->s[as16->length+1] = 0;
@@ -3700,7 +3711,7 @@ win_strncat_to_utf16le(struct archive_string *as16, const void *_p,
/*
* Convert a UTF-16BE string to current locale and copy the result.
- * Return -1 if conversion failes.
+ * Return -1 if conversion fails.
*/
static int
best_effort_strncat_from_utf16(struct archive_string *as, const void *_p,
@@ -3758,7 +3769,7 @@ best_effort_strncat_from_utf16le(struct archive_string *as, const void *_p,
/*
* Convert a current locale string to UTF-16BE/LE and copy the result.
- * Return -1 if conversion failes.
+ * Return -1 if conversion fails.
*/
static int
best_effort_strncat_to_utf16(struct archive_string *as16, const void *_p,
@@ -3942,7 +3953,7 @@ archive_mstring_get_mbs_l(struct archive_mstring *aes,
#if defined(_WIN32) && !defined(__CYGWIN__)
/*
- * Internationalization programing on Windows must use Wide
+ * Internationalization programming on Windows must use Wide
* characters because Windows platform cannot make locale UTF-8.
*/
if (sc != NULL && (aes->aes_set & AES_SET_WCS) != 0) {
@@ -4074,7 +4085,7 @@ archive_mstring_copy_mbs_len_l(struct archive_mstring *aes,
archive_string_empty(&(aes->aes_utf8));
#if defined(_WIN32) && !defined(__CYGWIN__)
/*
- * Internationalization programing on Windows must use Wide
+ * Internationalization programming on Windows must use Wide
* characters because Windows platform cannot make locale UTF-8.
*/
if (sc == NULL) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_string.h b/Utilities/cmlibarchive/libarchive/archive_string.h
index 23f4916..56dfbb2 100644
--- a/Utilities/cmlibarchive/libarchive/archive_string.h
+++ b/Utilities/cmlibarchive/libarchive/archive_string.h
@@ -81,6 +81,10 @@ archive_strappend_char(struct archive_string *, char);
struct archive_wstring *
archive_wstrappend_wchar(struct archive_wstring *, wchar_t);
+/* Append a raw array to an archive_string, resizing as necessary */
+struct archive_string *
+archive_array_append(struct archive_string *, const char *, size_t);
+
/* Convert a Unicode string to current locale and append the result. */
/* Returns -1 if conversion fails. */
int
@@ -115,13 +119,13 @@ archive_string_conversion_set_opt(struct archive_string_conv *, int);
/* Copy one archive_string to another in locale conversion.
- * Return -1 if conversion failes. */
+ * Return -1 if conversion fails. */
int
archive_strncpy_l(struct archive_string *, const void *, size_t,
struct archive_string_conv *);
/* Copy one archive_string to another in locale conversion.
- * Return -1 if conversion failes. */
+ * Return -1 if conversion fails. */
int
archive_strncat_l(struct archive_string *, const void *, size_t,
struct archive_string_conv *);
diff --git a/Utilities/cmlibarchive/libarchive/archive_string_composition.h b/Utilities/cmlibarchive/libarchive/archive_string_composition.h
index be41e33..8902ac1 100644
--- a/Utilities/cmlibarchive/libarchive/archive_string_composition.h
+++ b/Utilities/cmlibarchive/libarchive/archive_string_composition.h
@@ -1009,7 +1009,7 @@ static const char u_decomposable_blocks[0x1D2+1] = {
(((uc) > 0x1D244)?0:\
ccc_val[ccc_val_index[ccc_index[(uc)>>8]][((uc)>>4)&0x0F]][(uc)&0x0F])
-/* The table of the value of Canonical Cimbining Class */
+/* The table of the value of Canonical Combining Class */
static const unsigned char ccc_val[][16] = {
/* idx=0: XXXX0 - XXXXF */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
diff --git a/Utilities/cmlibarchive/libarchive/archive_util.c b/Utilities/cmlibarchive/libarchive/archive_util.c
index f89df1d..f56ca33 100644
--- a/Utilities/cmlibarchive/libarchive/archive_util.c
+++ b/Utilities/cmlibarchive/libarchive/archive_util.c
@@ -580,7 +580,7 @@ void
__archive_ensure_cloexec_flag(int fd)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
- (void)fd; /* UNSED */
+ (void)fd; /* UNUSED */
#else
int flags;
diff --git a/Utilities/cmlibarchive/libarchive/archive_windows.c b/Utilities/cmlibarchive/libarchive/archive_windows.c
index d4e93fe..6ff8749 100644
--- a/Utilities/cmlibarchive/libarchive/archive_windows.c
+++ b/Utilities/cmlibarchive/libarchive/archive_windows.c
@@ -766,7 +766,7 @@ __la_win_entry_in_posix_pathseparator(struct archive_entry *entry)
has_backslash = 1;
}
/*
- * If there is no backslach chars, return the original.
+ * If there is no backslash chars, return the original.
*/
if (!has_backslash)
return (entry);
@@ -891,7 +891,7 @@ __la_dosmaperr(unsigned long e)
return;
}
- for (i = 0; i < (int)sizeof(doserrors); i++)
+ for (i = 0; i < (int)(sizeof(doserrors)/sizeof(doserrors[0])); i++)
{
if (doserrors[i].winerr == e)
{
diff --git a/Utilities/cmlibarchive/libarchive/archive_windows.h b/Utilities/cmlibarchive/libarchive/archive_windows.h
index 7c31a16..c3aed0c 100644
--- a/Utilities/cmlibarchive/libarchive/archive_windows.h
+++ b/Utilities/cmlibarchive/libarchive/archive_windows.h
@@ -224,16 +224,20 @@
#define S_IWUSR _S_IWUSR
#define S_IRUSR _S_IRUSR
#endif
+#ifndef S_IRWXG
#define S_IRWXG _S_IRWXG
#define S_IXGRP _S_IXGRP
#define S_IWGRP _S_IWGRP
+#endif
#ifndef S_IRGRP
#define S_IRGRP _S_IRGRP
#endif
+#ifndef S_IRWXO
#define S_IRWXO _S_IRWXO
#define S_IXOTH _S_IXOTH
#define S_IWOTH _S_IWOTH
#define S_IROTH _S_IROTH
+#endif
#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_write.c b/Utilities/cmlibarchive/libarchive/archive_write.c
index e3fa335..0634a22 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write.c
@@ -109,10 +109,9 @@ archive_write_new(void)
struct archive_write *a;
unsigned char *nulls;
- a = (struct archive_write *)malloc(sizeof(*a));
+ a = (struct archive_write *)calloc(1, sizeof(*a));
if (a == NULL)
return (NULL);
- memset(a, 0, sizeof(*a));
a->archive.magic = ARCHIVE_WRITE_MAGIC;
a->archive.state = ARCHIVE_STATE_NEW;
a->archive.vtable = archive_write_vtable();
@@ -126,12 +125,11 @@ archive_write_new(void)
/* Initialize a block of nulls for padding purposes. */
a->null_length = 1024;
- nulls = (unsigned char *)malloc(a->null_length);
+ nulls = (unsigned char *)calloc(1, a->null_length);
if (nulls == NULL) {
free(a);
return (NULL);
}
- memset(nulls, 0, a->null_length);
a->nulls = nulls;
return (&a->archive);
}
@@ -233,7 +231,7 @@ __archive_write_filter(struct archive_write_filter *f,
if (length == 0)
return(ARCHIVE_OK);
if (f->write == NULL)
- /* If unset, a fatal error has already ocuured, so this filter
+ /* If unset, a fatal error has already occurred, so this filter
* didn't open. We cannot write anything. */
return(ARCHIVE_FATAL);
r = (f->write)(f, buff, length);
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c
index 1d0ab8c..e655185 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c
@@ -523,7 +523,7 @@ drive_compressor_independence(struct archive_write_filter *f, const char *p,
archive_le32enc(data->out, outsize);
data->out += 4;
} else {
- /* The buffer is not compressed. The commpressed size was
+ /* The buffer is not compressed. The compressed size was
* bigger than its uncompressed size. */
archive_le32enc(data->out, length | 0x80000000);
data->out += 4;
@@ -608,7 +608,7 @@ drive_compressor_dependence(struct archive_write_filter *f, const char *p,
archive_le32enc(data->out, outsize);
data->out += 4;
} else {
- /* The buffer is not compressed. The commpressed size was
+ /* The buffer is not compressed. The compressed size was
* bigger than its uncompressed size. */
archive_le32enc(data->out, length | 0x80000000);
data->out += 4;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c
index 31a1b6f..55b5e8e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c
@@ -200,6 +200,7 @@ __archive_write_program_free(struct archive_write_program_data *data)
if (data->child)
CloseHandle(data->child);
#endif
+ free(data->program_name);
free(data->child_buf);
free(data);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c
index 4f849ce..e4a3535 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c
@@ -233,7 +233,7 @@ archive_compressor_xz_init_stream(struct archive_write_filter *f,
if (f->code == ARCHIVE_FILTER_XZ) {
#ifdef HAVE_LZMA_STREAM_ENCODER_MT
if (data->threads != 1) {
- bzero(&mt_options, sizeof(mt_options));
+ memset(&mt_options, 0, sizeof(mt_options));
mt_options.threads = data->threads;
mt_options.timeout = 300;
mt_options.filters = data->lzmafilters;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c
index 5cbba54..144ab7e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c
@@ -34,6 +34,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 0
#define _ACL_PRIVATE /* For debugging */
#include <sys/acl.h>
#endif
+#if HAVE_DARWIN_ACL
+#include <membership.h>
+#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
@@ -43,7 +46,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 0
#include "archive_acl_private.h"
#include "archive_write_disk_private.h"
-#ifndef HAVE_POSIX_ACL
+#if !HAVE_POSIX_ACL && !HAVE_NFS4_ACL
/* Default empty function body to satisfy mainline code. */
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
@@ -56,47 +59,111 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
return (ARCHIVE_OK);
}
-#else
+#else /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
+
+#if HAVE_SUN_ACL
+#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACE_T
+#elif HAVE_DARWIN_ACL
+#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_EXTENDED
+#elif HAVE_ACL_TYPE_NFS4
+#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_NFS4
+#endif
static int set_acl(struct archive *, int fd, const char *,
struct archive_acl *,
acl_type_t, int archive_entry_acl_type, const char *tn);
-/*
- * XXX TODO: What about ACL types other than ACCESS and DEFAULT?
- */
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl)
{
- int ret;
+ int ret = ARCHIVE_OK;
- if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) > 0) {
- ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_ACCESS,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
- if (ret != ARCHIVE_OK)
- return (ret);
- ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_DEFAULT,
- ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
+#if !HAVE_DARWIN_ACL
+ if ((archive_acl_types(abstract_acl)
+ & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
+#if HAVE_SUN_ACL
+ /* Solaris writes POSIX.1e access and default ACLs together */
+ ret = set_acl(a, fd, name, abstract_acl, ACLENT_T,
+ ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
+#else /* HAVE_POSIX_ACL */
+ if ((archive_acl_types(abstract_acl)
+ & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+ ret = set_acl(a, fd, name, abstract_acl,
+ ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+ "access");
+ if (ret != ARCHIVE_OK)
+ return (ret);
+ }
+ if ((archive_acl_types(abstract_acl)
+ & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
+ ret = set_acl(a, fd, name, abstract_acl,
+ ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
+ "default");
+#endif /* !HAVE_SUN_ACL */
+ /* Simultaneous POSIX.1e and NFSv4 is not supported */
return (ret);
-#ifdef ACL_TYPE_NFS4
- } else if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4) > 0) {
- ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_NFS4,
+ }
+#endif /* !HAVE_DARWIN_ACL */
+#if HAVE_NFS4_ACL
+ if ((archive_acl_types(abstract_acl) &
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ ret = set_acl(a, fd, name, abstract_acl,
+ ARCHIVE_PLATFORM_ACL_TYPE_NFS4,
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
- return (ret);
-#endif
- } else
- return ARCHIVE_OK;
+ }
+#endif /* HAVE_NFS4_ACL */
+ return (ret);
}
-static struct {
- int archive_perm;
- int platform_perm;
+/*
+ * Translate system ACL permissions into libarchive internal structure
+ */
+static const struct {
+ const int archive_perm;
+ const int platform_perm;
} acl_perm_map[] = {
+#if HAVE_SUN_ACL /* Solaris NFSv4 ACL permissions */
+ {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
+ {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
+ {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
+ {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
+ {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
+ {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
+ {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
+ {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
+ {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
+#elif HAVE_DARWIN_ACL /* MacOS ACL permissions */
+ {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
+ {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
+ {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
+ {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+ {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
+ {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
+ {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
+ {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
+ {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
+ {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
+ {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+#else /* POSIX.1e ACL permissions */
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4 /* FreeBSD NFSv4 ACL permissions */
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
@@ -114,33 +181,69 @@ static struct {
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
#endif
+#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
};
-#ifdef ACL_TYPE_NFS4
-static struct {
- int archive_inherit;
- int platform_inherit;
+#if HAVE_NFS4_ACL
+/*
+ * Translate system NFSv4 inheritance flags into libarchive internal structure
+ */
+static const struct {
+ const int archive_inherit;
+ const int platform_inherit;
} acl_inherit_map[] = {
+#if HAVE_SUN_ACL /* Solaris NFSv4 inheritance flags */
+ {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
+ {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
+ {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
+#elif HAVE_DARWIN_ACL /* MacOS NFSv4 inheritance flags */
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
+ {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
+#else /* FreeBSD NFSv4 ACL inheritance flags */
{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
- {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
+ {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
+ {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
+#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
};
-#endif
+#endif /* HAVE_NFS4_ACL */
static int
set_acl(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl,
acl_type_t acl_type, int ae_requested_type, const char *tname)
{
+#if HAVE_SUN_ACL
+ aclent_t *aclent;
+ ace_t *ace;
+ int e, r;
+ acl_t *acl;
+#else
acl_t acl;
acl_entry_t acl_entry;
acl_permset_t acl_permset;
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
acl_flagset_t acl_flagset;
#endif
+#endif /* HAVE_SUN_ACL */
+#if HAVE_ACL_TYPE_NFS4
+ int r;
+#endif
int ret;
int ae_type, ae_permset, ae_tag, ae_id;
+#if HAVE_DARWIN_ACL
+ uuid_t ae_uuid;
+#endif
uid_t ae_uid;
gid_t ae_gid;
const char *ae_name;
@@ -151,22 +254,165 @@ set_acl(struct archive *a, int fd, const char *name,
entries = archive_acl_reset(abstract_acl, ae_requested_type);
if (entries == 0)
return (ARCHIVE_OK);
+
+#if HAVE_SUN_ACL
+ acl = NULL;
+ acl = malloc(sizeof(acl_t));
+ if (acl == NULL) {
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Invalid ACL type");
+ return (ARCHIVE_FAILED);
+ }
+ if (acl_type == ACE_T)
+ acl->acl_entry_size = sizeof(ace_t);
+ else if (acl_type == ACLENT_T)
+ acl->acl_entry_size = sizeof(aclent_t);
+ else {
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Invalid ACL type");
+ acl_free(acl);
+ return (ARCHIVE_FAILED);
+ }
+ acl->acl_type = acl_type;
+ acl->acl_cnt = entries;
+
+ acl->acl_aclp = malloc(entries * acl->acl_entry_size);
+ if (acl->acl_aclp == NULL) {
+ archive_set_error(a, errno,
+ "Can't allocate memory for acl buffer");
+ acl_free(acl);
+ return (ARCHIVE_FAILED);
+ }
+#else /* !HAVE_SUN_ACL */
acl = acl_init(entries);
+ if (acl == (acl_t)NULL) {
+ archive_set_error(a, errno,
+ "Failed to initialize ACL working storage");
+ return (ARCHIVE_FAILED);
+ }
+#endif /* !HAVE_SUN_ACL */
+#if HAVE_SUN_ACL
+ e = 0;
+#endif
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
- acl_create_entry(&acl, &acl_entry);
-
+#if HAVE_SUN_ACL
+ ace = NULL;
+ aclent = NULL;
+ if (acl->acl_type == ACE_T) {
+ ace = &((ace_t *)acl->acl_aclp)[e];
+ ace->a_who = -1;
+ ace->a_access_mask = 0;
+ ace->a_flags = 0;
+ } else {
+ aclent = &((aclent_t *)acl->acl_aclp)[e];
+ aclent->a_id = -1;
+ aclent->a_type = 0;
+ aclent->a_perm = 0;
+ }
+#else /* !HAVE_SUN_ACL */
+#if HAVE_DARWIN_ACL
+ /*
+ * Mac OS doesn't support NFSv4 ACLs for
+ * owner@, group@ and everyone@.
+ * We skip any of these ACLs found.
+ */
+ if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ ||
+ ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ ||
+ ae_tag == ARCHIVE_ENTRY_ACL_EVERYONE)
+ continue;
+#endif
+ if (acl_create_entry(&acl, &acl_entry) != 0) {
+ archive_set_error(a, errno,
+ "Failed to create a new ACL entry");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+#endif /* !HAVE_SUN_ACL */
+#if HAVE_DARWIN_ACL
+ switch (ae_type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
+ acl_set_tag_type(acl_entry, ACL_EXTENDED_ALLOW);
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DENY:
+ acl_set_tag_type(acl_entry, ACL_EXTENDED_DENY);
+ break;
+ default:
+ /* We don't support any other types on MacOS */
+ continue;
+ }
+#endif
switch (ae_tag) {
+#if HAVE_SUN_ACL
+ case ARCHIVE_ENTRY_ACL_USER:
+ ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
+ if (acl->acl_type == ACE_T)
+ ace->a_who = ae_uid;
+ else {
+ aclent->a_id = ae_uid;
+ aclent->a_type |= USER;
+ }
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP:
+ ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
+ if (acl->acl_type == ACE_T) {
+ ace->a_who = ae_gid;
+ ace->a_flags |= ACE_IDENTIFIER_GROUP;
+ } else {
+ aclent->a_id = ae_gid;
+ aclent->a_type |= GROUP;
+ }
+ break;
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ if (acl->acl_type == ACE_T)
+ ace->a_flags |= ACE_OWNER;
+ else
+ aclent->a_type |= USER_OBJ;
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ if (acl->acl_type == ACE_T) {
+ ace->a_flags |= ACE_GROUP;
+ ace->a_flags |= ACE_IDENTIFIER_GROUP;
+ } else
+ aclent->a_type |= GROUP_OBJ;
+ break;
+ case ARCHIVE_ENTRY_ACL_MASK:
+ aclent->a_type |= CLASS_OBJ;
+ break;
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ aclent->a_type |= OTHER_OBJ;
+ break;
+ case ARCHIVE_ENTRY_ACL_EVERYONE:
+ ace->a_flags |= ACE_EVERYONE;
+ break;
+#else /* !HAVE_SUN_ACL */
case ARCHIVE_ENTRY_ACL_USER:
- acl_set_tag_type(acl_entry, ACL_USER);
ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
+#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
+ acl_set_tag_type(acl_entry, ACL_USER);
acl_set_qualifier(acl_entry, &ae_uid);
+#else /* MacOS */
+ if (mbr_identifier_to_uuid(ID_TYPE_UID, &ae_uid,
+ sizeof(uid_t), ae_uuid) != 0)
+ continue;
+ if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
+ continue;
+#endif /* HAVE_DARWIN_ACL */
break;
case ARCHIVE_ENTRY_ACL_GROUP:
- acl_set_tag_type(acl_entry, ACL_GROUP);
ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
+#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
+ acl_set_tag_type(acl_entry, ACL_GROUP);
acl_set_qualifier(acl_entry, &ae_gid);
+#else /* MacOS */
+ if (mbr_identifier_to_uuid(ID_TYPE_GID, &ae_gid,
+ sizeof(gid_t), ae_uuid) != 0)
+ continue;
+ if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
+ continue;
+#endif /* HAVE_DARWIN_ACL */
break;
+#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
case ARCHIVE_ENTRY_ACL_USER_OBJ:
acl_set_tag_type(acl_entry, ACL_USER_OBJ);
break;
@@ -179,85 +425,230 @@ set_acl(struct archive *a, int fd, const char *name,
case ARCHIVE_ENTRY_ACL_OTHER:
acl_set_tag_type(acl_entry, ACL_OTHER);
break;
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4 /* FreeBSD only */
case ARCHIVE_ENTRY_ACL_EVERYONE:
acl_set_tag_type(acl_entry, ACL_EVERYONE);
break;
#endif
+#endif /* !HAVE_DARWIN_ACL */
+#endif /* !HAVE_SUN_ACL */
default:
- /* XXX */
- break;
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unknown ACL tag");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
}
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL
+ r = 0;
switch (ae_type) {
+#if HAVE_SUN_ACL
+ case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
+ if (ace != NULL)
+ ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ else
+ r = -1;
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DENY:
+ if (ace != NULL)
+ ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
+ else
+ r = -1;
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
+ if (ace != NULL)
+ ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
+ else
+ r = -1;
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
+ if (ace != NULL)
+ ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
+ else
+ r = -1;
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+ if (aclent == NULL)
+ r = -1;
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+ if (aclent != NULL)
+ aclent->a_type |= ACL_DEFAULT;
+ else
+ r = -1;
+ break;
+#else /* !HAVE_SUN_ACL */
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
- acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
+ r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
break;
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
- acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
+ r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
break;
case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
- acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
+ r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
break;
case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
- acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
+ r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
break;
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
// These don't translate directly into the system ACL.
break;
+#endif /* !HAVE_SUN_ACL */
default:
- // XXX error handling here.
- break;
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unknown ACL entry type");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
}
-#endif
- acl_get_permset(acl_entry, &acl_permset);
- acl_clear_perms(acl_permset);
+ if (r != 0) {
+#if HAVE_SUN_ACL
+ errno = EINVAL;
+#endif
+ archive_set_error(a, errno,
+ "Failed to set ACL entry type");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+#endif /* HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL */
+#if HAVE_SUN_ACL
+ if (acl->acl_type == ACLENT_T) {
+ if (ae_permset & ARCHIVE_ENTRY_ACL_EXECUTE)
+ aclent->a_perm |= 1;
+ if (ae_permset & ARCHIVE_ENTRY_ACL_WRITE)
+ aclent->a_perm |= 2;
+ if (ae_permset & ARCHIVE_ENTRY_ACL_READ)
+ aclent->a_perm |= 4;
+ } else
+#else
+ if (acl_get_permset(acl_entry, &acl_permset) != 0) {
+ archive_set_error(a, errno,
+ "Failed to get ACL permission set");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+ if (acl_clear_perms(acl_permset) != 0) {
+ archive_set_error(a, errno,
+ "Failed to clear ACL permissions");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+#endif /* !HAVE_SUN_ACL */
for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
- if (ae_permset & acl_perm_map[i].archive_perm)
- acl_add_perm(acl_permset,
- acl_perm_map[i].platform_perm);
+ if (ae_permset & acl_perm_map[i].archive_perm) {
+#if HAVE_SUN_ACL
+ ace->a_access_mask |=
+ acl_perm_map[i].platform_perm;
+#else
+ if (acl_add_perm(acl_permset,
+ acl_perm_map[i].platform_perm) != 0) {
+ archive_set_error(a, errno,
+ "Failed to add ACL permission");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+#endif
+ }
}
-#ifdef ACL_TYPE_NFS4
- acl_get_flagset_np(acl_entry, &acl_flagset);
- acl_clear_flags_np(acl_flagset);
- for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
- if (ae_permset & acl_inherit_map[i].archive_inherit)
- acl_add_flag_np(acl_flagset,
- acl_inherit_map[i].platform_inherit);
+#if HAVE_NFS4_ACL
+#if HAVE_SUN_ACL
+ if (acl_type == ACE_T)
+#elif HAVE_DARWIN_ACL
+ if (acl_type == ACL_TYPE_EXTENDED)
+#else /* FreeBSD */
+ if (acl_type == ACL_TYPE_NFS4)
+#endif
+ {
+#if HAVE_POSIX_ACL || HAVE_DARWIN_ACL
+ /*
+ * acl_get_flagset_np() fails with non-NFSv4 ACLs
+ */
+ if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
+ archive_set_error(a, errno,
+ "Failed to get flagset from an NFSv4 ACL entry");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+ if (acl_clear_flags_np(acl_flagset) != 0) {
+ archive_set_error(a, errno,
+ "Failed to clear flags from an NFSv4 ACL flagset");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+#endif /* HAVE_POSIX_ACL || HAVE_DARWIN_ACL */
+ for (i = 0; i < (int)(sizeof(acl_inherit_map) /sizeof(acl_inherit_map[0])); ++i) {
+ if (ae_permset & acl_inherit_map[i].archive_inherit) {
+#if HAVE_SUN_ACL
+ ace->a_flags |=
+ acl_inherit_map[i].platform_inherit;
+#else /* !HAVE_SUN_ACL */
+ if (acl_add_flag_np(acl_flagset,
+ acl_inherit_map[i].platform_inherit) != 0) {
+ archive_set_error(a, errno,
+ "Failed to add flag to NFSv4 ACL flagset");
+ ret = ARCHIVE_FAILED;
+ goto exit_free;
+ }
+#endif /* HAVE_SUN_ACL */
+ }
+ }
}
+#endif /* HAVE_NFS4_ACL */
+#if HAVE_SUN_ACL
+ e++;
#endif
}
+#if HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL
/* Try restoring the ACL through 'fd' if we can. */
-#if HAVE_ACL_SET_FD
- if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0)
- ret = ARCHIVE_OK;
- else
-#else
-#if HAVE_ACL_SET_FD_NP
- if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0)
- ret = ARCHIVE_OK;
- else
+#if HAVE_SUN_ACL || HAVE_ACL_SET_FD_NP
+ if (fd >= 0)
+#else /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
+ if (fd >= 0 && acl_type == ACL_TYPE_ACCESS)
#endif
+ {
+#if HAVE_SUN_ACL
+ if (facl_set(fd, acl) == 0)
+#elif HAVE_ACL_SET_FD_NP
+ if (acl_set_fd_np(fd, acl, acl_type) == 0)
+#else /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
+ if (acl_set_fd(fd, acl) == 0)
#endif
-#if HAVE_ACL_SET_LINK_NP
- if (acl_set_link_np(name, acl_type, acl) != 0) {
- archive_set_error(a, errno, "Failed to set %s acl", tname);
- ret = ARCHIVE_WARN;
- }
+ ret = ARCHIVE_OK;
+ else {
+ if (errno == EOPNOTSUPP) {
+ /* Filesystem doesn't support ACLs */
+ ret = ARCHIVE_OK;
+ } else {
+ archive_set_error(a, errno,
+ "Failed to set %s acl on fd", tname);
+ }
+ }
+ } else
+#endif /* HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL */
+#if HAVE_SUN_ACL
+ if (acl_set(name, acl) != 0)
+#elif HAVE_ACL_SET_LINK_NP
+ if (acl_set_link_np(name, acl_type, acl) != 0)
#else
/* TODO: Skip this if 'name' is a symlink. */
- if (acl_set_file(name, acl_type, acl) != 0) {
- archive_set_error(a, errno, "Failed to set %s acl", tname);
- ret = ARCHIVE_WARN;
- }
+ if (acl_set_file(name, acl_type, acl) != 0)
#endif
+ {
+ if (errno == EOPNOTSUPP) {
+ /* Filesystem doesn't support ACLs */
+ ret = ARCHIVE_OK;
+ } else {
+ archive_set_error(a, errno, "Failed to set %s acl",
+ tname);
+ ret = ARCHIVE_WARN;
+ }
+ }
+exit_free:
acl_free(acl);
return (ret);
}
-#endif
+#endif /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
index 5946683..a5f3067 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
@@ -110,6 +110,18 @@ __FBSDID("$FreeBSD$");
#include <sys/fcntl1.h>
#endif
+/*
+ * Macro to cast st_mtime and time_t to an int64 so that 2 numbers can reliably be compared.
+ *
+ * It assumes that the input is an integer type of no more than 64 bits.
+ * If the number is less than zero, t must be a signed type, so it fits in
+ * int64_t. Otherwise, it's a nonnegative value so we can cast it to uint64_t
+ * without loss. But it could be a large unsigned value, so we have to clip it
+ * to INT64_MAX.*
+ */
+#define to_int64_time(t) \
+ ((t) < 0 ? (int64_t)(t) : (uint64_t)(t) > (uint64_t)INT64_MAX ? INT64_MAX : (int64_t)(t))
+
#if __APPLE__
#include <TargetConditionals.h>
#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && HAVE_QUARANTINE_H
@@ -140,7 +152,17 @@ __FBSDID("$FreeBSD$");
#define O_BINARY 0
#endif
#ifndef O_CLOEXEC
-#define O_CLOEXEC 0
+#define O_CLOEXEC 0
+#endif
+
+/* Ignore non-int O_NOFOLLOW constant. */
+/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */
+#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX)
+#undef O_NOFOLLOW
+#endif
+
+#ifndef O_NOFOLLOW
+#define O_NOFOLLOW 0
#endif
struct fixup_entry {
@@ -298,7 +320,7 @@ struct archive_write_disk {
#define MAXIMUM_DIR_MODE 0775
/*
- * Maxinum uncompressed size of a decmpfs block.
+ * Maximum uncompressed size of a decmpfs block.
*/
#define MAX_DECMPFS_BLOCK_SIZE (64 * 1024)
/*
@@ -313,7 +335,7 @@ struct archive_write_disk {
#define RSRC_F_SIZE 50 /* Size of Resource fork footer. */
/* Size to write compressed data to resource fork. */
#define COMPRESSED_W_SIZE (64 * 1024)
-/* decmpfs difinitions. */
+/* decmpfs definitions. */
#define MAX_DECMPFS_XATTR_SIZE 3802
#ifndef DECMPFS_XATTR_NAME
#define DECMPFS_XATTR_NAME "com.apple.decmpfs"
@@ -326,12 +348,19 @@ struct archive_write_disk {
#define HFS_BLOCKS(s) ((s) >> 12)
+static void fsobj_error(int *, struct archive_string *, int, const char *,
+ const char *);
+static int check_symlinks_fsobj(char *, int *, struct archive_string *,
+ int);
static int check_symlinks(struct archive_write_disk *);
static int create_filesystem_object(struct archive_write_disk *);
-static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname);
+static struct fixup_entry *current_fixup(struct archive_write_disk *,
+ const char *pathname);
#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
static void edit_deep_directories(struct archive_write_disk *ad);
#endif
+static int cleanup_pathname_fsobj(char *, int *, struct archive_string *,
+ int);
static int cleanup_pathname(struct archive_write_disk *);
static int create_dir(struct archive_write_disk *, char *);
static int create_parent_dir(struct archive_write_disk *, char *);
@@ -362,11 +391,14 @@ static struct archive_vtable *archive_write_disk_vtable(void);
static int _archive_write_disk_close(struct archive *);
static int _archive_write_disk_free(struct archive *);
-static int _archive_write_disk_header(struct archive *, struct archive_entry *);
+static int _archive_write_disk_header(struct archive *,
+ struct archive_entry *);
static int64_t _archive_write_disk_filter_bytes(struct archive *, int);
static int _archive_write_disk_finish_entry(struct archive *);
-static ssize_t _archive_write_disk_data(struct archive *, const void *, size_t);
-static ssize_t _archive_write_disk_data_block(struct archive *, const void *, size_t, int64_t);
+static ssize_t _archive_write_disk_data(struct archive *, const void *,
+ size_t);
+static ssize_t _archive_write_disk_data_block(struct archive *, const void *,
+ size_t, int64_t);
static int
lazy_stat(struct archive_write_disk *a)
@@ -612,9 +644,9 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
/*
* NOTE: UF_COMPRESSED is ignored even if the filesystem
* supports HFS+ Compression because the file should
- * have at least an extended attriute "com.apple.decmpfs"
+ * have at least an extended attribute "com.apple.decmpfs"
* before the flag is set to indicate that the file have
- * been compressed. If hte filesystem does not support
+ * been compressed. If the filesystem does not support
* HFS+ Compression the system call will fail.
*/
if (a->fd < 0 || fchflags(a->fd, UF_COMPRESSED) != 0)
@@ -637,7 +669,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
if (a->restore_pwd >= 0) {
r = fchdir(a->restore_pwd);
if (r != 0) {
- archive_set_error(&a->archive, errno, "chdir() failure");
+ archive_set_error(&a->archive, errno,
+ "chdir() failure");
ret = ARCHIVE_FATAL;
}
close(a->restore_pwd);
@@ -685,7 +718,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
}
if (archive_entry_birthtime_is_set(entry)) {
fe->birthtime = archive_entry_birthtime(entry);
- fe->birthtime_nanos = archive_entry_birthtime_nsec(entry);
+ fe->birthtime_nanos = archive_entry_birthtime_nsec(
+ entry);
} else {
/* If birthtime is unset, use mtime. */
fe->birthtime = fe->mtime;
@@ -711,7 +745,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
return (ARCHIVE_FATAL);
fe->mac_metadata = malloc(metadata_size);
if (fe->mac_metadata != NULL) {
- memcpy(fe->mac_metadata, metadata, metadata_size);
+ memcpy(fe->mac_metadata, metadata,
+ metadata_size);
fe->mac_metadata_size = metadata_size;
fe->fixup |= TODO_MAC_METADATA;
}
@@ -1224,7 +1259,7 @@ hfs_drive_compressor(struct archive_write_disk *a, const char *buff,
ret = hfs_write_compressed_data(a, bytes_used + rsrc_size);
a->compressed_buffer_remaining = a->compressed_buffer_size;
- /* If the compressed size is not enouph smaller than
+ /* If the compressed size is not enough smaller than
* the uncompressed size. cancel HFS+ compression.
* TODO: study a behavior of ditto utility and improve
* the condition to fall back into no HFS+ compression. */
@@ -1329,7 +1364,7 @@ hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff,
(uint32_t *)(a->resource_fork + RSRC_H_SIZE);
/* Set the block count to the resource fork. */
archive_le32enc(a->decmpfs_block_info++, block_count);
- /* Get the position where we are goint to set compressed
+ /* Get the position where we are going to set compressed
* data. */
a->compressed_rsrc_position =
RSRC_H_SIZE + 4 + (block_count * 8);
@@ -1402,7 +1437,7 @@ hfs_write_data_block(struct archive_write_disk *a, const char *buff,
bytes_to_write = size;
/* Seek if necessary to the specified offset. */
if (a->offset < a->fd_offset) {
- /* Can't support backword move. */
+ /* Can't support backward move. */
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Seek failed");
return (ARCHIVE_FATAL);
@@ -1468,7 +1503,8 @@ _archive_write_disk_data_block(struct archive *_a,
return (r);
if ((size_t)r < size) {
archive_set_error(&a->archive, 0,
- "Too much data: Truncating file at %ju bytes", (uintmax_t)a->filesize);
+ "Too much data: Truncating file at %ju bytes",
+ (uintmax_t)a->filesize);
return (ARCHIVE_WARN);
}
#if ARCHIVE_VERSION_NUMBER < 3999000
@@ -1666,10 +1702,26 @@ _archive_write_disk_finish_entry(struct archive *_a)
* ACLs that prevent attribute changes (including time).
*/
if (a->todo & TODO_ACLS) {
- int r2 = archive_write_disk_set_acls(&a->archive, a->fd,
- archive_entry_pathname(a->entry),
- archive_entry_acl(a->entry));
+ int r2;
+#ifdef HAVE_DARWIN_ACL
+ /*
+ * On Mac OS, platform ACLs are stored also in mac_metadata by
+ * the operating system. If mac_metadata is present it takes
+ * precedence and we skip extracting libarchive NFSv4 ACLs
+ */
+ const void *metadata;
+ size_t metadata_size;
+ metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
+ if ((a->todo & TODO_MAC_METADATA) == 0 ||
+ metadata == NULL || metadata_size == 0) {
+#endif
+ r2 = archive_write_disk_set_acls(&a->archive, a->fd,
+ archive_entry_pathname(a->entry),
+ archive_entry_acl(a->entry));
if (r2 < ret) ret = r2;
+#ifdef HAVE_DARWIN_ACL
+ }
+#endif
}
finish_metadata:
@@ -1755,10 +1807,9 @@ archive_write_disk_new(void)
{
struct archive_write_disk *a;
- a = (struct archive_write_disk *)malloc(sizeof(*a));
+ a = (struct archive_write_disk *)calloc(1, sizeof(*a));
if (a == NULL)
return (NULL);
- memset(a, 0, sizeof(*a));
a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
/* We're ready to write a header immediately. */
a->archive.state = ARCHIVE_STATE_HEADER;
@@ -1796,7 +1847,7 @@ edit_deep_directories(struct archive_write_disk *a)
char *tail = a->name;
/* If path is short, avoid the open() below. */
- if (strlen(tail) <= PATH_MAX)
+ if (strlen(tail) < PATH_MAX)
return;
/* Try to record our starting dir. */
@@ -1806,7 +1857,7 @@ edit_deep_directories(struct archive_write_disk *a)
return;
/* As long as the path is too long... */
- while (strlen(tail) > PATH_MAX) {
+ while (strlen(tail) >= PATH_MAX) {
/* Locate a dir prefix shorter than PATH_MAX. */
tail += PATH_MAX - 8;
while (tail > a->name && *tail != '/')
@@ -1993,8 +2044,9 @@ restore_entry(struct archive_write_disk *a)
if (en) {
/* Everything failed; give up here. */
- archive_set_error(&a->archive, en, "Can't create '%s'",
- a->name);
+ if ((&a->archive)->error == NULL)
+ archive_set_error(&a->archive, en, "Can't create '%s'",
+ a->name);
return (ARCHIVE_FAILED);
}
@@ -2014,6 +2066,11 @@ create_filesystem_object(struct archive_write_disk *a)
const char *linkname;
mode_t final_mode, mode;
int r;
+ /* these for check_symlinks_fsobj */
+ char *linkname_copy; /* non-const copy of linkname */
+ struct stat st;
+ struct archive_string error_string;
+ int error_number;
/* We identify hard/symlinks according to the link names. */
/* Since link(2) and symlink(2) don't handle modes, we're done here. */
@@ -2022,6 +2079,43 @@ create_filesystem_object(struct archive_write_disk *a)
#if !HAVE_LINK
return (EPERM);
#else
+ archive_string_init(&error_string);
+ linkname_copy = strdup(linkname);
+ if (linkname_copy == NULL) {
+ return (EPERM);
+ }
+ /*
+ * TODO: consider using the cleaned-up path as the link
+ * target?
+ */
+ r = cleanup_pathname_fsobj(linkname_copy, &error_number,
+ &error_string, a->flags);
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, error_number, "%s",
+ error_string.s);
+ free(linkname_copy);
+ archive_string_free(&error_string);
+ /*
+ * EPERM is more appropriate than error_number for our
+ * callers
+ */
+ return (EPERM);
+ }
+ r = check_symlinks_fsobj(linkname_copy, &error_number,
+ &error_string, a->flags);
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, error_number, "%s",
+ error_string.s);
+ free(linkname_copy);
+ archive_string_free(&error_string);
+ /*
+ * EPERM is more appropriate than error_number for our
+ * callers
+ */
+ return (EPERM);
+ }
+ free(linkname_copy);
+ archive_string_free(&error_string);
r = link(linkname, a->name) ? errno : 0;
/*
* New cpio and pax formats allow hardlink entries
@@ -2039,11 +2133,20 @@ create_filesystem_object(struct archive_write_disk *a)
a->todo = 0;
a->deferred = 0;
} else if (r == 0 && a->filesize > 0) {
- a->fd = open(a->name,
- O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC);
- __archive_ensure_cloexec_flag(a->fd);
- if (a->fd < 0)
+#ifdef HAVE_LSTAT
+ r = lstat(a->name, &st);
+#else
+ r = stat(a->name, &st);
+#endif
+ if (r != 0)
r = errno;
+ else if ((st.st_mode & AE_IFMT) == AE_IFREG) {
+ a->fd = open(a->name, O_WRONLY | O_TRUNC |
+ O_BINARY | O_CLOEXEC | O_NOFOLLOW);
+ __archive_ensure_cloexec_flag(a->fd);
+ if (a->fd < 0)
+ r = errno;
+ }
}
return (r);
#endif
@@ -2190,8 +2293,13 @@ _archive_write_disk_close(struct archive *_a)
if (p->fixup & TODO_MODE_BASE)
chmod(p->name, p->mode);
if (p->fixup & TODO_ACLS)
- archive_write_disk_set_acls(&a->archive,
- -1, p->name, &p->acl);
+#ifdef HAVE_DARWIN_ACL
+ if ((p->fixup & TODO_MAC_METADATA) == 0 ||
+ p->mac_metadata == NULL ||
+ p->mac_metadata_size == 0)
+#endif
+ archive_write_disk_set_acls(&a->archive,
+ -1, p->name, &p->acl);
if (p->fixup & TODO_FFLAGS)
set_fflags_platform(a, -1, p->name,
p->mode, p->fflags_set, 0);
@@ -2351,116 +2459,283 @@ current_fixup(struct archive_write_disk *a, const char *pathname)
return (a->current_fixup);
}
-/* TODO: Make this work. */
-/*
- * TODO: The deep-directory support bypasses this; disable deep directory
- * support if we're doing symlink checks.
- */
+/* Error helper for new *_fsobj functions */
+static void
+fsobj_error(int *a_eno, struct archive_string *a_estr,
+ int err, const char *errstr, const char *path)
+{
+ if (a_eno)
+ *a_eno = err;
+ if (a_estr)
+ archive_string_sprintf(a_estr, errstr, path);
+}
+
/*
* TODO: Someday, integrate this with the deep dir support; they both
* scan the path and both can be optimized by comparing against other
* recent paths.
*/
/* TODO: Extend this to support symlinks on Windows Vista and later. */
+
+/*
+ * Checks the given path to see if any elements along it are symlinks. Returns
+ * ARCHIVE_OK if there are none, otherwise puts an error in errmsg.
+ */
static int
-check_symlinks(struct archive_write_disk *a)
+check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
+ int flags)
{
#if !defined(HAVE_LSTAT)
/* Platform doesn't have lstat, so we can't look for symlinks. */
- (void)a; /* UNUSED */
+ (void)path; /* UNUSED */
+ (void)error_number; /* UNUSED */
+ (void)error_string; /* UNUSED */
+ (void)flags; /* UNUSED */
return (ARCHIVE_OK);
#else
- char *pn;
+ int res = ARCHIVE_OK;
+ char *tail;
+ char *head;
+ int last;
char c;
int r;
struct stat st;
+ int restore_pwd;
+
+ /* Nothing to do here if name is empty */
+ if(path[0] == '\0')
+ return (ARCHIVE_OK);
/*
* Guard against symlink tricks. Reject any archive entry whose
* destination would be altered by a symlink.
+ *
+ * Walk the filename in chunks separated by '/'. For each segment:
+ * - if it doesn't exist, continue
+ * - if it's symlink, abort or remove it
+ * - if it's a directory and it's not the last chunk, cd into it
+ * As we go:
+ * head points to the current (relative) path
+ * tail points to the temporary \0 terminating the segment we're
+ * currently examining
+ * c holds what used to be in *tail
+ * last is 1 if this is the last tail
*/
- /* Whatever we checked last time doesn't need to be re-checked. */
- pn = a->name;
- if (archive_strlen(&(a->path_safe)) > 0) {
- char *p = a->path_safe.s;
- while ((*pn != '\0') && (*p == *pn))
- ++p, ++pn;
- }
+ restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(restore_pwd);
+ if (restore_pwd < 0)
+ return (ARCHIVE_FATAL);
+ head = path;
+ tail = path;
+ last = 0;
+ /* TODO: reintroduce a safe cache here? */
/* Skip the root directory if the path is absolute. */
- if(pn == a->name && pn[0] == '/')
- ++pn;
- c = pn[0];
- /* Keep going until we've checked the entire name. */
- while (pn[0] != '\0' && (pn[0] != '/' || pn[1] != '\0')) {
+ if(tail == path && tail[0] == '/')
+ ++tail;
+ /* Keep going until we've checked the entire name.
+ * head, tail, path all alias the same string, which is
+ * temporarily zeroed at tail, so be careful restoring the
+ * stashed (c=tail[0]) for error messages.
+ * Exiting the loop with break is okay; continue is not.
+ */
+ while (!last) {
+ /*
+ * Skip the separator we just consumed, plus any adjacent ones
+ */
+ while (*tail == '/')
+ ++tail;
/* Skip the next path element. */
- while (*pn != '\0' && *pn != '/')
- ++pn;
- c = pn[0];
- pn[0] = '\0';
+ while (*tail != '\0' && *tail != '/')
+ ++tail;
+ /* is this the last path component? */
+ last = (tail[0] == '\0') || (tail[0] == '/' && tail[1] == '\0');
+ /* temporarily truncate the string here */
+ c = tail[0];
+ tail[0] = '\0';
/* Check that we haven't hit a symlink. */
- r = lstat(a->name, &st);
+ r = lstat(head, &st);
if (r != 0) {
+ tail[0] = c;
/* We've hit a dir that doesn't exist; stop now. */
- if (errno == ENOENT)
+ if (errno == ENOENT) {
+ break;
+ } else {
+ /*
+ * Treat any other error as fatal - best to be
+ * paranoid here.
+ * Note: This effectively disables deep
+ * directory support when security checks are
+ * enabled. Otherwise, very long pathnames that
+ * trigger an error here could evade the
+ * sandbox.
+ * TODO: We could do better, but it would
+ * probably require merging the symlink checks
+ * with the deep-directory editing.
+ */
+ fsobj_error(a_eno, a_estr, errno,
+ "Could not stat %s", path);
+ res = ARCHIVE_FAILED;
break;
+ }
+ } else if (S_ISDIR(st.st_mode)) {
+ if (!last) {
+ if (chdir(head) != 0) {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, errno,
+ "Could not chdir %s", path);
+ res = (ARCHIVE_FATAL);
+ break;
+ }
+ /* Our view is now from inside this dir: */
+ head = tail + 1;
+ }
} else if (S_ISLNK(st.st_mode)) {
- if (c == '\0') {
+ if (last) {
/*
* Last element is symlink; remove it
* so we can overwrite it with the
* item being extracted.
*/
- if (unlink(a->name)) {
- archive_set_error(&a->archive, errno,
+ if (unlink(head)) {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, errno,
"Could not remove symlink %s",
- a->name);
- pn[0] = c;
- return (ARCHIVE_FAILED);
+ path);
+ res = ARCHIVE_FAILED;
+ break;
}
- a->pst = NULL;
/*
* Even if we did remove it, a warning
* is in order. The warning is silly,
* though, if we're just replacing one
* symlink with another symlink.
*/
- if (!S_ISLNK(a->mode)) {
- archive_set_error(&a->archive, 0,
- "Removing symlink %s",
- a->name);
+ tail[0] = c;
+ /*
+ * FIXME: not sure how important this is to
+ * restore
+ */
+ /*
+ if (!S_ISLNK(path)) {
+ fsobj_error(a_eno, a_estr, 0,
+ "Removing symlink %s", path);
}
+ */
/* Symlink gone. No more problem! */
- pn[0] = c;
- return (0);
- } else if (a->flags & ARCHIVE_EXTRACT_UNLINK) {
+ res = ARCHIVE_OK;
+ break;
+ } else if (flags & ARCHIVE_EXTRACT_UNLINK) {
/* User asked us to remove problems. */
- if (unlink(a->name) != 0) {
- archive_set_error(&a->archive, 0,
- "Cannot remove intervening symlink %s",
- a->name);
- pn[0] = c;
- return (ARCHIVE_FAILED);
+ if (unlink(head) != 0) {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, 0,
+ "Cannot remove intervening "
+ "symlink %s", path);
+ res = ARCHIVE_FAILED;
+ break;
+ }
+ tail[0] = c;
+ } else if ((flags &
+ ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) {
+ /*
+ * We are not the last element and we want to
+ * follow symlinks if they are a directory.
+ *
+ * This is needed to extract hardlinks over
+ * symlinks.
+ */
+ r = stat(head, &st);
+ if (r != 0) {
+ tail[0] = c;
+ if (errno == ENOENT) {
+ break;
+ } else {
+ fsobj_error(a_eno, a_estr,
+ errno,
+ "Could not stat %s", path);
+ res = (ARCHIVE_FAILED);
+ break;
+ }
+ } else if (S_ISDIR(st.st_mode)) {
+ if (chdir(head) != 0) {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr,
+ errno,
+ "Could not chdir %s", path);
+ res = (ARCHIVE_FATAL);
+ break;
+ }
+ /*
+ * Our view is now from inside
+ * this dir:
+ */
+ head = tail + 1;
+ } else {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, 0,
+ "Cannot extract through "
+ "symlink %s", path);
+ res = ARCHIVE_FAILED;
+ break;
}
- a->pst = NULL;
} else {
- archive_set_error(&a->archive, 0,
- "Cannot extract through symlink %s",
- a->name);
- pn[0] = c;
- return (ARCHIVE_FAILED);
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, 0,
+ "Cannot extract through symlink %s", path);
+ res = ARCHIVE_FAILED;
+ break;
}
}
- pn[0] = c;
- if (pn[0] != '\0')
- pn++; /* Advance to the next segment. */
+ /* be sure to always maintain this */
+ tail[0] = c;
+ if (tail[0] != '\0')
+ tail++; /* Advance to the next segment. */
+ }
+ /* Catches loop exits via break */
+ tail[0] = c;
+#ifdef HAVE_FCHDIR
+ /* If we changed directory above, restore it here. */
+ if (restore_pwd >= 0) {
+ r = fchdir(restore_pwd);
+ if (r != 0) {
+ fsobj_error(a_eno, a_estr, errno,
+ "chdir() failure", "");
+ }
+ close(restore_pwd);
+ restore_pwd = -1;
+ if (r != 0) {
+ res = (ARCHIVE_FATAL);
+ }
}
- pn[0] = c;
- /* We've checked and/or cleaned the whole path, so remember it. */
- archive_strcpy(&a->path_safe, a->name);
- return (ARCHIVE_OK);
#endif
+ /* TODO: reintroduce a safe cache here? */
+ return res;
+#endif
+}
+
+/*
+ * Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise
+ * calls archive_set_error and returns ARCHIVE_{FATAL,FAILED}
+ */
+static int
+check_symlinks(struct archive_write_disk *a)
+{
+ struct archive_string error_string;
+ int error_number;
+ int rc;
+ archive_string_init(&error_string);
+ rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
+ a->flags);
+ if (rc != ARCHIVE_OK) {
+ archive_set_error(&a->archive, error_number, "%s",
+ error_string.s);
+ }
+ archive_string_free(&error_string);
+ a->pst = NULL; /* to be safe */
+ return rc;
}
+
#if defined(__CYGWIN__)
/*
* 1. Convert a path separator from '\' to '/' .
@@ -2471,7 +2746,7 @@ check_symlinks(struct archive_write_disk *a)
* See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx
*/
static void
-cleanup_pathname_win(struct archive_write_disk *a)
+cleanup_pathname_win(char *path)
{
wchar_t wc;
char *p;
@@ -2482,7 +2757,7 @@ cleanup_pathname_win(struct archive_write_disk *a)
mb = 0;
complete = 1;
utf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)? 1: 0;
- for (p = a->name; *p != '\0'; p++) {
+ for (p = path; *p != '\0'; p++) {
++alen;
if (*p == '\\') {
/* If previous byte is smaller than 128,
@@ -2507,7 +2782,7 @@ cleanup_pathname_win(struct archive_write_disk *a)
/*
* Convert path separator in wide-character.
*/
- p = a->name;
+ p = path;
while (*p != '\0' && alen) {
l = mbtowc(&wc, p, alen);
if (l == (size_t)-1) {
@@ -2534,26 +2809,27 @@ cleanup_pathname_win(struct archive_write_disk *a)
* is set) if the path is absolute.
*/
static int
-cleanup_pathname(struct archive_write_disk *a)
+cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
+ int flags)
{
char *dest, *src;
char separator = '\0';
- dest = src = a->name;
+ dest = src = path;
if (*src == '\0') {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Invalid empty pathname");
+ fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
+ "Invalid empty ", "pathname");
return (ARCHIVE_FAILED);
}
#if defined(__CYGWIN__)
- cleanup_pathname_win(a);
+ cleanup_pathname_win(path);
#endif
/* Skip leading '/'. */
if (*src == '/') {
- if (a->flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Path is absolute");
+ if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
+ fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
+ "Path is ", "absolute");
return (ARCHIVE_FAILED);
}
@@ -2580,10 +2856,11 @@ cleanup_pathname(struct archive_write_disk *a)
} else if (src[1] == '.') {
if (src[2] == '/' || src[2] == '\0') {
/* Conditionally warn about '..' */
- if (a->flags & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
- archive_set_error(&a->archive,
+ if (flags
+ & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
+ fsobj_error(a_eno, a_estr,
ARCHIVE_ERRNO_MISC,
- "Path contains '..'");
+ "Path contains ", "'..'");
return (ARCHIVE_FAILED);
}
}
@@ -2614,7 +2891,7 @@ cleanup_pathname(struct archive_write_disk *a)
* We've just copied zero or more path elements, not including the
* final '/'.
*/
- if (dest == a->name) {
+ if (dest == path) {
/*
* Nothing got copied. The path must have been something
* like '.' or '/' or './' or '/././././/./'.
@@ -2629,6 +2906,23 @@ cleanup_pathname(struct archive_write_disk *a)
return (ARCHIVE_OK);
}
+static int
+cleanup_pathname(struct archive_write_disk *a)
+{
+ struct archive_string error_string;
+ int error_number;
+ int rc;
+ archive_string_init(&error_string);
+ rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string,
+ a->flags);
+ if (rc != ARCHIVE_OK) {
+ archive_set_error(&a->archive, error_number, "%s",
+ error_string.s);
+ }
+ archive_string_free(&error_string);
+ return rc;
+}
+
/*
* Create the parent directory of the specified path, assuming path
* is already in mutable storage.
@@ -2707,7 +3001,8 @@ create_dir(struct archive_write_disk *a, char *path)
}
} else if (errno != ENOENT && errno != ENOTDIR) {
/* Stat failed? */
- archive_set_error(&a->archive, errno, "Can't test directory '%s'", path);
+ archive_set_error(&a->archive, errno,
+ "Can't test directory '%s'", path);
return (ARCHIVE_FAILED);
} else if (slash != NULL) {
*slash = '\0';
@@ -3172,12 +3467,19 @@ set_fflags(struct archive_write_disk *a)
#ifdef UF_APPEND
critical_flags |= UF_APPEND;
#endif
-#ifdef EXT2_APPEND_FL
+#if defined(FS_APPEND_FL)
+ critical_flags |= FS_APPEND_FL;
+#elif defined(EXT2_APPEND_FL)
critical_flags |= EXT2_APPEND_FL;
#endif
-#ifdef EXT2_IMMUTABLE_FL
+#if defined(FS_IMMUTABLE_FL)
+ critical_flags |= FS_IMMUTABLE_FL;
+#elif defined(EXT2_IMMUTABLE_FL)
critical_flags |= EXT2_IMMUTABLE_FL;
#endif
+#ifdef FS_JOURNAL_DATA_FL
+ critical_flags |= FS_JOURNAL_DATA_FL;
+#endif
if (a->todo & TODO_FFLAGS) {
archive_entry_fflags(a->entry, &set, &clear);
@@ -3232,7 +3534,8 @@ clear_nochange_fflags(struct archive_write_disk *a)
nochange_flags |= EXT2_IMMUTABLE_FL;
#endif
- return (set_fflags_platform(a, a->fd, a->name, mode, 0, nochange_flags));
+ return (set_fflags_platform(a, a->fd, a->name, mode, 0,
+ nochange_flags));
}
@@ -3288,7 +3591,10 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
return (ARCHIVE_WARN);
}
-#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+#elif (defined(FS_IOC_GETFLAGS) && defined(FS_IOC_SETFLAGS) && \
+ defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+ (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && \
+ defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
/*
* Linux uses ioctl() to read and write file flags.
*/
@@ -3301,7 +3607,7 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
int newflags, oldflags;
int sf_mask = 0;
- if (set == 0 && clear == 0)
+ if (set == 0 && clear == 0)
return (ARCHIVE_OK);
/* Only regular files and dirs can have flags. */
if (!S_ISREG(mode) && !S_ISDIR(mode))
@@ -3322,12 +3628,19 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
* defines. (?) The code below degrades reasonably gracefully
* if sf_mask is incomplete.
*/
-#ifdef EXT2_IMMUTABLE_FL
+#if defined(FS_IMMUTABLE_FL)
+ sf_mask |= FS_IMMUTABLE_FL;
+#elif defined(EXT2_IMMUTABLE_FL)
sf_mask |= EXT2_IMMUTABLE_FL;
#endif
-#ifdef EXT2_APPEND_FL
+#if defined(FS_APPEND_FL)
+ sf_mask |= FS_APPEND_FL;
+#elif defined(EXT2_APPEND_FL)
sf_mask |= EXT2_APPEND_FL;
#endif
+#if defined(FS_JOURNAL_DATA_FL)
+ sf_mask |= FS_JOURNAL_DATA_FL;
+#endif
/*
* XXX As above, this would be way simpler if we didn't have
* to read the current flags from disk. XXX
@@ -3335,12 +3648,24 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
ret = ARCHIVE_OK;
/* Read the current file flags. */
- if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) < 0)
+ if (ioctl(myfd,
+#ifdef FS_IOC_GETFLAGS
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
+ &oldflags) < 0)
goto fail;
/* Try setting the flags as given. */
newflags = (oldflags & ~clear) | set;
- if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
+ if (ioctl(myfd,
+#ifdef FS_IOC_SETFLAGS
+ FS_IOC_SETFLAGS,
+#else
+ EXT2_IOC_SETFLAGS,
+#endif
+ &newflags) >= 0)
goto cleanup;
if (errno != EPERM)
goto fail;
@@ -3349,7 +3674,13 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
newflags &= ~sf_mask;
oldflags &= sf_mask;
newflags |= oldflags;
- if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
+ if (ioctl(myfd,
+#ifdef FS_IOC_SETFLAGS
+ FS_IOC_SETFLAGS,
+#else
+ EXT2_IOC_SETFLAGS,
+#endif
+ &newflags) >= 0)
goto cleanup;
/* We couldn't set the flags, so report the failure. */
@@ -3487,6 +3818,9 @@ exit_xattr:
static int
copy_acls(struct archive_write_disk *a, int tmpfd, int dffd)
{
+#ifndef HAVE_SYS_ACL_H
+ return 0;
+#else
acl_t acl, dfacl = NULL;
int acl_r, ret = ARCHIVE_OK;
@@ -3514,6 +3848,7 @@ exit_acl:
if (dfacl)
acl_free(dfacl);
return (ret);
+#endif
}
static int
@@ -3753,7 +4088,8 @@ set_xattrs(struct archive_write_disk *a)
if (errno == ENOTSUP || errno == ENOSYS) {
if (!warning_done) {
warning_done = 1;
- archive_set_error(&a->archive, errno,
+ archive_set_error(&a->archive,
+ errno,
"Cannot restore extended "
"attributes on this file "
"system");
@@ -3764,7 +4100,8 @@ set_xattrs(struct archive_write_disk *a)
ret = ARCHIVE_WARN;
}
} else {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid extended attribute encountered");
ret = ARCHIVE_WARN;
}
@@ -3808,19 +4145,22 @@ set_xattrs(struct archive_write_disk *a)
errno = 0;
#if HAVE_EXTATTR_SET_FD
if (a->fd >= 0)
- e = extattr_set_fd(a->fd, namespace, name, value, size);
+ e = extattr_set_fd(a->fd, namespace, name,
+ value, size);
else
#endif
/* TODO: should we use extattr_set_link() instead? */
{
- e = extattr_set_file(archive_entry_pathname(entry),
- namespace, name, value, size);
+ e = extattr_set_file(
+ archive_entry_pathname(entry), namespace,
+ name, value, size);
}
if (e != (int)size) {
if (errno == ENOTSUP || errno == ENOSYS) {
if (!warning_done) {
warning_done = 1;
- archive_set_error(&a->archive, errno,
+ archive_set_error(&a->archive,
+ errno,
"Cannot restore extended "
"attributes on this file "
"system");
@@ -3866,10 +4206,10 @@ older(struct stat *st, struct archive_entry *entry)
{
/* First, test the seconds and return if we have a definite answer. */
/* Definitely older. */
- if (st->st_mtime < archive_entry_mtime(entry))
+ if (to_int64_time(st->st_mtime) < to_int64_time(archive_entry_mtime(entry)))
return (1);
/* Definitely younger. */
- if (st->st_mtime > archive_entry_mtime(entry))
+ if (to_int64_time(st->st_mtime) > to_int64_time(archive_entry_mtime(entry)))
return (0);
/* If this platform supports fractional seconds, try those. */
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c
index 3b868fb..5c766d7 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c
@@ -84,15 +84,13 @@ static void cleanup(void *);
int
archive_write_disk_set_standard_lookup(struct archive *a)
{
- struct bucket *ucache = malloc(cache_size * sizeof(struct bucket));
- struct bucket *gcache = malloc(cache_size * sizeof(struct bucket));
+ struct bucket *ucache = calloc(cache_size, sizeof(struct bucket));
+ struct bucket *gcache = calloc(cache_size, sizeof(struct bucket));
if (ucache == NULL || gcache == NULL) {
free(ucache);
free(gcache);
return (ARCHIVE_FATAL);
}
- memset(ucache, 0, cache_size * sizeof(struct bucket));
- memset(gcache, 0, cache_size * sizeof(struct bucket));
archive_write_disk_set_group_lookup(a, gcache, lookup_gid, cleanup);
archive_write_disk_set_user_lookup(a, ucache, lookup_uid, cleanup);
return (ARCHIVE_OK);
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
index da76c54..94b016e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
@@ -192,7 +192,7 @@ struct archive_write_disk {
/*
* Default mode for dirs created automatically (will be modified by umask).
- * Note that POSIX specifies 0777 for implicity-created dirs, "modified
+ * Note that POSIX specifies 0777 for implicitly-created dirs, "modified
* by the process' file creation mask."
*/
#define DEFAULT_DIR_MODE 0777
@@ -396,7 +396,7 @@ permissive_name_w(struct archive_write_disk *a)
}
/*
- * A full-pathname pointig a network drive
+ * A full-pathname pointing to a network drive
* like "\\<server-name>\<share-name>\file".
*/
if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') {
@@ -1221,10 +1221,9 @@ archive_write_disk_new(void)
{
struct archive_write_disk *a;
- a = (struct archive_write_disk *)malloc(sizeof(*a));
+ a = (struct archive_write_disk *)calloc(1, sizeof(*a));
if (a == NULL)
return (NULL);
- memset(a, 0, sizeof(*a));
a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
/* We're ready to write a header immediately. */
a->archive.state = ARCHIVE_STATE_HEADER;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open.3 b/Utilities/cmlibarchive/libarchive/archive_write_open.3
index a52959b..457873e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_open.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_open.3
@@ -66,6 +66,7 @@ Freeze the settings, open the archive, and prepare for writing entries.
This is the most generic form of this function, which accepts
pointers to three callback functions which will be invoked by
the compression layer to write the constructed archive.
+This does not alter the default archive padding.
.It Fn archive_write_open_fd
A convenience form of
.Fn archive_write_open
@@ -123,12 +124,21 @@ is currently in use.
You should be careful to ensure that this variable
remains allocated until after the archive is
closed.
+This function will disable padding unless you
+have specifically set the block size.
.El
More information about the
.Va struct archive
object and the overall design of the library can be found in the
.Xr libarchive 3
overview.
+.Pp
+Note that the convenience forms above vary in how
+they block the output.
+See
+.Xr archive_write_blocksize 3
+if you need to control the block size used for writes
+or the end-of-file padding behavior.
.\"
.Sh CLIENT CALLBACKS
To use this library, you will need to define and register
@@ -226,6 +236,7 @@ functions.
.Xr tar 1 ,
.Xr libarchive 3 ,
.Xr archive_write 3 ,
+.Xr archive_write_blocksize 3 ,
.Xr archive_write_filter 3 ,
.Xr archive_write_format 3 ,
.Xr archive_write_new 3 ,
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c b/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c
index 4f8d679..ea6ae0a 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c
@@ -53,12 +53,11 @@ archive_write_open_memory(struct archive *a, void *buff, size_t buffSize, size_t
{
struct write_memory_data *mine;
- mine = (struct write_memory_data *)malloc(sizeof(*mine));
+ mine = (struct write_memory_data *)calloc(1, sizeof(*mine));
if (mine == NULL) {
archive_set_error(a, ENOMEM, "No memory");
return (ARCHIVE_FATAL);
}
- memset(mine, 0, sizeof(*mine));
mine->buff = buff;
mine->size = buffSize;
mine->client_size = used;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
index 8718d25..3fc5a07 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
@@ -205,7 +205,7 @@ struct _7zip {
/*
* The list of the file entries which has its contents is used to
* manage struct file objects.
- * We use 'next' a menber of struct file to chain.
+ * We use 'next' (a member of struct file) to chain.
*/
struct {
struct file *first;
@@ -1358,7 +1358,7 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size,
if (r < 0)
return (r);
- /* Write Nume size. */
+ /* Write Name size. */
r = enc_uint64(a, zip->total_bytes_entry_name+1);
if (r < 0)
return (r);
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c
index 9f17564..c9771d8 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c
@@ -126,12 +126,11 @@ archive_write_set_format_ar(struct archive_write *a)
if (a->format_free != NULL)
(a->format_free)(a);
- ar = (struct ar_w *)malloc(sizeof(*ar));
+ ar = (struct ar_w *)calloc(1, sizeof(*ar));
if (ar == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't allocate ar data");
return (ARCHIVE_FATAL);
}
- memset(ar, 0, sizeof(*ar));
a->format_data = ar;
a->format_name = "ar";
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c
index 3526493..a4c9d1e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c
@@ -289,7 +289,7 @@ write_header(struct archive_write *a, struct archive_entry *entry)
sconv = get_sconv(a);
#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure the path separators in pahtname, hardlink and symlink
+ /* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry);
if (entry_main == NULL) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c
index a9bfa80..957f1a3 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c
@@ -116,12 +116,11 @@ archive_write_set_format_cpio_newc(struct archive *_a)
if (a->format_free != NULL)
(a->format_free)(a);
- cpio = (struct cpio *)malloc(sizeof(*cpio));
+ cpio = (struct cpio *)calloc(1, sizeof(*cpio));
if (cpio == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
return (ARCHIVE_FATAL);
}
- memset(cpio, 0, sizeof(*cpio));
a->format_data = cpio;
a->format_name = "cpio";
a->format_options = archive_write_newc_options;
@@ -232,7 +231,7 @@ write_header(struct archive_write *a, struct archive_entry *entry)
sconv = get_sconv(a);
#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure the path separators in pahtname, hardlink and symlink
+ /* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry);
if (entry_main == NULL) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c
index 1d635d2..2d858c9 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c
@@ -119,9 +119,9 @@ static const char template_header[] = {
'0','0','0','0','0','0', '0','\0',
/* gid, null termination: 8 bytes */
'0','0','0','0','0','0', '0','\0',
- /* size, space termation: 12 bytes */
+ /* size, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', '\0',
- /* mtime, space termation: 12 bytes */
+ /* mtime, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', '\0',
/* Initial checksum value: 8 spaces */
' ',' ',' ',' ',' ',' ',' ',' ',
@@ -368,7 +368,7 @@ archive_write_gnutar_header(struct archive_write *a,
}
#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure the path separators in pahtname, hardlink and symlink
+ /* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry);
if (entry_main == NULL) {
@@ -478,15 +478,15 @@ archive_write_gnutar_header(struct archive_write *a,
archive_entry_set_pathname(temp, "././@LongLink");
archive_entry_set_size(temp, length);
ret = archive_format_gnutar_header(a, buff, temp, 'K');
+ archive_entry_free(temp);
if (ret < ARCHIVE_WARN)
goto exit_write_header;
ret = __archive_write_output(a, buff, 512);
- if(ret < ARCHIVE_WARN)
+ if (ret < ARCHIVE_WARN)
goto exit_write_header;
- archive_entry_free(temp);
/* Write name and trailing null byte. */
ret = __archive_write_output(a, gnutar->linkname, length);
- if(ret < ARCHIVE_WARN)
+ if (ret < ARCHIVE_WARN)
goto exit_write_header;
/* Pad to 512 bytes */
ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)length));
@@ -508,12 +508,12 @@ archive_write_gnutar_header(struct archive_write *a,
archive_entry_set_pathname(temp, "././@LongLink");
archive_entry_set_size(temp, length);
ret = archive_format_gnutar_header(a, buff, temp, 'L');
+ archive_entry_free(temp);
if (ret < ARCHIVE_WARN)
goto exit_write_header;
ret = __archive_write_output(a, buff, 512);
if(ret < ARCHIVE_WARN)
goto exit_write_header;
- archive_entry_free(temp);
/* Write pathname + trailing null byte. */
ret = __archive_write_output(a, pathname, length);
if(ret < ARCHIVE_WARN)
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
index 879a776..4adf68e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
@@ -161,7 +161,7 @@ struct isofile {
/* Used for managing struct isofile list. */
struct isofile *allnext;
struct isofile *datanext;
- /* Used for managing a hardlined struct isofile list. */
+ /* Used for managing a hardlinked struct isofile list. */
struct isofile *hlnext;
struct isofile *hardlink_target;
@@ -436,7 +436,7 @@ struct iso_option {
* Type : string
* Default: Auto detect
* : We check a size of boot image;
- * : If ths size is just 1.22M/1.44M/2.88M,
+ * : If the size is just 1.22M/1.44M/2.88M,
* : we assume boot_type is 'fd';
* : otherwise boot_type is 'no-emulation'.
* COMPAT :
@@ -528,7 +528,7 @@ struct iso_option {
* - allow more then 8 depths of directory trees;
* - disable a version number to a File Name;
* - disable a forced period to the tail of a File Name;
- * - the maxinum length of files and directories is raised to 193.
+ * - the maximum length of files and directories is raised to 193.
* if rockridge option is disabled, raised to 207.
*/
unsigned int iso_level:3;
@@ -626,7 +626,7 @@ struct iso_option {
* : NOTE Our rockridge=useful option does not set a zero
* : to uid and gid, you should use application
* : option such as --gid,--gname,--uid and --uname
- * : badtar options instead.
+ * : bsdtar options instead.
* Type : boolean/string
* Default: Enabled as rockridge=useful
* COMPAT : mkisofs -r / -R
@@ -660,7 +660,7 @@ struct iso_option {
* : for making zisofs.
* : When the file size is less than one Logical Block
* : size, that file will not zisofs'ed since it does
- * : reduece an ISO-image size.
+ * : reduce an ISO-image size.
* :
* : When you specify option 'boot=<boot-image>', that
* : 'boot-image' file won't be converted to zisofs file.
@@ -680,7 +680,7 @@ struct iso9660 {
/* The creation time of ISO image. */
time_t birth_time;
/* A file stream of a temporary file, which file contents
- * save to until ISO iamge can be created. */
+ * save to until ISO image can be created. */
int temp_fd;
struct isofile *cur_file;
@@ -703,7 +703,7 @@ struct iso9660 {
} all_file_list;
/* A list of struct isofile entries which have its
- * contents and are not a directory, a hardlined file
+ * contents and are not a directory, a hardlinked file
* and a symlink file. */
struct {
struct isofile *first;
@@ -1907,9 +1907,9 @@ iso9660_close(struct archive_write *a)
iso9660->primary.rootent);
if (ret < 0)
return (ret);
- /* Make sure we have UTF-16BE convertors.
- * if there is no file entry, convertors are still
- * uninitilized. */
+ /* Make sure we have UTF-16BE converters.
+ * if there is no file entry, converters are still
+ * uninitialized. */
if (iso9660->sconv_to_utf16be == NULL) {
iso9660->sconv_to_utf16be =
archive_string_conversion_to_charset(
@@ -1995,7 +1995,7 @@ iso9660_close(struct archive_write *a)
* Write an ISO 9660 image.
*/
- /* Switc to start using wbuff as file buffer. */
+ /* Switch to start using wbuff as file buffer. */
iso9660->wbuff_remaining = wb_buffmax();
iso9660->wbuff_type = WB_TO_STREAM;
iso9660->wbuff_offset = 0;
@@ -2524,7 +2524,8 @@ get_tmfromtime(struct tm *tm, time_t *t)
tzset();
localtime_r(t, tm);
#elif HAVE__LOCALTIME64_S
- _localtime64_s(tm, t);
+ __time64_t tmp_t = (__time64_t) *t; //time_t may be shorter than 64 bits
+ _localtime64_s(tm, &tmp_t);
#else
memcpy(tm, localtime(t), sizeof(*tm));
#endif
@@ -2553,7 +2554,7 @@ set_date_time(unsigned char *p, time_t t)
static void
set_date_time_null(unsigned char *p)
{
- memset(p, '0', 16);
+ memset(p, (int)'0', 16);
p[16] = 0;
}
@@ -2959,7 +2960,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
gid = archive_entry_gid(file->entry);
if (iso9660->opt.rr == OPT_RR_USEFUL) {
/*
- * This action is simular mkisofs -r option
+ * This action is similar to mkisofs -r option
* but our rockridge=useful option does not
* set a zero to uid and gid.
*/
@@ -3024,8 +3025,8 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
* +----+----+----+----+----+
* 10 11 12 13 14 15
*
- * - cflg : flag of componet
- * - clen : length of componet
+ * - cflg : flag of component
+ * - clen : length of component
*/
const char *sl;
char sl_last;
@@ -3108,7 +3109,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
/*
* flg len
* +----+----+
- * | 02 | 00 | CURREENT component.
+ * | 02 | 00 | CURRENT component.
* +----+----+ (".")
*/
if (nc != NULL) {
@@ -3947,7 +3948,7 @@ write_VD(struct archive_write *a, struct vdd *vdd)
"Abstract File", 0, D_CHAR);
if (r != ARCHIVE_OK)
return (r);
- /* Bibliongraphic File Identifier */
+ /* Bibliographic File Identifier */
r = set_file_identifier(bp, 777, 813, vdc, a, vdd,
&(iso9660->bibliographic_file_identifier),
"Bibliongraphic File", 0, D_CHAR);
@@ -4073,7 +4074,10 @@ write_information_block(struct archive_write *a)
memset(info.s, 0, info_size);
opt = 0;
#if defined(HAVE__CTIME64_S)
- _ctime64_s(buf, sizeof(buf), &(iso9660->birth_time));
+ {
+ __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits
+ _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp));
+ }
#elif defined(HAVE_CTIME_R)
ctime_r(&(iso9660->birth_time), buf);
#else
@@ -4558,7 +4562,7 @@ write_file_descriptors(struct archive_write *a)
file->cur_content = &(file->content);
do {
blocks += file->cur_content->blocks;
- /* Next fragument */
+ /* Next fragment */
file->cur_content = file->cur_content->next;
} while (file->cur_content != NULL);
}
@@ -4748,7 +4752,7 @@ isofile_gen_utility_names(struct archive_write *a, struct isofile *file)
}
/*
- * Converte a filename to UTF-16BE.
+ * Convert a filename to UTF-16BE.
*/
if (0 > archive_entry_pathname_l(file->entry, &u16, &u16len,
iso9660->sconv_to_utf16be)) {
@@ -5512,7 +5516,7 @@ isoent_setup_file_location(struct iso9660 *iso9660, int location)
file->cur_content->location = location;
location += file->cur_content->blocks;
total_block += file->cur_content->blocks;
- /* Next fragument */
+ /* Next fragment */
file->cur_content = file->cur_content->next;
} while (file->cur_content != NULL);
}
@@ -6135,7 +6139,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
off = ffmax - extlen;
if (off == 0) {
/* A dot('.') character
- * does't place to the first
+ * doesn't place to the first
* byte of identifier. */
off ++;
extlen --;
@@ -6164,7 +6168,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
np->id_len = l = ext_off + np->ext_len;
/* Make an offset of the number which is used to be set
- * hexadecimal number to avoid duplicate identififier. */
+ * hexadecimal number to avoid duplicate identifier. */
if (iso9660->opt.iso_level == 1) {
if (ext_off >= 5)
noff = 5;
@@ -6742,7 +6746,7 @@ isoent_rr_move(struct archive_write *a)
int r;
pt = &(iso9660->primary.pathtbl[MAX_DEPTH-1]);
- /* Theare aren't level 8 directories reaching a deepr level. */
+ /* There aren't level 8 directories reaching a deeper level. */
if (pt->cnt == 0)
return (ARCHIVE_OK);
@@ -6813,7 +6817,7 @@ _compare_path_table(const void *v1, const void *v2)
if (cmp != 0)
return (cmp);
- /* Compare indetifier */
+ /* Compare identifier */
s1 = p1->identifier;
s2 = p2->identifier;
l = p1->ext_off;
@@ -6855,7 +6859,7 @@ _compare_path_table_joliet(const void *v1, const void *v2)
if (cmp != 0)
return (cmp);
- /* Compare indetifier */
+ /* Compare identifier */
s1 = (const unsigned char *)p1->identifier;
s2 = (const unsigned char *)p2->identifier;
l = p1->ext_off;
@@ -7149,7 +7153,7 @@ isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent)
iso9660->el_torito.catalog = isoent;
/*
- * Get a boot medai type.
+ * Get a boot media type.
*/
switch (iso9660->opt.boot_type) {
default:
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c
index b686303..493d473 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c
@@ -1840,9 +1840,9 @@ mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
len = strlen(p);
/*
- * Add "./" prefiex.
+ * Add "./" prefix.
* NOTE: If the pathname does not have a path separator, we have
- * to add "./" to the head of the pathename because mtree reader
+ * to add "./" to the head of the pathname because mtree reader
* will suppose that it is v1(a.k.a classic) mtree format and
* change the directory unexpectedly and so it will make a wrong
* path.
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c
index 6f7fe78..6a301ac 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c
@@ -1,6 +1,7 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
+ * Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -61,15 +62,24 @@ struct pax {
struct sparse_block *sparse_tail;
struct archive_string_conv *sconv_utf8;
int opt_binary;
+
+ unsigned flags;
+#define WRITE_SCHILY_XATTR (1 << 0)
+#define WRITE_LIBARCHIVE_XATTR (1 << 1)
};
static void add_pax_attr(struct archive_string *, const char *key,
const char *value);
+static void add_pax_attr_binary(struct archive_string *,
+ const char *key,
+ const char *value, size_t value_len);
static void add_pax_attr_int(struct archive_string *,
const char *key, int64_t value);
static void add_pax_attr_time(struct archive_string *,
const char *key, int64_t sec,
unsigned long nanos);
+static int add_pax_acl(struct archive_write *,
+ struct archive_entry *, struct pax *, int);
static ssize_t archive_write_pax_data(struct archive_write *,
const void *, size_t);
static int archive_write_pax_close(struct archive_write *);
@@ -127,13 +137,14 @@ archive_write_set_format_pax(struct archive *_a)
if (a->format_free != NULL)
(a->format_free)(a);
- pax = (struct pax *)malloc(sizeof(*pax));
+ pax = (struct pax *)calloc(1, sizeof(*pax));
if (pax == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate pax data");
return (ARCHIVE_FATAL);
}
- memset(pax, 0, sizeof(*pax));
+ pax->flags = WRITE_LIBARCHIVE_XATTR | WRITE_SCHILY_XATTR;
+
a->format_data = pax;
a->format_name = "pax";
a->format_options = archive_write_pax_options;
@@ -273,6 +284,17 @@ add_pax_attr_int(struct archive_string *as, const char *key, int64_t value)
static void
add_pax_attr(struct archive_string *as, const char *key, const char *value)
{
+ add_pax_attr_binary(as, key, value, strlen(value));
+}
+
+/*
+ * Add a key/value attribute to the pax header. This function handles
+ * binary values.
+ */
+static void
+add_pax_attr_binary(struct archive_string *as, const char *key,
+ const char *value, size_t value_len)
+{
int digits, i, len, next_ten;
char tmp[1 + 3 * sizeof(int)]; /* < 3 base-10 digits per byte */
@@ -280,7 +302,7 @@ add_pax_attr(struct archive_string *as, const char *key, const char *value)
* PAX attributes have the following layout:
* <len> <space> <key> <=> <value> <nl>
*/
- len = 1 + (int)strlen(key) + 1 + (int)strlen(value) + 1;
+ len = 1 + (int)strlen(key) + 1 + (int)value_len + 1;
/*
* The <len> field includes the length of the <len> field, so
@@ -311,21 +333,47 @@ add_pax_attr(struct archive_string *as, const char *key, const char *value)
archive_strappend_char(as, ' ');
archive_strcat(as, key);
archive_strappend_char(as, '=');
- archive_strcat(as, value);
+ archive_array_append(as, value, value_len);
archive_strappend_char(as, '\n');
}
+static void
+archive_write_pax_header_xattr(struct pax *pax, const char *encoded_name,
+ const void *value, size_t value_len)
+{
+ struct archive_string s;
+ char *encoded_value;
+
+ if (pax->flags & WRITE_LIBARCHIVE_XATTR) {
+ encoded_value = base64_encode((const char *)value, value_len);
+
+ if (encoded_name != NULL && encoded_value != NULL) {
+ archive_string_init(&s);
+ archive_strcpy(&s, "LIBARCHIVE.xattr.");
+ archive_strcat(&s, encoded_name);
+ add_pax_attr(&(pax->pax_header), s.s, encoded_value);
+ archive_string_free(&s);
+ }
+ free(encoded_value);
+ }
+ if (pax->flags & WRITE_SCHILY_XATTR) {
+ archive_string_init(&s);
+ archive_strcpy(&s, "SCHILY.xattr.");
+ archive_strcat(&s, encoded_name);
+ add_pax_attr_binary(&(pax->pax_header), s.s, value, value_len);
+ archive_string_free(&s);
+ }
+}
+
static int
archive_write_pax_header_xattrs(struct archive_write *a,
struct pax *pax, struct archive_entry *entry)
{
- struct archive_string s;
int i = archive_entry_xattr_reset(entry);
while (i--) {
const char *name;
const void *value;
- char *encoded_value;
char *url_encoded_name = NULL, *encoded_name = NULL;
size_t size;
int r;
@@ -346,16 +394,9 @@ archive_write_pax_header_xattrs(struct archive_write *a,
}
}
- encoded_value = base64_encode((const char *)value, size);
+ archive_write_pax_header_xattr(pax, encoded_name,
+ value, size);
- if (encoded_name != NULL && encoded_value != NULL) {
- archive_string_init(&s);
- archive_strcpy(&s, "LIBARCHIVE.xattr.");
- archive_strcat(&s, encoded_name);
- add_pax_attr(&(pax->pax_header), s.s, encoded_value);
- archive_string_free(&s);
- }
- free(encoded_value);
}
return (ARCHIVE_OK);
}
@@ -450,6 +491,45 @@ get_entry_symlink(struct archive_write *a, struct archive_entry *entry,
return (ARCHIVE_OK);
}
+/* Add ACL to pax header */
+static int
+add_pax_acl(struct archive_write *a,
+ struct archive_entry *entry, struct pax *pax, int flags)
+{
+ char *p;
+ const char *attr;
+ int acl_types;
+
+ acl_types = archive_entry_acl_types(entry);
+
+ if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
+ attr = "SCHILY.acl.ace";
+ else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
+ attr = "SCHILY.acl.access";
+ else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
+ attr = "SCHILY.acl.default";
+ else
+ return (ARCHIVE_FATAL);
+
+ p = archive_entry_acl_to_text_l(entry, NULL, flags, pax->sconv_utf8);
+ if (p == NULL) {
+ if (errno == ENOMEM) {
+ archive_set_error(&a->archive, ENOMEM, "%s %s",
+ "Can't allocate memory for ", attr);
+ return (ARCHIVE_FATAL);
+ }
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT, "%s %s %s",
+ "Can't translate ", attr, " to UTF-8");
+ return(ARCHIVE_WARN);
+ } else if (*p != '\0') {
+ add_pax_attr(&(pax->pax_header),
+ attr, p);
+ free(p);
+ }
+ return(ARCHIVE_OK);
+}
+
/*
* TODO: Consider adding 'comment' and 'charset' fields to
* archive_entry so that clients can specify them. Also, consider
@@ -466,6 +546,7 @@ archive_write_pax_header(struct archive_write *a,
const char *p;
const char *suffix;
int need_extension, r, ret;
+ int acl_types;
int sparse_count;
uint64_t sparse_total, real_size;
struct pax *pax;
@@ -709,7 +790,7 @@ archive_write_pax_header(struct archive_write *a,
/* Copy entry so we can modify it as needed. */
#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure the path separators in pahtname, hardlink and symlink
+ /* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry_original);
if (entry_main == entry_original)
@@ -1017,16 +1098,6 @@ archive_write_pax_header(struct archive_write *a,
if (!need_extension && p != NULL && *p != '\0')
need_extension = 1;
- /* If there are non-trivial ACL entries, we need an extension. */
- if (!need_extension && archive_entry_acl_count(entry_original,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS) > 0)
- need_extension = 1;
-
- /* If there are non-trivial ACL entries, we need an extension. */
- if (!need_extension && archive_entry_acl_count(entry_original,
- ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) > 0)
- need_extension = 1;
-
/* If there are extended attributes, we need an extension */
if (!need_extension && archive_entry_xattr_count(entry_original) > 0)
need_extension = 1;
@@ -1035,6 +1106,12 @@ archive_write_pax_header(struct archive_write *a,
if (!need_extension && sparse_count > 0)
need_extension = 1;
+ acl_types = archive_entry_acl_types(entry_original);
+
+ /* If there are any ACL entries, we need an extension */
+ if (!need_extension && acl_types != 0)
+ need_extension = 1;
+
/*
* Libarchive used to include these in extended headers for
* restricted pax format, but that confused people who
@@ -1086,43 +1163,29 @@ archive_write_pax_header(struct archive_write *a,
add_pax_attr(&(pax->pax_header), "SCHILY.fflags", p);
/* I use star-compatible ACL attributes. */
- r = archive_entry_acl_text_l(entry_original,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
- ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID,
- &p, NULL, pax->sconv_utf8);
- if (r != 0) {
- if (errno == ENOMEM) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate memory for "
- "ACL.access");
+ if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+ ret = add_pax_acl(a, entry_original, pax,
+ ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
+ ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA |
+ ARCHIVE_ENTRY_ACL_STYLE_COMPACT);
+ if (ret == ARCHIVE_FATAL)
return (ARCHIVE_FATAL);
- }
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "Can't translate ACL.access to UTF-8");
- ret = ARCHIVE_WARN;
- } else if (p != NULL && *p != '\0') {
- add_pax_attr(&(pax->pax_header),
- "SCHILY.acl.access", p);
}
- r = archive_entry_acl_text_l(entry_original,
- ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
- ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID,
- &p, NULL, pax->sconv_utf8);
- if (r != 0) {
- if (errno == ENOMEM) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate memory for "
- "ACL.default");
+ if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
+ ret = add_pax_acl(a, entry_original, pax,
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
+ ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
+ ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA);
+ if (ret == ARCHIVE_FATAL)
+ return (ARCHIVE_FATAL);
+ }
+ if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) {
+ ret = add_pax_acl(a, entry_original, pax,
+ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
+ ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
+ ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA);
+ if (ret == ARCHIVE_FATAL)
return (ARCHIVE_FATAL);
- }
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "Can't translate ACL.default to UTF-8");
- ret = ARCHIVE_WARN;
- } else if (p != NULL && *p != '\0') {
- add_pax_attr(&(pax->pax_header),
- "SCHILY.acl.default", p);
}
/* We use GNU-tar-compatible sparse attributes. */
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_shar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_shar.c
index c033fb3..5be310a 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_shar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_shar.c
@@ -113,12 +113,11 @@ archive_write_set_format_shar(struct archive *_a)
if (a->format_free != NULL)
(a->format_free)(a);
- shar = (struct shar *)malloc(sizeof(*shar));
+ shar = (struct shar *)calloc(1, sizeof(*shar));
if (shar == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't allocate shar data");
return (ARCHIVE_FATAL);
}
- memset(shar, 0, sizeof(*shar));
archive_string_init(&shar->work);
archive_string_init(&shar->quoted_name);
a->format_data = shar;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c
index 484ab34..c54aeab 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c
@@ -114,9 +114,9 @@ static const char template_header[] = {
'0','0','0','0','0','0', ' ','\0',
/* gid, space-null termination: 8 bytes */
'0','0','0','0','0','0', ' ','\0',
- /* size, space termation: 12 bytes */
+ /* size, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', ' ',
- /* mtime, space termation: 12 bytes */
+ /* mtime, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', ' ',
/* Initial checksum value: 8 spaces */
' ',' ',' ',' ',' ',' ',' ',' ',
@@ -184,13 +184,12 @@ archive_write_set_format_ustar(struct archive *_a)
return (ARCHIVE_FATAL);
}
- ustar = (struct ustar *)malloc(sizeof(*ustar));
+ ustar = (struct ustar *)calloc(1, sizeof(*ustar));
if (ustar == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate ustar data");
return (ARCHIVE_FATAL);
}
- memset(ustar, 0, sizeof(*ustar));
a->format_data = ustar;
a->format_name = "ustar";
a->format_options = archive_write_ustar_options;
@@ -307,7 +306,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
* case getting WCS failed. On POSIX, this is a
* normal operation.
*/
- if (p != NULL && p[strlen(p) - 1] != '/') {
+ if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') {
struct archive_string as;
archive_string_init(&as);
@@ -336,7 +335,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
}
#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure the path separators in pahtname, hardlink and symlink
+ /* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry);
if (entry_main == NULL) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c
index 17efbaf..62b1522 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c
@@ -98,9 +98,9 @@ static const char template_header[] = {
'0','0','0','0','0','0', ' ','\0',
/* gid, space-null termination: 8 bytes */
'0','0','0','0','0','0', ' ','\0',
- /* size, space termation: 12 bytes */
+ /* size, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', ' ',
- /* mtime, space termation: 12 bytes */
+ /* mtime, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', ' ',
/* Initial checksum value: 8 spaces */
' ',' ',' ',' ',' ',' ',' ',' ',
@@ -161,13 +161,12 @@ archive_write_set_format_v7tar(struct archive *_a)
return (ARCHIVE_FATAL);
}
- v7tar = (struct v7tar *)malloc(sizeof(*v7tar));
+ v7tar = (struct v7tar *)calloc(1, sizeof(*v7tar));
if (v7tar == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate v7tar data");
return (ARCHIVE_FATAL);
}
- memset(v7tar, 0, sizeof(*v7tar));
a->format_data = v7tar;
a->format_name = "tar (non-POSIX)";
a->format_options = archive_write_v7tar_options;
@@ -314,7 +313,7 @@ archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry)
}
#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure the path separators in pahtname, hardlink and symlink
+ /* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry);
if (entry_main == NULL) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c
index ea66929..8b6daf9 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c
@@ -79,7 +79,7 @@ typedef enum {
WT_RVIS,
/* conversion, unsupported */
WT_CONV,
- /* continutation, unsupported at the moment */
+ /* continuation, unsupported at the moment */
WT_CONT,
/* invalid type */
LAST_WT
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c
index 58ad9e0..3c617ec 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c
@@ -63,7 +63,7 @@ __FBSDID("$FreeBSD$");
* - When writing an XML element <link type="<file-type>">, <file-type>
* which is a file type a symbolic link is referencing is always marked
* as "broken". Xar utility uses stat(2) to get the file type, but, in
- * libarcive format writer, we should not use it; if it is needed, we
+ * libarchive format writer, we should not use it; if it is needed, we
* should get about it at archive_read_disk.c.
* - It is possible to appear both <flags> and <ext2> elements.
* Xar utility generates <flags> on BSD platform and <ext2> on Linux
@@ -192,7 +192,7 @@ struct file {
struct file *parent; /* parent directory entry */
/*
* To manage sub directory files.
- * We use 'chnext' a menber of struct file to chain.
+ * We use 'chnext' (a member of struct file) to chain.
*/
struct {
struct file *first;
@@ -258,7 +258,7 @@ struct xar {
/*
* The list of all file entries is used to manage struct file
* objects.
- * We use 'next' a menber of struct file to chain.
+ * We use 'next' (a member of struct file) to chain.
*/
struct {
struct file *first;
@@ -266,7 +266,7 @@ struct xar {
} file_list;
/*
* The list of hard-linked file entries.
- * We use 'hlnext' a menber of struct file to chain.
+ * We use 'hlnext' (a member of struct file) to chain.
*/
struct archive_rb_tree hardlink_rbtree;
};
@@ -1227,7 +1227,7 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
case AE_IFLNK:
/*
* xar utility has checked a file type, which
- * a symblic-link file has referenced.
+ * a symbolic-link file has referenced.
* For example:
* <link type="directory">../ref/</link>
* The symlink target file is "../ref/" and its
@@ -1237,8 +1237,8 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
* The symlink target file is "../f" and its
* file type is a regular file.
*
- * But our implemention cannot do it, and then we
- * always record that a attribute "type" is "borken",
+ * But our implementation cannot do it, and then we
+ * always record that a attribute "type" is "broken",
* for example:
* <link type="broken">foo/bar</link>
* It means "foo/bar" is not reachable.
@@ -1544,7 +1544,7 @@ make_toc(struct archive_write *a)
}
/*
- * Start recoding TOC
+ * Start recording TOC
*/
r = xmlTextWriterStartElement(writer, BAD_CAST("xar"));
if (r < 0) {
@@ -1961,6 +1961,7 @@ file_free(struct file *file)
archive_string_free(&(file->basename));
archive_string_free(&(file->symlink));
archive_string_free(&(file->script));
+ archive_entry_free(file->entry);
free(file);
}
@@ -2484,7 +2485,7 @@ file_connect_hardlink_files(struct xar *xar)
archive_entry_set_nlink(target->entry, hl->nlink);
if (hl->nlink > 1)
/* It means this file is a hardlink
- * targe itself. */
+ * target itself. */
target->hardlink_target = target;
for (nf = target->hlnext;
nf != NULL; nf = nf->hlnext) {
@@ -2913,7 +2914,7 @@ compression_init_encoder_xz(struct archive *a,
*strm = lzma_init_data;
#ifdef HAVE_LZMA_STREAM_ENCODER_MT
if (threads > 1) {
- bzero(&mt_options, sizeof(mt_options));
+ memset(&mt_options, 0, sizeof(mt_options));
mt_options.threads = threads;
mt_options.timeout = 300;
mt_options.filters = lzmafilters;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c
index 0b2c69b..a4ae229 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c
@@ -592,7 +592,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
#if defined(_WIN32) && !defined(__CYGWIN__)
- /* Make sure the path separators in pahtname, hardlink and symlink
+ /* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
zip->entry = __la_win_entry_in_posix_pathseparator(entry);
if (zip->entry == entry)
@@ -878,7 +878,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
|| zip->entry_encryption == ENCRYPTION_WINZIP_AES256)) {
memcpy(e, "\001\231\007\000\001\000AE", 8);
- /* AES vendoer version AE-2 does not store a CRC.
+ /* AES vendor version AE-2 does not store a CRC.
* WinZip 11 uses AE-1, which does store the CRC,
* but it does not store the CRC when the file size
* is less than 20 bytes. So we simulate what
@@ -1013,7 +1013,7 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s)
if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) {
switch (zip->entry_encryption) {
case ENCRYPTION_TRADITIONAL:
- /* Initialize traditoinal PKWARE encryption context. */
+ /* Initialize traditional PKWARE encryption context. */
if (!zip->tctx_valid) {
ret = init_traditional_pkware_encryption(a);
if (ret != ARCHIVE_OK)
@@ -1499,7 +1499,7 @@ trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c)
}
static uint8_t
-trad_enc_decypt_byte(struct trad_enc_ctx *ctx)
+trad_enc_decrypt_byte(struct trad_enc_ctx *ctx)
{
unsigned temp = ctx->keys[2] | 2;
return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff;
@@ -1515,7 +1515,7 @@ trad_enc_encrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in,
for (i = 0; i < max; i++) {
uint8_t t = in[i];
- out[i] = t ^ trad_enc_decypt_byte(ctx);
+ out[i] = t ^ trad_enc_decrypt_byte(ctx);
trad_enc_update_keys(ctx, t);
}
return i;
@@ -1626,7 +1626,7 @@ init_winzip_aes_encryption(struct archive_write *a)
return (ARCHIVE_FAILED);
}
- /* Set a passowrd verification value after the 'salt'. */
+ /* Set a password verification value after the 'salt'. */
salt[salt_len] = derived_key[key_len * 2];
salt[salt_len + 1] = derived_key[key_len * 2 + 1];
diff --git a/Utilities/cmlibarchive/libarchive/config_freebsd.h b/Utilities/cmlibarchive/libarchive/config_freebsd.h
index 2073431..215e886 100644
--- a/Utilities/cmlibarchive/libarchive/config_freebsd.h
+++ b/Utilities/cmlibarchive/libarchive/config_freebsd.h
@@ -28,6 +28,7 @@
/* FreeBSD 5.0 and later have ACL and extattr support. */
#if __FreeBSD__ > 4
#define HAVE_ACL_CREATE_ENTRY 1
+#define HAVE_ACL_GET_FD_NP 1
#define HAVE_ACL_GET_LINK_NP 1
#define HAVE_ACL_GET_PERM_NP 1
#define HAVE_ACL_INIT 1
@@ -39,6 +40,7 @@
#define HAVE_EXTATTR_LIST_FILE 1
#define HAVE_EXTATTR_SET_FD 1
#define HAVE_EXTATTR_SET_FILE 1
+#define HAVE_STRUCT_XVFSCONF 1
#define HAVE_SYS_ACL_H 1
#define HAVE_SYS_EXTATTR_H 1
#endif
diff --git a/Utilities/cmlibarchive/libarchive/libarchive-formats.5 b/Utilities/cmlibarchive/libarchive/libarchive-formats.5
index 9cec760..62359dd 100644
--- a/Utilities/cmlibarchive/libarchive/libarchive-formats.5
+++ b/Utilities/cmlibarchive/libarchive/libarchive-formats.5
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 18, 2012
+.Dd December 27, 2016
.Dt LIBARCHIVE-FORMATS 5
.Os
.Sh NAME
@@ -191,8 +191,6 @@ and device numbers.
.It Solaris extensions
Libarchive recognizes ACL and extended attribute records written
by Solaris tar.
-Currently, libarchive only has support for old-style ACLs; the
-newer NFSv4 ACLs are recognized but discarded.
.El
.Pp
The first tar program appeared in Seventh Edition Unix in 1979.
diff --git a/Utilities/cmlibarchive/libarchive/tar.5 b/Utilities/cmlibarchive/libarchive/tar.5
index 6e6f0c0..30b837d 100644
--- a/Utilities/cmlibarchive/libarchive/tar.5
+++ b/Utilities/cmlibarchive/libarchive/tar.5
@@ -1,4 +1,5 @@
.\" Copyright (c) 2003-2009 Tim Kientzle
+.\" Copyright (c) 2016 Martin Matuska
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -24,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 23, 2011
+.Dd December 27, 2016
.Dt TAR 5
.Os
.Sh NAME
@@ -440,11 +441,11 @@ archives to store files much larger than the historic 8GB limit.
Vendor-specific attributes used by Joerg Schilling's
.Nm star
implementation.
-.It Cm SCHILY.acl.access , Cm SCHILY.acl.default
-Stores the access and default ACLs as textual strings in a format
+.It Cm SCHILY.acl.access , Cm SCHILY.acl.default, Cm SCHILY.acl.ace
+Stores the access, default and NFSv4 ACLs as textual strings in a format
that is an extension of the format specified by POSIX.1e draft 17.
-In particular, each user or group access specification can include a fourth
-colon-separated field with the numeric UID or GID.
+In particular, each user or group access specification can include
+an additional colon-separated field with the numeric UID or GID.
This allows ACLs to be restored on systems that may not have complete
user or group information available (such as when NIS/YP or LDAP services
are temporarily unavailable).
diff --git a/Utilities/cmlibarchive/libarchive/xxhash.c b/Utilities/cmlibarchive/libarchive/xxhash.c
index 262fecb..6f5ba52 100644
--- a/Utilities/cmlibarchive/libarchive/xxhash.c
+++ b/Utilities/cmlibarchive/libarchive/xxhash.c
@@ -29,13 +29,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- xxHash source repository : http://code.google.com/p/xxhash/
*/
-
#include "archive_platform.h"
-#include "archive_xxhash.h"
#include <stdlib.h>
#include <string.h>
+#include "archive_xxhash.h"
+
#ifdef HAVE_LIBLZ4
/***************************************
@@ -61,7 +61,7 @@ You can contact the author at :
** By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
** Results are therefore identical for little-endian and big-endian CPU.
** This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
-** Should endian-independance be of no importance for your application, you may set the #define below to 1.
+** Should endian-independence be of no importance for your application, you may set the #define below to 1.
** It will improve speed for Big-endian CPU.
** This option has no impact on Little_Endian CPU.
*/
diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt
index a8e25ba..6632a1e 100644
--- a/Utilities/cmlibuv/CMakeLists.txt
+++ b/Utilities/cmlibuv/CMakeLists.txt
@@ -212,6 +212,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
nsl
sendfile
socket
+ rt
)
list(APPEND uv_headers
include/uv-sunos.h
@@ -223,6 +224,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
list(APPEND uv_defines
_XOPEN_SOURCE=500
)
+ if(CMAKE_C_STANDARD)
+ set(CMAKE_C_STANDARD 90)
+ endif()
else()
list(APPEND uv_defines
_XOPEN_SOURCE=600
diff --git a/Utilities/cmlibuv/include/pthread-barrier.h b/Utilities/cmlibuv/include/pthread-barrier.h
index 3e01705..900ebed 100644
--- a/Utilities/cmlibuv/include/pthread-barrier.h
+++ b/Utilities/cmlibuv/include/pthread-barrier.h
@@ -18,7 +18,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define _UV_PTHREAD_BARRIER_
#include <errno.h>
#include <pthread.h>
+#if !defined(__MVS__)
#include <semaphore.h> /* sem_t */
+#endif
#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345
diff --git a/Utilities/cmlibuv/include/uv-os390.h b/Utilities/cmlibuv/include/uv-os390.h
index b0b068f..58f9261 100644
--- a/Utilities/cmlibuv/include/uv-os390.h
+++ b/Utilities/cmlibuv/include/uv-os390.h
@@ -24,4 +24,7 @@
#define UV_PLATFORM_SEM_T int
+#define UV_PLATFORM_LOOP_FIELDS \
+ void* ep; \
+
#endif /* UV_MVS_H */
diff --git a/Utilities/cmlibuv/include/uv-unix.h b/Utilities/cmlibuv/include/uv-unix.h
index bca2714..3030f71 100644
--- a/Utilities/cmlibuv/include/uv-unix.h
+++ b/Utilities/cmlibuv/include/uv-unix.h
@@ -36,7 +36,9 @@
#include <termios.h>
#include <pwd.h>
+#if !defined(__MVS__)
#include <semaphore.h>
+#endif
#include <pthread.h>
#include <signal.h>
@@ -44,6 +46,8 @@
#if defined(__linux__)
# include "uv-linux.h"
+#elif defined (__MVS__)
+# include "uv-os390.h"
#elif defined(_AIX)
# include "uv-aix.h"
#elif defined(__sun)
diff --git a/Utilities/cmlibuv/include/uv-version.h b/Utilities/cmlibuv/include/uv-version.h
index 3cb9b5f..e165809 100644
--- a/Utilities/cmlibuv/include/uv-version.h
+++ b/Utilities/cmlibuv/include/uv-version.h
@@ -31,8 +31,8 @@
*/
#define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 9
-#define UV_VERSION_PATCH 2
+#define UV_VERSION_MINOR 11
+#define UV_VERSION_PATCH 1
#define UV_VERSION_IS_RELEASE 0
#define UV_VERSION_SUFFIX "dev"
diff --git a/Utilities/cmlibuv/include/uv-win.h b/Utilities/cmlibuv/include/uv-win.h
index 89ee09a..d3e32a5 100644
--- a/Utilities/cmlibuv/include/uv-win.h
+++ b/Utilities/cmlibuv/include/uv-win.h
@@ -49,6 +49,7 @@ typedef struct pollfd {
#include <process.h>
#include <signal.h>
+#include <fcntl.h>
#include <sys/stat.h>
#if defined(_MSC_VER) && _MSC_VER < 1600
diff --git a/Utilities/cmlibuv/include/uv.h b/Utilities/cmlibuv/include/uv.h
index e3e20dc..5879764 100644
--- a/Utilities/cmlibuv/include/uv.h
+++ b/Utilities/cmlibuv/include/uv.h
@@ -367,6 +367,8 @@ typedef enum {
} uv_membership;
+UV_EXTERN int uv_translate_sys_error(int sys_errno);
+
UV_EXTERN const char* uv_strerror(int err);
UV_EXTERN const char* uv_err_name(int err);
diff --git a/Utilities/cmlibuv/src/unix/aix.c b/Utilities/cmlibuv/src/unix/aix.c
index 652cd98..1d2cd4a 100644
--- a/Utilities/cmlibuv/src/unix/aix.c
+++ b/Utilities/cmlibuv/src/unix/aix.c
@@ -64,6 +64,11 @@
#define RDWR_BUF_SIZE 4096
#define EQ(a,b) (strcmp(a,b) == 0)
+static void* args_mem = NULL;
+static char** process_argv = NULL;
+static int process_argc = 0;
+static char* process_title_ptr = NULL;
+
int uv__platform_loop_init(uv_loop_t* loop) {
loop->fs_fd = -1;
@@ -753,6 +758,13 @@ static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int
assert((bytes >= 0) && "uv__ahafs_event - Error reading monitor file");
+ /* In file / directory move cases, AIX Event infrastructure
+ * produces a second event with no data.
+ * Ignore it and return gracefully.
+ */
+ if(bytes == 0)
+ return;
+
/* Parse the data */
if(bytes > 0)
rc = uv__parse_data(result_data, &events, handle);
@@ -881,24 +893,94 @@ void uv__fs_event_close(uv_fs_event_t* handle) {
char** uv_setup_args(int argc, char** argv) {
- return argv;
+ char** new_argv;
+ size_t size;
+ char* s;
+ int i;
+
+ if (argc <= 0)
+ return argv;
+
+ /* Save the original pointer to argv.
+ * AIX uses argv to read the process name.
+ * (Not the memory pointed to by argv[0..n] as on Linux.)
+ */
+ process_argv = argv;
+ process_argc = argc;
+
+ /* Calculate how much memory we need for the argv strings. */
+ size = 0;
+ for (i = 0; i < argc; i++)
+ size += strlen(argv[i]) + 1;
+
+ /* Add space for the argv pointers. */
+ size += (argc + 1) * sizeof(char*);
+
+ new_argv = uv__malloc(size);
+ if (new_argv == NULL)
+ return argv;
+ args_mem = new_argv;
+
+ /* Copy over the strings and set up the pointer table. */
+ s = (char*) &new_argv[argc + 1];
+ for (i = 0; i < argc; i++) {
+ size = strlen(argv[i]) + 1;
+ memcpy(s, argv[i], size);
+ new_argv[i] = s;
+ s += size;
+ }
+ new_argv[i] = NULL;
+
+ return new_argv;
}
int uv_set_process_title(const char* title) {
+ char* new_title;
+
+ /* We cannot free this pointer when libuv shuts down,
+ * the process may still be using it.
+ */
+ new_title = uv__strdup(title);
+ if (new_title == NULL)
+ return -ENOMEM;
+
+ /* If this is the first time this is set,
+ * don't free and set argv[1] to NULL.
+ */
+ if (process_title_ptr != NULL)
+ uv__free(process_title_ptr);
+
+ process_title_ptr = new_title;
+
+ process_argv[0] = process_title_ptr;
+ if (process_argc > 1)
+ process_argv[1] = NULL;
+
return 0;
}
int uv_get_process_title(char* buffer, size_t size) {
+ size_t len;
+ len = strlen(process_argv[0]);
if (buffer == NULL || size == 0)
return -EINVAL;
+ else if (size <= len)
+ return -ENOBUFS;
+
+ memcpy(buffer, process_argv[0], len + 1);
- buffer[0] = '\0';
return 0;
}
+UV_DESTRUCTOR(static void free_args_mem(void)) {
+ uv__free(args_mem); /* Keep valgrind happy. */
+ args_mem = NULL;
+}
+
+
int uv_resident_set_memory(size_t* rss) {
char pp[64];
psinfo_t psinfo;
diff --git a/Utilities/cmlibuv/src/unix/atomic-ops.h b/Utilities/cmlibuv/src/unix/atomic-ops.h
index 815e355..9dac255 100644
--- a/Utilities/cmlibuv/src/unix/atomic-ops.h
+++ b/Utilities/cmlibuv/src/unix/atomic-ops.h
@@ -43,8 +43,12 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
__compare_and_swap(ptr, &oldval, newval);
return out;
#elif defined(__MVS__)
- return __plo_CS(ptr, (unsigned int*) ptr,
- oldval, (unsigned int*) &newval);
+ unsigned int op4;
+ if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
+ (unsigned int*) ptr, *ptr, &op4))
+ return oldval;
+ else
+ return op4;
#else
return __sync_val_compare_and_swap(ptr, oldval, newval);
#endif
@@ -67,13 +71,18 @@ UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) {
# endif /* if defined(__64BIT__) */
return out;
#elif defined (__MVS__)
-# ifdef _LP64
- return __plo_CSGR(ptr, (unsigned long long*) ptr,
- oldval, (unsigned long long*) &newval);
-# else
- return __plo_CS(ptr, (unsigned int*) ptr,
- oldval, (unsigned int*) &newval);
-# endif
+#ifdef _LP64
+ unsigned long long op4;
+ if (__plo_CSSTGR(ptr, (unsigned long long*) &oldval, newval,
+ (unsigned long long*) ptr, *ptr, &op4))
+#else
+ unsigned long op4;
+ if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
+ (unsigned int*) ptr, *ptr, &op4))
+#endif
+ return oldval;
+ else
+ return op4;
#else
return __sync_val_compare_and_swap(ptr, oldval, newval);
#endif
diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c
index d88fc1d..9ef7134 100644
--- a/Utilities/cmlibuv/src/unix/core.c
+++ b/Utilities/cmlibuv/src/unix/core.c
@@ -98,7 +98,7 @@ uint64_t uv_hrtime(void) {
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
- assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
+ assert(!uv__is_closing(handle));
handle->flags |= UV_CLOSING;
handle->close_cb = close_cb;
@@ -517,6 +517,9 @@ int uv__close_nocheckstdio(int fd) {
int uv__close(int fd) {
assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */
+#if defined(__MVS__)
+ epoll_file_close(fd);
+#endif
return uv__close_nocheckstdio(fd);
}
@@ -836,13 +839,8 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
* every tick of the event loop but the other backends allow us to
* short-circuit here if the event mask is unchanged.
*/
- if (w->events == w->pevents) {
- if (w->events == 0 && !QUEUE_EMPTY(&w->watcher_queue)) {
- QUEUE_REMOVE(&w->watcher_queue);
- QUEUE_INIT(&w->watcher_queue);
- }
+ if (w->events == w->pevents)
return;
- }
#endif
if (QUEUE_EMPTY(&w->watcher_queue))
@@ -1236,3 +1234,9 @@ void uv_os_free_passwd(uv_passwd_t* pwd) {
int uv_os_get_passwd(uv_passwd_t* pwd) {
return uv__getpwuid_r(pwd);
}
+
+
+int uv_translate_sys_error(int sys_errno) {
+ /* If < 0 then it's already a libuv error. */
+ return sys_errno <= 0 ? sys_errno : -sys_errno;
+}
diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c
index 3d478b7..8a4ba7a 100644
--- a/Utilities/cmlibuv/src/unix/fs.c
+++ b/Utilities/cmlibuv/src/unix/fs.c
@@ -129,8 +129,23 @@
static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
#if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
return fdatasync(req->file);
-#elif defined(__APPLE__) && defined(SYS_fdatasync)
- return syscall(SYS_fdatasync, req->file);
+#elif defined(__APPLE__)
+ /* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache
+ * to the drive platters. This is in contrast to Linux's fdatasync and fsync
+ * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent
+ * for flushing buffered data to permanent storage.
+ */
+ return fcntl(req->file, F_FULLFSYNC);
+#else
+ return fsync(req->file);
+#endif
+}
+
+
+static ssize_t uv__fs_fsync(uv_fs_t* req) {
+#if defined(__APPLE__)
+ /* See the comment in uv__fs_fdatasync. */
+ return fcntl(req->file, F_FULLFSYNC);
#else
return fsync(req->file);
#endif
@@ -229,9 +244,19 @@ skip:
#endif
}
+#if defined(__sun) && _XOPEN_SOURCE < 600
+static char* uv__mkdtemp(char *template)
+{
+ if (!mktemp(template) || mkdir(template, 0700))
+ return NULL;
+ return template;
+}
+#else
+#define uv__mkdtemp mkdtemp
+#endif
static ssize_t uv__fs_mkdtemp(uv_fs_t* req) {
- return mkdtemp((char*) req->path) ? 0 : -1;
+ return uv__mkdtemp((char*) req->path) ? 0 : -1;
}
@@ -365,7 +390,6 @@ static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) {
static ssize_t uv__fs_scandir(uv_fs_t* req) {
uv__dirent_t **dents;
- int saved_errno;
int n;
dents = NULL;
@@ -374,28 +398,17 @@ static ssize_t uv__fs_scandir(uv_fs_t* req) {
/* NOTE: We will use nbufs as an index field */
req->nbufs = 0;
- if (n == 0)
- goto out; /* osx still needs to deallocate some memory */
- else if (n == -1)
- return n;
-
- req->ptr = dents;
-
- return n;
-
-out:
- saved_errno = errno;
- if (dents != NULL) {
- int i;
-
- /* Memory was allocated using the system allocator, so use free() here. */
- for (i = 0; i < n; i++)
- free(dents[i]);
+ if (n == 0) {
+ /* OS X still needs to deallocate some memory.
+ * Memory was allocated using the system allocator, so use free() here.
+ */
free(dents);
+ dents = NULL;
+ } else if (n == -1) {
+ return n;
}
- errno = saved_errno;
- req->ptr = NULL;
+ req->ptr = dents;
return n;
}
@@ -798,6 +811,10 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
dst->st_flags = 0;
dst->st_gen = 0;
#elif !defined(_AIX) && ( \
+ defined(__DragonFly__) || \
+ defined(__FreeBSD__) || \
+ defined(__OpenBSD__) || \
+ defined(__NetBSD__) || \
defined(_GNU_SOURCE) || \
defined(_BSD_SOURCE) || \
defined(_SVID_SOURCE) || \
@@ -809,9 +826,7 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
dst->st_mtim.tv_nsec = src->st_mtim.tv_nsec;
dst->st_ctim.tv_sec = src->st_ctim.tv_sec;
dst->st_ctim.tv_nsec = src->st_ctim.tv_nsec;
-# if defined(__DragonFly__) || \
- defined(__FreeBSD__) || \
- defined(__OpenBSD__) || \
+# if defined(__FreeBSD__) || \
defined(__NetBSD__)
dst->st_birthtim.tv_sec = src->st_birthtim.tv_sec;
dst->st_birthtim.tv_nsec = src->st_birthtim.tv_nsec;
@@ -945,7 +960,7 @@ static void uv__fs_work(struct uv__work* w) {
X(FCHOWN, fchown(req->file, req->uid, req->gid));
X(FDATASYNC, uv__fs_fdatasync(req));
X(FSTAT, uv__fs_fstat(req->file, &req->statbuf));
- X(FSYNC, fsync(req->file));
+ X(FSYNC, uv__fs_fsync(req));
X(FTRUNCATE, ftruncate(req->file, req->off));
X(FUTIME, uv__fs_futime(req));
X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
diff --git a/Utilities/cmlibuv/src/unix/internal.h b/Utilities/cmlibuv/src/unix/internal.h
index 2570026..b48f8fa 100644
--- a/Utilities/cmlibuv/src/unix/internal.h
+++ b/Utilities/cmlibuv/src/unix/internal.h
@@ -38,6 +38,10 @@
# include "linux-syscalls.h"
#endif /* __linux__ */
+#if defined(__MVS__)
+# include "os390-syscalls.h"
+#endif /* __MVS__ */
+
#if defined(__sun)
# include <sys/port.h>
# include <port.h>
@@ -51,6 +55,10 @@
# include <poll.h>
#endif /* _AIX */
+#if defined(__APPLE__) && !TARGET_OS_IPHONE
+# include <AvailabilityMacros.h>
+#endif
+
#if defined(__ANDROID__)
int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
# ifdef pthread_sigmask
@@ -154,7 +162,8 @@ struct uv__stream_queued_fds_s {
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || \
- defined(__linux__)
+ defined(__linux__) || \
+ defined(__OpenBSD__)
#define uv__cloexec uv__cloexec_ioctl
#define uv__nonblock uv__nonblock_ioctl
#else
@@ -268,7 +277,6 @@ int uv__make_socketpair(int fds[2], int flags);
int uv__make_pipe(int fds[2], int flags);
#if defined(__APPLE__)
-#include <AvailabilityMacros.h>
int uv__fsevents_init(uv_fs_event_t* handle);
int uv__fsevents_close(uv_fs_event_t* handle);
diff --git a/Utilities/cmlibuv/src/unix/openbsd.c b/Utilities/cmlibuv/src/unix/openbsd.c
index 909288c..ac28b69 100644
--- a/Utilities/cmlibuv/src/unix/openbsd.c
+++ b/Utilities/cmlibuv/src/unix/openbsd.c
@@ -163,7 +163,7 @@ char** uv_setup_args(int argc, char** argv) {
int uv_set_process_title(const char* title) {
uv__free(process_title);
process_title = uv__strdup(title);
- setproctitle(title);
+ setproctitle("%s", title);
return 0;
}
diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.c b/Utilities/cmlibuv/src/unix/os390-syscalls.c
new file mode 100644
index 0000000..2bf3b73
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/os390-syscalls.c
@@ -0,0 +1,334 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+
+#include "os390-syscalls.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <search.h>
+
+#define CW_CONDVAR 32
+
+#pragma linkage(BPX4CTW, OS)
+#pragma linkage(BPX1CTW, OS)
+
+static int number_of_epolls;
+static QUEUE global_epoll_queue;
+static uv_mutex_t global_epoll_lock;
+static uv_once_t once = UV_ONCE_INIT;
+
+int scandir(const char* maindir, struct dirent*** namelist,
+ int (*filter)(const struct dirent*),
+ int (*compar)(const struct dirent**,
+ const struct dirent **)) {
+ struct dirent** nl;
+ struct dirent* dirent;
+ unsigned count;
+ size_t allocated;
+ DIR* mdir;
+
+ nl = NULL;
+ count = 0;
+ allocated = 0;
+ mdir = opendir(maindir);
+ if (!mdir)
+ return -1;
+
+ while (1) {
+ dirent = readdir(mdir);
+ if (!dirent)
+ break;
+ if (!filter || filter(dirent)) {
+ struct dirent* copy;
+ copy = uv__malloc(sizeof(*copy));
+ if (!copy) {
+ while (count) {
+ dirent = nl[--count];
+ uv__free(dirent);
+ }
+ uv__free(nl);
+ closedir(mdir);
+ errno = ENOMEM;
+ return -1;
+ }
+ memcpy(copy, dirent, sizeof(*copy));
+
+ nl = uv__realloc(nl, sizeof(*copy) * (count + 1));
+ nl[count++] = copy;
+ }
+ }
+
+ qsort(nl, count, sizeof(struct dirent *),
+ (int (*)(const void *, const void *)) compar);
+
+ closedir(mdir);
+
+ *namelist = nl;
+ return count;
+}
+
+
+static unsigned int next_power_of_two(unsigned int val) {
+ val -= 1;
+ val |= val >> 1;
+ val |= val >> 2;
+ val |= val >> 4;
+ val |= val >> 8;
+ val |= val >> 16;
+ val += 1;
+ return val;
+}
+
+
+static void maybe_resize(uv__os390_epoll* lst, unsigned int len) {
+ unsigned int newsize;
+ unsigned int i;
+ struct pollfd* newlst;
+
+ if (len <= lst->size)
+ return;
+
+ newsize = next_power_of_two(len);
+ newlst = uv__realloc(lst->items, newsize * sizeof(lst->items[0]));
+
+ if (newlst == NULL)
+ abort();
+ for (i = lst->size; i < newsize; ++i)
+ newlst[i].fd = -1;
+
+ lst->items = newlst;
+ lst->size = newsize;
+}
+
+
+static void epoll_init() {
+ QUEUE_INIT(&global_epoll_queue);
+ if (uv_mutex_init(&global_epoll_lock))
+ abort();
+}
+
+
+uv__os390_epoll* epoll_create1(int flags) {
+ uv__os390_epoll* lst;
+
+ uv_once(&once, epoll_init);
+ uv_mutex_lock(&global_epoll_lock);
+ lst = uv__malloc(sizeof(*lst));
+ if (lst == -1)
+ return NULL;
+ QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member);
+ uv_mutex_unlock(&global_epoll_lock);
+
+ /* initialize list */
+ lst->size = 0;
+ lst->items = NULL;
+ return lst;
+}
+
+
+int epoll_ctl(uv__os390_epoll* lst,
+ int op,
+ int fd,
+ struct epoll_event *event) {
+ if(op == EPOLL_CTL_DEL) {
+ if (fd >= lst->size || lst->items[fd].fd == -1) {
+ errno = ENOENT;
+ return -1;
+ }
+ lst->items[fd].fd = -1;
+ } else if(op == EPOLL_CTL_ADD) {
+ maybe_resize(lst, fd + 1);
+ if (lst->items[fd].fd != -1) {
+ errno = EEXIST;
+ return -1;
+ }
+ lst->items[fd].fd = fd;
+ lst->items[fd].events = event->events;
+ } else if(op == EPOLL_CTL_MOD) {
+ if (fd >= lst->size || lst->items[fd].fd == -1) {
+ errno = ENOENT;
+ return -1;
+ }
+ lst->items[fd].events = event->events;
+ } else
+ abort();
+
+ return 0;
+}
+
+
+int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
+ int maxevents, int timeout) {
+ size_t size;
+ struct pollfd* pfds;
+ int pollret;
+ int reventcount;
+
+ uv_mutex_lock(&global_epoll_lock);
+ uv_mutex_unlock(&global_epoll_lock);
+ size = lst->size;
+ pfds = lst->items;
+ pollret = poll(pfds, size, timeout);
+ if(pollret == -1)
+ return pollret;
+
+ reventcount = 0;
+ for (int i = 0; i < lst->size && i < maxevents; ++i) {
+ struct epoll_event ev;
+
+ ev.events = 0;
+ ev.fd = pfds[i].fd;
+ if(!pfds[i].revents)
+ continue;
+
+ if(pfds[i].revents & POLLRDNORM)
+ ev.events = ev.events | POLLIN;
+
+ if(pfds[i].revents & POLLWRNORM)
+ ev.events = ev.events | POLLOUT;
+
+ if(pfds[i].revents & POLLHUP)
+ ev.events = ev.events | POLLHUP;
+
+ pfds[i].revents = 0;
+ events[reventcount++] = ev;
+ }
+
+ return reventcount;
+}
+
+
+int epoll_file_close(int fd) {
+ QUEUE* q;
+
+ uv_once(&once, epoll_init);
+ uv_mutex_lock(&global_epoll_lock);
+ QUEUE_FOREACH(q, &global_epoll_queue) {
+ uv__os390_epoll* lst;
+
+ lst = QUEUE_DATA(q, uv__os390_epoll, member);
+ if (fd < lst->size && lst->items != NULL && lst->items[fd].fd != -1)
+ lst->items[fd].fd = -1;
+ }
+
+ uv_mutex_unlock(&global_epoll_lock);
+ return 0;
+}
+
+void epoll_queue_close(uv__os390_epoll* lst) {
+ uv_mutex_lock(&global_epoll_lock);
+ QUEUE_REMOVE(&lst->member);
+ uv_mutex_unlock(&global_epoll_lock);
+ uv__free(lst->items);
+ lst->items = NULL;
+}
+
+
+int nanosleep(const struct timespec* req, struct timespec* rem) {
+ unsigned nano;
+ unsigned seconds;
+ unsigned events;
+ unsigned secrem;
+ unsigned nanorem;
+ int rv;
+ int rc;
+ int rsn;
+
+ nano = (int)req->tv_nsec;
+ seconds = req->tv_sec;
+ events = CW_CONDVAR;
+
+#if defined(_LP64)
+ BPX4CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn);
+#else
+ BPX1CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn);
+#endif
+
+ assert(rv == -1 && errno == EAGAIN);
+
+ if(rem != NULL) {
+ rem->tv_nsec = nanorem;
+ rem->tv_sec = secrem;
+ }
+
+ return 0;
+}
+
+
+char* mkdtemp(char* path) {
+ static const char* tempchars =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ static const size_t num_chars = 62;
+ static const size_t num_x = 6;
+ char *ep, *cp;
+ unsigned int tries, i;
+ size_t len;
+ uint64_t v;
+ int fd;
+ int retval;
+ int saved_errno;
+
+ len = strlen(path);
+ ep = path + len;
+ if (len < num_x || strncmp(ep - num_x, "XXXXXX", num_x)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd == -1)
+ return NULL;
+
+ tries = TMP_MAX;
+ retval = -1;
+ do {
+ if (read(fd, &v, sizeof(v)) != sizeof(v))
+ break;
+
+ cp = ep - num_x;
+ for (i = 0; i < num_x; i++) {
+ *cp++ = tempchars[v % num_chars];
+ v /= num_chars;
+ }
+
+ if (mkdir(path, S_IRWXU) == 0) {
+ retval = 0;
+ break;
+ }
+ else if (errno != EEXIST)
+ break;
+ } while (--tries);
+
+ saved_errno = errno;
+ uv__close(fd);
+ if (tries == 0) {
+ errno = EEXIST;
+ return NULL;
+ }
+
+ if (retval == -1) {
+ errno = saved_errno;
+ return NULL;
+ }
+
+ return path;
+}
diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.h b/Utilities/cmlibuv/src/unix/os390-syscalls.h
new file mode 100644
index 0000000..61a7cee
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/os390-syscalls.h
@@ -0,0 +1,69 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+
+#ifndef UV_OS390_SYSCALL_H_
+#define UV_OS390_SYSCALL_H_
+
+#include "uv.h"
+#include "internal.h"
+#include <dirent.h>
+#include <poll.h>
+#include <pthread.h>
+
+#define EPOLL_CTL_ADD 1
+#define EPOLL_CTL_DEL 2
+#define EPOLL_CTL_MOD 3
+#define MAX_EPOLL_INSTANCES 256
+#define MAX_ITEMS_PER_EPOLL 1024
+
+#define UV__O_CLOEXEC 0x80000
+#define UV__EPOLL_CLOEXEC UV__O_CLOEXEC
+#define UV__EPOLL_CTL_ADD EPOLL_CTL_ADD
+#define UV__EPOLL_CTL_DEL EPOLL_CTL_DEL
+#define UV__EPOLL_CTL_MOD EPOLL_CTL_MOD
+
+struct epoll_event {
+ int events;
+ int fd;
+};
+
+typedef struct {
+ QUEUE member;
+ struct pollfd* items;
+ unsigned long size;
+} uv__os390_epoll;
+
+/* epoll api */
+uv__os390_epoll* epoll_create1(int flags);
+int epoll_ctl(uv__os390_epoll* ep, int op, int fd, struct epoll_event *event);
+int epoll_wait(uv__os390_epoll* ep, struct epoll_event *events, int maxevents, int timeout);
+int epoll_file_close(int fd);
+
+/* utility functions */
+int nanosleep(const struct timespec* req, struct timespec* rem);
+int scandir(const char* maindir, struct dirent*** namelist,
+ int (*filter)(const struct dirent *),
+ int (*compar)(const struct dirent **,
+ const struct dirent **));
+char *mkdtemp(char* path);
+
+#endif /* UV_OS390_SYSCALL_H_ */
diff --git a/Utilities/cmlibuv/src/unix/os390.c b/Utilities/cmlibuv/src/unix/os390.c
index bcdbc4b..be325a9 100644
--- a/Utilities/cmlibuv/src/unix/os390.c
+++ b/Utilities/cmlibuv/src/unix/os390.c
@@ -20,6 +20,628 @@
*/
#include "internal.h"
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <utmpx.h>
+#include <unistd.h>
+#include <sys/ps.h>
+#if defined(__clang__)
+#include "csrsic.h"
+#else
+#include "//'SYS1.SAMPLIB(CSRSIC)'"
+#endif
+
+#define CVT_PTR 0x10
+#define CSD_OFFSET 0x294
+
+/*
+ Long-term average CPU service used by this logical partition,
+ in millions of service units per hour. If this value is above
+ the partition's defined capacity, the partition will be capped.
+ It is calculated using the physical CPU adjustment factor
+ (RCTPCPUA) so it may not match other measures of service which
+ are based on the logical CPU adjustment factor. It is available
+ if the hardware supports LPAR cluster.
+*/
+#define RCTLACS_OFFSET 0xC4
+
+/* 32-bit count of alive CPUs. This includes both CPs and IFAs */
+#define CSD_NUMBER_ONLINE_CPUS 0xD4
+
+/* Address of system resources manager (SRM) control table */
+#define CVTOPCTP_OFFSET 0x25C
+
+/* Address of the RCT table */
+#define RMCTRCT_OFFSET 0xE4
+
+/* Address of the rsm control and enumeration area. */
+#define CVTRCEP_OFFSET 0x490
+
+/*
+ Number of frames currently available to system.
+ Excluded are frames backing perm storage, frames offline, and bad frames.
+*/
+#define RCEPOOL_OFFSET 0x004
+
+/* Total number of frames currently on all available frame queues. */
+#define RCEAFC_OFFSET 0x088
+
+/* CPC model length from the CSRSI Service. */
+#define CPCMODEL_LENGTH 16
+
+/* Thread Entry constants */
+#define PGTH_CURRENT 1
+#define PGTH_LEN 26
+#define PGTHAPATH 0x20
+#pragma linkage(BPX4GTH, OS)
+#pragma linkage(BPX1GTH, OS)
+
+typedef unsigned data_area_ptr_assign_type;
+
+typedef union {
+ struct {
+#if defined(_LP64)
+ data_area_ptr_assign_type lower;
+#endif
+ data_area_ptr_assign_type assign;
+ };
+ char* deref;
+} data_area_ptr;
+
+
+void uv_loadavg(double avg[3]) {
+ /* TODO: implement the following */
+ avg[0] = 0;
+ avg[1] = 0;
+ avg[2] = 0;
+}
+
+
+int uv__platform_loop_init(uv_loop_t* loop) {
+ uv__os390_epoll* ep;
+
+ ep = epoll_create1(UV__EPOLL_CLOEXEC);
+ loop->ep = ep;
+ if (ep == NULL)
+ return -errno;
+
+ return 0;
+}
+
+
+void uv__platform_loop_delete(uv_loop_t* loop) {
+ if (loop->ep != NULL) {
+ epoll_queue_close(loop->ep);
+ loop->ep = NULL;
+ }
+}
+
+
+uint64_t uv__hrtime(uv_clocktype_t type) {
+ struct timeval time;
+ gettimeofday(&time, NULL);
+ return (uint64_t) time.tv_sec * 1e9 + time.tv_usec * 1e3;
+}
+
+
+/*
+ Get the exe path using the thread entry information
+ in the address space.
+*/
+static int getexe(const int pid, char* buf, size_t len) {
+ struct {
+ int pid;
+ int thid[2];
+ char accesspid;
+ char accessthid;
+ char asid[2];
+ char loginname[8];
+ char flag;
+ char len;
+ } Input_data;
+
+ union {
+ struct {
+ char gthb[4];
+ int pid;
+ int thid[2];
+ char accesspid;
+ char accessthid[3];
+ int lenused;
+ int offsetProcess;
+ int offsetConTTY;
+ int offsetPath;
+ int offsetCommand;
+ int offsetFileData;
+ int offsetThread;
+ } Output_data;
+ char buf[2048];
+ } Output_buf;
+
+ struct Output_path_type {
+ char gthe[4];
+ short int len;
+ char path[1024];
+ };
+
+ int Input_length;
+ int Output_length;
+ void* Input_address;
+ void* Output_address;
+ struct Output_path_type* Output_path;
+ int rv;
+ int rc;
+ int rsn;
+
+ Input_length = PGTH_LEN;
+ Output_length = sizeof(Output_buf);
+ Output_address = &Output_buf;
+ Input_address = &Input_data;
+ memset(&Input_data, 0, sizeof Input_data);
+ Input_data.flag |= PGTHAPATH;
+ Input_data.pid = pid;
+ Input_data.accesspid = PGTH_CURRENT;
+
+#ifdef _LP64
+ BPX4GTH(&Input_length,
+ &Input_address,
+ &Output_length,
+ &Output_address,
+ &rv,
+ &rc,
+ &rsn);
+#else
+ BPX1GTH(&Input_length,
+ &Input_address,
+ &Output_length,
+ &Output_address,
+ &rv,
+ &rc,
+ &rsn);
+#endif
+
+ if (rv == -1) {
+ errno = rc;
+ return -1;
+ }
+
+ /* Check highest byte to ensure data availability */
+ assert(((Output_buf.Output_data.offsetPath >>24) & 0xFF) == 'A');
+
+ /* Get the offset from the lowest 3 bytes */
+ Output_path = (char*)(&Output_buf) +
+ (Output_buf.Output_data.offsetPath & 0x00FFFFFF);
+
+ if (Output_path->len >= len) {
+ errno = ENOBUFS;
+ return -1;
+ }
+
+ strncpy(buf, Output_path->path, len);
+
+ return 0;
+}
+
+
+/*
+ * We could use a static buffer for the path manipulations that we need outside
+ * of the function, but this function could be called by multiple consumers and
+ * we don't want to potentially create a race condition in the use of snprintf.
+ * There is no direct way of getting the exe path in zOS - either through /procfs
+ * or through some libc APIs. The below approach is to parse the argv[0]'s pattern
+ * and use it in conjunction with PATH environment variable to craft one.
+ */
+int uv_exepath(char* buffer, size_t* size) {
+ int res;
+ char args[PATH_MAX];
+ char abspath[PATH_MAX];
+ size_t abspath_size;
+ int pid;
+
+ if (buffer == NULL || size == NULL || *size == 0)
+ return -EINVAL;
+
+ pid = getpid();
+ res = getexe(pid, args, sizeof(args));
+ if (res < 0)
+ return -EINVAL;
+
+ /*
+ * Possibilities for args:
+ * i) an absolute path such as: /home/user/myprojects/nodejs/node
+ * ii) a relative path such as: ./node or ../myprojects/nodejs/node
+ * iii) a bare filename such as "node", after exporting PATH variable
+ * to its location.
+ */
+
+ /* Case i) and ii) absolute or relative paths */
+ if (strchr(args, '/') != NULL) {
+ if (realpath(args, abspath) != abspath)
+ return -errno;
+
+ abspath_size = strlen(abspath);
+
+ *size -= 1;
+ if (*size > abspath_size)
+ *size = abspath_size;
+
+ memcpy(buffer, abspath, *size);
+ buffer[*size] = '\0';
+
+ return 0;
+ } else {
+ /* Case iii). Search PATH environment variable */
+ char trypath[PATH_MAX];
+ char* clonedpath = NULL;
+ char* token = NULL;
+ char* path = getenv("PATH");
+
+ if (path == NULL)
+ return -EINVAL;
+
+ clonedpath = uv__strdup(path);
+ if (clonedpath == NULL)
+ return -ENOMEM;
+
+ token = strtok(clonedpath, ":");
+ while (token != NULL) {
+ snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args);
+ if (realpath(trypath, abspath) == abspath) {
+ /* Check the match is executable */
+ if (access(abspath, X_OK) == 0) {
+ abspath_size = strlen(abspath);
+
+ *size -= 1;
+ if (*size > abspath_size)
+ *size = abspath_size;
+
+ memcpy(buffer, abspath, *size);
+ buffer[*size] = '\0';
+
+ uv__free(clonedpath);
+ return 0;
+ }
+ }
+ token = strtok(NULL, ":");
+ }
+ uv__free(clonedpath);
+
+ /* Out of tokens (path entries), and no match found */
+ return -EINVAL;
+ }
+}
+
+
+uint64_t uv_get_free_memory(void) {
+ uint64_t freeram;
+
+ data_area_ptr cvt = {0};
+ data_area_ptr rcep = {0};
+ cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR);
+ rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET);
+ freeram = *((uint64_t*)(rcep.deref + RCEAFC_OFFSET)) * 4;
+ return freeram;
+}
+
+
+uint64_t uv_get_total_memory(void) {
+ uint64_t totalram;
+
+ data_area_ptr cvt = {0};
+ data_area_ptr rcep = {0};
+ cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR);
+ rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET);
+ totalram = *((uint64_t*)(rcep.deref + RCEPOOL_OFFSET)) * 4;
+ return totalram;
+}
+
+
+int uv_resident_set_memory(size_t* rss) {
+ W_PSPROC buf;
+
+ memset(&buf, 0, sizeof(buf));
+ if (w_getpsent(0, &buf, sizeof(W_PSPROC)) == -1)
+ return -EINVAL;
+
+ *rss = buf.ps_size;
+ return 0;
+}
+
+
+int uv_uptime(double* uptime) {
+ struct utmpx u ;
+ struct utmpx *v;
+ time64_t t;
+
+ u.ut_type = BOOT_TIME;
+ v = getutxid(&u);
+ if (v == NULL)
+ return -1;
+ *uptime = difftime64(time64(&t), v->ut_tv.tv_sec);
+ return 0;
+}
+
+
+int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
+ uv_cpu_info_t* cpu_info;
+ int result;
+ int idx;
+ siv1v2 info;
+ data_area_ptr cvt = {0};
+ data_area_ptr csd = {0};
+ data_area_ptr rmctrct = {0};
+ data_area_ptr cvtopctp = {0};
+ int cpu_usage_avg;
+
+ cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR);
+
+ csd.assign = *((data_area_ptr_assign_type *) (cvt.deref + CSD_OFFSET));
+ cvtopctp.assign = *((data_area_ptr_assign_type *) (cvt.deref + CVTOPCTP_OFFSET));
+ rmctrct.assign = *((data_area_ptr_assign_type *) (cvtopctp.deref + RMCTRCT_OFFSET));
+
+ *count = *((int*) (csd.deref + CSD_NUMBER_ONLINE_CPUS));
+ cpu_usage_avg = *((unsigned short int*) (rmctrct.deref + RCTLACS_OFFSET));
+
+ *cpu_infos = uv__malloc(*count * sizeof(uv_cpu_info_t));
+ if (!*cpu_infos)
+ return -ENOMEM;
+
+ cpu_info = *cpu_infos;
+ idx = 0;
+ while (idx < *count) {
+ cpu_info->speed = *(int*)(info.siv1v2si22v1.si22v1cpucapability);
+ cpu_info->model = uv__malloc(CPCMODEL_LENGTH + 1);
+ memset(cpu_info->model, '\0', CPCMODEL_LENGTH + 1);
+ memcpy(cpu_info->model, info.siv1v2si11v1.si11v1cpcmodel, CPCMODEL_LENGTH);
+ cpu_info->cpu_times.user = cpu_usage_avg;
+ /* TODO: implement the following */
+ cpu_info->cpu_times.sys = 0;
+ cpu_info->cpu_times.idle = 0;
+ cpu_info->cpu_times.irq = 0;
+ cpu_info->cpu_times.nice = 0;
+ ++cpu_info;
+ ++idx;
+ }
+
+ return 0;
+}
+
+
+void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
+ for (int i = 0; i < count; ++i)
+ uv__free(cpu_infos[i].model);
+ uv__free(cpu_infos);
+}
+
+
+static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
+ int* count) {
+ uv_interface_address_t* address;
+ int sockfd;
+ int maxsize;
+ __net_ifconf6header_t ifc;
+ __net_ifconf6entry_t* ifr;
+ __net_ifconf6entry_t* p;
+ __net_ifconf6entry_t flg;
+
+ *count = 0;
+ /* Assume maximum buffer size allowable */
+ maxsize = 16384;
+
+ if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)))
+ return -errno;
+
+ ifc.__nif6h_version = 1;
+ ifc.__nif6h_buflen = maxsize;
+ ifc.__nif6h_buffer = uv__calloc(1, maxsize);;
+
+ if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) {
+ uv__close(sockfd);
+ return -errno;
+ }
+
+
+ *count = 0;
+ ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer);
+ while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) {
+ p = ifr;
+ ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen);
+
+ if (!(p->__nif6e_addr.sin6_family == AF_INET6 ||
+ p->__nif6e_addr.sin6_family == AF_INET))
+ continue;
+
+ if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE))
+ continue;
+
+ ++(*count);
+ }
+
+ /* Alloc the return interface structs */
+ *addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
+ if (!(*addresses)) {
+ uv__close(sockfd);
+ return -ENOMEM;
+ }
+ address = *addresses;
+
+ ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer);
+ while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) {
+ p = ifr;
+ ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen);
+
+ if (!(p->__nif6e_addr.sin6_family == AF_INET6 ||
+ p->__nif6e_addr.sin6_family == AF_INET))
+ continue;
+
+ if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE))
+ continue;
+
+ /* All conditions above must match count loop */
+
+ address->name = uv__strdup(p->__nif6e_name);
+
+ if (p->__nif6e_addr.sin6_family == AF_INET6)
+ address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr);
+ else
+ address->address.address4 = *((struct sockaddr_in*) &p->__nif6e_addr);
+
+ /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */
+
+ address->is_internal = flg.__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0;
+
+ address++;
+ }
+
+ uv__close(sockfd);
+ return 0;
+}
+
+
+int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
+ uv_interface_address_t* address;
+ int sockfd;
+ int maxsize;
+ struct ifconf ifc;
+ struct ifreq flg;
+ struct ifreq* ifr;
+ struct ifreq* p;
+ int count_v6;
+
+ /* get the ipv6 addresses first */
+ uv_interface_address_t* addresses_v6;
+ uv__interface_addresses_v6(&addresses_v6, &count_v6);
+
+ /* now get the ipv4 addresses */
+ *count = 0;
+
+ /* Assume maximum buffer size allowable */
+ maxsize = 16384;
+
+ sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+ if (0 > sockfd)
+ return -errno;
+
+ ifc.ifc_req = uv__calloc(1, maxsize);
+ ifc.ifc_len = maxsize;
+ if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
+ uv__close(sockfd);
+ return -errno;
+ }
+
+#define MAX(a,b) (((a)>(b))?(a):(b))
+#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
+
+ /* Count all up and running ipv4/ipv6 addresses */
+ ifr = ifc.ifc_req;
+ while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
+ p = ifr;
+ ifr = (struct ifreq*)
+ ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
+
+ if (!(p->ifr_addr.sa_family == AF_INET6 ||
+ p->ifr_addr.sa_family == AF_INET))
+ continue;
+
+ memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
+ if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
+ uv__close(sockfd);
+ return -errno;
+ }
+
+ if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
+ continue;
+
+ (*count)++;
+ }
+
+ /* Alloc the return interface structs */
+ *addresses = uv__malloc((*count + count_v6) *
+ sizeof(uv_interface_address_t));
+
+ if (!(*addresses)) {
+ uv__close(sockfd);
+ return -ENOMEM;
+ }
+ address = *addresses;
+
+ /* copy over the ipv6 addresses */
+ memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t));
+ address += count_v6;
+ *count += count_v6;
+ uv__free(addresses_v6);
+
+ ifr = ifc.ifc_req;
+ while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
+ p = ifr;
+ ifr = (struct ifreq*)
+ ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
+
+ if (!(p->ifr_addr.sa_family == AF_INET6 ||
+ p->ifr_addr.sa_family == AF_INET))
+ continue;
+
+ memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
+ if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
+ uv__close(sockfd);
+ return -ENOSYS;
+ }
+
+ if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
+ continue;
+
+ /* All conditions above must match count loop */
+
+ address->name = uv__strdup(p->ifr_name);
+
+ if (p->ifr_addr.sa_family == AF_INET6) {
+ address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
+ } else {
+ address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
+ }
+
+ address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
+ address++;
+ }
+
+#undef ADDR_SIZE
+#undef MAX
+
+ uv__close(sockfd);
+ return 0;
+}
+
+
+void uv_free_interface_addresses(uv_interface_address_t* addresses,
+ int count) {
+ int i;
+ for (i = 0; i < count; ++i)
+ uv__free(addresses[i].name);
+ uv__free(addresses);
+}
+
+
+void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
+ struct epoll_event* events;
+ struct epoll_event dummy;
+ uintptr_t i;
+ uintptr_t nfds;
+
+ assert(loop->watchers != NULL);
+
+ events = (struct epoll_event*) loop->watchers[loop->nwatchers];
+ nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
+ if (events != NULL)
+ /* Invalidate events with same file descriptor */
+ for (i = 0; i < nfds; i++)
+ if ((int) events[i].fd == fd)
+ events[i].fd = -1;
+
+ /* Remove the file descriptor from the epoll. */
+ if (loop->ep != NULL)
+ epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, &dummy);
+}
+
int uv__io_check_fd(uv_loop_t* loop, int fd) {
struct pollfd p[1];
@@ -40,3 +662,204 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
return 0;
}
+
+
+void uv__fs_event_close(uv_fs_event_t* handle) {
+ UNREACHABLE();
+}
+
+
+int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
+ return -ENOSYS;
+}
+
+
+int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
+ const char* filename, unsigned int flags) {
+ return -ENOSYS;
+}
+
+
+int uv_fs_event_stop(uv_fs_event_t* handle) {
+ return -ENOSYS;
+}
+
+
+void uv__io_poll(uv_loop_t* loop, int timeout) {
+ static const int max_safe_timeout = 1789569;
+ struct epoll_event events[1024];
+ struct epoll_event* pe;
+ struct epoll_event e;
+ int real_timeout;
+ QUEUE* q;
+ uv__io_t* w;
+ uint64_t base;
+ int count;
+ int nfds;
+ int fd;
+ int op;
+ int i;
+
+ if (loop->nfds == 0) {
+ assert(QUEUE_EMPTY(&loop->watcher_queue));
+ return;
+ }
+
+ while (!QUEUE_EMPTY(&loop->watcher_queue)) {
+ uv_stream_t* stream;
+
+ q = QUEUE_HEAD(&loop->watcher_queue);
+ QUEUE_REMOVE(q);
+ QUEUE_INIT(q);
+ w = QUEUE_DATA(q, uv__io_t, watcher_queue);
+
+ assert(w->pevents != 0);
+ assert(w->fd >= 0);
+
+ stream= container_of(w, uv_stream_t, io_watcher);
+
+ assert(w->fd < (int) loop->nwatchers);
+
+ e.events = w->pevents;
+ e.fd = w->fd;
+
+ if (w->events == 0)
+ op = UV__EPOLL_CTL_ADD;
+ else
+ op = UV__EPOLL_CTL_MOD;
+
+ /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
+ * events, skip the syscall and squelch the events after epoll_wait().
+ */
+ if (epoll_ctl(loop->ep, op, w->fd, &e)) {
+ if (errno != EEXIST)
+ abort();
+
+ assert(op == UV__EPOLL_CTL_ADD);
+
+ /* We've reactivated a file descriptor that's been watched before. */
+ if (epoll_ctl(loop->ep, UV__EPOLL_CTL_MOD, w->fd, &e))
+ abort();
+ }
+
+ w->events = w->pevents;
+ }
+
+ assert(timeout >= -1);
+ base = loop->time;
+ count = 48; /* Benchmarks suggest this gives the best throughput. */
+ real_timeout = timeout;
+ int nevents = 0;
+
+ nfds = 0;
+ for (;;) {
+ if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
+ timeout = max_safe_timeout;
+
+ nfds = epoll_wait(loop->ep, events,
+ ARRAY_SIZE(events), timeout);
+
+ /* Update loop->time unconditionally. It's tempting to skip the update when
+ * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
+ * operating system didn't reschedule our process while in the syscall.
+ */
+ base = loop->time;
+ SAVE_ERRNO(uv__update_time(loop));
+ if (nfds == 0) {
+ assert(timeout != -1);
+ timeout = real_timeout - timeout;
+ if (timeout > 0)
+ continue;
+
+ return;
+ }
+
+ if (nfds == -1) {
+
+ if (errno != EINTR)
+ abort();
+
+ if (timeout == -1)
+ continue;
+
+ if (timeout == 0)
+ return;
+
+ /* Interrupted by a signal. Update timeout and poll again. */
+ goto update_timeout;
+ }
+
+
+ assert(loop->watchers != NULL);
+ loop->watchers[loop->nwatchers] = (void*) events;
+ loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
+ for (i = 0; i < nfds; i++) {
+ pe = events + i;
+ fd = pe->fd;
+
+ /* Skip invalidated events, see uv__platform_invalidate_fd */
+ if (fd == -1)
+ continue;
+
+ assert(fd >= 0);
+ assert((unsigned) fd < loop->nwatchers);
+
+ w = loop->watchers[fd];
+
+ if (w == NULL) {
+ /* File descriptor that we've stopped watching, disarm it.
+ *
+ * Ignore all errors because we may be racing with another thread
+ * when the file descriptor is closed.
+ */
+ epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, pe);
+ continue;
+ }
+
+ /* Give users only events they're interested in. Prevents spurious
+ * callbacks when previous callback invocation in this loop has stopped
+ * the current watcher. Also, filters out events that users has not
+ * requested us to watch.
+ */
+ pe->events &= w->pevents | POLLERR | POLLHUP;
+
+ if (pe->events == POLLERR || pe->events == POLLHUP)
+ pe->events |= w->pevents & (POLLIN | POLLOUT);
+
+ if (pe->events != 0) {
+ w->cb(loop, w, pe->events);
+ nevents++;
+ }
+ }
+ loop->watchers[loop->nwatchers] = NULL;
+ loop->watchers[loop->nwatchers + 1] = NULL;
+
+ if (nevents != 0) {
+ if (nfds == ARRAY_SIZE(events) && --count != 0) {
+ /* Poll for more events but don't block this time. */
+ timeout = 0;
+ continue;
+ }
+ return;
+ }
+
+ if (timeout == 0)
+ return;
+
+ if (timeout == -1)
+ continue;
+
+update_timeout:
+ assert(timeout > 0);
+
+ real_timeout -= (loop->time - base);
+ if (real_timeout <= 0)
+ return;
+
+ timeout = real_timeout;
+ }
+}
+
+void uv__set_process_title(const char* title) {
+ /* do nothing */
+}
diff --git a/Utilities/cmlibuv/src/unix/poll.c b/Utilities/cmlibuv/src/unix/poll.c
index 4c0d478..370994b 100644
--- a/Utilities/cmlibuv/src/unix/poll.c
+++ b/Utilities/cmlibuv/src/unix/poll.c
@@ -92,7 +92,7 @@ static void uv__poll_stop(uv_poll_t* handle) {
int uv_poll_stop(uv_poll_t* handle) {
- assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
+ assert(!uv__is_closing(handle));
uv__poll_stop(handle);
return 0;
}
@@ -102,7 +102,7 @@ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {
int events;
assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
- assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
+ assert(!uv__is_closing(handle));
uv__poll_stop(handle);
diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c
index 45f5b45..f2fe305 100644
--- a/Utilities/cmlibuv/src/unix/process.c
+++ b/Utilities/cmlibuv/src/unix/process.c
@@ -323,7 +323,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
}
if (fd == use_fd)
- uv__cloexec(use_fd, 0);
+ uv__cloexec_fcntl(use_fd, 0);
else
fd = dup2(use_fd, fd);
@@ -333,7 +333,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
}
if (fd <= 2)
- uv__nonblock(fd, 0);
+ uv__nonblock_fcntl(fd, 0);
if (close_fd >= stdio_count)
uv__close(close_fd);
diff --git a/Utilities/cmlibuv/src/unix/proctitle.c b/Utilities/cmlibuv/src/unix/proctitle.c
index 08d875f..9160f7e 100644
--- a/Utilities/cmlibuv/src/unix/proctitle.c
+++ b/Utilities/cmlibuv/src/unix/proctitle.c
@@ -48,9 +48,15 @@ char** uv_setup_args(int argc, char** argv) {
for (i = 0; i < argc; i++)
size += strlen(argv[i]) + 1;
+#if defined(__MVS__)
+ /* argv is not adjacent. So just use argv[0] */
+ process_title.str = argv[0];
+ process_title.len = strlen(argv[0]);
+#else
process_title.str = argv[0];
process_title.len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[0];
assert(process_title.len + 1 == size); /* argv memory should be adjacent. */
+#endif
/* Add space for the argv pointers. */
size += (argc + 1) * sizeof(char*);
diff --git a/Utilities/cmlibuv/src/unix/pthread-barrier.c b/Utilities/cmlibuv/src/unix/pthread-barrier.c
index f57bf25..b6e604d 100644
--- a/Utilities/cmlibuv/src/unix/pthread-barrier.c
+++ b/Utilities/cmlibuv/src/unix/pthread-barrier.c
@@ -73,7 +73,8 @@ int pthread_barrier_wait(pthread_barrier_t* barrier) {
if (++b->in == b->threshold) {
b->in = 0;
b->out = b->threshold - 1;
- assert(pthread_cond_signal(&b->cond) == 0);
+ rc = pthread_cond_signal(&b->cond);
+ assert(rc == 0);
pthread_mutex_unlock(&b->mutex);
return PTHREAD_BARRIER_SERIAL_THREAD;
diff --git a/Utilities/cmlibuv/src/unix/signal.c b/Utilities/cmlibuv/src/unix/signal.c
index d82b9b7..dbd8f86 100644
--- a/Utilities/cmlibuv/src/unix/signal.c
+++ b/Utilities/cmlibuv/src/unix/signal.c
@@ -43,7 +43,7 @@ static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2);
static void uv__signal_stop(uv_signal_t* handle);
-static pthread_once_t uv__signal_global_init_guard = PTHREAD_ONCE_INIT;
+static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT;
static struct uv__signal_tree_s uv__signal_tree =
RB_INITIALIZER(uv__signal_tree);
static int uv__signal_lock_pipefd[2];
@@ -64,7 +64,7 @@ static void uv__signal_global_init(void) {
void uv__signal_global_once_init(void) {
- pthread_once(&uv__signal_global_init_guard, uv__signal_global_init);
+ uv_once(&uv__signal_global_init_guard, uv__signal_global_init);
}
@@ -290,7 +290,7 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
sigset_t saved_sigmask;
int err;
- assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
+ assert(!uv__is_closing(handle));
/* If the user supplies signum == 0, then return an error already. If the
* signum is otherwise invalid then uv__signal_register will find out
@@ -434,7 +434,7 @@ static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
int uv_signal_stop(uv_signal_t* handle) {
- assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
+ assert(!uv__is_closing(handle));
uv__signal_stop(handle);
return 0;
}
diff --git a/Utilities/cmlibuv/src/unix/stream.c b/Utilities/cmlibuv/src/unix/stream.c
index d20d0bc..7059df1 100644
--- a/Utilities/cmlibuv/src/unix/stream.c
+++ b/Utilities/cmlibuv/src/unix/stream.c
@@ -390,7 +390,7 @@ failed_malloc:
int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
-#if defined(__APPLE__)
+#if defined(__APPLE__) || defined(__MVS__)
int enable;
#endif
@@ -409,7 +409,7 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
return -errno;
}
-#if defined(__APPLE__)
+#if defined(__APPLE__) || defined(__MVS__)
enable = 1;
if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) &&
errno != ENOTSOCK &&
@@ -1194,6 +1194,30 @@ static void uv__read(uv_stream_t* stream) {
return;
}
}
+
+#if defined(__MVS__)
+ if (is_ipc && msg.msg_controllen > 0) {
+ uv_buf_t blankbuf;
+ int nread;
+ struct iovec *old;
+
+ blankbuf.base = 0;
+ blankbuf.len = 0;
+ old = msg.msg_iov;
+ msg.msg_iov = (struct iovec*) &blankbuf;
+ nread = 0;
+ do {
+ nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0);
+ err = uv__stream_recv_cmsg(stream, &msg);
+ if (err != 0) {
+ stream->read_cb(stream, err, &buf);
+ msg.msg_iov = old;
+ return;
+ }
+ } while (nread == 0 && msg.msg_controllen > 0);
+ msg.msg_iov = old;
+ }
+#endif
stream->read_cb(stream, nread, &buf);
/* Return if we didn't fill the buffer, there is no more data to read. */
@@ -1221,8 +1245,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
if (!(stream->flags & UV_STREAM_WRITABLE) ||
stream->flags & UV_STREAM_SHUT ||
stream->flags & UV_STREAM_SHUTTING ||
- stream->flags & UV_CLOSED ||
- stream->flags & UV_CLOSING) {
+ uv__is_closing(stream)) {
return -ENOTCONN;
}
diff --git a/Utilities/cmlibuv/src/unix/sunos.c b/Utilities/cmlibuv/src/unix/sunos.c
index 3e7a759..14c58af 100644
--- a/Utilities/cmlibuv/src/unix/sunos.c
+++ b/Utilities/cmlibuv/src/unix/sunos.c
@@ -28,6 +28,10 @@
#include <assert.h>
#include <errno.h>
+#if !defined(SUNOS_NO_IFADDRS) && _XOPEN_SOURCE < 600
+#define SUNOS_NO_IFADDRS
+#endif
+
#ifndef SUNOS_NO_IFADDRS
# include <ifaddrs.h>
#endif
@@ -695,6 +699,11 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
uv__free(cpu_infos);
}
+#ifdef SUNOS_NO_IFADDRS
+int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
+ return -ENOSYS;
+}
+#else /* SUNOS_NO_IFADDRS */
/*
* Inspired By:
* https://blogs.oracle.com/paulie/entry/retrieving_mac_address_in_solaris
@@ -742,9 +751,6 @@ static int uv__set_phys_addr(uv_interface_address_t* address,
}
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
-#ifdef SUNOS_NO_IFADDRS
- return -ENOSYS;
-#else
uv_interface_address_t* address;
struct ifaddrs* addrs;
struct ifaddrs* ent;
@@ -805,9 +811,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
freeifaddrs(addrs);
return 0;
-#endif /* SUNOS_NO_IFADDRS */
}
-
+#endif /* SUNOS_NO_IFADDRS */
void uv_free_interface_addresses(uv_interface_address_t* addresses,
int count) {
diff --git a/Utilities/cmlibuv/src/unix/thread.c b/Utilities/cmlibuv/src/unix/thread.c
index 52989f7..a9b5e4c 100644
--- a/Utilities/cmlibuv/src/unix/thread.c
+++ b/Utilities/cmlibuv/src/unix/thread.c
@@ -40,28 +40,8 @@
#undef NANOSEC
#define NANOSEC ((uint64_t) 1e9)
-struct thread_ctx {
- void (*entry)(void* arg);
- void* arg;
-};
-
-
-static void* uv__thread_start(void *arg)
-{
- struct thread_ctx *ctx_p;
- struct thread_ctx ctx;
-
- ctx_p = arg;
- ctx = *ctx_p;
- uv__free(ctx_p);
- ctx.entry(ctx.arg);
-
- return 0;
-}
-
int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
- struct thread_ctx* ctx;
int err;
pthread_attr_t* attr;
#if defined(__APPLE__)
@@ -69,13 +49,6 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
struct rlimit lim;
#endif
- ctx = uv__malloc(sizeof(*ctx));
- if (ctx == NULL)
- return UV_ENOMEM;
-
- ctx->entry = entry;
- ctx->arg = arg;
-
/* On OSX threads other than the main thread are created with a reduced stack
* size by default, adjust it to RLIMIT_STACK.
*/
@@ -99,14 +72,11 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
attr = NULL;
#endif
- err = pthread_create(tid, attr, uv__thread_start, ctx);
+ err = pthread_create(tid, attr, (void*(*)(void*)) entry, arg);
if (attr != NULL)
pthread_attr_destroy(attr);
- if (err)
- uv__free(ctx);
-
return -err;
}
diff --git a/Utilities/cmlibuv/src/uv-common.c b/Utilities/cmlibuv/src/uv-common.c
index 46d9546..bc7d137 100644
--- a/Utilities/cmlibuv/src/uv-common.c
+++ b/Utilities/cmlibuv/src/uv-common.c
@@ -512,8 +512,18 @@ void uv__fs_scandir_cleanup(uv_fs_t* req) {
int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
uv__dirent_t** dents;
uv__dirent_t* dent;
+ unsigned int* nbufs;
- unsigned int* nbufs = uv__get_nbufs(req);
+ /* Check to see if req passed */
+ if (req->result < 0)
+ return req->result;
+
+ /* Ptr will be null if req was canceled or no files found */
+ if (!req->ptr)
+ return UV_EOF;
+
+ nbufs = uv__get_nbufs(req);
+ assert(nbufs);
dents = req->ptr;
diff --git a/Utilities/cmlibuv/src/win/core.c b/Utilities/cmlibuv/src/win/core.c
index 9d00afc..e84186d 100644
--- a/Utilities/cmlibuv/src/win/core.c
+++ b/Utilities/cmlibuv/src/win/core.c
@@ -35,10 +35,6 @@
#include "handle-inl.h"
#include "req-inl.h"
-
-static uv_loop_t default_loop_struct;
-static uv_loop_t* default_loop_ptr;
-
/* uv_once initialization guards */
static uv_once_t uv_init_guard_ = UV_ONCE_INIT;
diff --git a/Utilities/cmlibuv/src/win/error.c b/Utilities/cmlibuv/src/win/error.c
index c512f35..642d111 100644
--- a/Utilities/cmlibuv/src/win/error.c
+++ b/Utilities/cmlibuv/src/win/error.c
@@ -71,6 +71,7 @@ int uv_translate_sys_error(int sys_errno) {
switch (sys_errno) {
case ERROR_NOACCESS: return UV_EACCES;
case WSAEACCES: return UV_EACCES;
+ case ERROR_ELEVATION_REQUIRED: return UV_EACCES;
case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE;
case WSAEADDRINUSE: return UV_EADDRINUSE;
case WSAEADDRNOTAVAIL: return UV_EADDRNOTAVAIL;
diff --git a/Utilities/cmlibuv/src/win/fs-event.c b/Utilities/cmlibuv/src/win/fs-event.c
index 03e4adc..05fc1d0 100644
--- a/Utilities/cmlibuv/src/win/fs-event.c
+++ b/Utilities/cmlibuv/src/win/fs-event.c
@@ -188,7 +188,6 @@ int uv_fs_event_start(uv_fs_event_t* handle,
if (is_path_dir) {
/* path is a directory, so that's the directory that we will watch. */
- handle->dirw = pathw;
dir_to_watch = pathw;
} else {
/*
@@ -274,6 +273,8 @@ int uv_fs_event_start(uv_fs_event_t* handle,
goto error;
}
+ assert(is_path_dir ? pathw != NULL : pathw == NULL);
+ handle->dirw = pathw;
handle->req_pending = 1;
return 0;
diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c
index f1711ac..6902d4f 100644
--- a/Utilities/cmlibuv/src/win/fs.c
+++ b/Utilities/cmlibuv/src/win/fs.c
@@ -123,7 +123,7 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
const char* new_path, const int copy_path) {
char* buf;
char* pos;
- ssize_t buf_sz = 0, path_len, pathw_len = 0, new_pathw_len = 0;
+ ssize_t buf_sz = 0, path_len = 0, pathw_len = 0, new_pathw_len = 0;
/* new_path can only be set if path is also set. */
assert(new_path == NULL || path != NULL);
@@ -403,7 +403,6 @@ void fs__open(uv_fs_t* req) {
switch (flags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
case _O_RDONLY:
access = FILE_GENERIC_READ;
- attributes |= FILE_FLAG_BACKUP_SEMANTICS;
break;
case _O_WRONLY:
access = FILE_GENERIC_WRITE;
@@ -418,7 +417,6 @@ void fs__open(uv_fs_t* req) {
if (flags & _O_APPEND) {
access &= ~FILE_WRITE_DATA;
access |= FILE_APPEND_DATA;
- attributes &= ~FILE_FLAG_BACKUP_SEMANTICS;
}
/*
diff --git a/Utilities/cmlibuv/src/win/getaddrinfo.c b/Utilities/cmlibuv/src/win/getaddrinfo.c
index 744f8e0..c13bfec 100644
--- a/Utilities/cmlibuv/src/win/getaddrinfo.c
+++ b/Utilities/cmlibuv/src/win/getaddrinfo.c
@@ -262,8 +262,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
int err;
if (req == NULL || (node == NULL && service == NULL)) {
- err = WSAEINVAL;
- goto error;
+ return UV_EINVAL;
}
uv_req_init(loop, (uv_req_t*)req);
diff --git a/Utilities/cmlibuv/src/win/process-stdio.c b/Utilities/cmlibuv/src/win/process-stdio.c
index e3c06f5..032e309 100644
--- a/Utilities/cmlibuv/src/win/process-stdio.c
+++ b/Utilities/cmlibuv/src/win/process-stdio.c
@@ -372,6 +372,7 @@ int uv__stdio_create(uv_loop_t* loop,
case FILE_TYPE_PIPE:
CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;
+ break;
case FILE_TYPE_CHAR:
case FILE_TYPE_REMOTE:
diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c
index 855c374..bdf88d2 100644
--- a/Utilities/cmlibuv/src/win/process.c
+++ b/Utilities/cmlibuv/src/win/process.c
@@ -492,7 +492,7 @@ WCHAR* quote_cmd_arg(const WCHAR *source, WCHAR *target) {
* input : hello\\"world
* output: "hello\\\\\"world"
* input : hello world\
- * output: "hello world\"
+ * output: "hello world\\"
*/
*(target++) = L'"';
diff --git a/Utilities/cmlibuv/src/win/signal.c b/Utilities/cmlibuv/src/win/signal.c
index 2c64a55..af7974c 100644
--- a/Utilities/cmlibuv/src/win/signal.c
+++ b/Utilities/cmlibuv/src/win/signal.c
@@ -30,12 +30,14 @@
RB_HEAD(uv_signal_tree_s, uv_signal_s);
static struct uv_signal_tree_s uv__signal_tree = RB_INITIALIZER(uv__signal_tree);
-static ssize_t volatile uv__signal_control_handler_refs = 0;
static CRITICAL_SECTION uv__signal_lock;
+static BOOL WINAPI uv__signal_control_handler(DWORD type);
void uv_signals_init() {
InitializeCriticalSection(&uv__signal_lock);
+ if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE))
+ abort();
}
@@ -125,102 +127,6 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) {
}
-static int uv__signal_register_control_handler() {
- /* When this function is called, the uv__signal_lock must be held. */
-
- /* If the console control handler has already been hooked, just add a */
- /* reference. */
- if (uv__signal_control_handler_refs > 0) {
- uv__signal_control_handler_refs++;
- return 0;
- }
-
- if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE))
- return GetLastError();
-
- uv__signal_control_handler_refs++;
-
- return 0;
-}
-
-
-static void uv__signal_unregister_control_handler() {
- /* When this function is called, the uv__signal_lock must be held. */
- BOOL r;
-
- /* Don't unregister if the number of console control handlers exceeds one. */
- /* Just remove a reference in that case. */
- if (uv__signal_control_handler_refs > 1) {
- uv__signal_control_handler_refs--;
- return;
- }
-
- assert(uv__signal_control_handler_refs == 1);
-
- r = SetConsoleCtrlHandler(uv__signal_control_handler, FALSE);
- /* This should never fail; if it does it is probably a bug in libuv. */
- assert(r);
-
- uv__signal_control_handler_refs--;
-}
-
-
-static int uv__signal_register(int signum) {
- switch (signum) {
- case SIGINT:
- case SIGBREAK:
- case SIGHUP:
- return uv__signal_register_control_handler();
-
- case SIGWINCH:
- /* SIGWINCH is generated in tty.c. No need to register anything. */
- return 0;
-
- case SIGILL:
- case SIGABRT_COMPAT:
- case SIGFPE:
- case SIGSEGV:
- case SIGTERM:
- case SIGABRT:
- /* Signal is never raised. */
- return 0;
-
- default:
- /* Invalid signal. */
- return ERROR_INVALID_PARAMETER;
- }
-}
-
-
-static void uv__signal_unregister(int signum) {
- switch (signum) {
- case SIGINT:
- case SIGBREAK:
- case SIGHUP:
- uv__signal_unregister_control_handler();
- return;
-
- case SIGWINCH:
- /* SIGWINCH is generated in tty.c. No need to unregister anything. */
- return;
-
- case SIGILL:
- case SIGABRT_COMPAT:
- case SIGFPE:
- case SIGSEGV:
- case SIGTERM:
- case SIGABRT:
- /* Nothing is registered for this signal. */
- return;
-
- default:
- /* Libuv bug. */
- assert(0 && "Invalid signum");
- return;
- }
-}
-
-
int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) {
uv_req_t* req;
@@ -247,8 +153,6 @@ int uv_signal_stop(uv_signal_t* handle) {
EnterCriticalSection(&uv__signal_lock);
- uv__signal_unregister(handle->signum);
-
removed_handle = RB_REMOVE(uv_signal_tree_s, &uv__signal_tree, handle);
assert(removed_handle == handle);
@@ -262,14 +166,9 @@ int uv_signal_stop(uv_signal_t* handle) {
int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
- int err;
-
- /* If the user supplies signum == 0, then return an error already. If the */
- /* signum is otherwise invalid then uv__signal_register will find out */
- /* eventually. */
- if (signum == 0) {
+ /* Test for invalid signal values. */
+ if (signum != SIGWINCH && (signum <= 0 || signum >= NSIG))
return UV_EINVAL;
- }
/* Short circuit: if the signal watcher is already watching {signum} don't */
/* go through the process of deregistering and registering the handler. */
@@ -289,13 +188,6 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
EnterCriticalSection(&uv__signal_lock);
- err = uv__signal_register(signum);
- if (err) {
- /* Uh-oh, didn't work. */
- LeaveCriticalSection(&uv__signal_lock);
- return uv_translate_sys_error(err);
- }
-
handle->signum = signum;
RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle);
diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c
index 18d68d0..1b7adf6 100644
--- a/Utilities/cmlibuv/src/win/tty.c
+++ b/Utilities/cmlibuv/src/win/tty.c
@@ -56,6 +56,7 @@
#define ANSI_BACKSLASH_SEEN 0x80
#define MAX_INPUT_BUFFER_LENGTH 8192
+#define MAX_CONSOLE_CHAR 8192
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
@@ -1003,6 +1004,9 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
if (handle->tty.rd.last_key_len > 0) {
SET_REQ_SUCCESS(&handle->read_req);
uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req);
+ /* Make sure no attempt is made to insert it again until it's handled. */
+ handle->flags |= UV_HANDLE_READ_PENDING;
+ handle->reqs_pending++;
return 0;
}
@@ -1616,17 +1620,29 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
DWORD* error) {
/* We can only write 8k characters at a time. Windows can't handle */
/* much more characters in a single console write anyway. */
- WCHAR utf16_buf[8192];
+ WCHAR utf16_buf[MAX_CONSOLE_CHAR];
+ WCHAR* utf16_buffer;
DWORD utf16_buf_used = 0;
- unsigned int i;
-
-#define FLUSH_TEXT() \
- do { \
- if (utf16_buf_used > 0) { \
- uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error); \
- utf16_buf_used = 0; \
- } \
- } while (0)
+ unsigned int i, len, max_len, pos;
+ int allocate = 0;
+
+#define FLUSH_TEXT() \
+ do { \
+ pos = 0; \
+ do { \
+ len = utf16_buf_used - pos; \
+ if (len > MAX_CONSOLE_CHAR) \
+ len = MAX_CONSOLE_CHAR; \
+ uv_tty_emit_text(handle, &utf16_buffer[pos], len, error); \
+ pos += len; \
+ } while (pos < utf16_buf_used); \
+ if (allocate) { \
+ uv__free(utf16_buffer); \
+ allocate = 0; \
+ utf16_buffer = utf16_buf; \
+ } \
+ utf16_buf_used = 0; \
+ } while (0)
#define ENSURE_BUFFER_SPACE(wchars_needed) \
if (wchars_needed > ARRAY_SIZE(utf16_buf) - utf16_buf_used) { \
@@ -1644,38 +1660,47 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
/* state. */
*error = ERROR_SUCCESS;
+ utf16_buffer = utf16_buf;
+
uv_sem_wait(&uv_tty_output_lock);
for (i = 0; i < nbufs; i++) {
uv_buf_t buf = bufs[i];
unsigned int j;
- if (uv__vterm_state == UV_SUPPORTED) {
- utf16_buf_used = MultiByteToWideChar(CP_UTF8,
- 0,
- buf.base,
- buf.len,
- NULL,
- 0);
+ if (uv__vterm_state == UV_SUPPORTED && buf.len > 0) {
+ utf16_buf_used = MultiByteToWideChar(CP_UTF8,
+ 0,
+ buf.base,
+ buf.len,
+ NULL,
+ 0);
+
+ if (utf16_buf_used == 0) {
+ *error = GetLastError();
+ break;
+ }
- if (utf16_buf_used == 0) {
- *error = GetLastError();
- break;
- }
+ max_len = (utf16_buf_used + 1) * sizeof(WCHAR);
+ allocate = max_len > MAX_CONSOLE_CHAR;
+ if (allocate)
+ utf16_buffer = uv__malloc(max_len);
+ if (!MultiByteToWideChar(CP_UTF8,
+ 0,
+ buf.base,
+ buf.len,
+ utf16_buffer,
+ utf16_buf_used)) {
+ if (allocate)
+ uv__free(utf16_buffer);
+ *error = GetLastError();
+ break;
+ }
- if (!MultiByteToWideChar(CP_UTF8,
- 0,
- buf.base,
- buf.len,
- utf16_buf,
- utf16_buf_used)) {
- *error = GetLastError();
- break;
- }
+ FLUSH_TEXT();
- FLUSH_TEXT();
- continue;
- }
+ continue;
+ }
for (j = 0; j < buf.len; j++) {
unsigned char c = buf.base[j];
diff --git a/Utilities/cmlibuv/src/win/winapi.h b/Utilities/cmlibuv/src/win/winapi.h
index 597a93d..4b0eeca 100644
--- a/Utilities/cmlibuv/src/win/winapi.h
+++ b/Utilities/cmlibuv/src/win/winapi.h
@@ -4615,6 +4615,10 @@ typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile)
#endif
/* from winerror.h */
+#ifndef ERROR_ELEVATION_REQUIRED
+# define ERROR_ELEVATION_REQUIRED 740
+#endif
+
#ifndef ERROR_SYMLINK_NOT_SUPPORTED
# define ERROR_SYMLINK_NOT_SUPPORTED 1464
#endif