diff options
Diffstat (limited to 'sbin/md5')
-rw-r--r-- | sbin/md5/Makefile | 11 | ||||
-rw-r--r-- | sbin/md5/Makefile.depend | 1 | ||||
-rw-r--r-- | sbin/md5/md5.1 | 11 | ||||
-rw-r--r-- | sbin/md5/md5.c | 133 | ||||
-rw-r--r-- | sbin/md5/tests/Makefile | 1 | ||||
-rw-r--r-- | sbin/md5/tests/Makefile.depend | 10 | ||||
-rw-r--r-- | sbin/md5/tests/md5_test.sh | 35 |
7 files changed, 132 insertions, 70 deletions
diff --git a/sbin/md5/Makefile b/sbin/md5/Makefile index 359c4b96f9fd..ed87ff84876b 100644 --- a/sbin/md5/Makefile +++ b/sbin/md5/Makefile @@ -1,5 +1,3 @@ -# @(#)Makefile 8.1 (Berkeley) 6/9/93 - PACKAGE=runtime PROG= md5 @@ -59,16 +57,19 @@ MLINKS= md5.1 md5sum.1 \ LIBADD= md -.ifndef(BOOTSTRAPPING) +.include <src.opts.mk> + +.if ${MK_CASPER} != "no" && !defined(RESCUE) && !defined(BOOTSTRAPPING) # Avoid depending on capsicum during bootstrap. caph_limit_stdout() is not # available when building for Linux/MacOS or older FreeBSD hosts. # We need to bootstrap md5 when building on Linux since the md5sum command there # produces different output. CFLAGS+=-DHAVE_CAPSICUM +CFLAGS+=-DWITH_CASPER +LIBADD+= casper +LIBADD+= cap_fileargs .endif -.include <src.opts.mk> - HAS_TESTS= SUBDIR.${MK_TESTS}+= tests diff --git a/sbin/md5/Makefile.depend b/sbin/md5/Makefile.depend index e442dca35596..61733f6b057b 100644 --- a/sbin/md5/Makefile.depend +++ b/sbin/md5/Makefile.depend @@ -7,6 +7,7 @@ DIRDEPS = \ lib/libc \ lib/libcapsicum \ lib/libcasper/libcasper \ + lib/libcasper/services/cap_fileargs \ lib/libcompiler_rt \ lib/libmd \ diff --git a/sbin/md5/md5.1 b/sbin/md5/md5.1 index 0cdfff928211..b530292c8269 100644 --- a/sbin/md5/md5.1 +++ b/sbin/md5/md5.1 @@ -1,4 +1,4 @@ -.Dd May 10, 2023 +.Dd March 12, 2024 .Dt MD5 1 .Os .Sh NAME @@ -79,6 +79,11 @@ utility does the same, but with command-line options and an output format that match those of the similarly named utility that ships with Perl. .Pp +In all cases, each file listed on the command line is processed separately. +If no files are listed on the command line, or a file name is given as +.Pa - , +input is taken from stdin instead. +.Pp It is conjectured that it is computationally infeasible to produce two messages having the same message digest, or to produce any message having a given prespecified target message digest. @@ -124,6 +129,7 @@ option, the calculated digest is printed in addition to the exit status being se .Pq Note that this option is not yet useful if multiple files are specified. .It Fl p , -passthrough Echo stdin to stdout and append the checksum to stdout. +In this mode, any files specified on the command line are silently ignored. .It Fl q , -quiet Quiet mode \(em only the checksum is printed out. Overrides the @@ -141,6 +147,7 @@ options. .It Fl s Ar string , Fl -string= Ns Ar string Print a checksum of the given .Ar string . +In this mode, any files specified on the command line are silently ignored. .It Fl t , Fl -time-trial Run a built-in time trial. For the @@ -360,7 +367,7 @@ for .Pa /boot/loader.conf in the example above. .Bd -literal -offset indent -$ md5 -c digest /boot/loader.conf +$ md5sum -c digest /boot/loader.conf: OK .Ed .Pp diff --git a/sbin/md5/md5.c b/sbin/md5/md5.c index 15fd7ebec5d4..10ffae53c775 100644 --- a/sbin/md5/md5.c +++ b/sbin/md5/md5.c @@ -17,7 +17,6 @@ * documentation and/or software. */ -#include <sys/cdefs.h> #include <sys/param.h> #include <sys/resource.h> #include <sys/stat.h> @@ -47,6 +46,8 @@ #ifdef HAVE_CAPSICUM #include <sys/capsicum.h> #include <capsicum_helpers.h> +#include <libcasper.h> +#include <casper/cap_fileargs.h> #endif /* @@ -262,7 +263,8 @@ static const char *gnu_shortopts = "bctwz"; static const struct option perl_longopts[] = { { "algorithm", required_argument, 0, opt_algorithm }, - { "check", required_argument, 0, opt_check }, + { "binary", no_argument, 0, opt_binary }, + { "check", no_argument, 0, opt_check }, { "help", no_argument, 0, opt_help }, { "ignore-missing", no_argument, 0, opt_ignore_missing }, { "quiet", no_argument, 0, opt_quiet }, @@ -285,9 +287,10 @@ MD5_Update(MD5_CTX *c, const unsigned char *data, size_t len) } struct chksumrec { - char *filename; - char *chksum; - struct chksumrec *next; + char *filename; + enum input_mode input_mode; + char *chksum; + struct chksumrec *next; }; static struct chksumrec *head = NULL; @@ -300,17 +303,18 @@ static unsigned int numrecs; static void gnu_check(const char *checksumsfile) { - FILE *inp; - char *linebuf = NULL; - size_t linecap; - ssize_t linelen; - int lineno; - char *filename; - char *hashstr; - struct chksumrec *rec; - const char *digestname; - size_t digestnamelen; - size_t hashstrlen; + FILE *inp; + char *linebuf = NULL; + size_t linecap; + ssize_t linelen; + int lineno; + char *filename; + char *hashstr; + struct chksumrec *rec; + const char *digestname; + size_t digestnamelen; + size_t hashstrlen; + struct stat st; if (strcmp(checksumsfile, "-") == 0) inp = stdin; @@ -358,8 +362,19 @@ gnu_check(const char *checksumsfile) rec = malloc(sizeof(*rec)); if (rec == NULL) errx(1, "malloc failed"); + + if ((*filename == '*' || *filename == ' ' || + *filename == 'U' || *filename == '^') && + lstat(filename, &st) != 0 && + lstat(filename + 1, &st) == 0) { + rec->filename = strdup(filename + 1); + rec->input_mode = (enum input_mode)*filename; + } else { + rec->filename = strdup(filename); + rec->input_mode = input_mode; + } + rec->chksum = strdup(hashstr); - rec->filename = strdup(filename); if (rec->chksum == NULL || rec->filename == NULL) errx(1, "malloc failed"); rec->next = NULL; @@ -384,16 +399,17 @@ int main(int argc, char *argv[]) { #ifdef HAVE_CAPSICUM - cap_rights_t rights; + cap_rights_t rights; + fileargs_t *fa = NULL; #endif const struct option *longopts; const char *shortopts; - FILE *f; - int i, opt; - char *p, *string = NULL; - char buf[HEX_DIGEST_LENGTH]; - size_t len; - struct chksumrec *rec; + FILE *f; + int i, opt; + char *p, *string = NULL; + char buf[HEX_DIGEST_LENGTH]; + size_t len; + struct chksumrec *rec; if ((progname = strrchr(argv[0], '/')) == NULL) progname = argv[0]; @@ -562,7 +578,7 @@ main(int argc, char *argv[]) argv += optind; #ifdef HAVE_CAPSICUM - if (caph_limit_stdout() < 0 || caph_limit_stderr() < 0) + if (caph_limit_stdio() < 0) err(1, "unable to limit rights for stdio"); #endif @@ -576,7 +592,7 @@ main(int argc, char *argv[]) while (argc--) gnu_check(*argv++); argc = 0; - argv = calloc(sizeof(char *), numrecs + 1); + argv = calloc(numrecs + 1, sizeof(char *)); for (rec = head; rec != NULL; rec = rec->next) { argv[argc] = rec->filename; argc++; @@ -585,59 +601,49 @@ main(int argc, char *argv[]) rec = head; } - if (*argv) { +#ifdef HAVE_CAPSICUM + fa = fileargs_init(argc, argv, O_RDONLY, 0, + cap_rights_init(&rights, CAP_READ, CAP_FSTAT, CAP_FCNTL), FA_OPEN | FA_LSTAT); + if (fa == NULL) + err(1, "Unable to initialize casper"); + if (caph_enter_casper() < 0) + err(1, "Unable to enter capability mode"); +#endif + + if (*argv && !pflag && string == NULL) { do { - struct stat st; const char *filename = *argv; const char *filemode = "rb"; - if (*filename == '*' || - *filename == ' ' || - *filename == 'U' || - *filename == '^') { - if (lstat(filename, &st) != 0) { - input_mode = (int)*filename; - filename++; - } + if (cflag && mode != mode_bsd) { + input_mode = rec->input_mode; + checkAgainst = rec->chksum; + rec = rec->next; } if (input_mode == input_text) filemode = "r"; - if ((f = fopen(filename, filemode)) == NULL) { + if (strcmp(filename, "-") == 0) { + f = stdin; + } else { +#ifdef HAVE_CAPSICUM + f = fileargs_fopen(fa, filename, filemode); +#else + f = fopen(filename, filemode); +#endif + } + if (f == NULL) { if (errno != ENOENT || !(cflag && ignoreMissing)) { warn("%s", filename); failed = true; } - if (cflag && mode != mode_bsd) - rec = rec->next; continue; } - /* - * XXX Enter capability mode on the last argv file. - * When a casper file service or other approach is - * available, switch to that and enter capability mode - * earlier. - */ - if (*(argv + 1) == NULL) { -#ifdef HAVE_CAPSICUM - cap_rights_init(&rights, CAP_READ, CAP_FSTAT); - if (caph_rights_limit(fileno(f), &rights) < 0 || - caph_enter() < 0) - err(1, "capsicum"); -#endif - } - if (cflag && mode != mode_bsd) { - checkAgainst = rec->chksum; - rec = rec->next; - } p = MDInput(&Algorithm[digest], f, buf, false); - (void)fclose(f); + if (f != stdin) + (void)fclose(f); MDOutput(&Algorithm[digest], p, filename); } while (*++argv); } else if (!cflag && string == NULL && !skip) { -#ifdef HAVE_CAPSICUM - if (caph_limit_stdin() < 0 || caph_enter() < 0) - err(1, "capsicum"); -#endif if (mode == mode_bsd) output_mode = output_bare; p = MDInput(&Algorithm[digest], stdin, buf, pflag); @@ -659,6 +665,9 @@ main(int argc, char *argv[]) if (checksFailed != 0 || (strict && malformed > 0)) return (1); } +#ifdef HAVE_CAPSICUM + fileargs_free(fa); +#endif if (failed) return (1); if (checksFailed > 0) diff --git a/sbin/md5/tests/Makefile b/sbin/md5/tests/Makefile index 236e8433fd43..03c4da684eba 100644 --- a/sbin/md5/tests/Makefile +++ b/sbin/md5/tests/Makefile @@ -1,4 +1,3 @@ - .include <bsd.own.mk> PACKAGE= tests diff --git a/sbin/md5/tests/Makefile.depend b/sbin/md5/tests/Makefile.depend new file mode 100644 index 000000000000..11aba52f82cf --- /dev/null +++ b/sbin/md5/tests/Makefile.depend @@ -0,0 +1,10 @@ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/sbin/md5/tests/md5_test.sh b/sbin/md5/tests/md5_test.sh index c6bc1dfd7be0..34bdf43f13ea 100644 --- a/sbin/md5/tests/md5_test.sh +++ b/sbin/md5/tests/md5_test.sh @@ -197,11 +197,15 @@ bsd_${alg}_vec${i}_body() { printf '%s' \"\$inp_${i}\" >in atf_check -o inline:\"\$out_${i}_${alg}\n\" ${alg} <in atf_check -o inline:\"\$name_bsd_${alg} (in) = \$out_${i}_${alg}\n\" ${alg} in + atf_check -o inline:\"\$name_bsd_${alg} (-) = \$out_${i}_${alg}\n\" ${alg} - <in atf_check -o inline:\"\$out_${i}_${alg} in\n\" ${alg} -r in + atf_check -o inline:\"\$out_${i}_${alg} -\n\" ${alg} -r - <in # -q overrides -r regardless of order for opt in -q -qr -rq ; do atf_check -o inline:\"\$out_${i}_${alg}\n\" ${alg} \${opt} in done + atf_check -o inline:\"\$inp_${i}\$out_${i}_${alg}\n\" ${alg} -p <in + atf_check -o inline:\"\$out_${i}_${alg}\n\" ${alg} -s \"\$inp_${i}\" } " eval " @@ -215,9 +219,13 @@ gnu_${alg}_vec${i}_body() { atf_check -o inline:\"\$out_${i}_${alg} -\n\" ${alg}sum <in atf_check -o inline:\"\$out_${i}_${alg} *-\n\" ${alg}sum -b <in atf_check -o inline:\"\$out_${i}_${alg} in\n\" ${alg}sum in + atf_check -o inline:\"\$out_${i}_${alg} -\n\" ${alg}sum - <in atf_check -o inline:\"\$out_${i}_${alg} *in\n\" ${alg}sum -b in + atf_check -o inline:\"\$out_${i}_${alg} *-\n\" ${alg}sum -b - <in atf_check -o inline:\"\$name_bsd_${alg} (in) = \$out_${i}_${alg}\n\" ${alg}sum --tag in + atf_check -o inline:\"\$name_bsd_${alg} (-) = \$out_${i}_${alg}\n\" ${alg}sum --tag - <in atf_check -o inline:\"\$out_${i}_${alg} in\0\" ${alg}sum -z in + atf_check -o inline:\"\$out_${i}_${alg} -\0\" ${alg}sum -z - <in } " eval " @@ -233,9 +241,13 @@ perl_${alg}_vec${i}_body() { atf_check -o inline:\"\$out_${i}_${alg} *-\n\" shasum \$alg_perl_${alg} -b <in atf_check -o inline:\"\$out_${i}_${alg} U-\n\" shasum \$alg_perl_${alg} -U <in atf_check -o inline:\"\$out_${i}_${alg} in\n\" shasum \$alg_perl_${alg} in + atf_check -o inline:\"\$out_${i}_${alg} -\n\" shasum \$alg_perl_${alg} - <in atf_check -o inline:\"\$out_${i}_${alg} *in\n\" shasum \$alg_perl_${alg} -b in + atf_check -o inline:\"\$out_${i}_${alg} *-\n\" shasum \$alg_perl_${alg} -b - <in atf_check -o inline:\"\$out_${i}_${alg} Uin\n\" shasum \$alg_perl_${alg} -U in + atf_check -o inline:\"\$out_${i}_${alg} U-\n\" shasum \$alg_perl_${alg} -U - <in atf_check -o inline:\"\$name_perl_${alg} (in) = \$out_${i}_${alg}\n\" shasum \$alg_perl_${alg} --tag in + atf_check -o inline:\"\$name_perl_${alg} (-) = \$out_${i}_${alg}\n\" shasum \$alg_perl_${alg} --tag - <in } " done @@ -357,6 +369,28 @@ gnu_cflag_body() } +atf_test_case gnu_cflag_mode +gnu_cflag_mode_head() +{ + atf_set descr "Verify handling of input modes in GNU check mode" + atf_set require.progs "sha1sum" +} +gnu_cflag_mode_body() +{ + printf "The Magic Words are 01010011 01001111\r\n" >input + # The first line is malformed per GNU coreutils but matches + # what we produce when mode == mode_bsd && output_mode == + # output_reverse (i.e. `sha1 -r`) so we want to support it. + cat >digests <<EOF +53d88300dfb2be42f0ef25e3d9de798e31bb7e69 input +53d88300dfb2be42f0ef25e3d9de798e31bb7e69 *input +53d88300dfb2be42f0ef25e3d9de798e31bb7e69 input +2290cf6ba4ac5387e520088de760b71a523871b0 ^input +c1065e0d2bbc1c67dcecee0187d61316fb9c5582 Uinput +EOF + atf_check sha1sum --quiet --check digests +} + atf_init_test_cases() { for alg in $algorithms ; do @@ -371,4 +405,5 @@ atf_init_test_cases() done atf_add_test_case gnu_bflag atf_add_test_case gnu_cflag + atf_add_test_case gnu_cflag_mode } |