1 |
/* |
2 |
* piggyback.c (c) 2005 by Torben H. Nielsen <torben@t-hoerup.dk> |
3 |
* |
4 |
* requires openssl-dev |
5 |
* compile with gcc -o piggyback -l crypto piggyback.c |
6 |
* (perhaps with -O3) |
7 |
* |
8 |
* return values: |
9 |
* 0: success |
10 |
* 1: could not open file |
11 |
* 2: md5 mismatch |
12 |
*/ |
13 |
|
14 |
/***************************************************************** |
15 |
* ToDo: |
16 |
* V At detach, remove() outfile if data md5 mismatch is detected |
17 |
* V detach - read options field |
18 |
* - ReWrite commandline args handling |
19 |
* - Compression |
20 |
* - Encryption/Decryption |
21 |
*/ |
22 |
|
23 |
|
24 |
#include <stdlib.h> |
25 |
#include <stdio.h> |
26 |
#include <string.h> |
27 |
#include <openssl/md5.h> |
28 |
#include <sys/stat.h> |
29 |
|
30 |
#include "gzcompress.h" |
31 |
|
32 |
#define CHUNK_SIZE 512 |
33 |
|
34 |
|
35 |
void printusage( void ) { |
36 |
|
37 |
printf("piggyback by hoerup\n"); |
38 |
printf("Usage: piggyback [options] attach <carrier-file> <payload-file> <output-file>\n"); |
39 |
printf(" piggyback detach <carrier-file> <output-file>\n\n"); |
40 |
printf("Options:\n"); |
41 |
printf(" --compress: use gzcompression on payload data\n"); |
42 |
printf("\n"); |
43 |
|
44 |
exit(0); |
45 |
} |
46 |
|
47 |
int main(int argc, char *argv[]) { |
48 |
FILE *carrierfile, *payloadfile, *outfile; |
49 |
int carrieridx; |
50 |
|
51 |
unsigned char buf[CHUNK_SIZE]; |
52 |
unsigned char md5sum[16]; |
53 |
unsigned char md5string[33]; |
54 |
unsigned char options[8]; |
55 |
unsigned char tmpstr[40]; |
56 |
unsigned char header[80]; |
57 |
|
58 |
char *ptr; |
59 |
int num, bytes_extracted; |
60 |
int pointer, headerpointer; |
61 |
int i; |
62 |
MD5_CTX md5; |
63 |
|
64 |
if( !( (argc ==4 && strcmp(argv[1],"attach") ) || (argc == 5 && strcmp(argv[1],"detach")) ) ) { |
65 |
printusage(); |
66 |
} |
67 |
carrieridx = 2; |
68 |
|
69 |
//create output-file with 644 permissions |
70 |
umask(022); |
71 |
|
72 |
if ( strcmp(argv[1], "attach")==0 ) { //attach |
73 |
carrierfile = fopen(argv[carrieridx], "r"); |
74 |
payloadfile = fopen(argv[carrieridx+1], "r"); |
75 |
outfile = fopen(argv[carrieridx+2], "w"); |
76 |
|
77 |
if (carrierfile == 0) { |
78 |
printf("Could not open carrier file (%s) for reading\n", argv[carrieridx]); |
79 |
return 1; |
80 |
} |
81 |
if (payloadfile == 0) { |
82 |
printf("Could not open payload file (%s) for reading\n", argv[carrieridx+1]); |
83 |
return 1; |
84 |
} |
85 |
if (outfile == 0) { |
86 |
printf("Could not open output file (%s) for writing\n", argv[carrieridx+2]); |
87 |
return 1; |
88 |
} |
89 |
|
90 |
for (i=0;i<8;i++) |
91 |
options[i] = 0; |
92 |
|
93 |
pointer=0; |
94 |
while (!feof(carrierfile)) { |
95 |
num = fread(buf, 1, CHUNK_SIZE, carrierfile); |
96 |
fwrite(buf, 1, num, outfile); |
97 |
pointer += num; |
98 |
} |
99 |
|
100 |
MD5_Init(&md5); |
101 |
|
102 |
while (!feof(payloadfile)) { |
103 |
num = fread(buf, 1, CHUNK_SIZE, payloadfile); |
104 |
fwrite(buf, 1, num, outfile); |
105 |
MD5_Update(&md5, buf, num); |
106 |
} |
107 |
|
108 |
MD5_Final(md5sum, &md5); |
109 |
|
110 |
for (i=0; i<16; i++) |
111 |
fprintf(outfile, "%02x", md5sum[i]); |
112 |
|
113 |
sprintf(header, "%08x", pointer); |
114 |
|
115 |
for (i=0; i<8; i++) { |
116 |
sprintf(tmpstr, "%c", options[i]+48); //ascii(48)='0' |
117 |
strcat(header, tmpstr); |
118 |
} |
119 |
|
120 |
|
121 |
fprintf(outfile, header, 16); |
122 |
|
123 |
MD5_Init(&md5); |
124 |
MD5_Update(&md5, header, 16); |
125 |
MD5_Final(md5sum, &md5); |
126 |
|
127 |
for (i=0; i<16; i++) |
128 |
fprintf(outfile, "%02x", md5sum[i]); |
129 |
|
130 |
fclose(carrierfile); |
131 |
fclose(payloadfile); |
132 |
fclose(outfile); |
133 |
|
134 |
} else { //detach |
135 |
carrierfile = fopen(argv[carrieridx], "r"); |
136 |
outfile = fopen(argv[carrieridx+1], "w"); |
137 |
|
138 |
|
139 |
if (carrierfile == 0) { |
140 |
printf("Could not open carrier file (%s) for reading\n", argv[carrieridx]); |
141 |
return 1; |
142 |
} |
143 |
|
144 |
if (outfile == 0) { |
145 |
printf("Could not open output file (%s) for writing\n", argv[carrieridx+1]); |
146 |
return 1; |
147 |
} |
148 |
//header size is 80 bytes |
149 |
fseek(carrierfile, -80, SEEK_END); |
150 |
headerpointer = ftell(carrierfile); |
151 |
fread(header, 1, 80, carrierfile); |
152 |
|
153 |
ptr = header + 32; |
154 |
strncpy(tmpstr, ptr, 16); |
155 |
|
156 |
MD5_Init(&md5); |
157 |
MD5_Update(&md5, tmpstr, 16); |
158 |
MD5_Final(md5sum, &md5); |
159 |
md5string[0] = 0; |
160 |
|
161 |
for (i=0; i<16;i++) { |
162 |
sprintf(tmpstr, "%02x", md5sum[i]); |
163 |
strcat(md5string, tmpstr); |
164 |
} |
165 |
|
166 |
ptr += 16; |
167 |
strncpy(tmpstr, ptr, 32); |
168 |
tmpstr[32] = 0; |
169 |
|
170 |
if (strncmp(md5string, tmpstr, 32) != 0) { |
171 |
printf("Header MD5 checksum mismatch!\n"); |
172 |
return 2; |
173 |
} |
174 |
|
175 |
// Read data-pointer |
176 |
ptr = header + 32; |
177 |
strncpy(tmpstr, ptr, 8); |
178 |
|
179 |
tmpstr[8] = 0; //make tmpstr a 0-terminated string |
180 |
|
181 |
pointer = strtol(tmpstr, (char **)NULL, 16); |
182 |
|
183 |
// Read Options fields |
184 |
ptr += 8; |
185 |
strncpy(options, ptr, 8); |
186 |
for (i=0; i<8; i++) |
187 |
options[i] -= 48; |
188 |
|
189 |
bytes_extracted = 0; |
190 |
fseek(carrierfile, pointer, SEEK_SET); |
191 |
MD5_Init( &md5 ); |
192 |
num=CHUNK_SIZE; |
193 |
while ( num == CHUNK_SIZE) { |
194 |
num = headerpointer - pointer; |
195 |
num -= bytes_extracted; |
196 |
|
197 |
if ( num >= CHUNK_SIZE ) |
198 |
num = CHUNK_SIZE; |
199 |
|
200 |
fread(buf, 1 , num, carrierfile); |
201 |
fwrite(buf, 1, num, outfile); |
202 |
MD5_Update( &md5, buf, num); |
203 |
bytes_extracted += num; |
204 |
} |
205 |
|
206 |
fclose(carrierfile); |
207 |
fclose(outfile); |
208 |
|
209 |
MD5_Final(md5sum, &md5); |
210 |
md5string[0] = 0; |
211 |
|
212 |
for (i=0; i<16; i++) { |
213 |
sprintf(tmpstr, "%02x", md5sum[i]); |
214 |
strcat( md5string, tmpstr); |
215 |
} |
216 |
|
217 |
strncpy(tmpstr, header, 32); |
218 |
tmpstr[32] = 0; |
219 |
if (strncmp(md5string, tmpstr, 32) !=0) { |
220 |
printf("Payload MD5 checksum mismatch!\n"); |
221 |
remove( argv[carrieridx+1] ); |
222 |
return 2; |
223 |
} |
224 |
} |
225 |
|
226 |
|
227 |
return 0; |
228 |
} |