Improved filename handling and securiteee

Signed-off-by: Tyrolyean <tyrolyean@tyrolyean.net>
This commit is contained in:
Tyrolyean 2020-04-30 19:43:44 +02:00
parent 67b6aa29b0
commit 7e51aedc5b
No known key found for this signature in database
GPG key ID: 81EC9BAC5E9667C6
6 changed files with 62 additions and 18 deletions

View file

@ -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;

View file

@ -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 */

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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);
}