* release_quarmail implemented

* attachment mime-type by magic
* swagger definition update
This commit is contained in:
Dominik Chilla 2019-01-17 23:55:50 +01:00
parent aeb5fc932d
commit f4b4d65a0d
8 changed files with 79 additions and 13 deletions

View File

@ -197,6 +197,7 @@ class Attachment:
content_type = None content_type = None
content_encoding = None content_encoding = None
magic = None magic = None
mime_type = None
comment = None comment = None
mailbox_id = None mailbox_id = None
imap_uid = None imap_uid = None
@ -221,6 +222,9 @@ class Attachment:
if 'magic' not in at_ref: if 'magic' not in at_ref:
raise AttachmentException("'magic' is mandatory!") raise AttachmentException("'magic' is mandatory!")
self.magic = at_ref['magic'] self.magic = at_ref['magic']
if 'mime_type' not in at_ref:
raise AttachmentException("'mime_type' is mandatory!")
self.mime_type = at_ref['mime_type']
if 'comment' in at_ref: if 'comment' in at_ref:
self.comment = at_ref['comment'] self.comment = at_ref['comment']
if 'mailbox_id' not in at_ref: if 'mailbox_id' not in at_ref:

View File

@ -197,6 +197,7 @@ class Gulag:
'content_type': part.get_content_type(), 'content_type': part.get_content_type(),
'content_encoding': part['Content-Transfer-Encoding'], 'content_encoding': part['Content-Transfer-Encoding'],
'magic': magic.from_buffer(attach_decoded), 'magic': magic.from_buffer(attach_decoded),
'mime_type': magic.from_buffer(attach_decoded, mime=True),
'sha256': hashlib.sha256(attach_decoded).hexdigest(), 'sha256': hashlib.sha256(attach_decoded).hexdigest(),
'ssdeep': ssdeep.hash(attach_decoded), 'ssdeep': ssdeep.hash(attach_decoded),
'size': len(attach_decoded) 'size': len(attach_decoded)
@ -417,12 +418,27 @@ class Gulag:
"quarmail_id": args['quarmail_id'], "quarmail_id": args['quarmail_id'],
"rfc822_message": True "rfc822_message": True
}) })
# TODO: re-send quarmail to original env_rcpt # the mailbox reference holds the appropriate mailrelay_id
# TODO: self.delete_quarmail() if arg['purge'] mailbox_ref = self.db.get_mailbox(quarmail['mailbox_id'])
mailrelay_ref = self.db.get_mailrelay(mailbox_ref['mailrelay_id'])
mailrelay = GulagMailrelay(mailrelay_ref)
mailrelay.release_quarmail(quarmail)
logging.info(whoami(self) +
"QuarMail("+quarmail['id']+") released. env_rcpt: "+quarmail['env_rcpt']
)
if 'purge' in args:
self.delete_quarmail({"quarmail_id": args['quarmail_id']})
logging.info(whoami(self) +
"QuarMail(" + quarmail['id'] + ") deleted"
)
except GulagNotFoundException as e: except GulagNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagException as e: except GulagException as e:
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
except GulagDBNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagMailrelayException as e:
raise GulagException(whoami(self) + e.message) from e
def bounce_quarmail(self,args): def bounce_quarmail(self,args):
try: try:
@ -433,13 +449,17 @@ class Gulag:
}) })
# the mailbox reference holds the appropriate mailrelay_id # the mailbox reference holds the appropriate mailrelay_id
mailbox_ref = self.db.get_mailbox(quarmail['mailbox_id']) mailbox_ref = self.db.get_mailbox(quarmail['mailbox_id'])
logging.info(whoami(self)+"mailrelay_id: "+str(mailbox_ref['mailrelay_id']))
mailrelay_ref = self.db.get_mailrelay(mailbox_ref['mailrelay_id']) mailrelay_ref = self.db.get_mailrelay(mailbox_ref['mailrelay_id'])
logging.info(whoami(self) + str(mailrelay_ref))
mailrelay = GulagMailrelay(mailrelay_ref) mailrelay = GulagMailrelay(mailrelay_ref)
mailrelay.bounce_quarmail(quarmail) mailrelay.bounce_quarmail(quarmail)
logging.info(whoami(self) +
"QuarMail("+quarmail['id']+") bounced back to "+quarmail['env_from']
)
if 'purge' in args: if 'purge' in args:
self.delete_quarmail({"quarmail_id": args['quarmail_id']}) self.delete_quarmail({"quarmail_id": args['quarmail_id']})
logging.info(whoami(self) +
"QuarMail(" + quarmail['id'] + ") deleted"
)
except GulagNotFoundException as e: except GulagNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagException as e: except GulagException as e:

View File

@ -402,11 +402,13 @@ class GulagDB:
try: try:
cursor = self.conn.cursor() cursor = self.conn.cursor()
cursor.execute("insert into Attachments " + cursor.execute("insert into Attachments " +
"(filename,content_type,content_encoding,magic,sha256,ssdeep,size) " + "(filename,content_type,content_encoding,magic,sha256,"+
"values (%s,%s,%s,%s,%s,%s,%s)", "ssdeep,size,mime_type) " +
"values (%s,%s,%s,%s,%s,%s,%s,%s)",
(attach['filename'],attach['content_type'], (attach['filename'],attach['content_type'],
attach['content_encoding'],attach['magic'], attach['content_encoding'],attach['magic'],
attach['sha256'],attach['ssdeep'],attach['size'] attach['sha256'],attach['ssdeep'],attach['size'],
attach['mime_type']
) )
) )
return cursor.lastrowid return cursor.lastrowid

View File

