aboutsummaryrefslogtreecommitdiff
path: root/sbin/md5
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/md5')
-rw-r--r--sbin/md5/Makefile11
-rw-r--r--sbin/md5/Makefile.depend1
-rw-r--r--sbin/md5/md5.111
-rw-r--r--sbin/md5/md5.c133
-rw-r--r--sbin/md5/tests/Makefile1
-rw-r--r--sbin/md5/tests/Makefile.depend10
-rw-r--r--sbin/md5/tests/md5_test.sh35
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
}