-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfileTransfer.c
349 lines (303 loc) · 12 KB
/
fileTransfer.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include "commonDefines.h"
#include "net/networking.h"
#include "httpProcessing/commonHTTP.h"//TODO: parser states
#include "httpProcessing/realtimePacketParser.h"//TODO: parser states
#include "httpProcessing/createHTTPHeader.h"
#include "net/connection.h"
#include "utils.h"
#include "crypto.h"
#include "fileTransfer.h"
#include "fileTransferDriver.h"
#define ENCRYPTED_BUFFER_LEN 10000
#define DECRYPTED_BUFFER_LEN 10000
#define STRING_BUFFER_LEN 10000
#define DISABLE_ENCRYPTION 1
//returns the amount that needs to be trimmed off the top
//amountOfFileDecrypted must be kept up to date
int trimTop(long clientRangeEnd, long decryptedDataFileStart,
long amountOfFileDecrypted, int bufferLength) {
//the RangeEnd is inclusive so you must -1 here
if ((decryptedDataFileStart + amountOfFileDecrypted - 1) > clientRangeEnd) {
//then trim
return ((decryptedDataFileStart + amountOfFileDecrypted - 1)
- clientRangeEnd);
}
return 0;
}
//returns the amount that needs to be trimmed off the bottom
int trimBottom(long clientRangeStart, long decryptedDataFileStart,
long amountOfFileDecrypted, int bufferLength) {
if ((decryptedDataFileStart + amountOfFileDecrypted - bufferLength)
< clientRangeStart) {
return bufferLength - (decryptedDataFileStart
+ amountOfFileDecrypted - clientRangeStart);
}
return 0;
}
int __finishFileDownload() {
//close the connection and clean up
return 0;
}
int startEncryptedFileDownload( FileDownloadState_t *downloadState ) {
long startRange = downloadState->rangeStart;
long endRange = downloadState->rangeEnd;
//calculate the encrypted data we need to request to get the requested decrypted data
//we will need to fetch the whole of all the encrypted blocks
//that the decrytped data overlaps
long encFileStart, encFileEnd;
if ( startRange < AES_BLOCK_SIZE ) {
encFileStart = 0;
} else {
encFileStart = startRange - ( startRange % AES_BLOCK_SIZE );
//if the startRange isn't in the first block then we need the previous block for the IV
encFileStart -= AES_BLOCK_SIZE;
}
if ( downloadState->isEndRangeSet ) {
if( endRange % AES_BLOCK_SIZE ) {//if not 16 byte aligned
encFileEnd = endRange + ( AES_BLOCK_SIZE - ( endRange % AES_BLOCK_SIZE ) );
} else {
encFileEnd = endRange;
}
} else {
//it doesn't matter what value encFileEnd has
}
downloadState->encryptedRangeStart = encFileStart;
downloadState->encryptedRangeEnd = encFileEnd;
downloadState->amountOfFileDecrypted = 0;
downloadState->encryptedDataDownloaded = 0;
downloadState->fileDownloadComplete = 0;
downloadState->encryptionState = malloc( sizeof(CryptoState_t) );//FIXME: this probably isn't the right place for this
downloadState->connection = malloc( sizeof(Connection_t) );//FIXME: this probably isn't the right place for this
return downloadState->driverState->ops->downloadInit( downloadState );
}
//FIXME: This code is complicated, test every case
//returns the amount of data in the outputBuffer
int updateEncryptedFileDownload( FileDownloadState_t *downloadState,
char *outputBuffer, int outputBufferMaxLength ) {
printf("in:\t %lu\n", downloadState->encryptedDataDownloaded);
if( downloadState->fileDownloadComplete ) {
return 0;
}
#ifdef DISABLE_ENCRYPTION
return downloadState->driverState->ops->downloadUpdate(
downloadState,
outputBuffer,
outputBufferMaxLength );
#endif
//if this is the first time update has been called then first fetch
//enough data so that we can start the decryption
int outputBufferLength = 0;
if (downloadState->encryptedDataDownloaded == 0) {
if (downloadState->encryptedRangeStart < AES_BLOCK_SIZE) {
startDecryption( downloadState->encryptionState, "phone", NULL );
} else {
int encryptedPacketLength = 0;
char encryptedPacketBuffer[MAX_PACKET_SIZE];
//get the IV
while (downloadState->encryptedDataDownloaded < AES_BLOCK_SIZE) {
int result = downloadState->driverState->ops->downloadUpdate(
downloadState,
encryptedPacketBuffer + encryptedPacketLength,
MAX_PACKET_SIZE );
if (result == 0) {
printf("file server closed the connection right at the start");
//file server closed the connection
return 0;
}
encryptedPacketLength += result;
downloadState->encryptedDataDownloaded += encryptedPacketLength;
}
startDecryption( downloadState->encryptionState, "phone",
encryptedPacketBuffer );
//now decrypt any of the extra data we got when getting the IV and add it to the output buffer
updateDecryption( downloadState->encryptionState,
encryptedPacketBuffer + AES_BLOCK_SIZE,
encryptedPacketLength - AES_BLOCK_SIZE, outputBuffer,
&outputBufferLength );
downloadState->amountOfFileDecrypted += outputBufferLength;
}
} else {
//printf("not started\n");
}
//now that the decryption is started keep fetching data until we have
//enough to decrypt at least one byte of data
if (outputBufferLength == 0) {
char encryptedPacketBuffer[ MAX_PACKET_SIZE ];
int result = downloadState->driverState->ops->downloadUpdate(
downloadState,
encryptedPacketBuffer,
MAX_PACKET_SIZE );
downloadState->encryptedDataDownloaded += result;
printf("we got the following result: %d\n", result);
if ( result == 0 ) {
printf("result == 0 in bottom loop\n");
//file server closed the connection
//check if we reached the end of the http packet
if( downloadState->parserState.currentState == packetEnd_s ){
printf("packet end hit\n");
//check if we have reached the end of the file
//FIXME: confirm this size is correct
//FIXME: have these paddings as shared with the orginal padding code
long fullfileSize = downloadState->fileSize;
int startPadding = AES_BLOCK_SIZE;
int endPadding = (( AES_BLOCK_SIZE - ( fullfileSize % AES_BLOCK_SIZE ) ) % AES_BLOCK_SIZE);
long endOfEncryptedFile = fullfileSize
+ startPadding
+ endPadding;
printf( "range + downloaded\t%lu\n" , downloadState->encryptedRangeStart + downloadState->encryptedDataDownloaded );
printf( "endOfEncryptedFile\t%lu\n" , endOfEncryptedFile );
if (downloadState->encryptedRangeStart + downloadState->encryptedDataDownloaded >= endOfEncryptedFile ) {
// FIXME: log error here
printf("ERROR: downloadState->encryptedRangeStart + "
"downloadState->encryptedDataDownloaded > endOfEncryptedFile\n");
}
if ( downloadState->encryptedRangeStart + downloadState->encryptedDataDownloaded ==
endOfEncryptedFile ) {
printf("and packet ended\n");
//then finish the encryption
downloadState->fileDownloadComplete = 1;
int finalDataLength;
finishDecryption( downloadState->encryptionState, encryptedPacketBuffer,
result, outputBuffer,
&finalDataLength );
downloadState->amountOfFileDecrypted += finalDataLength;
outputBufferLength += finalDataLength;
return outputBufferLength;
}
}
return 0;
}
int dataLength;
updateDecryption( downloadState->encryptionState, encryptedPacketBuffer,
result, outputBuffer + outputBufferLength,
&dataLength );
outputBufferLength += dataLength; //dataLength can be 0, so we might have to loop again
downloadState->amountOfFileDecrypted += dataLength;
}
//remove any extra data from encrypted chunks where we only wanted part
//of the chunk
long tempStart =
(downloadState->encryptedRangeStart == 0) ?
downloadState->encryptedRangeStart :
downloadState->encryptedRangeStart + 16;//FIXME: magic number
int trimTopVal;
if(downloadState->isEndRangeSet){
trimTopVal = trimTop(downloadState->rangeEnd, tempStart,
downloadState->amountOfFileDecrypted, outputBufferLength);
}else{
trimTopVal = 0;
}
int trimBottomVal = trimBottom(downloadState->rangeStart, tempStart,
downloadState->amountOfFileDecrypted, outputBufferLength);
outputBufferLength -= trimBottomVal + trimTopVal;
memmove(outputBuffer, outputBuffer + trimBottomVal, outputBufferLength);
printf("out:\t %lu\n", downloadState->encryptedDataDownloaded);
return outputBufferLength;
}
int finishEncryptedFileDownload() {
return __finishFileDownload();
}
int startEncryptedFileUpload( FileUploadState_t *uploadState,
FileTransferDriver_ops_t *ops, const char *inputUrl,
Connection_t *con,
HTTPHeaderState_t *outputHInfo, HTTPParserState_t *outputParserState ) {
//we will under report the size of the buffers to functions when using them as input buffers
//so that we always meet the size+AES_BLOCK_SIZE requirements of the output buffer for the encrypt/decrypt functions
//see openssl docs for more info on ecrypted buffer/decrypted buffers size requirements
char filenameJson[ STRING_BUFFER_LEN ];
//get the file name
printf( "trying to store file %s\n", "FIXME: ADD FILE NAME HERE" );
sprintf( filenameJson, "\"title\": \"%s\"", "nuffin.bin" );
ops->uploadInit( uploadState );
//alright start reading in the file
startEncryption( uploadState->encryptionState, "phone" );
return 0;//fixme only one return code
}
//returns the amount of data in the outputBuffer
//this will ONLY return 0 if the connection has been close AND it cannot return any data
int updateEncryptedFileUpload( FileUploadState_t *uploadState,
FileTransferDriver_ops_t *ops, Connection_t *con, HTTPHeaderState_t *outputHInfo,
HTTPParserState_t *outputParserState, const char *inputBuffer,
int dataLength ) {
/*
long received;
long storFileSize = 0;
char encryptedDataBuffer[ ENCRYPTED_BUFFER_LEN + AES_BLOCK_SIZE ];
char decryptedDataBuffer[ DECRYPTED_BUFFER_LEN + AES_BLOCK_SIZE ];
if ( ( received = recv( clientState->data_fd, decryptedDataBuffer,
DECRYPTED_BUFFER_LEN, 0 ) ) > 0) {
storFileSize += received;
updateEncryption( &encryptionState, decryptedDataBuffer, received,
encryptedDataBuffer, &tempOutputSize );
googleUpload_update( &googleCon, encryptedDataBuffer,
tempOutputSize );
} else {
//call this one final time
finishEncryption( &encryptionState, decryptedDataBuffer, received,
encryptedDataBuffer, &tempOutputSize );
ops->uploadUpdate( &googleCon, encryptedDataBuffer, tempOutputSize );
GoogleUploadState_t fileState;
googleUpload_end( &googleCon, &fileState );
vfs_createFile( clientState->ctx, &clientState->ctx->cwd, parserState->paramBuffer,
storFileSize, fileState.id, fileState.webUrl, fileState.apiUrl );
sendFtpResponse( clientState, "226 Transfer complete.\r\n" );
}
*/
return 0;//fixme only one return code
}
int finishEncryptedFileUpload() {
//just clean up and stuff
return 0;//fixme only one return code
}
int startFileDownload( FileDownloadState_t *downloadState ) {
return startEncryptedFileDownload( downloadState );
}
//FIXME: move this function to the common code between downloadDrivers
//returns the amount of file data returned in the buffer
//returns 0 if no more data can be fetched, if this returns 0 then every call after wil return 0 //FIXME: test that this is true
int updateFileDownload( FileDownloadState_t *downloadState, char *outputBuffer,
int outputBufferMaxLength ) {
return updateEncryptedFileDownload( downloadState, outputBuffer,
outputBufferMaxLength );
}
int finishFileDownload(FileDownloadState_t *downloadState) {
return finishEncryptedFileDownload();
}
int startFileUpload( FileUploadState_t *uploadState ) {
return startEncryptedFileUpload(
uploadState,
uploadState->driverState->ops,
uploadState->fileUrl,
uploadState->connection,
&uploadState->headerState,
&uploadState->parserState );
}
//returns the amount of data downloaded INCLUDING HEADER
int updateFileUpload( FileUploadState_t *uploadState, const char *inputBuffer,
int dataLength ) {
return updateEncryptedFileUpload(
uploadState,
uploadState->driverState->ops,
uploadState->connection,
&uploadState->headerState,
&uploadState->parserState,
inputBuffer,
dataLength
);
}
int finishFileUpload(FileDownloadState_t *uploadState) {
//close the connection and clean up
return 0;
}