md5(1): fix -c flag to work with input on stdin

Previously, the -p and -c flags were ignored when reading from stdin
Additionally, -s and -c can be used together now.

PR:		247295
Reviewed by:	kevans
MFC after:	2 weeks
Relnotes:	yes
Sponsored by:	Klara Inc.
Differential Revision:	https://reviews.freebsd.org/D25362
This commit is contained in:
Allan Jude 2020-06-19 19:16:25 +00:00
parent fb0543afa8
commit 0bc6f34c3d

View File

@ -52,11 +52,14 @@ __FBSDID("$FreeBSD$");
#define TEST_BLOCK_COUNT 100000 #define TEST_BLOCK_COUNT 100000
#define MDTESTCOUNT 8 #define MDTESTCOUNT 8
static int pflag;
static int qflag; static int qflag;
static int rflag; static int rflag;
static int sflag; static int sflag;
static int skip;
static char* checkAgainst; static char* checkAgainst;
static int checksFailed; static int checksFailed;
static int failed;
typedef void (DIGEST_Init)(void *); typedef void (DIGEST_Init)(void *);
typedef void (DIGEST_Update)(void *, const unsigned char *, size_t); typedef void (DIGEST_Update)(void *, const unsigned char *, size_t);
@ -86,10 +89,10 @@ typedef struct Algorithm_t {
} Algorithm_t; } Algorithm_t;
static void MD5_Update(MD5_CTX *, const unsigned char *, size_t); static void MD5_Update(MD5_CTX *, const unsigned char *, size_t);
static void MDString(const Algorithm_t *, const char *); static void MDOutput(const Algorithm_t *, char *, char **);
static void MDTimeTrial(const Algorithm_t *); static void MDTimeTrial(const Algorithm_t *);
static void MDTestSuite(const Algorithm_t *); static void MDTestSuite(const Algorithm_t *);
static void MDFilter(const Algorithm_t *, int); static char *MDFilter(const Algorithm_t *, char*, int);
static void usage(const Algorithm_t *); static void usage(const Algorithm_t *);
typedef union { typedef union {
@ -170,9 +173,9 @@ main(int argc, char *argv[])
cap_rights_t rights; cap_rights_t rights;
#endif #endif
int ch, fd; int ch, fd;
char *p; char *p, *string;
char buf[HEX_DIGEST_LENGTH]; char buf[HEX_DIGEST_LENGTH];
int failed; size_t len;
unsigned digest; unsigned digest;
const char* progname; const char* progname;
@ -191,13 +194,14 @@ main(int argc, char *argv[])
failed = 0; failed = 0;
checkAgainst = NULL; checkAgainst = NULL;
checksFailed = 0; checksFailed = 0;
skip = 0;
while ((ch = getopt(argc, argv, "c:pqrs:tx")) != -1) while ((ch = getopt(argc, argv, "c:pqrs:tx")) != -1)
switch (ch) { switch (ch) {
case 'c': case 'c':
checkAgainst = optarg; checkAgainst = optarg;
break; break;
case 'p': case 'p':
MDFilter(&Algorithm[digest], 1); pflag = 1;
break; break;
case 'q': case 'q':
qflag = 1; qflag = 1;
@ -207,13 +211,15 @@ main(int argc, char *argv[])
break; break;
case 's': case 's':
sflag = 1; sflag = 1;
MDString(&Algorithm[digest], optarg); string = optarg;
break; break;
case 't': case 't':
MDTimeTrial(&Algorithm[digest]); MDTimeTrial(&Algorithm[digest]);
skip = 1;
break; break;
case 'x': case 'x':
MDTestSuite(&Algorithm[digest]); MDTestSuite(&Algorithm[digest]);
skip = 1;
break; break;
default: default:
usage(&Algorithm[digest]); usage(&Algorithm[digest]);
@ -249,32 +255,19 @@ main(int argc, char *argv[])
} }
p = Algorithm[digest].Fd(fd, buf); p = Algorithm[digest].Fd(fd, buf);
(void)close(fd); (void)close(fd);
if (p == NULL) { MDOutput(&Algorithm[digest], p, argv);
warn("%s", *argv);
failed++;
} else {
if (qflag)
printf("%s", p);
else if (rflag)
printf("%s %s", p, *argv);
else
printf("%s (%s) = %s",
Algorithm[digest].name, *argv, p);
if (checkAgainst && strcasecmp(checkAgainst, p) != 0)
{
checksFailed++;
if (!qflag)
printf(" [ Failed ]");
}
printf("\n");
}
} while (*++argv); } while (*++argv);
} else if (!sflag && (optind == 1 || qflag || rflag)) { } else if (!sflag && !skip) {
#ifdef HAVE_CAPSICUM #ifdef HAVE_CAPSICUM
if (caph_limit_stdin() < 0 || caph_enter() < 0) if (caph_limit_stdin() < 0 || caph_enter() < 0)
err(1, "capsicum"); err(1, "capsicum");
#endif #endif
MDFilter(&Algorithm[digest], 0); p = MDFilter(&Algorithm[digest], (char *)&buf, pflag);
MDOutput(&Algorithm[digest], p, NULL);
} else if (sflag) {
len = strlen(string);
p = Algorithm[digest].Data(string, len, buf);
MDOutput(&Algorithm[digest], p, &string);
} }
if (failed != 0) if (failed != 0)
@ -284,30 +277,38 @@ main(int argc, char *argv[])
return (0); return (0);
} }
/* /*
* Digests a string and prints the result. * Common output handling
*/ */
static void static void
MDString(const Algorithm_t *alg, const char *string) MDOutput(const Algorithm_t *alg, char *p, char *argv[])
{ {
size_t len = strlen(string); if (p == NULL) {
char buf[HEX_DIGEST_LENGTH]; warn("%s", *argv);
failed++;
alg->Data(string,len,buf); } else {
if (qflag) /*
printf("%s", buf); * If argv is NULL we are reading from stdin, where the output
else if (rflag) * format has always been just the hash.
printf("%s \"%s\"", buf, string); */
else if (qflag || argv == NULL)
printf("%s (\"%s\") = %s", alg->name, string, buf); printf("%s", p);
if (checkAgainst && strcasecmp(buf,checkAgainst) != 0) else if (rflag)
{ printf("%s %s", p, *argv);
checksFailed++; else
if (!qflag) printf("%s (%s) = %s",
printf(" [ failed ]"); alg->name, *argv, p);
if (checkAgainst && strcasecmp(checkAgainst, p) != 0)
{
checksFailed++;
if (!qflag)
printf(" [ Failed ]");
}
printf("\n");
} }
printf("\n");
} }
/* /*
* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks. * Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks.
*/ */
@ -507,13 +508,13 @@ MDTestSuite(const Algorithm_t *alg)
/* /*
* Digests the standard input and prints the result. * Digests the standard input and prints the result.
*/ */
static void static char *
MDFilter(const Algorithm_t *alg, int tee) MDFilter(const Algorithm_t *alg, char *buf, int tee)
{ {
DIGEST_CTX context; DIGEST_CTX context;
unsigned int len; unsigned int len;
unsigned char buffer[BUFSIZ]; unsigned char buffer[BUFSIZ];
char buf[HEX_DIGEST_LENGTH]; char *p;
alg->Init(&context); alg->Init(&context);
while ((len = fread(buffer, 1, BUFSIZ, stdin))) { while ((len = fread(buffer, 1, BUFSIZ, stdin))) {
@ -521,7 +522,9 @@ MDFilter(const Algorithm_t *alg, int tee)
err(1, "stdout"); err(1, "stdout");
alg->Update(&context, buffer, len); alg->Update(&context, buffer, len);
} }
printf("%s\n", alg->End(&context, buf)); p = alg->End(&context, buf);
return (p);
} }
static void static void