Projects STRLCPY geneva Commits 4f44a82e
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    plugins/smtp/client.py
     1 +"""
     2 +Client
     3 +Run by the evaluator, tests a forbidden string from client to server
     4 +"""
     5 + 
     6 +import argparse
     7 +import logging
     8 +import os
     9 +import random
     10 +import socket
     11 +import sys
     12 +import time
     13 +import traceback
     14 +import urllib.request
     15 + 
     16 +import requests
     17 + 
     18 +socket.setdefaulttimeout(1)
     19 + 
     20 +import external_sites
     21 +import actions.utils
     22 + 
     23 +from plugins.plugin_client import ClientPlugin
     24 + 
     25 +BASEPATH = os.path.dirname(os.path.abspath(__file__))
     26 + 
     27 + 
     28 +class SMTPClient(ClientPlugin):
     29 + """
     30 + Defines the SMTP client.
     31 + """
     32 + name = "smtp"
     33 + 
     34 + def __init__(self, args):
     35 + """
     36 + Initializes the SMTP client.
     37 + """
     38 + ClientPlugin.__init__(self)
     39 + self.args = args
     40 + 
     41 + @staticmethod
     42 + def get_args(command):
     43 + """
     44 + Defines required args for this plugin
     45 + """
     46 + super_args = ClientPlugin.get_args(command)
     47 + parser = argparse.ArgumentParser(description='SMTP Client')
     48 + 
     49 + parser.add_argument('--server', action='store', help="server to connect to")
     50 + parser.add_argument('--smtp-request', action='store_true', help='Send an SMTP byte string that triggers censorship')
     51 + 
     52 + args, _ = parser.parse_known_args(command)
     53 + args = vars(args)
     54 + 
     55 + super_args.update(args)
     56 + return super_args
     57 + 
     58 + def run(self, args, logger, engine=None):
     59 + """
     60 + Try to send a forbidden string
     61 + """
     62 + fitness = 0
     63 + port = int(args["port"])
     64 + server = args["server"]
     65 + bad_word = args["bad_word"]
     66 + msg = bad_word
     67 + 
     68 + if args.get('smtp_request'):
     69 + msg = b'MAIL FROM: [email protected] \r\n'
     70 + 
     71 + if type(msg) == str:
     72 + msg = msg.encode()
     73 + 
     74 + try:
     75 + client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     76 + client.settimeout(10)
     77 + client.connect((server, port))
     78 + 
     79 + tries = args.get("tries", 1)
     80 + for idx in range(0, int(tries)):
     81 + client.sendall(msg)
     82 + server_data = client.recv(1024)
     83 + logger.debug("Data recieved: %s", server_data.decode('utf-8', 'ignore'))
     84 + if server_data == b'k':
     85 + fitness += 100
     86 + else:
     87 + fitness -= 90
     88 + break
     89 + 
     90 + time.sleep(1)
     91 + client.close()
     92 + # If the fitness is 0, the strategy did something to corrupt/interfere with the socket
     93 + # sending/receiving, usually by just artificially closing the connection. This behavior
     94 + # should not be rewarded with a higher fitness
     95 + if fitness == 0:
     96 + fitness -= 100
     97 + except socket.timeout:
     98 + logger.debug("Client: Timeout")
     99 + fitness -= 100
     100 + except socket.error as exc:
     101 + # If the censor we're running against tears down connects via RSTs, we can punish RSTs as
     102 + # if the strategy did not harm the underlying connection. However, if the censor only injects
     103 + # traffic, not resets, we should punish RSTs harshly, as the strategy likely caused it.
     104 + 
     105 + if exc.errno == 104:
     106 + if args.get("injection_censor"):
     107 + fitness -= 110
     108 + else:
     109 + fitness -= 90
     110 + logger.debug("Client: Connection RST.")
     111 + else:
     112 + fitness -= 100
     113 + logger.exception("Socket error caught in client smtp test.")
     114 + except Exception:
     115 + logger.exception("Exception caught in client smtp test.")
     116 + fitness = -120
     117 + finally:
     118 + logger.debug("Client finished smtp test.")
     119 + return fitness * 4
     120 + 
  • ■ ■ ■ ■ ■ ■
    plugins/smtp/server.py
     1 +import argparse
     2 +import os
     3 +import socket
     4 +import subprocess
     5 +import time
     6 + 
     7 +from plugins.plugin_server import ServerPlugin
     8 + 
     9 +BASEPATH = os.path.dirname(os.path.abspath(__file__))
     10 + 
     11 + 
     12 +class SMTPServer(ServerPlugin):
     13 + """
     14 + Defines the SMTP client.
     15 + """
     16 + name = "smtp"
     17 + def __init__(self, args):
     18 + """
     19 + Initializes the SMTP client.
     20 + """
     21 + ServerPlugin.__init__(self)
     22 + self.args = args
     23 + if args:
     24 + self.port = args["port"]
     25 + 
     26 + @staticmethod
     27 + def get_args(command):
     28 + """
     29 + Defines arguments for this plugin
     30 + """
     31 + super_args = ServerPlugin.get_args(command)
     32 + 
     33 + parser = argparse.ArgumentParser(description='SMTP Server')
     34 + 
     35 + parser.add_argument('--smtp-request', action='store_true', help='Send an SMTP byte string that triggers censorship')
     36 + 
     37 + args, _ = parser.parse_known_args(command)
     38 + args = vars(args)
     39 + super_args.update(args)
     40 + return super_args
     41 + 
     42 + def run(self, args, logger):
     43 + """
     44 + Initializes the SMTP server.
     45 + """
     46 + logger.debug("SMTP server initializing")
     47 + try:
     48 + port = int(args["port"])
     49 + control_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     50 + # Allow socket re-use
     51 + control_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
     52 + server_address = ('0.0.0.0', port)
     53 + logger.debug("Binding to server address 0.0.0.0:%d" % port)
     54 + control_socket.bind(server_address)
     55 + control_socket.settimeout(5)
     56 + control_socket.listen(1)
     57 + except:
     58 + logger.exception("Caught exception in smtp run")
     59 + return
     60 + 
     61 + try:
     62 + connection, client_address = self.get_request(control_socket)
     63 + if not connection:
     64 + logger.error("Failed to get connection")
     65 + return
     66 + 
     67 + bad_word = args["bad_word"]
     68 + expected_msg = bad_word
     69 + 
     70 + if args.get('smtp_request'):
     71 + expected_msg = b'MAIL FROM: [email protected] \r\n'
     72 + 
     73 + if type(expected_msg) == str:
     74 + expected_msg = expected_msg.encode()
     75 + 
     76 + # SMTP data back and forth
     77 + tries = args.get("tries", 1)
     78 + for i in range(0, int(tries)):
     79 + msg = b''
     80 + while msg != expected_msg:
     81 + msg += connection.recv(1024)
     82 + time.sleep(1)
     83 + connection.sendall(b'k')
     84 + 
     85 + time.sleep(1)
     86 + connection.close()
     87 + except socket.error as e:
     88 + if e.errno == 104:
     89 + logger.debug("Server: Connection RST.")
     90 + else:
     91 + logger.debug("Server: Client quit.")
     92 + except socket.ConnectionResetError:
     93 + logger.debug("Server: Connection RST.")
     94 + except Exception:
     95 + logger.exception("Failed during server communication.")
     96 + finally:
     97 + logger.debug("Server exiting")
     98 + 
     99 + def get_request(self, control_socket):
     100 + """
     101 + Get a request from the socket.
     102 + """
     103 + while True:
     104 + try:
     105 + sock, addr = control_socket.accept()
     106 + sock.settimeout(5)
     107 + return (sock, addr)
     108 + except socket.timeout:
     109 + pass
     110 + return (None, None)
     111 + 
     112 + def stop(self):
     113 + """
     114 + Stops this server.
     115 + """
     116 + ServerPlugin.stop(self)
     117 + 
Please wait...
Page is in error, reload to recover