/* Copyright 2001 Red Hat, Inc. */
|
|
/* Michael Fulbright msf@redhat.com */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "md5.h"
|
|
#include "libimplantisomd5.h"
|
|
|
|
#define APPDATA_OFFSET 883
|
|
#define SIZE_OFFSET 84
|
|
|
|
/* number of sectors to ignore at end of iso when computing sum */
|
|
#define SKIPSECTORS 15
|
|
|
|
#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, long long *isosize) {
|
|
unsigned char buf[2048];
|
|
long long offset;
|
|
unsigned char *p __attribute__((unused));
|
|
|
|
if (lseek(isofd, 16*2048, SEEK_SET) == -1)
|
|
return ((long long)-1);
|
|
|
|
offset = (16 * 2048);
|
|
for (;1;) {
|
|
if (read(isofd, buf, 2048L) == -1)
|
|
return ((long long)-1);
|
|
|
|
if (buf[0] == 1)
|
|
/* found primary volume descriptor */
|
|
break;
|
|
else if (buf[0] == 255)
|
|
/* hit end and didn't find primary volume descriptor */
|
|
return ((long long)-1);
|
|
offset += 2048L;
|
|
}
|
|
|
|
/* read out md5sum */
|
|
#if 0
|
|
memcpy(mediasum, buf + APPDATA_OFFSET + 13, 32);
|
|
mediasum[32] = '\0';
|
|
|
|
for (p=mediasum; *p; p++)
|
|
if (*p != ' ')
|
|
break;
|
|
|
|
/* if the md5sum was all spaces, we didn't find md5sum */
|
|
if (!*p)
|
|
return -1;
|
|
#endif
|
|
|
|
/* get isosize */
|
|
*isosize = (buf[SIZE_OFFSET]*0x1000000+buf[SIZE_OFFSET+1]*0x10000 +
|
|
buf[SIZE_OFFSET+2]*0x100 + buf[SIZE_OFFSET+3]) * 2048LL;
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
static unsigned int writeAppData(unsigned char *appdata, char *valstr, unsigned int loc) {
|
|
if (loc + strlen(valstr) > 511) {
|
|
printf("Attempted to write too much appdata, exiting...\n");
|
|
exit(-1);
|
|
}
|
|
|
|
memcpy(appdata + loc, valstr, strlen(valstr));
|
|
|
|
return loc+strlen(valstr);
|
|
}
|
|
|
|
|
|
|
|
|
|
int implantISOFile(char *fname, int supported, int forceit, int quiet, char **errstr) {
|
|
int i;
|
|
int isofd;
|
|
int nread;
|
|
int dirty;
|
|
int pvd_offset;
|
|
long long isosize, total;
|
|
unsigned char md5sum[16];
|
|
unsigned int loc;
|
|
unsigned char buf[2048];
|
|
unsigned char orig_appdata[512];
|
|
unsigned char new_appdata[512];
|
|
unsigned char mediasum[33];
|
|
char md5str[40];
|
|
MD5_CTX md5ctx;
|
|
|
|
isofd = open(fname, O_RDWR);
|
|
|
|
if (isofd < 0) {
|
|
*errstr = "Error - Unable to open file %s\n\n";
|
|
return -1;
|
|
}
|
|
|
|
pvd_offset = parsepvd(isofd, (char *)mediasum, &isosize);
|
|
if (pvd_offset < 0) {
|
|
*errstr = "Could not find primary volumne!\n\n";
|
|
return -1;
|
|
}
|
|
|
|
lseek(isofd, pvd_offset + APPDATA_OFFSET, SEEK_SET);
|
|
nread = read(isofd, orig_appdata, 512);
|
|
|
|
if (!forceit) {
|
|
dirty = 0;
|
|
for (i=0; i < 512; i++)
|
|
if (orig_appdata[i] != ' ')
|
|
dirty = 1;
|
|
|
|
if (dirty) {
|
|
*errstr = "Application data has been used - not implanting md5sum!\n";
|
|
return -1;
|
|
}
|
|
} else {
|
|
/* write out blanks to erase old app data */
|
|
lseek(isofd, pvd_offset + APPDATA_OFFSET, SEEK_SET);
|
|
memset(new_appdata, ' ', 512);
|
|
i = write(isofd, new_appdata, 512);
|
|
if (i<0) {
|
|
printf("write failed %d\n", i);
|
|
perror("");
|
|
}
|
|
}
|
|
|
|
/* now do md5sum */
|
|
lseek(isofd, 0L, SEEK_SET);
|
|
|
|
MD5_Init(&md5ctx);
|
|
|
|
total = 0;
|
|
/* read up to 15 sectors from end, due to problems reading last few */
|
|
/* sectors on burned CDs */
|
|
while (total < isosize - SKIPSECTORS*2048) {
|
|
nread = read(isofd, buf, 2048);
|
|
if (nread <= 0)
|
|
break;
|
|
|
|
MD5_Update(&md5ctx, buf, nread);
|
|
total = total + nread;
|
|
}
|
|
|
|
MD5_Final(md5sum, &md5ctx);
|
|
|
|
*md5str = '\0';
|
|
for (i=0; i<16; i++) {
|
|
char tmpstr[4];
|
|
snprintf (tmpstr, 4, "%02x", md5sum[i]);
|
|
strcat(md5str, tmpstr);
|
|
}
|
|
|
|
if (!quiet) {
|
|
printf("Inserting md5sum into iso image...\n");
|
|
printf("md5 = %s\n", md5str);
|
|
}
|
|
/* memcpy(new_appdata, orig_appdata, 512); */
|
|
memset(new_appdata, ' ', 512);
|
|
|
|
loc = 0;
|
|
loc = writeAppData(new_appdata, "ISO MD5SUM = ", loc);
|
|
loc = writeAppData(new_appdata, md5str, loc);
|
|
loc = writeAppData(new_appdata, ";", loc);
|
|
snprintf((char *)buf, sizeof(buf), "SKIPSECTORS = %d", SKIPSECTORS);
|
|
loc = writeAppData(new_appdata, (char *)buf, loc);
|
|
loc = writeAppData(new_appdata, ";", loc);
|
|
|
|
if (supported) {
|
|
if (!quiet)
|
|
printf("Setting supported flag to 1\n");
|
|
loc = writeAppData(new_appdata, "RHLISOSTATUS=1", loc);
|
|
} else {
|
|
if (!quiet)
|
|
printf("Setting supported flag to 0\n");
|
|
loc = writeAppData(new_appdata, "RHLISOSTATUS=0", loc);
|
|
}
|
|
|
|
loc = writeAppData(new_appdata, ";", loc);
|
|
|
|
loc = writeAppData(new_appdata, "THIS IS NOT THE SAME AS RUNNING MD5SUM ON THIS ISO!!", loc);
|
|
|
|
i = lseek(isofd, pvd_offset + APPDATA_OFFSET, SEEK_SET);
|
|
if (i<0)
|
|
printf("seek failed\n");
|
|
|
|
i = write(isofd, new_appdata, 512);
|
|
if (i<0) {
|
|
printf("write failed %d\n", i);
|
|
perror("");
|
|
}
|
|
|
|
close(isofd);
|
|
errstr = NULL;
|
|
return 0;
|
|
}
|