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: