Compare commits

..

2 commits

Author SHA1 Message Date
1312510074
Added dkim detection
Signed-off-by: tyrolyean <tyrolyean@tyrolyean.net>
2020-04-28 23:43:09 +02:00
80a42e7896
Implement optarg and Readme update
Signed-off-by: tyrolyean <tyrolyean@tyrolyean.net>
2020-04-28 23:31:18 +02:00
9 changed files with 126 additions and 17 deletions

38
README
View file

@ -1,5 +1,37 @@
MAILATTACH MAILATTACH
This program starts a process which listens on a unix socket for incoming This program starts a process which listens on the LOOPBACKv4 address for
milter connections. Incoming mail is scanned for large files and files above a incoming connections from postfix. The postfix master should view this as an
certain threshold are replaced with links which the user may specify. advanced filter as explained in their documentation for post queue filtering:
http://www.postfix.org/FILTER_README.html
The original attempt was to implement this as a pre queue filter, but this
required the milter protocol and postfix currently does not implement the
replace body function from libmilter.
You can specify the following command line options:
--abort-pgp --noabort-pgp
To either abort the attachment process if PGP encryption or signatures
have been detected or not. If true, the mail will not be modified.
--abort-dkim --noabort-dkim
To either abort the attachment process if DKIM signatures have been
detected or not. If true, the mail will not be modified.
--in-port -i
The incoming smtp port/the port from which mail is received.
--out-port -o
The outgoing smtp port/the port to which mail ist passed through.
HOWTO
We essentially are MITM sniffing your email traffic and playing proxy from your
postfix to your postfix. That's how this is intended to work according to the
postfix website.
This program needs to be started via it's own systemd service on system boot.
You need to add the in and oputput ports to your postfix queue as described in
the link above. More documentation is to a TODO

View file

@ -22,6 +22,8 @@
extern uint16_t listen_port, forward_port; extern uint16_t listen_port, forward_port;
extern bool abort_on_pgp, abort_on_dkim; /* Used as booleans, but integers for getops sake... */
extern int abort_on_pgp, abort_on_dkim;
#endif /* CONFIG_H */ #endif /* CONFIG_H */

View file

@ -23,6 +23,7 @@
#include "attach.h" #include "attach.h"
bool detect_pgp(struct email_t* mail); bool detect_pgp(struct email_t* mail);
bool detect_dkim(struct email_t* mail);
char* detect_start_of_body(char* message); char* detect_start_of_body(char* message);
char* detect_end_of_body(char* message); char* detect_end_of_body(char* message);
#endif /* DETECT_H */ #endif /* DETECT_H */

View file

@ -23,4 +23,5 @@
const char* insert_string(char * destination, const char* source, const char* insert_string(char * destination, const char* source,
size_t dest_orig_len, size_t offset); size_t dest_orig_len, size_t offset);
#endif /* TOOLS_H */ #endif /* TOOLS_H */

View file

@ -83,17 +83,16 @@ char* attach_files(char* message, size_t len){
struct email_t email = mail_from_text(message,len); struct email_t email = mail_from_text(message,len);
printf("Received message header: [%.*s]\n", email.header_len,
email.message);
printf("Received message body: [%.*s]\n",
email.message_length-email.body_offset,
email.message + email.body_offset);
/* Check if mails are signed/encrypted, and abort if nescessary */ /* Check if mails are signed/encrypted, and abort if nescessary */
if(abort_on_pgp && detect_pgp(&email)){ if(abort_on_pgp && detect_pgp(&email)){
printf("PGP detected, aborting..."); printf("PGP detected, aborting...");
return email.message; return email.message;
} }
/* Check if mails are signed/encrypted, and abort if nescessary */
if(abort_on_dkim && detect_dkim(&email)){
printf("DKIM signature detected, aborting...");
return email.message;
}
return email.message; return email.message;
} }

View file

@ -17,4 +17,4 @@
#include "config.h" #include "config.h"
uint16_t listen_port = 4269, forward_port = 4270; uint16_t listen_port = 4269, forward_port = 4270;
bool abort_on_pgp = true, abort_on_dkim = true; int abort_on_pgp = true, abort_on_dkim = true;

View file

@ -29,6 +29,11 @@ char* pgp_signatures[] =
"-----BEGIN PGP MESSAGE-----" "-----BEGIN PGP MESSAGE-----"
}; };
char* dkim_signatures[] =
{
"DKIM-Signature:"
};
bool detect_pgp(struct email_t* mail){ bool detect_pgp(struct email_t* mail){
size_t points = 0; size_t points = 0;
@ -45,6 +50,23 @@ bool detect_pgp(struct email_t* mail){
return points >= 2; return points >= 2;
} }
bool detect_dkim(struct email_t* mail){
size_t points = 0;
for(size_t i = 0; i < (sizeof(dkim_signatures)/sizeof(char*));i++){
if(strcasestr(mail->message, dkim_signatures[i]) != NULL
&& strcasestr(mail->message, dkim_signatures[i])
<= (mail->message+mail->header_len)){
points++;
}
}
return points >= 1;
}
/* If body hasn't started yet, it returns NULL, if it has started, it returns /* If body hasn't started yet, it returns NULL, if it has started, it returns
* the pointer to the beginning of the newline. * the pointer to the beginning of the newline.
*/ */

View file

@ -6,7 +6,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <getopt.h>
#include "network.h" #include "network.h"
#include "config.h" #include "config.h"
@ -16,10 +16,65 @@ int main(int argc, char* argv[]){
printf("INIT\n"); printf("INIT\n");
int c;
while (1){
static struct option long_options[] =
{
{"abort-pgp", no_argument, &abort_on_pgp, 1},
{"abort-dkim", no_argument, &abort_on_dkim,1},
{"noabort-pgp", no_argument, &abort_on_pgp, 0},
{"noabort-dkim",no_argument, &abort_on_dkim,0},
{"in-port", required_argument, 0, 'i'},
{"out-port", required_argument, 0, 'o'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long (argc, argv, "i:o:pd",
long_options, &option_index);
/* Detect the end of the options. */
if (c == -1){
break;
}
switch (c){
case 0:
break;
case 'i':
listen_port = atoi(optarg);
break;
case 'o':
forward_port = atoi(optarg);
break;
case '?':
/* getopt_long already printed an error message. */
return EXIT_FAILURE;
break;
default:
abort ();
}
}
printf("Incoming port: %u outgoing port: %u on loopback interface\n",
listen_port, forward_port);
printf("Ignoring PGP signed/encrypted messages: %s\n",
abort_on_pgp ? "true":false);
printf("Ignoring DKIM signed messages: %s\n",
abort_on_dkim ? "true" : "false");
if(init_net() < 0){ if(init_net() < 0){
return EXIT_FAILURE; return EXIT_FAILURE;
} }
loop_clients();
return EXIT_SUCCESS;
} }

View file

@ -273,9 +273,6 @@ void loop_clients(){
while (1) { while (1) {
/*
* accept: wait for a connection request
*/
childfd = accept(parentfd, (struct sockaddr *) &clientaddr, &clientlen); childfd = accept(parentfd, (struct sockaddr *) &clientaddr, &clientlen);
if (childfd < 0){ if (childfd < 0){
perror("accept failed"); perror("accept failed");