[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: md5 package summaries on ftp server (was Re: System integrity) (fwd)



BAHH!!!  Forgot the friggen patch!  Attached now.


Chris goes and skrews his head back on.....



----- Forwarded message from Chris Leishman <masklin@debian.org> -----

Date: Sat, 26 Jun 1999 01:04:43 +1000
From: Chris Leishman <masklin@debian.org>
To: Jason Gunthorpe <jgg@wakko.deltatee.com>
Cc: debian-devel@lists.debian.org
Subject: Re: md5 package summaries on ftp server (was Re: System integrity)
X-Mailer: Mutt 0.95.3i

On Wed, Jun 23, 1999 at 10:54:53PM -0600, Jason Gunthorpe wrote:
> On Thu, Jun 24, 1999 at 02:43:26PM +1000, Chris Leishman wrote:
<snip>
> > 
> > Fair enough.  Perhaps we should modify out .md5sums file to have the
> > following format...
> > 
> > MD5 file_mode file_uid file_gid file_size filename
> 
> The UID's need to be names not strings, tar has a mapping algorithm it 
> uses.. You should also express the mode in octal..

Ok - this is done in the attached patch for md5sum.c
Again, a -l option is used, but the mode is in octal and the user/group
are strings (except where unavailable, and a number is fallen back to).

<snip>
--- md5sum.c.old	Mon Nov  2 03:06:49 1998
+++ md5sum.c	Sat Jun 26 00:59:47 1999
@@ -16,6 +16,11 @@
 #include <stdio.h>
 #include <string.h>
 #include <getopt.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <ctype.h>
 #include "config.h"
 #include "md5.h"
 
@@ -52,6 +57,8 @@
 #endif
 #endif
 
+enum { NOERROR, MD5, MODE, USER, GROUP, SIZE };
+
 extern char *optarg;
 extern int optind;
 
@@ -59,12 +66,16 @@
 void print_digest(unsigned char *p);
 int mdfile(FILE *fp, unsigned char *digest);
 int do_check(FILE *chkf);
+int checkit(char *, char *, struct stat, int, char *, char *, int);
 int hex_digit(int c);
 int get_md5_line(FILE *fp, unsigned char *digest, char *file);
+int get_lmd5_line(FILE *,unsigned char *,char *,int *,char *,char *,int *);
+int print_longfile(char *filename);
 
 char *progname;
 int verbose = 0;
 int bin_mode = 0;
+int long_mode = 0;
 
 void
 main(int argc, char **argv)
@@ -79,9 +90,10 @@
 	textdomain(PACKAGE);
 
 	progname = *argv;
-	while ((opt = getopt(argc, argv, "cbvp:h")) != EOF) {
+	while ((opt = getopt(argc, argv, "cblvp:h")) != EOF) {
 		switch (opt) {
 			case 'c': check = 1; break;
+			case 'l': long_mode = 1; break;
 			case 'v': verbose = 1; break;
 			case 'b': bin_mode = 1; break;
 			default: usage();
@@ -125,7 +137,12 @@
 			rc = 2;
 		} else {
 			print_digest(digest);
-			printf(" %c%s\n", bin_mode ? '*' : ' ', *argv);
+			printf(" %c", bin_mode ? '*' : ' ');
+			if (long_mode)
+				print_longfile(*argv);
+			else
+				printf("%s", *argv);
+			putchar('\n');
 		}
 		fclose(fp);
 	}
@@ -135,9 +152,10 @@
 void
 usage()
 {
-        fputs(_("usage: md5sum [-bv] [-c [file]] | [file...]\n\
+        fputs(_("usage: md5sum [-blv] [-c [file]] | [file...]\n\
 Generates or checks MD5 Message Digests\n\
     -c  check message digests (default is generate)\n\
+    -l  long output (includes file mode, uid, byte size and filename)\n\
     -v  verbose, print file names when checking\n\
     -b  read files in binary mode\n\
 The input for -c should be the list of message digests and file names\n\
@@ -220,6 +238,53 @@
 	return rc;
 }
 
+int 
+get_lmd5_line(FILE *fp, unsigned char *digest, char *file, int *mode,
+   char *user, char *group, int *size)
+{
+	char buf[1024];
+	int i, d1, d2, rc;
+	char *p = buf;
+
+	if (fgets(buf, sizeof(buf), fp) == NULL)
+		return -1;
+
+	for (i = 0; i < 16; ++i) {
+		if ((d1 = hex_digit(*p++)) == -1)
+			return 0;
+		if ((d2 = hex_digit(*p++)) == -1)
+			return 0;
+		*digest++ = d1*16 + d2;
+	}
+	if (*p++ != ' ')
+		return 0;
+	/*
+	 * next char is an attribute char, space means text file
+	 * if it's a '*' the file should be checked in binary mode.
+	 */
+	if (*p == ' ')
+		rc = 1;
+	else if (*p == '*')
+		rc = 2;
+	else {
+		fprintf(stderr, _("%s: unrecognized line: %s"), progname, buf);
+		return 0;
+	}
+	++p;
+	if (sscanf(p, "%o %s %s %d", mode, user, group, size) < 4) {
+		fprintf(stderr, _("%s: unrecognized line: %s"), progname, buf);
+		return 0;
+	}
+	for(i=0; i<4;) if (isspace(*(p++))) i++;
+	i = strlen(p);
+	if (i < 2 || i > 255)
+		return 0;
+	p[i-1] = '\0';
+	strcpy(file, p);
+	return rc;
+}
+
+
 int
 do_check(FILE *chkf)
 {
@@ -228,8 +293,23 @@
 	char filename[256];
 	FILE *fp;
 	int flen = 14;
-
-	while ((rc = get_md5_line(chkf, chk_digest, filename)) >= 0) {
+	char user[256];
+	char grp[256];
+	int mode, size;
+	struct stat s;
+	int fail;
+
+	while (1) {
+		if (!long_mode)
+		{
+			rc = get_md5_line(chkf, chk_digest, filename);
+		}
+		else
+		{
+	       rc = get_lmd5_line(chkf, chk_digest, filename, &mode, user, 
+           grp, &size);
+		}
+		if (rc < 0) break;
 		if (rc == 0)	/* not an md5 line */
 			continue;
 		if (verbose) {
@@ -253,14 +333,53 @@
 			continue;
 		}
 		fclose(fp);
-		if (memcmp(chk_digest, file_digest, 16) != 0) {
-			if (verbose)
+		if (lstat(filename, &s) != 0)
+		{
+			fprintf(stderr, _("%s: Stat of %s failed\n"), progname, filename);
+			ex = 2;
+			continue;
+		}
+
+		fail = 0;
+		if (long_mode)
+			fail = checkit(chk_digest, file_digest, s, mode, user, grp, size);
+		else if (memcmp(chk_digest, file_digest, 16) != 0)
+			fail = MD5;
+			
+
+		if (fail != 0) ++failed;
+
+		if (!verbose && fail != 0)
+		{
+			fprintf(stderr, _("%s: "), progname);
+
+			switch (fail)
+			{
+				case MODE:
+					fprintf(stderr, _("MODE"));
+					break;
+				case USER:
+					fprintf(stderr, _("USER"));
+					break;
+				case GROUP:
+					fprintf(stderr, _("GROUP"));
+					break;
+				case SIZE:
+					fprintf(stderr, _("SIZE"));
+					break;
+				case MD5:
+					fprintf(stderr, _("MD5"));
+					break;
+			}
+			fprintf(stderr,_(" check failed for '%s'\n"), filename);
+		}
+		else if (verbose)
+		{
+			if (fail != 0)
 				fprintf(stderr, _("FAILED\n"));
 			else
-				fprintf(stderr, _("%s: MD5 check failed for '%s'\n"), progname, filename);
-			++failed;
-		} else if (verbose)
-			fprintf(stderr, _("OK\n"));
+				fprintf(stderr, _("OK\n"));
+		}
 		++checked;
 	}
 	if (verbose && failed)
@@ -274,3 +393,67 @@
 	return ex;
 }
 
+
+int checkit(char *chk_digest, char *file_digest, struct stat s, int mode, 
+		      char *user, char *grp, int size)
+{
+	char tempstr[256];
+	struct passwd *pent = getpwuid(s.st_uid);
+	struct group *gent = getgrgid(s.st_gid);
+
+	if (memcmp(chk_digest, file_digest, 16) != 0)
+		return MD5;
+
+	if (s.st_mode != mode)
+		return MODE;
+
+	if (!pent || strncmp(pent->pw_name,user,256))
+	{
+		snprintf(tempstr, 256, "%d", s.st_uid);
+
+		if (strncmp(tempstr,user,256))
+			return USER;
+	}
+
+	if (!gent || strncmp(gent->gr_name,grp,256))
+	{
+		snprintf(tempstr, 256, "%d", s.st_gid);
+
+		if (strncmp(tempstr,grp,256))
+			return GROUP;
+	}
+
+	if (s.st_size != size)
+		return SIZE;
+
+	return NOERROR;
+}
+
+            
+int print_longfile(char *filename)
+{
+	struct stat s;
+	struct passwd *pent;
+	struct group *gent;
+
+	if (lstat(filename, &s) != 0)
+	{
+		fprintf(stderr, _("%s: Stat of %s failed\n"), progname, filename);
+		return 1;
+	}
+
+	printf("%06o ", s.st_mode);
+	if ((pent = getpwuid(s.st_uid)) != NULL)
+		printf("%s ", pent->pw_name);
+	else
+		printf("%d ", s.st_uid);
+	
+	if ((gent = getgrgid(s.st_gid)) != NULL)
+		printf("%s ", gent->gr_name);
+	else
+		printf("%d ", s.st_gid);
+
+	printf("%d %s", (int) s.st_size, filename);
+
+	return 0;
+}

Reply to: