rugged 0.21.4 → 0.22.0b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (224) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -5
  3. data/ext/rugged/extconf.rb +9 -9
  4. data/ext/rugged/rugged.c +4 -2
  5. data/ext/rugged/rugged.h +3 -7
  6. data/ext/rugged/rugged_blob.c +57 -0
  7. data/ext/rugged/rugged_cred.c +23 -0
  8. data/ext/rugged/rugged_index.c +6 -2
  9. data/ext/rugged/rugged_remote.c +65 -52
  10. data/ext/rugged/rugged_remote_collection.c +59 -10
  11. data/ext/rugged/rugged_repo.c +345 -11
  12. data/ext/rugged/rugged_revwalk.c +10 -0
  13. data/ext/rugged/rugged_submodule.c +1042 -0
  14. data/ext/rugged/rugged_submodule_collection.c +236 -0
  15. data/ext/rugged/rugged_tag_collection.c +70 -2
  16. data/ext/rugged/rugged_tree.c +29 -10
  17. data/lib/rugged.rb +3 -0
  18. data/lib/rugged/attributes.rb +41 -0
  19. data/lib/rugged/blob.rb +28 -0
  20. data/lib/rugged/diff.rb +0 -1
  21. data/lib/rugged/diff/line.rb +1 -3
  22. data/lib/rugged/patch.rb +12 -2
  23. data/lib/rugged/repository.rb +7 -0
  24. data/lib/rugged/submodule_collection.rb +48 -0
  25. data/lib/rugged/version.rb +1 -1
  26. data/vendor/libgit2/CMakeLists.txt +27 -3
  27. data/vendor/libgit2/cmake/Modules/FindGSSAPI.cmake +324 -0
  28. data/vendor/libgit2/deps/http-parser/http_parser.h +2 -0
  29. data/vendor/libgit2/deps/zlib/adler32.c +39 -29
  30. data/vendor/libgit2/deps/zlib/crc32.c +33 -50
  31. data/vendor/libgit2/deps/zlib/crc32.h +1 -1
  32. data/vendor/libgit2/deps/zlib/deflate.c +198 -65
  33. data/vendor/libgit2/deps/zlib/deflate.h +8 -4
  34. data/vendor/libgit2/deps/zlib/infback.c +640 -0
  35. data/vendor/libgit2/deps/zlib/inffast.c +3 -3
  36. data/vendor/libgit2/deps/zlib/inffixed.h +3 -3
  37. data/vendor/libgit2/deps/zlib/inflate.c +84 -52
  38. data/vendor/libgit2/deps/zlib/inftrees.c +15 -39
  39. data/vendor/libgit2/deps/zlib/trees.c +18 -36
  40. data/vendor/libgit2/deps/zlib/zconf.h +4 -0
  41. data/vendor/libgit2/deps/zlib/zlib.h +250 -95
  42. data/vendor/libgit2/deps/zlib/zutil.c +13 -10
  43. data/vendor/libgit2/deps/zlib/zutil.h +41 -62
  44. data/vendor/libgit2/include/git2.h +4 -0
  45. data/vendor/libgit2/include/git2/annotated_commit.h +99 -0
  46. data/vendor/libgit2/include/git2/attr.h +16 -13
  47. data/vendor/libgit2/include/git2/branch.h +11 -0
  48. data/vendor/libgit2/include/git2/buffer.h +16 -0
  49. data/vendor/libgit2/include/git2/checkout.h +12 -12
  50. data/vendor/libgit2/include/git2/cherrypick.h +15 -15
  51. data/vendor/libgit2/include/git2/clone.h +77 -69
  52. data/vendor/libgit2/include/git2/common.h +13 -1
  53. data/vendor/libgit2/include/git2/config.h +0 -14
  54. data/vendor/libgit2/include/git2/describe.h +162 -0
  55. data/vendor/libgit2/include/git2/diff.h +13 -8
  56. data/vendor/libgit2/include/git2/errors.h +5 -0
  57. data/vendor/libgit2/include/git2/global.h +38 -0
  58. data/vendor/libgit2/include/git2/merge.h +38 -64
  59. data/vendor/libgit2/include/git2/net.h +2 -2
  60. data/vendor/libgit2/include/git2/notes.h +17 -0
  61. data/vendor/libgit2/include/git2/oid.h +8 -4
  62. data/vendor/libgit2/include/git2/oidarray.h +40 -0
  63. data/vendor/libgit2/include/git2/rebase.h +261 -0
  64. data/vendor/libgit2/include/git2/reflog.h +1 -1
  65. data/vendor/libgit2/include/git2/remote.h +25 -47
  66. data/vendor/libgit2/include/git2/repository.h +4 -1
  67. data/vendor/libgit2/include/git2/reset.h +10 -1
  68. data/vendor/libgit2/include/git2/revert.h +1 -1
  69. data/vendor/libgit2/include/git2/revwalk.h +28 -23
  70. data/vendor/libgit2/include/git2/status.h +19 -15
  71. data/vendor/libgit2/include/git2/submodule.h +18 -0
  72. data/vendor/libgit2/include/git2/sys/config.h +0 -1
  73. data/vendor/libgit2/{src → include/git2/sys}/hashsig.h +11 -7
  74. data/vendor/libgit2/include/git2/sys/refdb_backend.h +13 -0
  75. data/vendor/libgit2/include/git2/sys/refs.h +0 -11
  76. data/vendor/libgit2/include/git2/sys/repository.h +13 -0
  77. data/vendor/libgit2/include/git2/sys/transport.h +352 -0
  78. data/vendor/libgit2/include/git2/threads.h +10 -20
  79. data/vendor/libgit2/include/git2/transaction.h +111 -0
  80. data/vendor/libgit2/include/git2/transport.h +79 -313
  81. data/vendor/libgit2/include/git2/tree.h +4 -2
  82. data/vendor/libgit2/include/git2/types.h +77 -8
  83. data/vendor/libgit2/include/git2/version.h +2 -2
  84. data/vendor/libgit2/src/annotated_commit.c +121 -0
  85. data/vendor/libgit2/src/annotated_commit.h +22 -0
  86. data/vendor/libgit2/src/attr.c +8 -4
  87. data/vendor/libgit2/src/attr_file.c +24 -2
  88. data/vendor/libgit2/src/blame.c +0 -1
  89. data/vendor/libgit2/src/branch.c +32 -3
  90. data/vendor/libgit2/src/buf_text.c +9 -5
  91. data/vendor/libgit2/src/buf_text.h +3 -2
  92. data/vendor/libgit2/src/buffer.c +67 -10
  93. data/vendor/libgit2/src/buffer.h +4 -2
  94. data/vendor/libgit2/src/cache.c +9 -9
  95. data/vendor/libgit2/src/cache.h +1 -1
  96. data/vendor/libgit2/src/cc-compat.h +2 -0
  97. data/vendor/libgit2/src/checkout.c +263 -82
  98. data/vendor/libgit2/src/checkout.h +1 -0
  99. data/vendor/libgit2/src/cherrypick.c +41 -44
  100. data/vendor/libgit2/src/clone.c +96 -58
  101. data/vendor/libgit2/src/commit.c +5 -31
  102. data/vendor/libgit2/src/commit_list.h +3 -1
  103. data/vendor/libgit2/src/config.c +0 -17
  104. data/vendor/libgit2/src/config_cache.c +0 -2
  105. data/vendor/libgit2/src/config_file.c +12 -15
  106. data/vendor/libgit2/src/crlf.c +2 -1
  107. data/vendor/libgit2/src/describe.c +886 -0
  108. data/vendor/libgit2/src/diff.c +29 -3
  109. data/vendor/libgit2/src/diff_file.c +1 -0
  110. data/vendor/libgit2/src/diff_patch.c +2 -3
  111. data/vendor/libgit2/src/diff_print.c +11 -9
  112. data/vendor/libgit2/src/diff_tform.c +4 -4
  113. data/vendor/libgit2/src/errors.c +9 -7
  114. data/vendor/libgit2/src/fetch.c +6 -6
  115. data/vendor/libgit2/src/fetchhead.h +2 -4
  116. data/vendor/libgit2/src/filebuf.c +0 -2
  117. data/vendor/libgit2/src/filebuf.h +2 -3
  118. data/vendor/libgit2/src/fileops.c +9 -7
  119. data/vendor/libgit2/src/global.c +44 -35
  120. data/vendor/libgit2/src/global.h +2 -0
  121. data/vendor/libgit2/src/graph.c +2 -2
  122. data/vendor/libgit2/src/hash.h +3 -1
  123. data/vendor/libgit2/src/hash/hash_common_crypto.h +44 -0
  124. data/vendor/libgit2/src/hash/hash_win32.c +1 -1
  125. data/vendor/libgit2/src/hashsig.c +1 -1
  126. data/vendor/libgit2/src/ignore.c +5 -88
  127. data/vendor/libgit2/src/index.c +70 -57
  128. data/vendor/libgit2/src/index.h +1 -0
  129. data/vendor/libgit2/src/indexer.c +16 -5
  130. data/vendor/libgit2/src/iterator.c +70 -1
  131. data/vendor/libgit2/src/iterator.h +5 -1
  132. data/vendor/libgit2/src/map.h +0 -1
  133. data/vendor/libgit2/src/merge.c +203 -327
  134. data/vendor/libgit2/src/merge.h +3 -13
  135. data/vendor/libgit2/src/mwindow.c +119 -8
  136. data/vendor/libgit2/src/mwindow.h +9 -1
  137. data/vendor/libgit2/src/netops.c +7 -8
  138. data/vendor/libgit2/src/netops.h +6 -16
  139. data/vendor/libgit2/src/notes.c +31 -4
  140. data/vendor/libgit2/src/notes.h +3 -0
  141. data/vendor/libgit2/src/odb.c +23 -1
  142. data/vendor/libgit2/src/odb_loose.c +1 -1
  143. data/vendor/libgit2/src/odb_pack.c +6 -3
  144. data/vendor/libgit2/src/oid.c +9 -1
  145. data/vendor/libgit2/src/oid.h +11 -0
  146. data/vendor/libgit2/src/oidarray.c +21 -0
  147. data/vendor/libgit2/src/oidarray.h +18 -0
  148. data/vendor/libgit2/src/oidmap.h +16 -0
  149. data/vendor/libgit2/src/pack.c +20 -7
  150. data/vendor/libgit2/src/pack.h +3 -0
  151. data/vendor/libgit2/src/path.c +120 -293
  152. data/vendor/libgit2/src/path.h +21 -44
  153. data/vendor/libgit2/src/pathspec.c +1 -1
  154. data/vendor/libgit2/src/pool.c +5 -11
  155. data/vendor/libgit2/src/pool.h +0 -2
  156. data/vendor/libgit2/src/posix.c +6 -6
  157. data/vendor/libgit2/src/posix.h +48 -28
  158. data/vendor/libgit2/src/push.c +19 -48
  159. data/vendor/libgit2/src/push.h +2 -4
  160. data/vendor/libgit2/src/rebase.c +1125 -0
  161. data/vendor/libgit2/src/refdb.c +19 -0
  162. data/vendor/libgit2/src/refdb.h +2 -1
  163. data/vendor/libgit2/src/refdb_fs.c +101 -29
  164. data/vendor/libgit2/src/reflog.c +1 -1
  165. data/vendor/libgit2/src/refs.c +38 -3
  166. data/vendor/libgit2/src/refs.h +13 -2
  167. data/vendor/libgit2/src/refspec.c +20 -2
  168. data/vendor/libgit2/src/remote.c +288 -154
  169. data/vendor/libgit2/src/remote.h +5 -1
  170. data/vendor/libgit2/src/repository.c +75 -36
  171. data/vendor/libgit2/src/repository.h +3 -25
  172. data/vendor/libgit2/src/reset.c +5 -1
  173. data/vendor/libgit2/src/revert.c +4 -6
  174. data/vendor/libgit2/src/revparse.c +15 -18
  175. data/vendor/libgit2/src/revwalk.c +96 -22
  176. data/vendor/libgit2/src/revwalk.h +5 -4
  177. data/vendor/libgit2/src/settings.c +22 -0
  178. data/vendor/libgit2/src/signature.c +37 -2
  179. data/vendor/libgit2/src/signature.h +3 -0
  180. data/vendor/libgit2/src/stash.c +17 -12
  181. data/vendor/libgit2/src/status.c +13 -3
  182. data/vendor/libgit2/src/strnlen.h +2 -1
  183. data/vendor/libgit2/src/submodule.c +75 -35
  184. data/vendor/libgit2/src/thread-utils.h +4 -9
  185. data/vendor/libgit2/src/trace.h +9 -1
  186. data/vendor/libgit2/src/transaction.c +352 -0
  187. data/vendor/libgit2/src/transport.c +91 -97
  188. data/vendor/libgit2/src/transports/auth.c +71 -0
  189. data/vendor/libgit2/src/transports/auth.h +63 -0
  190. data/vendor/libgit2/src/transports/auth_negotiate.c +275 -0
  191. data/vendor/libgit2/src/transports/auth_negotiate.h +27 -0
  192. data/vendor/libgit2/src/transports/cred.c +58 -0
  193. data/vendor/libgit2/src/transports/cred.h +14 -0
  194. data/vendor/libgit2/src/transports/cred_helpers.c +3 -0
  195. data/vendor/libgit2/src/transports/git.c +1 -0
  196. data/vendor/libgit2/src/transports/http.c +208 -82
  197. data/vendor/libgit2/src/transports/local.c +2 -2
  198. data/vendor/libgit2/src/transports/smart.c +2 -0
  199. data/vendor/libgit2/src/transports/smart.h +2 -0
  200. data/vendor/libgit2/src/transports/smart_protocol.c +10 -10
  201. data/vendor/libgit2/src/transports/ssh.c +243 -57
  202. data/vendor/libgit2/src/transports/winhttp.c +139 -35
  203. data/vendor/libgit2/src/tree-cache.c +118 -31
  204. data/vendor/libgit2/src/tree-cache.h +12 -7
  205. data/vendor/libgit2/src/tree.c +83 -64
  206. data/vendor/libgit2/src/tree.h +2 -3
  207. data/vendor/libgit2/src/unix/map.c +8 -2
  208. data/vendor/libgit2/src/unix/posix.h +23 -9
  209. data/vendor/libgit2/src/unix/realpath.c +8 -7
  210. data/vendor/libgit2/src/userdiff.h +3 -3
  211. data/vendor/libgit2/src/util.c +2 -92
  212. data/vendor/libgit2/src/util.h +3 -15
  213. data/vendor/libgit2/src/win32/findfile.c +0 -1
  214. data/vendor/libgit2/src/win32/map.c +3 -2
  215. data/vendor/libgit2/src/win32/mingw-compat.h +5 -12
  216. data/vendor/libgit2/src/win32/msvc-compat.h +3 -32
  217. data/vendor/libgit2/src/win32/posix.h +20 -32
  218. data/vendor/libgit2/src/win32/posix_w32.c +103 -31
  219. data/vendor/libgit2/src/win32/utf-conv.c +6 -36
  220. data/vendor/libgit2/src/win32/utf-conv.h +39 -0
  221. data/vendor/libgit2/src/win32/w32_util.h +0 -1
  222. metadata +32 -7
  223. data/vendor/libgit2/src/win32/path_w32.c +0 -305
  224. data/vendor/libgit2/src/win32/path_w32.h +0 -82
