]>
Commit | Line | Data |
---|---|---|
abca927d JK |
1 | #!/bin/sh |
2 | ||
3 | test_description='basic credential helper tests' | |
4 | . ./test-lib.sh | |
5 | . "$TEST_DIRECTORY"/lib-credential.sh | |
6 | ||
7 | test_expect_success 'setup helper scripts' ' | |
8 | cat >dump <<-\EOF && | |
dd64267f | 9 | whoami=$(echo $0 | sed s/.*git-credential-//) |
abca927d | 10 | echo >&2 "$whoami: $*" |
78ed1d2d MG |
11 | OIFS=$IFS |
12 | IFS== | |
13 | while read key value; do | |
abca927d | 14 | echo >&2 "$whoami: $key=$value" |
ca9ccbf6 | 15 | if test -z "${key%%*\[\]}" |
16 | then | |
17 | key=${key%%\[\]} | |
18 | eval "$key=\"\$$key $value\"" | |
19 | else | |
20 | eval "$key=$value" | |
21 | fi | |
abca927d | 22 | done |
78ed1d2d | 23 | IFS=$OIFS |
abca927d JK |
24 | EOF |
25 | ||
3d9f5b67 | 26 | write_script git-credential-useless <<-\EOF && |
abca927d JK |
27 | . ./dump |
28 | exit 0 | |
29 | EOF | |
abca927d | 30 | |
a88dbd2f JK |
31 | write_script git-credential-quit <<-\EOF && |
32 | . ./dump | |
33 | echo quit=1 | |
34 | EOF | |
35 | ||
3d9f5b67 | 36 | write_script git-credential-verbatim <<-\EOF && |
abca927d JK |
37 | user=$1; shift |
38 | pass=$1; shift | |
39 | . ./dump | |
40 | test -z "$user" || echo username=$user | |
41 | test -z "$pass" || echo password=$pass | |
42 | EOF | |
abca927d | 43 | |
ca9ccbf6 | 44 | write_script git-credential-verbatim-cred <<-\EOF && |
45 | authtype=$1; shift | |
46 | credential=$1; shift | |
47 | . ./dump | |
48 | echo capability[]=authtype | |
49 | test -z "${capability##*authtype*}" || exit 0 | |
50 | test -z "$authtype" || echo authtype=$authtype | |
51 | test -z "$credential" || echo credential=$credential | |
52 | EOF | |
53 | ||
d208bfdf H |
54 | write_script git-credential-verbatim-with-expiry <<-\EOF && |
55 | user=$1; shift | |
56 | pass=$1; shift | |
57 | pexpiry=$1; shift | |
58 | . ./dump | |
59 | test -z "$user" || echo username=$user | |
60 | test -z "$pass" || echo password=$pass | |
61 | test -z "$pexpiry" || echo password_expiry_utc=$pexpiry | |
62 | EOF | |
63 | ||
abca927d JK |
64 | PATH="$PWD:$PATH" |
65 | ' | |
66 | ||
67 | test_expect_success 'credential_fill invokes helper' ' | |
68 | check fill "verbatim foo bar" <<-\EOF | |
73aafe9b JK |
69 | protocol=http |
70 | host=example.com | |
abca927d | 71 | -- |
73aafe9b JK |
72 | protocol=http |
73 | host=example.com | |
abca927d JK |
74 | username=foo |
75 | password=bar | |
76 | -- | |
77 | verbatim: get | |
73aafe9b JK |
78 | verbatim: protocol=http |
79 | verbatim: host=example.com | |
abca927d JK |
80 | EOF |
81 | ' | |
82 | ||
ca9ccbf6 | 83 | test_expect_success 'credential_fill invokes helper with credential' ' |
84 | check fill "verbatim-cred Bearer token" <<-\EOF | |
85 | capability[]=authtype | |
86 | protocol=http | |
87 | host=example.com | |
88 | -- | |
89 | capability[]=authtype | |
90 | authtype=Bearer | |
91 | credential=token | |
92 | protocol=http | |
93 | host=example.com | |
94 | -- | |
95 | verbatim-cred: get | |
96 | verbatim-cred: capability[]=authtype | |
97 | verbatim-cred: protocol=http | |
98 | verbatim-cred: host=example.com | |
99 | EOF | |
100 | ' | |
101 | ||
102 | ||
abca927d JK |
103 | test_expect_success 'credential_fill invokes multiple helpers' ' |
104 | check fill useless "verbatim foo bar" <<-\EOF | |
73aafe9b JK |
105 | protocol=http |
106 | host=example.com | |
abca927d | 107 | -- |
73aafe9b JK |
108 | protocol=http |
109 | host=example.com | |
abca927d JK |
110 | username=foo |
111 | password=bar | |
112 | -- | |
113 | useless: get | |
73aafe9b JK |
114 | useless: protocol=http |
115 | useless: host=example.com | |
abca927d | 116 | verbatim: get |
73aafe9b JK |
117 | verbatim: protocol=http |
118 | verbatim: host=example.com | |
abca927d JK |
119 | EOF |
120 | ' | |
121 | ||
ca9ccbf6 | 122 | test_expect_success 'credential_fill response does not get capabilities when helpers are incapable' ' |
123 | check fill useless "verbatim foo bar" <<-\EOF | |
124 | capability[]=authtype | |
125 | protocol=http | |
126 | host=example.com | |
127 | -- | |
128 | protocol=http | |
129 | host=example.com | |
130 | username=foo | |
131 | password=bar | |
132 | -- | |
133 | useless: get | |
134 | useless: capability[]=authtype | |
135 | useless: protocol=http | |
136 | useless: host=example.com | |
137 | verbatim: get | |
138 | verbatim: capability[]=authtype | |
139 | verbatim: protocol=http | |
140 | verbatim: host=example.com | |
141 | EOF | |
142 | ' | |
143 | ||
144 | test_expect_success 'credential_fill response does not get capabilities when caller is incapable' ' | |
145 | check fill "verbatim-cred Bearer token" <<-\EOF | |
146 | protocol=http | |
147 | host=example.com | |
148 | -- | |
149 | protocol=http | |
150 | host=example.com | |
151 | -- | |
152 | verbatim-cred: get | |
153 | verbatim-cred: protocol=http | |
154 | verbatim-cred: host=example.com | |
155 | EOF | |
156 | ' | |
157 | ||
abca927d JK |
158 | test_expect_success 'credential_fill stops when we get a full response' ' |
159 | check fill "verbatim one two" "verbatim three four" <<-\EOF | |
73aafe9b JK |
160 | protocol=http |
161 | host=example.com | |
abca927d | 162 | -- |
73aafe9b JK |
163 | protocol=http |
164 | host=example.com | |
abca927d JK |
165 | username=one |
166 | password=two | |
167 | -- | |
168 | verbatim: get | |
73aafe9b JK |
169 | verbatim: protocol=http |
170 | verbatim: host=example.com | |
abca927d JK |
171 | EOF |
172 | ' | |
173 | ||
ca9ccbf6 | 174 | test_expect_success 'credential_fill thinks a credential is a full response' ' |
175 | check fill "verbatim-cred Bearer token" "verbatim three four" <<-\EOF | |
176 | capability[]=authtype | |
177 | protocol=http | |
178 | host=example.com | |
179 | -- | |
180 | capability[]=authtype | |
181 | authtype=Bearer | |
182 | credential=token | |
183 | protocol=http | |
184 | host=example.com | |
185 | -- | |
186 | verbatim-cred: get | |
187 | verbatim-cred: capability[]=authtype | |
188 | verbatim-cred: protocol=http | |
189 | verbatim-cred: host=example.com | |
190 | EOF | |
191 | ' | |
192 | ||
abca927d JK |
193 | test_expect_success 'credential_fill continues through partial response' ' |
194 | check fill "verbatim one \"\"" "verbatim two three" <<-\EOF | |
73aafe9b JK |
195 | protocol=http |
196 | host=example.com | |
abca927d | 197 | -- |
73aafe9b JK |
198 | protocol=http |
199 | host=example.com | |
abca927d JK |
200 | username=two |
201 | password=three | |
202 | -- | |
203 | verbatim: get | |
73aafe9b JK |
204 | verbatim: protocol=http |
205 | verbatim: host=example.com | |
abca927d | 206 | verbatim: get |
73aafe9b JK |
207 | verbatim: protocol=http |
208 | verbatim: host=example.com | |
abca927d JK |
209 | verbatim: username=one |
210 | EOF | |
211 | ' | |
212 | ||
d208bfdf H |
213 | test_expect_success 'credential_fill populates password_expiry_utc' ' |
214 | check fill "verbatim-with-expiry one two 9999999999" <<-\EOF | |
215 | protocol=http | |
216 | host=example.com | |
217 | -- | |
218 | protocol=http | |
219 | host=example.com | |
220 | username=one | |
221 | password=two | |
222 | password_expiry_utc=9999999999 | |
223 | -- | |
224 | verbatim-with-expiry: get | |
225 | verbatim-with-expiry: protocol=http | |
226 | verbatim-with-expiry: host=example.com | |
227 | EOF | |
228 | ' | |
229 | ||
230 | test_expect_success 'credential_fill ignores expired password' ' | |
231 | check fill "verbatim-with-expiry one two 5" "verbatim three four" <<-\EOF | |
232 | protocol=http | |
233 | host=example.com | |
234 | -- | |
235 | protocol=http | |
236 | host=example.com | |
237 | username=three | |
238 | password=four | |
239 | -- | |
240 | verbatim-with-expiry: get | |
241 | verbatim-with-expiry: protocol=http | |
242 | verbatim-with-expiry: host=example.com | |
243 | verbatim: get | |
244 | verbatim: protocol=http | |
245 | verbatim: host=example.com | |
246 | verbatim: username=one | |
247 | EOF | |
248 | ' | |
249 | ||
abca927d JK |
250 | test_expect_success 'credential_fill passes along metadata' ' |
251 | check fill "verbatim one two" <<-\EOF | |
252 | protocol=ftp | |
253 | host=example.com | |
254 | path=foo.git | |
255 | -- | |
2d6dc182 MM |
256 | protocol=ftp |
257 | host=example.com | |
258 | path=foo.git | |
abca927d JK |
259 | username=one |
260 | password=two | |
261 | -- | |
262 | verbatim: get | |
263 | verbatim: protocol=ftp | |
264 | verbatim: host=example.com | |
265 | verbatim: path=foo.git | |
266 | EOF | |
267 | ' | |
268 | ||
ca9ccbf6 | 269 | test_expect_success 'credential_fill produces no credential without capability' ' |
270 | check fill "verbatim-cred Bearer token" <<-\EOF | |
271 | protocol=http | |
272 | host=example.com | |
273 | -- | |
274 | protocol=http | |
275 | host=example.com | |
276 | -- | |
277 | verbatim-cred: get | |
278 | verbatim-cred: protocol=http | |
279 | verbatim-cred: host=example.com | |
280 | EOF | |
281 | ' | |
282 | ||
abca927d JK |
283 | test_expect_success 'credential_approve calls all helpers' ' |
284 | check approve useless "verbatim one two" <<-\EOF | |
73aafe9b JK |
285 | protocol=http |
286 | host=example.com | |
abca927d JK |
287 | username=foo |
288 | password=bar | |
289 | -- | |
290 | -- | |
291 | useless: store | |
73aafe9b JK |
292 | useless: protocol=http |
293 | useless: host=example.com | |
abca927d JK |
294 | useless: username=foo |
295 | useless: password=bar | |
296 | verbatim: store | |
73aafe9b JK |
297 | verbatim: protocol=http |
298 | verbatim: host=example.com | |
abca927d JK |
299 | verbatim: username=foo |
300 | verbatim: password=bar | |
301 | EOF | |
302 | ' | |
303 | ||
d208bfdf H |
304 | test_expect_success 'credential_approve stores password expiry' ' |
305 | check approve useless <<-\EOF | |
306 | protocol=http | |
307 | host=example.com | |
308 | username=foo | |
309 | password=bar | |
310 | password_expiry_utc=9999999999 | |
311 | -- | |
312 | -- | |
313 | useless: store | |
314 | useless: protocol=http | |
315 | useless: host=example.com | |
316 | useless: username=foo | |
317 | useless: password=bar | |
318 | useless: password_expiry_utc=9999999999 | |
319 | EOF | |
320 | ' | |
321 | ||
a5c76569 H |
322 | test_expect_success 'credential_approve stores oauth refresh token' ' |
323 | check approve useless <<-\EOF | |
324 | protocol=http | |
325 | host=example.com | |
326 | username=foo | |
327 | password=bar | |
328 | oauth_refresh_token=xyzzy | |
329 | -- | |
330 | -- | |
331 | useless: store | |
332 | useless: protocol=http | |
333 | useless: host=example.com | |
334 | useless: username=foo | |
335 | useless: password=bar | |
336 | useless: oauth_refresh_token=xyzzy | |
337 | EOF | |
338 | ' | |
339 | ||
abca927d JK |
340 | test_expect_success 'do not bother storing password-less credential' ' |
341 | check approve useless <<-\EOF | |
73aafe9b JK |
342 | protocol=http |
343 | host=example.com | |
abca927d JK |
344 | username=foo |
345 | -- | |
346 | -- | |
347 | EOF | |
348 | ' | |
349 | ||
d208bfdf H |
350 | test_expect_success 'credential_approve does not store expired password' ' |
351 | check approve useless <<-\EOF | |
352 | protocol=http | |
353 | host=example.com | |
354 | username=foo | |
355 | password=bar | |
356 | password_expiry_utc=5 | |
357 | -- | |
358 | -- | |
359 | EOF | |
360 | ' | |
abca927d JK |
361 | |
362 | test_expect_success 'credential_reject calls all helpers' ' | |
363 | check reject useless "verbatim one two" <<-\EOF | |
73aafe9b JK |
364 | protocol=http |
365 | host=example.com | |
abca927d JK |
366 | username=foo |
367 | password=bar | |
368 | -- | |
369 | -- | |
370 | useless: erase | |
73aafe9b JK |
371 | useless: protocol=http |
372 | useless: host=example.com | |
abca927d JK |
373 | useless: username=foo |
374 | useless: password=bar | |
375 | verbatim: erase | |
73aafe9b JK |
376 | verbatim: protocol=http |
377 | verbatim: host=example.com | |
abca927d JK |
378 | verbatim: username=foo |
379 | verbatim: password=bar | |
380 | EOF | |
381 | ' | |
382 | ||
d208bfdf H |
383 | test_expect_success 'credential_reject erases credential regardless of expiry' ' |
384 | check reject useless <<-\EOF | |
385 | protocol=http | |
386 | host=example.com | |
387 | username=foo | |
388 | password=bar | |
389 | password_expiry_utc=5 | |
390 | -- | |
391 | -- | |
392 | useless: erase | |
393 | useless: protocol=http | |
394 | useless: host=example.com | |
395 | useless: username=foo | |
396 | useless: password=bar | |
397 | useless: password_expiry_utc=5 | |
398 | EOF | |
399 | ' | |
400 | ||
abca927d JK |
401 | test_expect_success 'usernames can be preserved' ' |
402 | check fill "verbatim \"\" three" <<-\EOF | |
73aafe9b JK |
403 | protocol=http |
404 | host=example.com | |
abca927d JK |
405 | username=one |
406 | -- | |
73aafe9b JK |
407 | protocol=http |
408 | host=example.com | |
abca927d JK |
409 | username=one |
410 | password=three | |
411 | -- | |
412 | verbatim: get | |
73aafe9b JK |
413 | verbatim: protocol=http |
414 | verbatim: host=example.com | |
abca927d JK |
415 | verbatim: username=one |
416 | EOF | |
417 | ' | |
418 | ||
419 | test_expect_success 'usernames can be overridden' ' | |
420 | check fill "verbatim two three" <<-\EOF | |
73aafe9b JK |
421 | protocol=http |
422 | host=example.com | |
abca927d JK |
423 | username=one |
424 | -- | |
73aafe9b JK |
425 | protocol=http |
426 | host=example.com | |
abca927d JK |
427 | username=two |
428 | password=three | |
429 | -- | |
430 | verbatim: get | |
73aafe9b JK |
431 | verbatim: protocol=http |
432 | verbatim: host=example.com | |
abca927d JK |
433 | verbatim: username=one |
434 | EOF | |
435 | ' | |
436 | ||
437 | test_expect_success 'do not bother completing already-full credential' ' | |
438 | check fill "verbatim three four" <<-\EOF | |
73aafe9b JK |
439 | protocol=http |
440 | host=example.com | |
abca927d JK |
441 | username=one |
442 | password=two | |
443 | -- | |
73aafe9b JK |
444 | protocol=http |
445 | host=example.com | |
abca927d JK |
446 | username=one |
447 | password=two | |
448 | -- | |
449 | EOF | |
450 | ' | |
451 | ||
452 | # We can't test the basic terminal password prompt here because | |
453 | # getpass() tries too hard to find the real terminal. But if our | |
454 | # askpass helper is run, we know the internal getpass is working. | |
455 | test_expect_success 'empty helper list falls back to internal getpass' ' | |
456 | check fill <<-\EOF | |
73aafe9b JK |
457 | protocol=http |
458 | host=example.com | |
abca927d | 459 | -- |
73aafe9b JK |
460 | protocol=http |
461 | host=example.com | |
abca927d JK |
462 | username=askpass-username |
463 | password=askpass-password | |
464 | -- | |
73aafe9b JK |
465 | askpass: Username for '\''http://example.com'\'': |
466 | askpass: Password for '\''http://askpass-username@example.com'\'': | |
abca927d JK |
467 | EOF |
468 | ' | |
469 | ||
470 | test_expect_success 'internal getpass does not ask for known username' ' | |
471 | check fill <<-\EOF | |
73aafe9b JK |
472 | protocol=http |
473 | host=example.com | |
abca927d JK |
474 | username=foo |
475 | -- | |
73aafe9b JK |
476 | protocol=http |
477 | host=example.com | |
abca927d JK |
478 | username=foo |
479 | password=askpass-password | |
480 | -- | |
73aafe9b | 481 | askpass: Password for '\''http://foo@example.com'\'': |
abca927d JK |
482 | EOF |
483 | ' | |
484 | ||
567ad2c0 TK |
485 | test_expect_success 'git-credential respects core.askPass' ' |
486 | write_script alternate-askpass <<-\EOF && | |
487 | echo >&2 "alternate askpass invoked" | |
488 | echo alternate-value | |
489 | EOF | |
490 | test_config core.askpass "$PWD/alternate-askpass" && | |
491 | ( | |
492 | # unset GIT_ASKPASS set by lib-credential.sh which would | |
493 | # override our config, but do so in a subshell so that we do | |
494 | # not interfere with other tests | |
495 | sane_unset GIT_ASKPASS && | |
496 | check fill <<-\EOF | |
497 | protocol=http | |
498 | host=example.com | |
499 | -- | |
500 | protocol=http | |
501 | host=example.com | |
502 | username=alternate-value | |
503 | password=alternate-value | |
504 | -- | |
505 | alternate askpass invoked | |
506 | alternate askpass invoked | |
507 | EOF | |
508 | ) | |
509 | ' | |
510 | ||
11825072 JK |
511 | HELPER="!f() { |
512 | cat >/dev/null | |
513 | echo username=foo | |
514 | echo password=bar | |
515 | }; f" | |
516 | test_expect_success 'respect configured credentials' ' | |
517 | test_config credential.helper "$HELPER" && | |
518 | check fill <<-\EOF | |
73aafe9b JK |
519 | protocol=http |
520 | host=example.com | |
11825072 | 521 | -- |
73aafe9b JK |
522 | protocol=http |
523 | host=example.com | |
11825072 JK |
524 | username=foo |
525 | password=bar | |
526 | -- | |
527 | EOF | |
528 | ' | |
529 | ||
530 | test_expect_success 'match configured credential' ' | |
531 | test_config credential.https://example.com.helper "$HELPER" && | |
532 | check fill <<-\EOF | |
533 | protocol=https | |
534 | host=example.com | |
535 | path=repo.git | |
536 | -- | |
2d6dc182 MM |
537 | protocol=https |
538 | host=example.com | |
11825072 JK |
539 | username=foo |
540 | password=bar | |
541 | -- | |
542 | EOF | |
543 | ' | |
544 | ||
545 | test_expect_success 'do not match configured credential' ' | |
546 | test_config credential.https://foo.helper "$HELPER" && | |
547 | check fill <<-\EOF | |
548 | protocol=https | |
549 | host=bar | |
550 | -- | |
2d6dc182 MM |
551 | protocol=https |
552 | host=bar | |
11825072 JK |
553 | username=askpass-username |
554 | password=askpass-password | |
555 | -- | |
556 | askpass: Username for '\''https://bar'\'': | |
557 | askpass: Password for '\''https://askpass-username@bar'\'': | |
558 | EOF | |
559 | ' | |
560 | ||
588c70e1 | 561 | test_expect_success 'match multiple configured helpers' ' |
562 | test_config credential.helper "verbatim \"\" \"\"" && | |
563 | test_config credential.https://example.com.helper "$HELPER" && | |
564 | check fill <<-\EOF | |
565 | protocol=https | |
566 | host=example.com | |
567 | path=repo.git | |
568 | -- | |
569 | protocol=https | |
570 | host=example.com | |
571 | username=foo | |
572 | password=bar | |
573 | -- | |
574 | verbatim: get | |
575 | verbatim: protocol=https | |
576 | verbatim: host=example.com | |
577 | EOF | |
578 | ' | |
579 | ||
580 | test_expect_success 'match multiple configured helpers with URLs' ' | |
581 | test_config credential.https://example.com/repo.git.helper "verbatim \"\" \"\"" && | |
582 | test_config credential.https://example.com.helper "$HELPER" && | |
583 | check fill <<-\EOF | |
584 | protocol=https | |
585 | host=example.com | |
586 | path=repo.git | |
587 | -- | |
588 | protocol=https | |
589 | host=example.com | |
590 | username=foo | |
591 | password=bar | |
592 | -- | |
593 | verbatim: get | |
594 | verbatim: protocol=https | |
595 | verbatim: host=example.com | |
596 | EOF | |
597 | ' | |
598 | ||
599 | test_expect_success 'match percent-encoded values' ' | |
600 | test_config credential.https://example.com/%2566.git.helper "$HELPER" && | |
601 | check fill <<-\EOF | |
602 | url=https://example.com/%2566.git | |
603 | -- | |
604 | protocol=https | |
605 | host=example.com | |
606 | username=foo | |
607 | password=bar | |
608 | -- | |
609 | EOF | |
610 | ' | |
611 | ||
b44d0118 | 612 | test_expect_success 'match percent-encoded UTF-8 values in path' ' |
613 | test_config credential.https://example.com.useHttpPath true && | |
614 | test_config credential.https://example.com/perú.git.helper "$HELPER" && | |
615 | check fill <<-\EOF | |
616 | url=https://example.com/per%C3%BA.git | |
617 | -- | |
618 | protocol=https | |
619 | host=example.com | |
620 | path=perú.git | |
621 | username=foo | |
622 | password=bar | |
623 | -- | |
624 | EOF | |
625 | ' | |
626 | ||
627 | test_expect_success 'match percent-encoded values in username' ' | |
628 | test_config credential.https://user%2fname@example.com/foo/bar.git.helper "$HELPER" && | |
629 | check fill <<-\EOF | |
630 | url=https://user%2fname@example.com/foo/bar.git | |
631 | -- | |
632 | protocol=https | |
633 | host=example.com | |
634 | username=foo | |
635 | password=bar | |
636 | -- | |
637 | EOF | |
638 | ' | |
639 | ||
640 | test_expect_success 'fetch with multiple path components' ' | |
641 | test_unconfig credential.helper && | |
642 | test_config credential.https://example.com/foo/repo.git.helper "verbatim foo bar" && | |
643 | check fill <<-\EOF | |
644 | url=https://example.com/foo/repo.git | |
645 | -- | |
646 | protocol=https | |
647 | host=example.com | |
648 | username=foo | |
649 | password=bar | |
650 | -- | |
651 | verbatim: get | |
652 | verbatim: protocol=https | |
653 | verbatim: host=example.com | |
654 | EOF | |
655 | ' | |
656 | ||
d5742425 JK |
657 | test_expect_success 'pull username from config' ' |
658 | test_config credential.https://example.com.username foo && | |
659 | check fill <<-\EOF | |
660 | protocol=https | |
661 | host=example.com | |
662 | -- | |
2d6dc182 MM |
663 | protocol=https |
664 | host=example.com | |
d5742425 JK |
665 | username=foo |
666 | password=askpass-password | |
667 | -- | |
668 | askpass: Password for '\''https://foo@example.com'\'': | |
669 | EOF | |
670 | ' | |
671 | ||
588c70e1 | 672 | test_expect_success 'honors username from URL over helper (URL)' ' |
673 | test_config credential.https://example.com.username bob && | |
674 | test_config credential.https://example.com.helper "verbatim \"\" bar" && | |
675 | check fill <<-\EOF | |
676 | url=https://alice@example.com | |
677 | -- | |
678 | protocol=https | |
679 | host=example.com | |
680 | username=alice | |
681 | password=bar | |
682 | -- | |
683 | verbatim: get | |
684 | verbatim: protocol=https | |
685 | verbatim: host=example.com | |
686 | verbatim: username=alice | |
687 | EOF | |
688 | ' | |
689 | ||
690 | test_expect_success 'honors username from URL over helper (components)' ' | |
691 | test_config credential.https://example.com.username bob && | |
692 | test_config credential.https://example.com.helper "verbatim \"\" bar" && | |
693 | check fill <<-\EOF | |
694 | protocol=https | |
695 | host=example.com | |
696 | username=alice | |
697 | -- | |
698 | protocol=https | |
699 | host=example.com | |
700 | username=alice | |
701 | password=bar | |
702 | -- | |
703 | verbatim: get | |
704 | verbatim: protocol=https | |
705 | verbatim: host=example.com | |
706 | verbatim: username=alice | |
707 | EOF | |
708 | ' | |
709 | ||
82eb2498 | 710 | test_expect_success 'last matching username wins' ' |
588c70e1 | 711 | test_config credential.https://example.com/path.git.username bob && |
712 | test_config credential.https://example.com.username alice && | |
713 | test_config credential.https://example.com.helper "verbatim \"\" bar" && | |
714 | check fill <<-\EOF | |
715 | url=https://example.com/path.git | |
716 | -- | |
717 | protocol=https | |
718 | host=example.com | |
719 | username=alice | |
720 | password=bar | |
721 | -- | |
722 | verbatim: get | |
723 | verbatim: protocol=https | |
724 | verbatim: host=example.com | |
725 | verbatim: username=alice | |
726 | EOF | |
727 | ' | |
728 | ||
a78fbb4f JK |
729 | test_expect_success 'http paths can be part of context' ' |
730 | check fill "verbatim foo bar" <<-\EOF && | |
731 | protocol=https | |
732 | host=example.com | |
733 | path=foo.git | |
734 | -- | |
2d6dc182 MM |
735 | protocol=https |
736 | host=example.com | |
a78fbb4f JK |
737 | username=foo |
738 | password=bar | |
739 | -- | |
740 | verbatim: get | |
741 | verbatim: protocol=https | |
742 | verbatim: host=example.com | |
743 | EOF | |
744 | test_config credential.https://example.com.useHttpPath true && | |
745 | check fill "verbatim foo bar" <<-\EOF | |
746 | protocol=https | |
747 | host=example.com | |
748 | path=foo.git | |
749 | -- | |
2d6dc182 MM |
750 | protocol=https |
751 | host=example.com | |
752 | path=foo.git | |
a78fbb4f JK |
753 | username=foo |
754 | password=bar | |
755 | -- | |
756 | verbatim: get | |
757 | verbatim: protocol=https | |
758 | verbatim: host=example.com | |
759 | verbatim: path=foo.git | |
760 | EOF | |
761 | ' | |
762 | ||
46fd7b39 | 763 | test_expect_success 'context uses urlmatch' ' |
764 | test_config "credential.https://*.org.useHttpPath" true && | |
765 | check fill "verbatim foo bar" <<-\EOF | |
766 | protocol=https | |
767 | host=example.org | |
768 | path=foo.git | |
769 | -- | |
770 | protocol=https | |
771 | host=example.org | |
772 | path=foo.git | |
773 | username=foo | |
774 | password=bar | |
775 | -- | |
776 | verbatim: get | |
777 | verbatim: protocol=https | |
778 | verbatim: host=example.org | |
779 | verbatim: path=foo.git | |
780 | EOF | |
781 | ' | |
782 | ||
59b38652 JK |
783 | test_expect_success 'helpers can abort the process' ' |
784 | test_must_fail git \ | |
a88dbd2f | 785 | -c credential.helper=quit \ |
59b38652 | 786 | -c credential.helper="verbatim foo bar" \ |
73aafe9b JK |
787 | credential fill >stdout 2>stderr <<-\EOF && |
788 | protocol=http | |
789 | host=example.com | |
790 | EOF | |
76b54ee9 | 791 | test_must_be_empty stdout && |
a88dbd2f JK |
792 | cat >expect <<-\EOF && |
793 | quit: get | |
73aafe9b JK |
794 | quit: protocol=http |
795 | quit: host=example.com | |
a88dbd2f JK |
796 | fatal: credential helper '\''quit'\'' told us to quit |
797 | EOF | |
1108cea7 | 798 | test_cmp expect stderr |
59b38652 JK |
799 | ' |
800 | ||
24321375 JK |
801 | test_expect_success 'empty helper spec resets helper list' ' |
802 | test_config credential.helper "verbatim file file" && | |
803 | check fill "" "verbatim cmdline cmdline" <<-\EOF | |
73aafe9b JK |
804 | protocol=http |
805 | host=example.com | |
24321375 | 806 | -- |
73aafe9b JK |
807 | protocol=http |
808 | host=example.com | |
24321375 JK |
809 | username=cmdline |
810 | password=cmdline | |
811 | -- | |
812 | verbatim: get | |
73aafe9b JK |
813 | verbatim: protocol=http |
814 | verbatim: host=example.com | |
24321375 JK |
815 | EOF |
816 | ' | |
817 | ||
8ba8ed56 JK |
818 | test_expect_success 'url parser rejects embedded newlines' ' |
819 | test_must_fail git credential fill 2>stderr <<-\EOF && | |
9a6bbee8 | 820 | url=https://one.example.com?%0ahost=two.example.com/ |
8ba8ed56 JK |
821 | EOF |
822 | cat >expect <<-\EOF && | |
a397e9c2 | 823 | warning: url contains a newline in its path component: https://one.example.com?%0ahost=two.example.com/ |
fe29a9b7 | 824 | fatal: credential url cannot be parsed: https://one.example.com?%0ahost=two.example.com/ |
9a6bbee8 | 825 | EOF |
1108cea7 | 826 | test_cmp expect stderr |
9a6bbee8 JK |
827 | ' |
828 | ||
24036686 JK |
829 | test_expect_success 'host-less URLs are parsed as empty host' ' |
830 | check fill "verbatim foo bar" <<-\EOF | |
831 | url=cert:///path/to/cert.pem | |
c716fe4b | 832 | -- |
24036686 JK |
833 | protocol=cert |
834 | host= | |
835 | path=path/to/cert.pem | |
836 | username=foo | |
837 | password=bar | |
c716fe4b | 838 | -- |
24036686 JK |
839 | verbatim: get |
840 | verbatim: protocol=cert | |
841 | verbatim: host= | |
842 | verbatim: path=path/to/cert.pem | |
843 | EOF | |
844 | ' | |
845 | ||
8ba8ed56 JK |
846 | test_expect_success 'credential system refuses to work with missing host' ' |
847 | test_must_fail git credential fill 2>stderr <<-\EOF && | |
848 | protocol=http | |
849 | EOF | |
850 | cat >expect <<-\EOF && | |
851 | fatal: refusing to work with credential missing host field | |
852 | EOF | |
1108cea7 | 853 | test_cmp expect stderr |
8ba8ed56 JK |
854 | ' |
855 | ||
856 | test_expect_success 'credential system refuses to work with missing protocol' ' | |
857 | test_must_fail git credential fill 2>stderr <<-\EOF && | |
858 | host=example.com | |
859 | EOF | |
860 | cat >expect <<-\EOF && | |
861 | fatal: refusing to work with credential missing protocol field | |
9a6bbee8 | 862 | EOF |
1108cea7 | 863 | test_cmp expect stderr |
9a6bbee8 JK |
864 | ' |
865 | ||
4c5971e1 JK |
866 | # usage: check_host_and_path <url> <expected-host> <expected-path> |
867 | check_host_and_path () { | |
868 | # we always parse the path component, but we need this to make sure it | |
869 | # is passed to the helper | |
870 | test_config credential.useHTTPPath true && | |
871 | check fill "verbatim user pass" <<-EOF | |
872 | url=$1 | |
873 | -- | |
874 | protocol=https | |
875 | host=$2 | |
876 | path=$3 | |
877 | username=user | |
878 | password=pass | |
879 | -- | |
880 | verbatim: get | |
881 | verbatim: protocol=https | |
882 | verbatim: host=$2 | |
883 | verbatim: path=$3 | |
884 | EOF | |
885 | } | |
886 | ||
887 | test_expect_success 'url parser handles bare query marker' ' | |
888 | check_host_and_path https://example.com?foo.git example.com ?foo.git | |
889 | ' | |
890 | ||
891 | test_expect_success 'url parser handles bare fragment marker' ' | |
892 | check_host_and_path https://example.com#foo.git example.com "#foo.git" | |
893 | ' | |
894 | ||
895 | test_expect_success 'url parser not confused by encoded markers' ' | |
896 | check_host_and_path https://example.com%23%3f%2f/foo.git \ | |
897 | "example.com#?/" foo.git | |
898 | ' | |
899 | ||
9a121b0d JS |
900 | test_expect_success 'credential config with partial URLs' ' |
901 | echo "echo password=yep" | write_script git-credential-yep && | |
902 | test_write_lines url=https://user@example.com/repo.git >stdin && | |
903 | for partial in \ | |
904 | example.com \ | |
905 | user@example.com \ | |
906 | https:// \ | |
907 | https://example.com \ | |
908 | https://example.com/ \ | |
909 | https://user@example.com \ | |
910 | https://user@example.com/ \ | |
911 | https://example.com/repo.git \ | |
912 | https://user@example.com/repo.git \ | |
913 | /repo.git | |
914 | do | |
915 | git -c credential.$partial.helper=yep \ | |
916 | credential fill <stdin >stdout && | |
917 | grep yep stdout || | |
918 | return 1 | |
919 | done && | |
920 | ||
921 | for partial in \ | |
922 | dont.use.this \ | |
923 | http:// \ | |
924 | /repo | |
925 | do | |
926 | git -c credential.$partial.helper=yep \ | |
927 | credential fill <stdin >stdout && | |
928 | ! grep yep stdout || | |
929 | return 1 | |
930 | done && | |
931 | ||
932 | git -c credential.$partial.helper=yep \ | |
933 | -c credential.with%0anewline.username=uh-oh \ | |
ed5288cf | 934 | credential fill <stdin 2>stderr && |
6789275d | 935 | test_grep "skipping credential lookup for key" stderr |
9a121b0d JS |
936 | ' |
937 | ||
abca927d | 938 | test_done |