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.
Files changed (409) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rugged/version.rb +1 -1
  3. data/vendor/libgit2/AUTHORS +1 -0
  4. data/vendor/libgit2/CMakeLists.txt +99 -51
  5. data/vendor/libgit2/COPYING +28 -0
  6. data/vendor/libgit2/cmake/Modules/AddCFlagIfSupported.cmake +15 -1
  7. data/vendor/libgit2/cmake/Modules/CheckPrototypeDefinition.c.in +29 -0
  8. data/vendor/libgit2/cmake/Modules/CheckPrototypeDefinition.cmake +96 -0
  9. data/vendor/libgit2/cmake/Modules/EnableWarnings.cmake +9 -8
  10. data/vendor/libgit2/cmake/Modules/FindCoreFoundation.cmake +2 -2
  11. data/vendor/libgit2/cmake/Modules/FindGSSAPI.cmake +1 -1
  12. data/vendor/libgit2/cmake/Modules/FindGSSFramework.cmake +28 -0
  13. data/vendor/libgit2/cmake/Modules/FindIconv.cmake +11 -6
  14. data/vendor/libgit2/cmake/Modules/FindPCRE.cmake +38 -0
  15. data/vendor/libgit2/cmake/Modules/FindPCRE2.cmake +37 -0
  16. data/vendor/libgit2/cmake/Modules/FindSecurity.cmake +2 -2
  17. data/vendor/libgit2/cmake/Modules/FindStatNsec.cmake +6 -0
  18. data/vendor/libgit2/cmake/Modules/PkgBuildConfig.cmake +110 -0
  19. data/vendor/libgit2/cmake/Modules/SelectGSSAPI.cmake +53 -0
  20. data/vendor/libgit2/cmake/Modules/SelectHTTPSBackend.cmake +124 -0
  21. data/vendor/libgit2/cmake/Modules/SelectHashes.cmake +66 -0
  22. data/vendor/libgit2/deps/http-parser/http_parser.c +11 -6
  23. data/vendor/libgit2/deps/ntlmclient/CMakeLists.txt +21 -0
  24. data/vendor/libgit2/deps/ntlmclient/compat.h +33 -0
  25. data/vendor/libgit2/deps/ntlmclient/crypt.h +64 -0
  26. data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.c +120 -0
  27. data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.h +18 -0
  28. data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.c +145 -0
  29. data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.h +18 -0
  30. data/vendor/libgit2/deps/ntlmclient/crypt_openssl.c +130 -0
  31. data/vendor/libgit2/deps/ntlmclient/crypt_openssl.h +21 -0
  32. data/vendor/libgit2/deps/ntlmclient/ntlm.c +1420 -0
  33. data/vendor/libgit2/deps/ntlmclient/ntlm.h +174 -0
  34. data/vendor/libgit2/deps/ntlmclient/ntlmclient.h +320 -0
  35. data/vendor/libgit2/deps/ntlmclient/unicode.h +36 -0
  36. data/vendor/libgit2/deps/ntlmclient/unicode_builtin.c +445 -0
  37. data/vendor/libgit2/deps/ntlmclient/unicode_iconv.c +201 -0
  38. data/vendor/libgit2/deps/ntlmclient/utf8.h +1257 -0
  39. data/vendor/libgit2/deps/ntlmclient/util.c +21 -0
  40. data/vendor/libgit2/deps/ntlmclient/util.h +14 -0
  41. data/vendor/libgit2/deps/pcre/CMakeLists.txt +140 -0
  42. data/vendor/libgit2/deps/pcre/COPYING +5 -0
  43. data/vendor/libgit2/deps/pcre/cmake/COPYING-CMAKE-SCRIPTS +22 -0
  44. data/vendor/libgit2/deps/pcre/cmake/FindEditline.cmake +17 -0
  45. data/vendor/libgit2/deps/pcre/cmake/FindPackageHandleStandardArgs.cmake +58 -0
  46. data/vendor/libgit2/deps/pcre/cmake/FindReadline.cmake +29 -0
  47. data/vendor/libgit2/deps/pcre/config.h.in +57 -0
  48. data/vendor/libgit2/deps/pcre/pcre.h +641 -0
  49. data/vendor/libgit2/deps/pcre/pcre_byte_order.c +319 -0
  50. data/vendor/libgit2/deps/pcre/pcre_chartables.c +198 -0
  51. data/vendor/libgit2/deps/pcre/pcre_compile.c +9800 -0
  52. data/vendor/libgit2/deps/pcre/pcre_config.c +190 -0
  53. data/vendor/libgit2/deps/pcre/pcre_dfa_exec.c +3676 -0
  54. data/vendor/libgit2/deps/pcre/pcre_exec.c +7173 -0
  55. data/vendor/libgit2/deps/pcre/pcre_fullinfo.c +245 -0
  56. data/vendor/libgit2/deps/pcre/pcre_get.c +669 -0
  57. data/vendor/libgit2/deps/pcre/pcre_globals.c +86 -0
  58. data/vendor/libgit2/deps/pcre/pcre_internal.h +2787 -0
  59. data/vendor/libgit2/deps/pcre/pcre_jit_compile.c +11913 -0
  60. data/vendor/libgit2/deps/pcre/pcre_maketables.c +156 -0
  61. data/vendor/libgit2/deps/pcre/pcre_newline.c +210 -0
  62. data/vendor/libgit2/deps/pcre/pcre_ord2utf8.c +94 -0
  63. data/vendor/libgit2/deps/pcre/pcre_printint.c +834 -0
  64. data/vendor/libgit2/deps/pcre/pcre_refcount.c +92 -0
  65. data/vendor/libgit2/deps/pcre/pcre_string_utils.c +211 -0
  66. data/vendor/libgit2/deps/pcre/pcre_study.c +1686 -0
  67. data/vendor/libgit2/deps/pcre/pcre_tables.c +727 -0
  68. data/vendor/libgit2/deps/pcre/pcre_ucd.c +3644 -0
  69. data/vendor/libgit2/deps/pcre/pcre_valid_utf8.c +301 -0
  70. data/vendor/libgit2/deps/pcre/pcre_version.c +98 -0
  71. data/vendor/libgit2/deps/pcre/pcre_xclass.c +268 -0
  72. data/vendor/libgit2/deps/pcre/pcreposix.c +421 -0
  73. data/vendor/libgit2/deps/pcre/pcreposix.h +117 -0
  74. data/vendor/libgit2/deps/pcre/ucp.h +224 -0
  75. data/vendor/libgit2/deps/winhttp/COPYING.GPL +993 -0
  76. data/vendor/libgit2/deps/winhttp/COPYING.LGPL +502 -0
  77. data/vendor/libgit2/deps/zlib/CMakeLists.txt +1 -0
  78. data/vendor/libgit2/deps/zlib/COPYING +27 -0
  79. data/vendor/libgit2/deps/zlib/adler32.c +0 -7
  80. data/vendor/libgit2/deps/zlib/crc32.c +0 -7
  81. data/vendor/libgit2/include/git2/annotated_commit.h +9 -0
  82. data/vendor/libgit2/include/git2/apply.h +149 -0
  83. data/vendor/libgit2/include/git2/attr.h +20 -13
  84. data/vendor/libgit2/include/git2/blame.h +4 -4
  85. data/vendor/libgit2/include/git2/blob.h +44 -12
  86. data/vendor/libgit2/include/git2/buffer.h +20 -26
  87. data/vendor/libgit2/include/git2/cert.h +135 -0
  88. data/vendor/libgit2/include/git2/checkout.h +53 -21
  89. data/vendor/libgit2/include/git2/cherrypick.h +3 -3
  90. data/vendor/libgit2/include/git2/clone.h +5 -5
  91. data/vendor/libgit2/include/git2/commit.h +25 -3
  92. data/vendor/libgit2/include/git2/common.h +35 -10
  93. data/vendor/libgit2/include/git2/config.h +29 -19
  94. data/vendor/libgit2/include/git2/cred.h +308 -0
  95. data/vendor/libgit2/include/git2/deprecated.h +493 -0
  96. data/vendor/libgit2/include/git2/describe.h +4 -4
  97. data/vendor/libgit2/include/git2/diff.h +177 -135
  98. data/vendor/libgit2/include/git2/errors.h +53 -46
  99. data/vendor/libgit2/include/git2/filter.h +8 -0
  100. data/vendor/libgit2/include/git2/index.h +74 -52
  101. data/vendor/libgit2/include/git2/indexer.h +76 -6
  102. data/vendor/libgit2/include/git2/merge.h +25 -10
  103. data/vendor/libgit2/include/git2/net.h +0 -5
  104. data/vendor/libgit2/include/git2/notes.h +1 -1
  105. data/vendor/libgit2/include/git2/object.h +17 -29
  106. data/vendor/libgit2/include/git2/odb.h +12 -11
  107. data/vendor/libgit2/include/git2/odb_backend.h +10 -9
  108. data/vendor/libgit2/include/git2/oid.h +2 -2
  109. data/vendor/libgit2/include/git2/pack.h +14 -3
  110. data/vendor/libgit2/include/git2/proxy.h +5 -3
  111. data/vendor/libgit2/include/git2/rebase.h +46 -2
  112. data/vendor/libgit2/include/git2/refs.h +34 -16
  113. data/vendor/libgit2/include/git2/remote.h +111 -14
  114. data/vendor/libgit2/include/git2/repository.h +69 -34
  115. data/vendor/libgit2/include/git2/revert.h +1 -1
  116. data/vendor/libgit2/include/git2/revwalk.h +7 -7
  117. data/vendor/libgit2/include/git2/signature.h +2 -2
  118. data/vendor/libgit2/include/git2/stash.h +5 -5
  119. data/vendor/libgit2/include/git2/status.h +26 -17
  120. data/vendor/libgit2/include/git2/submodule.h +23 -6
  121. data/vendor/libgit2/include/git2/sys/alloc.h +18 -18
  122. data/vendor/libgit2/include/git2/sys/commit.h +1 -1
  123. data/vendor/libgit2/include/git2/sys/config.h +13 -13
  124. data/vendor/libgit2/include/git2/sys/cred.h +90 -0
  125. data/vendor/libgit2/include/git2/sys/filter.h +6 -6
  126. data/vendor/libgit2/include/git2/sys/merge.h +3 -3
  127. data/vendor/libgit2/include/git2/sys/odb_backend.h +66 -22
  128. data/vendor/libgit2/include/git2/sys/path.h +14 -5
  129. data/vendor/libgit2/include/git2/sys/refdb_backend.h +76 -40
  130. data/vendor/libgit2/include/git2/sys/repository.h +5 -1
  131. data/vendor/libgit2/include/git2/sys/stream.h +92 -12
  132. data/vendor/libgit2/include/git2/sys/transport.h +129 -83
  133. data/vendor/libgit2/include/git2/tag.h +13 -4
  134. data/vendor/libgit2/include/git2/trace.h +2 -2
  135. data/vendor/libgit2/include/git2/transport.h +11 -311
  136. data/vendor/libgit2/include/git2/tree.h +4 -4
  137. data/vendor/libgit2/include/git2/types.h +25 -106
  138. data/vendor/libgit2/include/git2/version.h +3 -3
  139. data/vendor/libgit2/include/git2/worktree.h +5 -5
  140. data/vendor/libgit2/include/git2.h +4 -0
  141. data/vendor/libgit2/src/CMakeLists.txt +104 -235
  142. data/vendor/libgit2/src/alloc.c +14 -18
  143. data/vendor/libgit2/src/{stdalloc.c → allocators/stdalloc.c} +7 -8
  144. data/vendor/libgit2/src/{stdalloc.h → allocators/stdalloc.h} +4 -4
  145. data/vendor/libgit2/src/allocators/win32_crtdbg.c +118 -0
  146. data/vendor/libgit2/src/{transports/cred.h → allocators/win32_crtdbg.h} +5 -4
  147. data/vendor/libgit2/src/annotated_commit.c +18 -11
  148. data/vendor/libgit2/src/apply.c +535 -28
  149. data/vendor/libgit2/src/apply.h +3 -1
  150. data/vendor/libgit2/src/array.h +2 -2
  151. data/vendor/libgit2/src/attr.c +77 -71
  152. data/vendor/libgit2/src/attr_file.c +203 -117
  153. data/vendor/libgit2/src/attr_file.h +9 -9
  154. data/vendor/libgit2/src/attrcache.c +49 -51
  155. data/vendor/libgit2/src/attrcache.h +2 -1
  156. data/vendor/libgit2/src/blame.c +38 -18
  157. data/vendor/libgit2/src/blame.h +1 -1
  158. data/vendor/libgit2/src/blame_git.c +29 -15
  159. data/vendor/libgit2/src/blob.c +123 -37
  160. data/vendor/libgit2/src/blob.h +19 -2
  161. data/vendor/libgit2/src/branch.c +47 -23
  162. data/vendor/libgit2/src/buf_text.c +7 -6
  163. data/vendor/libgit2/src/buffer.c +60 -53
  164. data/vendor/libgit2/src/cache.c +38 -45
  165. data/vendor/libgit2/src/cache.h +3 -3
  166. data/vendor/libgit2/src/cc-compat.h +20 -3
  167. data/vendor/libgit2/src/checkout.c +77 -67
  168. data/vendor/libgit2/src/cherrypick.c +12 -6
  169. data/vendor/libgit2/src/clone.c +36 -14
  170. data/vendor/libgit2/src/clone.h +4 -0
  171. data/vendor/libgit2/src/commit.c +103 -48
  172. data/vendor/libgit2/src/commit.h +7 -0
  173. data/vendor/libgit2/src/commit_list.c +36 -78
  174. data/vendor/libgit2/src/commit_list.h +2 -2
  175. data/vendor/libgit2/src/common.h +24 -90
  176. data/vendor/libgit2/src/config.c +203 -176
  177. data/vendor/libgit2/src/config.h +8 -20
  178. data/vendor/libgit2/src/config_backend.h +96 -0
  179. data/vendor/libgit2/src/config_cache.c +41 -35
  180. data/vendor/libgit2/src/config_entries.c +229 -0
  181. data/vendor/libgit2/src/config_entries.h +24 -0
  182. data/vendor/libgit2/src/config_file.c +422 -680
  183. data/vendor/libgit2/src/config_mem.c +220 -0
  184. data/vendor/libgit2/src/config_parse.c +96 -68
  185. data/vendor/libgit2/src/config_parse.h +15 -14
  186. data/vendor/libgit2/src/config_snapshot.c +206 -0
  187. data/vendor/libgit2/src/crlf.c +219 -196
  188. data/vendor/libgit2/src/delta.c +25 -18
  189. data/vendor/libgit2/src/describe.c +42 -41
  190. data/vendor/libgit2/src/diff.c +52 -67
  191. data/vendor/libgit2/src/diff.h +2 -1
  192. data/vendor/libgit2/src/diff_driver.c +44 -46
  193. data/vendor/libgit2/src/diff_file.c +16 -14
  194. data/vendor/libgit2/src/diff_file.h +1 -1
  195. data/vendor/libgit2/src/diff_generate.c +158 -103
  196. data/vendor/libgit2/src/diff_generate.h +3 -3
  197. data/vendor/libgit2/src/diff_parse.c +4 -4
  198. data/vendor/libgit2/src/diff_print.c +34 -22
  199. data/vendor/libgit2/src/diff_stats.c +22 -7
  200. data/vendor/libgit2/src/diff_tform.c +18 -16
  201. data/vendor/libgit2/src/diff_xdiff.c +3 -3
  202. data/vendor/libgit2/src/errors.c +51 -39
  203. data/vendor/libgit2/src/errors.h +81 -0
  204. data/vendor/libgit2/src/features.h.in +9 -3
  205. data/vendor/libgit2/src/fetch.c +8 -3
  206. data/vendor/libgit2/src/fetchhead.c +12 -12
  207. data/vendor/libgit2/src/filebuf.c +28 -32
  208. data/vendor/libgit2/src/filebuf.h +2 -2
  209. data/vendor/libgit2/src/filter.c +47 -33
  210. data/vendor/libgit2/src/filter.h +0 -10
  211. data/vendor/libgit2/src/{fileops.c → futils.c} +70 -63
  212. data/vendor/libgit2/src/{fileops.h → futils.h} +6 -6
  213. data/vendor/libgit2/src/global.c +35 -55
  214. data/vendor/libgit2/src/global.h +0 -2
  215. data/vendor/libgit2/src/hash/sha1/collisiondetect.c +48 -0
  216. data/vendor/libgit2/src/hash/sha1/collisiondetect.h +19 -0
  217. data/vendor/libgit2/src/hash/{hash_common_crypto.h → sha1/common_crypto.c} +17 -17
  218. data/vendor/libgit2/src/hash/sha1/common_crypto.h +19 -0
  219. data/vendor/libgit2/src/hash/{hash_generic.c → sha1/generic.c} +22 -10
  220. data/vendor/libgit2/src/hash/{hash_generic.h → sha1/generic.h} +4 -10
  221. data/vendor/libgit2/src/hash/{hash_mbedtls.c → sha1/mbedtls.c} +15 -7
  222. data/vendor/libgit2/src/hash/{hash_mbedtls.h → sha1/mbedtls.h} +6 -7
  223. data/vendor/libgit2/src/hash/sha1/openssl.c +59 -0
  224. data/vendor/libgit2/src/hash/sha1/openssl.h +19 -0
  225. data/vendor/libgit2/src/hash/{sha1dc → sha1/sha1dc}/sha1.c +14 -3
  226. data/vendor/libgit2/src/hash/{hash_win32.c → sha1/win32.c} +47 -37
  227. data/vendor/libgit2/src/hash/{hash_win32.h → sha1/win32.h} +6 -19
  228. data/vendor/libgit2/src/hash/sha1.h +38 -0
  229. data/vendor/libgit2/src/hash.c +61 -0
  230. data/vendor/libgit2/src/hash.h +20 -21
  231. data/vendor/libgit2/src/hashsig.c +5 -5
  232. data/vendor/libgit2/src/idxmap.c +107 -61
  233. data/vendor/libgit2/src/idxmap.h +153 -31
  234. data/vendor/libgit2/src/ignore.c +38 -42
  235. data/vendor/libgit2/src/index.c +264 -199
  236. data/vendor/libgit2/src/index.h +7 -1
  237. data/vendor/libgit2/src/indexer.c +338 -167
  238. data/vendor/libgit2/src/integer.h +71 -26
  239. data/vendor/libgit2/src/iterator.c +134 -62
  240. data/vendor/libgit2/src/iterator.h +15 -0
  241. data/vendor/libgit2/src/mailmap.c +8 -8
  242. data/vendor/libgit2/src/map.h +1 -1
  243. data/vendor/libgit2/src/merge.c +137 -93
  244. data/vendor/libgit2/src/merge_driver.c +11 -11
  245. data/vendor/libgit2/src/merge_file.c +2 -2
  246. data/vendor/libgit2/src/mwindow.c +24 -29
  247. data/vendor/libgit2/src/mwindow.h +4 -4
  248. data/vendor/libgit2/src/net.c +184 -0
  249. data/vendor/libgit2/src/net.h +36 -0
  250. data/vendor/libgit2/src/netops.c +55 -156
  251. data/vendor/libgit2/src/netops.h +3 -23
  252. data/vendor/libgit2/src/notes.c +14 -9
  253. data/vendor/libgit2/src/object.c +120 -69
  254. data/vendor/libgit2/src/object.h +22 -9
  255. data/vendor/libgit2/src/object_api.c +8 -8
  256. data/vendor/libgit2/src/odb.c +111 -88
  257. data/vendor/libgit2/src/odb.h +8 -7
  258. data/vendor/libgit2/src/odb_loose.c +58 -47
  259. data/vendor/libgit2/src/odb_mempack.c +21 -34
  260. data/vendor/libgit2/src/odb_pack.c +17 -13
  261. data/vendor/libgit2/src/offmap.c +53 -35
  262. data/vendor/libgit2/src/offmap.h +108 -21
  263. data/vendor/libgit2/src/oid.c +12 -7
  264. data/vendor/libgit2/src/oidmap.c +49 -47
  265. data/vendor/libgit2/src/oidmap.h +101 -24
  266. data/vendor/libgit2/src/pack-objects.c +87 -86
  267. data/vendor/libgit2/src/pack-objects.h +2 -8
  268. data/vendor/libgit2/src/pack.c +94 -96
  269. data/vendor/libgit2/src/pack.h +16 -18
  270. data/vendor/libgit2/src/parse.c +17 -4
  271. data/vendor/libgit2/src/parse.h +3 -3
  272. data/vendor/libgit2/src/patch.c +3 -3
  273. data/vendor/libgit2/src/patch_generate.c +18 -18
  274. data/vendor/libgit2/src/patch_parse.c +147 -79
  275. data/vendor/libgit2/src/path.c +207 -62
  276. data/vendor/libgit2/src/path.h +14 -0
  277. data/vendor/libgit2/src/pathspec.c +18 -18
  278. data/vendor/libgit2/src/pool.c +26 -22
  279. data/vendor/libgit2/src/pool.h +7 -7
  280. data/vendor/libgit2/src/posix.c +10 -10
  281. data/vendor/libgit2/src/posix.h +12 -1
  282. data/vendor/libgit2/src/proxy.c +8 -3
  283. data/vendor/libgit2/src/push.c +35 -29
  284. data/vendor/libgit2/src/push.h +2 -1
  285. data/vendor/libgit2/src/reader.c +265 -0
  286. data/vendor/libgit2/src/reader.h +107 -0
  287. data/vendor/libgit2/src/rebase.c +97 -38
  288. data/vendor/libgit2/src/refdb.c +15 -3
  289. data/vendor/libgit2/src/refdb_fs.c +318 -222
  290. data/vendor/libgit2/src/reflog.c +13 -15
  291. data/vendor/libgit2/src/refs.c +122 -89
  292. data/vendor/libgit2/src/refs.h +5 -3
  293. data/vendor/libgit2/src/refspec.c +27 -33
  294. data/vendor/libgit2/src/regexp.c +221 -0
  295. data/vendor/libgit2/src/regexp.h +97 -0
  296. data/vendor/libgit2/src/remote.c +229 -178
  297. data/vendor/libgit2/src/remote.h +11 -2
  298. data/vendor/libgit2/src/repository.c +227 -172
  299. data/vendor/libgit2/src/repository.h +52 -40
  300. data/vendor/libgit2/src/reset.c +7 -7
  301. data/vendor/libgit2/src/revert.c +11 -6
  302. data/vendor/libgit2/src/revparse.c +46 -46
  303. data/vendor/libgit2/src/revwalk.c +89 -54
  304. data/vendor/libgit2/src/revwalk.h +20 -0
  305. data/vendor/libgit2/src/settings.c +22 -9
  306. data/vendor/libgit2/src/signature.c +15 -13
  307. data/vendor/libgit2/src/sortedcache.c +22 -36
  308. data/vendor/libgit2/src/sortedcache.h +1 -1
  309. data/vendor/libgit2/src/stash.c +56 -76
  310. data/vendor/libgit2/src/status.c +27 -21
  311. data/vendor/libgit2/src/stream.h +17 -2
  312. data/vendor/libgit2/src/streams/mbedtls.c +100 -80
  313. data/vendor/libgit2/src/streams/mbedtls.h +5 -2
  314. data/vendor/libgit2/src/streams/openssl.c +93 -81
  315. data/vendor/libgit2/src/streams/openssl.h +5 -2
  316. data/vendor/libgit2/src/streams/registry.c +118 -0
  317. data/vendor/libgit2/src/streams/registry.h +19 -0
  318. data/vendor/libgit2/src/streams/socket.c +55 -30
  319. data/vendor/libgit2/src/streams/stransport.c +57 -32
  320. data/vendor/libgit2/src/streams/stransport.h +5 -0
  321. data/vendor/libgit2/src/streams/tls.c +48 -20
  322. data/vendor/libgit2/src/streams/tls.h +12 -4
  323. data/vendor/libgit2/src/strmap.c +47 -74
  324. data/vendor/libgit2/src/strmap.h +108 -33
  325. data/vendor/libgit2/src/submodule.c +190 -169
  326. data/vendor/libgit2/src/submodule.h +1 -1
  327. data/vendor/libgit2/src/sysdir.c +25 -15
  328. data/vendor/libgit2/src/tag.c +39 -26
  329. data/vendor/libgit2/src/tag.h +2 -1
  330. data/vendor/libgit2/src/trace.c +2 -2
  331. data/vendor/libgit2/src/trace.h +2 -2
  332. data/vendor/libgit2/src/trailer.c +46 -32
  333. data/vendor/libgit2/src/transaction.c +30 -29
  334. data/vendor/libgit2/src/transport.c +3 -3
  335. data/vendor/libgit2/src/transports/auth.c +14 -10
  336. data/vendor/libgit2/src/transports/auth.h +10 -3
  337. data/vendor/libgit2/src/transports/auth_negotiate.c +31 -16
  338. data/vendor/libgit2/src/transports/auth_negotiate.h +2 -2
  339. data/vendor/libgit2/src/transports/auth_ntlm.c +223 -0
  340. data/vendor/libgit2/src/transports/auth_ntlm.h +35 -0
  341. data/vendor/libgit2/src/transports/cred.c +24 -24
  342. data/vendor/libgit2/src/transports/git.c +25 -30
  343. data/vendor/libgit2/src/transports/http.c +871 -335
  344. data/vendor/libgit2/src/transports/http.h +2 -0
  345. data/vendor/libgit2/src/transports/local.c +28 -28
  346. data/vendor/libgit2/src/transports/smart.c +64 -46
  347. data/vendor/libgit2/src/transports/smart.h +5 -6
  348. data/vendor/libgit2/src/transports/smart_pkt.c +162 -151
  349. data/vendor/libgit2/src/transports/smart_protocol.c +64 -94
  350. data/vendor/libgit2/src/transports/ssh.c +76 -65
  351. data/vendor/libgit2/src/transports/winhttp.c +328 -319
  352. data/vendor/libgit2/src/tree-cache.c +21 -14
  353. data/vendor/libgit2/src/tree.c +119 -112
  354. data/vendor/libgit2/src/tree.h +1 -0
  355. data/vendor/libgit2/src/unix/map.c +3 -3
  356. data/vendor/libgit2/src/unix/posix.h +1 -11
  357. data/vendor/libgit2/src/userdiff.h +3 -1
  358. data/vendor/libgit2/src/util.c +154 -93
  359. data/vendor/libgit2/src/util.h +19 -23
  360. data/vendor/libgit2/src/vector.c +15 -10
  361. data/vendor/libgit2/src/wildmatch.c +320 -0
  362. data/vendor/libgit2/src/wildmatch.h +23 -0
  363. data/vendor/libgit2/src/win32/dir.c +3 -3
  364. data/vendor/libgit2/src/win32/findfile.c +1 -1
  365. data/vendor/libgit2/src/win32/map.c +9 -11
  366. data/vendor/libgit2/src/win32/msvc-compat.h +6 -0
  367. data/vendor/libgit2/src/win32/path_w32.c +113 -9
  368. data/vendor/libgit2/src/win32/path_w32.h +18 -29
  369. data/vendor/libgit2/src/win32/posix.h +1 -4
  370. data/vendor/libgit2/src/win32/posix_w32.c +69 -44
  371. data/vendor/libgit2/src/win32/precompiled.h +0 -2
  372. data/vendor/libgit2/src/win32/thread.c +5 -10
  373. data/vendor/libgit2/src/win32/w32_buffer.c +9 -5
  374. data/vendor/libgit2/src/win32/w32_common.h +39 -0
  375. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.c +2 -95
  376. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.h +0 -2
  377. data/vendor/libgit2/src/win32/w32_stack.c +6 -11
  378. data/vendor/libgit2/src/win32/w32_stack.h +3 -3
  379. data/vendor/libgit2/src/win32/w32_util.c +27 -64
  380. data/vendor/libgit2/src/win32/w32_util.h +5 -49
  381. data/vendor/libgit2/src/worktree.c +44 -30
  382. data/vendor/libgit2/src/xdiff/xdiffi.c +5 -5
  383. data/vendor/libgit2/src/xdiff/xhistogram.c +1 -1
  384. data/vendor/libgit2/src/xdiff/xmerge.c +27 -15
  385. data/vendor/libgit2/src/xdiff/xpatience.c +3 -0
  386. data/vendor/libgit2/src/zstream.c +4 -4
  387. metadata +115 -38
  388. data/vendor/libgit2/deps/regex/CMakeLists.txt +0 -2
  389. data/vendor/libgit2/deps/regex/config.h +0 -7
  390. data/vendor/libgit2/deps/regex/regcomp.c +0 -3857
  391. data/vendor/libgit2/deps/regex/regex.c +0 -92
  392. data/vendor/libgit2/deps/regex/regex.h +0 -582
  393. data/vendor/libgit2/deps/regex/regex_internal.c +0 -1744
  394. data/vendor/libgit2/deps/regex/regex_internal.h +0 -819
  395. data/vendor/libgit2/deps/regex/regexec.c +0 -4369
  396. data/vendor/libgit2/include/git2/inttypes.h +0 -309
  397. data/vendor/libgit2/include/git2/sys/time.h +0 -31
  398. data/vendor/libgit2/libgit2.pc.in +0 -13
  399. data/vendor/libgit2/src/config_file.h +0 -73
  400. data/vendor/libgit2/src/fnmatch.c +0 -248
  401. data/vendor/libgit2/src/fnmatch.h +0 -48
  402. data/vendor/libgit2/src/hash/hash_collisiondetect.h +0 -47
  403. data/vendor/libgit2/src/hash/hash_openssl.h +0 -59
  404. data/vendor/libgit2/src/streams/curl.c +0 -385
  405. data/vendor/libgit2/src/streams/curl.h +0 -17
  406. /data/vendor/libgit2/deps/http-parser/{LICENSE-MIT → COPYING} +0 -0
  407. /data/vendor/libgit2/src/hash/{sha1dc → sha1/sha1dc}/sha1.h +0 -0
  408. /data/vendor/libgit2/src/hash/{sha1dc → sha1/sha1dc}/ubc_check.c +0 -0
  409. /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 *io;
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 parse_finished : 1;
90
-
91
- /* Authentication */
92
- git_cred *cred;
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 bool credtype_match(git_http_auth_scheme *scheme, void *data)
108
- {
109
- unsigned int credtype = *(unsigned int *)data;
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
- if (scheme_match(&auth_schemes[i], data)) {
139
- scheme = &auth_schemes[i];
140
- break;
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
- if (!scheme)
145
- return 0;
145
+ scheme_len = strlen(scheme_name);
146
146
 
147
- /* See if authentication has already started for this scheme */
148
- git_vector_foreach(&t->auth_contexts, i, c) {
149
- if (c->type == scheme->type) {
150
- context = c;
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
- if (!context) {
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(git_buf *buf, http_subtransport *t)
158
+ static int apply_credentials(
159
+ git_buf *buf,
160
+ http_server *server,
161
+ const char *header_name)
170
162
  {
171
- git_cred *cred = t->cred;
172
- git_http_auth_context *context;
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
- cred = t->url_cred;
182
- }
166
+ if (!server->auth_context)
167
+ goto done;
183
168
 
184
- if (!cred)
185
- return 0;
169
+ if ((error = server->auth_context->next_token(&token, server->auth_context, server->cred)) < 0)
170
+ goto done;
186
171
 
187
- /* Get or create a context for the best scheme for this cred type */
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
- return context->next_token(buf, context, cred);
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->connection_data.path ? t->connection_data.path : "/";
185
+ const char *path = t->server.url.path ? t->server.url.path : "/";
201
186
  size_t i;
202
187
 
203
- git_buf_printf(buf, "%s %s%s HTTP/1.1\r\n", s->verb, path, s->service_url);
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\r\n", t->connection_data.host);
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 (apply_credentials(buf, t) < 0)
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 parse_authenticate_response(
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
- git_http_auth_context *context;
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(www_authenticate, i, challenge) {
248
- if (auth_context_match(&context, t, challenge_match, challenge) < 0)
249
- return -1;
250
- else if (!context)
251
- continue;
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
- if (context->set_challenge &&
254
- context->set_challenge(context, challenge) < 0)
255
- return -1;
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
- *allowed_types |= context->credtypes;
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
- return 0;
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 (!t->content_type) {
270
- t->content_type = git__strdup(git_buf_cstr(value));
271
- GITERR_CHECK_ALLOC(t->content_type);
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
- GITERR_CHECK_ALLOC(dup);
355
+ GIT_ERROR_CHECK_ALLOC(dup);
277
356
 
278
- git_vector_insert(&t->www_authenticate, dup);
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 (!t->location) {
282
- t->location = git__strdup(git_buf_cstr(value));
283
- GITERR_CHECK_ALLOC(t->location);
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 (VALUE == t->last_cb)
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 an authentication failure. */
351
- if (parser->status_code == 401 && get_verb == s->verb) {
352
- if (!t->owner->cred_acquire_cb) {
353
- no_callback = 1;
354
- } else {
355
- if (allowed_auth_types) {
356
- if (t->cred) {
357
- t->cred->free(t->cred);
358
- t->cred = NULL;
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
- if (no_callback) {
388
- giterr_set(GITERR_NET, "authentication required but no callback set");
389
- return t->parse_error = PARSE_ERROR_GENERIC;
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->redirect_count >= 7) {
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
- giterr_set(GITERR_NET,
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
- giterr_set(GITERR_NET, "no Content-Type header in response");
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
- giterr_set(GITERR_NET,
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 our goal is to replay the request (either an auth failure or
480
- * a redirect) then don't bother buffering since we're ignoring the
481
- * content anyway.
482
- */
483
- if (t->parse_error == PARSE_ERROR_REPLAY)
484
- return 0;
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
- if (ctx->buf_size < len) {
487
- giterr_set(GITERR_NET, "can't fit data in the buffer");
488
- return t->parse_error = PARSE_ERROR_GENERIC;
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->io,
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->www_authenticate);
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 (git_stream_write(io, buf.ptr, buf.size, 0) < 0) {
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 && git_stream_write(io, buffer, len, 0) < 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 (git_stream_write(io, "\r\n", 2, 0) < 0)
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 apply_proxy_config(http_subtransport *t)
757
+ static int load_proxy_config(http_subtransport *t)
555
758
  {
556
759
  int error;
557
- git_proxy_t proxy_type;
558
760
 
559
- if (!git_stream_supports_proxy(t->io))
761
+ switch (t->owner->proxy.type) {
762
+ case GIT_PROXY_NONE:
560
763
  return 0;
561
764
 
562
- proxy_type = t->owner->proxy.type;
765
+ case GIT_PROXY_AUTO:
766
+ git__free(t->proxy_url);
767
+ t->proxy_url = NULL;
563
768
 
564
- if (proxy_type == GIT_PROXY_NONE)
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, !!t->connection_data.use_ssl, &url)) < 0)
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
- opts.credentials = t->owner->proxy.credentials;
575
- opts.certificate_check = t->owner->proxy.certificate_check;
576
- opts.payload = t->owner->proxy.payload;
577
- opts.type = GIT_PROXY_SPECIFIED;
578
- opts.url = url;
579
- error = git_stream_set_proxy(t->io, &opts);
580
- git__free(url);
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
- return error;
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
- return git_stream_set_proxy(t->io, &t->owner->proxy);
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 http_connect(http_subtransport *t)
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 (t->connected &&
593
- http_should_keep_alive(&t->parser) &&
594
- t->parse_finished)
595
- return 0;
810
+ if ((error = git_stream_certificate(&cert, stream)) < 0)
811
+ return error;
596
812
 
597
- if (t->io) {
598
- git_stream_close(t->io);
599
- git_stream_free(t->io);
600
- t->io = NULL;
601
- t->connected = 0;
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
- if (t->connection_data.use_ssl) {
605
- error = git_tls_stream_new(&t->io, t->connection_data.host, t->connection_data.port);
606
- } else {
607
- #ifdef GIT_CURL
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
- if (error < 0)
615
- return error;
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
- GITERR_CHECK_VERSION(t->io, GIT_STREAM_VERSION, "git_stream");
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
- apply_proxy_config(t);
919
+ return 0;
920
+ }
620
921
 
621
- error = git_stream_connect(t->io);
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
- if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL &&
624
- git_stream_is_encrypted(t->io)) {
625
- git_cert *cert;
626
- int is_valid = (error == GIT_OK);
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
- if ((error = git_stream_certificate(&cert, t->io)) < 0)
629
- return error;
938
+ replay:
939
+ clear_parser_state(t);
630
940
 
631
- giterr_clear();
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
- if (error < 0) {
635
- if (!giterr_last())
636
- giterr_set(GITERR_NET, "user cancelled certificate check");
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
- return error;
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
- if (error < 0)
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
- git_buf request = GIT_BUF_INIT;
667
-
1180
+ git_buf_clear(&request);
668
1181
  clear_parser_state(t);
669
1182
 
670
- if (gen_request(&request, s, 0) < 0)
671
- return -1;
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->io, s->chunk_buffer, s->chunk_buffer_len) < 0)
690
- return -1;
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
- s->chunk_buffer_len = 0;
1199
+ s->chunk_buffer_len = 0;
1200
+ }
693
1201
 
694
1202
  /* Write the final chunk. */
695
- if (git_stream_write(t->io, "0\r\n\r\n", 5, 0) < 0)
696
- return -1;
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
- } else {
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
- return -1;
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
- /* This call to http_parser_execute will result in invocations of the
726
- * on_* family of callbacks. The most interesting of these is
727
- * on_body_fill_buffer, which is called when data is ready to be copied
728
- * into the target buffer. We need to marshal the buffer, buf_size, and
729
- * bytes_read parameters to this callback. */
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
- /* If there was a handled authentication failure, then parse_error
747
- * will have signaled us that we should replay the request. */
748
- if (PARSE_ERROR_REPLAY == t->parse_error) {
749
- s->sent_request = 0;
750
-
751
- if ((error = http_connect(t)) < 0)
752
- return error;
753
-
754
- goto replay;
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
- giterr_set(GITERR_NET,
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
- return -1;
1280
+ error = -1;
1281
+ goto done;
769
1282
  }
770
1283
  }
771
1284
 
772
- return 0;
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 *)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 (git_stream_write(t->io, request.ptr, request.size, 0) < 0) {
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->io, s->chunk_buffer, s->chunk_buffer_len) < 0)
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->io, buffer, len) < 0)
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->io, s->chunk_buffer, s->chunk_buffer_len) < 0)
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 *)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
- giterr_set(GITERR_NET, "subtransport configured for only one write");
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 (git_stream_write(t->io, request.ptr, request.size, 0) < 0)
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 && git_stream_write(t->io, buffer, len, 0) < 0)
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 *)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
- GITERR_CHECK_ALLOC(s);
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 *)subtransport;
1529
+ http_subtransport *t = GIT_CONTAINER_OF(subtransport, http_subtransport, parent);
999
1530
  int ret;
1000
1531
 
1001
- if (!stream)
1002
- return -1;
1532
+ assert(stream);
1003
1533
 
1004
- if ((!t->connection_data.host || !t->connection_data.port || !t->connection_data.path) &&
1005
- (ret = gitno_connection_data_from_url(&t->connection_data, url, NULL)) < 0)
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 *) 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->io) {
1040
- git_stream_close(t->io);
1041
- git_stream_free(t->io);
1042
- t->io = NULL;
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->cred) {
1046
- t->cred->free(t->cred);
1047
- t->cred = NULL;
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
- if (t->url_cred) {
1051
- t->url_cred->free(t->url_cred);
1052
- t->url_cred = NULL;
1053
- }
1588
+ free_cred(&t->server.cred);
1589
+ free_cred(&t->proxy.cred);
1054
1590
 
1055
- git_vector_foreach(&t->auth_contexts, i, context) {
1056
- if (context->free)
1057
- context->free(context);
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
- git_vector_clear(&t->auth_contexts);
1597
+ git_net_url_dispose(&t->server.url);
1598
+ git_net_url_dispose(&t->proxy.url);
1061
1599
 
1062
- gitno_connection_data_free_ptrs(&t->connection_data);
1063
- memset(&t->connection_data, 0x0, sizeof(gitno_connection_data));
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 *) 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
- GITERR_CHECK_ALLOC(t);
1624
+ GIT_ERROR_CHECK_ALLOC(t);
1089
1625
 
1090
1626
  t->owner = (transport_smart *)owner;
1091
1627
  t->parent.action = http_action;