| @@ -1,16 +1,16 @@ | | | @@ -1,16 +1,16 @@ |
1 | #!/bin/sh | | 1 | #!/bin/sh |
2 | | | 2 | |
3 | # $NetBSD: certctl.sh,v 1.4.2.3 2023/09/06 15:04:33 martin Exp $ | | 3 | # $NetBSD: certctl.sh,v 1.4.2.4 2024/03/11 17:12:53 martin Exp $ |
4 | # | | 4 | # |
5 | # Copyright (c) 2023 The NetBSD Foundation, Inc. | | 5 | # Copyright (c) 2023 The NetBSD Foundation, Inc. |
6 | # All rights reserved. | | 6 | # All rights reserved. |
7 | # | | 7 | # |
8 | # Redistribution and use in source and binary forms, with or without | | 8 | # Redistribution and use in source and binary forms, with or without |
9 | # modification, are permitted provided that the following conditions | | 9 | # modification, are permitted provided that the following conditions |
10 | # are met: | | 10 | # are met: |
11 | # 1. Redistributions of source code must retain the above copyright | | 11 | # 1. Redistributions of source code must retain the above copyright |
12 | # notice, this list of conditions and the following disclaimer. | | 12 | # notice, this list of conditions and the following disclaimer. |
13 | # 2. Redistributions in binary form must reproduce the above copyright | | 13 | # 2. Redistributions in binary form must reproduce the above copyright |
14 | # notice, this list of conditions and the following disclaimer in the | | 14 | # notice, this list of conditions and the following disclaimer in the |
15 | # documentation and/or other materials provided with the distribution. | | 15 | # documentation and/or other materials provided with the distribution. |
16 | # | | 16 | # |
| @@ -20,27 +20,27 @@ | | | @@ -20,27 +20,27 @@ |
20 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 20 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
21 | # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 21 | # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
22 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 22 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
23 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 23 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
24 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 24 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
25 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 25 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
26 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 26 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
27 | # POSSIBILITY OF SUCH DAMAGE. | | 27 | # POSSIBILITY OF SUCH DAMAGE. |
28 | # | | 28 | # |
29 | | | 29 | |
30 | set -o pipefail | | 30 | set -o pipefail |
31 | set -Ceu | | 31 | set -Ceu |
32 | | | 32 | |
33 | progname=$(basename -- "$0") | | 33 | progname=${0##*/} |
34 | | | 34 | |
35 | ### Options and arguments | | 35 | ### Options and arguments |
36 | | | 36 | |
37 | usage() | | 37 | usage() |
38 | { | | 38 | { |
39 | exec >&2 | | 39 | exec >&2 |
40 | printf 'Usage: %s %s\n' \ | | 40 | printf 'Usage: %s %s\n' \ |
41 | "$progname" \ | | 41 | "$progname" \ |
42 | "[-nv] [-C <config>] [-c <certsdir>] [-u <untrusted>]" | | 42 | "[-nv] [-C <config>] [-c <certsdir>] [-u <untrusted>]" |
43 | printf ' <cmd> <args>...\n' | | 43 | printf ' <cmd> <args>...\n' |
44 | printf ' %s list\n' "$progname" | | 44 | printf ' %s list\n' "$progname" |
45 | printf ' %s rehash\n' "$progname" | | 45 | printf ' %s rehash\n' "$progname" |
46 | printf ' %s trust <cert>\n' "$progname" | | 46 | printf ' %s trust <cert>\n' "$progname" |
| @@ -266,28 +266,27 @@ list_default_trusted() | | | @@ -266,28 +266,27 @@ list_default_trusted() |
266 | # or | | 266 | # or |
267 | # (b) the shell glob failed to match, | | 267 | # (b) the shell glob failed to match, |
268 | # so ignore it and move on. | | 268 | # so ignore it and move on. |
269 | if [ ! -e "$cert" ]; then | | 269 | if [ ! -e "$cert" ]; then |
270 | if [ -h "$cert" ]; then | | 270 | if [ -h "$cert" ]; then |
271 | error "broken symlink: $vcert" | | 271 | error "broken symlink: $vcert" |
272 | status=1 | | 272 | status=1 |
273 | fi | | 273 | fi |
274 | continue | | 274 | continue |
275 | fi | | 275 | fi |
276 | | | 276 | |
277 | # Print the vis-encoded absolute path to the | | 277 | # Print the vis-encoded absolute path to the |
278 | # certificate and base name on a single line. | | 278 | # certificate and base name on a single line. |
279 | vbase=$(basename -- "$vcert.") | | 279 | vbase=${vcert##*/} |
280 | vbase=${vbase%.} | | | |
281 | printf '%s %s\n' "$vcert" "$vbase" | | 280 | printf '%s %s\n' "$vcert" "$vbase" |
282 | done | | 281 | done |
283 | done | | 282 | done |
284 | } | | 283 | } |
285 | | | 284 | |
286 | # list_distrusted | | 285 | # list_distrusted |
287 | # | | 286 | # |
288 | # List the vis-encoded certificate paths and their base names, | | 287 | # List the vis-encoded certificate paths and their base names, |
289 | # separated by a space, for the certificates that have been | | 288 | # separated by a space, for the certificates that have been |
290 | # distrusted by the user. | | 289 | # distrusted by the user. |
291 | # | | 290 | # |
292 | # No order guaranteed; caller must sort. | | 291 | # No order guaranteed; caller must sort. |
293 | # | | 292 | # |
| @@ -329,28 +328,27 @@ list_distrusted() | | | @@ -329,28 +328,27 @@ list_distrusted() |
329 | case $cert in | | 328 | case $cert in |
330 | /*) | | 329 | /*) |
331 | ;; | | 330 | ;; |
332 | *) | | 331 | *) |
333 | vlink=$(printf '%s' "$link" | vis -M) | | 332 | vlink=$(printf '%s' "$link" | vis -M) |
334 | vcert=$(printf '%s' "$cert" | vis -M) | | 333 | vcert=$(printf '%s' "$cert" | vis -M) |
335 | error "distrusted relative symlink: $vlink -> $vcert" | | 334 | error "distrusted relative symlink: $vlink -> $vcert" |
336 | ;; | | 335 | ;; |
337 | esac | | 336 | esac |
338 | | | 337 | |
339 | # Print the vis-encoded absolute path to the | | 338 | # Print the vis-encoded absolute path to the |
340 | # certificate and base name on a single line. | | 339 | # certificate and base name on a single line. |
341 | vcert=$(printf '%s' "$cert" | vis -M) | | 340 | vcert=$(printf '%s' "$cert" | vis -M) |
342 | vbase=$(basename -- "$vcert.") | | 341 | vbase=${vcert##*/} |
343 | vbase=${vbase%.} | | | |
344 | printf '%s %s\n' "$vcert" "$vbase" | | 342 | printf '%s %s\n' "$vcert" "$vbase" |
345 | done | | 343 | done |
346 | | | 344 | |
347 | return $status | | 345 | return $status |
348 | } | | 346 | } |
349 | | | 347 | |
350 | # list_trusted | | 348 | # list_trusted |
351 | # | | 349 | # |
352 | # List the trusted certificates, excluding the distrusted one, as | | 350 | # List the trusted certificates, excluding the distrusted one, as |
353 | # one vis(3) line per certificate. Reject duplicate base names, | | 351 | # one vis(3) line per certificate. Reject duplicate base names, |
354 | # since we will be creating symlinks to the same base names in | | 352 | # since we will be creating symlinks to the same base names in |
355 | # the certsdir. Sorted lexicographically by vis-encoding. | | 353 | # the certsdir. Sorted lexicographically by vis-encoding. |
356 | # | | 354 | # |
| @@ -552,39 +550,38 @@ cmd_trust() | | | @@ -552,39 +550,38 @@ cmd_trust() |
552 | | | 550 | |
553 | # XXX Accept base name. | | 551 | # XXX Accept base name. |
554 | | | 552 | |
555 | # vis the certificate path for terminal-safe error messages. | | 553 | # vis the certificate path for terminal-safe error messages. |
556 | vcert=$(printf '%s' "$cert" | vis -M) | | 554 | vcert=$(printf '%s' "$cert" | vis -M) |
557 | | | 555 | |
558 | # Verify the certificate actually exists. | | 556 | # Verify the certificate actually exists. |
559 | if [ ! -f "$cert" ]; then | | 557 | if [ ! -f "$cert" ]; then |
560 | error "no such certificate: $vcert" | | 558 | error "no such certificate: $vcert" |
561 | return 1 | | 559 | return 1 |
562 | fi | | 560 | fi |
563 | | | 561 | |
564 | # Verify we currently distrust a certificate by this base name. | | 562 | # Verify we currently distrust a certificate by this base name. |
565 | certbase=$(basename -- "$cert.") | | 563 | certbase=${cert##*/} |
566 | certbase=${certbase%.} | | | |
567 | if [ ! -h "$distrustdir/$certbase" ]; then | | 564 | if [ ! -h "$distrustdir/$certbase" ]; then |
568 | error "not currently distrusted: $vcert" | | 565 | error "not currently distrusted: $vcert" |
569 | return 1 | | 566 | return 1 |
570 | fi | | 567 | fi |
571 | | | 568 | |
572 | # Verify the certificate we distrust by this base name is the | | 569 | # Verify the certificate we distrust by this base name is the |
573 | # same one. | | 570 | # same one. |
574 | target=$(readlink -n -- "$distrustdir/$certbase" && printf .) | | 571 | target=$(readlink -n -- "$distrustdir/$certbase" && printf .) |
575 | target=${target%.} | | 572 | target=${target%.} |
576 | if [ "$cert" != "$target" ]; then | | 573 | if [ "$cert" != "$target" ]; then |
577 | vcertbase=$(basename -- "$vcert") | | 574 | vcertbase=${vcert##*/} |
578 | error "distrusted $vcertbase does not point to $vcert" | | 575 | error "distrusted $vcertbase does not point to $vcert" |
579 | return 1 | | 576 | return 1 |
580 | fi | | 577 | fi |
581 | | | 578 | |
582 | # Remove the link from the distrusted directory, and rehash -- | | 579 | # Remove the link from the distrusted directory, and rehash -- |
583 | # quietly, so verbose output emphasizes the distrust part and | | 580 | # quietly, so verbose output emphasizes the distrust part and |
584 | # not the whole certificate set. | | 581 | # not the whole certificate set. |
585 | run rm -- "$distrustdir/$certbase" | | 582 | run rm -- "$distrustdir/$certbase" |
586 | $vflag && echo '# rehash' | | 583 | $vflag && echo '# rehash' |
587 | vflag=false | | 584 | vflag=false |
588 | rehash | | 585 | rehash |
589 | } | | 586 | } |
590 | | | 587 | |
| @@ -607,28 +604,27 @@ cmd_untrust() | | | @@ -607,28 +604,27 @@ cmd_untrust() |
607 | vcert=$(printf '%s' "$cert" | vis -M) | | 604 | vcert=$(printf '%s' "$cert" | vis -M) |
608 | | | 605 | |
609 | # Verify the certificate actually exists. Otherwise, you might | | 606 | # Verify the certificate actually exists. Otherwise, you might |
610 | # fail to distrust a certificate you intended to distrust, | | 607 | # fail to distrust a certificate you intended to distrust, |
611 | # e.g. if you made a typo in its path. | | 608 | # e.g. if you made a typo in its path. |
612 | if [ ! -f "$cert" ]; then | | 609 | if [ ! -f "$cert" ]; then |
613 | error "no such certificate: $vcert" | | 610 | error "no such certificate: $vcert" |
614 | return 1 | | 611 | return 1 |
615 | fi | | 612 | fi |
616 | | | 613 | |
617 | # Check whether this certificate is already distrusted. | | 614 | # Check whether this certificate is already distrusted. |
618 | # - If the same base name points to the same path, stop here. | | 615 | # - If the same base name points to the same path, stop here. |
619 | # - Otherwise, fail noisily. | | 616 | # - Otherwise, fail noisily. |
620 | certbase=$(basename "$cert.") | | 617 | certbase=${cert##*/} |
621 | certbase=${certbase%.} | | | |
622 | if [ -h "$distrustdir/$certbase" ]; then | | 618 | if [ -h "$distrustdir/$certbase" ]; then |
623 | target=$(readlink -n -- "$distrustdir/$certbase" && printf .) | | 619 | target=$(readlink -n -- "$distrustdir/$certbase" && printf .) |
624 | target=${target%.} | | 620 | target=${target%.} |
625 | if [ "$target" = "$cert" ]; then | | 621 | if [ "$target" = "$cert" ]; then |
626 | $vflag && echo '# already distrusted' | | 622 | $vflag && echo '# already distrusted' |
627 | return | | 623 | return |
628 | fi | | 624 | fi |
629 | vcertbase=$(printf '%s' "$certbase" | vis -M) | | 625 | vcertbase=$(printf '%s' "$certbase" | vis -M) |
630 | vtarget=$(printf '%s' "$target" | vis -M) | | 626 | vtarget=$(printf '%s' "$target" | vis -M) |
631 | error "distrusted $vcertbase at different path $vtarget" | | 627 | error "distrusted $vcertbase at different path $vtarget" |
632 | return 1 | | 628 | return 1 |
633 | fi | | 629 | fi |
634 | | | 630 | |