Пример #1
0
def SIGALRMhandler(signum, frame):
    CommonUtils.atm_protocol_error_exit('TIMEOUT')
Пример #2
0
    def do_GET(self):
        self.connection.settimeout(10.0)
        # Parse URL query parameters, error out if invalid
        # FIXME: Move everything to POST once ATM-side implemented

        response_to_client = ""

        try:
            urlparts = urlparse.urlparse(self.path)
            path = urlparts.path
            if path != "/atm.cgi":
                raise Exception("Invalid path")
            query = urlparts.query
            queryitems = urlparse.parse_qs(query)
            action = queryitems['action'][0]

            if action not in ('new', 'balance', 'deposit', 'withdraw'):
                raise Exception("Invalid action")

            if (action == 'balance') and ('amount' in queryitems):
                raise Exception("Invalid parameters")

            account = queryitems['account'][0]
            if CommonUtils.valid_accountstr(account) is False:
                raise Exception("Invalid parameters")

            amount = None
            if (action != 'balance'):
                amount = queryitems['amount'][0]
                if CommonUtils.valid_currency(amount) is False:
                    raise Exception("Invalid parameters")

            card = None
            if (action != 'new'):
                card = queryitems['card'][0]
                if (card is None) or (card == ""):
                    raise Exception("Invalid parameters")
            elif (action == 'new') and (card in queryitems):
                raise Exception("Invalid parameters")

            # After validation completes above, process the request
            if action == 'new':
                response_to_client = BANKVAULT.adduser(account, amount)
            elif action == 'balance':
                response_to_client = BANKVAULT.getbalance(account, card)
            elif action == 'deposit':
                response_to_client = BANKVAULT.deposit(account, card, amount)
            elif action == 'withdraw':
                response_to_client = BANKVAULT.withdraw(account, card, amount)
        except ParameterException:  # ATM supplied something incorrect
            self.fail_request("REQUEST FAILED")
            return
        except Exception:
            sys.stdout.write("protocol_error\n")
            sys.stdout.flush()
            self.fail_request("REQUEST FAILED")
            return

        # FIXME: Parse POST parameters
        # Validate supplied parameters/combinations (POST items)

        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.send_header("Pragma", "no-cache")
        self.send_header("Content-control", "no-cache")
        self.end_headers()
        self.wfile.write(response_to_client)
        sys.stdout.write(response_to_client.split("\n")[0] + "\n")
        sys.stdout.flush()
