1
/* Copyright 2001 Red Hat, Inc. */
2
/* Michael Fulbright msf@redhat.com */
4
/* 4/2005 Dustin Kirkland (dustin.kirkland@gmail.com) */
5
/* Added support for checkpoint fragment sums; */
6
/* Allows for exiting media check when bad fragment md5sum'ed */
10
#include <sys/types.h>
17
#include "libimplantisomd5.h"
19
#define APPDATA_OFFSET 883
20
#define SIZE_OFFSET 84
22
/* Length in characters of string used for fragment md5sum checking */
23
#define FRAGMENT_SUM_LENGTH 60
24
/* FRAGMENT_COUNT must be an integral divisor or FRAGMENT_SUM_LENGTH */
25
/* 60 => 2, 3, 4, 5, 6, 10, 12, 15, 20, or 30 */
26
#define FRAGMENT_COUNT 20
28
/* number of sectors to ignore at end of iso when computing sum */
29
#define SKIPSECTORS 15
31
#define MAX(x, y) ((x > y) ? x : y)
32
#define MIN(x, y) ((x < y) ? x : y)
34
/* finds primary volume descriptor and returns info from it */
35
/* mediasum must be a preallocated buffer at least 33 bytes long */
36
static int parsepvd(int isofd, char *mediasum, long long *isosize) {
37
unsigned char buf[2048];
39
unsigned char *p __attribute__((unused));
41
if (lseek(isofd, 16*2048, SEEK_SET) == -1)
42
return ((long long)-1);
46
if (read(isofd, buf, 2048L) == -1)
47
return ((long long)-1);
50
/* found primary volume descriptor */
52
else if (buf[0] == 255)
53
/* hit end and didn't find primary volume descriptor */
54
return ((long long)-1);
60
memcpy(mediasum, buf + APPDATA_OFFSET + 13, 32);
63
for (p=mediasum; *p; p++)
67
/* if the md5sum was all spaces, we didn't find md5sum */
73
*isosize = (buf[SIZE_OFFSET]*0x1000000+buf[SIZE_OFFSET+1]*0x10000 +
74
buf[SIZE_OFFSET+2]*0x100 + buf[SIZE_OFFSET+3]) * 2048LL;
80
static unsigned int writeAppData(unsigned char *appdata, char *valstr, unsigned int loc) {
81
if (loc + strlen(valstr) > 511) {
82
printf("Attempted to write too much appdata, exiting...\n");
86
memcpy(appdata + loc, valstr, strlen(valstr));
88
return loc+strlen(valstr);
94
int implantISOFile(char *fname, int supported, int forceit, int quiet, char **errstr) {
100
int current_fragment = 0;
101
int previous_fragment = 0;
103
long long isosize, total;
104
unsigned char md5sum[16];
105
unsigned char fragmd5sum[16];
107
unsigned int bufsize = 32768;
109
unsigned char orig_appdata[512];
110
unsigned char new_appdata[512];
113
char fragstr[FRAGMENT_SUM_LENGTH+1];
114
MD5_CTX md5ctx, fragmd5ctx;
116
isofd = open(fname, O_RDWR);
119
*errstr = "Error - Unable to open file %s\n\n";
123
pvd_offset = parsepvd(isofd, mediasum, &isosize);
124
if (pvd_offset < 0) {
125
*errstr = "Could not find primary volumne!\n\n";
129
lseek(isofd, pvd_offset + APPDATA_OFFSET, SEEK_SET);
130
nread = read(isofd, orig_appdata, 512);
134
for (i=0; i < 512; i++)
135
if (orig_appdata[i] != ' ')
139
*errstr = "Application data has been used - not implanting md5sum!\n";
143
/* write out blanks to erase old app data */
144
lseek(isofd, pvd_offset + APPDATA_OFFSET, SEEK_SET);
145
memset(new_appdata, ' ', 512);
146
i = write(isofd, new_appdata, 512);
148
printf("write failed %d\n", i);
154
lseek(isofd, 0L, SEEK_SET);
158
buf = malloc(bufsize * sizeof(unsigned char));
161
/* read up to 15 sectors from end, due to problems reading last few */
162
/* sectors on burned CDs */
163
while (total < isosize - SKIPSECTORS*2048) {
164
nattempt = MIN(isosize - SKIPSECTORS*2048 - total, bufsize);
165
nread = read(isofd, buf, nattempt);
170
MD5_Update(&md5ctx, buf, nread);
172
/* if we're onto the next fragment, calculate the previous sum and write */
173
current_fragment = total * (FRAGMENT_COUNT+1) / (isosize - SKIPSECTORS*2048);
174
if ( current_fragment != previous_fragment ) {
175
memcpy(&fragmd5ctx, &md5ctx, sizeof(MD5_CTX));
176
MD5_Final(fragmd5sum, &fragmd5ctx);
177
for (i=0; i<FRAGMENT_SUM_LENGTH/FRAGMENT_COUNT; i++) {
179
snprintf(tmpstr, 2, "%01x", fragmd5sum[i]);
180
strncat(fragstr, tmpstr, 2);
182
/* printf("\nFragment [%i]: %s\n", previous_fragment, fragstr); */
183
previous_fragment = current_fragment;
186
total = total + nread;
190
MD5_Final(md5sum, &md5ctx);
193
for (i=0; i<16; i++) {
195
snprintf (tmpstr, 4, "%02x", md5sum[i]);
196
strncat(md5str, tmpstr, 2);
200
printf("Inserting md5sum into iso image...\n");
201
printf("md5 = %s\n", md5str);
202
printf("Inserting fragment md5sums into iso image...\n");
203
printf("fragmd5 = %s\n", fragstr);
204
printf("frags = %d\n", FRAGMENT_COUNT);
206
/* memcpy(new_appdata, orig_appdata, 512); */
207
memset(new_appdata, ' ', 512);
210
loc = writeAppData(new_appdata, "ISO MD5SUM = ", loc);
211
loc = writeAppData(new_appdata, md5str, loc);
212
loc = writeAppData(new_appdata, ";", loc);
214
buf = malloc(512 * sizeof(unsigned char));
215
snprintf((char *)buf, 512, "SKIPSECTORS = %d", SKIPSECTORS);
217
loc = writeAppData(new_appdata, (char *)buf, loc);
218
loc = writeAppData(new_appdata, ";", loc);
223
printf("Setting supported flag to 1\n");
224
loc = writeAppData(new_appdata, "RHLISOSTATUS=1", loc);
227
printf("Setting supported flag to 0\n");
228
loc = writeAppData(new_appdata, "RHLISOSTATUS=0", loc);
231
loc = writeAppData(new_appdata, ";", loc);
233
loc = writeAppData(new_appdata, "FRAGMENT SUMS = ", loc);
234
loc = writeAppData(new_appdata, fragstr, loc);
235
loc = writeAppData(new_appdata, ";", loc);
237
buf = malloc(512 * sizeof(unsigned char));
238
snprintf((char *)buf, 512, "FRAGMENT COUNT = %d", FRAGMENT_COUNT);
239
loc = writeAppData(new_appdata, (char *)buf, loc);
240
loc = writeAppData(new_appdata, ";", loc);
243
loc = writeAppData(new_appdata, "THIS IS NOT THE SAME AS RUNNING MD5SUM ON THIS ISO!!", loc);
245
i = lseek(isofd, pvd_offset + APPDATA_OFFSET, SEEK_SET);
247
printf("seek failed\n");
249
i = write(isofd, new_appdata, 512);
251
printf("write failed %d\n", i);