def check_pin(request, account): """:returns True on success, False on failure""" if request.card_pin != account.pin: eprint("wrong pin!") # eprint("expected '{}', but got '{}'".format(account.pin, request.card_pin)) return False return True
def create_new_account(request): """:return True on success, False otherwise""" if request.account in accounts: eprint("account name '{}' already exists".format(request.account)) return False if request.amount < Balance(10 * 100): eprint("initial balance {} must be at least 10.00".format( request.amount)) return False accounts[request.account] = Account(request.card_pin, request.amount) return True
def deposit(request): """:return True on success, False otherwise""" if not check_account_name_exists(request.account): return False account = accounts[request.account] if not check_pin(request, account): return False if request.amount <= Balance(0): eprint("amount {} must be larger than 0.00".format(request.amount)) return False account.balance += request.amount return True
def process_request(request): """:returns True on success, False on failure""" if request.command == "n": return accounting.create_new_account(request) if request.command == "g": return accounting.check_balance(request) if request.command == "w": return accounting.withdraw(request) if request.command == "d": return accounting.deposit(request) eprint("Invalid command '" + request.command + "'. This shouldn't happen...") return False # this should never happen
def withdraw(request): """:return True on success, False otherwise""" if not check_account_name_exists(request.account): return False account = accounts[request.account] if not check_pin(request, account): return False if request.amount <= Balance(0): eprint("amount {} must be larger than 0.00".format(request.amount)) return False if account.balance < request.amount: eprint("balance '{}' not sufficient to withdraw amount '{}'".format( account.balance, request.amount)) return False account.balance -= request.amount return True
def exit_gracefully(signum, frame): eprint("received SIGINT or SIGTERM, terminating gracefully...") if conn is not None: conn.close() s.close() sys.exit(0)
def input_error_exit(): eprint("input error exit 255") sys.exit(255)
if request.command == "g": return accounting.check_balance(request) if request.command == "w": return accounting.withdraw(request) if request.command == "d": return accounting.deposit(request) eprint("Invalid command '" + request.command + "'. This shouldn't happen...") return False # this should never happen if __name__ == '__main__': args = arguments.read_bank_arguments(sys.argv[1:]) if args is None: eprint("parsing of bank arguments failed, terminating...") input_error_exit() (port, auth_filename) = args if port is None: port = constants.DEFAULT_PORT if auth_filename is None: auth_filename = "bank.auth" key = encryption.create_random_key() eprint("bank key (base64): " + base64.b64encode(key).decode("utf-8")) auth_file = open(auth_filename, "wb") auth_file.write(key) auth_file.close() myprint("created") conn = None
def check_account_name_exists(account_name): """:returns True on success, False on failure""" if account_name not in accounts: eprint("account name '{}' doesn't exists".format(account_name)) return False return True
def main(): args = arguments.read_atm_arguments(sys.argv[1:]) if args is None: eprint("parsing ATM arguments failed. terminating...") input_error_exit() (auth_filename, ip_address, port, card_filename, account_name, command, amount) = args if ip_address is None: ip_address = "127.0.0.1" if port is None: port = constants.DEFAULT_PORT if card_filename is None: card_filename = account_name + ".card" if auth_filename is None: auth_filename = "bank.auth" pin, key = None, None try: if command != "n": card_file = open(card_filename, 'r') pin = card_file.read() card_file.close() else: if os.path.isfile(card_filename): eprint("card file already exists:", card_filename) input_error_exit() pin = my_base64encode(encryption.create_random_key()) auth_file = open(auth_filename, 'rb') key = auth_file.read() eprint("atm key (base64): " + base64.b64encode(key).decode("utf-8")) auth_file.close() except IOError as e: eprint(e) input_error_exit() request = Request.Request(account_name, pin, command, amount) s = socket.socket() s.settimeout(10) try: s.connect((ip_address, port)) data_to_send = str(request) eprint("atm, sending (decrypted): " + data_to_send) encrypted_data_to_send = encryption.encrypt_message(data_to_send, key) eprint("atm, sending " + str(len(encrypted_data_to_send)) + " bytes, (encrypted)") s.send(encrypted_data_to_send) received_data = s.recv(BUFFER_SIZE) if not received_data: s.close() protocol_error_exit() decrypted_data = encryption.decrypt_message(received_data, key) if decrypted_data is None: s.close() protocol_error_exit() else: if decrypted_data == constants.FAILURE: eprint("received FAILURE code from bank. terminating...") s.close() input_error_exit() else: # success eprint("received JSON result from bank") myprint(decrypted_data) if command == "n": card_file = open(card_filename, 'w') card_file.write(pin) card_file.close() except Exception as e: eprint("socket error:", e) s.close() protocol_error_exit()
def protocol_error_exit(): eprint("protocol error exit 63") sys.exit(63)