]> git.proxmox.com Git - libgit2.git/blame - tests/online/clone.c
DFSG changes
[libgit2.git] / tests / online / clone.c
CommitLineData
65415ea2
BS
1#include "clar_libgit2.h"
2
3#include "git2/clone.h"
520dcc1c 4#include "git2/cred_helpers.h"
6f748f38 5#include "remote.h"
114f5a6c
RB
6#include "fileops.h"
7#include "refs.h"
65415ea2 8
44f36f6e
BS
9#define LIVE_REPO_URL "http://github.com/libgit2/TestGitRepository"
10#define LIVE_EMPTYREPO_URL "http://github.com/libgit2/TestEmptyRepository"
3382d8b1
CMN
11#define BB_REPO_URL "https://libgit3@bitbucket.org/libgit2/testgitrepository.git"
12#define BB_REPO_URL_WITH_PASS "https://libgit3:libgit3@bitbucket.org/libgit2/testgitrepository.git"
13#define BB_REPO_URL_WITH_WRONG_PASS "https://libgit3:wrong@bitbucket.org/libgit2/testgitrepository.git"
65415ea2 14
22618906
CMN
15#define SSH_REPO_URL "ssh://github.com/libgit2/TestGitRepository"
16
65415ea2 17static git_repository *g_repo;
18b2d560 18static git_clone_options g_options;
65415ea2 19
e069c621
ET
20static char *_remote_url = NULL;
21static char *_remote_user = NULL;
22static char *_remote_pass = NULL;
23static char *_remote_ssh_pubkey = NULL;
24static char *_remote_ssh_privkey = NULL;
25static char *_remote_ssh_passphrase = NULL;
26static char *_remote_ssh_fingerprint = NULL;
07bd3e57
CMN
27static char *_remote_proxy_url = NULL;
28static char *_remote_proxy_user = NULL;
29static char *_remote_proxy_pass = NULL;
e069c621
ET
30
31
6443eaf2 32void test_online_clone__initialize(void)
65415ea2 33{
6affd71f 34 git_checkout_options dummy_opts = GIT_CHECKOUT_OPTIONS_INIT;
8f0104ec 35 git_fetch_options dummy_fetch = GIT_FETCH_OPTIONS_INIT;
730df6d0 36
65415ea2 37 g_repo = NULL;
18b2d560
BS
38
39 memset(&g_options, 0, sizeof(git_clone_options));
40 g_options.version = GIT_CLONE_OPTIONS_VERSION;
730df6d0
BS
41 g_options.checkout_opts = dummy_opts;
42 g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
8f0104ec 43 g_options.fetch_opts = dummy_fetch;
e069c621
ET
44
45 _remote_url = cl_getenv("GITTEST_REMOTE_URL");
46 _remote_user = cl_getenv("GITTEST_REMOTE_USER");
47 _remote_pass = cl_getenv("GITTEST_REMOTE_PASS");
48 _remote_ssh_pubkey = cl_getenv("GITTEST_REMOTE_SSH_PUBKEY");
49 _remote_ssh_privkey = cl_getenv("GITTEST_REMOTE_SSH_KEY");
50 _remote_ssh_passphrase = cl_getenv("GITTEST_REMOTE_SSH_PASSPHRASE");
51 _remote_ssh_fingerprint = cl_getenv("GITTEST_REMOTE_SSH_FINGERPRINT");
07bd3e57
CMN
52 _remote_proxy_url = cl_getenv("GITTEST_REMOTE_PROXY_URL");
53 _remote_proxy_user = cl_getenv("GITTEST_REMOTE_PROXY_USER");
54 _remote_proxy_pass = cl_getenv("GITTEST_REMOTE_PROXY_PASS");
65415ea2
BS
55}
56
6443eaf2 57void test_online_clone__cleanup(void)
65415ea2 58{
9094d30b 59 if (g_repo) {
65415ea2 60 git_repository_free(g_repo);
9094d30b
SC
61 g_repo = NULL;
62 }
7761ce21 63 cl_fixture_cleanup("./foo");
e069c621
ET
64
65 git__free(_remote_url);
66 git__free(_remote_user);
67 git__free(_remote_pass);
68 git__free(_remote_ssh_pubkey);
69 git__free(_remote_ssh_privkey);
70 git__free(_remote_ssh_passphrase);
71 git__free(_remote_ssh_fingerprint);
07bd3e57
CMN
72 git__free(_remote_proxy_url);
73 git__free(_remote_proxy_user);
74 git__free(_remote_proxy_pass);
65415ea2
BS
75}
76
6443eaf2 77void test_online_clone__network_full(void)
65415ea2
BS
78{
79 git_remote *origin;
80
b412d563 81 cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
65415ea2 82 cl_assert(!git_repository_is_bare(g_repo));
209425ce 83 cl_git_pass(git_remote_lookup(&origin, g_repo, "origin"));
add5efe7 84
6f748f38
JM
85 cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_AUTO, origin->download_tags);
86
add5efe7 87 git_remote_free(origin);
65415ea2
BS
88}
89
6443eaf2 90void test_online_clone__network_bare(void)
65415ea2
BS
91{
92 git_remote *origin;
93
18b2d560 94 g_options.bare = true;
65415ea2 95
b412d563 96 cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
65415ea2 97 cl_assert(git_repository_is_bare(g_repo));
209425ce 98 cl_git_pass(git_remote_lookup(&origin, g_repo, "origin"));
add5efe7 99
100 git_remote_free(origin);
65415ea2
BS
101}
102
6443eaf2 103void test_online_clone__empty_repository(void)
65415ea2
BS
104{
105 git_reference *head;
106
b412d563 107 cl_git_pass(git_clone(&g_repo, LIVE_EMPTYREPO_URL, "./foo", &g_options));
65415ea2
BS
108
109 cl_assert_equal_i(true, git_repository_is_empty(g_repo));
605da51a 110 cl_assert_equal_i(true, git_repository_head_unborn(g_repo));
65415ea2
BS
111
112 cl_git_pass(git_reference_lookup(&head, g_repo, GIT_HEAD_FILE));
113 cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head));
2508cc66 114 cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head));
65415ea2
BS
115
116 git_reference_free(head);
117}
4d968f13 118
9c05c17b 119static void checkout_progress(const char *path, size_t cur, size_t tot, void *payload)
183d8bdd 120{
183d8bdd 121 bool *was_called = (bool*)payload;
1fc375e6 122 GIT_UNUSED(path); GIT_UNUSED(cur); GIT_UNUSED(tot);
183d8bdd
BS
123 (*was_called) = true;
124}
125
fe95ac1b 126static int fetch_progress(const git_transfer_progress *stats, void *payload)
aa1e8674 127{
aa1e8674 128 bool *was_called = (bool*)payload;
1fc375e6 129 GIT_UNUSED(stats);
aa1e8674 130 (*was_called) = true;
fe95ac1b 131 return 0;
aa1e8674
BS
132}
133
6443eaf2 134void test_online_clone__can_checkout_a_cloned_repo(void)
4d968f13 135{
4d968f13 136 git_buf path = GIT_BUF_INIT;
c4f68b32 137 git_reference *head;
aa1e8674
BS
138 bool checkout_progress_cb_was_called = false,
139 fetch_progress_cb_was_called = false;
4d968f13 140
6c9e86ad 141 g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
730df6d0
BS
142 g_options.checkout_opts.progress_cb = &checkout_progress;
143 g_options.checkout_opts.progress_payload = &checkout_progress_cb_was_called;
8f0104ec
CMN
144 g_options.fetch_opts.callbacks.transfer_progress = &fetch_progress;
145 g_options.fetch_opts.callbacks.payload = &fetch_progress_cb_was_called;
4d968f13 146
b412d563 147 cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
4d968f13 148
149 cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt"));
150 cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path)));
c4f68b32 151
152 cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
153 cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head));
2508cc66 154 cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head));
add5efe7 155
aa1e8674
BS
156 cl_assert_equal_i(true, checkout_progress_cb_was_called);
157 cl_assert_equal_i(true, fetch_progress_cb_was_called);
183d8bdd 158
add5efe7 159 git_reference_free(head);
160 git_buf_free(&path);
4d968f13 161}
621b50e4 162
6812afaf
CMN
163static int remote_mirror_cb(git_remote **out, git_repository *repo,
164 const char *name, const char *url, void *payload)
d19870d9 165{
6812afaf 166 int error;
d19870d9 167 git_remote *remote;
d19870d9 168
8f0104ec 169 GIT_UNUSED(payload);
d19870d9 170
77254990 171 if ((error = git_remote_create_with_fetchspec(&remote, repo, name, url, "+refs/*:refs/*")) < 0)
6812afaf 172 return error;
d19870d9 173
6812afaf
CMN
174 *out = remote;
175 return 0;
d19870d9
CMN
176}
177
b2067248
CMN
178void test_online_clone__clone_mirror(void)
179{
6812afaf 180 git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
b2067248 181 git_reference *head;
b2067248
CMN
182
183 bool fetch_progress_cb_was_called = false;
184
8f0104ec
CMN
185 opts.fetch_opts.callbacks.transfer_progress = &fetch_progress;
186 opts.fetch_opts.callbacks.payload = &fetch_progress_cb_was_called;
b2067248 187
6812afaf
CMN
188 opts.bare = true;
189 opts.remote_cb = remote_mirror_cb;
b2067248 190
6812afaf 191 cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo.git", &opts));
b2067248
CMN
192
193 cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
194 cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head));
195 cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head));
196
197 cl_assert_equal_i(true, fetch_progress_cb_was_called);
198
b2067248 199 git_reference_free(head);
6d1b0438
PK
200 git_repository_free(g_repo);
201 g_repo = NULL;
202
b2067248
CMN
203 cl_fixture_cleanup("./foo.git");
204}
205
621b50e4
BS
206static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void *payload)
207{
208 int *callcount = (int*)payload;
209 GIT_UNUSED(refname); GIT_UNUSED(a); GIT_UNUSED(b);
210 *callcount = *callcount + 1;
211 return 0;
212}
213
ffb02b16 214void test_online_clone__custom_remote_callbacks(void)
621b50e4 215{
621b50e4
BS
216 int callcount = 0;
217
8f0104ec
CMN
218 g_options.fetch_opts.callbacks.update_tips = update_tips;
219 g_options.fetch_opts.callbacks.payload = &callcount;
621b50e4
BS
220
221 cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
222 cl_assert(callcount > 0);
223}
224
3245896b
MB
225void test_online_clone__custom_headers(void)
226{
227 char *empty_header = "";
228 char *unnamed_header = "this is a header about nothing";
229 char *newlines = "X-Custom: almost OK\n";
230 char *conflict = "Accept: defined-by-git";
231 char *ok = "X-Custom: this should be ok";
232
233 g_options.fetch_opts.custom_headers.count = 1;
234
235 g_options.fetch_opts.custom_headers.strings = &empty_header;
236 cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
237
238 g_options.fetch_opts.custom_headers.strings = &unnamed_header;
239 cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
240
241 g_options.fetch_opts.custom_headers.strings = &newlines;
242 cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
243
244 g_options.fetch_opts.custom_headers.strings = &conflict;
245 cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
246
247 /* Finally, we got it right! */
248 g_options.fetch_opts.custom_headers.strings = &ok;
249 cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
250}
251
80fc7d6b
ET
252static int cred_failure_cb(
253 git_cred **cred,
254 const char *url,
255 const char *username_from_url,
256 unsigned int allowed_types,
257 void *data)
258{
8f2a3d62
RB
259 GIT_UNUSED(cred); GIT_UNUSED(url); GIT_UNUSED(username_from_url);
260 GIT_UNUSED(allowed_types); GIT_UNUSED(data);
fe45922d 261 return -172;
80fc7d6b
ET
262}
263
fe45922d 264void test_online_clone__cred_callback_failure_return_code_is_tunnelled(void)
80fc7d6b 265{
e069c621 266 if (!_remote_url || !_remote_user)
0f65733b 267 clar__skip();
5dae3ffe 268
8f0104ec 269 g_options.fetch_opts.callbacks.credentials = cred_failure_cb;
80fc7d6b 270
e069c621 271 cl_git_fail_with(-172, git_clone(&g_repo, _remote_url, "./foo", &g_options));
80fc7d6b
ET
272}
273
d7f962f4
CMN
274static int cred_count_calls_cb(git_cred **cred, const char *url, const char *user,
275 unsigned int allowed_types, void *data)
276{
277 size_t *counter = (size_t *) data;
278
279 GIT_UNUSED(url); GIT_UNUSED(user); GIT_UNUSED(allowed_types);
280
ccb85c8f
CMN
281 if (allowed_types == GIT_CREDTYPE_USERNAME)
282 return git_cred_username_new(cred, "foo");
283
d7f962f4
CMN
284 (*counter)++;
285
286 if (*counter == 3)
287 return GIT_EUSER;
288
289 return git_cred_userpass_plaintext_new(cred, "foo", "bar");
290}
291
292void test_online_clone__cred_callback_called_again_on_auth_failure(void)
293{
d7f962f4
CMN
294 size_t counter = 0;
295
e069c621 296 if (!_remote_url || !_remote_user)
d7f962f4
CMN
297 clar__skip();
298
8f0104ec
CMN
299 g_options.fetch_opts.callbacks.credentials = cred_count_calls_cb;
300 g_options.fetch_opts.callbacks.payload = &counter;
d7f962f4 301
e069c621 302 cl_git_fail_with(GIT_EUSER, git_clone(&g_repo, _remote_url, "./foo", &g_options));
d7f962f4
CMN
303 cl_assert_equal_i(3, counter);
304}
305
adcdeb36
ET
306int cred_default(
307 git_cred **cred,
308 const char *url,
309 const char *user_from_url,
310 unsigned int allowed_types,
311 void *payload)
312{
313 GIT_UNUSED(url);
314 GIT_UNUSED(user_from_url);
315 GIT_UNUSED(payload);
316
317 if (!(allowed_types & GIT_CREDTYPE_DEFAULT))
318 return 0;
319
320 return git_cred_default_new(cred);
321}
322
ffb02b16 323void test_online_clone__credentials(void)
621b50e4 324{
adcdeb36
ET
325 /* Remote URL environment variable must be set.
326 * User and password are optional.
327 */
520dcc1c 328 git_cred_userpass_payload user_pass = {
e069c621
ET
329 _remote_user,
330 _remote_pass
621b50e4
BS
331 };
332
e069c621
ET
333 if (!_remote_url)
334 clar__skip();
621b50e4 335
e069c621 336 if (cl_is_env_set("GITTEST_REMOTE_DEFAULT")) {
8f0104ec 337 g_options.fetch_opts.callbacks.credentials = cred_default;
adcdeb36 338 } else {
8f0104ec
CMN
339 g_options.fetch_opts.callbacks.credentials = git_cred_userpass;
340 g_options.fetch_opts.callbacks.payload = &user_pass;
adcdeb36 341 }
621b50e4 342
e069c621 343 cl_git_pass(git_clone(&g_repo, _remote_url, "./foo", &g_options));
5f10853e
BS
344 git_repository_free(g_repo); g_repo = NULL;
345 cl_fixture_cleanup("./foo");
346}
347
348void test_online_clone__bitbucket_style(void)
349{
350 git_cred_userpass_payload user_pass = {
351 "libgit2", "libgit2"
352 };
353
8f0104ec
CMN
354 g_options.fetch_opts.callbacks.credentials = git_cred_userpass;
355 g_options.fetch_opts.callbacks.payload = &user_pass;
5f10853e
BS
356
357 cl_git_pass(git_clone(&g_repo, BB_REPO_URL, "./foo", &g_options));
358 git_repository_free(g_repo); g_repo = NULL;
359 cl_fixture_cleanup("./foo");
cf7038a6 360
54ffc1f7
BS
361 /* User and pass from URL */
362 user_pass.password = "wrong";
cf7038a6
BS
363 cl_git_pass(git_clone(&g_repo, BB_REPO_URL_WITH_PASS, "./foo", &g_options));
364 git_repository_free(g_repo); g_repo = NULL;
365 cl_fixture_cleanup("./foo");
54ffc1f7
BS
366
367 /* Wrong password in URL, fall back to user_pass */
368 user_pass.password = "libgit2";
369 cl_git_pass(git_clone(&g_repo, BB_REPO_URL_WITH_WRONG_PASS, "./foo", &g_options));
370 git_repository_free(g_repo); g_repo = NULL;
371 cl_fixture_cleanup("./foo");
621b50e4 372}
fe95ac1b
BS
373
374static int cancel_at_half(const git_transfer_progress *stats, void *payload)
375{
376 GIT_UNUSED(payload);
377
378 if (stats->received_objects > (stats->total_objects/2))
25e0b157 379 return 4321;
fe95ac1b
BS
380 return 0;
381}
382
383void test_online_clone__can_cancel(void)
384{
8f0104ec 385 g_options.fetch_opts.callbacks.transfer_progress = cancel_at_half;
d31402a3 386
25e0b157
RB
387 cl_git_fail_with(
388 git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), 4321);
fe95ac1b 389}
d31402a3 390
d4256ed5
CMN
391static int cred_cb(git_cred **cred, const char *url, const char *user_from_url,
392 unsigned int allowed_types, void *payload)
393{
d4256ed5
CMN
394 GIT_UNUSED(url); GIT_UNUSED(user_from_url); GIT_UNUSED(payload);
395
c13b6844 396 if (allowed_types & GIT_CREDTYPE_USERNAME)
e069c621 397 return git_cred_username_new(cred, _remote_user);
c13b6844 398
d4256ed5 399 if (allowed_types & GIT_CREDTYPE_SSH_KEY)
e069c621
ET
400 return git_cred_ssh_key_new(cred,
401 _remote_user, _remote_ssh_pubkey,
402 _remote_ssh_privkey, _remote_ssh_passphrase);
d4256ed5
CMN
403
404 giterr_set(GITERR_NET, "unexpected cred type");
405 return -1;
406}
d31402a3 407
22618906
CMN
408static int check_ssh_auth_methods(git_cred **cred, const char *url, const char *username_from_url,
409 unsigned int allowed_types, void *data)
410{
e26b08d3 411 int *with_user = (int *) data;
22618906 412 GIT_UNUSED(cred); GIT_UNUSED(url); GIT_UNUSED(username_from_url); GIT_UNUSED(data);
d31402a3 413
e26b08d3
CMN
414 if (!*with_user)
415 cl_assert_equal_i(GIT_CREDTYPE_USERNAME, allowed_types);
416 else
417 cl_assert(!(allowed_types & GIT_CREDTYPE_USERNAME));
d31402a3 418
22618906
CMN
419 return GIT_EUSER;
420}
d31402a3 421
22618906
CMN
422void test_online_clone__ssh_auth_methods(void)
423{
e26b08d3
CMN
424 int with_user;
425
fe3b6789
L
426#ifndef GIT_SSH
427 clar__skip();
428#endif
8f0104ec
CMN
429 g_options.fetch_opts.callbacks.credentials = check_ssh_auth_methods;
430 g_options.fetch_opts.callbacks.payload = &with_user;
d31402a3 431
e26b08d3 432 with_user = 0;
22618906
CMN
433 cl_git_fail_with(GIT_EUSER,
434 git_clone(&g_repo, SSH_REPO_URL, "./foo", &g_options));
e26b08d3
CMN
435
436 with_user = 1;
437 cl_git_fail_with(GIT_EUSER,
438 git_clone(&g_repo, "ssh://git@github.com/libgit2/TestGitRepository", "./foo", &g_options));
439}
440
d4256ed5
CMN
441static int custom_remote_ssh_with_paths(
442 git_remote **out,
443 git_repository *repo,
444 const char *name,
445 const char *url,
446 void *payload)
447{
448 int error;
d4256ed5 449
058b753c 450 GIT_UNUSED(payload);
d4256ed5 451
058b753c 452 if ((error = git_remote_create(out, repo, name, url)) < 0)
d4256ed5 453 return error;
d31402a3 454
d4256ed5
CMN
455 return 0;
456}
457
458void test_online_clone__ssh_with_paths(void)
459{
460 char *bad_paths[] = {
461 "/bin/yes",
462 "/bin/false",
463 };
464 char *good_paths[] = {
465 "/usr/bin/git-upload-pack",
466 "/usr/bin/git-receive-pack",
467 };
468 git_strarray arr = {
469 bad_paths,
470 2,
471 };
472
fe3b6789
L
473#ifndef GIT_SSH
474 clar__skip();
475#endif
e069c621 476 if (!_remote_url || !_remote_user || strncmp(_remote_url, "ssh://", 5) != 0)
d4256ed5
CMN
477 clar__skip();
478
479 g_options.remote_cb = custom_remote_ssh_with_paths;
058b753c 480 g_options.fetch_opts.callbacks.transport = git_transport_ssh_with_paths;
352ee171 481 g_options.fetch_opts.callbacks.credentials = cred_cb;
058b753c 482 g_options.fetch_opts.callbacks.payload = &arr;
d31402a3 483
e069c621 484 cl_git_fail(git_clone(&g_repo, _remote_url, "./foo", &g_options));
d31402a3 485
d4256ed5 486 arr.strings = good_paths;
e069c621 487 cl_git_pass(git_clone(&g_repo, _remote_url, "./foo", &g_options));
d4256ed5 488}
d31402a3 489
e26b08d3
CMN
490static int cred_foo_bar(git_cred **cred, const char *url, const char *username_from_url,
491 unsigned int allowed_types, void *data)
492
493{
494 GIT_UNUSED(url); GIT_UNUSED(username_from_url); GIT_UNUSED(allowed_types); GIT_UNUSED(data);
495
496 return git_cred_userpass_plaintext_new(cred, "foo", "bar");
497}
498
499void test_online_clone__ssh_cannot_change_username(void)
500{
fe3b6789
L
501#ifndef GIT_SSH
502 clar__skip();
503#endif
8f0104ec 504 g_options.fetch_opts.callbacks.credentials = cred_foo_bar;
e26b08d3
CMN
505
506 cl_git_fail(git_clone(&g_repo, "ssh://git@github.com/libgit2/TestGitRepository", "./foo", &g_options));
22618906 507}
f0c53d21 508
e6e834a1 509int ssh_certificate_check(git_cert *cert, int valid, const char *host, void *payload)
bf8756d6
CMN
510{
511 git_cert_hostkey *key;
512 git_oid expected = {{0}}, actual = {{0}};
bf8756d6 513
bf8756d6
CMN
514 GIT_UNUSED(valid);
515 GIT_UNUSED(payload);
516
e069c621 517 cl_assert(_remote_ssh_fingerprint);
bf8756d6 518
e069c621 519 cl_git_pass(git_oid_fromstrp(&expected, _remote_ssh_fingerprint));
0782fc43 520 cl_assert_equal_i(GIT_CERT_HOSTKEY_LIBSSH2, cert->cert_type);
0782fc43 521 key = (git_cert_hostkey *) cert;
bf8756d6 522
1e0aa105
CMN
523 /*
524 * We need to figure out how long our input was to check for
525 * the type. Here we abuse the fact that both hashes fit into
526 * our git_oid type.
527 */
e069c621 528 if (strlen(_remote_ssh_fingerprint) == 32 && key->type & GIT_CERT_SSH_MD5) {
1e0aa105 529 memcpy(&actual.id, key->hash_md5, 16);
e069c621 530 } else if (strlen(_remote_ssh_fingerprint) == 40 && key->type & GIT_CERT_SSH_SHA1) {
1e0aa105
CMN
531 memcpy(&actual, key->hash_sha1, 20);
532 } else {
533 cl_fail("Cannot find a usable SSH hash");
534 }
286369a8 535
1e0aa105 536 cl_assert(!memcmp(&expected, &actual, 20));
bf8756d6 537
db3d169c
SS
538 cl_assert_equal_s("localhost", host);
539
bf8756d6
CMN
540 return GIT_EUSER;
541}
542
543void test_online_clone__ssh_cert(void)
544{
8f0104ec 545 g_options.fetch_opts.callbacks.certificate_check = ssh_certificate_check;
bf8756d6 546
e069c621 547 if (!_remote_ssh_fingerprint)
52e09724
CMN
548 cl_skip();
549
bf8756d6
CMN
550 cl_git_fail_with(GIT_EUSER, git_clone(&g_repo, "ssh://localhost/foo", "./foo", &g_options));
551}
552
8085adf8
MG
553static char *read_key_file(const char *path)
554{
555 FILE *f;
556 char *buf;
557 long key_length;
558
559 if (!path || !*path)
560 return NULL;
561
562 cl_assert((f = fopen(path, "r")) != NULL);
563 cl_assert(fseek(f, 0, SEEK_END) != -1);
564 cl_assert((key_length = ftell(f)) != -1);
565 cl_assert(fseek(f, 0, SEEK_SET) != -1);
566 cl_assert((buf = malloc(key_length)) != NULL);
567 cl_assert(fread(buf, key_length, 1, f) == 1);
568 fclose(f);
569
570 return buf;
571}
572
573static int ssh_memory_cred_cb(git_cred **cred, const char *url, const char *user_from_url,
574 unsigned int allowed_types, void *payload)
575{
8085adf8
MG
576 GIT_UNUSED(url); GIT_UNUSED(user_from_url); GIT_UNUSED(payload);
577
578 if (allowed_types & GIT_CREDTYPE_USERNAME)
e069c621 579 return git_cred_username_new(cred, _remote_user);
8085adf8
MG
580
581 if (allowed_types & GIT_CREDTYPE_SSH_KEY)
582 {
e069c621
ET
583 char *pubkey = read_key_file(_remote_ssh_pubkey);
584 char *privkey = read_key_file(_remote_ssh_privkey);
8085adf8 585
e069c621 586 int ret = git_cred_ssh_key_memory_new(cred, _remote_user, pubkey, privkey, _remote_ssh_passphrase);
8085adf8
MG
587
588 if (privkey)
589 free(privkey);
590 if (pubkey)
591 free(pubkey);
592 return ret;
593 }
594
595 giterr_set(GITERR_NET, "unexpected cred type");
596 return -1;
597}
598
599void test_online_clone__ssh_memory_auth(void)
600{
8085adf8
MG
601#ifndef GIT_SSH_MEMORY_CREDENTIALS
602 clar__skip();
603#endif
e069c621 604 if (!_remote_url || !_remote_user || !_remote_ssh_privkey || strncmp(_remote_url, "ssh://", 5) != 0)
8085adf8
MG
605 clar__skip();
606
607 g_options.fetch_opts.callbacks.credentials = ssh_memory_cred_cb;
608
e069c621 609 cl_git_pass(git_clone(&g_repo, _remote_url, "./foo", &g_options));
8085adf8
MG
610}
611
f0c53d21 612void test_online_clone__url_with_no_path_returns_EINVALIDSPEC(void)
613{
614 cl_git_fail_with(git_clone(&g_repo, "http://github.com", "./foo", &g_options),
615 GIT_EINVALIDSPEC);
616}
85acc562 617
e6e834a1 618static int fail_certificate_check(git_cert *cert, int valid, const char *host, void *payload)
85acc562 619{
0782fc43 620 GIT_UNUSED(cert);
17491f6e 621 GIT_UNUSED(valid);
e6e834a1 622 GIT_UNUSED(host);
85acc562
CMN
623 GIT_UNUSED(payload);
624
23ca0ad5 625 return GIT_ECERTIFICATE;
85acc562
CMN
626}
627
628void test_online_clone__certificate_invalid(void)
629{
8f0104ec 630 g_options.fetch_opts.callbacks.certificate_check = fail_certificate_check;
85acc562 631
08545d36 632 cl_git_fail_with(git_clone(&g_repo, "https://github.com/libgit2/TestGitRepository", "./foo", &g_options),
17491f6e 633 GIT_ECERTIFICATE);
2f5864c5 634
08545d36 635#ifdef GIT_SSH
2f5864c5
CMN
636 cl_git_fail_with(git_clone(&g_repo, "ssh://github.com/libgit2/TestGitRepository", "./foo", &g_options),
637 GIT_ECERTIFICATE);
08545d36 638#endif
85acc562
CMN
639}
640
e6e834a1 641static int succeed_certificate_check(git_cert *cert, int valid, const char *host, void *payload)
85acc562 642{
0782fc43 643 GIT_UNUSED(cert);
17491f6e 644 GIT_UNUSED(valid);
85acc562
CMN
645 GIT_UNUSED(payload);
646
db3d169c
SS
647 cl_assert_equal_s("github.com", host);
648
23ca0ad5 649 return 0;
85acc562
CMN
650}
651
652void test_online_clone__certificate_valid(void)
653{
8f0104ec 654 g_options.fetch_opts.callbacks.certificate_check = succeed_certificate_check;
85acc562 655
08545d36 656 cl_git_pass(git_clone(&g_repo, "https://github.com/libgit2/TestGitRepository", "./foo", &g_options));
85acc562 657}
29e7ae5d
CMN
658
659void test_online_clone__start_with_http(void)
660{
8f0104ec 661 g_options.fetch_opts.callbacks.certificate_check = succeed_certificate_check;
29e7ae5d
CMN
662
663 cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options));
664}
07bd3e57
CMN
665
666static int called_proxy_creds;
667static int proxy_creds(git_cred **out, const char *url, const char *username, unsigned int allowed, void *payload)
668{
0bd77401 669 GIT_UNUSED(url);
07bd3e57 670 GIT_UNUSED(username);
0bd77401
ET
671 GIT_UNUSED(allowed);
672 GIT_UNUSED(payload);
07bd3e57
CMN
673
674 called_proxy_creds = 1;
675 return git_cred_userpass_plaintext_new(out, _remote_proxy_user, _remote_proxy_pass);
676}
677
678void test_online_clone__proxy_credentials_request(void)
679{
680 if (!_remote_proxy_url || !_remote_proxy_user || !_remote_proxy_pass)
681 cl_skip();
682
0d72f67f 683 g_options.fetch_opts.proxy_opts.type = GIT_PROXY_SPECIFIED;
07bd3e57
CMN
684 g_options.fetch_opts.proxy_opts.url = _remote_proxy_url;
685 g_options.fetch_opts.proxy_opts.credentials = proxy_creds;
686 called_proxy_creds = 0;
687 cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options));
688 cl_assert(called_proxy_creds);
689}
690
691void test_online_clone__proxy_credentials_in_url(void)
692{
693 if (!_remote_proxy_url)
694 cl_skip();
695
0d72f67f 696 g_options.fetch_opts.proxy_opts.type = GIT_PROXY_SPECIFIED;
07bd3e57 697 g_options.fetch_opts.proxy_opts.url = _remote_proxy_url;
07bd3e57
CMN
698 called_proxy_creds = 0;
699 cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options));
700 cl_assert(called_proxy_creds == 0);
701}