rugged 0.27.7 → 0.27.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/rugged/version.rb +1 -1
- data/vendor/libgit2/AUTHORS +1 -0
- data/vendor/libgit2/CMakeLists.txt +99 -51
- data/vendor/libgit2/COPYING +28 -0
- data/vendor/libgit2/cmake/Modules/AddCFlagIfSupported.cmake +15 -1
- data/vendor/libgit2/cmake/Modules/CheckPrototypeDefinition.c.in +29 -0
- data/vendor/libgit2/cmake/Modules/CheckPrototypeDefinition.cmake +96 -0
- data/vendor/libgit2/cmake/Modules/EnableWarnings.cmake +9 -8
- data/vendor/libgit2/cmake/Modules/FindCoreFoundation.cmake +2 -2
- data/vendor/libgit2/cmake/Modules/FindGSSAPI.cmake +1 -1
- data/vendor/libgit2/cmake/Modules/FindGSSFramework.cmake +28 -0
- data/vendor/libgit2/cmake/Modules/FindIconv.cmake +11 -6
- data/vendor/libgit2/cmake/Modules/FindPCRE.cmake +38 -0
- data/vendor/libgit2/cmake/Modules/FindPCRE2.cmake +37 -0
- data/vendor/libgit2/cmake/Modules/FindSecurity.cmake +2 -2
- data/vendor/libgit2/cmake/Modules/FindStatNsec.cmake +6 -0
- data/vendor/libgit2/cmake/Modules/PkgBuildConfig.cmake +110 -0
- data/vendor/libgit2/cmake/Modules/SelectGSSAPI.cmake +53 -0
- data/vendor/libgit2/cmake/Modules/SelectHTTPSBackend.cmake +124 -0
- data/vendor/libgit2/cmake/Modules/SelectHashes.cmake +66 -0
- data/vendor/libgit2/deps/http-parser/http_parser.c +11 -6
- data/vendor/libgit2/deps/ntlmclient/CMakeLists.txt +21 -0
- data/vendor/libgit2/deps/ntlmclient/compat.h +33 -0
- data/vendor/libgit2/deps/ntlmclient/crypt.h +64 -0
- data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.c +120 -0
- data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.h +18 -0
- data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.c +145 -0
- data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.h +18 -0
- data/vendor/libgit2/deps/ntlmclient/crypt_openssl.c +130 -0
- data/vendor/libgit2/deps/ntlmclient/crypt_openssl.h +21 -0
- data/vendor/libgit2/deps/ntlmclient/ntlm.c +1420 -0
- data/vendor/libgit2/deps/ntlmclient/ntlm.h +174 -0
- data/vendor/libgit2/deps/ntlmclient/ntlmclient.h +320 -0
- data/vendor/libgit2/deps/ntlmclient/unicode.h +36 -0
- data/vendor/libgit2/deps/ntlmclient/unicode_builtin.c +445 -0
- data/vendor/libgit2/deps/ntlmclient/unicode_iconv.c +201 -0
- data/vendor/libgit2/deps/ntlmclient/utf8.h +1257 -0
- data/vendor/libgit2/deps/ntlmclient/util.c +21 -0
- data/vendor/libgit2/deps/ntlmclient/util.h +14 -0
- data/vendor/libgit2/deps/pcre/CMakeLists.txt +140 -0
- data/vendor/libgit2/deps/pcre/COPYING +5 -0
- data/vendor/libgit2/deps/pcre/cmake/COPYING-CMAKE-SCRIPTS +22 -0
- data/vendor/libgit2/deps/pcre/cmake/FindEditline.cmake +17 -0
- data/vendor/libgit2/deps/pcre/cmake/FindPackageHandleStandardArgs.cmake +58 -0
- data/vendor/libgit2/deps/pcre/cmake/FindReadline.cmake +29 -0
- data/vendor/libgit2/deps/pcre/config.h.in +57 -0
- data/vendor/libgit2/deps/pcre/pcre.h +641 -0
- data/vendor/libgit2/deps/pcre/pcre_byte_order.c +319 -0
- data/vendor/libgit2/deps/pcre/pcre_chartables.c +198 -0
- data/vendor/libgit2/deps/pcre/pcre_compile.c +9800 -0
- data/vendor/libgit2/deps/pcre/pcre_config.c +190 -0
- data/vendor/libgit2/deps/pcre/pcre_dfa_exec.c +3676 -0
- data/vendor/libgit2/deps/pcre/pcre_exec.c +7173 -0
- data/vendor/libgit2/deps/pcre/pcre_fullinfo.c +245 -0
- data/vendor/libgit2/deps/pcre/pcre_get.c +669 -0
- data/vendor/libgit2/deps/pcre/pcre_globals.c +86 -0
- data/vendor/libgit2/deps/pcre/pcre_internal.h +2787 -0
- data/vendor/libgit2/deps/pcre/pcre_jit_compile.c +11913 -0
- data/vendor/libgit2/deps/pcre/pcre_maketables.c +156 -0
- data/vendor/libgit2/deps/pcre/pcre_newline.c +210 -0
- data/vendor/libgit2/deps/pcre/pcre_ord2utf8.c +94 -0
- data/vendor/libgit2/deps/pcre/pcre_printint.c +834 -0
- data/vendor/libgit2/deps/pcre/pcre_refcount.c +92 -0
- data/vendor/libgit2/deps/pcre/pcre_string_utils.c +211 -0
- data/vendor/libgit2/deps/pcre/pcre_study.c +1686 -0
- data/vendor/libgit2/deps/pcre/pcre_tables.c +727 -0
- data/vendor/libgit2/deps/pcre/pcre_ucd.c +3644 -0
- data/vendor/libgit2/deps/pcre/pcre_valid_utf8.c +301 -0
- data/vendor/libgit2/deps/pcre/pcre_version.c +98 -0
- data/vendor/libgit2/deps/pcre/pcre_xclass.c +268 -0
- data/vendor/libgit2/deps/pcre/pcreposix.c +421 -0
- data/vendor/libgit2/deps/pcre/pcreposix.h +117 -0
- data/vendor/libgit2/deps/pcre/ucp.h +224 -0
- data/vendor/libgit2/deps/winhttp/COPYING.GPL +993 -0
- data/vendor/libgit2/deps/winhttp/COPYING.LGPL +502 -0
- data/vendor/libgit2/deps/zlib/CMakeLists.txt +1 -0
- data/vendor/libgit2/deps/zlib/COPYING +27 -0
- data/vendor/libgit2/deps/zlib/adler32.c +0 -7
- data/vendor/libgit2/deps/zlib/crc32.c +0 -7
- data/vendor/libgit2/include/git2/annotated_commit.h +9 -0
- data/vendor/libgit2/include/git2/apply.h +149 -0
- data/vendor/libgit2/include/git2/attr.h +20 -13
- data/vendor/libgit2/include/git2/blame.h +4 -4
- data/vendor/libgit2/include/git2/blob.h +44 -12
- data/vendor/libgit2/include/git2/buffer.h +20 -26
- data/vendor/libgit2/include/git2/cert.h +135 -0
- data/vendor/libgit2/include/git2/checkout.h +53 -21
- data/vendor/libgit2/include/git2/cherrypick.h +3 -3
- data/vendor/libgit2/include/git2/clone.h +5 -5
- data/vendor/libgit2/include/git2/commit.h +25 -3
- data/vendor/libgit2/include/git2/common.h +35 -10
- data/vendor/libgit2/include/git2/config.h +29 -19
- data/vendor/libgit2/include/git2/cred.h +308 -0
- data/vendor/libgit2/include/git2/deprecated.h +493 -0
- data/vendor/libgit2/include/git2/describe.h +4 -4
- data/vendor/libgit2/include/git2/diff.h +177 -135
- data/vendor/libgit2/include/git2/errors.h +53 -46
- data/vendor/libgit2/include/git2/filter.h +8 -0
- data/vendor/libgit2/include/git2/index.h +74 -52
- data/vendor/libgit2/include/git2/indexer.h +76 -6
- data/vendor/libgit2/include/git2/merge.h +25 -10
- data/vendor/libgit2/include/git2/net.h +0 -5
- data/vendor/libgit2/include/git2/notes.h +1 -1
- data/vendor/libgit2/include/git2/object.h +17 -29
- data/vendor/libgit2/include/git2/odb.h +12 -11
- data/vendor/libgit2/include/git2/odb_backend.h +10 -9
- data/vendor/libgit2/include/git2/oid.h +2 -2
- data/vendor/libgit2/include/git2/pack.h +14 -3
- data/vendor/libgit2/include/git2/proxy.h +5 -3
- data/vendor/libgit2/include/git2/rebase.h +46 -2
- data/vendor/libgit2/include/git2/refs.h +34 -16
- data/vendor/libgit2/include/git2/remote.h +111 -14
- data/vendor/libgit2/include/git2/repository.h +69 -34
- data/vendor/libgit2/include/git2/revert.h +1 -1
- data/vendor/libgit2/include/git2/revwalk.h +7 -7
- data/vendor/libgit2/include/git2/signature.h +2 -2
- data/vendor/libgit2/include/git2/stash.h +5 -5
- data/vendor/libgit2/include/git2/status.h +26 -17
- data/vendor/libgit2/include/git2/submodule.h +23 -6
- data/vendor/libgit2/include/git2/sys/alloc.h +18 -18
- data/vendor/libgit2/include/git2/sys/commit.h +1 -1
- data/vendor/libgit2/include/git2/sys/config.h +13 -13
- data/vendor/libgit2/include/git2/sys/cred.h +90 -0
- data/vendor/libgit2/include/git2/sys/filter.h +6 -6
- data/vendor/libgit2/include/git2/sys/merge.h +3 -3
- data/vendor/libgit2/include/git2/sys/odb_backend.h +66 -22
- data/vendor/libgit2/include/git2/sys/path.h +14 -5
- data/vendor/libgit2/include/git2/sys/refdb_backend.h +76 -40
- data/vendor/libgit2/include/git2/sys/repository.h +5 -1
- data/vendor/libgit2/include/git2/sys/stream.h +92 -12
- data/vendor/libgit2/include/git2/sys/transport.h +129 -83
- data/vendor/libgit2/include/git2/tag.h +13 -4
- data/vendor/libgit2/include/git2/trace.h +2 -2
- data/vendor/libgit2/include/git2/transport.h +11 -311
- data/vendor/libgit2/include/git2/tree.h +4 -4
- data/vendor/libgit2/include/git2/types.h +25 -106
- data/vendor/libgit2/include/git2/version.h +3 -3
- data/vendor/libgit2/include/git2/worktree.h +5 -5
- data/vendor/libgit2/include/git2.h +4 -0
- data/vendor/libgit2/src/CMakeLists.txt +104 -235
- data/vendor/libgit2/src/alloc.c +14 -18
- data/vendor/libgit2/src/{stdalloc.c → allocators/stdalloc.c} +7 -8
- data/vendor/libgit2/src/{stdalloc.h → allocators/stdalloc.h} +4 -4
- data/vendor/libgit2/src/allocators/win32_crtdbg.c +118 -0
- data/vendor/libgit2/src/{transports/cred.h → allocators/win32_crtdbg.h} +5 -4
- data/vendor/libgit2/src/annotated_commit.c +18 -11
- data/vendor/libgit2/src/apply.c +535 -28
- data/vendor/libgit2/src/apply.h +3 -1
- data/vendor/libgit2/src/array.h +2 -2
- data/vendor/libgit2/src/attr.c +77 -71
- data/vendor/libgit2/src/attr_file.c +203 -117
- data/vendor/libgit2/src/attr_file.h +9 -9
- data/vendor/libgit2/src/attrcache.c +49 -51
- data/vendor/libgit2/src/attrcache.h +2 -1
- data/vendor/libgit2/src/blame.c +38 -18
- data/vendor/libgit2/src/blame.h +1 -1
- data/vendor/libgit2/src/blame_git.c +29 -15
- data/vendor/libgit2/src/blob.c +123 -37
- data/vendor/libgit2/src/blob.h +19 -2
- data/vendor/libgit2/src/branch.c +47 -23
- data/vendor/libgit2/src/buf_text.c +7 -6
- data/vendor/libgit2/src/buffer.c +60 -53
- data/vendor/libgit2/src/cache.c +38 -45
- data/vendor/libgit2/src/cache.h +3 -3
- data/vendor/libgit2/src/cc-compat.h +20 -3
- data/vendor/libgit2/src/checkout.c +77 -67
- data/vendor/libgit2/src/cherrypick.c +12 -6
- data/vendor/libgit2/src/clone.c +36 -14
- data/vendor/libgit2/src/clone.h +4 -0
- data/vendor/libgit2/src/commit.c +103 -48
- data/vendor/libgit2/src/commit.h +7 -0
- data/vendor/libgit2/src/commit_list.c +36 -78
- data/vendor/libgit2/src/commit_list.h +2 -2
- data/vendor/libgit2/src/common.h +24 -90
- data/vendor/libgit2/src/config.c +203 -176
- data/vendor/libgit2/src/config.h +8 -20
- data/vendor/libgit2/src/config_backend.h +96 -0
- data/vendor/libgit2/src/config_cache.c +41 -35
- data/vendor/libgit2/src/config_entries.c +229 -0
- data/vendor/libgit2/src/config_entries.h +24 -0
- data/vendor/libgit2/src/config_file.c +422 -680
- data/vendor/libgit2/src/config_mem.c +220 -0
- data/vendor/libgit2/src/config_parse.c +96 -68
- data/vendor/libgit2/src/config_parse.h +15 -14
- data/vendor/libgit2/src/config_snapshot.c +206 -0
- data/vendor/libgit2/src/crlf.c +219 -196
- data/vendor/libgit2/src/delta.c +25 -18
- data/vendor/libgit2/src/describe.c +42 -41
- data/vendor/libgit2/src/diff.c +52 -67
- data/vendor/libgit2/src/diff.h +2 -1
- data/vendor/libgit2/src/diff_driver.c +44 -46
- data/vendor/libgit2/src/diff_file.c +16 -14
- data/vendor/libgit2/src/diff_file.h +1 -1
- data/vendor/libgit2/src/diff_generate.c +158 -103
- data/vendor/libgit2/src/diff_generate.h +3 -3
- data/vendor/libgit2/src/diff_parse.c +4 -4
- data/vendor/libgit2/src/diff_print.c +34 -22
- data/vendor/libgit2/src/diff_stats.c +22 -7
- data/vendor/libgit2/src/diff_tform.c +18 -16
- data/vendor/libgit2/src/diff_xdiff.c +3 -3
- data/vendor/libgit2/src/errors.c +51 -39
- data/vendor/libgit2/src/errors.h +81 -0
- data/vendor/libgit2/src/features.h.in +9 -3
- data/vendor/libgit2/src/fetch.c +8 -3
- data/vendor/libgit2/src/fetchhead.c +12 -12
- data/vendor/libgit2/src/filebuf.c +28 -32
- data/vendor/libgit2/src/filebuf.h +2 -2
- data/vendor/libgit2/src/filter.c +47 -33
- data/vendor/libgit2/src/filter.h +0 -10
- data/vendor/libgit2/src/{fileops.c → futils.c} +70 -63
- data/vendor/libgit2/src/{fileops.h → futils.h} +6 -6
- data/vendor/libgit2/src/global.c +35 -55
- data/vendor/libgit2/src/global.h +0 -2
- data/vendor/libgit2/src/hash/sha1/collisiondetect.c +48 -0
- data/vendor/libgit2/src/hash/sha1/collisiondetect.h +19 -0
- data/vendor/libgit2/src/hash/{hash_common_crypto.h → sha1/common_crypto.c} +17 -17
- data/vendor/libgit2/src/hash/sha1/common_crypto.h +19 -0
- data/vendor/libgit2/src/hash/{hash_generic.c → sha1/generic.c} +22 -10
- data/vendor/libgit2/src/hash/{hash_generic.h → sha1/generic.h} +4 -10
- data/vendor/libgit2/src/hash/{hash_mbedtls.c → sha1/mbedtls.c} +15 -7
- data/vendor/libgit2/src/hash/{hash_mbedtls.h → sha1/mbedtls.h} +6 -7
- data/vendor/libgit2/src/hash/sha1/openssl.c +59 -0
- data/vendor/libgit2/src/hash/sha1/openssl.h +19 -0
- data/vendor/libgit2/src/hash/{sha1dc → sha1/sha1dc}/sha1.c +14 -3
- data/vendor/libgit2/src/hash/{hash_win32.c → sha1/win32.c} +47 -37
- data/vendor/libgit2/src/hash/{hash_win32.h → sha1/win32.h} +6 -19
- data/vendor/libgit2/src/hash/sha1.h +38 -0
- data/vendor/libgit2/src/hash.c +61 -0
- data/vendor/libgit2/src/hash.h +20 -21
- data/vendor/libgit2/src/hashsig.c +5 -5
- data/vendor/libgit2/src/idxmap.c +107 -61
- data/vendor/libgit2/src/idxmap.h +153 -31
- data/vendor/libgit2/src/ignore.c +38 -42
- data/vendor/libgit2/src/index.c +264 -199
- data/vendor/libgit2/src/index.h +7 -1
- data/vendor/libgit2/src/indexer.c +338 -167
- data/vendor/libgit2/src/integer.h +71 -26
- data/vendor/libgit2/src/iterator.c +134 -62
- data/vendor/libgit2/src/iterator.h +15 -0
- data/vendor/libgit2/src/mailmap.c +8 -8
- data/vendor/libgit2/src/map.h +1 -1
- data/vendor/libgit2/src/merge.c +137 -93
- data/vendor/libgit2/src/merge_driver.c +11 -11
- data/vendor/libgit2/src/merge_file.c +2 -2
- data/vendor/libgit2/src/mwindow.c +24 -29
- data/vendor/libgit2/src/mwindow.h +4 -4
- data/vendor/libgit2/src/net.c +184 -0
- data/vendor/libgit2/src/net.h +36 -0
- data/vendor/libgit2/src/netops.c +55 -156
- data/vendor/libgit2/src/netops.h +3 -23
- data/vendor/libgit2/src/notes.c +14 -9
- data/vendor/libgit2/src/object.c +120 -69
- data/vendor/libgit2/src/object.h +22 -9
- data/vendor/libgit2/src/object_api.c +8 -8
- data/vendor/libgit2/src/odb.c +111 -88
- data/vendor/libgit2/src/odb.h +8 -7
- data/vendor/libgit2/src/odb_loose.c +58 -47
- data/vendor/libgit2/src/odb_mempack.c +21 -34
- data/vendor/libgit2/src/odb_pack.c +17 -13
- data/vendor/libgit2/src/offmap.c +53 -35
- data/vendor/libgit2/src/offmap.h +108 -21
- data/vendor/libgit2/src/oid.c +12 -7
- data/vendor/libgit2/src/oidmap.c +49 -47
- data/vendor/libgit2/src/oidmap.h +101 -24
- data/vendor/libgit2/src/pack-objects.c +87 -86
- data/vendor/libgit2/src/pack-objects.h +2 -8
- data/vendor/libgit2/src/pack.c +94 -96
- data/vendor/libgit2/src/pack.h +16 -18
- data/vendor/libgit2/src/parse.c +17 -4
- data/vendor/libgit2/src/parse.h +3 -3
- data/vendor/libgit2/src/patch.c +3 -3
- data/vendor/libgit2/src/patch_generate.c +18 -18
- data/vendor/libgit2/src/patch_parse.c +147 -79
- data/vendor/libgit2/src/path.c +207 -62
- data/vendor/libgit2/src/path.h +14 -0
- data/vendor/libgit2/src/pathspec.c +18 -18
- data/vendor/libgit2/src/pool.c +26 -22
- data/vendor/libgit2/src/pool.h +7 -7
- data/vendor/libgit2/src/posix.c +10 -10
- data/vendor/libgit2/src/posix.h +12 -1
- data/vendor/libgit2/src/proxy.c +8 -3
- data/vendor/libgit2/src/push.c +35 -29
- data/vendor/libgit2/src/push.h +2 -1
- data/vendor/libgit2/src/reader.c +265 -0
- data/vendor/libgit2/src/reader.h +107 -0
- data/vendor/libgit2/src/rebase.c +97 -38
- data/vendor/libgit2/src/refdb.c +15 -3
- data/vendor/libgit2/src/refdb_fs.c +318 -222
- data/vendor/libgit2/src/reflog.c +13 -15
- data/vendor/libgit2/src/refs.c +122 -89
- data/vendor/libgit2/src/refs.h +5 -3
- data/vendor/libgit2/src/refspec.c +27 -33
- data/vendor/libgit2/src/regexp.c +221 -0
- data/vendor/libgit2/src/regexp.h +97 -0
- data/vendor/libgit2/src/remote.c +229 -178
- data/vendor/libgit2/src/remote.h +11 -2
- data/vendor/libgit2/src/repository.c +227 -172
- data/vendor/libgit2/src/repository.h +52 -40
- data/vendor/libgit2/src/reset.c +7 -7
- data/vendor/libgit2/src/revert.c +11 -6
- data/vendor/libgit2/src/revparse.c +46 -46
- data/vendor/libgit2/src/revwalk.c +89 -54
- data/vendor/libgit2/src/revwalk.h +20 -0
- data/vendor/libgit2/src/settings.c +22 -9
- data/vendor/libgit2/src/signature.c +15 -13
- data/vendor/libgit2/src/sortedcache.c +22 -36
- data/vendor/libgit2/src/sortedcache.h +1 -1
- data/vendor/libgit2/src/stash.c +56 -76
- data/vendor/libgit2/src/status.c +27 -21
- data/vendor/libgit2/src/stream.h +17 -2
- data/vendor/libgit2/src/streams/mbedtls.c +100 -80
- data/vendor/libgit2/src/streams/mbedtls.h +5 -2
- data/vendor/libgit2/src/streams/openssl.c +93 -81
- data/vendor/libgit2/src/streams/openssl.h +5 -2
- data/vendor/libgit2/src/streams/registry.c +118 -0
- data/vendor/libgit2/src/streams/registry.h +19 -0
- data/vendor/libgit2/src/streams/socket.c +55 -30
- data/vendor/libgit2/src/streams/stransport.c +57 -32
- data/vendor/libgit2/src/streams/stransport.h +5 -0
- data/vendor/libgit2/src/streams/tls.c +48 -20
- data/vendor/libgit2/src/streams/tls.h +12 -4
- data/vendor/libgit2/src/strmap.c +47 -74
- data/vendor/libgit2/src/strmap.h +108 -33
- data/vendor/libgit2/src/submodule.c +190 -169
- data/vendor/libgit2/src/submodule.h +1 -1
- data/vendor/libgit2/src/sysdir.c +25 -15
- data/vendor/libgit2/src/tag.c +39 -26
- data/vendor/libgit2/src/tag.h +2 -1
- data/vendor/libgit2/src/trace.c +2 -2
- data/vendor/libgit2/src/trace.h +2 -2
- data/vendor/libgit2/src/trailer.c +46 -32
- data/vendor/libgit2/src/transaction.c +30 -29
- data/vendor/libgit2/src/transport.c +3 -3
- data/vendor/libgit2/src/transports/auth.c +14 -10
- data/vendor/libgit2/src/transports/auth.h +10 -3
- data/vendor/libgit2/src/transports/auth_negotiate.c +31 -16
- data/vendor/libgit2/src/transports/auth_negotiate.h +2 -2
- data/vendor/libgit2/src/transports/auth_ntlm.c +223 -0
- data/vendor/libgit2/src/transports/auth_ntlm.h +35 -0
- data/vendor/libgit2/src/transports/cred.c +24 -24
- data/vendor/libgit2/src/transports/git.c +25 -30
- data/vendor/libgit2/src/transports/http.c +871 -335
- data/vendor/libgit2/src/transports/http.h +2 -0
- data/vendor/libgit2/src/transports/local.c +28 -28
- data/vendor/libgit2/src/transports/smart.c +64 -46
- data/vendor/libgit2/src/transports/smart.h +5 -6
- data/vendor/libgit2/src/transports/smart_pkt.c +162 -151
- data/vendor/libgit2/src/transports/smart_protocol.c +64 -94
- data/vendor/libgit2/src/transports/ssh.c +76 -65
- data/vendor/libgit2/src/transports/winhttp.c +328 -319
- data/vendor/libgit2/src/tree-cache.c +21 -14
- data/vendor/libgit2/src/tree.c +119 -112
- data/vendor/libgit2/src/tree.h +1 -0
- data/vendor/libgit2/src/unix/map.c +3 -3
- data/vendor/libgit2/src/unix/posix.h +1 -11
- data/vendor/libgit2/src/userdiff.h +3 -1
- data/vendor/libgit2/src/util.c +154 -93
- data/vendor/libgit2/src/util.h +19 -23
- data/vendor/libgit2/src/vector.c +15 -10
- data/vendor/libgit2/src/wildmatch.c +320 -0
- data/vendor/libgit2/src/wildmatch.h +23 -0
- data/vendor/libgit2/src/win32/dir.c +3 -3
- data/vendor/libgit2/src/win32/findfile.c +1 -1
- data/vendor/libgit2/src/win32/map.c +9 -11
- data/vendor/libgit2/src/win32/msvc-compat.h +6 -0
- data/vendor/libgit2/src/win32/path_w32.c +113 -9
- data/vendor/libgit2/src/win32/path_w32.h +18 -29
- data/vendor/libgit2/src/win32/posix.h +1 -4
- data/vendor/libgit2/src/win32/posix_w32.c +69 -44
- data/vendor/libgit2/src/win32/precompiled.h +0 -2
- data/vendor/libgit2/src/win32/thread.c +5 -10
- data/vendor/libgit2/src/win32/w32_buffer.c +9 -5
- data/vendor/libgit2/src/win32/w32_common.h +39 -0
- data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.c +2 -95
- data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.h +0 -2
- data/vendor/libgit2/src/win32/w32_stack.c +6 -11
- data/vendor/libgit2/src/win32/w32_stack.h +3 -3
- data/vendor/libgit2/src/win32/w32_util.c +27 -64
- data/vendor/libgit2/src/win32/w32_util.h +5 -49
- data/vendor/libgit2/src/worktree.c +44 -30
- data/vendor/libgit2/src/xdiff/xdiffi.c +5 -5
- data/vendor/libgit2/src/xdiff/xhistogram.c +1 -1
- data/vendor/libgit2/src/xdiff/xmerge.c +27 -15
- data/vendor/libgit2/src/xdiff/xpatience.c +3 -0
- data/vendor/libgit2/src/zstream.c +4 -4
- metadata +115 -38
- data/vendor/libgit2/deps/regex/CMakeLists.txt +0 -2
- data/vendor/libgit2/deps/regex/config.h +0 -7
- data/vendor/libgit2/deps/regex/regcomp.c +0 -3857
- data/vendor/libgit2/deps/regex/regex.c +0 -92
- data/vendor/libgit2/deps/regex/regex.h +0 -582
- data/vendor/libgit2/deps/regex/regex_internal.c +0 -1744
- data/vendor/libgit2/deps/regex/regex_internal.h +0 -819
- data/vendor/libgit2/deps/regex/regexec.c +0 -4369
- data/vendor/libgit2/include/git2/inttypes.h +0 -309
- data/vendor/libgit2/include/git2/sys/time.h +0 -31
- data/vendor/libgit2/libgit2.pc.in +0 -13
- data/vendor/libgit2/src/config_file.h +0 -73
- data/vendor/libgit2/src/fnmatch.c +0 -248
- data/vendor/libgit2/src/fnmatch.h +0 -48
- data/vendor/libgit2/src/hash/hash_collisiondetect.h +0 -47
- data/vendor/libgit2/src/hash/hash_openssl.h +0 -59
- data/vendor/libgit2/src/streams/curl.c +0 -385
- data/vendor/libgit2/src/streams/curl.h +0 -17
- /data/vendor/libgit2/deps/http-parser/{LICENSE-MIT → COPYING} +0 -0
- /data/vendor/libgit2/src/hash/{sha1dc → sha1/sha1dc}/sha1.h +0 -0
- /data/vendor/libgit2/src/hash/{sha1dc → sha1/sha1dc}/ubc_check.c +0 -0
- /data/vendor/libgit2/src/hash/{sha1dc → sha1/sha1dc}/ubc_check.h +0 -0
|
@@ -12,19 +12,22 @@
|
|
|
12
12
|
#include "git2.h"
|
|
13
13
|
#include "http_parser.h"
|
|
14
14
|
#include "buffer.h"
|
|
15
|
+
#include "net.h"
|
|
15
16
|
#include "netops.h"
|
|
16
17
|
#include "global.h"
|
|
17
18
|
#include "remote.h"
|
|
19
|
+
#include "git2/sys/cred.h"
|
|
18
20
|
#include "smart.h"
|
|
19
21
|
#include "auth.h"
|
|
20
22
|
#include "http.h"
|
|
21
23
|
#include "auth_negotiate.h"
|
|
24
|
+
#include "auth_ntlm.h"
|
|
22
25
|
#include "streams/tls.h"
|
|
23
26
|
#include "streams/socket.h"
|
|
24
|
-
#include "streams/curl.h"
|
|
25
27
|
|
|
26
28
|
git_http_auth_scheme auth_schemes[] = {
|
|
27
29
|
{ GIT_AUTHTYPE_NEGOTIATE, "Negotiate", GIT_CREDTYPE_DEFAULT, git_http_auth_negotiate },
|
|
30
|
+
{ GIT_AUTHTYPE_NTLM, "NTLM", GIT_CREDTYPE_USERPASS_PLAINTEXT, git_http_auth_ntlm },
|
|
28
31
|
{ GIT_AUTHTYPE_BASIC, "Basic", GIT_CREDTYPE_USERPASS_PLAINTEXT, git_http_auth_basic },
|
|
29
32
|
};
|
|
30
33
|
|
|
@@ -37,6 +40,12 @@ static const char *receive_pack_service_url = "/git-receive-pack";
|
|
|
37
40
|
static const char *get_verb = "GET";
|
|
38
41
|
static const char *post_verb = "POST";
|
|
39
42
|
|
|
43
|
+
#define AUTH_HEADER_SERVER "Authorization"
|
|
44
|
+
#define AUTH_HEADER_PROXY "Proxy-Authorization"
|
|
45
|
+
|
|
46
|
+
#define SERVER_TYPE_REMOTE "remote"
|
|
47
|
+
#define SERVER_TYPE_PROXY "proxy"
|
|
48
|
+
|
|
40
49
|
#define OWNING_SUBTRANSPORT(s) ((http_subtransport *)(s)->parent.subtransport)
|
|
41
50
|
|
|
42
51
|
#define PARSE_ERROR_GENERIC -1
|
|
@@ -62,17 +71,36 @@ typedef struct {
|
|
|
62
71
|
unsigned chunk_buffer_len;
|
|
63
72
|
unsigned sent_request : 1,
|
|
64
73
|
received_response : 1,
|
|
65
|
-
chunked : 1
|
|
66
|
-
redirect_count : 3;
|
|
74
|
+
chunked : 1;
|
|
67
75
|
} http_stream;
|
|
68
76
|
|
|
77
|
+
typedef struct {
|
|
78
|
+
git_net_url url;
|
|
79
|
+
git_stream *stream;
|
|
80
|
+
|
|
81
|
+
git_http_authtype_t authtypes;
|
|
82
|
+
git_credtype_t credtypes;
|
|
83
|
+
|
|
84
|
+
git_cred *cred;
|
|
85
|
+
unsigned url_cred_presented : 1,
|
|
86
|
+
authenticated : 1;
|
|
87
|
+
|
|
88
|
+
git_vector auth_challenges;
|
|
89
|
+
git_http_auth_context *auth_context;
|
|
90
|
+
} http_server;
|
|
91
|
+
|
|
69
92
|
typedef struct {
|
|
70
93
|
git_smart_subtransport parent;
|
|
71
94
|
transport_smart *owner;
|
|
72
|
-
git_stream *
|
|
73
|
-
gitno_connection_data connection_data;
|
|
95
|
+
git_stream *gitserver_stream;
|
|
74
96
|
bool connected;
|
|
75
97
|
|
|
98
|
+
http_server server;
|
|
99
|
+
|
|
100
|
+
http_server proxy;
|
|
101
|
+
char *proxy_url;
|
|
102
|
+
git_proxy_options proxy_opts;
|
|
103
|
+
|
|
76
104
|
/* Parser structures */
|
|
77
105
|
http_parser parser;
|
|
78
106
|
http_parser_settings settings;
|
|
@@ -81,17 +109,15 @@ typedef struct {
|
|
|
81
109
|
git_buf parse_header_value;
|
|
82
110
|
char parse_buffer_data[NETIO_BUFSIZE];
|
|
83
111
|
char *content_type;
|
|
112
|
+
char *content_length;
|
|
84
113
|
char *location;
|
|
85
|
-
git_vector www_authenticate;
|
|
86
114
|
enum last_cb last_cb;
|
|
87
115
|
int parse_error;
|
|
88
116
|
int error;
|
|
89
|
-
unsigned
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
git_cred *url_cred;
|
|
94
|
-
git_vector auth_contexts;
|
|
117
|
+
unsigned request_count;
|
|
118
|
+
unsigned parse_finished : 1,
|
|
119
|
+
keepalive : 1,
|
|
120
|
+
replay_count : 4;
|
|
95
121
|
} http_subtransport;
|
|
96
122
|
|
|
97
123
|
typedef struct {
|
|
@@ -104,91 +130,50 @@ typedef struct {
|
|
|
104
130
|
size_t *bytes_read;
|
|
105
131
|
} parser_context;
|
|
106
132
|
|
|
107
|
-
static
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return !!(scheme->credtypes & credtype);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
static bool challenge_match(git_http_auth_scheme *scheme, void *data)
|
|
115
|
-
{
|
|
116
|
-
const char *scheme_name = scheme->name;
|
|
117
|
-
const char *challenge = (const char *)data;
|
|
118
|
-
size_t scheme_len;
|
|
119
|
-
|
|
120
|
-
scheme_len = strlen(scheme_name);
|
|
121
|
-
return (strncasecmp(challenge, scheme_name, scheme_len) == 0 &&
|
|
122
|
-
(challenge[scheme_len] == '\0' || challenge[scheme_len] == ' '));
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
static int auth_context_match(
|
|
126
|
-
git_http_auth_context **out,
|
|
127
|
-
http_subtransport *t,
|
|
128
|
-
bool (*scheme_match)(git_http_auth_scheme *scheme, void *data),
|
|
129
|
-
void *data)
|
|
133
|
+
static git_http_auth_scheme *scheme_for_challenge(
|
|
134
|
+
const char *challenge,
|
|
135
|
+
git_cred *cred)
|
|
130
136
|
{
|
|
131
137
|
git_http_auth_scheme *scheme = NULL;
|
|
132
|
-
git_http_auth_context *context = NULL, *c;
|
|
133
138
|
size_t i;
|
|
134
139
|
|
|
135
|
-
*out = NULL;
|
|
136
|
-
|
|
137
140
|
for (i = 0; i < ARRAY_SIZE(auth_schemes); i++) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
}
|
|
141
|
+
const char *scheme_name = auth_schemes[i].name;
|
|
142
|
+
const git_credtype_t scheme_types = auth_schemes[i].credtypes;
|
|
143
|
+
size_t scheme_len;
|
|
143
144
|
|
|
144
|
-
|
|
145
|
-
return 0;
|
|
145
|
+
scheme_len = strlen(scheme_name);
|
|
146
146
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
147
|
+
if ((!cred || (cred->credtype & scheme_types)) &&
|
|
148
|
+
strncasecmp(challenge, scheme_name, scheme_len) == 0 &&
|
|
149
|
+
(challenge[scheme_len] == '\0' || challenge[scheme_len] == ' ')) {
|
|
150
|
+
scheme = &auth_schemes[i];
|
|
151
151
|
break;
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
|
|
156
|
-
if (scheme->init_context(&context, &t->connection_data) < 0)
|
|
157
|
-
return -1;
|
|
158
|
-
else if (!context)
|
|
159
|
-
return 0;
|
|
160
|
-
else if (git_vector_insert(&t->auth_contexts, context) < 0)
|
|
161
|
-
return -1;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
*out = context;
|
|
165
|
-
|
|
166
|
-
return 0;
|
|
155
|
+
return scheme;
|
|
167
156
|
}
|
|
168
157
|
|
|
169
|
-
static int apply_credentials(
|
|
158
|
+
static int apply_credentials(
|
|
159
|
+
git_buf *buf,
|
|
160
|
+
http_server *server,
|
|
161
|
+
const char *header_name)
|
|
170
162
|
{
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
/* Apply the credentials given to us in the URL */
|
|
175
|
-
if (!cred && t->connection_data.user && t->connection_data.pass) {
|
|
176
|
-
if (!t->url_cred &&
|
|
177
|
-
git_cred_userpass_plaintext_new(&t->url_cred,
|
|
178
|
-
t->connection_data.user, t->connection_data.pass) < 0)
|
|
179
|
-
return -1;
|
|
163
|
+
git_buf token = GIT_BUF_INIT;
|
|
164
|
+
int error = 0;
|
|
180
165
|
|
|
181
|
-
|
|
182
|
-
|
|
166
|
+
if (!server->auth_context)
|
|
167
|
+
goto done;
|
|
183
168
|
|
|
184
|
-
if (
|
|
185
|
-
|
|
169
|
+
if ((error = server->auth_context->next_token(&token, server->auth_context, server->cred)) < 0)
|
|
170
|
+
goto done;
|
|
186
171
|
|
|
187
|
-
|
|
188
|
-
if (auth_context_match(&context, t, credtype_match, &cred->credtype) < 0)
|
|
189
|
-
return -1;
|
|
172
|
+
error = git_buf_printf(buf, "%s: %s\r\n", header_name, token.ptr);
|
|
190
173
|
|
|
191
|
-
|
|
174
|
+
done:
|
|
175
|
+
git_buf_dispose(&token);
|
|
176
|
+
return error;
|
|
192
177
|
}
|
|
193
178
|
|
|
194
179
|
static int gen_request(
|
|
@@ -197,15 +182,29 @@ static int gen_request(
|
|
|
197
182
|
size_t content_length)
|
|
198
183
|
{
|
|
199
184
|
http_subtransport *t = OWNING_SUBTRANSPORT(s);
|
|
200
|
-
const char *path = t->
|
|
185
|
+
const char *path = t->server.url.path ? t->server.url.path : "/";
|
|
201
186
|
size_t i;
|
|
202
187
|
|
|
203
|
-
|
|
188
|
+
if (t->proxy_opts.type == GIT_PROXY_SPECIFIED)
|
|
189
|
+
git_buf_printf(buf, "%s %s://%s:%s%s%s HTTP/1.1\r\n",
|
|
190
|
+
s->verb,
|
|
191
|
+
t->server.url.scheme,
|
|
192
|
+
t->server.url.host,
|
|
193
|
+
t->server.url.port,
|
|
194
|
+
path, s->service_url);
|
|
195
|
+
else
|
|
196
|
+
git_buf_printf(buf, "%s %s%s HTTP/1.1\r\n",
|
|
197
|
+
s->verb, path, s->service_url);
|
|
204
198
|
|
|
205
199
|
git_buf_puts(buf, "User-Agent: ");
|
|
206
200
|
git_http__user_agent(buf);
|
|
207
201
|
git_buf_puts(buf, "\r\n");
|
|
208
|
-
git_buf_printf(buf, "Host: %s
|
|
202
|
+
git_buf_printf(buf, "Host: %s", t->server.url.host);
|
|
203
|
+
|
|
204
|
+
if (!git_net_url_is_default_port(&t->server.url))
|
|
205
|
+
git_buf_printf(buf, ":%s", t->server.url.port);
|
|
206
|
+
|
|
207
|
+
git_buf_puts(buf, "\r\n");
|
|
209
208
|
|
|
210
209
|
if (s->chunked || content_length > 0) {
|
|
211
210
|
git_buf_printf(buf, "Accept: application/x-git-%s-result\r\n", s->service);
|
|
@@ -223,8 +222,12 @@ static int gen_request(
|
|
|
223
222
|
git_buf_printf(buf, "%s\r\n", t->owner->custom_headers.strings[i]);
|
|
224
223
|
}
|
|
225
224
|
|
|
226
|
-
/* Apply credentials to the request */
|
|
227
|
-
if (
|
|
225
|
+
/* Apply proxy and server credentials to the request */
|
|
226
|
+
if (t->proxy_opts.type != GIT_PROXY_NONE &&
|
|
227
|
+
apply_credentials(buf, &t->proxy, AUTH_HEADER_PROXY) < 0)
|
|
228
|
+
return -1;
|
|
229
|
+
|
|
230
|
+
if (apply_credentials(buf, &t->server, AUTH_HEADER_SERVER) < 0)
|
|
228
231
|
return -1;
|
|
229
232
|
|
|
230
233
|
git_buf_puts(buf, "\r\n");
|
|
@@ -235,29 +238,86 @@ static int gen_request(
|
|
|
235
238
|
return 0;
|
|
236
239
|
}
|
|
237
240
|
|
|
238
|
-
static int
|
|
239
|
-
git_vector *www_authenticate,
|
|
240
|
-
http_subtransport *t,
|
|
241
|
-
int *allowed_types)
|
|
241
|
+
static int set_authentication_challenge(http_server *server)
|
|
242
242
|
{
|
|
243
|
-
|
|
243
|
+
const char *challenge;
|
|
244
|
+
|
|
245
|
+
if (git_vector_length(&server->auth_challenges) > 1) {
|
|
246
|
+
git_error_set(GIT_ERROR_NET, "received multiple authentication challenges");
|
|
247
|
+
return -1;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
challenge = git_vector_get(&server->auth_challenges, 0);
|
|
251
|
+
|
|
252
|
+
if (server->auth_context->set_challenge)
|
|
253
|
+
return server->auth_context->set_challenge(server->auth_context, challenge);
|
|
254
|
+
else
|
|
255
|
+
return 0;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
static int set_authentication_types(http_server *server)
|
|
259
|
+
{
|
|
260
|
+
git_http_auth_scheme *scheme;
|
|
244
261
|
char *challenge;
|
|
245
262
|
size_t i;
|
|
246
263
|
|
|
247
|
-
git_vector_foreach(
|
|
248
|
-
if (
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
264
|
+
git_vector_foreach(&server->auth_challenges, i, challenge) {
|
|
265
|
+
if ((scheme = scheme_for_challenge(challenge, NULL)) != NULL) {
|
|
266
|
+
server->authtypes |= scheme->type;
|
|
267
|
+
server->credtypes |= scheme->credtypes;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
252
270
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
271
|
+
return 0;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
static bool auth_context_complete(http_server *server)
|
|
275
|
+
{
|
|
276
|
+
/* If there's no is_complete function, we're always complete */
|
|
277
|
+
if (!server->auth_context->is_complete)
|
|
278
|
+
return true;
|
|
279
|
+
|
|
280
|
+
if (server->auth_context->is_complete(server->auth_context))
|
|
281
|
+
return true;
|
|
282
|
+
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
static void free_auth_context(http_server *server)
|
|
287
|
+
{
|
|
288
|
+
if (!server->auth_context)
|
|
289
|
+
return;
|
|
290
|
+
|
|
291
|
+
if (server->auth_context->free)
|
|
292
|
+
server->auth_context->free(server->auth_context);
|
|
293
|
+
|
|
294
|
+
server->auth_context = NULL;
|
|
295
|
+
}
|
|
256
296
|
|
|
257
|
-
|
|
297
|
+
static int parse_authenticate_response(http_server *server)
|
|
298
|
+
{
|
|
299
|
+
/*
|
|
300
|
+
* If we think that we've completed authentication (ie, we've either
|
|
301
|
+
* sent a basic credential or we've sent the NTLM/Negotiate response)
|
|
302
|
+
* but we've got an authentication request from the server then our
|
|
303
|
+
* last authentication did not succeed. Start over.
|
|
304
|
+
*/
|
|
305
|
+
if (server->auth_context && auth_context_complete(server)) {
|
|
306
|
+
free_auth_context(server);
|
|
307
|
+
|
|
308
|
+
server->authenticated = 0;
|
|
258
309
|
}
|
|
259
310
|
|
|
260
|
-
|
|
311
|
+
/*
|
|
312
|
+
* If we've begun authentication, give the challenge to the context.
|
|
313
|
+
* Otherwise, set up the types to prepare credentials.
|
|
314
|
+
*/
|
|
315
|
+
if (git_vector_length(&server->auth_challenges) == 0)
|
|
316
|
+
return 0;
|
|
317
|
+
else if (server->auth_context)
|
|
318
|
+
return set_authentication_challenge(server);
|
|
319
|
+
else
|
|
320
|
+
return set_authentication_types(server);
|
|
261
321
|
}
|
|
262
322
|
|
|
263
323
|
static int on_header_ready(http_subtransport *t)
|
|
@@ -266,22 +326,45 @@ static int on_header_ready(http_subtransport *t)
|
|
|
266
326
|
git_buf *value = &t->parse_header_value;
|
|
267
327
|
|
|
268
328
|
if (!strcasecmp("Content-Type", git_buf_cstr(name))) {
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
|
|
329
|
+
if (t->content_type) {
|
|
330
|
+
git_error_set(GIT_ERROR_NET, "multiple Content-Type headers");
|
|
331
|
+
return -1;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
t->content_type = git__strdup(git_buf_cstr(value));
|
|
335
|
+
GIT_ERROR_CHECK_ALLOC(t->content_type);
|
|
336
|
+
}
|
|
337
|
+
else if (!strcasecmp("Content-Length", git_buf_cstr(name))) {
|
|
338
|
+
if (t->content_length) {
|
|
339
|
+
git_error_set(GIT_ERROR_NET, "multiple Content-Length headers");
|
|
340
|
+
return -1;
|
|
272
341
|
}
|
|
342
|
+
|
|
343
|
+
t->content_length = git__strdup(git_buf_cstr(value));
|
|
344
|
+
GIT_ERROR_CHECK_ALLOC(t->content_length);
|
|
345
|
+
}
|
|
346
|
+
else if (!strcasecmp("Proxy-Authenticate", git_buf_cstr(name))) {
|
|
347
|
+
char *dup = git__strdup(git_buf_cstr(value));
|
|
348
|
+
GIT_ERROR_CHECK_ALLOC(dup);
|
|
349
|
+
|
|
350
|
+
if (git_vector_insert(&t->proxy.auth_challenges, dup) < 0)
|
|
351
|
+
return -1;
|
|
273
352
|
}
|
|
274
353
|
else if (!strcasecmp("WWW-Authenticate", git_buf_cstr(name))) {
|
|
275
354
|
char *dup = git__strdup(git_buf_cstr(value));
|
|
276
|
-
|
|
355
|
+
GIT_ERROR_CHECK_ALLOC(dup);
|
|
277
356
|
|
|
278
|
-
git_vector_insert(&t->
|
|
357
|
+
if (git_vector_insert(&t->server.auth_challenges, dup) < 0)
|
|
358
|
+
return -1;
|
|
279
359
|
}
|
|
280
360
|
else if (!strcasecmp("Location", git_buf_cstr(name))) {
|
|
281
|
-
if (
|
|
282
|
-
|
|
283
|
-
|
|
361
|
+
if (t->location) {
|
|
362
|
+
git_error_set(GIT_ERROR_NET, "multiple Location headers");
|
|
363
|
+
return -1;
|
|
284
364
|
}
|
|
365
|
+
|
|
366
|
+
t->location = git__strdup(git_buf_cstr(value));
|
|
367
|
+
GIT_ERROR_CHECK_ALLOC(t->location);
|
|
285
368
|
}
|
|
286
369
|
|
|
287
370
|
return 0;
|
|
@@ -325,85 +408,204 @@ static int on_header_value(http_parser *parser, const char *str, size_t len)
|
|
|
325
408
|
return 0;
|
|
326
409
|
}
|
|
327
410
|
|
|
411
|
+
GIT_INLINE(void) free_cred(git_cred **cred)
|
|
412
|
+
{
|
|
413
|
+
if (*cred) {
|
|
414
|
+
git_cred_free(*cred);
|
|
415
|
+
(*cred) = NULL;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
static int apply_url_credentials(
|
|
420
|
+
git_cred **cred,
|
|
421
|
+
unsigned int allowed_types,
|
|
422
|
+
const char *username,
|
|
423
|
+
const char *password)
|
|
424
|
+
{
|
|
425
|
+
if (allowed_types & GIT_CREDTYPE_USERPASS_PLAINTEXT)
|
|
426
|
+
return git_cred_userpass_plaintext_new(cred, username, password);
|
|
427
|
+
|
|
428
|
+
if ((allowed_types & GIT_CREDTYPE_DEFAULT) && *username == '\0' && *password == '\0')
|
|
429
|
+
return git_cred_default_new(cred);
|
|
430
|
+
|
|
431
|
+
return GIT_PASSTHROUGH;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
static int init_auth(http_server *server)
|
|
435
|
+
{
|
|
436
|
+
git_http_auth_scheme *s, *scheme = NULL;
|
|
437
|
+
char *c, *challenge = NULL;
|
|
438
|
+
size_t i;
|
|
439
|
+
int error;
|
|
440
|
+
|
|
441
|
+
git_vector_foreach(&server->auth_challenges, i, c) {
|
|
442
|
+
s = scheme_for_challenge(c, server->cred);
|
|
443
|
+
|
|
444
|
+
if (s && !!(s->credtypes & server->credtypes)) {
|
|
445
|
+
scheme = s;
|
|
446
|
+
challenge = c;
|
|
447
|
+
break;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (!scheme) {
|
|
452
|
+
git_error_set(GIT_ERROR_NET, "no authentication mechanism could be negotiated");
|
|
453
|
+
return -1;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
if ((error = scheme->init_context(&server->auth_context, &server->url)) == GIT_PASSTHROUGH)
|
|
457
|
+
return 0;
|
|
458
|
+
else if (error < 0)
|
|
459
|
+
return error;
|
|
460
|
+
|
|
461
|
+
if (server->auth_context->set_challenge &&
|
|
462
|
+
(error = server->auth_context->set_challenge(server->auth_context, challenge)) < 0)
|
|
463
|
+
return error;
|
|
464
|
+
|
|
465
|
+
return 0;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
static int on_auth_required(
|
|
469
|
+
http_parser *parser,
|
|
470
|
+
http_server *server,
|
|
471
|
+
const char *url,
|
|
472
|
+
const char *type,
|
|
473
|
+
git_cred_acquire_cb callback,
|
|
474
|
+
void *callback_payload)
|
|
475
|
+
{
|
|
476
|
+
parser_context *ctx = (parser_context *) parser->data;
|
|
477
|
+
http_subtransport *t = ctx->t;
|
|
478
|
+
int error = 1;
|
|
479
|
+
|
|
480
|
+
if (parse_authenticate_response(server) < 0) {
|
|
481
|
+
t->parse_error = PARSE_ERROR_GENERIC;
|
|
482
|
+
return t->parse_error;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/* If we're in the middle of challenge/response auth, continue */
|
|
486
|
+
if (parser->status_code == 407 || parser->status_code == 401) {
|
|
487
|
+
if (server->auth_context && !auth_context_complete(server)) {
|
|
488
|
+
t->parse_error = PARSE_ERROR_REPLAY;
|
|
489
|
+
return 0;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/* Enforce a reasonable cap on the number of replays */
|
|
494
|
+
if (t->replay_count++ >= GIT_HTTP_REPLAY_MAX) {
|
|
495
|
+
git_error_set(GIT_ERROR_NET, "too many redirects or authentication replays");
|
|
496
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if (!server->credtypes) {
|
|
500
|
+
git_error_set(GIT_ERROR_NET, "%s requested authentication but did not negotiate mechanisms", type);
|
|
501
|
+
t->parse_error = PARSE_ERROR_GENERIC;
|
|
502
|
+
return t->parse_error;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
free_auth_context(server);
|
|
506
|
+
free_cred(&server->cred);
|
|
507
|
+
|
|
508
|
+
/* Start with URL-specified credentials, if there were any. */
|
|
509
|
+
if (!server->url_cred_presented && server->url.username && server->url.password) {
|
|
510
|
+
error = apply_url_credentials(&server->cred, server->credtypes, server->url.username, server->url.password);
|
|
511
|
+
server->url_cred_presented = 1;
|
|
512
|
+
|
|
513
|
+
if (error == GIT_PASSTHROUGH) {
|
|
514
|
+
/* treat GIT_PASSTHROUGH as if callback isn't set */
|
|
515
|
+
error = 1;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
if (error > 0 && callback) {
|
|
520
|
+
error = callback(&server->cred, url, server->url.username, server->credtypes, callback_payload);
|
|
521
|
+
|
|
522
|
+
if (error == GIT_PASSTHROUGH) {
|
|
523
|
+
/* treat GIT_PASSTHROUGH as if callback isn't set */
|
|
524
|
+
error = 1;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if (error > 0) {
|
|
529
|
+
git_error_set(GIT_ERROR_NET, "%s authentication required but no callback set",
|
|
530
|
+
type);
|
|
531
|
+
t->parse_error = PARSE_ERROR_GENERIC;
|
|
532
|
+
return t->parse_error;
|
|
533
|
+
} else if (error < 0) {
|
|
534
|
+
t->error = error;
|
|
535
|
+
t->parse_error = PARSE_ERROR_EXT;
|
|
536
|
+
return t->parse_error;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
assert(server->cred);
|
|
540
|
+
|
|
541
|
+
if (!(server->cred->credtype & server->credtypes)) {
|
|
542
|
+
git_error_set(GIT_ERROR_NET, "%s credential provider returned an invalid cred type", type);
|
|
543
|
+
t->parse_error = PARSE_ERROR_GENERIC;
|
|
544
|
+
return t->parse_error;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/* Successfully acquired a credential. Start an auth context. */
|
|
548
|
+
if (init_auth(server) < 0) {
|
|
549
|
+
t->parse_error = PARSE_ERROR_GENERIC;
|
|
550
|
+
return t->parse_error;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
t->parse_error = PARSE_ERROR_REPLAY;
|
|
554
|
+
return 0;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
static void on_auth_success(http_server *server)
|
|
558
|
+
{
|
|
559
|
+
server->url_cred_presented = 0;
|
|
560
|
+
server->authenticated = 1;
|
|
561
|
+
}
|
|
562
|
+
|
|
328
563
|
static int on_headers_complete(http_parser *parser)
|
|
329
564
|
{
|
|
330
565
|
parser_context *ctx = (parser_context *) parser->data;
|
|
331
566
|
http_subtransport *t = ctx->t;
|
|
332
567
|
http_stream *s = ctx->s;
|
|
333
568
|
git_buf buf = GIT_BUF_INIT;
|
|
334
|
-
int error = 0, no_callback = 0, allowed_auth_types = 0;
|
|
335
569
|
|
|
336
570
|
/* Both parse_header_name and parse_header_value are populated
|
|
337
571
|
* and ready for consumption. */
|
|
338
|
-
if (
|
|
339
|
-
if (on_header_ready(t) < 0)
|
|
340
|
-
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
341
|
-
|
|
342
|
-
/* Capture authentication headers which may be a 401 (authentication
|
|
343
|
-
* is not complete) or a 200 (simply informing us that auth *is*
|
|
344
|
-
* complete.)
|
|
345
|
-
*/
|
|
346
|
-
if (parse_authenticate_response(&t->www_authenticate, t,
|
|
347
|
-
&allowed_auth_types) < 0)
|
|
572
|
+
if (t->last_cb == VALUE && on_header_ready(t) < 0)
|
|
348
573
|
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
349
574
|
|
|
350
|
-
/* Check for
|
|
351
|
-
if (parser->status_code ==
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
error = t->owner->cred_acquire_cb(&t->cred,
|
|
362
|
-
t->owner->url,
|
|
363
|
-
t->connection_data.user,
|
|
364
|
-
allowed_auth_types,
|
|
365
|
-
t->owner->cred_acquire_payload);
|
|
366
|
-
|
|
367
|
-
if (error == GIT_PASSTHROUGH) {
|
|
368
|
-
no_callback = 1;
|
|
369
|
-
} else if (error < 0) {
|
|
370
|
-
t->error = error;
|
|
371
|
-
return t->parse_error = PARSE_ERROR_EXT;
|
|
372
|
-
} else {
|
|
373
|
-
assert(t->cred);
|
|
374
|
-
|
|
375
|
-
if (!(t->cred->credtype & allowed_auth_types)) {
|
|
376
|
-
giterr_set(GITERR_NET, "credentials callback returned an invalid cred type");
|
|
377
|
-
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/* Successfully acquired a credential. */
|
|
381
|
-
t->parse_error = PARSE_ERROR_REPLAY;
|
|
382
|
-
return 0;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
}
|
|
575
|
+
/* Check for a proxy authentication failure. */
|
|
576
|
+
if (parser->status_code == 407 && get_verb == s->verb)
|
|
577
|
+
return on_auth_required(
|
|
578
|
+
parser,
|
|
579
|
+
&t->proxy,
|
|
580
|
+
t->proxy_opts.url,
|
|
581
|
+
SERVER_TYPE_PROXY,
|
|
582
|
+
t->proxy_opts.credentials,
|
|
583
|
+
t->proxy_opts.payload);
|
|
584
|
+
else
|
|
585
|
+
on_auth_success(&t->proxy);
|
|
386
586
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
587
|
+
/* Check for an authentication failure. */
|
|
588
|
+
if (parser->status_code == 401 && get_verb == s->verb)
|
|
589
|
+
return on_auth_required(
|
|
590
|
+
parser,
|
|
591
|
+
&t->server,
|
|
592
|
+
t->owner->url,
|
|
593
|
+
SERVER_TYPE_REMOTE,
|
|
594
|
+
t->owner->cred_acquire_cb,
|
|
595
|
+
t->owner->cred_acquire_payload);
|
|
596
|
+
else
|
|
597
|
+
on_auth_success(&t->server);
|
|
392
598
|
|
|
393
599
|
/* Check for a redirect.
|
|
394
600
|
* Right now we only permit a redirect to the same hostname. */
|
|
395
601
|
if ((parser->status_code == 301 ||
|
|
396
602
|
parser->status_code == 302 ||
|
|
397
603
|
(parser->status_code == 303 && get_verb == s->verb) ||
|
|
398
|
-
parser->status_code == 307
|
|
604
|
+
parser->status_code == 307 ||
|
|
605
|
+
parser->status_code == 308) &&
|
|
399
606
|
t->location) {
|
|
400
607
|
|
|
401
|
-
if (s->
|
|
402
|
-
giterr_set(GITERR_NET, "too many redirects");
|
|
403
|
-
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
if (gitno_connection_data_from_url(&t->connection_data, t->location, s->service_url) < 0)
|
|
608
|
+
if (gitno_connection_data_handle_redirect(&t->server.url, t->location, s->service_url) < 0)
|
|
407
609
|
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
408
610
|
|
|
409
611
|
/* Set the redirect URL on the stream. This is a transfer of
|
|
@@ -415,15 +617,13 @@ static int on_headers_complete(http_parser *parser)
|
|
|
415
617
|
t->location = NULL;
|
|
416
618
|
|
|
417
619
|
t->connected = 0;
|
|
418
|
-
s->redirect_count++;
|
|
419
|
-
|
|
420
620
|
t->parse_error = PARSE_ERROR_REPLAY;
|
|
421
621
|
return 0;
|
|
422
622
|
}
|
|
423
623
|
|
|
424
624
|
/* Check for a 200 HTTP status code. */
|
|
425
625
|
if (parser->status_code != 200) {
|
|
426
|
-
|
|
626
|
+
git_error_set(GIT_ERROR_NET,
|
|
427
627
|
"unexpected HTTP status code: %d",
|
|
428
628
|
parser->status_code);
|
|
429
629
|
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
@@ -431,7 +631,7 @@ static int on_headers_complete(http_parser *parser)
|
|
|
431
631
|
|
|
432
632
|
/* The response must contain a Content-Type header. */
|
|
433
633
|
if (!t->content_type) {
|
|
434
|
-
|
|
634
|
+
git_error_set(GIT_ERROR_NET, "no Content-Type header in response");
|
|
435
635
|
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
436
636
|
}
|
|
437
637
|
|
|
@@ -450,7 +650,7 @@ static int on_headers_complete(http_parser *parser)
|
|
|
450
650
|
|
|
451
651
|
if (strcmp(t->content_type, git_buf_cstr(&buf))) {
|
|
452
652
|
git_buf_dispose(&buf);
|
|
453
|
-
|
|
653
|
+
git_error_set(GIT_ERROR_NET,
|
|
454
654
|
"invalid Content-Type: %s",
|
|
455
655
|
t->content_type);
|
|
456
656
|
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
@@ -467,6 +667,7 @@ static int on_message_complete(http_parser *parser)
|
|
|
467
667
|
http_subtransport *t = ctx->t;
|
|
468
668
|
|
|
469
669
|
t->parse_finished = 1;
|
|
670
|
+
t->keepalive = http_should_keep_alive(parser);
|
|
470
671
|
|
|
471
672
|
return 0;
|
|
472
673
|
}
|
|
@@ -476,22 +677,19 @@ static int on_body_fill_buffer(http_parser *parser, const char *str, size_t len)
|
|
|
476
677
|
parser_context *ctx = (parser_context *) parser->data;
|
|
477
678
|
http_subtransport *t = ctx->t;
|
|
478
679
|
|
|
479
|
-
/* If
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
680
|
+
/* If there's no buffer set, we're explicitly ignoring the body. */
|
|
681
|
+
if (ctx->buffer) {
|
|
682
|
+
if (ctx->buf_size < len) {
|
|
683
|
+
git_error_set(GIT_ERROR_NET, "can't fit data in the buffer");
|
|
684
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
685
|
+
}
|
|
485
686
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
687
|
+
memcpy(ctx->buffer, str, len);
|
|
688
|
+
ctx->buffer += len;
|
|
689
|
+
ctx->buf_size -= len;
|
|
489
690
|
}
|
|
490
691
|
|
|
491
|
-
memcpy(ctx->buffer, str, len);
|
|
492
692
|
*(ctx->bytes_read) += len;
|
|
493
|
-
ctx->buffer += len;
|
|
494
|
-
ctx->buf_size -= len;
|
|
495
693
|
|
|
496
694
|
return 0;
|
|
497
695
|
}
|
|
@@ -499,7 +697,7 @@ static int on_body_fill_buffer(http_parser *parser, const char *str, size_t len)
|
|
|
499
697
|
static void clear_parser_state(http_subtransport *t)
|
|
500
698
|
{
|
|
501
699
|
http_parser_init(&t->parser, HTTP_RESPONSE);
|
|
502
|
-
gitno_buffer_setup_fromstream(t->
|
|
700
|
+
gitno_buffer_setup_fromstream(t->server.stream,
|
|
503
701
|
&t->parse_buffer,
|
|
504
702
|
t->parse_buffer_data,
|
|
505
703
|
sizeof(t->parse_buffer_data));
|
|
@@ -507,6 +705,7 @@ static void clear_parser_state(http_subtransport *t)
|
|
|
507
705
|
t->last_cb = NONE;
|
|
508
706
|
t->parse_error = 0;
|
|
509
707
|
t->parse_finished = 0;
|
|
708
|
+
t->keepalive = 0;
|
|
510
709
|
|
|
511
710
|
git_buf_dispose(&t->parse_header_name);
|
|
512
711
|
git_buf_init(&t->parse_header_name, 0);
|
|
@@ -517,10 +716,14 @@ static void clear_parser_state(http_subtransport *t)
|
|
|
517
716
|
git__free(t->content_type);
|
|
518
717
|
t->content_type = NULL;
|
|
519
718
|
|
|
719
|
+
git__free(t->content_length);
|
|
720
|
+
t->content_length = NULL;
|
|
721
|
+
|
|
520
722
|
git__free(t->location);
|
|
521
723
|
t->location = NULL;
|
|
522
724
|
|
|
523
|
-
git_vector_free_deep(&t->
|
|
725
|
+
git_vector_free_deep(&t->proxy.auth_challenges);
|
|
726
|
+
git_vector_free_deep(&t->server.auth_challenges);
|
|
524
727
|
}
|
|
525
728
|
|
|
526
729
|
static int write_chunk(git_stream *io, const char *buffer, size_t len)
|
|
@@ -533,7 +736,7 @@ static int write_chunk(git_stream *io, const char *buffer, size_t len)
|
|
|
533
736
|
if (git_buf_oom(&buf))
|
|
534
737
|
return -1;
|
|
535
738
|
|
|
536
|
-
if (
|
|
739
|
+
if (git_stream__write_full(io, buf.ptr, buf.size, 0) < 0) {
|
|
537
740
|
git_buf_dispose(&buf);
|
|
538
741
|
return -1;
|
|
539
742
|
}
|
|
@@ -541,109 +744,416 @@ static int write_chunk(git_stream *io, const char *buffer, size_t len)
|
|
|
541
744
|
git_buf_dispose(&buf);
|
|
542
745
|
|
|
543
746
|
/* Chunk body */
|
|
544
|
-
if (len > 0 &&
|
|
747
|
+
if (len > 0 && git_stream__write_full(io, buffer, len, 0) < 0)
|
|
545
748
|
return -1;
|
|
546
749
|
|
|
547
750
|
/* Chunk footer */
|
|
548
|
-
if (
|
|
751
|
+
if (git_stream__write_full(io, "\r\n", 2, 0) < 0)
|
|
549
752
|
return -1;
|
|
550
753
|
|
|
551
754
|
return 0;
|
|
552
755
|
}
|
|
553
756
|
|
|
554
|
-
static int
|
|
757
|
+
static int load_proxy_config(http_subtransport *t)
|
|
555
758
|
{
|
|
556
759
|
int error;
|
|
557
|
-
git_proxy_t proxy_type;
|
|
558
760
|
|
|
559
|
-
|
|
761
|
+
switch (t->owner->proxy.type) {
|
|
762
|
+
case GIT_PROXY_NONE:
|
|
560
763
|
return 0;
|
|
561
764
|
|
|
562
|
-
|
|
765
|
+
case GIT_PROXY_AUTO:
|
|
766
|
+
git__free(t->proxy_url);
|
|
767
|
+
t->proxy_url = NULL;
|
|
563
768
|
|
|
564
|
-
|
|
565
|
-
return 0;
|
|
566
|
-
|
|
567
|
-
if (proxy_type == GIT_PROXY_AUTO) {
|
|
568
|
-
char *url;
|
|
569
|
-
git_proxy_options opts = GIT_PROXY_OPTIONS_INIT;
|
|
769
|
+
git_proxy_options_init(&t->proxy_opts, GIT_PROXY_OPTIONS_VERSION);
|
|
570
770
|
|
|
571
|
-
if ((error = git_remote__get_http_proxy(t->owner->owner,
|
|
771
|
+
if ((error = git_remote__get_http_proxy(t->owner->owner,
|
|
772
|
+
!strcmp(t->server.url.scheme, "https"), &t->proxy_url)) < 0)
|
|
572
773
|
return error;
|
|
573
774
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
775
|
+
if (!t->proxy_url)
|
|
776
|
+
return 0;
|
|
777
|
+
|
|
778
|
+
t->proxy_opts.type = GIT_PROXY_SPECIFIED;
|
|
779
|
+
t->proxy_opts.url = t->proxy_url;
|
|
780
|
+
t->proxy_opts.credentials = t->owner->proxy.credentials;
|
|
781
|
+
t->proxy_opts.certificate_check = t->owner->proxy.certificate_check;
|
|
782
|
+
t->proxy_opts.payload = t->owner->proxy.payload;
|
|
783
|
+
break;
|
|
581
784
|
|
|
582
|
-
|
|
785
|
+
case GIT_PROXY_SPECIFIED:
|
|
786
|
+
memcpy(&t->proxy_opts, &t->owner->proxy, sizeof(git_proxy_options));
|
|
787
|
+
break;
|
|
788
|
+
|
|
789
|
+
default:
|
|
790
|
+
assert(0);
|
|
791
|
+
return -1;
|
|
583
792
|
}
|
|
584
793
|
|
|
585
|
-
|
|
794
|
+
git_net_url_dispose(&t->proxy.url);
|
|
795
|
+
|
|
796
|
+
return git_net_url_parse(&t->proxy.url, t->proxy_opts.url);
|
|
586
797
|
}
|
|
587
798
|
|
|
588
|
-
static int
|
|
799
|
+
static int check_certificate(
|
|
800
|
+
git_stream *stream,
|
|
801
|
+
git_net_url *url,
|
|
802
|
+
int is_valid,
|
|
803
|
+
git_transport_certificate_check_cb cert_cb,
|
|
804
|
+
void *cert_cb_payload)
|
|
589
805
|
{
|
|
806
|
+
git_cert *cert;
|
|
807
|
+
git_error_state last_error = {0};
|
|
590
808
|
int error;
|
|
591
809
|
|
|
592
|
-
if (
|
|
593
|
-
|
|
594
|
-
t->parse_finished)
|
|
595
|
-
return 0;
|
|
810
|
+
if ((error = git_stream_certificate(&cert, stream)) < 0)
|
|
811
|
+
return error;
|
|
596
812
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
813
|
+
git_error_state_capture(&last_error, GIT_ECERTIFICATE);
|
|
814
|
+
|
|
815
|
+
error = cert_cb(cert, is_valid, url->host, cert_cb_payload);
|
|
816
|
+
|
|
817
|
+
if (error == GIT_PASSTHROUGH && !is_valid)
|
|
818
|
+
return git_error_state_restore(&last_error);
|
|
819
|
+
else if (error == GIT_PASSTHROUGH)
|
|
820
|
+
error = 0;
|
|
821
|
+
else if (error && !git_error_last())
|
|
822
|
+
git_error_set(GIT_ERROR_NET, "user rejected certificate for %s", url->host);
|
|
823
|
+
|
|
824
|
+
git_error_state_free(&last_error);
|
|
825
|
+
return error;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
static int stream_connect(
|
|
829
|
+
git_stream *stream,
|
|
830
|
+
git_net_url *url,
|
|
831
|
+
git_transport_certificate_check_cb cert_cb,
|
|
832
|
+
void *cb_payload)
|
|
833
|
+
{
|
|
834
|
+
int error;
|
|
835
|
+
|
|
836
|
+
GIT_ERROR_CHECK_VERSION(stream, GIT_STREAM_VERSION, "git_stream");
|
|
837
|
+
|
|
838
|
+
error = git_stream_connect(stream);
|
|
839
|
+
|
|
840
|
+
if (error && error != GIT_ECERTIFICATE)
|
|
841
|
+
return error;
|
|
842
|
+
|
|
843
|
+
if (git_stream_is_encrypted(stream) && cert_cb != NULL)
|
|
844
|
+
error = check_certificate(stream, url, !error, cert_cb, cb_payload);
|
|
845
|
+
|
|
846
|
+
return error;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
static int gen_connect_req(git_buf *buf, http_subtransport *t)
|
|
850
|
+
{
|
|
851
|
+
git_buf_printf(buf, "CONNECT %s:%s HTTP/1.1\r\n",
|
|
852
|
+
t->server.url.host, t->server.url.port);
|
|
853
|
+
|
|
854
|
+
git_buf_puts(buf, "User-Agent: ");
|
|
855
|
+
git_http__user_agent(buf);
|
|
856
|
+
git_buf_puts(buf, "\r\n");
|
|
857
|
+
|
|
858
|
+
git_buf_printf(buf, "Host: %s\r\n", t->proxy.url.host);
|
|
859
|
+
|
|
860
|
+
if (apply_credentials(buf, &t->proxy, AUTH_HEADER_PROXY) < 0)
|
|
861
|
+
return -1;
|
|
862
|
+
|
|
863
|
+
git_buf_puts(buf, "\r\n");
|
|
864
|
+
|
|
865
|
+
return git_buf_oom(buf) ? -1 : 0;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
static int proxy_headers_complete(http_parser *parser)
|
|
869
|
+
{
|
|
870
|
+
parser_context *ctx = (parser_context *) parser->data;
|
|
871
|
+
http_subtransport *t = ctx->t;
|
|
872
|
+
|
|
873
|
+
/* Both parse_header_name and parse_header_value are populated
|
|
874
|
+
* and ready for consumption. */
|
|
875
|
+
if (t->last_cb == VALUE && on_header_ready(t) < 0)
|
|
876
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
877
|
+
|
|
878
|
+
/*
|
|
879
|
+
* Capture authentication headers for the proxy or final endpoint,
|
|
880
|
+
* these may be 407/401 (authentication is not complete) or a 200
|
|
881
|
+
* (informing us that auth has completed).
|
|
882
|
+
*/
|
|
883
|
+
if (parse_authenticate_response(&t->proxy) < 0)
|
|
884
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
885
|
+
|
|
886
|
+
/* If we're in the middle of challenge/response auth, continue */
|
|
887
|
+
if (parser->status_code == 407) {
|
|
888
|
+
if (t->proxy.auth_context && !auth_context_complete(&t->proxy)) {
|
|
889
|
+
t->parse_error = PARSE_ERROR_REPLAY;
|
|
890
|
+
return 0;
|
|
891
|
+
}
|
|
602
892
|
}
|
|
603
893
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
error = git_curl_stream_new(&t->io, t->connection_data.host, t->connection_data.port);
|
|
609
|
-
#else
|
|
610
|
-
error = git_socket_stream_new(&t->io, t->connection_data.host, t->connection_data.port);
|
|
611
|
-
#endif
|
|
894
|
+
/* Enforce a reasonable cap on the number of replays */
|
|
895
|
+
if (t->replay_count++ >= GIT_HTTP_REPLAY_MAX) {
|
|
896
|
+
git_error_set(GIT_ERROR_NET, "too many redirects or authentication replays");
|
|
897
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
612
898
|
}
|
|
613
899
|
|
|
614
|
-
|
|
615
|
-
|
|
900
|
+
/* Check for a proxy authentication failure. */
|
|
901
|
+
if (parser->status_code == 407)
|
|
902
|
+
return on_auth_required(
|
|
903
|
+
parser,
|
|
904
|
+
&t->proxy,
|
|
905
|
+
t->proxy_opts.url,
|
|
906
|
+
SERVER_TYPE_PROXY,
|
|
907
|
+
t->proxy_opts.credentials,
|
|
908
|
+
t->proxy_opts.payload);
|
|
616
909
|
|
|
617
|
-
|
|
910
|
+
if (parser->status_code != 200) {
|
|
911
|
+
git_error_set(GIT_ERROR_NET, "unexpected status code from proxy: %d",
|
|
912
|
+
parser->status_code);
|
|
913
|
+
return t->parse_error = PARSE_ERROR_GENERIC;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
if (!t->content_length || strcmp(t->content_length, "0") == 0)
|
|
917
|
+
t->parse_finished = 1;
|
|
618
918
|
|
|
619
|
-
|
|
919
|
+
return 0;
|
|
920
|
+
}
|
|
620
921
|
|
|
621
|
-
|
|
922
|
+
static int proxy_connect(
|
|
923
|
+
git_stream **out, git_stream *proxy_stream, http_subtransport *t)
|
|
924
|
+
{
|
|
925
|
+
git_buf request = GIT_BUF_INIT;
|
|
926
|
+
static http_parser_settings proxy_parser_settings = {0};
|
|
927
|
+
size_t bytes_read = 0, bytes_parsed;
|
|
928
|
+
parser_context ctx;
|
|
929
|
+
bool auth_replay;
|
|
930
|
+
int error;
|
|
622
931
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
932
|
+
/* Use the parser settings only to parser headers. */
|
|
933
|
+
proxy_parser_settings.on_header_field = on_header_field;
|
|
934
|
+
proxy_parser_settings.on_header_value = on_header_value;
|
|
935
|
+
proxy_parser_settings.on_headers_complete = proxy_headers_complete;
|
|
936
|
+
proxy_parser_settings.on_message_complete = on_message_complete;
|
|
627
937
|
|
|
628
|
-
|
|
629
|
-
|
|
938
|
+
replay:
|
|
939
|
+
clear_parser_state(t);
|
|
630
940
|
|
|
631
|
-
|
|
632
|
-
error = t->owner->certificate_check_cb(cert, is_valid, t->connection_data.host, t->owner->message_cb_payload);
|
|
941
|
+
auth_replay = false;
|
|
633
942
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
943
|
+
gitno_buffer_setup_fromstream(proxy_stream,
|
|
944
|
+
&t->parse_buffer,
|
|
945
|
+
t->parse_buffer_data,
|
|
946
|
+
sizeof(t->parse_buffer_data));
|
|
637
947
|
|
|
638
|
-
|
|
948
|
+
if ((error = gen_connect_req(&request, t)) < 0)
|
|
949
|
+
goto done;
|
|
950
|
+
|
|
951
|
+
if ((error = git_stream__write_full(proxy_stream, request.ptr,
|
|
952
|
+
request.size, 0)) < 0)
|
|
953
|
+
goto done;
|
|
954
|
+
|
|
955
|
+
git_buf_dispose(&request);
|
|
956
|
+
|
|
957
|
+
while (!bytes_read && !t->parse_finished) {
|
|
958
|
+
t->parse_buffer.offset = 0;
|
|
959
|
+
|
|
960
|
+
if ((error = gitno_recv(&t->parse_buffer)) < 0) {
|
|
961
|
+
goto done;
|
|
962
|
+
} else if (error == 0 && t->request_count > 0) {
|
|
963
|
+
/* Server closed a keep-alive socket; reconnect. */
|
|
964
|
+
auth_replay = true;
|
|
965
|
+
goto done;
|
|
966
|
+
} else if (error == 0) {
|
|
967
|
+
git_error_set(GIT_ERROR_NET, "unexpected disconnection from server");
|
|
968
|
+
error = -1;
|
|
969
|
+
goto done;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/*
|
|
973
|
+
* This call to http_parser_execute will invoke the on_*
|
|
974
|
+
* callbacks. Since we don't care about the body of the response,
|
|
975
|
+
* we can set our buffer to NULL.
|
|
976
|
+
*/
|
|
977
|
+
ctx.t = t;
|
|
978
|
+
ctx.s = NULL;
|
|
979
|
+
ctx.buffer = NULL;
|
|
980
|
+
ctx.buf_size = 0;
|
|
981
|
+
ctx.bytes_read = &bytes_read;
|
|
982
|
+
|
|
983
|
+
/* Set the context, call the parser, then unset the context. */
|
|
984
|
+
t->parser.data = &ctx;
|
|
985
|
+
|
|
986
|
+
bytes_parsed = http_parser_execute(&t->parser,
|
|
987
|
+
&proxy_parser_settings, t->parse_buffer.data, t->parse_buffer.offset);
|
|
988
|
+
|
|
989
|
+
t->parser.data = NULL;
|
|
990
|
+
|
|
991
|
+
/* Ensure that we didn't get a redirect; unsupported. */
|
|
992
|
+
if (t->location) {
|
|
993
|
+
git_error_set(GIT_ERROR_NET, "proxy server sent unsupported redirect during CONNECT");
|
|
994
|
+
error = -1;
|
|
995
|
+
goto done;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
/* Replay the request with authentication headers. */
|
|
999
|
+
if (PARSE_ERROR_REPLAY == t->parse_error) {
|
|
1000
|
+
auth_replay = true;
|
|
1001
|
+
} else if (t->parse_error < 0) {
|
|
1002
|
+
error = t->parse_error == PARSE_ERROR_EXT ? PARSE_ERROR_EXT : -1;
|
|
1003
|
+
goto done;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
if (bytes_parsed != t->parse_buffer.offset) {
|
|
1007
|
+
git_error_set(GIT_ERROR_NET,
|
|
1008
|
+
"HTTP parser error: %s",
|
|
1009
|
+
http_errno_description((enum http_errno)t->parser.http_errno));
|
|
1010
|
+
error = -1;
|
|
1011
|
+
goto done;
|
|
639
1012
|
}
|
|
640
1013
|
}
|
|
641
1014
|
|
|
642
|
-
|
|
1015
|
+
t->request_count++;
|
|
1016
|
+
|
|
1017
|
+
if (auth_replay) {
|
|
1018
|
+
if (t->keepalive && t->parse_finished)
|
|
1019
|
+
goto replay;
|
|
1020
|
+
|
|
1021
|
+
return PARSE_ERROR_REPLAY;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
if ((error = git_tls_stream_wrap(out, proxy_stream, t->server.url.host)) == 0)
|
|
1025
|
+
error = stream_connect(*out, &t->server.url,
|
|
1026
|
+
t->owner->certificate_check_cb,
|
|
1027
|
+
t->owner->message_cb_payload);
|
|
1028
|
+
|
|
1029
|
+
/*
|
|
1030
|
+
* Since we've connected via a HTTPS proxy tunnel, we don't behave
|
|
1031
|
+
* as if we have an HTTP proxy.
|
|
1032
|
+
*/
|
|
1033
|
+
t->proxy_opts.type = GIT_PROXY_NONE;
|
|
1034
|
+
t->replay_count = 0;
|
|
1035
|
+
t->request_count = 0;
|
|
1036
|
+
|
|
1037
|
+
done:
|
|
1038
|
+
return error;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
static void reset_auth_connection(http_server *server)
|
|
1042
|
+
{
|
|
1043
|
+
/*
|
|
1044
|
+
* If we've authenticated and we're doing "normal"
|
|
1045
|
+
* authentication with a request affinity (Basic, Digest)
|
|
1046
|
+
* then we want to _keep_ our context, since authentication
|
|
1047
|
+
* survives even through non-keep-alive connections. If
|
|
1048
|
+
* we've authenticated and we're doing connection-based
|
|
1049
|
+
* authentication (NTLM, Negotiate) - indicated by the presence
|
|
1050
|
+
* of an `is_complete` callback - then we need to restart
|
|
1051
|
+
* authentication on a new connection.
|
|
1052
|
+
*/
|
|
1053
|
+
|
|
1054
|
+
if (server->authenticated &&
|
|
1055
|
+
server->auth_context &&
|
|
1056
|
+
server->auth_context->connection_affinity) {
|
|
1057
|
+
free_auth_context(server);
|
|
1058
|
+
|
|
1059
|
+
server->url_cred_presented = 0;
|
|
1060
|
+
server->authenticated = 0;
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
static int http_connect(http_subtransport *t)
|
|
1065
|
+
{
|
|
1066
|
+
git_net_url *url;
|
|
1067
|
+
git_stream *proxy_stream = NULL, *stream = NULL;
|
|
1068
|
+
git_transport_certificate_check_cb cert_cb;
|
|
1069
|
+
void *cb_payload;
|
|
1070
|
+
int error;
|
|
1071
|
+
|
|
1072
|
+
auth_replay:
|
|
1073
|
+
if (t->connected && t->keepalive && t->parse_finished)
|
|
1074
|
+
return 0;
|
|
1075
|
+
|
|
1076
|
+
if ((error = load_proxy_config(t)) < 0)
|
|
643
1077
|
return error;
|
|
644
1078
|
|
|
1079
|
+
if (t->server.stream) {
|
|
1080
|
+
git_stream_close(t->server.stream);
|
|
1081
|
+
git_stream_free(t->server.stream);
|
|
1082
|
+
t->server.stream = NULL;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
if (t->proxy.stream) {
|
|
1086
|
+
git_stream_close(t->proxy.stream);
|
|
1087
|
+
git_stream_free(t->proxy.stream);
|
|
1088
|
+
t->proxy.stream = NULL;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
reset_auth_connection(&t->server);
|
|
1092
|
+
reset_auth_connection(&t->proxy);
|
|
1093
|
+
|
|
1094
|
+
t->connected = 0;
|
|
1095
|
+
t->keepalive = 0;
|
|
1096
|
+
t->request_count = 0;
|
|
1097
|
+
|
|
1098
|
+
if (t->proxy_opts.type == GIT_PROXY_SPECIFIED) {
|
|
1099
|
+
url = &t->proxy.url;
|
|
1100
|
+
cert_cb = t->proxy_opts.certificate_check;
|
|
1101
|
+
cb_payload = t->proxy_opts.payload;
|
|
1102
|
+
} else {
|
|
1103
|
+
url = &t->server.url;
|
|
1104
|
+
cert_cb = t->owner->certificate_check_cb;
|
|
1105
|
+
cb_payload = t->owner->message_cb_payload;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
if (strcmp(url->scheme, "https") == 0)
|
|
1109
|
+
error = git_tls_stream_new(&stream, url->host, url->port);
|
|
1110
|
+
else
|
|
1111
|
+
error = git_socket_stream_new(&stream, url->host, url->port);
|
|
1112
|
+
|
|
1113
|
+
if (error < 0)
|
|
1114
|
+
goto on_error;
|
|
1115
|
+
|
|
1116
|
+
if ((error = stream_connect(stream, url, cert_cb, cb_payload)) < 0)
|
|
1117
|
+
goto on_error;
|
|
1118
|
+
|
|
1119
|
+
/*
|
|
1120
|
+
* At this point we have a connection to the remote server or to
|
|
1121
|
+
* a proxy. If it's a proxy and the remote server is actually
|
|
1122
|
+
* an HTTPS connection, then we need to build a CONNECT tunnel.
|
|
1123
|
+
*/
|
|
1124
|
+
if (t->proxy_opts.type == GIT_PROXY_SPECIFIED &&
|
|
1125
|
+
strcmp(t->server.url.scheme, "https") == 0) {
|
|
1126
|
+
proxy_stream = stream;
|
|
1127
|
+
stream = NULL;
|
|
1128
|
+
|
|
1129
|
+
error = proxy_connect(&stream, proxy_stream, t);
|
|
1130
|
+
|
|
1131
|
+
if (error == PARSE_ERROR_REPLAY) {
|
|
1132
|
+
git_stream_close(proxy_stream);
|
|
1133
|
+
git_stream_free(proxy_stream);
|
|
1134
|
+
goto auth_replay;
|
|
1135
|
+
} else if (error < 0) {
|
|
1136
|
+
goto on_error;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
t->proxy.stream = proxy_stream;
|
|
1141
|
+
t->server.stream = stream;
|
|
645
1142
|
t->connected = 1;
|
|
646
1143
|
return 0;
|
|
1144
|
+
|
|
1145
|
+
on_error:
|
|
1146
|
+
if (stream) {
|
|
1147
|
+
git_stream_close(stream);
|
|
1148
|
+
git_stream_free(stream);
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
if (proxy_stream) {
|
|
1152
|
+
git_stream_close(proxy_stream);
|
|
1153
|
+
git_stream_free(proxy_stream);
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
return error;
|
|
647
1157
|
}
|
|
648
1158
|
|
|
649
1159
|
static int http_stream_read(
|
|
@@ -656,26 +1166,23 @@ static int http_stream_read(
|
|
|
656
1166
|
http_subtransport *t = OWNING_SUBTRANSPORT(s);
|
|
657
1167
|
parser_context ctx;
|
|
658
1168
|
size_t bytes_parsed;
|
|
1169
|
+
git_buf request = GIT_BUF_INIT;
|
|
1170
|
+
bool auth_replay;
|
|
1171
|
+
int error = 0;
|
|
659
1172
|
|
|
660
1173
|
replay:
|
|
661
1174
|
*bytes_read = 0;
|
|
1175
|
+
auth_replay = false;
|
|
662
1176
|
|
|
663
1177
|
assert(t->connected);
|
|
664
1178
|
|
|
665
1179
|
if (!s->sent_request) {
|
|
666
|
-
|
|
667
|
-
|
|
1180
|
+
git_buf_clear(&request);
|
|
668
1181
|
clear_parser_state(t);
|
|
669
1182
|
|
|
670
|
-
if (gen_request(&request, s, 0) < 0
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
if (git_stream_write(t->io, request.ptr, request.size, 0) < 0) {
|
|
674
|
-
git_buf_dispose(&request);
|
|
675
|
-
return -1;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
git_buf_dispose(&request);
|
|
1183
|
+
if ((error = gen_request(&request, s, 0)) < 0 ||
|
|
1184
|
+
(error = git_stream__write_full(t->server.stream, request.ptr, request.size, 0)) < 0)
|
|
1185
|
+
goto done;
|
|
679
1186
|
|
|
680
1187
|
s->sent_request = 1;
|
|
681
1188
|
}
|
|
@@ -685,15 +1192,17 @@ replay:
|
|
|
685
1192
|
assert(s->verb == post_verb);
|
|
686
1193
|
|
|
687
1194
|
/* Flush, if necessary */
|
|
688
|
-
if (s->chunk_buffer_len > 0
|
|
689
|
-
write_chunk(t->
|
|
690
|
-
|
|
1195
|
+
if (s->chunk_buffer_len > 0) {
|
|
1196
|
+
if ((error = write_chunk(t->server.stream, s->chunk_buffer, s->chunk_buffer_len)) < 0)
|
|
1197
|
+
goto done;
|
|
691
1198
|
|
|
692
|
-
|
|
1199
|
+
s->chunk_buffer_len = 0;
|
|
1200
|
+
}
|
|
693
1201
|
|
|
694
1202
|
/* Write the final chunk. */
|
|
695
|
-
if (
|
|
696
|
-
|
|
1203
|
+
if ((error = git_stream__write_full(t->server.stream,
|
|
1204
|
+
"0\r\n\r\n", 5, 0)) < 0)
|
|
1205
|
+
goto done;
|
|
697
1206
|
}
|
|
698
1207
|
|
|
699
1208
|
s->received_response = 1;
|
|
@@ -701,7 +1210,6 @@ replay:
|
|
|
701
1210
|
|
|
702
1211
|
while (!*bytes_read && !t->parse_finished) {
|
|
703
1212
|
size_t data_offset;
|
|
704
|
-
int error;
|
|
705
1213
|
|
|
706
1214
|
/*
|
|
707
1215
|
* Make the parse_buffer think it's as full of data as
|
|
@@ -711,26 +1219,37 @@ replay:
|
|
|
711
1219
|
* data_offset is the actual data offset from which we
|
|
712
1220
|
* should tell the parser to start reading.
|
|
713
1221
|
*/
|
|
714
|
-
if (buf_size >= t->parse_buffer.len)
|
|
1222
|
+
if (buf_size >= t->parse_buffer.len)
|
|
715
1223
|
t->parse_buffer.offset = 0;
|
|
716
|
-
|
|
1224
|
+
else
|
|
717
1225
|
t->parse_buffer.offset = t->parse_buffer.len - buf_size;
|
|
718
|
-
}
|
|
719
1226
|
|
|
720
1227
|
data_offset = t->parse_buffer.offset;
|
|
721
1228
|
|
|
722
|
-
if (gitno_recv(&t->parse_buffer) < 0)
|
|
723
|
-
|
|
1229
|
+
if ((error = gitno_recv(&t->parse_buffer)) < 0) {
|
|
1230
|
+
goto done;
|
|
1231
|
+
} else if (error == 0 && t->request_count > 0) {
|
|
1232
|
+
/* Server closed a keep-alive socket; reconnect. */
|
|
1233
|
+
auth_replay = true;
|
|
1234
|
+
goto done;
|
|
1235
|
+
} else if (error == 0) {
|
|
1236
|
+
git_error_set(GIT_ERROR_NET, "unexpected disconnection from server");
|
|
1237
|
+
error = -1;
|
|
1238
|
+
goto done;
|
|
1239
|
+
}
|
|
724
1240
|
|
|
725
|
-
/*
|
|
726
|
-
*
|
|
727
|
-
*
|
|
728
|
-
* into the target buffer.
|
|
729
|
-
*
|
|
1241
|
+
/*
|
|
1242
|
+
* This call to http_parser_execute will result in invocations
|
|
1243
|
+
* of the on_* family of callbacks, including on_body_fill_buffer
|
|
1244
|
+
* which will write into the target buffer. Set up the buffer
|
|
1245
|
+
* for it to write into _unless_ we got an auth failure; in
|
|
1246
|
+
* that case we only care about the headers and don't need to
|
|
1247
|
+
* bother copying the body.
|
|
1248
|
+
*/
|
|
730
1249
|
ctx.t = t;
|
|
731
1250
|
ctx.s = s;
|
|
732
|
-
ctx.buffer = buffer;
|
|
733
|
-
ctx.buf_size = buf_size;
|
|
1251
|
+
ctx.buffer = auth_replay ? NULL : buffer;
|
|
1252
|
+
ctx.buf_size = auth_replay ? 0 : buf_size;
|
|
734
1253
|
ctx.bytes_read = bytes_read;
|
|
735
1254
|
|
|
736
1255
|
/* Set the context, call the parser, then unset the context. */
|
|
@@ -743,33 +1262,40 @@ replay:
|
|
|
743
1262
|
|
|
744
1263
|
t->parser.data = NULL;
|
|
745
1264
|
|
|
746
|
-
/*
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
goto
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
if (t->parse_error == PARSE_ERROR_EXT) {
|
|
758
|
-
return t->error;
|
|
1265
|
+
/* On a 401, read the rest of the response then retry. */
|
|
1266
|
+
if (t->parse_error == PARSE_ERROR_REPLAY) {
|
|
1267
|
+
auth_replay = true;
|
|
1268
|
+
} else if (t->parse_error == PARSE_ERROR_EXT) {
|
|
1269
|
+
error = t->error;
|
|
1270
|
+
goto done;
|
|
1271
|
+
} else if (t->parse_error < 0) {
|
|
1272
|
+
error = -1;
|
|
1273
|
+
goto done;
|
|
759
1274
|
}
|
|
760
1275
|
|
|
761
|
-
if (t->parse_error < 0)
|
|
762
|
-
return -1;
|
|
763
|
-
|
|
764
1276
|
if (bytes_parsed != t->parse_buffer.offset - data_offset) {
|
|
765
|
-
|
|
1277
|
+
git_error_set(GIT_ERROR_NET,
|
|
766
1278
|
"HTTP parser error: %s",
|
|
767
1279
|
http_errno_description((enum http_errno)t->parser.http_errno));
|
|
768
|
-
|
|
1280
|
+
error = -1;
|
|
1281
|
+
goto done;
|
|
769
1282
|
}
|
|
770
1283
|
}
|
|
771
1284
|
|
|
772
|
-
|
|
1285
|
+
t->request_count++;
|
|
1286
|
+
|
|
1287
|
+
if (auth_replay) {
|
|
1288
|
+
s->sent_request = 0;
|
|
1289
|
+
|
|
1290
|
+
if ((error = http_connect(t)) < 0)
|
|
1291
|
+
return error;
|
|
1292
|
+
|
|
1293
|
+
goto replay;
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
done:
|
|
1297
|
+
git_buf_dispose(&request);
|
|
1298
|
+
return error;
|
|
773
1299
|
}
|
|
774
1300
|
|
|
775
1301
|
static int http_stream_write_chunked(
|
|
@@ -777,7 +1303,7 @@ static int http_stream_write_chunked(
|
|
|
777
1303
|
const char *buffer,
|
|
778
1304
|
size_t len)
|
|
779
1305
|
{
|
|
780
|
-
http_stream *s = (http_stream
|
|
1306
|
+
http_stream *s = GIT_CONTAINER_OF(stream, http_stream, parent);
|
|
781
1307
|
http_subtransport *t = OWNING_SUBTRANSPORT(s);
|
|
782
1308
|
|
|
783
1309
|
assert(t->connected);
|
|
@@ -791,7 +1317,8 @@ static int http_stream_write_chunked(
|
|
|
791
1317
|
if (gen_request(&request, s, 0) < 0)
|
|
792
1318
|
return -1;
|
|
793
1319
|
|
|
794
|
-
if (
|
|
1320
|
+
if (git_stream__write_full(t->server.stream, request.ptr,
|
|
1321
|
+
request.size, 0) < 0) {
|
|
795
1322
|
git_buf_dispose(&request);
|
|
796
1323
|
return -1;
|
|
797
1324
|
}
|
|
@@ -804,22 +1331,25 @@ static int http_stream_write_chunked(
|
|
|
804
1331
|
if (len > CHUNK_SIZE) {
|
|
805
1332
|
/* Flush, if necessary */
|
|
806
1333
|
if (s->chunk_buffer_len > 0) {
|
|
807
|
-
if (write_chunk(t->
|
|
1334
|
+
if (write_chunk(t->server.stream,
|
|
1335
|
+
s->chunk_buffer, s->chunk_buffer_len) < 0)
|
|
808
1336
|
return -1;
|
|
809
1337
|
|
|
810
1338
|
s->chunk_buffer_len = 0;
|
|
811
1339
|
}
|
|
812
1340
|
|
|
813
1341
|
/* Write chunk directly */
|
|
814
|
-
if (write_chunk(t->
|
|
1342
|
+
if (write_chunk(t->server.stream, buffer, len) < 0)
|
|
815
1343
|
return -1;
|
|
816
1344
|
}
|
|
817
1345
|
else {
|
|
818
1346
|
/* Append as much to the buffer as we can */
|
|
819
1347
|
int count = min(CHUNK_SIZE - s->chunk_buffer_len, len);
|
|
820
1348
|
|
|
821
|
-
if (!s->chunk_buffer)
|
|
1349
|
+
if (!s->chunk_buffer) {
|
|
822
1350
|
s->chunk_buffer = git__malloc(CHUNK_SIZE);
|
|
1351
|
+
GIT_ERROR_CHECK_ALLOC(s->chunk_buffer);
|
|
1352
|
+
}
|
|
823
1353
|
|
|
824
1354
|
memcpy(s->chunk_buffer + s->chunk_buffer_len, buffer, count);
|
|
825
1355
|
s->chunk_buffer_len += count;
|
|
@@ -828,7 +1358,8 @@ static int http_stream_write_chunked(
|
|
|
828
1358
|
|
|
829
1359
|
/* Is the buffer full? If so, then flush */
|
|
830
1360
|
if (CHUNK_SIZE == s->chunk_buffer_len) {
|
|
831
|
-
if (write_chunk(t->
|
|
1361
|
+
if (write_chunk(t->server.stream,
|
|
1362
|
+
s->chunk_buffer, s->chunk_buffer_len) < 0)
|
|
832
1363
|
return -1;
|
|
833
1364
|
|
|
834
1365
|
s->chunk_buffer_len = 0;
|
|
@@ -848,14 +1379,14 @@ static int http_stream_write_single(
|
|
|
848
1379
|
const char *buffer,
|
|
849
1380
|
size_t len)
|
|
850
1381
|
{
|
|
851
|
-
http_stream *s = (http_stream
|
|
1382
|
+
http_stream *s = GIT_CONTAINER_OF(stream, http_stream, parent);
|
|
852
1383
|
http_subtransport *t = OWNING_SUBTRANSPORT(s);
|
|
853
1384
|
git_buf request = GIT_BUF_INIT;
|
|
854
1385
|
|
|
855
1386
|
assert(t->connected);
|
|
856
1387
|
|
|
857
1388
|
if (s->sent_request) {
|
|
858
|
-
|
|
1389
|
+
git_error_set(GIT_ERROR_NET, "subtransport configured for only one write");
|
|
859
1390
|
return -1;
|
|
860
1391
|
}
|
|
861
1392
|
|
|
@@ -864,10 +1395,10 @@ static int http_stream_write_single(
|
|
|
864
1395
|
if (gen_request(&request, s, len) < 0)
|
|
865
1396
|
return -1;
|
|
866
1397
|
|
|
867
|
-
if (
|
|
1398
|
+
if (git_stream__write_full(t->server.stream, request.ptr, request.size, 0) < 0)
|
|
868
1399
|
goto on_error;
|
|
869
1400
|
|
|
870
|
-
if (len &&
|
|
1401
|
+
if (len && git_stream__write_full(t->server.stream, buffer, len, 0) < 0)
|
|
871
1402
|
goto on_error;
|
|
872
1403
|
|
|
873
1404
|
git_buf_dispose(&request);
|
|
@@ -882,7 +1413,7 @@ on_error:
|
|
|
882
1413
|
|
|
883
1414
|
static void http_stream_free(git_smart_subtransport_stream *stream)
|
|
884
1415
|
{
|
|
885
|
-
http_stream *s = (http_stream
|
|
1416
|
+
http_stream *s = GIT_CONTAINER_OF(stream, http_stream, parent);
|
|
886
1417
|
|
|
887
1418
|
if (s->chunk_buffer)
|
|
888
1419
|
git__free(s->chunk_buffer);
|
|
@@ -902,7 +1433,7 @@ static int http_stream_alloc(http_subtransport *t,
|
|
|
902
1433
|
return -1;
|
|
903
1434
|
|
|
904
1435
|
s = git__calloc(sizeof(http_stream), 1);
|
|
905
|
-
|
|
1436
|
+
GIT_ERROR_CHECK_ALLOC(s);
|
|
906
1437
|
|
|
907
1438
|
s->parent.subtransport = &t->parent;
|
|
908
1439
|
s->parent.read = http_stream_read;
|
|
@@ -995,16 +1526,24 @@ static int http_action(
|
|
|
995
1526
|
const char *url,
|
|
996
1527
|
git_smart_service_t action)
|
|
997
1528
|
{
|
|
998
|
-
http_subtransport *t = (http_subtransport
|
|
1529
|
+
http_subtransport *t = GIT_CONTAINER_OF(subtransport, http_subtransport, parent);
|
|
999
1530
|
int ret;
|
|
1000
1531
|
|
|
1001
|
-
|
|
1002
|
-
return -1;
|
|
1532
|
+
assert(stream);
|
|
1003
1533
|
|
|
1004
|
-
|
|
1005
|
-
|
|
1534
|
+
/*
|
|
1535
|
+
* If we've seen a redirect then preserve the location that we've
|
|
1536
|
+
* been given. This is important to continue authorization against
|
|
1537
|
+
* the redirect target, not the user-given source; the endpoint may
|
|
1538
|
+
* have redirected us from HTTP->HTTPS and is using an auth mechanism
|
|
1539
|
+
* that would be insecure in plaintext (eg, HTTP Basic).
|
|
1540
|
+
*/
|
|
1541
|
+
if ((!t->server.url.host || !t->server.url.port || !t->server.url.path) &&
|
|
1542
|
+
(ret = git_net_url_parse(&t->server.url, url)) < 0)
|
|
1006
1543
|
return ret;
|
|
1007
1544
|
|
|
1545
|
+
assert(t->server.url.host && t->server.url.port && t->server.url.path);
|
|
1546
|
+
|
|
1008
1547
|
if ((ret = http_connect(t)) < 0)
|
|
1009
1548
|
return ret;
|
|
1010
1549
|
|
|
@@ -1028,50 +1567,47 @@ static int http_action(
|
|
|
1028
1567
|
|
|
1029
1568
|
static int http_close(git_smart_subtransport *subtransport)
|
|
1030
1569
|
{
|
|
1031
|
-
http_subtransport *t = (http_subtransport
|
|
1032
|
-
git_http_auth_context *context;
|
|
1033
|
-
size_t i;
|
|
1570
|
+
http_subtransport *t = GIT_CONTAINER_OF(subtransport, http_subtransport, parent);
|
|
1034
1571
|
|
|
1035
1572
|
clear_parser_state(t);
|
|
1036
1573
|
|
|
1037
1574
|
t->connected = 0;
|
|
1038
1575
|
|
|
1039
|
-
if (t->
|
|
1040
|
-
git_stream_close(t->
|
|
1041
|
-
git_stream_free(t->
|
|
1042
|
-
t->
|
|
1576
|
+
if (t->server.stream) {
|
|
1577
|
+
git_stream_close(t->server.stream);
|
|
1578
|
+
git_stream_free(t->server.stream);
|
|
1579
|
+
t->server.stream = NULL;
|
|
1043
1580
|
}
|
|
1044
1581
|
|
|
1045
|
-
if (t->
|
|
1046
|
-
|
|
1047
|
-
t->
|
|
1582
|
+
if (t->proxy.stream) {
|
|
1583
|
+
git_stream_close(t->proxy.stream);
|
|
1584
|
+
git_stream_free(t->proxy.stream);
|
|
1585
|
+
t->proxy.stream = NULL;
|
|
1048
1586
|
}
|
|
1049
1587
|
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
t->url_cred = NULL;
|
|
1053
|
-
}
|
|
1588
|
+
free_cred(&t->server.cred);
|
|
1589
|
+
free_cred(&t->proxy.cred);
|
|
1054
1590
|
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1591
|
+
free_auth_context(&t->server);
|
|
1592
|
+
free_auth_context(&t->proxy);
|
|
1593
|
+
|
|
1594
|
+
t->server.url_cred_presented = false;
|
|
1595
|
+
t->proxy.url_cred_presented = false;
|
|
1059
1596
|
|
|
1060
|
-
|
|
1597
|
+
git_net_url_dispose(&t->server.url);
|
|
1598
|
+
git_net_url_dispose(&t->proxy.url);
|
|
1061
1599
|
|
|
1062
|
-
|
|
1063
|
-
|
|
1600
|
+
git__free(t->proxy_url);
|
|
1601
|
+
t->proxy_url = NULL;
|
|
1064
1602
|
|
|
1065
1603
|
return 0;
|
|
1066
1604
|
}
|
|
1067
1605
|
|
|
1068
1606
|
static void http_free(git_smart_subtransport *subtransport)
|
|
1069
1607
|
{
|
|
1070
|
-
http_subtransport *t = (http_subtransport
|
|
1608
|
+
http_subtransport *t = GIT_CONTAINER_OF(subtransport, http_subtransport, parent);
|
|
1071
1609
|
|
|
1072
1610
|
http_close(subtransport);
|
|
1073
|
-
|
|
1074
|
-
git_vector_free(&t->auth_contexts);
|
|
1075
1611
|
git__free(t);
|
|
1076
1612
|
}
|
|
1077
1613
|
|
|
@@ -1085,7 +1621,7 @@ int git_smart_subtransport_http(git_smart_subtransport **out, git_transport *own
|
|
|
1085
1621
|
return -1;
|
|
1086
1622
|
|
|
1087
1623
|
t = git__calloc(sizeof(http_subtransport), 1);
|
|
1088
|
-
|
|
1624
|
+
GIT_ERROR_CHECK_ALLOC(t);
|
|
1089
1625
|
|
|
1090
1626
|
t->owner = (transport_smart *)owner;
|
|
1091
1627
|
t->parent.action = http_action;
|