diff options
Diffstat (limited to 'client')
| -rwxr-xr-x | client/client.py | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/client/client.py b/client/client.py new file mode 100755 index 0000000..abbc9de --- /dev/null +++ b/client/client.py | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | #!/usr/bin/env python3 | ||
| 2 | |||
| 3 | import socket | ||
| 4 | import time | ||
| 5 | import argparse | ||
| 6 | import sys | ||
| 7 | |||
| 8 | HEADER_LENGTH = 64 | ||
| 9 | KEY_LENGTH = 64 | ||
| 10 | DISCONNECT_LENGTH = ACK_LENGTH = 3 | ||
| 11 | ACK_MESSAGE = "ACK" | ||
| 12 | DISCONNECT_MESSAGE = "BYE" | ||
| 13 | FORMAT = "utf-8" | ||
| 14 | |||
| 15 | def parse_arguments(): | ||
| 16 | parser = argparse.ArgumentParser() | ||
| 17 | parser.add_argument("--server",type=str,help="IP of MFA Server",required=True) | ||
| 18 | parser.add_argument("--port",type=int,help="Port to connect to",required=True) | ||
| 19 | parser.add_argument("--key",type=str,help="Client connection key",required=True) | ||
| 20 | return parser.parse_args() | ||
| 21 | |||
| 22 | def prompt_user(prompt): | ||
| 23 | # Prompt user for input and return input | ||
| 24 | print(prompt) | ||
| 25 | result = input("> ") | ||
| 26 | return result | ||
| 27 | |||
| 28 | |||
| 29 | def init_connection(mfa_server, client_port, client_key): | ||
| 30 | # Attempts to connect to MFA server with provided address,port, and key. | ||
| 31 | # Repeats attempt once a seconds until timeout is reached. | ||
| 32 | # Returns socket or None if unable to connect | ||
| 33 | connection = None | ||
| 34 | timeout = 0 | ||
| 35 | timeout_length = 5 | ||
| 36 | sleep_length = 1 | ||
| 37 | while connection == None and timeout < timeout_length: | ||
| 38 | try: | ||
| 39 | connection = socket.create_connection((mfa_server,client_port)) | ||
| 40 | connection.send(client_key.encode(FORMAT)) | ||
| 41 | response = connection.recv(ACK_LENGTH).decode(FORMAT) | ||
| 42 | if response == ACK_MESSAGE: | ||
| 43 | print("connected to mfa server") | ||
| 44 | elif response == DISCONNECT_MESSAGE: | ||
| 45 | print("server terminated connection") | ||
| 46 | sys.exit(1) | ||
| 47 | except ConnectionError: | ||
| 48 | time.sleep(sleep_length) | ||
| 49 | timeout += sleep_length | ||
| 50 | return connection | ||
| 51 | |||
| 52 | |||
| 53 | def main(): | ||
| 54 | # Get arguments, exit if unable to connect | ||
| 55 | args = parse_arguments() | ||
| 56 | mfa_server = args.server | ||
| 57 | client_port = args.port | ||
| 58 | client_key = args.key | ||
| 59 | |||
| 60 | # Exit if invalid key is provided | ||
| 61 | if len(client_key) != KEY_LENGTH: | ||
| 62 | print("invalid key") | ||
| 63 | sys.exit(1) | ||
| 64 | |||
| 65 | # Open connection to server | ||
| 66 | conn = init_connection(mfa_server,client_port,client_key) | ||
| 67 | if conn == None: | ||
| 68 | print("timed out attempting to connect to server") | ||
| 69 | sys.exit(1) | ||
| 70 | |||
| 71 | # Main loop | ||
| 72 | running = True | ||
| 73 | while running: | ||
| 74 | # Receive MFA prompt from server | ||
| 75 | prompt_len = int(conn.recv(HEADER_LENGTH).decode(FORMAT)) | ||
| 76 | prompt = conn.recv(prompt_len).decode(FORMAT) | ||
| 77 | # Ask user for response | ||
| 78 | answer = prompt_user(prompt) | ||
| 79 | # Send answer to MFA server | ||
| 80 | answer_length = len(answer) | ||
| 81 | length_msg = str(answer_length) | ||
| 82 | length_msg += ' ' * (HEADER_LENGTH - len(length_msg)) | ||
| 83 | conn.send(length_msg.encode(FORMAT)) | ||
| 84 | conn.send(answer.encode(FORMAT)) | ||
| 85 | |||
| 86 | |||
| 87 | |||
| 88 | |||
| 89 | if __name__ == '__main__': | ||
| 90 | main() | ||