@ -42,12 +42,12 @@ class GulagMailrelay:
self.mailrelay.sendmail( self.mailrelay.sendmail(
quarmail['env_from'], quarmail['env_from'],
quarmail['env_rcpt'], quarmail['env_rcpt'],
quarmail['rfc822_message'] str(quarmail['rfc822_message'])
) )
self.mailrelay.quit() self.mailrelay.quit()
except (SMTPRecipientsRefused,SMTPHeloError,SMTPSenderRefused, except (SMTPRecipientsRefused,SMTPHeloError,SMTPSenderRefused,
SMTPDataError,SMTPNotSupportedError) as e: SMTPDataError,SMTPNotSupportedError) as e:
raise GulagMailrelayException(whoami(self) + e.message) from e raise GulagMailrelayException(whoami(self) + str(e)) from e
except TimeoutError as e: except TimeoutError as e:
raise GulagMailrelayException(whoami(self) + e.message) from e raise GulagMailrelayException(whoami(self) + e.message) from e
except ConnectionRefusedError as e: except ConnectionRefusedError as e:

View File

@ -31,6 +31,13 @@ class GulagResource(Resource):
if api_key not in self.gulag.config['api_keys']: if api_key not in self.gulag.config['api_keys']:
abort(401, message="NOT AUTHORIZED!") abort(401, message="NOT AUTHORIZED!")
def check_dos(self):
body_len = len(request.get_data(as_text=True))
if(body_len > self.gulag.config['dos_protection']['max_body_bytes']):
raise GulagBadInputException(whoami(self) +
"Request body max size exceeded"
)
class ResRoot(GulagResource): class ResRoot(GulagResource):
def get(self): def get(self):
return {"resource": "Root :)"} return {"resource": "Root :)"}
@ -98,7 +105,7 @@ class ResQuarMail(GulagResource):
abort(500, message=whoami(self)+e.message) abort(500, message=whoami(self)+e.message)
class ResQuarMailRelease(GulagResource): class ResQuarMailRelease(GulagResource):
def get(self,quarmail_id): def post(self,quarmail_id):
args = {"quarmail_id": quarmail_id} args = {"quarmail_id": quarmail_id}
if(request.args.get('purge')): if(request.args.get('purge')):
args['purge'] = True args['purge'] = True

View File

@ -29,6 +29,9 @@
"quarmails": "http://127.0.0.1:9090/api/v1/quarmails/", "quarmails": "http://127.0.0.1:9090/api/v1/quarmails/",
"attachments": "http://127.0.0.1:9090/api/v1/attachments/" "attachments": "http://127.0.0.1:9090/api/v1/attachments/"
}, },
"dos_protection": {
"max_body_bytes": 8388608
},
"db":{ "db":{
"unix_socket": "/mysqld/mysqld.sock", "unix_socket": "/mysqld/mysqld.sock",
"user": "root", "user": "root",

View File

@ -66,6 +66,7 @@ create table Attachments (
content_type varchar(256) not null collate 'ascii_general_ci', content_type varchar(256) not null collate 'ascii_general_ci',
content_encoding varchar(64) collate 'ascii_general_ci', content_encoding varchar(64) collate 'ascii_general_ci',
magic varchar(128), magic varchar(128),
mime_type varchar(128),
comment varchar(256), comment varchar(256),
size int unsigned not null, size int unsigned not null,
sandbox_results varchar(1024) default null collate 'ascii_general_ci', sandbox_results varchar(1024) default null collate 'ascii_general_ci',

View File

@ -52,6 +52,7 @@ paths:
description: get full RFC822 email message for each QuarMail object description: get full RFC822 email message for each QuarMail object
- in: query - in: query
name: headers name: headers
type: string
description: get all email headers for each QuarMail object description: get all email headers for each QuarMail object
required: false required: false
- in: query - in: query
@ -90,6 +91,7 @@ paths:
required: false required: false
- in: query - in: query
name: headers name: headers
type: string
description: if set to a (random) value, all email headers will be returned description: if set to a (random) value, all email headers will be returned
required: false required: false
responses: responses:
@ -117,8 +119,8 @@ paths:
- in: body - in: body
name: quarmail name: quarmail
description: quarmail fields to modify. description: quarmail fields to modify.
schema: schema:
$ref: "#/definitions/QuarMail" $ref: "#/definitions/QuarMail"
responses: responses:
202: 202:
description: quarantined email deleted description: quarantined email deleted
@ -259,6 +261,7 @@ paths:
description: not found description: not found
500: 500:
description: server error description: server error
/quarmails/{quarmail_id}/bounce: /quarmails/{quarmail_id}/bounce:
post: post:
summary: bounces a quarantined email by quarmail_id summary: bounces a quarantined email by quarmail_id
@ -273,7 +276,29 @@ paths:
type: string type: string
responses: responses:
200: 200:
description: null description: nothing
400:
description: bad input parameter
404:
description: not found
500:
description: server error
/quarmails/{quarmail_id}/release:
post:
summary: releases a quarantined email by quarmail_id
operationId: release_quarmail
produces:
- application/json
parameters:
- in: path
name: quarmail_id
description: unique id of quarantined email
required: true
type: string
responses:
200:
description: nothing
400: 400:
description: bad input parameter description: bad input parameter
404: 404:
@ -373,6 +398,7 @@ definitions:
- content_encoding - content_encoding
- content_type - content_type
- magic - magic
- mime_type
- mailbox_id - mailbox_id
- imap_uid - imap_uid
- ssdeep - ssdeep
@ -397,6 +423,9 @@ definitions:
magic: magic:
type: string type: string
example: "PDF document, version 1.2" example: "PDF document, version 1.2"
mime_type:
type: string
example: "application/pdf"
href: href:
type: string type: string
description: hypermedia description: hypermedia