1/* Compute MD5, SHA1, SHA224, SHA256, SHA384 or SHA512 checksum of files or strings 2 Copyright (C) 1995-2010 Free Software Foundation, Inc. 3 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. 8 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. 13 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/>. */ 16 17/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>. */ 18 19#include <config.h> 20 21#include <getopt.h> 22#include <sys/types.h> 23 24#include "system.h" 25 26#if HASH_ALGO_MD5 27# include "md5.h" 28#endif 29#if HASH_ALGO_SHA1 30# include "sha1.h" 31#endif 32#if HASH_ALGO_SHA256 || HASH_ALGO_SHA224 33# include "sha256.h" 34#endif 35#if HASH_ALGO_SHA512 || HASH_ALGO_SHA384 36# include "sha512.h" 37#endif 38#include "error.h" 39#include "stdio--.h" 40#include "xfreopen.h" 41 42/* The official name of this program (e.g., no `g' prefix). */ 43#if HASH_ALGO_MD5 44# define PROGRAM_NAME "md5sum" 45# define DIGEST_TYPE_STRING "MD5" 46# define DIGEST_STREAM md5_stream 47# define DIGEST_BITS 128 48# define DIGEST_REFERENCE "RFC 1321" 49# define DIGEST_ALIGN 4 50#elif HASH_ALGO_SHA1 51# define PROGRAM_NAME "sha1sum" 52# define DIGEST_TYPE_STRING "SHA1" 53# define DIGEST_STREAM sha1_stream 54# define DIGEST_BITS 160 55# define DIGEST_REFERENCE "FIPS-180-1" 56# define DIGEST_ALIGN 4 57#elif HASH_ALGO_SHA256 58# define PROGRAM_NAME "sha256sum" 59# define DIGEST_TYPE_STRING "SHA256" 60# define DIGEST_STREAM sha256_stream 61# define DIGEST_BITS 256 62# define DIGEST_REFERENCE "FIPS-180-2" 63# define DIGEST_ALIGN 4 64#elif HASH_ALGO_SHA224 65# define PROGRAM_NAME "sha224sum" 66# define DIGEST_TYPE_STRING "SHA224" 67# define DIGEST_STREAM sha224_stream 68# define DIGEST_BITS 224 69# define DIGEST_REFERENCE "RFC 3874" 70# define DIGEST_ALIGN 4 71#elif HASH_ALGO_SHA512 72# define PROGRAM_NAME "sha512sum" 73# define DIGEST_TYPE_STRING "SHA512" 74# define DIGEST_STREAM sha512_stream 75# define DIGEST_BITS 512 76# define DIGEST_REFERENCE "FIPS-180-2" 77# define DIGEST_ALIGN 8 78#elif HASH_ALGO_SHA384 79# define PROGRAM_NAME "sha384sum" 80# define DIGEST_TYPE_STRING "SHA384" 81# define DIGEST_STREAM sha384_stream 82# define DIGEST_BITS 384 83# define DIGEST_REFERENCE "FIPS-180-2" 84# define DIGEST_ALIGN 8 85#else 86# error "Can't decide which hash algorithm to compile." 87#endif 88 89#define DIGEST_HEX_BYTES (DIGEST_BITS / 4) 90#define DIGEST_BIN_BYTES (DIGEST_BITS / 8) 91 92#define AUTHORS \ 93 proper_name ("Ulrich Drepper"), \ 94 proper_name ("Scott Miller"), \ 95 proper_name ("David Madore") 96 97/* The minimum length of a valid digest line. This length does 98 not include any newline character at the end of a line. */ 99#define MIN_DIGEST_LINE_LENGTH \ 100 (DIGEST_HEX_BYTES /* length of hexadecimal message digest */ \ 101 + 2 /* blank and binary indicator */ \ 102 + 1 /* minimum filename length */ ) 103 104/* True if any of the files read were the standard input. */ 105static bool have_read_stdin; 106 107/* The minimum length of a valid checksum line for the selected algorithm. */ 108static size_t min_digest_line_length; 109 110/* Set to the length of a digest hex string for the selected algorithm. */ 111static size_t digest_hex_bytes; 112 113/* With --check, don't generate any output. 114 The exit code indicates success or failure. */ 115static bool status_only = false; 116 117/* With --check, print a message to standard error warning about each 118 improperly formatted checksum line. */ 119static bool warn = false; 120 121/* With --check, suppress the "OK" printed for each verified file. */ 122static bool quiet = false; 123 124/* For long options that have no equivalent short option, use a 125 non-character as a pseudo short option, starting with CHAR_MAX + 1. */ 126enum 127{ 128 STATUS_OPTION = CHAR_MAX + 1, 129 QUIET_OPTION 130}; 131 132static struct option const long_options[] = 133{ 134 { "binary", no_argument, NULL, 'b' }, 135 { "check", no_argument, NULL, 'c' }, 136 { "quiet", no_argument, NULL, QUIET_OPTION }, 137 { "status", no_argument, NULL, STATUS_OPTION }, 138 { "text", no_argument, NULL, 't' }, 139 { "warn", no_argument, NULL, 'w' }, 140 { GETOPT_HELP_OPTION_DECL }, 141 { GETOPT_VERSION_OPTION_DECL }, 142 { NULL, 0, NULL, 0 } 143}; 144 145void 146usage (int status) 147{ 148 if (status != EXIT_SUCCESS) 149 fprintf (stderr, _("Try `%s --help' for more information.\n"), 150 program_name); 151 else 152 { 153 printf (_("\ 154Usage: %s [OPTION]... [FILE]...\n\ 155Print or check %s (%d-bit) checksums.\n\ 156With no FILE, or when FILE is -, read standard input.\n\ 157\n\ 158"), 159 program_name, 160 DIGEST_TYPE_STRING, 161 DIGEST_BITS); 162 if (O_BINARY) 163 fputs (_("\ 164 -b, --binary read in binary mode (default unless reading tty stdin)\n\ 165"), stdout); 166 else 167 fputs (_("\ 168 -b, --binary read in binary mode\n\ 169"), stdout); 170 printf (_("\ 171 -c, --check read %s sums from the FILEs and check them\n"), 172 DIGEST_TYPE_STRING); 173 if (O_BINARY) 174 fputs (_("\ 175 -t, --text read in text mode (default if reading tty stdin)\n\ 176"), stdout); 177 else 178 fputs (_("\ 179 -t, --text read in text mode (default)\n\ 180"), stdout); 181 fputs (_("\ 182\n\ 183The following three options are useful only when verifying checksums:\n\ 184 --quiet don't print OK for each successfully verified file\n\ 185 --status don't output anything, status code shows success\n\ 186 -w, --warn warn about improperly formatted checksum lines\n\ 187\n\ 188"), stdout); 189 fputs (HELP_OPTION_DESCRIPTION, stdout); 190 fputs (VERSION_OPTION_DESCRIPTION, stdout); 191 printf (_("\ 192\n\ 193The sums are computed as described in %s. When checking, the input\n\ 194should be a former output of this program. The default mode is to print\n\ 195a line with checksum, a character indicating type (`*' for binary, ` ' for\n\ 196text), and name for each FILE.\n"), 197 DIGEST_REFERENCE); 198 emit_ancillary_info (); 199 } 200 201 exit (status); 202} 203 204#define ISWHITE(c) ((c) == ' ' || (c) == '\t') 205 206/* Split the checksum string S (of length S_LEN) from a BSD 'md5' or 207 'sha1' command into two parts: a hexadecimal digest, and the file 208 name. S is modified. Return true if successful. */ 209 210static bool 211bsd_split_3 (char *s, size_t s_len, unsigned char **hex_digest, char **file_name) 212{ 213 size_t i; 214 215 if (s_len == 0) 216 return false; 217 218 *file_name = s; 219 220 /* Find end of filename. The BSD 'md5' and 'sha1' commands do not escape 221 filenames, so search backwards for the last ')'. */ 222 i = s_len - 1; 223 while (i && s[i] != ')') 224 i--; 225 226 if (s[i] != ')') 227 return false; 228 229 s[i++] = '\0'; 230 231 while (ISWHITE (s[i])) 232 i++; 233 234 if (s[i] != '=') 235 return false; 236 237 i++; 238 239 while (ISWHITE (s[i])) 240 i++; 241 242 *hex_digest = (unsigned char *) &s[i]; 243 return true; 244} 245 246/* Split the string S (of length S_LEN) into three parts: 247 a hexadecimal digest, binary flag, and the file name. 248 S is modified. Return true if successful. */ 249 250static bool 251split_3 (char *s, size_t s_len, 252 unsigned char **hex_digest, int *binary, char **file_name) 253{ 254 bool escaped_filename = false; 255 size_t algo_name_len; 256 257 size_t i = 0; 258 while (ISWHITE (s[i])) 259 ++i; 260 261 /* Check for BSD-style checksum line. */ 262 algo_name_len = strlen (DIGEST_TYPE_STRING); 263 if (strncmp (s + i, DIGEST_TYPE_STRING, algo_name_len) == 0) 264 { 265 if (s[i + algo_name_len] == ' ') 266 ++i; 267 if (s[i + algo_name_len] == '(') 268 { 269 *binary = 0; 270 return bsd_split_3 (s + i + algo_name_len + 1, 271 s_len - (i + algo_name_len + 1), 272 hex_digest, file_name); 273 } 274 } 275 276 /* Ignore this line if it is too short. 277 Each line must have at least `min_digest_line_length - 1' (or one more, if 278 the first is a backslash) more characters to contain correct message digest 279 information. */ 280 if (s_len - i < min_digest_line_length + (s[i] == '\\')) 281 return false; 282 283 if (s[i] == '\\') 284 { 285 ++i; 286 escaped_filename = true; 287 } 288 *hex_digest = (unsigned char *) &s[i]; 289 290 /* The first field has to be the n-character hexadecimal 291 representation of the message digest. If it is not followed 292 immediately by a white space it's an error. */ 293 i += digest_hex_bytes; 294 if (!ISWHITE (s[i])) 295 return false; 296 297 s[i++] = '\0'; 298 299 if (s[i] != ' ' && s[i] != '*') 300 return false; 301 *binary = (s[i++] == '*'); 302 303 /* All characters between the type indicator and end of line are 304 significant -- that includes leading and trailing white space. */ 305 *file_name = &s[i]; 306 307 if (escaped_filename) 308 { 309 /* Translate each `\n' string in the file name to a NEWLINE, 310 and each `\\' string to a backslash. */ 311 312 char *dst = &s[i]; 313 314 while (i < s_len) 315 { 316 switch (s[i]) 317 { 318 case '\\': 319 if (i == s_len - 1) 320 { 321 /* A valid line does not end with a backslash. */ 322 return false; 323 } 324 ++i; 325 switch (s[i++]) 326 { 327 case 'n': 328 *dst++ = '\n'; 329 break; 330 case '\\': 331 *dst++ = '\\'; 332 break; 333 default: 334 /* Only `\' or `n' may follow a backslash. */ 335 return false; 336 } 337 break; 338 339 case '\0': 340 /* The file name may not contain a NUL. */ 341 return false; 342 break; 343 344 default: 345 *dst++ = s[i++]; 346 break; 347 } 348 } 349 *dst = '\0'; 350 } 351 return true; 352} 353 354/* Return true if S is a NUL-terminated string of DIGEST_HEX_BYTES hex digits. 355 Otherwise, return false. */ 356static bool 357hex_digits (unsigned char const *s) 358{ 359 unsigned int i; 360 for (i = 0; i < digest_hex_bytes; i++) 361 { 362 if (!isxdigit (*s)) 363 return false; 364 ++s; 365 } 366 return *s == '\0'; 367} 368 369/* An interface to the function, DIGEST_STREAM. 370 Operate on FILENAME (it may be "-"). 371 372 *BINARY indicates whether the file is binary. BINARY < 0 means it 373 depends on whether binary mode makes any difference and the file is 374 a terminal; in that case, clear *BINARY if the file was treated as 375 text because it was a terminal. 376 377 Put the checksum in *BIN_RESULT, which must be properly aligned. 378 Return true if successful. */ 379 380static bool 381digest_file (const char *filename, int *binary, unsigned char *bin_result) 382{ 383 FILE *fp; 384 int err; 385 bool is_stdin = STREQ (filename, "-"); 386 387 if (is_stdin) 388 { 389 have_read_stdin = true; 390 fp = stdin; 391 if (O_BINARY && *binary) 392 { 393 if (*binary < 0) 394 *binary = ! isatty (STDIN_FILENO); 395 if (*binary) 396 xfreopen (NULL, "rb", stdin); 397 } 398 } 399 else 400 { 401 fp = fopen (filename, (O_BINARY && *binary ? "rb" : "r")); 402 if (fp == NULL) 403 { 404 error (0, errno, "%s", filename); 405 return false; 406 } 407 } 408 409 err = DIGEST_STREAM (fp, bin_result); 410 if (err) 411 { 412 error (0, errno, "%s", filename); 413 if (fp != stdin) 414 fclose (fp); 415 return false; 416 } 417 418 if (!is_stdin && fclose (fp) != 0) 419 { 420 error (0, errno, "%s", filename); 421 return false; 422 } 423 424 return true; 425} 426 427static bool 428digest_check (const char *checkfile_name) 429{ 430 FILE *checkfile_stream; 431 uintmax_t n_properly_formatted_lines = 0; 432 uintmax_t n_mismatched_checksums = 0; 433 uintmax_t n_open_or_read_failures = 0; 434 unsigned char bin_buffer_unaligned[DIGEST_BIN_BYTES + DIGEST_ALIGN]; 435 /* Make sure bin_buffer is properly aligned. */ 436 unsigned char *bin_buffer = ptr_align (bin_buffer_unaligned, DIGEST_ALIGN); 437 uintmax_t line_number; 438 char *line; 439 size_t line_chars_allocated; 440 bool is_stdin = STREQ (checkfile_name, "-"); 441 442 if (is_stdin) 443 { 444 have_read_stdin = true; 445 checkfile_name = _("standard input"); 446 checkfile_stream = stdin; 447 } 448 else 449 { 450 checkfile_stream = fopen (checkfile_name, "r"); 451 if (checkfile_stream == NULL) 452 { 453 error (0, errno, "%s", checkfile_name); 454 return false; 455 } 456 } 457 458 line_number = 0; 459 line = NULL; 460 line_chars_allocated = 0; 461 do 462 { 463 char *filename IF_LINT (= NULL); 464 int binary; 465 unsigned char *hex_digest IF_LINT (= NULL); 466 ssize_t line_length; 467 468 ++line_number; 469 if (line_number == 0) 470 error (EXIT_FAILURE, 0, _("%s: too many checksum lines"), 471 checkfile_name); 472 473 line_length = getline (&line, &line_chars_allocated, checkfile_stream); 474 if (line_length <= 0) 475 break; 476 477 /* Ignore comment lines, which begin with a '#' character. */ 478 if (line[0] == '#') 479 continue; 480 481 /* Remove any trailing newline. */ 482 if (line[line_length - 1] == '\n') 483 line[--line_length] = '\0'; 484 485 if (! (split_3 (line, line_length, &hex_digest, &binary, &filename) 486 && ! (is_stdin && STREQ (filename, "-")) 487 && hex_digits (hex_digest))) 488 { 489 if (warn) 490 { 491 error (0, 0, 492 _("%s: %" PRIuMAX 493 ": improperly formatted %s checksum line"), 494 checkfile_name, line_number, 495 DIGEST_TYPE_STRING); 496 } 497 } 498 else 499 { 500 static const char bin2hex[] = { '0', '1', '2', '3', 501 '4', '5', '6', '7', 502 '8', '9', 'a', 'b', 503 'c', 'd', 'e', 'f' }; 504 bool ok; 505 506 ++n_properly_formatted_lines; 507 508 ok = digest_file (filename, &binary, bin_buffer); 509 510 if (!ok) 511 { 512 ++n_open_or_read_failures; 513 if (!status_only) 514 { 515 printf (_("%s: FAILED open or read\n"), filename); 516 } 517 } 518 else 519 { 520 size_t digest_bin_bytes = digest_hex_bytes / 2; 521 size_t cnt; 522 /* Compare generated binary number with text representation 523 in check file. Ignore case of hex digits. */ 524 for (cnt = 0; cnt < digest_bin_bytes; ++cnt) 525 { 526 if (tolower (hex_digest[2 * cnt]) 527 != bin2hex[bin_buffer[cnt] >> 4] 528 || (tolower (hex_digest[2 * cnt + 1]) 529 != (bin2hex[bin_buffer[cnt] & 0xf]))) 530 break; 531 } 532 if (cnt != digest_bin_bytes) 533 ++n_mismatched_checksums; 534 535 if (!status_only) 536 { 537 if (cnt != digest_bin_bytes) 538 printf ("%s: %s\n", filename, _("FAILED")); 539 else if (!quiet) 540 printf ("%s: %s\n", filename, _("OK")); 541 } 542 } 543 } 544 } 545 while (!feof (checkfile_stream) && !ferror (checkfile_stream)); 546 547 free (line); 548 549 if (ferror (checkfile_stream)) 550 { 551 error (0, 0, _("%s: read error"), checkfile_name); 552 return false; 553 } 554 555 if (!is_stdin && fclose (checkfile_stream) != 0) 556 { 557 error (0, errno, "%s", checkfile_name); 558 return false; 559 } 560 561 if (n_properly_formatted_lines == 0) 562 { 563 /* Warn if no tests are found. */ 564 error (0, 0, _("%s: no properly formatted %s checksum lines found"), 565 checkfile_name, DIGEST_TYPE_STRING); 566 } 567 else 568 { 569 if (!status_only) 570 { 571 if (n_open_or_read_failures != 0) 572 error (0, 0, 573 ngettext ("WARNING: %" PRIuMAX " of %" PRIuMAX 574 " listed file could not be read", 575 "WARNING: %" PRIuMAX " of %" PRIuMAX 576 " listed files could not be read", 577 select_plural (n_properly_formatted_lines)), 578 n_open_or_read_failures, n_properly_formatted_lines); 579 580 if (n_mismatched_checksums != 0) 581 { 582 uintmax_t n_computed_checksums = 583 (n_properly_formatted_lines - n_open_or_read_failures); 584 error (0, 0, 585 ngettext ("WARNING: %" PRIuMAX " of %" PRIuMAX 586 " computed checksum did NOT match", 587 "WARNING: %" PRIuMAX " of %" PRIuMAX 588 " computed checksums did NOT match", 589 select_plural (n_computed_checksums)), 590 n_mismatched_checksums, n_computed_checksums); 591 } 592 } 593 } 594 595 return (n_properly_formatted_lines != 0 596 && n_mismatched_checksums == 0 597 && n_open_or_read_failures == 0); 598} 599 600int 601main (int argc, char **argv) 602{ 603 unsigned char bin_buffer_unaligned[DIGEST_BIN_BYTES + DIGEST_ALIGN]; 604 /* Make sure bin_buffer is properly aligned. */ 605 unsigned char *bin_buffer = ptr_align (bin_buffer_unaligned, DIGEST_ALIGN); 606 bool do_check = false; 607 int opt; 608 bool ok = true; 609 int binary = -1; 610 611 /* Setting values of global variables. */ 612 initialize_main (&argc, &argv); 613 set_program_name (argv[0]); 614 setlocale (LC_ALL, ""); 615 bindtextdomain (PACKAGE, LOCALEDIR); 616 textdomain (PACKAGE); 617 618 atexit (close_stdout); 619 620 /* Line buffer stdout to ensure lines are written atomically and immediately 621 so that processes running in parallel do not intersperse their output. */ 622 setvbuf (stdout, NULL, _IOLBF, 0); 623 624 while ((opt = getopt_long (argc, argv, "bctw", long_options, NULL)) != -1) 625 switch (opt) 626 { 627 case 'b': 628 binary = 1; 629 break; 630 case 'c': 631 do_check = true; 632 break; 633 case STATUS_OPTION: 634 status_only = true; 635 warn = false; 636 quiet = false; 637 break; 638 case 't': 639 binary = 0; 640 break; 641 case 'w': 642 status_only = false; 643 warn = true; 644 quiet = false; 645 break; 646 case QUIET_OPTION: 647 status_only = false; 648 warn = false; 649 quiet = true; 650 break; 651 case_GETOPT_HELP_CHAR; 652 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); 653 default: 654 usage (EXIT_FAILURE); 655 } 656 657 min_digest_line_length = MIN_DIGEST_LINE_LENGTH; 658 digest_hex_bytes = DIGEST_HEX_BYTES; 659 660 if (0 <= binary && do_check) 661 { 662 error (0, 0, _("the --binary and --text options are meaningless when " 663 "verifying checksums")); 664 usage (EXIT_FAILURE); 665 } 666 667 if (status_only && !do_check) 668 { 669 error (0, 0, 670 _("the --status option is meaningful only when verifying checksums")); 671 usage (EXIT_FAILURE); 672 } 673 674 if (warn && !do_check) 675 { 676 error (0, 0, 677 _("the --warn option is meaningful only when verifying checksums")); 678 usage (EXIT_FAILURE); 679 } 680 681 if (quiet && !do_check) 682 { 683 error (0, 0, 684 _("the --quiet option is meaningful only when verifying checksums")); 685 usage (EXIT_FAILURE); 686 } 687 688 if (!O_BINARY && binary < 0) 689 binary = 0; 690 691 if (optind == argc) 692 argv[argc++] = bad_cast ("-"); 693 694 for (; optind < argc; ++optind) 695 { 696 char *file = argv[optind]; 697 698 if (do_check) 699 ok &= digest_check (file); 700 else 701 { 702 int file_is_binary = binary; 703 704 if (! digest_file (file, &file_is_binary, bin_buffer)) 705 ok = false; 706 else 707 { 708 size_t i; 709 710 /* Output a leading backslash if the file name contains 711 a newline or backslash. */ 712 if (strchr (file, '\n') || strchr (file, '\\')) 713 putchar ('\\'); 714 715 for (i = 0; i < (digest_hex_bytes / 2); ++i) 716 printf ("%02x", bin_buffer[i]); 717 718 putchar (' '); 719 if (file_is_binary) 720 putchar ('*'); 721 else 722 putchar (' '); 723 724 /* Translate each NEWLINE byte to the string, "\\n", 725 and each backslash to "\\\\". */ 726 for (i = 0; i < strlen (file); ++i) 727 { 728 switch (file[i]) 729 { 730 case '\n': 731 fputs ("\\n", stdout); 732 break; 733 734 case '\\': 735 fputs ("\\\\", stdout); 736 break; 737 738 default: 739 putchar (file[i]); 740 break; 741 } 742 } 743 putchar ('\n'); 744 } 745 } 746 } 747 748 if (have_read_stdin && fclose (stdin) == EOF) 749 error (EXIT_FAILURE, errno, _("standard input")); 750 751 exit (ok ? EXIT_SUCCESS : EXIT_FAILURE); 752} 753