rugged 1.6.3 → 1.9.0
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/ext/rugged/rugged_allocator.c +0 -54
- data/lib/rugged/version.rb +1 -1
- data/vendor/libgit2/AUTHORS +1 -0
- data/vendor/libgit2/CMakeLists.txt +25 -17
- data/vendor/libgit2/COPYING +195 -1
- data/vendor/libgit2/cmake/CheckPrototypeDefinitionSafe.cmake +16 -0
- data/vendor/libgit2/cmake/{FindIconv.cmake → FindIntlIconv.cmake} +6 -0
- data/vendor/libgit2/cmake/FindLLHTTP.cmake +39 -0
- data/vendor/libgit2/cmake/SelectGSSAPI.cmake +4 -4
- data/vendor/libgit2/cmake/SelectHTTPParser.cmake +23 -8
- data/vendor/libgit2/cmake/SelectHTTPSBackend.cmake +34 -6
- data/vendor/libgit2/cmake/SelectHashes.cmake +32 -11
- data/vendor/libgit2/cmake/SelectRegex.cmake +6 -1
- data/vendor/libgit2/cmake/SelectSSH.cmake +22 -17
- data/vendor/libgit2/cmake/SelectXdiff.cmake +9 -0
- data/vendor/libgit2/cmake/SelectZlib.cmake +4 -0
- data/vendor/libgit2/deps/llhttp/CMakeLists.txt +8 -0
- data/vendor/libgit2/deps/llhttp/LICENSE-MIT +22 -0
- data/vendor/libgit2/deps/llhttp/api.c +510 -0
- data/vendor/libgit2/deps/llhttp/http.c +170 -0
- data/vendor/libgit2/deps/llhttp/llhttp.c +10168 -0
- data/vendor/libgit2/deps/llhttp/llhttp.h +897 -0
- data/vendor/libgit2/deps/ntlmclient/CMakeLists.txt +1 -1
- data/vendor/libgit2/deps/ntlmclient/crypt_builtin_md4.c +311 -0
- data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.c +2 -1
- data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.c +0 -20
- data/vendor/libgit2/deps/ntlmclient/crypt_openssl.c +4 -4
- data/vendor/libgit2/deps/ntlmclient/ntlm.c +21 -21
- data/vendor/libgit2/deps/ntlmclient/unicode_builtin.c +5 -4
- data/vendor/libgit2/deps/ntlmclient/unicode_iconv.c +2 -1
- data/vendor/libgit2/deps/ntlmclient/utf8.h +1176 -721
- data/vendor/libgit2/deps/ntlmclient/util.h +11 -0
- data/vendor/libgit2/deps/pcre/CMakeLists.txt +1 -0
- data/vendor/libgit2/deps/pcre/LICENCE +5 -5
- data/vendor/libgit2/deps/pcre/pcre.h +2 -2
- data/vendor/libgit2/deps/pcre/pcre_compile.c +6 -3
- data/vendor/libgit2/deps/pcre/pcre_exec.c +2 -2
- data/vendor/libgit2/deps/xdiff/CMakeLists.txt +28 -0
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/git-xdiff.h +4 -1
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xdiffi.c +19 -18
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xdiffi.h +2 -4
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xemit.c +3 -3
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xhistogram.c +7 -18
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xmacros.h +18 -1
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xmerge.c +22 -20
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xpatience.c +21 -30
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xprepare.c +13 -30
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xutils.c +18 -1
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xutils.h +2 -1
- data/vendor/libgit2/deps/zlib/CMakeLists.txt +6 -1
- data/vendor/libgit2/deps/zlib/LICENSE +22 -0
- data/vendor/libgit2/deps/zlib/adler32.c +5 -27
- data/vendor/libgit2/deps/zlib/crc32.c +94 -167
- data/vendor/libgit2/deps/zlib/deflate.c +358 -435
- data/vendor/libgit2/deps/zlib/deflate.h +41 -10
- data/vendor/libgit2/deps/zlib/gzguts.h +13 -18
- data/vendor/libgit2/deps/zlib/infback.c +17 -30
- data/vendor/libgit2/deps/zlib/inffast.c +1 -4
- data/vendor/libgit2/deps/zlib/inffast.h +1 -1
- data/vendor/libgit2/deps/zlib/inflate.c +36 -102
- data/vendor/libgit2/deps/zlib/inftrees.c +6 -11
- data/vendor/libgit2/deps/zlib/inftrees.h +6 -6
- data/vendor/libgit2/deps/zlib/trees.c +287 -352
- data/vendor/libgit2/deps/zlib/zconf.h +23 -14
- data/vendor/libgit2/deps/zlib/zlib.h +202 -202
- data/vendor/libgit2/deps/zlib/zutil.c +18 -44
- data/vendor/libgit2/deps/zlib/zutil.h +13 -33
- data/vendor/libgit2/include/git2/annotated_commit.h +12 -5
- data/vendor/libgit2/include/git2/apply.h +27 -6
- data/vendor/libgit2/include/git2/attr.h +17 -4
- data/vendor/libgit2/include/git2/blame.h +133 -28
- data/vendor/libgit2/include/git2/blob.h +71 -28
- data/vendor/libgit2/include/git2/branch.h +22 -15
- data/vendor/libgit2/include/git2/buffer.h +6 -4
- data/vendor/libgit2/include/git2/cert.h +2 -1
- data/vendor/libgit2/include/git2/checkout.h +83 -32
- data/vendor/libgit2/include/git2/cherrypick.h +10 -3
- data/vendor/libgit2/include/git2/clone.h +25 -9
- data/vendor/libgit2/include/git2/commit.h +132 -3
- data/vendor/libgit2/include/git2/common.h +138 -56
- data/vendor/libgit2/include/git2/config.h +93 -23
- data/vendor/libgit2/include/git2/credential.h +30 -2
- data/vendor/libgit2/include/git2/credential_helpers.h +1 -0
- data/vendor/libgit2/include/git2/deprecated.h +133 -3
- data/vendor/libgit2/include/git2/describe.h +13 -1
- data/vendor/libgit2/include/git2/diff.h +77 -9
- data/vendor/libgit2/include/git2/email.h +9 -29
- data/vendor/libgit2/include/git2/errors.h +49 -74
- data/vendor/libgit2/include/git2/filter.h +14 -7
- data/vendor/libgit2/include/git2/global.h +8 -1
- data/vendor/libgit2/include/git2/graph.h +3 -2
- data/vendor/libgit2/include/git2/ignore.h +10 -0
- data/vendor/libgit2/include/git2/index.h +100 -6
- data/vendor/libgit2/include/git2/indexer.h +21 -4
- data/vendor/libgit2/include/git2/mailmap.h +7 -1
- data/vendor/libgit2/include/git2/merge.h +46 -1
- data/vendor/libgit2/include/git2/message.h +2 -2
- data/vendor/libgit2/include/git2/net.h +3 -1
- data/vendor/libgit2/include/git2/notes.h +9 -6
- data/vendor/libgit2/include/git2/object.h +9 -8
- data/vendor/libgit2/include/git2/odb.h +91 -49
- data/vendor/libgit2/include/git2/odb_backend.h +80 -52
- data/vendor/libgit2/include/git2/oid.h +24 -25
- data/vendor/libgit2/include/git2/oidarray.h +7 -1
- data/vendor/libgit2/include/git2/pack.h +13 -1
- data/vendor/libgit2/include/git2/patch.h +2 -3
- data/vendor/libgit2/include/git2/pathspec.h +9 -0
- data/vendor/libgit2/include/git2/proxy.h +10 -0
- data/vendor/libgit2/include/git2/rebase.h +9 -6
- data/vendor/libgit2/include/git2/refdb.h +2 -2
- data/vendor/libgit2/include/git2/reflog.h +3 -2
- data/vendor/libgit2/include/git2/refs.h +9 -6
- data/vendor/libgit2/include/git2/refspec.h +14 -4
- data/vendor/libgit2/include/git2/remote.h +112 -18
- data/vendor/libgit2/include/git2/repository.h +61 -15
- data/vendor/libgit2/include/git2/reset.h +16 -3
- data/vendor/libgit2/include/git2/revert.h +9 -4
- data/vendor/libgit2/include/git2/revparse.h +3 -3
- data/vendor/libgit2/include/git2/revwalk.h +3 -2
- data/vendor/libgit2/include/git2/signature.h +46 -1
- data/vendor/libgit2/include/git2/stash.h +17 -3
- data/vendor/libgit2/include/git2/status.h +10 -6
- data/vendor/libgit2/include/git2/stdint.h +87 -85
- data/vendor/libgit2/include/git2/strarray.h +2 -3
- data/vendor/libgit2/include/git2/submodule.h +20 -9
- data/vendor/libgit2/include/git2/sys/alloc.h +12 -34
- data/vendor/libgit2/include/git2/sys/commit.h +77 -3
- data/vendor/libgit2/include/git2/sys/commit_graph.h +109 -58
- data/vendor/libgit2/include/git2/sys/config.h +80 -4
- data/vendor/libgit2/include/git2/sys/credential.h +4 -3
- data/vendor/libgit2/include/git2/sys/diff.h +21 -1
- data/vendor/libgit2/include/git2/sys/email.h +7 -0
- data/vendor/libgit2/include/git2/sys/errors.h +76 -0
- data/vendor/libgit2/include/git2/sys/filter.h +66 -3
- data/vendor/libgit2/include/git2/sys/hashsig.h +11 -0
- data/vendor/libgit2/include/git2/sys/index.h +3 -2
- data/vendor/libgit2/include/git2/sys/mempack.h +32 -2
- data/vendor/libgit2/include/git2/sys/merge.h +55 -7
- data/vendor/libgit2/include/git2/sys/midx.h +47 -4
- data/vendor/libgit2/include/git2/sys/odb_backend.h +7 -3
- data/vendor/libgit2/include/git2/sys/openssl.h +8 -1
- data/vendor/libgit2/include/git2/sys/path.h +12 -1
- data/vendor/libgit2/include/git2/sys/refdb_backend.h +40 -36
- data/vendor/libgit2/include/git2/sys/refs.h +3 -2
- data/vendor/libgit2/include/git2/sys/remote.h +8 -1
- data/vendor/libgit2/include/git2/sys/repository.h +63 -3
- data/vendor/libgit2/include/git2/sys/stream.h +25 -2
- data/vendor/libgit2/include/git2/sys/transport.h +44 -5
- data/vendor/libgit2/include/git2/tag.h +3 -1
- data/vendor/libgit2/include/git2/trace.h +9 -3
- data/vendor/libgit2/include/git2/transaction.h +3 -2
- data/vendor/libgit2/include/git2/transport.h +11 -3
- data/vendor/libgit2/include/git2/tree.h +16 -5
- data/vendor/libgit2/include/git2/types.h +19 -3
- data/vendor/libgit2/include/git2/version.h +44 -8
- data/vendor/libgit2/include/git2/worktree.h +19 -7
- data/vendor/libgit2/src/CMakeLists.txt +40 -15
- data/vendor/libgit2/src/cli/CMakeLists.txt +2 -2
- data/vendor/libgit2/src/cli/cmd.c +1 -1
- data/vendor/libgit2/src/cli/cmd.h +4 -0
- data/vendor/libgit2/src/cli/cmd_blame.c +287 -0
- data/vendor/libgit2/src/cli/cmd_cat_file.c +6 -8
- data/vendor/libgit2/src/cli/cmd_clone.c +27 -13
- data/vendor/libgit2/src/cli/cmd_config.c +241 -0
- data/vendor/libgit2/src/cli/cmd_hash_object.c +6 -8
- data/vendor/libgit2/src/cli/cmd_help.c +6 -7
- data/vendor/libgit2/src/cli/cmd_index_pack.c +114 -0
- data/vendor/libgit2/src/cli/cmd_init.c +102 -0
- data/vendor/libgit2/src/cli/common.c +168 -0
- data/vendor/libgit2/src/cli/common.h +63 -0
- data/vendor/libgit2/src/cli/error.h +1 -1
- data/vendor/libgit2/src/cli/main.c +52 -24
- data/vendor/libgit2/src/cli/opt.c +29 -3
- data/vendor/libgit2/src/cli/opt.h +21 -3
- data/vendor/libgit2/src/cli/opt_usage.c +102 -33
- data/vendor/libgit2/src/cli/opt_usage.h +6 -1
- data/vendor/libgit2/src/cli/progress.c +60 -10
- data/vendor/libgit2/src/cli/progress.h +16 -4
- data/vendor/libgit2/src/cli/unix/sighandler.c +2 -1
- data/vendor/libgit2/src/cli/win32/precompiled.h +1 -1
- data/vendor/libgit2/src/cli/win32/sighandler.c +1 -1
- data/vendor/libgit2/src/libgit2/CMakeLists.txt +27 -27
- data/vendor/libgit2/src/libgit2/annotated_commit.c +2 -2
- data/vendor/libgit2/src/libgit2/annotated_commit.h +1 -1
- data/vendor/libgit2/src/libgit2/apply.c +14 -16
- data/vendor/libgit2/src/libgit2/attr.c +30 -13
- data/vendor/libgit2/src/libgit2/attr_file.c +7 -2
- data/vendor/libgit2/src/libgit2/attr_file.h +2 -0
- data/vendor/libgit2/src/libgit2/attrcache.c +69 -33
- data/vendor/libgit2/src/libgit2/attrcache.h +5 -9
- data/vendor/libgit2/src/libgit2/blame.c +152 -59
- data/vendor/libgit2/src/libgit2/blame.h +1 -0
- data/vendor/libgit2/src/libgit2/blame_git.c +0 -1
- data/vendor/libgit2/src/libgit2/branch.c +2 -2
- data/vendor/libgit2/src/libgit2/cache.c +22 -17
- data/vendor/libgit2/src/libgit2/cache.h +7 -9
- data/vendor/libgit2/src/libgit2/checkout.c +34 -24
- data/vendor/libgit2/src/libgit2/checkout.h +0 -2
- data/vendor/libgit2/src/libgit2/cherrypick.c +4 -5
- data/vendor/libgit2/src/libgit2/clone.c +186 -164
- data/vendor/libgit2/src/libgit2/clone.h +4 -1
- data/vendor/libgit2/src/libgit2/commit.c +123 -9
- data/vendor/libgit2/src/libgit2/commit_graph.c +166 -88
- data/vendor/libgit2/src/libgit2/commit_graph.h +21 -6
- data/vendor/libgit2/src/libgit2/commit_list.c +12 -5
- data/vendor/libgit2/src/libgit2/commit_list.h +1 -0
- data/vendor/libgit2/src/libgit2/config.c +394 -300
- data/vendor/libgit2/src/libgit2/config.cmake.in +3 -0
- data/vendor/libgit2/src/libgit2/config.h +9 -4
- data/vendor/libgit2/src/libgit2/config_backend.h +8 -10
- data/vendor/libgit2/src/libgit2/config_cache.c +4 -5
- data/vendor/libgit2/src/libgit2/config_file.c +113 -96
- data/vendor/libgit2/src/libgit2/config_list.c +285 -0
- data/vendor/libgit2/src/libgit2/config_list.h +32 -0
- data/vendor/libgit2/src/libgit2/config_mem.c +194 -40
- data/vendor/libgit2/src/libgit2/config_parse.c +10 -9
- data/vendor/libgit2/src/libgit2/config_snapshot.c +24 -31
- data/vendor/libgit2/src/libgit2/describe.c +34 -31
- data/vendor/libgit2/src/libgit2/diff.c +17 -8
- data/vendor/libgit2/src/libgit2/diff.h +6 -6
- data/vendor/libgit2/src/libgit2/diff_driver.c +12 -19
- data/vendor/libgit2/src/libgit2/diff_driver.h +2 -2
- data/vendor/libgit2/src/libgit2/diff_file.c +7 -7
- data/vendor/libgit2/src/libgit2/diff_generate.c +39 -18
- data/vendor/libgit2/src/libgit2/diff_parse.c +22 -6
- data/vendor/libgit2/src/libgit2/diff_print.c +88 -13
- data/vendor/libgit2/src/libgit2/diff_tform.c +40 -12
- data/vendor/libgit2/src/libgit2/diff_xdiff.h +1 -1
- data/vendor/libgit2/src/libgit2/email.c +5 -3
- data/vendor/libgit2/src/libgit2/fetch.c +39 -9
- data/vendor/libgit2/src/libgit2/fetch.h +0 -2
- data/vendor/libgit2/src/libgit2/fetchhead.c +11 -9
- data/vendor/libgit2/src/libgit2/filter.c +5 -5
- data/vendor/libgit2/src/libgit2/git2.rc +3 -3
- data/vendor/libgit2/src/libgit2/grafts.c +270 -0
- data/vendor/libgit2/src/libgit2/grafts.h +35 -0
- data/vendor/libgit2/src/libgit2/graph.c +1 -1
- data/vendor/libgit2/src/libgit2/hashmap_oid.h +30 -0
- data/vendor/libgit2/src/libgit2/ident.c +3 -3
- data/vendor/libgit2/src/libgit2/ignore.c +9 -5
- data/vendor/libgit2/src/libgit2/index.c +392 -208
- data/vendor/libgit2/src/libgit2/index.h +16 -3
- data/vendor/libgit2/src/libgit2/index_map.c +95 -0
- data/vendor/libgit2/src/libgit2/index_map.h +28 -0
- data/vendor/libgit2/src/libgit2/indexer.c +44 -41
- data/vendor/libgit2/src/libgit2/iterator.c +34 -13
- data/vendor/libgit2/src/libgit2/iterator.h +3 -0
- data/vendor/libgit2/src/libgit2/libgit2.c +155 -331
- data/vendor/libgit2/src/libgit2/mailmap.c +1 -1
- data/vendor/libgit2/src/libgit2/merge.c +56 -46
- data/vendor/libgit2/src/libgit2/merge_driver.c +2 -2
- data/vendor/libgit2/src/libgit2/merge_file.c +0 -2
- data/vendor/libgit2/src/libgit2/midx.c +86 -44
- data/vendor/libgit2/src/libgit2/midx.h +13 -3
- data/vendor/libgit2/src/libgit2/mwindow.c +38 -45
- data/vendor/libgit2/src/libgit2/mwindow.h +4 -0
- data/vendor/libgit2/src/libgit2/notes.c +9 -8
- data/vendor/libgit2/src/libgit2/object.c +42 -16
- data/vendor/libgit2/src/libgit2/object.h +6 -0
- data/vendor/libgit2/src/libgit2/odb.c +16 -9
- data/vendor/libgit2/src/libgit2/odb_mempack.c +49 -17
- data/vendor/libgit2/src/libgit2/odb_pack.c +28 -7
- data/vendor/libgit2/src/libgit2/oid.c +35 -2
- data/vendor/libgit2/src/libgit2/oid.h +11 -0
- data/vendor/libgit2/src/libgit2/oidarray.c +49 -3
- data/vendor/libgit2/src/libgit2/oidarray.h +5 -1
- data/vendor/libgit2/src/libgit2/pack-objects.c +77 -43
- data/vendor/libgit2/src/libgit2/pack-objects.h +17 -6
- data/vendor/libgit2/src/libgit2/pack.c +33 -27
- data/vendor/libgit2/src/libgit2/pack.h +15 -10
- data/vendor/libgit2/src/libgit2/parse.c +7 -4
- data/vendor/libgit2/src/libgit2/parse.h +1 -1
- data/vendor/libgit2/src/libgit2/patch.h +7 -1
- data/vendor/libgit2/src/libgit2/patch_generate.c +24 -5
- data/vendor/libgit2/src/libgit2/patch_parse.c +18 -10
- data/vendor/libgit2/src/libgit2/path.c +1 -1
- data/vendor/libgit2/src/libgit2/pathspec.c +1 -1
- data/vendor/libgit2/src/libgit2/push.c +81 -30
- data/vendor/libgit2/src/libgit2/push.h +1 -0
- data/vendor/libgit2/src/libgit2/reader.c +1 -1
- data/vendor/libgit2/src/libgit2/rebase.c +72 -84
- data/vendor/libgit2/src/libgit2/refdb_fs.c +146 -70
- data/vendor/libgit2/src/libgit2/reflog.c +1 -2
- data/vendor/libgit2/src/libgit2/reflog.h +2 -0
- data/vendor/libgit2/src/libgit2/refs.c +34 -8
- data/vendor/libgit2/src/libgit2/refs.h +6 -1
- data/vendor/libgit2/src/libgit2/refspec.c +28 -1
- data/vendor/libgit2/src/libgit2/refspec.h +8 -0
- data/vendor/libgit2/src/libgit2/remote.c +136 -67
- data/vendor/libgit2/src/libgit2/remote.h +1 -0
- data/vendor/libgit2/src/libgit2/repository.c +789 -330
- data/vendor/libgit2/src/libgit2/repository.h +22 -3
- data/vendor/libgit2/src/libgit2/reset.c +2 -2
- data/vendor/libgit2/src/libgit2/revert.c +9 -13
- data/vendor/libgit2/src/libgit2/revparse.c +6 -3
- data/vendor/libgit2/src/libgit2/revwalk.c +36 -11
- data/vendor/libgit2/src/libgit2/revwalk.h +3 -3
- data/vendor/libgit2/src/libgit2/settings.c +468 -0
- data/vendor/libgit2/src/libgit2/settings.h +6 -2
- data/vendor/libgit2/src/libgit2/signature.c +132 -15
- data/vendor/libgit2/src/libgit2/signature.h +0 -1
- data/vendor/libgit2/src/libgit2/stash.c +9 -8
- data/vendor/libgit2/src/libgit2/status.c +1 -1
- data/vendor/libgit2/src/libgit2/streams/mbedtls.c +54 -61
- data/vendor/libgit2/src/libgit2/streams/openssl.c +40 -23
- data/vendor/libgit2/src/libgit2/streams/openssl.h +2 -0
- data/vendor/libgit2/src/libgit2/streams/openssl_dynamic.c +4 -0
- data/vendor/libgit2/src/libgit2/streams/openssl_dynamic.h +3 -0
- data/vendor/libgit2/src/libgit2/streams/schannel.c +715 -0
- data/vendor/libgit2/src/libgit2/streams/schannel.h +28 -0
- data/vendor/libgit2/src/libgit2/streams/socket.c +237 -51
- data/vendor/libgit2/src/libgit2/streams/socket.h +3 -1
- data/vendor/libgit2/src/libgit2/streams/stransport.c +79 -19
- data/vendor/libgit2/src/libgit2/streams/tls.c +5 -0
- data/vendor/libgit2/src/libgit2/submodule.c +106 -63
- data/vendor/libgit2/src/libgit2/submodule.h +9 -10
- data/vendor/libgit2/src/libgit2/tag.c +1 -1
- data/vendor/libgit2/src/libgit2/trailer.c +6 -6
- data/vendor/libgit2/src/libgit2/transaction.c +26 -20
- data/vendor/libgit2/src/libgit2/transaction.h +4 -1
- data/vendor/libgit2/src/libgit2/transport.c +4 -1
- data/vendor/libgit2/src/libgit2/transports/auth.h +1 -2
- data/vendor/libgit2/src/libgit2/transports/{auth_negotiate.c → auth_gssapi.c} +32 -32
- data/vendor/libgit2/src/libgit2/transports/auth_negotiate.h +1 -1
- data/vendor/libgit2/src/libgit2/transports/auth_ntlm.h +1 -1
- data/vendor/libgit2/src/libgit2/transports/{auth_ntlm.c → auth_ntlmclient.c} +12 -12
- data/vendor/libgit2/src/libgit2/transports/auth_sspi.c +341 -0
- data/vendor/libgit2/src/libgit2/transports/credential.c +1 -1
- data/vendor/libgit2/src/libgit2/transports/git.c +7 -8
- data/vendor/libgit2/src/libgit2/transports/http.c +8 -4
- data/vendor/libgit2/src/libgit2/transports/http.h +0 -10
- data/vendor/libgit2/src/libgit2/transports/httpclient.c +117 -72
- data/vendor/libgit2/src/libgit2/transports/httpparser.c +128 -0
- data/vendor/libgit2/src/libgit2/transports/httpparser.h +99 -0
- data/vendor/libgit2/src/libgit2/transports/local.c +21 -11
- data/vendor/libgit2/src/libgit2/transports/smart.c +50 -32
- data/vendor/libgit2/src/libgit2/transports/smart.h +26 -9
- data/vendor/libgit2/src/libgit2/transports/smart_pkt.c +139 -18
- data/vendor/libgit2/src/libgit2/transports/smart_protocol.c +209 -57
- data/vendor/libgit2/src/libgit2/transports/ssh.c +41 -1103
- data/vendor/libgit2/src/libgit2/transports/ssh_exec.c +347 -0
- data/vendor/libgit2/src/libgit2/transports/ssh_exec.h +26 -0
- data/vendor/libgit2/src/libgit2/transports/ssh_libssh2.c +1126 -0
- data/vendor/libgit2/src/libgit2/transports/ssh_libssh2.h +28 -0
- data/vendor/libgit2/src/libgit2/transports/winhttp.c +48 -21
- data/vendor/libgit2/src/libgit2/tree-cache.c +26 -16
- data/vendor/libgit2/src/libgit2/tree-cache.h +5 -3
- data/vendor/libgit2/src/libgit2/tree.c +35 -27
- data/vendor/libgit2/src/libgit2/tree.h +3 -2
- data/vendor/libgit2/src/libgit2/worktree.c +39 -27
- data/vendor/libgit2/src/util/CMakeLists.txt +4 -6
- data/vendor/libgit2/src/util/alloc.c +69 -7
- data/vendor/libgit2/src/util/alloc.h +34 -9
- data/vendor/libgit2/src/util/allocators/debugalloc.c +73 -0
- data/vendor/libgit2/src/{cli/cli.h → util/allocators/debugalloc.h} +6 -9
- data/vendor/libgit2/src/util/allocators/failalloc.c +0 -60
- data/vendor/libgit2/src/util/allocators/failalloc.h +0 -6
- data/vendor/libgit2/src/util/allocators/stdalloc.c +2 -115
- data/vendor/libgit2/src/util/allocators/win32_leakcheck.c +0 -68
- data/vendor/libgit2/src/util/array.h +24 -18
- data/vendor/libgit2/src/util/cc-compat.h +4 -0
- data/vendor/libgit2/src/util/ctype_compat.h +70 -0
- data/vendor/libgit2/src/util/date.c +22 -14
- data/vendor/libgit2/src/util/date.h +12 -0
- data/vendor/libgit2/src/util/errors.c +401 -0
- data/vendor/libgit2/src/{libgit2 → util}/errors.h +21 -17
- data/vendor/libgit2/src/util/filebuf.c +6 -1
- data/vendor/libgit2/src/util/filebuf.h +19 -6
- data/vendor/libgit2/src/util/fs_path.c +16 -5
- data/vendor/libgit2/src/util/fs_path.h +23 -0
- data/vendor/libgit2/src/util/futils.c +14 -10
- data/vendor/libgit2/src/util/futils.h +13 -4
- data/vendor/libgit2/src/util/git2_features.h.in +21 -4
- data/vendor/libgit2/src/util/git2_util.h +6 -0
- data/vendor/libgit2/src/util/hash/openssl.c +152 -0
- data/vendor/libgit2/src/util/hash/openssl.h +17 -1
- data/vendor/libgit2/src/util/hash/sha.h +4 -1
- data/vendor/libgit2/src/util/hashmap.h +424 -0
- data/vendor/libgit2/src/util/hashmap_str.h +43 -0
- data/vendor/libgit2/src/util/integer.h +3 -1
- data/vendor/libgit2/src/util/net.c +318 -161
- data/vendor/libgit2/src/util/net.h +27 -0
- data/vendor/libgit2/src/util/pool.c +1 -1
- data/vendor/libgit2/src/util/pool.h +5 -0
- data/vendor/libgit2/src/util/posix.c +54 -0
- data/vendor/libgit2/src/util/posix.h +22 -0
- data/vendor/libgit2/src/util/pqueue.h +1 -1
- data/vendor/libgit2/src/util/process.h +222 -0
- data/vendor/libgit2/src/util/rand.c +6 -10
- data/vendor/libgit2/src/util/regexp.c +1 -1
- data/vendor/libgit2/src/util/sortedcache.c +14 -13
- data/vendor/libgit2/src/util/sortedcache.h +3 -3
- data/vendor/libgit2/src/util/staticstr.h +66 -0
- data/vendor/libgit2/src/util/str.c +2 -2
- data/vendor/libgit2/src/util/strlist.c +108 -0
- data/vendor/libgit2/src/util/strlist.h +36 -0
- data/vendor/libgit2/src/util/unix/posix.h +0 -2
- data/vendor/libgit2/src/util/unix/process.c +629 -0
- data/vendor/libgit2/src/util/unix/realpath.c +23 -5
- data/vendor/libgit2/src/util/util.c +17 -12
- data/vendor/libgit2/src/util/util.h +28 -54
- data/vendor/libgit2/src/util/vector.c +3 -3
- data/vendor/libgit2/src/util/vector.h +2 -2
- data/vendor/libgit2/src/util/win32/error.c +1 -1
- data/vendor/libgit2/src/util/win32/path_w32.c +8 -8
- data/vendor/libgit2/src/util/win32/posix_w32.c +30 -7
- data/vendor/libgit2/src/util/win32/process.c +506 -0
- data/vendor/libgit2/src/util/win32/utf-conv.c +73 -75
- data/vendor/libgit2/src/util/win32/utf-conv.h +81 -14
- data/vendor/libgit2/src/util/win32/w32_util.c +1 -1
- metadata +72 -49
- data/vendor/libgit2/cmake/SelectWinHTTP.cmake +0 -17
- data/vendor/libgit2/deps/http-parser/CMakeLists.txt +0 -6
- data/vendor/libgit2/deps/http-parser/COPYING +0 -23
- data/vendor/libgit2/deps/http-parser/http_parser.c +0 -2182
- data/vendor/libgit2/deps/http-parser/http_parser.h +0 -305
- data/vendor/libgit2/deps/zlib/COPYING +0 -27
- data/vendor/libgit2/include/git2/sys/reflog.h +0 -21
- data/vendor/libgit2/src/libgit2/config_entries.c +0 -237
- data/vendor/libgit2/src/libgit2/config_entries.h +0 -24
- data/vendor/libgit2/src/libgit2/errors.c +0 -238
- data/vendor/libgit2/src/libgit2/idxmap.c +0 -157
- data/vendor/libgit2/src/libgit2/idxmap.h +0 -177
- data/vendor/libgit2/src/libgit2/libgit2.h +0 -15
- data/vendor/libgit2/src/libgit2/netops.c +0 -124
- data/vendor/libgit2/src/libgit2/netops.h +0 -68
- data/vendor/libgit2/src/libgit2/offmap.c +0 -101
- data/vendor/libgit2/src/libgit2/offmap.h +0 -133
- data/vendor/libgit2/src/libgit2/oidmap.c +0 -107
- data/vendor/libgit2/src/libgit2/oidmap.h +0 -128
- data/vendor/libgit2/src/libgit2/threadstate.c +0 -84
- data/vendor/libgit2/src/libgit2/threadstate.h +0 -24
- data/vendor/libgit2/src/libgit2/transports/ssh.h +0 -14
- data/vendor/libgit2/src/util/khash.h +0 -615
- data/vendor/libgit2/src/util/strmap.c +0 -100
- data/vendor/libgit2/src/util/strmap.h +0 -131
- /data/vendor/libgit2/cmake/{FindHTTPParser.cmake → FindHTTP_Parser.cmake} +0 -0
- /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xdiff.h +0 -0
- /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xemit.h +0 -0
- /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xinclude.h +0 -0
- /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xprepare.h +0 -0
- /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xtypes.h +0 -0
@@ -0,0 +1,1126 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) the libgit2 contributors. All rights reserved.
|
3
|
+
*
|
4
|
+
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
5
|
+
* a Linking Exception. For full terms see the included COPYING file.
|
6
|
+
*/
|
7
|
+
|
8
|
+
#include "ssh_libssh2.h"
|
9
|
+
|
10
|
+
#ifdef GIT_SSH_LIBSSH2
|
11
|
+
|
12
|
+
#include <libssh2.h>
|
13
|
+
|
14
|
+
#include "runtime.h"
|
15
|
+
#include "net.h"
|
16
|
+
#include "smart.h"
|
17
|
+
#include "process.h"
|
18
|
+
#include "streams/socket.h"
|
19
|
+
#include "sysdir.h"
|
20
|
+
|
21
|
+
#include "git2/credential.h"
|
22
|
+
#include "git2/sys/credential.h"
|
23
|
+
|
24
|
+
#define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport)
|
25
|
+
|
26
|
+
extern int git_socket_stream__timeout;
|
27
|
+
|
28
|
+
static const char cmd_uploadpack[] = "git-upload-pack";
|
29
|
+
static const char cmd_receivepack[] = "git-receive-pack";
|
30
|
+
|
31
|
+
typedef struct {
|
32
|
+
git_smart_subtransport_stream parent;
|
33
|
+
git_stream *io;
|
34
|
+
LIBSSH2_SESSION *session;
|
35
|
+
LIBSSH2_CHANNEL *channel;
|
36
|
+
const char *cmd;
|
37
|
+
git_net_url url;
|
38
|
+
unsigned sent_command : 1;
|
39
|
+
} ssh_stream;
|
40
|
+
|
41
|
+
typedef struct {
|
42
|
+
git_smart_subtransport parent;
|
43
|
+
transport_smart *owner;
|
44
|
+
ssh_stream *current_stream;
|
45
|
+
git_credential *cred;
|
46
|
+
char *cmd_uploadpack;
|
47
|
+
char *cmd_receivepack;
|
48
|
+
} ssh_subtransport;
|
49
|
+
|
50
|
+
static int list_auth_methods(int *out, LIBSSH2_SESSION *session, const char *username);
|
51
|
+
|
52
|
+
static void ssh_error(LIBSSH2_SESSION *session, const char *errmsg)
|
53
|
+
{
|
54
|
+
char *ssherr;
|
55
|
+
libssh2_session_last_error(session, &ssherr, NULL, 0);
|
56
|
+
|
57
|
+
git_error_set(GIT_ERROR_SSH, "%s: %s", errmsg, ssherr);
|
58
|
+
}
|
59
|
+
|
60
|
+
/*
|
61
|
+
* Create a git protocol request.
|
62
|
+
*
|
63
|
+
* For example: git-upload-pack '/libgit2/libgit2'
|
64
|
+
*/
|
65
|
+
static int gen_proto(git_str *request, const char *cmd, git_net_url *url)
|
66
|
+
{
|
67
|
+
const char *repo;
|
68
|
+
|
69
|
+
repo = url->path;
|
70
|
+
|
71
|
+
if (repo && repo[0] == '/' && repo[1] == '~')
|
72
|
+
repo++;
|
73
|
+
|
74
|
+
if (!repo || !repo[0]) {
|
75
|
+
git_error_set(GIT_ERROR_NET, "malformed git protocol URL");
|
76
|
+
return -1;
|
77
|
+
}
|
78
|
+
|
79
|
+
git_str_puts(request, cmd);
|
80
|
+
git_str_puts(request, " '");
|
81
|
+
git_str_puts(request, repo);
|
82
|
+
git_str_puts(request, "'");
|
83
|
+
|
84
|
+
if (git_str_oom(request))
|
85
|
+
return -1;
|
86
|
+
|
87
|
+
return 0;
|
88
|
+
}
|
89
|
+
|
90
|
+
static int send_command(ssh_stream *s)
|
91
|
+
{
|
92
|
+
int error;
|
93
|
+
git_str request = GIT_STR_INIT;
|
94
|
+
|
95
|
+
error = gen_proto(&request, s->cmd, &s->url);
|
96
|
+
if (error < 0)
|
97
|
+
goto cleanup;
|
98
|
+
|
99
|
+
error = libssh2_channel_exec(s->channel, request.ptr);
|
100
|
+
if (error < LIBSSH2_ERROR_NONE) {
|
101
|
+
ssh_error(s->session, "SSH could not execute request");
|
102
|
+
goto cleanup;
|
103
|
+
}
|
104
|
+
|
105
|
+
s->sent_command = 1;
|
106
|
+
|
107
|
+
cleanup:
|
108
|
+
git_str_dispose(&request);
|
109
|
+
return error;
|
110
|
+
}
|
111
|
+
|
112
|
+
static int ssh_stream_read(
|
113
|
+
git_smart_subtransport_stream *stream,
|
114
|
+
char *buffer,
|
115
|
+
size_t buf_size,
|
116
|
+
size_t *bytes_read)
|
117
|
+
{
|
118
|
+
ssh_stream *s = GIT_CONTAINER_OF(stream, ssh_stream, parent);
|
119
|
+
ssize_t rc;
|
120
|
+
|
121
|
+
*bytes_read = 0;
|
122
|
+
|
123
|
+
if (!s->sent_command && send_command(s) < 0)
|
124
|
+
return -1;
|
125
|
+
|
126
|
+
if ((rc = libssh2_channel_read(s->channel, buffer, buf_size)) < LIBSSH2_ERROR_NONE) {
|
127
|
+
ssh_error(s->session, "SSH could not read data");
|
128
|
+
return -1;
|
129
|
+
}
|
130
|
+
|
131
|
+
/*
|
132
|
+
* If we can't get anything out of stdout, it's typically a
|
133
|
+
* not-found error, so read from stderr and signal EOF on
|
134
|
+
* stderr.
|
135
|
+
*/
|
136
|
+
if (rc == 0) {
|
137
|
+
if ((rc = libssh2_channel_read_stderr(s->channel, buffer, buf_size)) > 0) {
|
138
|
+
git_error_set(GIT_ERROR_SSH, "%*s", (int)rc, buffer);
|
139
|
+
return GIT_EEOF;
|
140
|
+
} else if (rc < LIBSSH2_ERROR_NONE) {
|
141
|
+
ssh_error(s->session, "SSH could not read stderr");
|
142
|
+
return -1;
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
*bytes_read = rc;
|
147
|
+
|
148
|
+
return 0;
|
149
|
+
}
|
150
|
+
|
151
|
+
static int ssh_stream_write(
|
152
|
+
git_smart_subtransport_stream *stream,
|
153
|
+
const char *buffer,
|
154
|
+
size_t len)
|
155
|
+
{
|
156
|
+
ssh_stream *s = GIT_CONTAINER_OF(stream, ssh_stream, parent);
|
157
|
+
size_t off = 0;
|
158
|
+
ssize_t ret = 0;
|
159
|
+
|
160
|
+
if (!s->sent_command && send_command(s) < 0)
|
161
|
+
return -1;
|
162
|
+
|
163
|
+
do {
|
164
|
+
ret = libssh2_channel_write(s->channel, buffer + off, len - off);
|
165
|
+
if (ret < 0)
|
166
|
+
break;
|
167
|
+
|
168
|
+
off += ret;
|
169
|
+
|
170
|
+
} while (off < len);
|
171
|
+
|
172
|
+
if (ret < 0) {
|
173
|
+
ssh_error(s->session, "SSH could not write data");
|
174
|
+
return -1;
|
175
|
+
}
|
176
|
+
|
177
|
+
return 0;
|
178
|
+
}
|
179
|
+
|
180
|
+
static void ssh_stream_free(git_smart_subtransport_stream *stream)
|
181
|
+
{
|
182
|
+
ssh_stream *s = GIT_CONTAINER_OF(stream, ssh_stream, parent);
|
183
|
+
ssh_subtransport *t;
|
184
|
+
|
185
|
+
if (!stream)
|
186
|
+
return;
|
187
|
+
|
188
|
+
t = OWNING_SUBTRANSPORT(s);
|
189
|
+
t->current_stream = NULL;
|
190
|
+
|
191
|
+
if (s->channel) {
|
192
|
+
libssh2_channel_close(s->channel);
|
193
|
+
libssh2_channel_free(s->channel);
|
194
|
+
s->channel = NULL;
|
195
|
+
}
|
196
|
+
|
197
|
+
if (s->session) {
|
198
|
+
libssh2_session_disconnect(s->session, "closing transport");
|
199
|
+
libssh2_session_free(s->session);
|
200
|
+
s->session = NULL;
|
201
|
+
}
|
202
|
+
|
203
|
+
if (s->io) {
|
204
|
+
git_stream_close(s->io);
|
205
|
+
git_stream_free(s->io);
|
206
|
+
s->io = NULL;
|
207
|
+
}
|
208
|
+
|
209
|
+
git_net_url_dispose(&s->url);
|
210
|
+
git__free(s);
|
211
|
+
}
|
212
|
+
|
213
|
+
static int ssh_stream_alloc(
|
214
|
+
ssh_subtransport *t,
|
215
|
+
const char *cmd,
|
216
|
+
git_smart_subtransport_stream **stream)
|
217
|
+
{
|
218
|
+
ssh_stream *s;
|
219
|
+
|
220
|
+
GIT_ASSERT_ARG(stream);
|
221
|
+
|
222
|
+
s = git__calloc(sizeof(ssh_stream), 1);
|
223
|
+
GIT_ERROR_CHECK_ALLOC(s);
|
224
|
+
|
225
|
+
s->parent.subtransport = &t->parent;
|
226
|
+
s->parent.read = ssh_stream_read;
|
227
|
+
s->parent.write = ssh_stream_write;
|
228
|
+
s->parent.free = ssh_stream_free;
|
229
|
+
|
230
|
+
s->cmd = cmd;
|
231
|
+
|
232
|
+
*stream = &s->parent;
|
233
|
+
return 0;
|
234
|
+
}
|
235
|
+
|
236
|
+
static int ssh_agent_auth(LIBSSH2_SESSION *session, git_credential_ssh_key *c) {
|
237
|
+
int rc = LIBSSH2_ERROR_NONE;
|
238
|
+
|
239
|
+
struct libssh2_agent_publickey *curr, *prev = NULL;
|
240
|
+
|
241
|
+
LIBSSH2_AGENT *agent = libssh2_agent_init(session);
|
242
|
+
|
243
|
+
if (agent == NULL)
|
244
|
+
return -1;
|
245
|
+
|
246
|
+
rc = libssh2_agent_connect(agent);
|
247
|
+
|
248
|
+
if (rc != LIBSSH2_ERROR_NONE) {
|
249
|
+
rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED;
|
250
|
+
goto shutdown;
|
251
|
+
}
|
252
|
+
|
253
|
+
rc = libssh2_agent_list_identities(agent);
|
254
|
+
|
255
|
+
if (rc != LIBSSH2_ERROR_NONE)
|
256
|
+
goto shutdown;
|
257
|
+
|
258
|
+
while (1) {
|
259
|
+
rc = libssh2_agent_get_identity(agent, &curr, prev);
|
260
|
+
|
261
|
+
if (rc < 0)
|
262
|
+
goto shutdown;
|
263
|
+
|
264
|
+
/* rc is set to 1 whenever the ssh agent ran out of keys to check.
|
265
|
+
* Set the error code to authentication failure rather than erroring
|
266
|
+
* out with an untranslatable error code.
|
267
|
+
*/
|
268
|
+
if (rc == 1) {
|
269
|
+
rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED;
|
270
|
+
goto shutdown;
|
271
|
+
}
|
272
|
+
|
273
|
+
rc = libssh2_agent_userauth(agent, c->username, curr);
|
274
|
+
|
275
|
+
if (rc == 0)
|
276
|
+
break;
|
277
|
+
|
278
|
+
prev = curr;
|
279
|
+
}
|
280
|
+
|
281
|
+
shutdown:
|
282
|
+
|
283
|
+
if (rc != LIBSSH2_ERROR_NONE)
|
284
|
+
ssh_error(session, "error authenticating");
|
285
|
+
|
286
|
+
libssh2_agent_disconnect(agent);
|
287
|
+
libssh2_agent_free(agent);
|
288
|
+
|
289
|
+
return rc;
|
290
|
+
}
|
291
|
+
|
292
|
+
static int _git_ssh_authenticate_session(
|
293
|
+
LIBSSH2_SESSION *session,
|
294
|
+
git_credential *cred)
|
295
|
+
{
|
296
|
+
int rc;
|
297
|
+
|
298
|
+
do {
|
299
|
+
git_error_clear();
|
300
|
+
switch (cred->credtype) {
|
301
|
+
case GIT_CREDENTIAL_USERPASS_PLAINTEXT: {
|
302
|
+
git_credential_userpass_plaintext *c = (git_credential_userpass_plaintext *)cred;
|
303
|
+
rc = libssh2_userauth_password(session, c->username, c->password);
|
304
|
+
break;
|
305
|
+
}
|
306
|
+
case GIT_CREDENTIAL_SSH_KEY: {
|
307
|
+
git_credential_ssh_key *c = (git_credential_ssh_key *)cred;
|
308
|
+
|
309
|
+
if (c->privatekey)
|
310
|
+
rc = libssh2_userauth_publickey_fromfile(
|
311
|
+
session, c->username, c->publickey,
|
312
|
+
c->privatekey, c->passphrase);
|
313
|
+
else
|
314
|
+
rc = ssh_agent_auth(session, c);
|
315
|
+
|
316
|
+
break;
|
317
|
+
}
|
318
|
+
case GIT_CREDENTIAL_SSH_CUSTOM: {
|
319
|
+
git_credential_ssh_custom *c = (git_credential_ssh_custom *)cred;
|
320
|
+
|
321
|
+
rc = libssh2_userauth_publickey(
|
322
|
+
session, c->username, (const unsigned char *)c->publickey,
|
323
|
+
c->publickey_len, c->sign_callback, &c->payload);
|
324
|
+
break;
|
325
|
+
}
|
326
|
+
case GIT_CREDENTIAL_SSH_INTERACTIVE: {
|
327
|
+
void **abstract = libssh2_session_abstract(session);
|
328
|
+
git_credential_ssh_interactive *c = (git_credential_ssh_interactive *)cred;
|
329
|
+
|
330
|
+
/* ideally, we should be able to set this by calling
|
331
|
+
* libssh2_session_init_ex() instead of libssh2_session_init().
|
332
|
+
* libssh2's API is inconsistent here i.e. libssh2_userauth_publickey()
|
333
|
+
* allows you to pass the `abstract` as part of the call, whereas
|
334
|
+
* libssh2_userauth_keyboard_interactive() does not!
|
335
|
+
*
|
336
|
+
* The only way to set the `abstract` pointer is by calling
|
337
|
+
* libssh2_session_abstract(), which will replace the existing
|
338
|
+
* pointer as is done below. This is safe for now (at time of writing),
|
339
|
+
* but may not be valid in future.
|
340
|
+
*/
|
341
|
+
*abstract = c->payload;
|
342
|
+
|
343
|
+
rc = libssh2_userauth_keyboard_interactive(
|
344
|
+
session, c->username, c->prompt_callback);
|
345
|
+
break;
|
346
|
+
}
|
347
|
+
#ifdef GIT_SSH_LIBSSH2_MEMORY_CREDENTIALS
|
348
|
+
case GIT_CREDENTIAL_SSH_MEMORY: {
|
349
|
+
git_credential_ssh_key *c = (git_credential_ssh_key *)cred;
|
350
|
+
|
351
|
+
GIT_ASSERT(c->username);
|
352
|
+
GIT_ASSERT(c->privatekey);
|
353
|
+
|
354
|
+
rc = libssh2_userauth_publickey_frommemory(
|
355
|
+
session,
|
356
|
+
c->username,
|
357
|
+
strlen(c->username),
|
358
|
+
c->publickey,
|
359
|
+
c->publickey ? strlen(c->publickey) : 0,
|
360
|
+
c->privatekey,
|
361
|
+
strlen(c->privatekey),
|
362
|
+
c->passphrase);
|
363
|
+
break;
|
364
|
+
}
|
365
|
+
#endif
|
366
|
+
default:
|
367
|
+
rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED;
|
368
|
+
}
|
369
|
+
} while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);
|
370
|
+
|
371
|
+
if (rc == LIBSSH2_ERROR_PASSWORD_EXPIRED ||
|
372
|
+
rc == LIBSSH2_ERROR_AUTHENTICATION_FAILED ||
|
373
|
+
rc == LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED)
|
374
|
+
return GIT_EAUTH;
|
375
|
+
|
376
|
+
if (rc != LIBSSH2_ERROR_NONE) {
|
377
|
+
if (git_error_last()->klass == GIT_ERROR_NONE)
|
378
|
+
ssh_error(session, "failed to authenticate SSH session");
|
379
|
+
return -1;
|
380
|
+
}
|
381
|
+
|
382
|
+
return 0;
|
383
|
+
}
|
384
|
+
|
385
|
+
static int request_creds(git_credential **out, ssh_subtransport *t, const char *user, int auth_methods)
|
386
|
+
{
|
387
|
+
int error, no_callback = 0;
|
388
|
+
git_credential *cred = NULL;
|
389
|
+
|
390
|
+
if (!t->owner->connect_opts.callbacks.credentials) {
|
391
|
+
no_callback = 1;
|
392
|
+
} else {
|
393
|
+
error = t->owner->connect_opts.callbacks.credentials(
|
394
|
+
&cred,
|
395
|
+
t->owner->url,
|
396
|
+
user,
|
397
|
+
auth_methods,
|
398
|
+
t->owner->connect_opts.callbacks.payload);
|
399
|
+
|
400
|
+
if (error == GIT_PASSTHROUGH) {
|
401
|
+
no_callback = 1;
|
402
|
+
} else if (error < 0) {
|
403
|
+
return error;
|
404
|
+
} else if (!cred) {
|
405
|
+
git_error_set(GIT_ERROR_SSH, "callback failed to initialize SSH credentials");
|
406
|
+
return -1;
|
407
|
+
}
|
408
|
+
}
|
409
|
+
|
410
|
+
if (no_callback) {
|
411
|
+
git_error_set(GIT_ERROR_SSH, "authentication required but no callback set");
|
412
|
+
return GIT_EAUTH;
|
413
|
+
}
|
414
|
+
|
415
|
+
if (!(cred->credtype & auth_methods)) {
|
416
|
+
cred->free(cred);
|
417
|
+
git_error_set(GIT_ERROR_SSH, "authentication callback returned unsupported credentials type");
|
418
|
+
return GIT_EAUTH;
|
419
|
+
}
|
420
|
+
|
421
|
+
*out = cred;
|
422
|
+
|
423
|
+
return 0;
|
424
|
+
}
|
425
|
+
|
426
|
+
#define SSH_DIR ".ssh"
|
427
|
+
#define KNOWN_HOSTS_FILE "known_hosts"
|
428
|
+
|
429
|
+
/*
|
430
|
+
* Load the known_hosts file.
|
431
|
+
*
|
432
|
+
* Returns success but leaves the output NULL if we couldn't find the file.
|
433
|
+
*/
|
434
|
+
static int load_known_hosts(LIBSSH2_KNOWNHOSTS **hosts, LIBSSH2_SESSION *session)
|
435
|
+
{
|
436
|
+
git_str path = GIT_STR_INIT, sshdir = GIT_STR_INIT;
|
437
|
+
LIBSSH2_KNOWNHOSTS *known_hosts = NULL;
|
438
|
+
int error;
|
439
|
+
|
440
|
+
GIT_ASSERT_ARG(hosts);
|
441
|
+
|
442
|
+
if ((error = git_sysdir_expand_homedir_file(&sshdir, SSH_DIR)) < 0 ||
|
443
|
+
(error = git_str_joinpath(&path, git_str_cstr(&sshdir), KNOWN_HOSTS_FILE)) < 0)
|
444
|
+
goto out;
|
445
|
+
|
446
|
+
if ((known_hosts = libssh2_knownhost_init(session)) == NULL) {
|
447
|
+
ssh_error(session, "error initializing known hosts");
|
448
|
+
error = -1;
|
449
|
+
goto out;
|
450
|
+
}
|
451
|
+
|
452
|
+
/*
|
453
|
+
* Try to read the file and consider not finding it as not trusting the
|
454
|
+
* host rather than an error.
|
455
|
+
*/
|
456
|
+
error = libssh2_knownhost_readfile(known_hosts, git_str_cstr(&path), LIBSSH2_KNOWNHOST_FILE_OPENSSH);
|
457
|
+
if (error == LIBSSH2_ERROR_FILE)
|
458
|
+
error = 0;
|
459
|
+
if (error < 0)
|
460
|
+
ssh_error(session, "error reading known_hosts");
|
461
|
+
|
462
|
+
out:
|
463
|
+
*hosts = known_hosts;
|
464
|
+
|
465
|
+
git_str_dispose(&sshdir);
|
466
|
+
git_str_dispose(&path);
|
467
|
+
|
468
|
+
return error;
|
469
|
+
}
|
470
|
+
|
471
|
+
static void add_hostkey_pref_if_avail(
|
472
|
+
LIBSSH2_KNOWNHOSTS *known_hosts,
|
473
|
+
const char *hostname,
|
474
|
+
int port,
|
475
|
+
git_str *prefs,
|
476
|
+
int type,
|
477
|
+
const char *type_name)
|
478
|
+
{
|
479
|
+
struct libssh2_knownhost *host = NULL;
|
480
|
+
const char key = '\0';
|
481
|
+
int mask = LIBSSH2_KNOWNHOST_TYPE_PLAIN | LIBSSH2_KNOWNHOST_KEYENC_RAW | type;
|
482
|
+
int error;
|
483
|
+
|
484
|
+
error = libssh2_knownhost_checkp(known_hosts, hostname, port, &key, 1, mask, &host);
|
485
|
+
if (error == LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
|
486
|
+
if (git_str_len(prefs) > 0) {
|
487
|
+
git_str_putc(prefs, ',');
|
488
|
+
}
|
489
|
+
git_str_puts(prefs, type_name);
|
490
|
+
}
|
491
|
+
}
|
492
|
+
|
493
|
+
/*
|
494
|
+
* We figure out what kind of key we want to ask the remote for by trying to
|
495
|
+
* look it up with a nonsense key and using that mismatch to figure out what key
|
496
|
+
* we do have stored for the host.
|
497
|
+
*
|
498
|
+
* Populates prefs with the string to pass to libssh2_session_method_pref.
|
499
|
+
*/
|
500
|
+
static void find_hostkey_preference(
|
501
|
+
LIBSSH2_KNOWNHOSTS *known_hosts,
|
502
|
+
const char *hostname,
|
503
|
+
int port,
|
504
|
+
git_str *prefs)
|
505
|
+
{
|
506
|
+
/*
|
507
|
+
* The order here is important as it indicates the priority of what will
|
508
|
+
* be preferred.
|
509
|
+
*/
|
510
|
+
#ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
|
511
|
+
add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_ED25519, "ssh-ed25519");
|
512
|
+
#endif
|
513
|
+
#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
|
514
|
+
add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_ECDSA_256, "ecdsa-sha2-nistp256");
|
515
|
+
add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_ECDSA_384, "ecdsa-sha2-nistp384");
|
516
|
+
add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_ECDSA_521, "ecdsa-sha2-nistp521");
|
517
|
+
#endif
|
518
|
+
add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_SSHRSA, "rsa-sha2-512");
|
519
|
+
add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_SSHRSA, "rsa-sha2-256");
|
520
|
+
add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_SSHRSA, "ssh-rsa");
|
521
|
+
}
|
522
|
+
|
523
|
+
static int _git_ssh_session_create(
|
524
|
+
LIBSSH2_SESSION **session,
|
525
|
+
LIBSSH2_KNOWNHOSTS **hosts,
|
526
|
+
const char *hostname,
|
527
|
+
int port,
|
528
|
+
git_stream *io)
|
529
|
+
{
|
530
|
+
git_socket_stream *socket = GIT_CONTAINER_OF(io, git_socket_stream, parent);
|
531
|
+
LIBSSH2_SESSION *s;
|
532
|
+
LIBSSH2_KNOWNHOSTS *known_hosts;
|
533
|
+
git_str prefs = GIT_STR_INIT;
|
534
|
+
int rc = 0;
|
535
|
+
|
536
|
+
GIT_ASSERT_ARG(session);
|
537
|
+
GIT_ASSERT_ARG(hosts);
|
538
|
+
|
539
|
+
s = libssh2_session_init();
|
540
|
+
if (!s) {
|
541
|
+
git_error_set(GIT_ERROR_NET, "failed to initialize SSH session");
|
542
|
+
return -1;
|
543
|
+
}
|
544
|
+
|
545
|
+
if (git_socket_stream__timeout > 0) {
|
546
|
+
libssh2_session_set_timeout(s, git_socket_stream__timeout);
|
547
|
+
}
|
548
|
+
|
549
|
+
if ((rc = load_known_hosts(&known_hosts, s)) < 0) {
|
550
|
+
ssh_error(s, "error loading known_hosts");
|
551
|
+
libssh2_session_free(s);
|
552
|
+
return -1;
|
553
|
+
}
|
554
|
+
|
555
|
+
find_hostkey_preference(known_hosts, hostname, port, &prefs);
|
556
|
+
if (git_str_len(&prefs) > 0) {
|
557
|
+
do {
|
558
|
+
rc = libssh2_session_method_pref(s, LIBSSH2_METHOD_HOSTKEY, git_str_cstr(&prefs));
|
559
|
+
} while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);
|
560
|
+
if (rc != LIBSSH2_ERROR_NONE) {
|
561
|
+
ssh_error(s, "failed to set hostkey preference");
|
562
|
+
goto on_error;
|
563
|
+
}
|
564
|
+
}
|
565
|
+
git_str_dispose(&prefs);
|
566
|
+
|
567
|
+
do {
|
568
|
+
rc = libssh2_session_handshake(s, socket->s);
|
569
|
+
} while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);
|
570
|
+
|
571
|
+
if (rc != LIBSSH2_ERROR_NONE) {
|
572
|
+
ssh_error(s, "failed to start SSH session");
|
573
|
+
goto on_error;
|
574
|
+
}
|
575
|
+
|
576
|
+
libssh2_session_set_blocking(s, 1);
|
577
|
+
|
578
|
+
*session = s;
|
579
|
+
*hosts = known_hosts;
|
580
|
+
|
581
|
+
return 0;
|
582
|
+
|
583
|
+
on_error:
|
584
|
+
libssh2_knownhost_free(known_hosts);
|
585
|
+
libssh2_session_free(s);
|
586
|
+
return -1;
|
587
|
+
}
|
588
|
+
|
589
|
+
|
590
|
+
/*
|
591
|
+
* Returns the typemask argument to pass to libssh2_knownhost_check{,p} based on
|
592
|
+
* the type of key that libssh2_session_hostkey returns.
|
593
|
+
*/
|
594
|
+
static int fingerprint_type_mask(int keytype)
|
595
|
+
{
|
596
|
+
int mask = LIBSSH2_KNOWNHOST_TYPE_PLAIN | LIBSSH2_KNOWNHOST_KEYENC_RAW;
|
597
|
+
return mask;
|
598
|
+
|
599
|
+
switch (keytype) {
|
600
|
+
case LIBSSH2_HOSTKEY_TYPE_RSA:
|
601
|
+
mask |= LIBSSH2_KNOWNHOST_KEY_SSHRSA;
|
602
|
+
break;
|
603
|
+
case LIBSSH2_HOSTKEY_TYPE_DSS:
|
604
|
+
mask |= LIBSSH2_KNOWNHOST_KEY_SSHDSS;
|
605
|
+
break;
|
606
|
+
#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_256
|
607
|
+
case LIBSSH2_HOSTKEY_TYPE_ECDSA_256:
|
608
|
+
mask |= LIBSSH2_KNOWNHOST_KEY_ECDSA_256;
|
609
|
+
break;
|
610
|
+
case LIBSSH2_HOSTKEY_TYPE_ECDSA_384:
|
611
|
+
mask |= LIBSSH2_KNOWNHOST_KEY_ECDSA_384;
|
612
|
+
break;
|
613
|
+
case LIBSSH2_HOSTKEY_TYPE_ECDSA_521:
|
614
|
+
mask |= LIBSSH2_KNOWNHOST_KEY_ECDSA_521;
|
615
|
+
break;
|
616
|
+
#endif
|
617
|
+
#ifdef LIBSSH2_HOSTKEY_TYPE_ED25519
|
618
|
+
case LIBSSH2_HOSTKEY_TYPE_ED25519:
|
619
|
+
mask |= LIBSSH2_KNOWNHOST_KEY_ED25519;
|
620
|
+
break;
|
621
|
+
#endif
|
622
|
+
}
|
623
|
+
|
624
|
+
return mask;
|
625
|
+
}
|
626
|
+
|
627
|
+
/*
|
628
|
+
* Check the host against the user's known_hosts file.
|
629
|
+
*
|
630
|
+
* Returns 1/0 for valid/''not-valid or <0 for an error
|
631
|
+
*/
|
632
|
+
static int check_against_known_hosts(
|
633
|
+
LIBSSH2_SESSION *session,
|
634
|
+
LIBSSH2_KNOWNHOSTS *known_hosts,
|
635
|
+
const char *hostname,
|
636
|
+
int port,
|
637
|
+
const char *key,
|
638
|
+
size_t key_len,
|
639
|
+
int key_type)
|
640
|
+
{
|
641
|
+
int check, typemask, ret = 0;
|
642
|
+
struct libssh2_knownhost *host = NULL;
|
643
|
+
|
644
|
+
if (known_hosts == NULL)
|
645
|
+
return 0;
|
646
|
+
|
647
|
+
typemask = fingerprint_type_mask(key_type);
|
648
|
+
check = libssh2_knownhost_checkp(known_hosts, hostname, port, key, key_len, typemask, &host);
|
649
|
+
if (check == LIBSSH2_KNOWNHOST_CHECK_FAILURE) {
|
650
|
+
ssh_error(session, "error checking for known host");
|
651
|
+
return -1;
|
652
|
+
}
|
653
|
+
|
654
|
+
ret = check == LIBSSH2_KNOWNHOST_CHECK_MATCH ? 1 : 0;
|
655
|
+
|
656
|
+
return ret;
|
657
|
+
}
|
658
|
+
|
659
|
+
/*
|
660
|
+
* Perform the check for the session's certificate against known hosts if
|
661
|
+
* possible and then ask the user if they have a callback.
|
662
|
+
*
|
663
|
+
* Returns 1/0 for valid/not-valid or <0 for an error
|
664
|
+
*/
|
665
|
+
static int check_certificate(
|
666
|
+
LIBSSH2_SESSION *session,
|
667
|
+
LIBSSH2_KNOWNHOSTS *known_hosts,
|
668
|
+
git_transport_certificate_check_cb check_cb,
|
669
|
+
void *check_cb_payload,
|
670
|
+
const char *host,
|
671
|
+
int port)
|
672
|
+
{
|
673
|
+
git_cert_hostkey cert = {{ 0 }};
|
674
|
+
const char *key;
|
675
|
+
size_t cert_len;
|
676
|
+
int cert_type, cert_valid = 0, error = GIT_ECERTIFICATE;
|
677
|
+
|
678
|
+
if ((key = libssh2_session_hostkey(session, &cert_len, &cert_type)) == NULL) {
|
679
|
+
ssh_error(session, "failed to retrieve hostkey");
|
680
|
+
return -1;
|
681
|
+
}
|
682
|
+
|
683
|
+
if ((cert_valid = check_against_known_hosts(session, known_hosts, host, port, key, cert_len, cert_type)) < 0)
|
684
|
+
return -1;
|
685
|
+
|
686
|
+
cert.parent.cert_type = GIT_CERT_HOSTKEY_LIBSSH2;
|
687
|
+
if (key != NULL) {
|
688
|
+
cert.type |= GIT_CERT_SSH_RAW;
|
689
|
+
cert.hostkey = key;
|
690
|
+
cert.hostkey_len = cert_len;
|
691
|
+
switch (cert_type) {
|
692
|
+
case LIBSSH2_HOSTKEY_TYPE_RSA:
|
693
|
+
cert.raw_type = GIT_CERT_SSH_RAW_TYPE_RSA;
|
694
|
+
break;
|
695
|
+
case LIBSSH2_HOSTKEY_TYPE_DSS:
|
696
|
+
cert.raw_type = GIT_CERT_SSH_RAW_TYPE_DSS;
|
697
|
+
break;
|
698
|
+
|
699
|
+
#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_256
|
700
|
+
case LIBSSH2_HOSTKEY_TYPE_ECDSA_256:
|
701
|
+
cert.raw_type = GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_256;
|
702
|
+
break;
|
703
|
+
case LIBSSH2_HOSTKEY_TYPE_ECDSA_384:
|
704
|
+
cert.raw_type = GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_384;
|
705
|
+
break;
|
706
|
+
case LIBSSH2_KNOWNHOST_KEY_ECDSA_521:
|
707
|
+
cert.raw_type = GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_521;
|
708
|
+
break;
|
709
|
+
#endif
|
710
|
+
|
711
|
+
#ifdef LIBSSH2_HOSTKEY_TYPE_ED25519
|
712
|
+
case LIBSSH2_HOSTKEY_TYPE_ED25519:
|
713
|
+
cert.raw_type = GIT_CERT_SSH_RAW_TYPE_KEY_ED25519;
|
714
|
+
break;
|
715
|
+
#endif
|
716
|
+
default:
|
717
|
+
cert.raw_type = GIT_CERT_SSH_RAW_TYPE_UNKNOWN;
|
718
|
+
}
|
719
|
+
}
|
720
|
+
|
721
|
+
#ifdef LIBSSH2_HOSTKEY_HASH_SHA256
|
722
|
+
key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA256);
|
723
|
+
if (key != NULL) {
|
724
|
+
cert.type |= GIT_CERT_SSH_SHA256;
|
725
|
+
memcpy(&cert.hash_sha256, key, 32);
|
726
|
+
}
|
727
|
+
#endif
|
728
|
+
|
729
|
+
key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
730
|
+
if (key != NULL) {
|
731
|
+
cert.type |= GIT_CERT_SSH_SHA1;
|
732
|
+
memcpy(&cert.hash_sha1, key, 20);
|
733
|
+
}
|
734
|
+
|
735
|
+
key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
736
|
+
if (key != NULL) {
|
737
|
+
cert.type |= GIT_CERT_SSH_MD5;
|
738
|
+
memcpy(&cert.hash_md5, key, 16);
|
739
|
+
}
|
740
|
+
|
741
|
+
if (cert.type == 0) {
|
742
|
+
git_error_set(GIT_ERROR_SSH, "unable to get the host key");
|
743
|
+
return -1;
|
744
|
+
}
|
745
|
+
|
746
|
+
if (check_cb != NULL) {
|
747
|
+
git_cert_hostkey *cert_ptr = &cert;
|
748
|
+
|
749
|
+
error = check_cb((git_cert *)cert_ptr, cert_valid, host,
|
750
|
+
check_cb_payload);
|
751
|
+
|
752
|
+
if (error == 0)
|
753
|
+
cert_valid = 1;
|
754
|
+
else if (error != GIT_PASSTHROUGH)
|
755
|
+
cert_valid = 0;
|
756
|
+
}
|
757
|
+
|
758
|
+
if (!cert_valid) {
|
759
|
+
git_error_set(GIT_ERROR_SSH, "invalid or unknown remote ssh hostkey");
|
760
|
+
return (error == GIT_PASSTHROUGH) ? GIT_ECERTIFICATE : error;
|
761
|
+
}
|
762
|
+
|
763
|
+
return 0;
|
764
|
+
}
|
765
|
+
|
766
|
+
#define SSH_DEFAULT_PORT "22"
|
767
|
+
|
768
|
+
static int _git_ssh_setup_conn(
|
769
|
+
ssh_subtransport *t,
|
770
|
+
const char *url,
|
771
|
+
const char *cmd,
|
772
|
+
git_smart_subtransport_stream **stream)
|
773
|
+
{
|
774
|
+
int auth_methods, error = 0, port;
|
775
|
+
ssh_stream *s;
|
776
|
+
git_credential *cred = NULL;
|
777
|
+
LIBSSH2_SESSION *session=NULL;
|
778
|
+
LIBSSH2_CHANNEL *channel=NULL;
|
779
|
+
LIBSSH2_KNOWNHOSTS *known_hosts = NULL;
|
780
|
+
|
781
|
+
t->current_stream = NULL;
|
782
|
+
|
783
|
+
*stream = NULL;
|
784
|
+
if (ssh_stream_alloc(t, cmd, stream) < 0)
|
785
|
+
return -1;
|
786
|
+
|
787
|
+
s = (ssh_stream *)*stream;
|
788
|
+
s->session = NULL;
|
789
|
+
s->channel = NULL;
|
790
|
+
|
791
|
+
if (git_net_str_is_url(url))
|
792
|
+
error = git_net_url_parse(&s->url, url);
|
793
|
+
else
|
794
|
+
error = git_net_url_parse_scp(&s->url, url);
|
795
|
+
|
796
|
+
if (error < 0)
|
797
|
+
goto done;
|
798
|
+
|
799
|
+
/* Safety check: like git, we forbid paths that look like an option as
|
800
|
+
* that could lead to injection on the remote side */
|
801
|
+
if (git_process__is_cmdline_option(s->url.path)) {
|
802
|
+
git_error_set(GIT_ERROR_NET, "cannot ssh: path '%s' is ambiguous with command-line option", s->url.path);
|
803
|
+
error = -1;
|
804
|
+
goto done;
|
805
|
+
}
|
806
|
+
|
807
|
+
|
808
|
+
if ((error = git_socket_stream_new(&s->io, s->url.host, s->url.port)) < 0 ||
|
809
|
+
(error = git_stream_connect(s->io)) < 0)
|
810
|
+
goto done;
|
811
|
+
|
812
|
+
/*
|
813
|
+
* Try to parse the port as a number, if we can't then fall back to
|
814
|
+
* default. It would be nice if we could get the port that was resolved
|
815
|
+
* as part of the stream connection, but that's not something that's
|
816
|
+
* exposed.
|
817
|
+
*/
|
818
|
+
if (git__strntol32(&port, s->url.port, strlen(s->url.port), NULL, 10) < 0)
|
819
|
+
port = -1;
|
820
|
+
|
821
|
+
if ((error = _git_ssh_session_create(&session, &known_hosts, s->url.host, port, s->io)) < 0)
|
822
|
+
goto done;
|
823
|
+
|
824
|
+
if ((error = check_certificate(session, known_hosts, t->owner->connect_opts.callbacks.certificate_check, t->owner->connect_opts.callbacks.payload, s->url.host, port)) < 0)
|
825
|
+
goto done;
|
826
|
+
|
827
|
+
/* we need the username to ask for auth methods */
|
828
|
+
if (!s->url.username) {
|
829
|
+
if ((error = request_creds(&cred, t, NULL, GIT_CREDENTIAL_USERNAME)) < 0)
|
830
|
+
goto done;
|
831
|
+
|
832
|
+
s->url.username = git__strdup(((git_credential_username *) cred)->username);
|
833
|
+
cred->free(cred);
|
834
|
+
cred = NULL;
|
835
|
+
if (!s->url.username)
|
836
|
+
goto done;
|
837
|
+
} else if (s->url.username && s->url.password) {
|
838
|
+
if ((error = git_credential_userpass_plaintext_new(&cred, s->url.username, s->url.password)) < 0)
|
839
|
+
goto done;
|
840
|
+
}
|
841
|
+
|
842
|
+
if ((error = list_auth_methods(&auth_methods, session, s->url.username)) < 0)
|
843
|
+
goto done;
|
844
|
+
|
845
|
+
error = GIT_EAUTH;
|
846
|
+
/* if we already have something to try */
|
847
|
+
if (cred && auth_methods & cred->credtype)
|
848
|
+
error = _git_ssh_authenticate_session(session, cred);
|
849
|
+
|
850
|
+
while (error == GIT_EAUTH) {
|
851
|
+
if (cred) {
|
852
|
+
cred->free(cred);
|
853
|
+
cred = NULL;
|
854
|
+
}
|
855
|
+
|
856
|
+
if ((error = request_creds(&cred, t, s->url.username, auth_methods)) < 0)
|
857
|
+
goto done;
|
858
|
+
|
859
|
+
if (strcmp(s->url.username, git_credential_get_username(cred))) {
|
860
|
+
git_error_set(GIT_ERROR_SSH, "username does not match previous request");
|
861
|
+
error = -1;
|
862
|
+
goto done;
|
863
|
+
}
|
864
|
+
|
865
|
+
error = _git_ssh_authenticate_session(session, cred);
|
866
|
+
|
867
|
+
if (error == GIT_EAUTH) {
|
868
|
+
/* refresh auth methods */
|
869
|
+
if ((error = list_auth_methods(&auth_methods, session, s->url.username)) < 0)
|
870
|
+
goto done;
|
871
|
+
else
|
872
|
+
error = GIT_EAUTH;
|
873
|
+
}
|
874
|
+
}
|
875
|
+
|
876
|
+
if (error < 0)
|
877
|
+
goto done;
|
878
|
+
|
879
|
+
channel = libssh2_channel_open_session(session);
|
880
|
+
if (!channel) {
|
881
|
+
error = -1;
|
882
|
+
ssh_error(session, "Failed to open SSH channel");
|
883
|
+
goto done;
|
884
|
+
}
|
885
|
+
|
886
|
+
libssh2_channel_set_blocking(channel, 1);
|
887
|
+
|
888
|
+
s->session = session;
|
889
|
+
s->channel = channel;
|
890
|
+
|
891
|
+
t->current_stream = s;
|
892
|
+
|
893
|
+
done:
|
894
|
+
if (known_hosts)
|
895
|
+
libssh2_knownhost_free(known_hosts);
|
896
|
+
|
897
|
+
if (error < 0) {
|
898
|
+
ssh_stream_free(*stream);
|
899
|
+
|
900
|
+
if (session)
|
901
|
+
libssh2_session_free(session);
|
902
|
+
}
|
903
|
+
|
904
|
+
if (cred)
|
905
|
+
cred->free(cred);
|
906
|
+
|
907
|
+
return error;
|
908
|
+
}
|
909
|
+
|
910
|
+
static int ssh_uploadpack_ls(
|
911
|
+
ssh_subtransport *t,
|
912
|
+
const char *url,
|
913
|
+
git_smart_subtransport_stream **stream)
|
914
|
+
{
|
915
|
+
const char *cmd = t->cmd_uploadpack ? t->cmd_uploadpack : cmd_uploadpack;
|
916
|
+
|
917
|
+
return _git_ssh_setup_conn(t, url, cmd, stream);
|
918
|
+
}
|
919
|
+
|
920
|
+
static int ssh_uploadpack(
|
921
|
+
ssh_subtransport *t,
|
922
|
+
const char *url,
|
923
|
+
git_smart_subtransport_stream **stream)
|
924
|
+
{
|
925
|
+
GIT_UNUSED(url);
|
926
|
+
|
927
|
+
if (t->current_stream) {
|
928
|
+
*stream = &t->current_stream->parent;
|
929
|
+
return 0;
|
930
|
+
}
|
931
|
+
|
932
|
+
git_error_set(GIT_ERROR_NET, "must call UPLOADPACK_LS before UPLOADPACK");
|
933
|
+
return -1;
|
934
|
+
}
|
935
|
+
|
936
|
+
static int ssh_receivepack_ls(
|
937
|
+
ssh_subtransport *t,
|
938
|
+
const char *url,
|
939
|
+
git_smart_subtransport_stream **stream)
|
940
|
+
{
|
941
|
+
const char *cmd = t->cmd_receivepack ? t->cmd_receivepack : cmd_receivepack;
|
942
|
+
|
943
|
+
|
944
|
+
return _git_ssh_setup_conn(t, url, cmd, stream);
|
945
|
+
}
|
946
|
+
|
947
|
+
static int ssh_receivepack(
|
948
|
+
ssh_subtransport *t,
|
949
|
+
const char *url,
|
950
|
+
git_smart_subtransport_stream **stream)
|
951
|
+
{
|
952
|
+
GIT_UNUSED(url);
|
953
|
+
|
954
|
+
if (t->current_stream) {
|
955
|
+
*stream = &t->current_stream->parent;
|
956
|
+
return 0;
|
957
|
+
}
|
958
|
+
|
959
|
+
git_error_set(GIT_ERROR_NET, "must call RECEIVEPACK_LS before RECEIVEPACK");
|
960
|
+
return -1;
|
961
|
+
}
|
962
|
+
|
963
|
+
static int _ssh_action(
|
964
|
+
git_smart_subtransport_stream **stream,
|
965
|
+
git_smart_subtransport *subtransport,
|
966
|
+
const char *url,
|
967
|
+
git_smart_service_t action)
|
968
|
+
{
|
969
|
+
ssh_subtransport *t = GIT_CONTAINER_OF(subtransport, ssh_subtransport, parent);
|
970
|
+
|
971
|
+
switch (action) {
|
972
|
+
case GIT_SERVICE_UPLOADPACK_LS:
|
973
|
+
return ssh_uploadpack_ls(t, url, stream);
|
974
|
+
|
975
|
+
case GIT_SERVICE_UPLOADPACK:
|
976
|
+
return ssh_uploadpack(t, url, stream);
|
977
|
+
|
978
|
+
case GIT_SERVICE_RECEIVEPACK_LS:
|
979
|
+
return ssh_receivepack_ls(t, url, stream);
|
980
|
+
|
981
|
+
case GIT_SERVICE_RECEIVEPACK:
|
982
|
+
return ssh_receivepack(t, url, stream);
|
983
|
+
}
|
984
|
+
|
985
|
+
*stream = NULL;
|
986
|
+
return -1;
|
987
|
+
}
|
988
|
+
|
989
|
+
static int _ssh_close(git_smart_subtransport *subtransport)
|
990
|
+
{
|
991
|
+
ssh_subtransport *t = GIT_CONTAINER_OF(subtransport, ssh_subtransport, parent);
|
992
|
+
|
993
|
+
GIT_ASSERT(!t->current_stream);
|
994
|
+
|
995
|
+
GIT_UNUSED(t);
|
996
|
+
|
997
|
+
return 0;
|
998
|
+
}
|
999
|
+
|
1000
|
+
static void _ssh_free(git_smart_subtransport *subtransport)
|
1001
|
+
{
|
1002
|
+
ssh_subtransport *t = GIT_CONTAINER_OF(subtransport, ssh_subtransport, parent);
|
1003
|
+
|
1004
|
+
git__free(t->cmd_uploadpack);
|
1005
|
+
git__free(t->cmd_receivepack);
|
1006
|
+
git__free(t);
|
1007
|
+
}
|
1008
|
+
|
1009
|
+
#define SSH_AUTH_PUBLICKEY "publickey"
|
1010
|
+
#define SSH_AUTH_PASSWORD "password"
|
1011
|
+
#define SSH_AUTH_KEYBOARD_INTERACTIVE "keyboard-interactive"
|
1012
|
+
|
1013
|
+
static int list_auth_methods(int *out, LIBSSH2_SESSION *session, const char *username)
|
1014
|
+
{
|
1015
|
+
const char *list, *ptr;
|
1016
|
+
|
1017
|
+
*out = 0;
|
1018
|
+
|
1019
|
+
list = libssh2_userauth_list(session, username,
|
1020
|
+
(unsigned int)strlen(username));
|
1021
|
+
|
1022
|
+
/* either error, or the remote accepts NONE auth, which is bizarre, let's punt */
|
1023
|
+
if (list == NULL && !libssh2_userauth_authenticated(session)) {
|
1024
|
+
ssh_error(session, "remote rejected authentication");
|
1025
|
+
return GIT_EAUTH;
|
1026
|
+
}
|
1027
|
+
|
1028
|
+
ptr = list;
|
1029
|
+
while (ptr) {
|
1030
|
+
if (*ptr == ',')
|
1031
|
+
ptr++;
|
1032
|
+
|
1033
|
+
if (!git__prefixcmp(ptr, SSH_AUTH_PUBLICKEY)) {
|
1034
|
+
*out |= GIT_CREDENTIAL_SSH_KEY;
|
1035
|
+
*out |= GIT_CREDENTIAL_SSH_CUSTOM;
|
1036
|
+
#ifdef GIT_SSH_LIBSSH2_MEMORY_CREDENTIALS
|
1037
|
+
*out |= GIT_CREDENTIAL_SSH_MEMORY;
|
1038
|
+
#endif
|
1039
|
+
ptr += strlen(SSH_AUTH_PUBLICKEY);
|
1040
|
+
continue;
|
1041
|
+
}
|
1042
|
+
|
1043
|
+
if (!git__prefixcmp(ptr, SSH_AUTH_PASSWORD)) {
|
1044
|
+
*out |= GIT_CREDENTIAL_USERPASS_PLAINTEXT;
|
1045
|
+
ptr += strlen(SSH_AUTH_PASSWORD);
|
1046
|
+
continue;
|
1047
|
+
}
|
1048
|
+
|
1049
|
+
if (!git__prefixcmp(ptr, SSH_AUTH_KEYBOARD_INTERACTIVE)) {
|
1050
|
+
*out |= GIT_CREDENTIAL_SSH_INTERACTIVE;
|
1051
|
+
ptr += strlen(SSH_AUTH_KEYBOARD_INTERACTIVE);
|
1052
|
+
continue;
|
1053
|
+
}
|
1054
|
+
|
1055
|
+
/* Skip it if we don't know it */
|
1056
|
+
ptr = strchr(ptr, ',');
|
1057
|
+
}
|
1058
|
+
|
1059
|
+
return 0;
|
1060
|
+
}
|
1061
|
+
|
1062
|
+
int git_smart_subtransport_ssh_libssh2(
|
1063
|
+
git_smart_subtransport **out,
|
1064
|
+
git_transport *owner,
|
1065
|
+
void *param)
|
1066
|
+
{
|
1067
|
+
ssh_subtransport *t;
|
1068
|
+
|
1069
|
+
GIT_ASSERT_ARG(out);
|
1070
|
+
|
1071
|
+
GIT_UNUSED(param);
|
1072
|
+
|
1073
|
+
t = git__calloc(sizeof(ssh_subtransport), 1);
|
1074
|
+
GIT_ERROR_CHECK_ALLOC(t);
|
1075
|
+
|
1076
|
+
t->owner = (transport_smart *)owner;
|
1077
|
+
t->parent.action = _ssh_action;
|
1078
|
+
t->parent.close = _ssh_close;
|
1079
|
+
t->parent.free = _ssh_free;
|
1080
|
+
|
1081
|
+
*out = (git_smart_subtransport *) t;
|
1082
|
+
return 0;
|
1083
|
+
}
|
1084
|
+
|
1085
|
+
int git_smart_subtransport_ssh_libssh2_set_paths(
|
1086
|
+
git_smart_subtransport *subtransport,
|
1087
|
+
const char *cmd_uploadpack,
|
1088
|
+
const char *cmd_receivepack)
|
1089
|
+
{
|
1090
|
+
ssh_subtransport *t = (ssh_subtransport *)subtransport;
|
1091
|
+
|
1092
|
+
git__free(t->cmd_uploadpack);
|
1093
|
+
git__free(t->cmd_receivepack);
|
1094
|
+
|
1095
|
+
t->cmd_uploadpack = git__strdup(cmd_uploadpack);
|
1096
|
+
GIT_ERROR_CHECK_ALLOC(t->cmd_uploadpack);
|
1097
|
+
|
1098
|
+
t->cmd_receivepack = git__strdup(cmd_receivepack);
|
1099
|
+
GIT_ERROR_CHECK_ALLOC(t->cmd_receivepack);
|
1100
|
+
|
1101
|
+
return 0;
|
1102
|
+
}
|
1103
|
+
|
1104
|
+
static void shutdown_libssh2(void)
|
1105
|
+
{
|
1106
|
+
libssh2_exit();
|
1107
|
+
}
|
1108
|
+
|
1109
|
+
int git_transport_ssh_libssh2_global_init(void)
|
1110
|
+
{
|
1111
|
+
if (libssh2_init(0) < 0) {
|
1112
|
+
git_error_set(GIT_ERROR_SSH, "unable to initialize libssh2");
|
1113
|
+
return -1;
|
1114
|
+
}
|
1115
|
+
|
1116
|
+
return git_runtime_shutdown_register(shutdown_libssh2);
|
1117
|
+
}
|
1118
|
+
|
1119
|
+
#else /* GIT_SSH */
|
1120
|
+
|
1121
|
+
int git_transport_ssh_libssh2_global_init(void)
|
1122
|
+
{
|
1123
|
+
return 0;
|
1124
|
+
}
|
1125
|
+
|
1126
|
+
#endif
|