1 /* Compute checksums of files or strings.
2 Copyright (C) 1995-2016 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 /* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>. */
22 #include <sys/types.h>
32 #if HASH_ALGO_SHA256 || HASH_ALGO_SHA224
35 #if HASH_ALGO_SHA512 || HASH_ALGO_SHA384
43 /* The official name of this program (e.g., no 'g' prefix). */
45 # define PROGRAM_NAME "md5sum"
46 # define DIGEST_TYPE_STRING "MD5"
47 # define DIGEST_STREAM md5_stream
48 # define DIGEST_BITS 128
49 # define DIGEST_REFERENCE "RFC 1321"
50 # define DIGEST_ALIGN 4
52 # define PROGRAM_NAME "sha1sum"
53 # define DIGEST_TYPE_STRING "SHA1"
54 # define DIGEST_STREAM sha1_stream
55 # define DIGEST_BITS 160
56 # define DIGEST_REFERENCE "FIPS-180-1"
57 # define DIGEST_ALIGN 4
58 #elif HASH_ALGO_SHA256
59 # define PROGRAM_NAME "sha256sum"
60 # define DIGEST_TYPE_STRING "SHA256"
61 # define DIGEST_STREAM sha256_stream
62 # define DIGEST_BITS 256
63 # define DIGEST_REFERENCE "FIPS-180-2"
64 # define DIGEST_ALIGN 4
65 #elif HASH_ALGO_SHA224
66 # define PROGRAM_NAME "sha224sum"
67 # define DIGEST_TYPE_STRING "SHA224"
68 # define DIGEST_STREAM sha224_stream
69 # define DIGEST_BITS 224
70 # define DIGEST_REFERENCE "RFC 3874"
71 # define DIGEST_ALIGN 4
72 #elif HASH_ALGO_SHA512
73 # define PROGRAM_NAME "sha512sum"
74 # define DIGEST_TYPE_STRING "SHA512"
75 # define DIGEST_STREAM sha512_stream
76 # define DIGEST_BITS 512
77 # define DIGEST_REFERENCE "FIPS-180-2"
78 # define DIGEST_ALIGN 8
79 #elif HASH_ALGO_SHA384
80 # define PROGRAM_NAME "sha384sum"
81 # define DIGEST_TYPE_STRING "SHA384"
82 # define DIGEST_STREAM sha384_stream
83 # define DIGEST_BITS 384
84 # define DIGEST_REFERENCE "FIPS-180-2"
85 # define DIGEST_ALIGN 8
87 # error "Can't decide which hash algorithm to compile."
90 #define DIGEST_HEX_BYTES (DIGEST_BITS / 4)
91 #define DIGEST_BIN_BYTES (DIGEST_BITS / 8)
94 proper_name ("Ulrich Drepper"), \
95 proper_name ("Scott Miller"), \
96 proper_name ("David Madore")
98 /* The minimum length of a valid digest line. This length does
99 not include any newline character at the end of a line. */
100 #define MIN_DIGEST_LINE_LENGTH \
101 (DIGEST_HEX_BYTES /* length of hexadecimal message digest */ \
103 + 1 /* minimum filename length */ )
105 /* True if any of the files read were the standard input. */
106 static bool have_read_stdin
;
108 /* The minimum length of a valid checksum line for the selected algorithm. */
109 static size_t min_digest_line_length
;
111 /* Set to the length of a digest hex string for the selected algorithm. */
112 static size_t digest_hex_bytes
;
114 /* With --check, don't generate any output.
115 The exit code indicates success or failure. */
116 static bool status_only
= false;
118 /* With --check, print a message to standard error warning about each
119 improperly formatted checksum line. */
120 static bool warn
= false;
122 /* With --check, ignore missing files. */
123 static bool ignore_missing
= false;
125 /* With --check, suppress the "OK" printed for each verified file. */
126 static bool quiet
= false;
128 /* With --check, exit with a non-zero return code if any line is
129 improperly formatted. */
130 static bool strict
= false;
132 /* Whether a BSD reversed format checksum is detected. */
133 static int bsd_reversed
= -1;
135 /* For long options that have no equivalent short option, use a
136 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
139 IGNORE_MISSING_OPTION
= CHAR_MAX
+ 1,
146 static struct option
const long_options
[] =
148 { "binary", no_argument
, NULL
, 'b' },
149 { "check", no_argument
, NULL
, 'c' },
150 { "ignore-missing", no_argument
, NULL
, IGNORE_MISSING_OPTION
},
151 { "quiet", no_argument
, NULL
, QUIET_OPTION
},
152 { "status", no_argument
, NULL
, STATUS_OPTION
},
153 { "text", no_argument
, NULL
, 't' },
154 { "warn", no_argument
, NULL
, 'w' },
155 { "strict", no_argument
, NULL
, STRICT_OPTION
},
156 { "tag", no_argument
, NULL
, TAG_OPTION
},
157 { GETOPT_HELP_OPTION_DECL
},
158 { GETOPT_VERSION_OPTION_DECL
},
165 if (status
!= EXIT_SUCCESS
)
170 Usage: %s [OPTION]... [FILE]...\n\
171 Print or check %s (%d-bit) checksums.\n\
182 -b, --binary read in binary mode (default unless reading tty stdin)\n\
187 -b, --binary read in binary mode\n\
190 -c, --check read %s sums from the FILEs and check them\n"),
193 --tag create a BSD-style checksum\n\
197 -t, --text read in text mode (default if reading tty stdin)\n\
201 -t, --text read in text mode (default)\n\
205 The following five options are useful only when verifying checksums:\n\
206 --ignore-missing don't fail or report status for missing files\n\
207 --quiet don't print OK for each successfully verified file\n\
208 --status don't output anything, status code shows success\n\
209 --strict exit non-zero for improperly formatted checksum lines\n\
210 -w, --warn warn about improperly formatted checksum lines\n\
213 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
214 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
217 The sums are computed as described in %s. When checking, the input\n\
218 should be a former output of this program. The default mode is to print a\n\
219 line with checksum, a space, a character indicating input mode ('*' for binary,\
220 \n' ' for text or where binary is insignificant), and name for each FILE.\n"),
222 emit_ancillary_info (PROGRAM_NAME
);
228 #define ISWHITE(c) ((c) == ' ' || (c) == '\t')
230 /* Given a file name, S of length S_LEN, that is not NUL-terminated,
231 modify it in place, performing the equivalent of this sed substitution:
232 's/\\n/\n/g;s/\\\\/\\/g' i.e., replacing each "\\n" string with a newline
233 and each "\\\\" with a single backslash, NUL-terminate it and return S.
234 If S is not a valid escaped file name, i.e., if it ends with an odd number
235 of backslashes or if it contains a backslash followed by anything other
236 than "n" or another backslash, return NULL. */
239 filename_unescape (char *s
, size_t s_len
)
243 for (size_t i
= 0; i
< s_len
; i
++)
250 /* File name ends with an unescaped backslash: invalid. */
263 /* Only '\' or 'n' may follow a backslash. */
269 /* The file name may not contain a NUL. */
283 /* Split the checksum string S (of length S_LEN) from a BSD 'md5' or
284 'sha1' command into two parts: a hexadecimal digest, and the file
285 name. S is modified. Return true if successful. */
288 bsd_split_3 (char *s
, size_t s_len
, unsigned char **hex_digest
,
289 char **file_name
, bool escaped_filename
)
296 /* Find end of filename. */
298 while (i
&& s
[i
] != ')')
306 if (escaped_filename
&& filename_unescape (s
, i
) == NULL
)
311 while (ISWHITE (s
[i
]))
319 while (ISWHITE (s
[i
]))
322 *hex_digest
= (unsigned char *) &s
[i
];
326 /* Split the string S (of length S_LEN) into three parts:
327 a hexadecimal digest, binary flag, and the file name.
328 S is modified. Return true if successful. */
331 split_3 (char *s
, size_t s_len
,
332 unsigned char **hex_digest
, int *binary
, char **file_name
)
334 bool escaped_filename
= false;
335 size_t algo_name_len
;
338 while (ISWHITE (s
[i
]))
344 escaped_filename
= true;
347 /* Check for BSD-style checksum line. */
349 algo_name_len
= strlen (DIGEST_TYPE_STRING
);
350 if (STREQ_LEN (s
+ i
, DIGEST_TYPE_STRING
, algo_name_len
))
352 if (s
[i
+ algo_name_len
] == ' ')
354 if (s
[i
+ algo_name_len
] == '(')
357 return bsd_split_3 (s
+ i
+ algo_name_len
+ 1,
358 s_len
- (i
+ algo_name_len
+ 1),
359 hex_digest
, file_name
, escaped_filename
);
363 /* Ignore this line if it is too short.
364 Each line must have at least 'min_digest_line_length - 1' (or one more, if
365 the first is a backslash) more characters to contain correct message digest
367 if (s_len
- i
< min_digest_line_length
+ (s
[i
] == '\\'))
370 *hex_digest
= (unsigned char *) &s
[i
];
372 /* The first field has to be the n-character hexadecimal
373 representation of the message digest. If it is not followed
374 immediately by a white space it's an error. */
375 i
+= digest_hex_bytes
;
381 /* If "bsd reversed" format detected. */
382 if ((s_len
- i
== 1) || (s
[i
] != ' ' && s
[i
] != '*'))
384 /* Don't allow mixing bsd and standard formats,
385 to minimize security issues with attackers
386 renaming files with leading spaces.
387 This assumes that with bsd format checksums
388 that the first file name does not have
389 a leading ' ' or '*'. */
390 if (bsd_reversed
== 0)
394 else if (bsd_reversed
!= 1)
397 *binary
= (s
[i
++] == '*');
400 /* All characters between the type indicator and end of line are
401 significant -- that includes leading and trailing white space. */
404 if (escaped_filename
)
405 return filename_unescape (&s
[i
], s_len
- i
) != NULL
;
410 /* Return true if S is a NUL-terminated string of DIGEST_HEX_BYTES hex digits.
411 Otherwise, return false. */
412 static bool _GL_ATTRIBUTE_PURE
413 hex_digits (unsigned char const *s
)
416 for (i
= 0; i
< digest_hex_bytes
; i
++)
425 /* If ESCAPE is true, then translate each NEWLINE byte to the string, "\\n",
426 and each backslash to "\\\\". */
428 print_filename (char const *file
, bool escape
)
432 fputs (file
, stdout
);
441 fputs ("\\n", stdout
);
445 fputs ("\\\\", stdout
);
456 /* An interface to the function, DIGEST_STREAM.
457 Operate on FILENAME (it may be "-").
459 *BINARY indicates whether the file is binary. BINARY < 0 means it
460 depends on whether binary mode makes any difference and the file is
461 a terminal; in that case, clear *BINARY if the file was treated as
462 text because it was a terminal.
464 Put the checksum in *BIN_RESULT, which must be properly aligned.
465 Return true if successful. */
468 digest_file (const char *filename
, int *binary
, unsigned char *bin_result
)
472 bool is_stdin
= STREQ (filename
, "-");
476 have_read_stdin
= true;
478 if (O_BINARY
&& *binary
)
481 *binary
= ! isatty (STDIN_FILENO
);
483 xfreopen (NULL
, "rb", stdin
);
488 fp
= fopen (filename
, (O_BINARY
&& *binary
? "rb" : "r"));
491 if (ignore_missing
&& errno
== ENOENT
)
496 error (0, errno
, "%s", quotef (filename
));
501 fadvise (fp
, FADVISE_SEQUENTIAL
);
503 err
= DIGEST_STREAM (fp
, bin_result
);
506 error (0, errno
, "%s", quotef (filename
));
512 if (!is_stdin
&& fclose (fp
) != 0)
514 error (0, errno
, "%s", quotef (filename
));
522 digest_check (const char *checkfile_name
)
524 FILE *checkfile_stream
;
525 uintmax_t n_misformatted_lines
= 0;
526 uintmax_t n_improperly_formatted_lines
= 0;
527 uintmax_t n_mismatched_checksums
= 0;
528 uintmax_t n_open_or_read_failures
= 0;
529 bool properly_formatted_lines
= false;
530 bool matched_checksums
= false;
531 unsigned char bin_buffer_unaligned
[DIGEST_BIN_BYTES
+ DIGEST_ALIGN
];
532 /* Make sure bin_buffer is properly aligned. */
533 unsigned char *bin_buffer
= ptr_align (bin_buffer_unaligned
, DIGEST_ALIGN
);
534 uintmax_t line_number
;
536 size_t line_chars_allocated
;
537 bool is_stdin
= STREQ (checkfile_name
, "-");
541 have_read_stdin
= true;
542 checkfile_name
= _("standard input");
543 checkfile_stream
= stdin
;
547 checkfile_stream
= fopen (checkfile_name
, "r");
548 if (checkfile_stream
== NULL
)
550 error (0, errno
, "%s", quotef (checkfile_name
));
557 line_chars_allocated
= 0;
560 char *filename
IF_LINT ( = NULL
);
562 unsigned char *hex_digest
IF_LINT ( = NULL
);
566 if (line_number
== 0)
567 error (EXIT_FAILURE
, 0, _("%s: too many checksum lines"),
568 quotef (checkfile_name
));
570 line_length
= getline (&line
, &line_chars_allocated
, checkfile_stream
);
571 if (line_length
<= 0)
574 /* Ignore comment lines, which begin with a '#' character. */
578 /* Remove any trailing newline. */
579 if (line
[line_length
- 1] == '\n')
580 line
[--line_length
] = '\0';
582 if (! (split_3 (line
, line_length
, &hex_digest
, &binary
, &filename
)
583 && ! (is_stdin
&& STREQ (filename
, "-"))
584 && hex_digits (hex_digest
)))
586 ++n_misformatted_lines
;
592 ": improperly formatted %s checksum line"),
593 quotef (checkfile_name
), line_number
,
597 ++n_improperly_formatted_lines
;
601 static const char bin2hex
[] = { '0', '1', '2', '3',
604 'c', 'd', 'e', 'f' };
606 /* Only escape in the edge case producing multiple lines,
607 to ease automatic processing of status output. */
608 bool needs_escape
= ! status_only
&& strchr (filename
, '\n');
610 properly_formatted_lines
= true;
612 *bin_buffer
= '\1'; /* flag set to 0 for ignored missing files. */
613 ok
= digest_file (filename
, &binary
, bin_buffer
);
617 ++n_open_or_read_failures
;
622 print_filename (filename
, needs_escape
);
623 printf (": %s\n", _("FAILED open or read"));
626 else if (ignore_missing
&& ! *bin_buffer
)
628 /* Treat an empty buffer as meaning a missing file,
629 which is ignored with --ignore-missing. */
634 size_t digest_bin_bytes
= digest_hex_bytes
/ 2;
637 /* Compare generated binary number with text representation
638 in check file. Ignore case of hex digits. */
639 for (cnt
= 0; cnt
< digest_bin_bytes
; ++cnt
)
641 if (tolower (hex_digest
[2 * cnt
])
642 != bin2hex
[bin_buffer
[cnt
] >> 4]
643 || (tolower (hex_digest
[2 * cnt
+ 1])
644 != (bin2hex
[bin_buffer
[cnt
] & 0xf])))
647 if (cnt
!= digest_bin_bytes
)
648 ++n_mismatched_checksums
;
650 matched_checksums
= true;
654 if (cnt
!= digest_bin_bytes
|| ! quiet
)
658 print_filename (filename
, needs_escape
);
661 if (cnt
!= digest_bin_bytes
)
662 printf (": %s\n", _("FAILED"));
664 printf (": %s\n", _("OK"));
669 while (!feof (checkfile_stream
) && !ferror (checkfile_stream
));
673 if (ferror (checkfile_stream
))
675 error (0, 0, _("%s: read error"), quotef (checkfile_name
));
679 if (!is_stdin
&& fclose (checkfile_stream
) != 0)
681 error (0, errno
, "%s", quotef (checkfile_name
));
685 if (! properly_formatted_lines
)
687 /* Warn if no tests are found. */
688 error (0, 0, _("%s: no properly formatted %s checksum lines found"),
689 quotef (checkfile_name
), DIGEST_TYPE_STRING
);
695 if (n_misformatted_lines
!= 0)
698 ("WARNING: %" PRIuMAX
" line is improperly formatted",
699 "WARNING: %" PRIuMAX
" lines are improperly formatted",
700 select_plural (n_misformatted_lines
))),
701 n_misformatted_lines
);
703 if (n_open_or_read_failures
!= 0)
706 ("WARNING: %" PRIuMAX
" listed file could not be read",
707 "WARNING: %" PRIuMAX
" listed files could not be read",
708 select_plural (n_open_or_read_failures
))),
709 n_open_or_read_failures
);
711 if (n_mismatched_checksums
!= 0)
714 ("WARNING: %" PRIuMAX
" computed checksum did NOT match",
715 "WARNING: %" PRIuMAX
" computed checksums did NOT match",
716 select_plural (n_mismatched_checksums
))),
717 n_mismatched_checksums
);
719 if (ignore_missing
&& ! matched_checksums
)
720 error (0, 0, _("%s: no file was verified"),
721 quotef (checkfile_name
));
725 return (properly_formatted_lines
727 && n_mismatched_checksums
== 0
728 && n_open_or_read_failures
== 0
729 && (!strict
|| n_improperly_formatted_lines
== 0));
733 main (int argc
, char **argv
)
735 unsigned char bin_buffer_unaligned
[DIGEST_BIN_BYTES
+ DIGEST_ALIGN
];
736 /* Make sure bin_buffer is properly aligned. */
737 unsigned char *bin_buffer
= ptr_align (bin_buffer_unaligned
, DIGEST_ALIGN
);
738 bool do_check
= false;
742 bool prefix_tag
= false;
744 /* Setting values of global variables. */
745 initialize_main (&argc
, &argv
);
746 set_program_name (argv
[0]);
747 setlocale (LC_ALL
, "");
748 bindtextdomain (PACKAGE
, LOCALEDIR
);
749 textdomain (PACKAGE
);
751 atexit (close_stdout
);
753 /* Line buffer stdout to ensure lines are written atomically and immediately
754 so that processes running in parallel do not intersperse their output. */
755 setvbuf (stdout
, NULL
, _IOLBF
, 0);
757 while ((opt
= getopt_long (argc
, argv
, "bctw", long_options
, NULL
)) != -1)
779 case IGNORE_MISSING_OPTION
:
780 ignore_missing
= true;
794 case_GETOPT_HELP_CHAR
;
795 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
797 usage (EXIT_FAILURE
);
800 min_digest_line_length
= MIN_DIGEST_LINE_LENGTH
;
801 digest_hex_bytes
= DIGEST_HEX_BYTES
;
803 if (prefix_tag
&& !binary
)
805 /* This could be supported in a backwards compatible way
806 by prefixing the output line with a space in text mode.
807 However that's invasive enough that it was agreed to
808 not support this mode with --tag, as --text use cases
809 are adequately supported by the default output format. */
810 error (0, 0, _("--tag does not support --text mode"));
811 usage (EXIT_FAILURE
);
814 if (prefix_tag
&& do_check
)
816 error (0, 0, _("the --tag option is meaningless when "
817 "verifying checksums"));
818 usage (EXIT_FAILURE
);
821 if (0 <= binary
&& do_check
)
823 error (0, 0, _("the --binary and --text options are meaningless when "
824 "verifying checksums"));
825 usage (EXIT_FAILURE
);
828 if (ignore_missing
&& !do_check
)
831 _("the --ignore-missing option is meaningful only when "
832 "verifying checksums"));
833 usage (EXIT_FAILURE
);
836 if (status_only
&& !do_check
)
839 _("the --status option is meaningful only when verifying checksums"));
840 usage (EXIT_FAILURE
);
843 if (warn
&& !do_check
)
846 _("the --warn option is meaningful only when verifying checksums"));
847 usage (EXIT_FAILURE
);
850 if (quiet
&& !do_check
)
853 _("the --quiet option is meaningful only when verifying checksums"));
854 usage (EXIT_FAILURE
);
857 if (strict
& !do_check
)
860 _("the --strict option is meaningful only when verifying checksums"));
861 usage (EXIT_FAILURE
);
864 if (!O_BINARY
&& binary
< 0)
868 argv
[argc
++] = bad_cast ("-");
870 for (; optind
< argc
; ++optind
)
872 char *file
= argv
[optind
];
875 ok
&= digest_check (file
);
878 int file_is_binary
= binary
;
880 if (! digest_file (file
, &file_is_binary
, bin_buffer
))
884 /* We don't really need to escape, and hence detect, the '\\'
885 char, and not doing so should be both forwards and backwards
886 compatible, since only escaped lines would have a '\\' char at
887 the start. However just in case users are directly comparing
888 against old (hashed) outputs, in the presence of files
889 containing '\\' characters, we decided to not simplify the
890 output in this case. */
891 bool needs_escape
= strchr (file
, '\\') || strchr (file
, '\n');
898 fputs (DIGEST_TYPE_STRING
, stdout
);
899 fputs (" (", stdout
);
900 print_filename (file
, needs_escape
);
901 fputs (") = ", stdout
);
906 /* Output a leading backslash if the file name contains
907 a newline or backslash. */
908 if (!prefix_tag
&& needs_escape
)
911 for (i
= 0; i
< (digest_hex_bytes
/ 2); ++i
)
912 printf ("%02x", bin_buffer
[i
]);
918 putchar (file_is_binary
? '*' : ' ');
920 print_filename (file
, needs_escape
);
928 if (have_read_stdin
&& fclose (stdin
) == EOF
)
929 error (EXIT_FAILURE
, errno
, _("standard input"));
931 return ok
? EXIT_SUCCESS
: EXIT_FAILURE
;