Subject: Re: bug#7155: [md5sum] does not accept

From: Pádraig Brady <[email-masked]>
Date: Fri, 16 Sep 2011 13:54:17 +0100

On 09/14/2011 11:43 PM, Rimas Kudelis wrote:
> 2011.09.14 17:12, Jim Meyering rašė:
>> Good point. I don't see a way to make GNU md5sum handle this automatically and safely. However, that's not a big deal: it's easy to convert from one format to the other using sed or perl. I'd be inclined to mark this "wontfix" (because we cannot) or simply to close it. 
> 
> 
> I think you could also implement this as a commandline switch, right?

Right. But that complicates the interface unnecessarily I think.

I'm going to apply the attached to give automatic support,
with the aforementioned caveat that BSD -r format checksums
where the _first_ file starts with a ' ' or '*' are not supported.
In that very unlikely case, one can always preprocess with sed 's/ /  /'

cheers,
Pádraig.
From 29904f907bfa22c8492176a0e6c2bb65deac0e9b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <[email-masked]>
Date: Fri, 16 Sep 2011 11:47:35 +0100
Subject: [PATCH] md5sum: handle BSD reversed format checksums

* src/md5sum.c (split_3): Detect and handle BSD reversed
format checksums.
* tests/misc/md5sum-bsd: Add a new test.
* tests/Makefile.am: Reference new test.
* NEWS: Mention the improvement
Suggested by Rimas Kudelis.
---
 NEWS                  |    5 +++++
 src/md5sum.c          |   26 ++++++++++++++++++++++----
 tests/Makefile.am     |    1 +
 tests/misc/md5sum-bsd |   41 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 69 insertions(+), 4 deletions(-)
 create mode 100755 tests/misc/md5sum-bsd

diff --git a/NEWS b/NEWS
index 879828e..8c218b7 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,11 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 * Noteworthy changes in release ?.? (????-??-??) [?]
 
+** Improvements
+
+  md5sum --check now supports the -r format from the corresponding BSD tool.
+  This also affects sha1sum, sha224sum, sha384sum and sha512sum.
+
 
 * Noteworthy changes in release 8.13 (2011-09-08) [stable]
 
diff --git a/src/md5sum.c b/src/md5sum.c
index ff9538a..9de34a5 100644
--- a/src/md5sum.c
+++ b/src/md5sum.c
@@ -99,7 +99,7 @@
    not include any newline character at the end of a line.  */
 #define MIN_DIGEST_LINE_LENGTH \
   (DIGEST_HEX_BYTES /* length of hexadecimal message digest */ \
-   + 2 /* blank and binary indicator */ \
+   + 1 /* blank */ \
    + 1 /* minimum filename length */ )
 
 /* True if any of the files read were the standard input. */
@@ -126,6 +126,9 @@ static bool quiet = false;
    improperly formatted. */
 static bool strict = false;
 
+/* Whether a BSD reversed format checksum is detected.  */
+static int bsd_reversed = -1;
+
 /* For long options that have no equivalent short option, use a
    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
 enum
@@ -307,9 +310,24 @@ split_3 (char *s, size_t s_len,
 
   s[i++] = '\0';
 
-  if (s[i] != ' ' && s[i] != '*')
-    return false;
-  *binary = (s[i++] == '*');
+  /* If "bsd reversed" format detected.  */
+  if ((s_len - i == 1) || (s[i] != ' ' && s[i] != '*'))
+    {
+      /* Don't allow mixing bsd and standard formats,
+         to minimize security issues with attackers
+         renaming files with leading spaces.
+         This assumes that with bsd format checksums
+         that the first file name does not have
+         a leading ' ' or '*'.  */
+      if (bsd_reversed == 0)
+        return false;
+      bsd_reversed = 1;
+    }
+  else if (bsd_reversed != 1)
+    {
+      bsd_reversed = 0;
+      *binary = (s[i++] == '*');
+    }
 
   /* All characters between the type indicator and end of line are
      significant -- that includes leading and trailing white space.  */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b920aba..eeb4cab 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -198,6 +198,7 @@ TESTS =						\
   misc/id-context				\
   misc/id-groups				\
   misc/md5sum					\
+  misc/md5sum-bsd				\
   misc/md5sum-newline				\
   misc/md5sum-parallel				\
   misc/mknod					\
diff --git a/tests/misc/md5sum-bsd b/tests/misc/md5sum-bsd
new file mode 100755
index 0000000..324530c
--- /dev/null
+++ b/tests/misc/md5sum-bsd
@@ -0,0 +1,41 @@
+#!/bin/sh
+# make sure `md5sum -c' works for alternate BSD format (md5 -r)
+
+# Copyright (C) 2011 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ../src
+print_ver_ md5sum
+
+# Note we start this list with a name
+# that's unambiguous in BSD format.
+# I.E. one not starting with ' ' or '*'
+for i in 'a' ' b' '*c' 'dd' ' '; do
+  echo "$i" > "$i"
+  md5sum "$i" >> check.md5sum
+done
+sed 's/  / /' check.md5sum > check.md5
+
+# Note only a single format is supported per run
+md5sum --strict -c check.md5sum || fail=1
+md5sum --strict -c check.md5 || fail=1
+
+# If we skip the first entry in the BSD format checksums
+# then it'll be detected as standard format and error.
+# This unlikely caveat was thought better than mandating
+# an option to avoid the ambiguity.
+tail -n+2 check.md5 | md5sum --strict -c && fail=1
+
+Exit $fail
-- 
1.7.6