Improved filename handling and securiteee
Signed-off-by: Tyrolyean <tyrolyean@tyrolyean.net>
This commit is contained in:
parent
67b6aa29b0
commit
7e51aedc5b
6 changed files with 62 additions and 18 deletions
|
@ -24,7 +24,7 @@ extern uint16_t listen_port, forward_port;
|
|||
|
||||
/* 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;
|
||||
|
||||
|
|
|
@ -25,9 +25,12 @@
|
|||
char* generate_safe_dirname();
|
||||
|
||||
int base64_decode_file(const char* directory, const struct email_t* mail);
|
||||
|
||||
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);
|
||||
|
||||
char* sanitizie_filename(char* filename);
|
||||
|
||||
#endif /* FILE_H */
|
||||
|
|
|
@ -212,6 +212,9 @@ void unravel_multipart_mail(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){
|
||||
return;
|
||||
}
|
||||
|
@ -336,6 +339,10 @@ int replace_base64_files(struct email_t* mail, const char* dirname){
|
|||
return 0;
|
||||
|
||||
}
|
||||
if(mail->file_info.name == NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(mail->base64_encoded){
|
||||
if(base64_decode_file(dirname, mail) < 0){
|
||||
fprintf(stderr, "Failed to decode base64 file\n!");
|
||||
|
@ -344,7 +351,7 @@ int replace_base64_files(struct email_t* mail, const char* dirname){
|
|||
}else{
|
||||
if(decode_file(dirname, (mail->message+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!");
|
||||
return -1;
|
||||
|
|
|
@ -20,10 +20,11 @@
|
|||
#include <stddef.h>
|
||||
|
||||
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;
|
||||
|
||||
int verbose = false;
|
||||
char* directory = NULL;
|
||||
char* url_base = NULL;
|
||||
|
||||
|
||||
|
|
51
src/file.c
51
src/file.c
|
@ -27,6 +27,7 @@
|
|||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/random.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* 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
|
||||
|
@ -44,14 +45,14 @@ char* generate_safe_dirname(){
|
|||
#define TIME_LEN 30
|
||||
char datestr[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
|
||||
* 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
|
||||
* to do so!
|
||||
*/
|
||||
int randie[3];
|
||||
int randie[2];
|
||||
|
||||
if(getrandom(randie, sizeof(randie), 0) <= 0){
|
||||
perror("Failed to get random seed! Aborting");
|
||||
|
@ -62,8 +63,8 @@ char* generate_safe_dirname(){
|
|||
char * dir_id = malloc(dir_len+1);
|
||||
memset(dir_id, 0, dir_len+1 );
|
||||
|
||||
snprintf(dir_id,dir_len, "%s/%s%i%i%i/",directory, datestr,
|
||||
randie[0], randie[1], randie[2]);
|
||||
snprintf(dir_id,dir_len, "%s/%s%i%i/",directory, datestr,
|
||||
randie[0], randie[1]);
|
||||
#undef TIME_LEN
|
||||
return dir_id;
|
||||
}
|
||||
|
@ -90,7 +91,8 @@ int base64_decode_file(const char* directory, const struct email_t* mail){
|
|||
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);
|
||||
|
||||
|
@ -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,
|
||||
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! */
|
||||
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);
|
||||
if(filename == NULL){
|
||||
|
@ -116,20 +119,24 @@ int decode_file(const char* directory, const char * message, size_t len,
|
|||
|
||||
memset(filename, 0, fn_len);
|
||||
strcat(filename, directory);
|
||||
strcat(filename, finf.name);
|
||||
|
||||
strcat(filename, sane_name);
|
||||
|
||||
|
||||
bool exists = false;
|
||||
for(size_t i = 0; i < 10; i++){
|
||||
exists = file_exists(filename);
|
||||
if(exists){
|
||||
free(filename);
|
||||
fn_len = strlen(finf.name) +
|
||||
fn_len = strlen(sane_name) +
|
||||
strlen(directory) + 20;
|
||||
filename = malloc(fn_len);
|
||||
snprintf(filename, fn_len, "%s%i-%s",directory,
|
||||
rand(), finf.name);
|
||||
rand(), sane_name);
|
||||
}
|
||||
}
|
||||
|
||||
free(sane_name);
|
||||
|
||||
if(exists){
|
||||
/* What?*/
|
||||
fprintf(stderr,"Failed to create unique file name!\n");
|
||||
|
@ -164,3 +171,23 @@ bool file_exists(const char* filename){
|
|||
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},
|
||||
{"verbose", no_argument, &verbose, 1},
|
||||
{"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'},
|
||||
{"out-port", required_argument, 0, 'o'},
|
||||
{"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 "
|
||||
"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);
|
||||
|
||||
printf("Ignoring DKIM signed messages: %s\n",
|
||||
printf("Aborting on DKIM signed messages: %s\n",
|
||||
abort_on_dkim ? "true" : "false");
|
||||
|
||||
printf("Instance id for messages: %s\n",
|
||||
instance_id);
|
||||
|
||||
printf("Only saving bas64 encoded files: %s\n",
|
||||
only_base64 ? "true":false);
|
||||
|
||||
|
||||
printf("Placing files into [%s] linked by [%s]\n", directory,
|
||||
url_base);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue