Compare commits

...

3 commits

Author SHA1 Message Date
c5257bbb6c
Base 64 debug output
Signed-off-by: Tyrolyean <tyrolyean@tyrolyean.net>
2020-04-29 19:29:13 +02:00
60c0050a9b
Added base 64 en-decode logic, detection
Signed-off-by: Tyrolyean <tyrolyean@tyrolyean.net>
2020-04-29 19:19:38 +02:00
5c71c8895c
Added options for url base an directory
Signed-off-by: Tyrolyean <tyrolyean@tyrolyean.net>
2020-04-29 17:33:23 +02:00
11 changed files with 398 additions and 7 deletions

12
README
View file

@ -26,6 +26,18 @@ You can specify the following command line options:
--out-port -o --out-port -o
The outgoing smtp port/the port to which mail ist passed through. The outgoing smtp port/the port to which mail ist passed through.
--directory -d
The directory inside of which the attachments will be stored in.
--url -u
The base which should point to the same location as the directory does,
for exaple if the directory is /var/www/html and the URL base is
https://example.com then a file in /var/www/html/attachment01.pdf should
be linkable via https://example.com/attachment01.pdf
Ah and please, please, pretty please disable directory indexing on your
webserver!
That WILL BE a security riks!
HOWTO HOWTO
We essentially are MITM sniffing your email traffic and playing proxy from your We essentially are MITM sniffing your email traffic and playing proxy from your

97
include/base64.h Normal file
View file

@ -0,0 +1,97 @@
/*
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/* ====================================================================
* Copyright (c) 1995-1999 The Apache Group. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* 4. The names "Apache Server" and "Apache Group" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Group and was originally based
* on public domain software written at the National Center for
* Supercomputing Applications, University of Illinois, Urbana-Champaign.
* For more information on the Apache Group and the Apache HTTP server
* project, please see <http://www.apache.org/>.
*
*/
/* Base64 encoder/decoder. Originally Apache file ap_base64.c
*/
#ifndef BASE64_H
#define BASE64_H
extern const unsigned char pr2six[256];
int Base64decode_len(const char *bufcoded);
int Base64decode(char *bufplain, const char *bufcoded);
extern const char basis_64[];
int Base64encode_len(int len);
int Base64encode(char *encoded, const char *string, int len);
#endif /* BASE64_H */

View file

@ -30,4 +30,8 @@ extern char* instance_id;
extern int verbose; extern int verbose;
extern char* directory;
extern char* url_base;
#endif /* CONFIG_H */ #endif /* CONFIG_H */

View file

@ -52,6 +52,7 @@ struct email_t{
size_t submes_cnt; size_t submes_cnt;
struct email_t** submes; struct email_t** submes;
struct email_t* parent; struct email_t* parent;
bool base64_encoded;
}; };
int append_header(struct email_t* mail, const char* key, const char* value); int append_header(struct email_t* mail, const char* key, const char* value);
@ -64,5 +65,6 @@ void propagate_insert_delete(struct email_t* mail, char* change_p,
void propagate_root_pointer(struct email_t* mail, char* change_p, char* old_p); void propagate_root_pointer(struct email_t* mail, char* change_p, char* old_p);
#define MULTIPART_MIME "multipart/" #define MULTIPART_MIME "multipart/"
#define BASE64_ENC "base64"
#endif /* MAIL_H */ #endif /* MAIL_H */

View file

@ -24,14 +24,16 @@
char* insert_string(char * destination, const char* source, char* insert_string(char * destination, const char* source,
size_t dest_orig_len, size_t offset); size_t dest_orig_len, size_t offset);
char* search_header_key(struct email_t* mail, const char* key); char* search_header_key(const struct email_t* mail, const char* key);
char* get_value_from_key(size_t* val_len, size_t key_offset, char* get_value_from_key(size_t* val_len, size_t key_offset,
struct email_t* mail); const struct email_t* mail);
char* get_multipart_boundary(char* content_type, size_t content_len, char* get_multipart_boundary(char* content_type, size_t content_len,
size_t* boundary_len); size_t* boundary_len);
const char* get_next_line(const char* message, size_t len); const char* get_next_line(const char* message, size_t len);
const char* get_prev_line(const char* message, size_t len_neg); const char* get_prev_line(const char* message, size_t len_neg);
bool detect_base64(const struct email_t* mail);
#endif /* TOOLS_H */ #endif /* TOOLS_H */

View file

@ -96,6 +96,7 @@ struct email_t* mail_from_text(char* message, size_t length,
} }
} }
} }
mail->base64_encoded = detect_base64(mail);
return mail; return mail;
} }
@ -224,14 +225,18 @@ void print_mail_structure(struct email_t *email, unsigned int level){
printf(" "); printf(" ");
} }
if(email->base64_encoded){
printf("Base64 encoded ");
}
if(email->is_multipart){ if(email->is_multipart){
printf("Multipart Message with %lu submessages:\n", printf("multipart Message with %lu submessages:\n",
email->submes_cnt); email->submes_cnt);
for(size_t i = 0; i < email->submes_cnt; i++){ for(size_t i = 0; i < email->submes_cnt; i++){
print_mail_structure(email->submes[i], level+1); print_mail_structure(email->submes[i], level+1);
} }
}else{ }else{
printf("Final message with length %lu and type [%.*s] \n", printf("final message with length %lu and type [%.*s] \n",
email->message_length, (int)email->ct_len, email->message_length, (int)email->ct_len,
email->content_type); email->content_type);
} }
@ -272,6 +277,7 @@ char* attach_files(char* message, size_t len){
fprintf(stderr, "Failed to attach header!\n"); fprintf(stderr, "Failed to attach header!\n");
goto finish; goto finish;
} }
finish: finish:
mess = email->message; mess = email->message;
free_submails(email); free_submails(email);

209
src/base64.c Normal file
View file

@ -0,0 +1,209 @@
/*
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/* ====================================================================
* Copyright (c) 1995-1999 The Apache Group. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* 4. The names "Apache Server" and "Apache Group" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Group and was originally based
* on public domain software written at the National Center for
* Supercomputing Applications, University of Illinois, Urbana-Champaign.
* For more information on the Apache Group and the Apache HTTP server
* project, please see <http://www.apache.org/>.
*
*/
/* Base64 encoder/decoder. Originally Apache file ap_base64.c
*/
#include <string.h>
#include "base64.h"
/* aaaack but it's fast and const should make it shared text page. */
const unsigned char pr2six[256] =
{
/* ASCII table */
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
64, 0, 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, 64, 64, 64, 64, 64,
64, 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, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
};
int Base64decode_len(const char *bufcoded)
{
int nbytesdecoded;
register const unsigned char *bufin;
register int nprbytes;
bufin = (const unsigned char *) bufcoded;
while (pr2six[*(bufin++)] <= 63);
nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
nbytesdecoded = ((nprbytes + 3) / 4) * 3;
return nbytesdecoded + 1;
}
int Base64decode(char *bufplain, const char *bufcoded)
{
int nbytesdecoded;
register const unsigned char *bufin;
register unsigned char *bufout;
register int nprbytes;
bufin = (const unsigned char *) bufcoded;
while (pr2six[*(bufin++)] <= 63);
nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
nbytesdecoded = ((nprbytes + 3) / 4) * 3;
bufout = (unsigned char *) bufplain;
bufin = (const unsigned char *) bufcoded;
while (nprbytes > 4) {
*(bufout++) =
(unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
*(bufout++) =
(unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
*(bufout++) =
(unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
bufin += 4;
nprbytes -= 4;
}
/* Note: (nprbytes == 1) would be an error, so just ingore that case */
if (nprbytes > 1) {
*(bufout++) =
(unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
}
if (nprbytes > 2) {
*(bufout++) =
(unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
}
if (nprbytes > 3) {
*(bufout++) =
(unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
}
*(bufout++) = '\0';
nbytesdecoded -= (4 - nprbytes) & 3;
return nbytesdecoded;
}
const char basis_64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int Base64encode_len(int len)
{
return ((len + 2) / 3 * 4) + 1;
}
int Base64encode(char *encoded, const char *string, int len)
{
int i;
char *p;
p = encoded;
for (i = 0; i < len - 2; i += 3) {
*p++ = basis_64[(string[i] >> 2) & 0x3F];
*p++ = basis_64[((string[i] & 0x3) << 4) |
((int) (string[i + 1] & 0xF0) >> 4)];
*p++ = basis_64[((string[i + 1] & 0xF) << 2) |
((int) (string[i + 2] & 0xC0) >> 6)];
*p++ = basis_64[string[i + 2] & 0x3F];
}
if (i < len) {
*p++ = basis_64[(string[i] >> 2) & 0x3F];
if (i == (len - 1)) {
*p++ = basis_64[((string[i] & 0x3) << 4)];
*p++ = '=';
}
else {
*p++ = basis_64[((string[i] & 0x3) << 4) |
((int) (string[i + 1] & 0xF0) >> 4)];
*p++ = basis_64[((string[i + 1] & 0xF) << 2)];
}
*p++ = '=';
}
*p++ = '\0';
return p - encoded;
}

View file

@ -24,3 +24,6 @@ int abort_on_pgp = true, abort_on_dkim = true;
char* instance_id = NULL; char* instance_id = NULL;
int verbose = false; int verbose = false;
char* directory = NULL;
char* url_base = NULL;

View file

@ -20,6 +20,7 @@
#include <string.h> #include <string.h>
#include "detect.h" #include "detect.h"
#include "tools.h"
char* pgp_signatures[] = char* pgp_signatures[] =
{ {
@ -111,3 +112,35 @@ char* detect_end_of_body(char* message){
return strstr(message, data); return strstr(message, data);
} }
bool detect_base64(const struct email_t* mail){
char* encoding = search_header_key(mail, "Content-Transfer-Encoding");
if(encoding == NULL){
return false;
}else{
size_t value_length = 0;
char * type = get_value_from_key(&value_length,
encoding - mail->message, mail);
if(type != NULL){
if(strncasecmp(type, BASE64_ENC, strlen(BASE64_ENC))
== 0){
return true;
}else{
return false;
}
}else{
return false;
}
}
}

View file

@ -33,12 +33,14 @@ int main(int argc, char* argv[]){
{"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'},
{"directory", required_argument, 0, 'd'},
{"url", required_argument, 0, 'u'},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
/* getopt_long stores the option index here. */ /* getopt_long stores the option index here. */
int option_index = 0; int option_index = 0;
c = getopt_long (argc, argv, "n:i:o:pd", c = getopt_long (argc, argv, "n:i:o:d:u:",
long_options, &option_index); long_options, &option_index);
/* Detect the end of the options. */ /* Detect the end of the options. */
@ -60,6 +62,13 @@ int main(int argc, char* argv[]){
case 'n': case 'n':
instance_id = optarg; instance_id = optarg;
break; break;
case 'd':
directory = optarg;
break;
case 'u':
url_base = optarg;
break;
case '?': case '?':
/* getopt_long already printed an error message. */ /* getopt_long already printed an error message. */
@ -81,6 +90,17 @@ int main(int argc, char* argv[]){
perror("gethostname failed! set instance id manually"); perror("gethostname failed! set instance id manually");
} }
} }
if(directory == NULL){
fprintf(stderr, "directory option MUST be set!\n");
return EXIT_FAILURE;
}
if(url_base == NULL){
fprintf(stderr, "url option MUST be set!\n");
return EXIT_FAILURE;
}
if(verbose){ if(verbose){
printf("Incoming port: %u outgoing port: %u on loopback " printf("Incoming port: %u outgoing port: %u on loopback "
@ -94,6 +114,9 @@ int main(int argc, char* argv[]){
printf("Instance id for messages: %s\n", printf("Instance id for messages: %s\n",
instance_id); instance_id);
printf("Placing files into [%s] linked by [%s]\n", directory,
url_base);
} }
if(init_net() < 0){ if(init_net() < 0){

View file

@ -52,7 +52,7 @@ char* insert_string(char * destination, const char* source,
/* Searches the given header for the key provided and, if found, returns the /* Searches the given header for the key provided and, if found, returns the
* pointer to that key NOT the value * pointer to that key NOT the value
*/ */
char* search_header_key(struct email_t* mail, const char* key){ char* search_header_key(const struct email_t* mail, const char* key){
if(mail == NULL || key == NULL){ if(mail == NULL || key == NULL){
return NULL; return NULL;
@ -79,7 +79,7 @@ char* search_header_key(struct email_t* mail, const char* key){
* otherwise a pointer to the first character of the value is returned. * otherwise a pointer to the first character of the value is returned.
*/ */
char* get_value_from_key(size_t* val_len, size_t key_offset, char* get_value_from_key(size_t* val_len, size_t key_offset,
struct email_t* mail){ const struct email_t* mail){
if(val_len == NULL || mail == NULL){ if(val_len == NULL || mail == NULL){