On 4/15/05, Peter Jones <pjones@xxxxxxxxxx> wrote: > On Fri, 2005-04-15 at 17:03 +0100, Luciano Miguel Ferreira Rocha wrote: > > > One option is to create a copy of the md5ctx and do the MD5_Final on > > that one. > > Just having another context structure and copying the data with memcpy > should get another perfectly valid context to run MD5_Final on. Ok, you're both very right... And this fully well addresses all of the concerns I mentioned in the previous email. This was quite simple, I'm sorry I missed. Basically, two instances of: memcpy(&fragmd5ctx, &md5ctx, sizeof(MD5_CTX)); MD5_Final(fragmd5sum, &fragmd5ctx); Thus, we can continuously overwrite fragmd5ctx and never actually do the MD5_Final() on md5ctx until the very end. So here's the third revision... Dustin
--- anaconda-10.1.0.2/isomd5sum/libcheckisomd5.c 2005-04-19 15:34:15.000000000 -0400 +++ anaconda-10.1.0.2.dustin/isomd5sum/libcheckisomd5.c 2005-04-19 16:10:03.000000000 -0400 @@ -1,6 +1,10 @@ /* Copyright 2001 Red Hat, Inc. */ /* Michael Fulbright msf@xxxxxxxxxx */ +/* 4/2005 Dustin Kirkland (dustin.kirkland@xxxxxxxxx) */ +/* Added support for checkpoint fragment sums; */ +/* Exits media check as soon as bad fragment md5sum'ed */ + #include <stdio.h> #include <stdlib.h> #include <sys/types.h> @@ -15,16 +19,20 @@ #define APPDATA_OFFSET 883 #define SIZE_OFFSET 84 +/* Length in characters of string used for fragment md5sum checking */ +#define FRAGMENT_SUM_LENGTH 60 + #define MAX(x, y) ((x > y) ? x : y) #define MIN(x, y) ((x < y) ? x : y) /* finds primary volume descriptor and returns info from it */ /* mediasum must be a preallocated buffer at least 33 bytes long */ -static int parsepvd(int isofd, char *mediasum, int *skipsectors, long long *isosize, int *supported) { +/* fragmentsums must be a preallocated buffer at least FRAGMENT_SUM_LENGTH+1 bytes long */ +static int parsepvd(int isofd, char *mediasum, int *skipsectors, long long *isosize, int *supported, char *fragmentsums, long long *fragmentcount) { unsigned char buf[2048]; unsigned char buf2[512]; unsigned char tmpbuf[512]; - int skipfnd, md5fnd, supportedfnd; + int skipfnd, md5fnd, supportedfnd, fragsumfnd, fragcntfnd; unsigned int loc; long long offset; unsigned char *p; @@ -54,6 +62,8 @@ md5fnd = 0; skipfnd = 0; + fragsumfnd = 0; + fragcntfnd = 0; supportedfnd = 0; loc = 0; while (loc < 512) { @@ -92,14 +102,46 @@ } else if (!strncmp(buf2 + loc, "RHLISOSTATUS=1", 14)) { *supported = 1; supportedfnd = 1; + for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++); } else if (!strncmp(buf2 + loc, "RHLISOSTATUS=0", 14)) { *supported = 0; supportedfnd = 1; - } else { + for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++); + } else if (!strncmp(buf2 + loc, "FRAGMENT SUMS = ", 16)) { + /* make sure we dont walk off end */ + if ((loc + FRAGMENT_SUM_LENGTH) > 511) + return -1; + + memcpy(fragmentsums, buf2 + loc + 16, FRAGMENT_SUM_LENGTH); + fragmentsums[FRAGMENT_SUM_LENGTH] = '\0'; + fragsumfnd = 1; + loc += FRAGMENT_SUM_LENGTH + 16; + for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++); + } else if (!strncmp(buf2 + loc, "FRAGMENT COUNT = ", 17)) { + char *errptr; + /* make sure we dont walk off end */ + if ((loc + 17) > 511) + return -1; + + loc = loc + 17; + for (p=tmpbuf; buf2[loc] != ';' && loc < 512; p++, loc++) + *p = buf2[loc]; + + *p = '\0'; + + *fragmentcount = strtol(tmpbuf, &errptr, 10); + if (errptr && *errptr) { + return -1; + } else { + fragcntfnd = 1; + } + + for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++); + } else { loc++; } - if ((skipfnd & md5fnd) & supportedfnd) + if ((skipfnd & md5fnd & fragsumfnd & fragcntfnd) & supportedfnd) break; } @@ -119,19 +161,25 @@ /* both strings must be pre-allocated at least 33 chars in length */ static int checkmd5sum(int isofd, char *mediasum, char *computedsum, int quiet) { int nread; - int i; + int i, j; int appdata_start_offset, appdata_end_offset; int nattempt; int skipsectors; int supported; + int current_fragment = 0; + int previous_fragment = 0; unsigned int bufsize = 32768; unsigned char md5sum[16]; + unsigned char fragmd5sum[16]; unsigned int len; unsigned char *buf; long long isosize, offset, pvd_offset, apoff; - MD5_CTX md5ctx; + char fragmentsums[FRAGMENT_SUM_LENGTH]; + char thisfragsum[FRAGMENT_SUM_LENGTH]; + long long fragmentcount = 0; + MD5_CTX md5ctx, fragmd5ctx; - if ((pvd_offset = parsepvd(isofd, mediasum, &skipsectors, &isosize, &supported)) < 0) + if ((pvd_offset = parsepvd(isofd, mediasum, &skipsectors, &isosize, &supported, fragmentsums, &fragmentcount)) < 0) return -1; /* printf("Mediasum = %s\n",mediasum); */ @@ -179,6 +227,30 @@ } MD5_Update(&md5ctx, buf, nread); + if (fragmentcount) { + current_fragment = offset * (fragmentcount+1) / (isosize - skipsectors*2048); + /* if we're onto the next fragment, calculate the previous sum and check */ + if ( current_fragment != previous_fragment ) { + memcpy(&fragmd5ctx, &md5ctx, sizeof(MD5_CTX)); + MD5_Final(fragmd5sum, &fragmd5ctx); + *computedsum = '\0'; + j = (current_fragment-1)*FRAGMENT_SUM_LENGTH/fragmentcount; + for (i=0; i<FRAGMENT_SUM_LENGTH/fragmentcount; i++) { + char tmpstr[2]; + snprintf(tmpstr, 2, "%01x", fragmd5sum[i]); + strncat(computedsum, tmpstr, 2); + thisfragsum[i] = fragmentsums[j++]; + } + thisfragsum[j] = '\0'; + /* printf("\nFragment [%i]: %s ?= %s\n", previous_fragment, computedsum, thisfragsum); */ + previous_fragment = current_fragment; + /* Exit immediatiately if current fragment sum is incorrect */ + if (strcmp(thisfragsum, computedsum) != 0) { + free(buf); + return 0; + } + } + } offset = offset + nread; if (!quiet) { @@ -201,7 +273,7 @@ for (i=0; i<16; i++) { char tmpstr[4]; snprintf (tmpstr, 4, "%02x", md5sum[i]); - strcat(computedsum, tmpstr); + strncat(computedsum, tmpstr, 2); } /* printf("mediasum, computedsum = %s %s\n", mediasum, computedsum); */ @@ -210,7 +282,7 @@ return 0; else return 1; - } +} #if 0 @@ -233,8 +305,10 @@ static int doMediaCheck(int isofd, char *mediasum, char *computedsum, long long *isosize, int *supported, int quiet) { int rc; int skipsectors; + long long fragmentcount = 0; + char fragmentsums[FRAGMENT_SUM_LENGTH+1]; - if (parsepvd(isofd, mediasum, &skipsectors, isosize, supported) < 0) { + if (parsepvd(isofd, mediasum, &skipsectors, isosize, supported, fragmentsums, &fragmentcount) < 0) { fprintf(stderr, "Unable to read the disc checksum from the " "primary volume descriptor.\nThis probably " "means the disc was created without adding the " @@ -290,6 +364,8 @@ int isofd; char mediasum[64]; long long isosize; + char fragmentsums[FRAGMENT_SUM_LENGTH+1]; + long long fragmentcount = 0; int supported; int skipsectors; @@ -300,7 +376,7 @@ exit(1); } - if (parsepvd(isofd, mediasum, &skipsectors, &isosize, &supported) < 0) { + if (parsepvd(isofd, mediasum, &skipsectors, &isosize, &supported, fragmentsums, &fragmentcount) < 0) { fprintf(stderr, "%s: Could not get pvd data", file); fprintf(stderr, "\nUnable to read the disc checksum from the " "primary volume descriptor.\nThis probably " @@ -312,4 +388,8 @@ close(isofd); printf("%s: %s\n", file, mediasum); + if ( (strlen(fragmentsums) > 0) && (fragmentcount > 0) ) { + printf("Fragment sums: %s\n", fragmentsums); + printf("Fragment count: %lld\n", fragmentcount); + } }