Improved filename handling and securiteee
Signed-off-by: Tyrolyean <tyrolyean@tyrolyean.net>
This commit is contained in:
parent
67b6aa29b0
commit
7e51aedc5b
|
@ -24,7 +24,7 @@ extern uint16_t listen_port, forward_port;
|
||||||
|
|
||||||
/* Used as booleans, but integers for getops sake... */
|
/* Used as booleans, but integers for getops sake... */
|
||||||
|
|
||||||
extern int abort_on_pgp, abort_on_dkim;
|
extern int abort_on_pgp, abort_on_dkim, only_base64;
|
||||||
|
|
||||||
extern char* instance_id;
|
extern char* instance_id;
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,12 @@
|
||||||
char* generate_safe_dirname();
|
char* generate_safe_dirname();
|
||||||
|
|
||||||
int base64_decode_file(const char* directory, const struct email_t* mail);
|
int base64_decode_file(const char* directory, const struct email_t* mail);
|
||||||
|
|
||||||
int decode_file(const char* directory, const char * message, size_t len,
|
int decode_file(const char* directory, const char * message, size_t len,
|
||||||
struct type_file_info_t finf);
|
char* name);
|
||||||
|
|
||||||
bool file_exists(const char* filename);
|
bool file_exists(const char* filename);
|
||||||
|
|
||||||
|
char* sanitizie_filename(char* filename);
|
||||||
|
|
||||||
#endif /* FILE_H */
|
#endif /* FILE_H */
|
||||||
|
|
|
@ -212,6 +212,9 @@ void unravel_multipart_mail(struct email_t* mail){
|
||||||
|
|
||||||
void free_submails(struct email_t* mail){
|
void free_submails(struct email_t* mail){
|
||||||
|
|
||||||
|
free(mail->file_info.name);
|
||||||
|
free(mail->file_info.mime_type);
|
||||||
|
|
||||||
if(!mail->is_multipart){
|
if(!mail->is_multipart){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -336,6 +339,10 @@ int replace_base64_files(struct email_t* mail, const char* dirname){
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if(mail->file_info.name == NULL){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(mail->base64_encoded){
|
if(mail->base64_encoded){
|
||||||
if(base64_decode_file(dirname, mail) < 0){
|
if(base64_decode_file(dirname, mail) < 0){
|
||||||
fprintf(stderr, "Failed to decode base64 file\n!");
|
fprintf(stderr, "Failed to decode base64 file\n!");
|
||||||
|
@ -344,7 +351,7 @@ int replace_base64_files(struct email_t* mail, const char* dirname){
|
||||||
}else{
|
}else{
|
||||||
if(decode_file(dirname, (mail->message+mail->body_offset),
|
if(decode_file(dirname, (mail->message+mail->body_offset),
|
||||||
(mail->message_length - mail->body_offset),
|
(mail->message_length - mail->body_offset),
|
||||||
mail->file_info) < 0){
|
mail->file_info.name) < 0){
|
||||||
|
|
||||||
fprintf(stderr, "Failed to decode base64 file\n!");
|
fprintf(stderr, "Failed to decode base64 file\n!");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -20,10 +20,11 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
uint16_t listen_port = 4269, forward_port = 4270;
|
uint16_t listen_port = 4269, forward_port = 4270;
|
||||||
int abort_on_pgp = true, abort_on_dkim = true;
|
int abort_on_pgp = true, abort_on_dkim = true, only_base64 = true;
|
||||||
char* instance_id = NULL;
|
char* instance_id = NULL;
|
||||||
|
|
||||||
int verbose = false;
|
int verbose = false;
|
||||||
char* directory = NULL;
|
char* directory = NULL;
|
||||||
char* url_base = NULL;
|
char* url_base = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
51
src/file.c
51
src/file.c
|
@ -27,6 +27,7 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/random.h>
|
#include <sys/random.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
/* Generate a safe directory name to store ONE emails files into. This is
|
/* Generate a safe directory name to store ONE emails files into. This is
|
||||||
* done to prevent someone from guessing the directory names. THe first part
|
* done to prevent someone from guessing the directory names. THe first part
|
||||||
|
@ -44,14 +45,14 @@ char* generate_safe_dirname(){
|
||||||
#define TIME_LEN 30
|
#define TIME_LEN 30
|
||||||
char datestr[TIME_LEN];
|
char datestr[TIME_LEN];
|
||||||
memset(datestr, 0, TIME_LEN);
|
memset(datestr, 0, TIME_LEN);
|
||||||
strftime(datestr, TIME_LEN, "%FT%T%z", info);
|
strftime(datestr, TIME_LEN, "%FT%H%M", info);
|
||||||
|
|
||||||
/* Get data from urandom to be secure. I mean from what I
|
/* Get data from urandom to be secure. I mean from what I
|
||||||
* know it should be, but I'm not a crypto expert. If you have doubts
|
* know it should be, but I'm not a crypto expert. If you have doubts
|
||||||
* and know how I should do that, PLEASE TELL ME! The man pages told me
|
* and know how I should do that, PLEASE TELL ME! The man pages told me
|
||||||
* to do so!
|
* to do so!
|
||||||
*/
|
*/
|
||||||
int randie[3];
|
int randie[2];
|
||||||
|
|
||||||
if(getrandom(randie, sizeof(randie), 0) <= 0){
|
if(getrandom(randie, sizeof(randie), 0) <= 0){
|
||||||
perror("Failed to get random seed! Aborting");
|
perror("Failed to get random seed! Aborting");
|
||||||
|
@ -62,8 +63,8 @@ char* generate_safe_dirname(){
|
||||||
char * dir_id = malloc(dir_len+1);
|
char * dir_id = malloc(dir_len+1);
|
||||||
memset(dir_id, 0, dir_len+1 );
|
memset(dir_id, 0, dir_len+1 );
|
||||||
|
|
||||||
snprintf(dir_id,dir_len, "%s/%s%i%i%i/",directory, datestr,
|
snprintf(dir_id,dir_len, "%s/%s%i%i/",directory, datestr,
|
||||||
randie[0], randie[1], randie[2]);
|
randie[0], randie[1]);
|
||||||
#undef TIME_LEN
|
#undef TIME_LEN
|
||||||
return dir_id;
|
return dir_id;
|
||||||
}
|
}
|
||||||
|
@ -90,7 +91,8 @@ int base64_decode_file(const char* directory, const struct email_t* mail){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int n = decode_file(directory,(char*) decoded, dec_len, mail->file_info);
|
int n = decode_file(directory,(char*) decoded, dec_len,
|
||||||
|
mail->file_info.name);
|
||||||
|
|
||||||
free(decoded);
|
free(decoded);
|
||||||
|
|
||||||
|
@ -99,15 +101,16 @@ int base64_decode_file(const char* directory, const struct email_t* mail){
|
||||||
}
|
}
|
||||||
|
|
||||||
int decode_file(const char* directory, const char * message, size_t len,
|
int decode_file(const char* directory, const char * message, size_t len,
|
||||||
struct type_file_info_t finf){
|
char* name){
|
||||||
|
|
||||||
if(directory == NULL || message == NULL || finf.name == NULL){
|
if(directory == NULL || message == NULL || name == NULL){
|
||||||
|
|
||||||
/* I don't know how I should call that file! */
|
/* I don't know how I should call that file! */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
char* sane_name = sanitizie_filename(name);
|
||||||
|
|
||||||
size_t fn_len = strlen(finf.name) + strlen(directory) + 1;
|
size_t fn_len = strlen(sane_name) + strlen(directory) + 1;
|
||||||
|
|
||||||
char* filename = malloc(fn_len);
|
char* filename = malloc(fn_len);
|
||||||
if(filename == NULL){
|
if(filename == NULL){
|
||||||
|
@ -116,20 +119,24 @@ int decode_file(const char* directory, const char * message, size_t len,
|
||||||
|
|
||||||
memset(filename, 0, fn_len);
|
memset(filename, 0, fn_len);
|
||||||
strcat(filename, directory);
|
strcat(filename, directory);
|
||||||
strcat(filename, finf.name);
|
strcat(filename, sane_name);
|
||||||
|
|
||||||
|
|
||||||
bool exists = false;
|
bool exists = false;
|
||||||
for(size_t i = 0; i < 10; i++){
|
for(size_t i = 0; i < 10; i++){
|
||||||
exists = file_exists(filename);
|
exists = file_exists(filename);
|
||||||
if(exists){
|
if(exists){
|
||||||
free(filename);
|
free(filename);
|
||||||
fn_len = strlen(finf.name) +
|
fn_len = strlen(sane_name) +
|
||||||
strlen(directory) + 20;
|
strlen(directory) + 20;
|
||||||
filename = malloc(fn_len);
|
filename = malloc(fn_len);
|
||||||
snprintf(filename, fn_len, "%s%i-%s",directory,
|
snprintf(filename, fn_len, "%s%i-%s",directory,
|
||||||
rand(), finf.name);
|
rand(), sane_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(sane_name);
|
||||||
|
|
||||||
if(exists){
|
if(exists){
|
||||||
/* What?*/
|
/* What?*/
|
||||||
fprintf(stderr,"Failed to create unique file name!\n");
|
fprintf(stderr,"Failed to create unique file name!\n");
|
||||||
|
@ -164,3 +171,23 @@ bool file_exists(const char* filename){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Generates a filename which should fit into a URL without URL-encode and which
|
||||||
|
* doesn't allow for */
|
||||||
|
char* sanitizie_filename(char* filename){
|
||||||
|
|
||||||
|
if(filename == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
size_t filename_len = strlen(filename);
|
||||||
|
size_t new_len = 0;
|
||||||
|
char* new_name = malloc(filename_len + 1);
|
||||||
|
memset(new_name, 0, filename_len+1);
|
||||||
|
for(size_t i = 0; i < filename_len; i++){
|
||||||
|
if(isalnum(filename[i]) || filename[i] == '-' ||
|
||||||
|
filename[i] == '.'){
|
||||||
|
new_name[new_len++] = filename[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new_name;
|
||||||
|
}
|
||||||
|
|
10
src/main.c
10
src/main.c
|
@ -30,6 +30,8 @@ int main(int argc, char* argv[]){
|
||||||
{"noabort-dkim",no_argument, &abort_on_dkim,0},
|
{"noabort-dkim",no_argument, &abort_on_dkim,0},
|
||||||
{"verbose", no_argument, &verbose, 1},
|
{"verbose", no_argument, &verbose, 1},
|
||||||
{"quiet", no_argument, &verbose, 0},
|
{"quiet", no_argument, &verbose, 0},
|
||||||
|
{"only-base64", no_argument, &only_base64, 1},
|
||||||
|
{"other-base64",no_argument, &only_base64, 0},
|
||||||
{"in-port", required_argument, 0, 'i'},
|
{"in-port", required_argument, 0, 'i'},
|
||||||
{"out-port", required_argument, 0, 'o'},
|
{"out-port", required_argument, 0, 'o'},
|
||||||
{"instance-id", required_argument, 0, 'n'},
|
{"instance-id", required_argument, 0, 'n'},
|
||||||
|
@ -106,15 +108,19 @@ int main(int argc, char* argv[]){
|
||||||
printf("Incoming port: %u outgoing port: %u on loopback "
|
printf("Incoming port: %u outgoing port: %u on loopback "
|
||||||
"interface\n", listen_port, forward_port);
|
"interface\n", listen_port, forward_port);
|
||||||
|
|
||||||
printf("Ignoring PGP signed/encrypted messages: %s\n",
|
printf("Aborting on PGP signed/encrypted messages: %s\n",
|
||||||
abort_on_pgp ? "true":false);
|
abort_on_pgp ? "true":false);
|
||||||
|
|
||||||
printf("Ignoring DKIM signed messages: %s\n",
|
printf("Aborting on DKIM signed messages: %s\n",
|
||||||
abort_on_dkim ? "true" : "false");
|
abort_on_dkim ? "true" : "false");
|
||||||
|
|
||||||
printf("Instance id for messages: %s\n",
|
printf("Instance id for messages: %s\n",
|
||||||
instance_id);
|
instance_id);
|
||||||
|
|
||||||
|
printf("Only saving bas64 encoded files: %s\n",
|
||||||
|
only_base64 ? "true":false);
|
||||||
|
|
||||||
|
|
||||||
printf("Placing files into [%s] linked by [%s]\n", directory,
|
printf("Placing files into [%s] linked by [%s]\n", directory,
|
||||||
url_base);
|
url_base);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue