diff options
author | Sam Chudnick <sam@chudnick.com> | 2022-07-04 12:24:59 -0400 |
---|---|---|
committer | Sam Chudnick <sam@chudnick.com> | 2022-07-04 12:24:59 -0400 |
commit | 755d7f5f94b720b028d085cf971c5935c130dec1 (patch) | |
tree | f015e8929563e5302d2ba8e2ee7215d1231debdd /pam | |
parent | 11a4a5edb9f0e22fe8355291942ed03c9765ced5 (diff) |
Implemented TLS encrypted connections
Implemented TLS encrypted connections. Added command line argument and
configuration file option to accept invalid (self-signed) certificates.
Fixed a couple of unrelated issues.
Diffstat (limited to 'pam')
-rwxr-xr-x | pam/pam_mfa.py | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/pam/pam_mfa.py b/pam/pam_mfa.py index 85d0a82..5a5a112 100755 --- a/pam/pam_mfa.py +++ b/pam/pam_mfa.py | |||
@@ -1,5 +1,6 @@ | |||
1 | #!/usr/bin/python3 | 1 | #!/usr/bin/python3 |
2 | import socket | 2 | import socket |
3 | import ssl | ||
3 | import argparse | 4 | import argparse |
4 | import time | 5 | import time |
5 | import sys | 6 | import sys |
@@ -33,9 +34,11 @@ def parse_arguments(): | |||
33 | default="/etc/mfa/mfa.conf") | 34 | default="/etc/mfa/mfa.conf") |
34 | parser.add_argument("--server",type=str,help="MFA server address") | 35 | parser.add_argument("--server",type=str,help="MFA server address") |
35 | parser.add_argument("--port",type=str,help="MFA server PAM connection port") | 36 | parser.add_argument("--port",type=str,help="MFA server PAM connection port") |
37 | parser.add_argument("--insecure",action="store_true", | ||
38 | help="Accept invalid TLS certificates") | ||
36 | return parser.parse_args() | 39 | return parser.parse_args() |
37 | 40 | ||
38 | def init_connection(mfa_server, pam_port): | 41 | def init_connection(mfa_server, pam_port, insecure): |
39 | # Attempts to connect to MFA server with provided address and port | 42 | # Attempts to connect to MFA server with provided address and port |
40 | # Repeats connection attempts once per second until timeout is reached | 43 | # Repeats connection attempts once per second until timeout is reached |
41 | # Returns the socket if connection was successful or None otherwise | 44 | # Returns the socket if connection was successful or None otherwise |
@@ -43,13 +46,22 @@ def init_connection(mfa_server, pam_port): | |||
43 | timeout = 0 | 46 | timeout = 0 |
44 | timeout_length = 5 | 47 | timeout_length = 5 |
45 | sleep_length = 1 | 48 | sleep_length = 1 |
49 | context = ssl.create_default_context() | ||
50 | if insecure: | ||
51 | context.check_hostname = False | ||
52 | context.verify_mode = 0 | ||
46 | while connection == None and timeout < timeout_length: | 53 | while connection == None and timeout < timeout_length: |
47 | try: | 54 | try: |
48 | connection = socket.create_connection((mfa_server,pam_port)) | 55 | #connection = socket.create_connection((mfa_server,client_port)) |
56 | connection = context.wrap_socket(socket.socket(socket.AF_INET), | ||
57 | server_hostname=mfa_server) | ||
58 | connection.connect((mfa_server,int(pam_port))) | ||
49 | return connection | 59 | return connection |
50 | except (ConnectionError,ConnectionRefusedError): | 60 | except (ConnectionError,ConnectionRefusedError): |
51 | time.sleep(sleep_length) | 61 | time.sleep(sleep_length) |
52 | timeout += sleep_length | 62 | timeout += sleep_length |
63 | except ssl.SSLCertVerificationError: | ||
64 | die("error: server presented invalid certificate") | ||
53 | return None | 65 | return None |
54 | 66 | ||
55 | 67 | ||
@@ -82,24 +94,28 @@ def get_vars(args,confparser): | |||
82 | 94 | ||
83 | server = None | 95 | server = None |
84 | port = None | 96 | port = None |
97 | insecure = None | ||
85 | 98 | ||
86 | # Set values from config file first | 99 | # Set values from config file first |
87 | if confparser.has_section("pam"): | 100 | if confparser.has_section("pam"): |
88 | server = confparser.get("pam","server",fallback=None) | 101 | server = confparser.get("pam","server",fallback=None) |
89 | port = confparser.get("pam","port",fallback=None) | 102 | port = confparser.get("pam","port",fallback=None) |
103 | insecure = bool(confparser.get("pam","insecure",fallback=False)) | ||
90 | 104 | ||
91 | # Let command line args overwrite any values | 105 | # Let command line args overwrite any values |
92 | if args.server: | 106 | if args.server != None: |
93 | server = args.server | 107 | server = args.server |
94 | if args.port: | 108 | if args.port != None: |
95 | port = args.port | 109 | port = args.port |
110 | if args.insecure: | ||
111 | insecure = args.insecure | ||
96 | 112 | ||
97 | # Exit if any value is null | 113 | # Exit if any value is null |
98 | if None in [server,port]: | 114 | if None in [server,port]: |
99 | print("error: one or more items unspecified") | 115 | print("error: one or more items unspecified") |
100 | sys.exit(1) | 116 | sys.exit(1) |
101 | 117 | ||
102 | return server,port | 118 | return server,port,insecure |
103 | 119 | ||
104 | 120 | ||
105 | def main(): | 121 | def main(): |
@@ -109,7 +125,7 @@ def main(): | |||
109 | # Get arguments | 125 | # Get arguments |
110 | args = parse_arguments() | 126 | args = parse_arguments() |
111 | confparser = read_config(args.config) | 127 | confparser = read_config(args.config) |
112 | mfa_server,pam_port = get_vars(args,confparser) | 128 | mfa_server,pam_port,insecure = get_vars(args,confparser) |
113 | user = args.user | 129 | user = args.user |
114 | service = args.service | 130 | service = args.service |
115 | 131 | ||
@@ -130,7 +146,7 @@ def main(): | |||
130 | 146 | ||
131 | 147 | ||
132 | # Initalize connection to MFA server. Quit if unable to connect. | 148 | # Initalize connection to MFA server. Quit if unable to connect. |
133 | connection = init_connection(mfa_server,pam_port) | 149 | connection = init_connection(mfa_server,pam_port,insecure) |
134 | if connection == None: | 150 | if connection == None: |
135 | print(failed) | 151 | print(failed) |
136 | sys.exit(1) | 152 | sys.exit(1) |