1 |
torben |
328 |
/* |
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 |
|
|
} |