Пример #3
0
class Bank:
    def __init__(self):
        self._common_utils = CommonUtils('Bank')
        self.error_exit = self._common_utils.error_exit
        self._common_utils.parse_opts()

        # For CA
        self._certauthorityprivatekey = None
        self._certauthority = None
        self._certauthoritynextserial = None
        # For web server
        self._tlscert = None
        self._tlsprivatekey = None

    def setup_ca(self):
        self._certauthorityprivatekey = crypto.PKey()
        # Key sizes based on survey of bank web sites & CA Authorities
        # Code based on http://docs.ganeti.org/ganeti/2.9/html/design-x509-ca.html
        self._certauthorityprivatekey.generate_key(crypto.TYPE_RSA, 2048)
        self._certauthority = crypto.X509()
        self._certauthority.set_version(3)
        self._certauthority.set_serial_number(1)
        self._certauthority.get_subject().CN = "ca.bank.example.com"
        self._certauthority.gmtime_adj_notBefore(0)
        self._certauthority.gmtime_adj_notAfter(86400 * 365 * 5)  # ~5 years
        self._certauthority.set_issuer(self._certauthority.get_subject())
        self._certauthority.set_pubkey(self._certauthorityprivatekey)
        self._certauthority.add_extensions([
            crypto.X509Extension("basicConstraints", True,
                                 "CA:TRUE, pathlen:0"),
            crypto.X509Extension("subjectAltName", True,
                                 "DNS:ca.bank.example.com"),
            crypto.X509ExtensionType("keyUsage", True, "keyCertSign, cRLSign"),
            crypto.X509ExtensionType("subjectKeyIdentifier",
                                     False,
                                     "hash",
                                     subject=self._certauthority),
        ])
        self._certauthority.sign(self._certauthorityprivatekey, "sha256")
        self._certauthoritynextserial = 2

    def setup_atmcrypto(self):
        atmkey = crypto.PKey()
        atmkey.generate_key(crypto.TYPE_RSA, 2048)

        certreq = crypto.X509Req()
        certreq.get_subject().CN = "atm-machine.bank.example.com"
        certreq.set_pubkey(atmkey)
        certreq.sign(atmkey, "sha256")

        atmcert = crypto.X509()
        atmcert.set_subject(certreq.get_subject())
        atmcert.set_serial_number(self._certauthoritynextserial)
        atmcert.set_issuer(self._certauthority.get_subject())
        atmcert.gmtime_adj_notBefore(0)
        atmcert.gmtime_adj_notAfter(86400 * 365 * 3)  # under CA's lifetime
        atmcert.set_pubkey(certreq.get_pubkey())
        atmcert.add_extensions([
            crypto.X509Extension("basicConstraints", True, "CA:FALSE"),
            crypto.X509ExtensionType("extendedKeyUsage", True, "clientAuth"),
        ])
        atmcert.sign(self._certauthorityprivatekey, "sha256")
        self._certauthoritynextserial = self._certauthoritynextserial + 1

        if path.exists(self._common_utils.get_authfilename()):
            self.error_exit('Auth file already exists (race check)')
        outfile = file(self._common_utils.get_authfilename(), 'w')
        outfile.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, atmkey))
        outfile.write(crypto.dump_certificate(crypto.FILETYPE_PEM, atmcert))
        outfile.write(
            crypto.dump_certificate(crypto.FILETYPE_PEM, self._certauthority))
        outfile.close()

    def setup_webcrypto(self):
        global TLStempfile

        self._tlsprivatekey = crypto.PKey()
        self._tlsprivatekey.generate_key(crypto.TYPE_RSA, 2048)

        certreq = crypto.X509Req()
        certreq.get_subject().CN = "atmserver.bank.example.com"
        certreq.set_pubkey(self._tlsprivatekey)
        certreq.sign(self._tlsprivatekey, "sha256")

        self._tlscert = crypto.X509()
        self._tlscert.set_subject(certreq.get_subject())
        self._tlscert.set_serial_number(self._certauthoritynextserial)
        self._tlscert.set_issuer(self._certauthority.get_subject())
        self._tlscert.gmtime_adj_notBefore(0)
        self._tlscert.gmtime_adj_notAfter(86400 * 365 *
                                          3)  # under CA's lifetime
        self._tlscert.set_pubkey(certreq.get_pubkey())
        self._tlscert.add_extensions([
            crypto.X509Extension("basicConstraints", True, "CA:FALSE"),
            crypto.X509Extension("subjectAltName", True,
                                 "DNS:atmserver.bank.example.com"),
            crypto.X509ExtensionType("extendedKeyUsage", True, "serverAuth"),
        ])
        self._tlscert.sign(self._certauthorityprivatekey, "sha256")
        self._certauthoritynextserial = self._certauthoritynextserial + 1

        tlsfile = tempfile.NamedTemporaryFile()
        tlsfile.file.write(
            crypto.dump_privatekey(crypto.FILETYPE_PEM, self._tlsprivatekey))
        tlsfile.file.write(
            crypto.dump_certificate(crypto.FILETYPE_PEM, self._tlscert))
        tlsfile.file.write(
            crypto.dump_certificate(crypto.FILETYPE_PEM, self._certauthority))
        tlsfile.file.flush()
        TLStempfile = tlsfile
        # Closing the file/program will destroy this temporary file

    def start_webserver(self):
        tlsServer = Threading_TLSHTTPServer(self._common_utils.get_ipaddress(),
                                            self._common_utils.get_ipport(),
                                            self._tlscert, self._tlsprivatekey)
        # Since we infinitely loop in the webserver
        # Notify that the card was created as late as possible to avoid races
        # with the test infrastructure
        sys.stdout.write("created\n")
        sys.stdout.flush()
        tlsServer.run()

    def run(self):
        global BANKVAULT
        global BANKVAULT_THREADLOCK
        BANKVAULT = Vault()
        BANKVAULT_THREADLOCK = threading.Lock()
        self.setup_ca()
        self.setup_webcrypto()
        self.setup_atmcrypto()

        # Start mutlithreading
        try:
            self.start_webserver()
        except socket.error as e:
            self.error_exit(str(e))
