rugged 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rugged/version.rb +1 -1
- data/vendor/libgit2/CMakeLists.txt +1 -1
- data/vendor/libgit2/deps/ntlmclient/CMakeLists.txt +1 -0
- data/vendor/libgit2/deps/ntlmclient/compat.h +0 -34
- data/vendor/libgit2/deps/ntlmclient/crypt_openssl.c +1 -1
- data/vendor/libgit2/deps/ntlmclient/ntlm.c +5 -5
- data/vendor/libgit2/deps/ntlmclient/util.c +15 -1
- data/vendor/libgit2/deps/ntlmclient/util.h +2 -1
- data/vendor/libgit2/include/git2/apply.h +2 -0
- data/vendor/libgit2/include/git2/blob.h +17 -1
- data/vendor/libgit2/include/git2/common.h +5 -0
- data/vendor/libgit2/include/git2/config.h +1 -1
- data/vendor/libgit2/include/git2/diff.h +1 -1
- data/vendor/libgit2/include/git2/index.h +2 -2
- data/vendor/libgit2/include/git2/indexer.h +2 -1
- data/vendor/libgit2/include/git2/odb.h +15 -20
- data/vendor/libgit2/include/git2/refs.h +3 -3
- data/vendor/libgit2/include/git2/repository.h +95 -52
- data/vendor/libgit2/include/git2/transport.h +1 -1
- data/vendor/libgit2/include/git2/tree.h +2 -0
- data/vendor/libgit2/include/git2/version.h +2 -2
- data/vendor/libgit2/src/blame.c +15 -10
- data/vendor/libgit2/src/blob.c +9 -0
- data/vendor/libgit2/src/clone.c +42 -21
- data/vendor/libgit2/src/config_cache.c +6 -3
- data/vendor/libgit2/src/diff_tform.c +2 -2
- data/vendor/libgit2/src/index.c +6 -5
- data/vendor/libgit2/src/indexer.c +19 -3
- data/vendor/libgit2/src/integer.h +15 -0
- data/vendor/libgit2/src/merge.c +5 -2
- data/vendor/libgit2/src/mwindow.c +3 -1
- data/vendor/libgit2/src/odb.c +4 -3
- data/vendor/libgit2/src/pack.c +10 -6
- data/vendor/libgit2/src/posix.c +32 -9
- data/vendor/libgit2/src/posix.h +9 -0
- data/vendor/libgit2/src/refdb_fs.c +4 -2
- data/vendor/libgit2/src/refs.c +20 -7
- data/vendor/libgit2/src/refs.h +1 -1
- data/vendor/libgit2/src/refspec.c +48 -32
- data/vendor/libgit2/src/remote.c +13 -7
- data/vendor/libgit2/src/repository.c +15 -15
- data/vendor/libgit2/src/repository.h +1 -1
- data/vendor/libgit2/src/thread-utils.h +24 -19
- data/vendor/libgit2/src/transports/httpclient.c +9 -4
- data/vendor/libgit2/src/transports/winhttp.c +99 -52
- data/vendor/libgit2/src/unix/posix.h +3 -0
- data/vendor/libgit2/src/win32/posix_w32.c +70 -0
- data/vendor/libgit2/src/worktree.c +8 -1
- metadata +2 -2
data/vendor/libgit2/src/posix.h
CHANGED
@@ -89,6 +89,12 @@
|
|
89
89
|
#define EAFNOSUPPORT (INT_MAX-1)
|
90
90
|
#endif
|
91
91
|
|
92
|
+
/* Compiler independent macro to handle signal interrpted system calls */
|
93
|
+
#define HANDLE_EINTR(result, x) do { \
|
94
|
+
result = (x); \
|
95
|
+
} while (result == -1 && errno == EINTR);
|
96
|
+
|
97
|
+
|
92
98
|
/* Provide a 64-bit size for offsets. */
|
93
99
|
|
94
100
|
#if defined(_MSC_VER)
|
@@ -119,6 +125,9 @@ typedef int git_file;
|
|
119
125
|
extern ssize_t p_read(git_file fd, void *buf, size_t cnt);
|
120
126
|
extern int p_write(git_file fd, const void *buf, size_t cnt);
|
121
127
|
|
128
|
+
extern ssize_t p_pread(int fd, void *data, size_t size, off64_t offset);
|
129
|
+
extern ssize_t p_pwrite(int fd, const void *data, size_t size, off64_t offset);
|
130
|
+
|
122
131
|
#define p_close(fd) close(fd)
|
123
132
|
#define p_umask(m) umask(m)
|
124
133
|
|
@@ -254,7 +254,8 @@ static int loose_lookup_to_packfile(refdb_fs_backend *backend, const char *name)
|
|
254
254
|
if ((error = loose_parse_oid(&oid, name, &ref_file)) < 0)
|
255
255
|
goto done;
|
256
256
|
|
257
|
-
git_sortedcache_wlock(backend->refcache)
|
257
|
+
if ((error = git_sortedcache_wlock(backend->refcache)) < 0)
|
258
|
+
goto done;
|
258
259
|
|
259
260
|
if (!(error = git_sortedcache_upsert(
|
260
261
|
(void **)&ref, backend->refcache, name))) {
|
@@ -760,7 +761,8 @@ static int reference_path_available(
|
|
760
761
|
}
|
761
762
|
}
|
762
763
|
|
763
|
-
git_sortedcache_rlock(backend->refcache)
|
764
|
+
if ((error = git_sortedcache_rlock(backend->refcache)) < 0)
|
765
|
+
return error;
|
764
766
|
|
765
767
|
for (i = 0; i < git_sortedcache_entrycount(backend->refcache); ++i) {
|
766
768
|
struct packref *ref = git_sortedcache_entry(backend->refcache, i);
|
data/vendor/libgit2/src/refs.c
CHANGED
@@ -1287,19 +1287,32 @@ cleanup:
|
|
1287
1287
|
return error;
|
1288
1288
|
}
|
1289
1289
|
|
1290
|
-
int
|
1290
|
+
int git_reference__name_is_valid(
|
1291
|
+
int *valid,
|
1292
|
+
const char *refname,
|
1293
|
+
unsigned int flags)
|
1291
1294
|
{
|
1292
|
-
|
1293
|
-
git_error_clear();
|
1294
|
-
return false;
|
1295
|
-
}
|
1295
|
+
int error;
|
1296
1296
|
|
1297
|
-
|
1297
|
+
*valid = 0;
|
1298
|
+
|
1299
|
+
error = git_reference__normalize_name(NULL, refname, flags);
|
1300
|
+
|
1301
|
+
if (!error)
|
1302
|
+
*valid = 1;
|
1303
|
+
else if (error == GIT_EINVALIDSPEC)
|
1304
|
+
error = 0;
|
1305
|
+
|
1306
|
+
return error;
|
1298
1307
|
}
|
1299
1308
|
|
1300
1309
|
int git_reference_is_valid_name(const char *refname)
|
1301
1310
|
{
|
1302
|
-
|
1311
|
+
int valid = 0;
|
1312
|
+
|
1313
|
+
git_reference__name_is_valid(&valid, refname, GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL);
|
1314
|
+
|
1315
|
+
return valid;
|
1303
1316
|
}
|
1304
1317
|
|
1305
1318
|
const char *git_reference__shorthand(const char *name)
|
data/vendor/libgit2/src/refs.h
CHANGED
@@ -85,7 +85,7 @@ git_reference *git_reference__realloc(git_reference **ptr_to_ref, const char *na
|
|
85
85
|
|
86
86
|
int git_reference__normalize_name(git_buf *buf, const char *name, unsigned int flags);
|
87
87
|
int git_reference__update_terminal(git_repository *repo, const char *ref_name, const git_oid *oid, const git_signature *sig, const char *log_message);
|
88
|
-
int
|
88
|
+
int git_reference__name_is_valid(int *valid, const char *name, unsigned int flags);
|
89
89
|
int git_reference__is_branch(const char *ref_name);
|
90
90
|
int git_reference__is_remote(const char *ref_name);
|
91
91
|
int git_reference__is_tag(const char *ref_name);
|
@@ -21,7 +21,8 @@ int git_refspec__parse(git_refspec *refspec, const char *input, bool is_fetch)
|
|
21
21
|
size_t llen;
|
22
22
|
int is_glob = 0;
|
23
23
|
const char *lhs, *rhs;
|
24
|
-
int
|
24
|
+
int valid = 0;
|
25
|
+
unsigned int flags;
|
25
26
|
|
26
27
|
assert(refspec && input);
|
27
28
|
|
@@ -75,57 +76,69 @@ int git_refspec__parse(git_refspec *refspec, const char *input, bool is_fetch)
|
|
75
76
|
|
76
77
|
if (is_fetch) {
|
77
78
|
/*
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
79
|
+
* LHS
|
80
|
+
* - empty is allowed; it means HEAD.
|
81
|
+
* - otherwise it must be a valid looking ref.
|
82
|
+
*/
|
82
83
|
if (!*refspec->src)
|
83
84
|
; /* empty is ok */
|
84
|
-
else if (
|
85
|
+
else if (git_reference__name_is_valid(&valid, refspec->src, flags) < 0)
|
86
|
+
goto on_error;
|
87
|
+
else if (!valid)
|
85
88
|
goto invalid;
|
89
|
+
|
86
90
|
/*
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
91
|
+
* RHS
|
92
|
+
* - missing is ok, and is same as empty.
|
93
|
+
* - empty is ok; it means not to store.
|
94
|
+
* - otherwise it must be a valid looking ref.
|
95
|
+
*/
|
92
96
|
if (!refspec->dst)
|
93
97
|
; /* ok */
|
94
98
|
else if (!*refspec->dst)
|
95
99
|
; /* ok */
|
96
|
-
else if (
|
100
|
+
else if (git_reference__name_is_valid(&valid, refspec->dst, flags) < 0)
|
101
|
+
goto on_error;
|
102
|
+
else if (!valid)
|
97
103
|
goto invalid;
|
98
104
|
} else {
|
99
105
|
/*
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
+
* LHS
|
107
|
+
* - empty is allowed; it means delete.
|
108
|
+
* - when wildcarded, it must be a valid looking ref.
|
109
|
+
* - otherwise, it must be an extended SHA-1, but
|
110
|
+
* there is no existing way to validate this.
|
111
|
+
*/
|
106
112
|
if (!*refspec->src)
|
107
113
|
; /* empty is ok */
|
108
114
|
else if (is_glob) {
|
109
|
-
if (
|
115
|
+
if (git_reference__name_is_valid(&valid, refspec->src, flags) < 0)
|
116
|
+
goto on_error;
|
117
|
+
else if (!valid)
|
110
118
|
goto invalid;
|
111
119
|
}
|
112
120
|
else {
|
113
121
|
; /* anything goes, for now */
|
114
122
|
}
|
123
|
+
|
115
124
|
/*
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
125
|
+
* RHS
|
126
|
+
* - missing is allowed, but LHS then must be a
|
127
|
+
* valid looking ref.
|
128
|
+
* - empty is not allowed.
|
129
|
+
* - otherwise it must be a valid looking ref.
|
130
|
+
*/
|
122
131
|
if (!refspec->dst) {
|
123
|
-
if (
|
132
|
+
if (git_reference__name_is_valid(&valid, refspec->src, flags) < 0)
|
133
|
+
goto on_error;
|
134
|
+
else if (!valid)
|
124
135
|
goto invalid;
|
125
136
|
} else if (!*refspec->dst) {
|
126
137
|
goto invalid;
|
127
138
|
} else {
|
128
|
-
if (
|
139
|
+
if (git_reference__name_is_valid(&valid, refspec->dst, flags) < 0)
|
140
|
+
goto on_error;
|
141
|
+
else if (!valid)
|
129
142
|
goto invalid;
|
130
143
|
}
|
131
144
|
|
@@ -141,11 +154,14 @@ int git_refspec__parse(git_refspec *refspec, const char *input, bool is_fetch)
|
|
141
154
|
|
142
155
|
return 0;
|
143
156
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
157
|
+
invalid:
|
158
|
+
git_error_set(GIT_ERROR_INVALID,
|
159
|
+
"'%s' is not a valid refspec.", input);
|
160
|
+
git_refspec__dispose(refspec);
|
161
|
+
return GIT_EINVALIDSPEC;
|
162
|
+
|
163
|
+
on_error:
|
164
|
+
git_refspec__dispose(refspec);
|
149
165
|
return -1;
|
150
166
|
}
|
151
167
|
|
data/vendor/libgit2/src/remote.c
CHANGED
@@ -110,12 +110,8 @@ static int write_add_refspec(git_repository *repo, const char *name, const char
|
|
110
110
|
if ((error = ensure_remote_name_is_valid(name)) < 0)
|
111
111
|
return error;
|
112
112
|
|
113
|
-
if ((error = git_refspec__parse(&spec, refspec, fetch)) < 0)
|
114
|
-
if (git_error_last()->klass != GIT_ERROR_NOMEMORY)
|
115
|
-
error = GIT_EINVALIDSPEC;
|
116
|
-
|
113
|
+
if ((error = git_refspec__parse(&spec, refspec, fetch)) < 0)
|
117
114
|
return error;
|
118
|
-
}
|
119
115
|
|
120
116
|
git_refspec__dispose(&spec);
|
121
117
|
|
@@ -1116,7 +1112,7 @@ static int remote_head_for_ref(git_remote_head **out, git_remote *remote, git_re
|
|
1116
1112
|
git_reference *resolved_ref = NULL;
|
1117
1113
|
git_buf remote_name = GIT_BUF_INIT;
|
1118
1114
|
git_config *config = NULL;
|
1119
|
-
const char *ref_name;
|
1115
|
+
const char *ref_name = NULL;
|
1120
1116
|
int error = 0, update;
|
1121
1117
|
|
1122
1118
|
assert(out && spec && ref);
|
@@ -1129,10 +1125,20 @@ static int remote_head_for_ref(git_remote_head **out, git_remote *remote, git_re
|
|
1129
1125
|
if (error == GIT_ENOTFOUND && git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC) {
|
1130
1126
|
ref_name = git_reference_symbolic_target(ref);
|
1131
1127
|
error = 0;
|
1132
|
-
} else {
|
1128
|
+
} else if (resolved_ref) {
|
1133
1129
|
ref_name = git_reference_name(resolved_ref);
|
1134
1130
|
}
|
1135
1131
|
|
1132
|
+
/*
|
1133
|
+
* The ref name may be unresolvable - perhaps it's pointing to
|
1134
|
+
* something invalid. In this case, there is no remote head for
|
1135
|
+
* this ref.
|
1136
|
+
*/
|
1137
|
+
if (!ref_name) {
|
1138
|
+
error = 0;
|
1139
|
+
goto cleanup;
|
1140
|
+
}
|
1141
|
+
|
1136
1142
|
if ((error = ref_to_update(&update, &remote_name, remote, spec, ref_name)) < 0)
|
1137
1143
|
goto cleanup;
|
1138
1144
|
|
@@ -2078,7 +2078,8 @@ static int repo_init_head(const char *repo_dir, const char *given)
|
|
2078
2078
|
if (given) {
|
2079
2079
|
initial_head = given;
|
2080
2080
|
} else if ((error = git_config_open_default(&cfg)) >= 0 &&
|
2081
|
-
(error = git_config_get_string_buf(&cfg_branch, cfg, "init.defaultbranch")) >= 0
|
2081
|
+
(error = git_config_get_string_buf(&cfg_branch, cfg, "init.defaultbranch")) >= 0 &&
|
2082
|
+
*cfg_branch.ptr) {
|
2082
2083
|
initial_head = cfg_branch.ptr;
|
2083
2084
|
}
|
2084
2085
|
|
@@ -2334,21 +2335,19 @@ int git_repository_head_unborn(git_repository *repo)
|
|
2334
2335
|
return 0;
|
2335
2336
|
}
|
2336
2337
|
|
2337
|
-
static int at_least_one_cb(const char *refname, void *payload)
|
2338
|
-
{
|
2339
|
-
GIT_UNUSED(refname);
|
2340
|
-
GIT_UNUSED(payload);
|
2341
|
-
return GIT_PASSTHROUGH;
|
2342
|
-
}
|
2343
|
-
|
2344
2338
|
static int repo_contains_no_reference(git_repository *repo)
|
2345
2339
|
{
|
2346
|
-
|
2340
|
+
git_reference_iterator *iter;
|
2341
|
+
const char *refname;
|
2342
|
+
int error;
|
2347
2343
|
|
2348
|
-
if (error
|
2349
|
-
return
|
2344
|
+
if ((error = git_reference_iterator_new(&iter, repo)) < 0)
|
2345
|
+
return error;
|
2350
2346
|
|
2351
|
-
|
2347
|
+
error = git_reference_next_name(&refname, iter);
|
2348
|
+
git_reference_iterator_free(iter);
|
2349
|
+
|
2350
|
+
if (error == GIT_ITEROVER)
|
2352
2351
|
return 1;
|
2353
2352
|
|
2354
2353
|
return error;
|
@@ -2364,10 +2363,11 @@ int git_repository_initialbranch(git_buf *out, git_repository *repo)
|
|
2364
2363
|
if ((error = git_repository_config__weakptr(&config, repo)) < 0)
|
2365
2364
|
return error;
|
2366
2365
|
|
2367
|
-
if ((error = git_config_get_entry(&entry, config, "init.defaultbranch")) == 0
|
2366
|
+
if ((error = git_config_get_entry(&entry, config, "init.defaultbranch")) == 0 &&
|
2367
|
+
*entry->value) {
|
2368
2368
|
branch = entry->value;
|
2369
2369
|
}
|
2370
|
-
else if (error == GIT_ENOTFOUND) {
|
2370
|
+
else if (!error || error == GIT_ENOTFOUND) {
|
2371
2371
|
branch = GIT_BRANCH_DEFAULT;
|
2372
2372
|
}
|
2373
2373
|
else {
|
@@ -2379,7 +2379,7 @@ int git_repository_initialbranch(git_buf *out, git_repository *repo)
|
|
2379
2379
|
goto done;
|
2380
2380
|
|
2381
2381
|
if (!git_reference_is_valid_name(out->ptr)) {
|
2382
|
-
git_error_set(GIT_ERROR_INVALID, "the value of init.defaultBranch is not a valid
|
2382
|
+
git_error_set(GIT_ERROR_INVALID, "the value of init.defaultBranch is not a valid branch name");
|
2383
2383
|
error = -1;
|
2384
2384
|
}
|
2385
2385
|
|
@@ -235,35 +235,35 @@ GIT_INLINE(int64_t) git_atomic64_get(git_atomic64 *a)
|
|
235
235
|
|
236
236
|
#else
|
237
237
|
|
238
|
+
GIT_INLINE(int) git___noop(void) { return 0; }
|
239
|
+
|
238
240
|
#define git_thread unsigned int
|
239
|
-
#define git_thread_create(thread, start_routine, arg)
|
240
|
-
#define git_thread_join(id, status) (
|
241
|
+
#define git_thread_create(thread, start_routine, arg) git___noop()
|
242
|
+
#define git_thread_join(id, status) git___noop()
|
241
243
|
|
242
244
|
/* Pthreads Mutex */
|
243
245
|
#define git_mutex unsigned int
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
#define git_mutex_unlock(a) (void)0
|
249
|
-
#define git_mutex_free(a) (void)0
|
246
|
+
#define git_mutex_init(a) git___noop()
|
247
|
+
#define git_mutex_lock(a) git___noop()
|
248
|
+
#define git_mutex_unlock(a) git___noop()
|
249
|
+
#define git_mutex_free(a) git___noop()
|
250
250
|
|
251
251
|
/* Pthreads condition vars */
|
252
252
|
#define git_cond unsigned int
|
253
|
-
#define git_cond_init(c, a) (
|
254
|
-
#define git_cond_free(c) (
|
255
|
-
#define git_cond_wait(c, l) (
|
256
|
-
#define git_cond_signal(c) (
|
257
|
-
#define git_cond_broadcast(c) (
|
253
|
+
#define git_cond_init(c, a) git___noop()
|
254
|
+
#define git_cond_free(c) git___noop()
|
255
|
+
#define git_cond_wait(c, l) git___noop()
|
256
|
+
#define git_cond_signal(c) git___noop()
|
257
|
+
#define git_cond_broadcast(c) git___noop()
|
258
258
|
|
259
259
|
/* Pthreads rwlock */
|
260
260
|
#define git_rwlock unsigned int
|
261
|
-
#define git_rwlock_init(a)
|
262
|
-
#define git_rwlock_rdlock(a)
|
263
|
-
#define git_rwlock_rdunlock(a) (
|
264
|
-
#define git_rwlock_wrlock(a)
|
265
|
-
#define git_rwlock_wrunlock(a) (
|
266
|
-
#define git_rwlock_free(a) (
|
261
|
+
#define git_rwlock_init(a) git___noop()
|
262
|
+
#define git_rwlock_rdlock(a) git___noop()
|
263
|
+
#define git_rwlock_rdunlock(a) git___noop()
|
264
|
+
#define git_rwlock_wrlock(a) git___noop()
|
265
|
+
#define git_rwlock_wrunlock(a) git___noop()
|
266
|
+
#define git_rwlock_free(a) git___noop()
|
267
267
|
#define GIT_RWLOCK_STATIC_INIT 0
|
268
268
|
|
269
269
|
|
@@ -311,6 +311,11 @@ GIT_INLINE(volatile void *) git___swap(
|
|
311
311
|
return old;
|
312
312
|
}
|
313
313
|
|
314
|
+
GIT_INLINE(volatile void *) git___load(void * volatile *ptr)
|
315
|
+
{
|
316
|
+
return *ptr;
|
317
|
+
}
|
318
|
+
|
314
319
|
#ifdef GIT_ARCH_64
|
315
320
|
|
316
321
|
GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend)
|
@@ -658,6 +658,11 @@ static int generate_connect_request(
|
|
658
658
|
return git_buf_oom(buf) ? -1 : 0;
|
659
659
|
}
|
660
660
|
|
661
|
+
static bool use_connect_proxy(git_http_client *client)
|
662
|
+
{
|
663
|
+
return client->proxy.url.host && !strcmp(client->server.url.scheme, "https");
|
664
|
+
}
|
665
|
+
|
661
666
|
static int generate_request(
|
662
667
|
git_http_client *client,
|
663
668
|
git_http_request *request)
|
@@ -713,7 +718,8 @@ static int generate_request(
|
|
713
718
|
git_buf_printf(buf, "Expect: 100-continue\r\n");
|
714
719
|
|
715
720
|
if ((error = apply_server_credentials(buf, client, request)) < 0 ||
|
716
|
-
(
|
721
|
+
(!use_connect_proxy(client) &&
|
722
|
+
(error = apply_proxy_credentials(buf, client, request)) < 0))
|
717
723
|
return error;
|
718
724
|
|
719
725
|
if (request->custom_headers) {
|
@@ -1003,8 +1009,7 @@ static int http_client_connect(
|
|
1003
1009
|
reset_parser(client);
|
1004
1010
|
|
1005
1011
|
/* Reconnect to the proxy if necessary. */
|
1006
|
-
use_proxy = client
|
1007
|
-
!strcmp(client->server.url.scheme, "https");
|
1012
|
+
use_proxy = use_connect_proxy(client);
|
1008
1013
|
|
1009
1014
|
if (use_proxy) {
|
1010
1015
|
if (!client->proxy_connected || !client->keepalive ||
|
@@ -1476,7 +1481,7 @@ int git_http_client_skip_body(git_http_client *client)
|
|
1476
1481
|
"unexpected data handled in callback");
|
1477
1482
|
error = -1;
|
1478
1483
|
}
|
1479
|
-
} while (
|
1484
|
+
} while (error >= 0 && client->state != DONE);
|
1480
1485
|
|
1481
1486
|
if (error < 0)
|
1482
1487
|
client->connected = 0;
|
@@ -53,6 +53,10 @@
|
|
53
53
|
# define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3 0x00002000
|
54
54
|
#endif
|
55
55
|
|
56
|
+
#ifndef WINHTTP_NO_CLIENT_CERT_CONTEXT
|
57
|
+
# define WINHTTP_NO_CLIENT_CERT_CONTEXT NULL
|
58
|
+
#endif
|
59
|
+
|
56
60
|
#ifndef HTTP_STATUS_PERMANENT_REDIRECT
|
57
61
|
# define HTTP_STATUS_PERMANENT_REDIRECT 308
|
58
62
|
#endif
|
@@ -112,7 +116,8 @@ typedef struct {
|
|
112
116
|
DWORD post_body_len;
|
113
117
|
unsigned sent_request : 1,
|
114
118
|
received_response : 1,
|
115
|
-
chunked : 1
|
119
|
+
chunked : 1,
|
120
|
+
status_sending_request_reached: 1;
|
116
121
|
} winhttp_stream;
|
117
122
|
|
118
123
|
typedef struct {
|
@@ -708,30 +713,36 @@ static void CALLBACK winhttp_status(
|
|
708
713
|
DWORD status;
|
709
714
|
|
710
715
|
GIT_UNUSED(connection);
|
711
|
-
GIT_UNUSED(ctx);
|
712
716
|
GIT_UNUSED(info_len);
|
713
717
|
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
718
|
+
switch (code) {
|
719
|
+
case WINHTTP_CALLBACK_STATUS_SECURE_FAILURE:
|
720
|
+
status = *((DWORD *)info);
|
721
|
+
|
722
|
+
if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID))
|
723
|
+
git_error_set(GIT_ERROR_HTTP, "SSL certificate issued for different common name");
|
724
|
+
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID))
|
725
|
+
git_error_set(GIT_ERROR_HTTP, "SSL certificate has expired");
|
726
|
+
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA))
|
727
|
+
git_error_set(GIT_ERROR_HTTP, "SSL certificate signed by unknown CA");
|
728
|
+
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT))
|
729
|
+
git_error_set(GIT_ERROR_HTTP, "SSL certificate is invalid");
|
730
|
+
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED))
|
731
|
+
git_error_set(GIT_ERROR_HTTP, "certificate revocation check failed");
|
732
|
+
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED))
|
733
|
+
git_error_set(GIT_ERROR_HTTP, "SSL certificate was revoked");
|
734
|
+
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR))
|
735
|
+
git_error_set(GIT_ERROR_HTTP, "security libraries could not be loaded");
|
736
|
+
else
|
737
|
+
git_error_set(GIT_ERROR_HTTP, "unknown security error %lu", status);
|
738
|
+
|
739
|
+
break;
|
740
|
+
|
741
|
+
case WINHTTP_CALLBACK_STATUS_SENDING_REQUEST:
|
742
|
+
((winhttp_stream *) ctx)->status_sending_request_reached = 1;
|
743
|
+
|
744
|
+
break;
|
745
|
+
}
|
735
746
|
}
|
736
747
|
|
737
748
|
static int winhttp_connect(
|
@@ -826,7 +837,12 @@ static int winhttp_connect(
|
|
826
837
|
goto on_error;
|
827
838
|
}
|
828
839
|
|
829
|
-
if (WinHttpSetStatusCallback(
|
840
|
+
if (WinHttpSetStatusCallback(
|
841
|
+
t->connection,
|
842
|
+
winhttp_status,
|
843
|
+
WINHTTP_CALLBACK_FLAG_SECURE_FAILURE | WINHTTP_CALLBACK_FLAG_SEND_REQUEST,
|
844
|
+
0
|
845
|
+
) == WINHTTP_INVALID_STATUS_CALLBACK) {
|
830
846
|
git_error_set(GIT_ERROR_OS, "failed to set status callback");
|
831
847
|
goto on_error;
|
832
848
|
}
|
@@ -858,12 +874,12 @@ static int do_send_request(winhttp_stream *s, size_t len, bool chunked)
|
|
858
874
|
success = WinHttpSendRequest(s->request,
|
859
875
|
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
|
860
876
|
WINHTTP_NO_REQUEST_DATA, 0,
|
861
|
-
WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH,
|
877
|
+
WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, (DWORD_PTR)s);
|
862
878
|
} else {
|
863
879
|
success = WinHttpSendRequest(s->request,
|
864
880
|
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
|
865
881
|
WINHTTP_NO_REQUEST_DATA, 0,
|
866
|
-
(DWORD)len,
|
882
|
+
(DWORD)len, (DWORD_PTR)s);
|
867
883
|
}
|
868
884
|
|
869
885
|
if (success || GetLastError() != (DWORD)SEC_E_BUFFER_TOO_SMALL)
|
@@ -875,42 +891,73 @@ static int do_send_request(winhttp_stream *s, size_t len, bool chunked)
|
|
875
891
|
|
876
892
|
static int send_request(winhttp_stream *s, size_t len, bool chunked)
|
877
893
|
{
|
878
|
-
int request_failed =
|
879
|
-
DWORD ignore_flags;
|
894
|
+
int request_failed = 1, error, attempts = 0;
|
895
|
+
DWORD ignore_flags, send_request_error;
|
880
896
|
|
881
897
|
git_error_clear();
|
882
|
-
if ((error = do_send_request(s, len, chunked)) < 0) {
|
883
|
-
if (GetLastError() != ERROR_WINHTTP_SECURE_FAILURE) {
|
884
|
-
git_error_set(GIT_ERROR_OS, "failed to send request");
|
885
|
-
return -1;
|
886
|
-
}
|
887
898
|
|
888
|
-
|
889
|
-
cert_valid =
|
890
|
-
|
899
|
+
while (request_failed && attempts++ < 3) {
|
900
|
+
int cert_valid = 1;
|
901
|
+
int client_cert_requested = 0;
|
902
|
+
request_failed = 0;
|
903
|
+
|
904
|
+
if ((error = do_send_request(s, len, chunked)) < 0) {
|
905
|
+
send_request_error = GetLastError();
|
906
|
+
request_failed = 1;
|
907
|
+
|
908
|
+
switch (send_request_error) {
|
909
|
+
case ERROR_WINHTTP_SECURE_FAILURE:
|
910
|
+
cert_valid = 0;
|
911
|
+
break;
|
912
|
+
case ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED:
|
913
|
+
client_cert_requested = 1;
|
914
|
+
break;
|
915
|
+
default:
|
916
|
+
git_error_set(GIT_ERROR_OS, "failed to send request");
|
917
|
+
return -1;
|
918
|
+
}
|
919
|
+
}
|
891
920
|
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
921
|
+
/*
|
922
|
+
* Only check the certificate if we were able to reach the sending request phase, or
|
923
|
+
* received a secure failure error. Otherwise, the server certificate won't be available
|
924
|
+
* since the request wasn't able to complete (e.g. proxy auth required)
|
925
|
+
*/
|
926
|
+
if (!cert_valid ||
|
927
|
+
(!request_failed && s->status_sending_request_reached)) {
|
928
|
+
git_error_clear();
|
929
|
+
if ((error = certificate_check(s, cert_valid)) < 0) {
|
930
|
+
if (!git_error_last())
|
931
|
+
git_error_set(GIT_ERROR_OS, "user cancelled certificate check");
|
896
932
|
|
897
|
-
|
898
|
-
|
933
|
+
return error;
|
934
|
+
}
|
935
|
+
}
|
899
936
|
|
900
|
-
|
901
|
-
|
902
|
-
|
937
|
+
/* if neither the request nor the certificate check returned errors, we're done */
|
938
|
+
if (!request_failed)
|
939
|
+
return 0;
|
903
940
|
|
904
|
-
|
941
|
+
if (!cert_valid) {
|
942
|
+
ignore_flags = no_check_cert_flags;
|
943
|
+
if (!WinHttpSetOption(s->request, WINHTTP_OPTION_SECURITY_FLAGS, &ignore_flags, sizeof(ignore_flags))) {
|
944
|
+
git_error_set(GIT_ERROR_OS, "failed to set security options");
|
945
|
+
return -1;
|
946
|
+
}
|
947
|
+
}
|
905
948
|
|
906
|
-
|
907
|
-
|
908
|
-
|
949
|
+
if (client_cert_requested) {
|
950
|
+
/*
|
951
|
+
* Client certificates are not supported, explicitly tell the server that
|
952
|
+
* (it's possible a client certificate was requested but is not required)
|
953
|
+
*/
|
954
|
+
if (!WinHttpSetOption(s->request, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0)) {
|
955
|
+
git_error_set(GIT_ERROR_OS, "failed to set client cert context");
|
956
|
+
return -1;
|
957
|
+
}
|
958
|
+
}
|
909
959
|
}
|
910
960
|
|
911
|
-
if ((error = do_send_request(s, len, chunked)) < 0)
|
912
|
-
git_error_set(GIT_ERROR_OS, "failed to send request with unchecked certificate");
|
913
|
-
|
914
961
|
return error;
|
915
962
|
}
|
916
963
|
|