Committed missing SMTP plugin

This commit is contained in:
Kkevsterrr 2020-09-05 23:56:28 -04:00
parent 88cfcf45d5
commit 4f44a82e1d
2 changed files with 235 additions and 0 deletions

119
plugins/smtp/client.py Normal file
View File

@ -0,0 +1,119 @@
"""
Client
Run by the evaluator, tests a forbidden string from client to server
"""
import argparse
import logging
import os
import random
import socket
import sys
import time
import traceback
import urllib.request
import requests
socket.setdefaulttimeout(1)
import external_sites
import actions.utils
from plugins.plugin_client import ClientPlugin
BASEPATH = os.path.dirname(os.path.abspath(__file__))
class SMTPClient(ClientPlugin):
"""
Defines the SMTP client.
"""
name = "smtp"
def __init__(self, args):
"""
Initializes the SMTP client.
"""
ClientPlugin.__init__(self)
self.args = args
@staticmethod
def get_args(command):
"""
Defines required args for this plugin
"""
super_args = ClientPlugin.get_args(command)
parser = argparse.ArgumentParser(description='SMTP Client')
parser.add_argument('--server', action='store', help="server to connect to")
parser.add_argument('--smtp-request', action='store_true', help='Send an SMTP byte string that triggers censorship')
args, _ = parser.parse_known_args(command)
args = vars(args)
super_args.update(args)
return super_args
def run(self, args, logger, engine=None):
"""
Try to send a forbidden string
"""
fitness = 0
port = int(args["port"])
server = args["server"]
bad_word = args["bad_word"]
msg = bad_word
if args.get('smtp_request'):
msg = b'MAIL FROM: xiazai@upup.info \r\n'
if type(msg) == str:
msg = msg.encode()
try:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.settimeout(10)
client.connect((server, port))
tries = args.get("tries", 1)
for idx in range(0, int(tries)):
client.sendall(msg)
server_data = client.recv(1024)
logger.debug("Data recieved: %s", server_data.decode('utf-8', 'ignore'))
if server_data == b'k':
fitness += 100
else:
fitness -= 90
break
time.sleep(1)
client.close()
# If the fitness is 0, the strategy did something to corrupt/interfere with the socket
# sending/receiving, usually by just artificially closing the connection. This behavior
# should not be rewarded with a higher fitness
if fitness == 0:
fitness -= 100
except socket.timeout:
logger.debug("Client: Timeout")
fitness -= 100
except socket.error as exc:
# If the censor we're running against tears down connects via RSTs, we can punish RSTs as
# if the strategy did not harm the underlying connection. However, if the censor only injects
# traffic, not resets, we should punish RSTs harshly, as the strategy likely caused it.
if exc.errno == 104:
if args.get("injection_censor"):
fitness -= 110
else:
fitness -= 90
logger.debug("Client: Connection RST.")
else:
fitness -= 100
logger.exception("Socket error caught in client smtp test.")
except Exception:
logger.exception("Exception caught in client smtp test.")
fitness = -120
finally:
logger.debug("Client finished smtp test.")
return fitness * 4

116
plugins/smtp/server.py Normal file
View File

@ -0,0 +1,116 @@
import argparse
import os
import socket
import subprocess
import time
from plugins.plugin_server import ServerPlugin
BASEPATH = os.path.dirname(os.path.abspath(__file__))
class SMTPServer(ServerPlugin):
"""
Defines the SMTP client.
"""
name = "smtp"
def __init__(self, args):
"""
Initializes the SMTP client.
"""
ServerPlugin.__init__(self)
self.args = args
if args:
self.port = args["port"]
@staticmethod
def get_args(command):
"""
Defines arguments for this plugin
"""
super_args = ServerPlugin.get_args(command)
parser = argparse.ArgumentParser(description='SMTP Server')
parser.add_argument('--smtp-request', action='store_true', help='Send an SMTP byte string that triggers censorship')
args, _ = parser.parse_known_args(command)
args = vars(args)
super_args.update(args)
return super_args
def run(self, args, logger):
"""
Initializes the SMTP server.
"""
logger.debug("SMTP server initializing")
try:
port = int(args["port"])
control_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Allow socket re-use
control_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_address = ('0.0.0.0', port)
logger.debug("Binding to server address 0.0.0.0:%d" % port)
control_socket.bind(server_address)
control_socket.settimeout(5)
control_socket.listen(1)
except:
logger.exception("Caught exception in smtp run")
return
try:
connection, client_address = self.get_request(control_socket)
if not connection:
logger.error("Failed to get connection")
return
bad_word = args["bad_word"]
expected_msg = bad_word
if args.get('smtp_request'):
expected_msg = b'MAIL FROM: xiazai@upup.info \r\n'
if type(expected_msg) == str:
expected_msg = expected_msg.encode()
# SMTP data back and forth
tries = args.get("tries", 1)
for i in range(0, int(tries)):
msg = b''
while msg != expected_msg:
msg += connection.recv(1024)
time.sleep(1)
connection.sendall(b'k')
time.sleep(1)
connection.close()
except socket.error as e:
if e.errno == 104:
logger.debug("Server: Connection RST.")
else:
logger.debug("Server: Client quit.")
except socket.ConnectionResetError:
logger.debug("Server: Connection RST.")
except Exception:
logger.exception("Failed during server communication.")
finally:
logger.debug("Server exiting")
def get_request(self, control_socket):
"""
Get a request from the socket.
"""
while True:
try:
sock, addr = control_socket.accept()
sock.settimeout(5)
return (sock, addr)
except socket.timeout:
pass
return (None, None)
def stop(self):
"""
Stops this server.
"""
ServerPlugin.stop(self)