Пример #4
0
def test_int_to_str():
    assert CommonUtils.int_to_str(1) == "1"
    assert CommonUtils.int_to_str(1000) == "1,000"
    assert CommonUtils.int_to_str(1000000) == "1,000,000"
    assert CommonUtils.int_to_str(-1000) == "-1,000"
Пример #5
0
def test_timestamp_to_datetime():
    assert CommonUtils.timestamp_to_datetime(0) == datetime.datetime(1970, month=1, day=1, hour=2)
Пример #6
0
def test_bytes_to_str():
    assert CommonUtils.bytes_to_str(11) == "11 Bytes"
    assert CommonUtils.bytes_to_str(1000) == "1000 Bytes"
    assert CommonUtils.bytes_to_str(10000000) == "9.54 MiB"
    assert CommonUtils.bytes_to_str(100000000000000) == "90.95 TiB"
Пример #7
0
 def __init__(self):
     self._common_utils = CommonUtils('ATM')
     self.atm_protocol_error_exit = \
         self._common_utils.atm_protocol_error_exit
     self.error_exit = self._common_utils.error_exit
     self._common_utils.parse_opts()
Пример #8
0
class ATM:
    def __init__(self):
        self._common_utils = CommonUtils('ATM')
        self.atm_protocol_error_exit = \
            self._common_utils.atm_protocol_error_exit
        self.error_exit = self._common_utils.error_exit
        self._common_utils.parse_opts()

    def read_cardfile(self, card_filename):
        cardhandle = file(card_filename, 'r')
        card_data = cardhandle.readline().rstrip()
        cardhandle.close()
        return card_data

    def write_cardfile(self, card_filename, card_data):
        cardhandle = file(card_filename, 'w')
        cardhandle.write(card_data)
        cardhandle.close()

    def run(self):
        global tempcafile

        utils = self._common_utils
        transactiontype = utils.get_transactiontype()

        card_filename = utils.get_cardfilename()
        card_data = ""

        if transactiontype != 'N':
            if card_filename is not None and os.path.isfile(card_filename):
                try:
                    card_data = self.read_cardfile(card_filename)
                except Exception:
                    self.error_exit('Error loading ATM card')
            else:
                self.error_exit('Card file not found to load')
        params = {}
        if transactiontype == 'N':
            params['action'] = 'new'
            params['account'] = utils.get_account()
            params['amount'] = utils.get_transactionamount()
        elif transactiontype == 'G':
            params['action'] = 'balance'
            params['account'] = utils.get_account()
            params['card'] = card_data
        elif transactiontype == 'D':
            params['action'] = 'deposit'
            params['account'] = utils.get_account()
            params['amount'] = utils.get_transactionamount()
            params['card'] = card_data
        elif transactiontype == 'W':
            params['action'] = 'withdraw'
            params['account'] = utils.get_account()
            params['amount'] = utils.get_transactionamount()
            params['card'] = card_data
        else:
            self.error_exit('Unknown transaction type - should never get here')

        clientcertfile = self._common_utils.get_authfilename()
        cacertfile = clientcertfile  # Last item; only cert with CA:TRUE set

        try:
            # We are using IPs, but certificates prefer names
            # Override the SSL processing to look for our desired name
            atmserverhostname = 'atmserver.bank.example.com'
            httpsclient = urllib3.HTTPSConnectionPool(
                host=utils.get_ipaddress(),
                port=utils.get_ipport(),
                maxsize=1,
                ca_certs=cacertfile,
                cert_reqs=ssl.CERT_REQUIRED,
                cert_file=clientcertfile,
                ssl_version=ssl.PROTOCOL_TLSv1_2,
                retries=0,
                timeout=10,
                assert_hostname=atmserverhostname)
            response = httpsclient.request('GET', '/atm.cgi', params)

        except urllib3.exceptions.SSLError:
            self.atm_protocol_error_exit('SSL Communication failure')
        except Exception:
            self.error_exit('Unknown Communication failure')

        if response.status != 200:
            self.error_exit('Remote error')

        response_data = response.data
        responselines = response_data.split('\n')

        if transactiontype == 'N':
            if len(responselines) == 1:
                self.error_exit('No card info provided')
            if os.path.exists(card_filename) is False:
                self.write_cardfile(card_filename, responselines[1] + '\n')
            else:
                self.error_exit('Card file found-cannot overwrite')

        sys.stdout.write(responselines[0] + '\n')
        sys.stdout.flush()