@@ -0,0 +1,14 @@
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
+ #ifndef INCLUDE_git_cred_h__
8
+ #define INCLUDE_git_cred_h__
9
+
10
+ #include "git2/transport.h"
11
+
12
+ const char *git_cred__username(git_cred *cred);
13
+
14
+ #endif
@@ -41,6 +41,9 @@ int git_cred_userpass(
41
41
  else
42
42
  return -1;
43
43
 
44
+ if (GIT_CREDTYPE_USERNAME & allowed_types)
45
+ return git_cred_username_new(cred, effective_username);
46
+
44
47
  if ((GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) == 0 ||
45
48
  git_cred_userpass_plaintext_new(cred, effective_username, userpass->password) < 0)
46
49
  return -1;
@@ -8,6 +8,7 @@
8
8
  #include "git2.h"
9
9
  #include "buffer.h"
10
10
  #include "netops.h"
11
+ #include "git2/sys/transport.h"
11
12
 
12
13
  #define OWNING_SUBTRANSPORT(s) ((git_subtransport *)(s)->parent.subtransport)
13
14
 
@@ -11,6 +11,17 @@
11
11
  #include "buffer.h"
12
12
  #include "netops.h"
13
13
  #include "smart.h"
14
+ #include "auth.h"
15
+ #include "auth_negotiate.h"
16
+
17
+ git_http_auth_scheme auth_schemes[] = {
18
+ { GIT_AUTHTYPE_NEGOTIATE, "Negotiate", GIT_CREDTYPE_DEFAULT, git_http_auth_negotiate },
19
+ { GIT_AUTHTYPE_BASIC, "Basic", GIT_CREDTYPE_USERPASS_PLAINTEXT, git_http_auth_basic },
20
+ };
21
+
22
+ #ifdef GIT_SSL
23
+ # include <openssl/x509v3.h>
24
+ #endif
14
25
 
15
26
  static const char *upload_pack_service = "upload-pack";
16
27
  static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack";
@@ -20,7 +31,6 @@ static const char *receive_pack_ls_service_url = "/info/refs?service=git-receive
20
31
  static const char *receive_pack_service_url = "/git-receive-pack";
21
32
  static const char *get_verb = "GET";
22
33
  static const char *post_verb = "POST";
23
- static const char *basic_authtype = "Basic";
24
34
 
25
35
  #define OWNING_SUBTRANSPORT(s) ((http_subtransport *)(s)->parent.subtransport)
26
36
 
@@ -35,10 +45,6 @@ enum last_cb {
35
45
  VALUE
36
46
  };
37
47
 
38
- typedef enum {
39
- GIT_HTTP_AUTH_BASIC = 1,
40
- } http_authmechanism_t;
41
-
42
48
  typedef struct {
43
49
  git_smart_subtransport_stream parent;
44
50
  const char *service;
@@ -58,9 +64,6 @@ typedef struct {
58
64
  transport_smart *owner;
59
65
  gitno_socket socket;
60
66
  gitno_connection_data connection_data;
61
- git_cred *cred;
62
- git_cred *url_cred;
63
- http_authmechanism_t auth_mechanism;
64
67
  bool connected;
65
68
 
66
69
  /* Parser structures */
@@ -76,6 +79,11 @@ typedef struct {
76
79
  enum last_cb last_cb;
77
80
  int parse_error;
78
81
  unsigned parse_finished : 1;
82
+
83
+ /* Authentication */
84
+ git_cred *cred;
85
+ git_cred *url_cred;
86
+ git_vector auth_contexts;
79
87
  } http_subtransport;
80
88
 
81
89
  typedef struct {
@@ -88,28 +96,91 @@ typedef struct {
88
96
  size_t *bytes_read;
89
97
  } parser_context;
90
98
 
91
- static int apply_basic_credential(git_buf *buf, git_cred *cred)
99
+ static bool credtype_match(git_http_auth_scheme *scheme, void *data)
92
100
  {
93
- git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred;
94
- git_buf raw = GIT_BUF_INIT;
95
- int error = -1;
101
+ unsigned int credtype = *(unsigned int *)data;
96
102
 
97
- git_buf_printf(&raw, "%s:%s", c->username, c->password);
103
+ return !!(scheme->credtypes & credtype);
104
+ }
98
105
 
99
- if (git_buf_oom(&raw) ||
100
- git_buf_puts(buf, "Authorization: Basic ") < 0 ||
101
- git_buf_put_base64(buf, git_buf_cstr(&raw), raw.size) < 0 ||
102
- git_buf_puts(buf, "\r\n") < 0)
103
- goto on_error;
106
+ static bool challenge_match(git_http_auth_scheme *scheme, void *data)
107
+ {
108
+ const char *scheme_name = scheme->name;
109
+ const char *challenge = (const char *)data;
110
+ size_t scheme_len;
104
111
 
105
- error = 0;
112
+ scheme_len = strlen(scheme_name);
113
+ return (strncmp(challenge, scheme_name, scheme_len) == 0 &&
114
+ (challenge[scheme_len] == '\0' || challenge[scheme_len] == ' '));
115
+ }
106
116
 
107
- on_error:
108
- if (raw.size)
109
- memset(raw.ptr, 0x0, raw.size);
117
+ static int auth_context_match(
118
+ git_http_auth_context **out,
119
+ http_subtransport *t,
120
+ bool (*scheme_match)(git_http_auth_scheme *scheme, void *data),
121
+ void *data)
122
+ {
123
+ git_http_auth_scheme *scheme = NULL;
124
+ git_http_auth_context *context = NULL, *c;
125
+ size_t i;
126
+
127
+ *out = NULL;
128
+
129
+ for (i = 0; i < ARRAY_SIZE(auth_schemes); i++) {
130
+ if (scheme_match(&auth_schemes[i], data)) {
131
+ scheme = &auth_schemes[i];
132
+ break;
133
+ }
134
+ }
135
+
136
+ if (!scheme)
137
+ return 0;
110
138
 
111
- git_buf_free(&raw);
112
- return error;
139
+ /* See if authentication has already started for this scheme */
140
+ git_vector_foreach(&t->auth_contexts, i, c) {
141
+ if (c->type == scheme->type) {
142
+ context = c;
143
+ break;
144
+ }
145
+ }
146
+
147
+ if (!context) {
148
+ if (scheme->init_context(&context, &t->connection_data) < 0)
149
+ return -1;
150
+ else if (!context)
151
+ return 0;
152
+ else if (git_vector_insert(&t->auth_contexts, context) < 0)
153
+ return -1;
154
+ }
155
+
156
+ *out = context;
157
+
158
+ return 0;
159
+ }
160
+
161
+ static int apply_credentials(git_buf *buf, http_subtransport *t)
162
+ {
163
+ git_cred *cred = t->cred;
164
+ git_http_auth_context *context;
165
+
166
+ /* Apply the credentials given to us in the URL */
167
+ if (!cred && t->connection_data.user && t->connection_data.pass) {
168
+ if (!t->url_cred &&
169
+ git_cred_userpass_plaintext_new(&t->url_cred,
170
+ t->connection_data.user, t->connection_data.pass) < 0)
171
+ return -1;
172
+
173
+ cred = t->url_cred;
174
+ }
175
+
176
+ if (!cred)
177
+ return 0;
178
+
179
+ /* Get or create a context for the best scheme for this cred type */
180
+ if (auth_context_match(&context, t, credtype_match, &cred->credtype) < 0)
181
+ return -1;
182
+
183
+ return context->next_token(buf, context, cred);
113
184
  }
114
185
 
115
186
  static int gen_request(
@@ -137,19 +208,9 @@ static int gen_request(
137
208
  git_buf_puts(buf, "Accept: */*\r\n");
138
209
 
139
210
  /* Apply credentials to the request */
140
- if (t->cred && t->cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT &&
141
- t->auth_mechanism == GIT_HTTP_AUTH_BASIC &&
142
- apply_basic_credential(buf, t->cred) < 0)
211
+ if (apply_credentials(buf, t) < 0)
143
212
  return -1;
144
213
 
145
- /* Use url-parsed basic auth if username and password are both provided */
146
- if (!t->cred && t->connection_data.user && t->connection_data.pass) {
147
- if (!t->url_cred && git_cred_userpass_plaintext_new(&t->url_cred,
148
- t->connection_data.user, t->connection_data.pass) < 0)
149
- return -1;
150
- if (apply_basic_credential(buf, t->url_cred) < 0) return -1;
151
- }
152
-
153
214
  git_buf_puts(buf, "\r\n");
154
215
 
155
216
  if (git_buf_oom(buf))
@@ -158,20 +219,26 @@ static int gen_request(
158
219
  return 0;
159
220
  }
160
221
 
161
- static int parse_unauthorized_response(
222
+ static int parse_authenticate_response(
162
223
  git_vector *www_authenticate,
163
- int *allowed_types,
164
- http_authmechanism_t *auth_mechanism)
224
+ http_subtransport *t,
225
+ int *allowed_types)
165
226
  {
166
- unsigned i;
167
- char *entry;
168
-
169
- git_vector_foreach(www_authenticate, i, entry) {
170
- if (!strncmp(entry, basic_authtype, 5) &&
171
- (entry[5] == '\0' || entry[5] == ' ')) {
172
- *allowed_types |= GIT_CREDTYPE_USERPASS_PLAINTEXT;
173
- *auth_mechanism = GIT_HTTP_AUTH_BASIC;
174
- }
227
+ git_http_auth_context *context;
228
+ char *challenge;
229
+ size_t i;
230
+
231
+ git_vector_foreach(www_authenticate, i, challenge) {
232
+ if (auth_context_match(&context, t, challenge_match, challenge) < 0)
233
+ return -1;
234
+ else if (!context)
235
+ continue;
236
+
237
+ if (context->set_challenge &&
238
+ context->set_challenge(context, challenge) < 0)
239
+ return -1;
240
+
241
+ *allowed_types |= context->credtypes;
175
242
  }
176
243
 
177
244
  return 0;
@@ -248,7 +315,7 @@ static int on_headers_complete(http_parser *parser)
248
315
  http_subtransport *t = ctx->t;
249
316
  http_stream *s = ctx->s;
250
317
  git_buf buf = GIT_BUF_INIT;
251
- int error = 0, no_callback = 0;
318
+ int error = 0, no_callback = 0, allowed_auth_types = 0;
252
319
 
253
320
  /* Both parse_header_name and parse_header_value are populated
254
321
  * and ready for consumption. */
@@ -256,26 +323,26 @@ static int on_headers_complete(http_parser *parser)
256
323
  if (on_header_ready(t) < 0)
257
324
  return t->parse_error = PARSE_ERROR_GENERIC;
258
325
 
259
- /* Check for an authentication failure. */
326
+ /* Capture authentication headers which may be a 401 (authentication
327
+ * is not complete) or a 200 (simply informing us that auth *is*
328
+ * complete.)
329
+ */
330
+ if (parse_authenticate_response(&t->www_authenticate, t,
331
+ &allowed_auth_types) < 0)
332
+ return t->parse_error = PARSE_ERROR_GENERIC;
260
333
 
261
- if (parser->status_code == 401 &&
262
- get_verb == s->verb) {
334
+ /* Check for an authentication failure. */
335
+ if (parser->status_code == 401 && get_verb == s->verb) {
263
336
  if (!t->owner->cred_acquire_cb) {
264
337
  no_callback = 1;
265
338
  } else {
266
- int allowed_types = 0;
267
-
268
- if (parse_unauthorized_response(&t->www_authenticate,
269
- &allowed_types, &t->auth_mechanism) < 0)
270
- return t->parse_error = PARSE_ERROR_GENERIC;
271
-
272
- if (allowed_types &&
273
- (!t->cred || 0 == (t->cred->credtype & allowed_types))) {
339
+ if (allowed_auth_types &&
340
+ (!t->cred || 0 == (t->cred->credtype & allowed_auth_types))) {
274
341
 
275
342
  error = t->owner->cred_acquire_cb(&t->cred,
276
343
  t->owner->url,
277
344
  t->connection_data.user,
278
- allowed_types,
345
+ allowed_auth_types,
279
346
  t->owner->cred_acquire_payload);
280
347
 
281
348
  if (error == GIT_PASSTHROUGH) {
@@ -286,7 +353,8 @@ static int on_headers_complete(http_parser *parser)
286
353
  assert(t->cred);
287
354
 
288
355
  /* Successfully acquired a credential. */
289
- return t->parse_error = PARSE_ERROR_REPLAY;
356
+ t->parse_error = PARSE_ERROR_REPLAY;
357
+ return 0;
290
358
  }
291
359
  }
292
360
  }
@@ -324,7 +392,8 @@ static int on_headers_complete(http_parser *parser)
324
392
  t->connected = 0;
325
393
  s->redirect_count++;
326
394
 
327
- return t->parse_error = PARSE_ERROR_REPLAY;
395
+ t->parse_error = PARSE_ERROR_REPLAY;
396
+ return 0;
328
397
  }
329
398
 
330
399
  /* Check for a 200 HTTP status code. */
@@ -382,6 +451,13 @@ static int on_body_fill_buffer(http_parser *parser, const char *str, size_t len)
382
451
  parser_context *ctx = (parser_context *) parser->data;
383
452
  http_subtransport *t = ctx->t;
384
453
 
454
+ /* If our goal is to replay the request (either an auth failure or
455
+ * a redirect) then don't bother buffering since we're ignoring the
456
+ * content anyway.
457
+ */
458
+ if (t->parse_error == PARSE_ERROR_REPLAY)
459
+ return 0;
460
+
385
461
  if (ctx->buf_size < len) {
386
462
  giterr_set(GITERR_NET, "Can't fit data in the buffer");
387
463
  return t->parse_error = PARSE_ERROR_GENERIC;
@@ -452,11 +528,11 @@ static int write_chunk(gitno_socket *socket, const char *buffer, size_t len)
452
528
 
453
529
  static int http_connect(http_subtransport *t)
454
530
  {
455
- int flags = 0;
531
+ int flags = 0, error;
456
532
 
457
533
  if (t->connected &&
458
534
  http_should_keep_alive(&t->parser) &&
459
- http_body_is_final(&t->parser))
535
+ t->parse_finished)
460
536
  return 0;
461
537
 
462
538
  if (t->socket.socket)
@@ -469,13 +545,58 @@ static int http_connect(http_subtransport *t)
469
545
  return -1;
470
546
 
471
547
  flags |= GITNO_CONNECT_SSL;
472
-
473
- if (GIT_TRANSPORTFLAGS_NO_CHECK_CERT & tflags)
474
- flags |= GITNO_CONNECT_SSL_NO_CHECK_CERT;
475
548
  }
476
549
 
477
- if (gitno_connect(&t->socket, t->connection_data.host, t->connection_data.port, flags) < 0)
478
- return -1;
550
+ error = gitno_connect(&t->socket, t->connection_data.host, t->connection_data.port, flags);
551
+
552
+ #ifdef GIT_SSL
553
+ if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL) {
554
+ X509 *cert = SSL_get_peer_certificate(t->socket.ssl.ssl);
555
+ git_cert_x509 cert_info, *cert_info_ptr;
556
+ int len, is_valid;
557
+ unsigned char *guard, *encoded_cert;
558
+
559
+ /* Retrieve the length of the certificate first */
560
+ len = i2d_X509(cert, NULL);
561
+ if (len < 0) {
562
+ giterr_set(GITERR_NET, "failed to retrieve certificate information");
563
+ return -1;
564
+ }
565
+
566
+
567
+ encoded_cert = git__malloc(len);
568
+ GITERR_CHECK_ALLOC(encoded_cert);
569
+ /* i2d_X509 makes 'copy' point to just after the data */
570
+ guard = encoded_cert;
571
+
572
+ len = i2d_X509(cert, &guard);
573
+ if (len < 0) {
574
+ git__free(encoded_cert);
575
+ giterr_set(GITERR_NET, "failed to retrieve certificate information");
576
+ return -1;
577
+ }
578
+
579
+ giterr_clear();
580
+ is_valid = error != GIT_ECERTIFICATE;
581
+ cert_info.cert_type = GIT_CERT_X509;
582
+ cert_info.data = encoded_cert;
583
+ cert_info.len = len;
584
+
585
+ cert_info_ptr = &cert_info;
586
+
587
+ error = t->owner->certificate_check_cb((git_cert *) cert_info_ptr, is_valid, t->connection_data.host, t->owner->message_cb_payload);
588
+ git__free(encoded_cert);
589
+
590
+ if (error < 0) {
591
+ if (!giterr_last())
592
+ giterr_set(GITERR_NET, "user cancelled certificate check");
593
+
594
+ return error;
595
+ }
596
+ }
597
+ #endif
598
+ if (error < 0)
599
+ return error;
479
600
 
480
601
  t->connected = 1;
481
602
  return 0;
@@ -502,10 +623,8 @@ replay:
502
623
 
503
624
  clear_parser_state(t);
504
625
 
505
- if (gen_request(&request, s, 0) < 0) {
506
- giterr_set(GITERR_NET, "Failed to generate request");
626
+ if (gen_request(&request, s, 0) < 0)
507
627
  return -1;
508
- }
509
628
 
510
629
  if (gitno_send(&t->socket, request.ptr, request.size, 0) < 0) {
511
630
  git_buf_free(&request);
@@ -538,6 +657,7 @@ replay:
538
657
 
539
658
  while (!*bytes_read && !t->parse_finished) {
540
659
  size_t data_offset;
660
+ int error;
541
661
 
542
662
  /*
543
663
  * Make the parse_buffer think it's as full of data as
@@ -584,8 +704,8 @@ replay:
584
704
  if (PARSE_ERROR_REPLAY == t->parse_error) {
585
705
  s->sent_request = 0;
586
706
 
587
- if (http_connect(t) < 0)
588
- return -1;
707
+ if ((error = http_connect(t)) < 0)
708
+ return error;
589
709
 
590
710
  goto replay;
591
711
  }
@@ -620,10 +740,8 @@ static int http_stream_write_chunked(
620
740
 
621
741
  clear_parser_state(t);
622
742
 
623
- if (gen_request(&request, s, 0) < 0) {
624
- giterr_set(GITERR_NET, "Failed to generate request");
743
+ if (gen_request(&request, s, 0) < 0)
625
744
  return -1;
626
- }
627
745
 
628
746
  if (gitno_send(&t->socket, request.ptr, request.size, 0) < 0) {
629
747
  git_buf_free(&request);
@@ -695,10 +813,8 @@ static int http_stream_write_single(
695
813
 
696
814
  clear_parser_state(t);
697
815
 
698
- if (gen_request(&request, s, len) < 0) {
699
- giterr_set(GITERR_NET, "Failed to generate request");
816
+ if (gen_request(&request, s, len) < 0)
700
817
  return -1;
701
- }
702
818
 
703
819
  if (gitno_send(&t->socket, request.ptr, request.size, 0) < 0)
704
820
  goto on_error;
@@ -841,8 +957,8 @@ static int http_action(
841
957
  (ret = gitno_connection_data_from_url(&t->connection_data, url, NULL)) < 0)
842
958
  return ret;
843
959
 
844
- if (http_connect(t) < 0)
845
- return -1;
960
+ if ((ret = http_connect(t)) < 0)
961
+ return ret;
846
962
 
847
963
  switch (action) {
848
964
  case GIT_SERVICE_UPLOADPACK_LS:
@@ -865,6 +981,8 @@ static int http_action(
865
981
  static int http_close(git_smart_subtransport *subtransport)
866
982
  {
867
983
  http_subtransport *t = (http_subtransport *) subtransport;
984
+ git_http_auth_context *context;
985
+ size_t i;
868
986
 
869
987
  clear_parser_state(t);
870
988
 
@@ -883,6 +1001,13 @@ static int http_close(git_smart_subtransport *subtransport)
883
1001
  t->url_cred = NULL;
884
1002
  }
885
1003
 
1004
+ git_vector_foreach(&t->auth_contexts, i, context) {
1005
+ if (context->free)
1006
+ context->free(context);
1007
+ }
1008
+
1009
+ git_vector_clear(&t->auth_contexts);
1010
+
886
1011
  gitno_connection_data_free_ptrs(&t->connection_data);
887
1012
 
888
1013
  return 0;
@@ -894,6 +1019,7 @@ static void http_free(git_smart_subtransport *subtransport)
894
1019
 
895
1020
  http_close(subtransport);
896
1021
 
1022
+ git_vector_free(&t->auth_contexts);
897
1023
  git__free(t);
898
1024
  }
899
1025