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