From 2e840e7c381f88425952c6fa9d68e0d433084a5a Mon Sep 17 00:00:00 2001 From: Sam Chudnick Date: Mon, 4 Jul 2022 20:03:27 -0400 Subject: Support both TLS encrypted sessions and plaintext sessions Added support for both TLS and plaintext connections. Server can accept both types of connection simultaneously or in different combinations (i.e encrypted client and plaintext PAM). Added options for specifying dedicated TLS ports on server. Added --plain options for client and PAM to force plaintext connections, default is to use encrypted connections. Configuring encrypted client and PAM connections and plaintext server connections allows for use of a reverse proxy setup with something like nginx. This will avoid having to expose the MFA server directly in setups that traverse the internet. --- client/client.py | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) (limited to 'client') diff --git a/client/client.py b/client/client.py index cc22d0b..0388073 100755 --- a/client/client.py +++ b/client/client.py @@ -26,6 +26,7 @@ def parse_arguments(): parser.add_argument("--config",type=str,help="Path to config file",\ default="/etc/mfa/mfa.conf") parser.add_argument("--key",type=str,help="Client connection key") + parser.add_argument("--plain",action="store_true",help="Connect without TLS") parser.add_argument("--insecure",action="store_true",\ help="Accept invalid TLS certificates") return parser.parse_args() @@ -37,7 +38,7 @@ def prompt_user(prompt): return result -def init_connection(mfa_server, client_port, client_key, insecure=False): +def init_connection_tls(mfa_server, client_port, client_key, insecure=False): # Attempts to connect to MFA server with provided address,port, and key. # Repeats attempt once a seconds until timeout is reached. # Returns socket or None if unable to connect @@ -70,6 +71,27 @@ def init_connection(mfa_server, client_port, client_key, insecure=False): return connection +def init_connection(mfa_server, client_port, client_key): + connection = None + timeout = 0 + timeout_length = 5 + sleep_length = 1 + while connection == None and timeout < timeout_length: + try: + connection = socket.create_connection((mfa_server,client_port)) + connection.send(client_key.encode(FORMAT)) + response = connection.recv(ACK_LENGTH).decode(FORMAT) + if response == ACK_MESSAGE: + print("connected to mfa server") + elif response == DISCONNECT_MESSAGE: + print("server terminated connection") + sys.exit(1) + except ConnectionError: + time.sleep(sleep_length) + timeout += sleep_length + return connection + + def read_config(config_file): parser = configparser.ConfigParser(inline_comment_prefixes="#") parser.read(config_file) @@ -84,6 +106,7 @@ def get_vars(args,confparser): server = None port = None key = None + plain = None insecure = None # Set values from config file first @@ -91,7 +114,13 @@ def get_vars(args,confparser): server = confparser.get("client","server",fallback=None) port = confparser.get("client","port",fallback=None) key = confparser.get("client","key",fallback=None) - insecure = bool(confparser.get("client","insecure",fallback=False)) + plain = confparser.get("client","plain",fallback=False) + insecure = confparser.get("client","insecure",fallback=False) + + if plain.lower() == "false": + plain = False + if insecure.lower() == "false": + insecure = False # Let command line args overwrite any values if args.server != None: @@ -100,6 +129,8 @@ def get_vars(args,confparser): port = args.port if args.key != None: key = args.key + if args.plain: + plain = args.plain if args.insecure: insecure = args.insecure @@ -108,7 +139,7 @@ def get_vars(args,confparser): print("error: one or more items unspecified") sys.exit(1) - return server,port,key,insecure + return server,port,key,plain,insecure def main(): @@ -116,7 +147,7 @@ def main(): args = parse_arguments() confparser = read_config(args.config) - mfa_server,client_port,client_key,insecure = get_vars(args,confparser) + mfa_server,client_port,client_key,plain,insecure = get_vars(args,confparser) # Exit if invalid key is provided if len(client_key) != KEY_LENGTH: @@ -124,7 +155,10 @@ def main(): sys.exit(1) # Open connection to server - conn = init_connection(mfa_server,client_port,client_key,insecure) + if plain: + conn = init_connection(mfa_server,client_port,client_key) + else: + conn = init_connection_tls(mfa_server,client_port,client_key,insecure) if conn == None: print("timed out attempting to connect to server") sys.exit(1) -- cgit v1.2.3