diff options
author | Sam Chudnick <sam@chudnick.com> | 2023-06-11 08:15:38 -0400 |
---|---|---|
committer | Sam Chudnick <sam@chudnick.com> | 2023-06-11 08:15:38 -0400 |
commit | 0ccdd42ff4a4cf8f774689ce88439821da7d14f7 (patch) | |
tree | 6d5c945e6d3a08900eafc0bc942de0e07a1e8030 | |
parent | ceddd0cb74f4404b8d743c3fce011c2c9fda4f32 (diff) |
-rw-r--r-- | pam/Makefile | 14 | ||||
-rwxr-xr-x | server/mfad.py | 25 |
2 files changed, 12 insertions, 27 deletions
diff --git a/pam/Makefile b/pam/Makefile deleted file mode 100644 index 46c2cab..0000000 --- a/pam/Makefile +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | all: pam_mfa | ||
2 | |||
3 | pam_mfa: | ||
4 | gcc -fPIC -c pam_mfa.c | ||
5 | gcc -shared -o pam_mfa.so pam_mfa.o -lpam | ||
6 | |||
7 | install: all | ||
8 | PAMDIR = /usr/lib/x86_64-linux-gnu/security/ | ||
9 | cp -f pam_mfa.so ${PAMDIR} | ||
10 | chmod 755 ${PAMDIR}/pam_mfa.so | ||
11 | |||
12 | clean: | ||
13 | rm pam_mfa.so | ||
14 | rm pam_mfa.o | ||
diff --git a/server/mfad.py b/server/mfad.py index cc5073b..169e186 100755 --- a/server/mfad.py +++ b/server/mfad.py | |||
@@ -72,9 +72,6 @@ def read_config(config): | |||
72 | 72 | ||
73 | 73 | ||
74 | def eval_mfa(db, client_key, mfa_methods, client_response): | 74 | def eval_mfa(db, client_key, mfa_methods, client_response): |
75 | print("response: " + client_response) | ||
76 | print("length: " + str(len(client_response))) | ||
77 | print("methods: " + str(mfa_methods)) | ||
78 | # Evaluates MFA and decides if authenticated or denied | 75 | # Evaluates MFA and decides if authenticated or denied |
79 | # Returns 0 for authenticated on 1 for denied | 76 | # Returns 0 for authenticated on 1 for denied |
80 | if "push" in mfa_methods and client_response == "allow": | 77 | if "push" in mfa_methods and client_response == "allow": |
@@ -97,8 +94,6 @@ def validate_totp(db, client_key, client_response): | |||
97 | client = c.fetchone() | 94 | client = c.fetchone() |
98 | secret = client[CLIENT_SECRET_INDEX] | 95 | secret = client[CLIENT_SECRET_INDEX] |
99 | totp = pyotp.TOTP(secret) | 96 | totp = pyotp.TOTP(secret) |
100 | print("Client Response: " + str(client_response)) | ||
101 | print("Valid TOTP: " + str(totp.now())) | ||
102 | if totp.verify(client_response): | 97 | if totp.verify(client_response): |
103 | return AUTHED | 98 | return AUTHED |
104 | else: | 99 | else: |
@@ -112,8 +107,6 @@ def validate_totp(db, client_key, client_response): | |||
112 | # connection for identification | 107 | # connection for identification |
113 | # Client key is used to identify client throughout communication process | 108 | # Client key is used to identify client throughout communication process |
114 | 109 | ||
115 | # //TODO RSA public/private key pairs for proper authentication | ||
116 | |||
117 | def get_client_key(db, username,hostname,service): | 110 | def get_client_key(db, username,hostname,service): |
118 | # Correlates a PAM request to a registered client | 111 | # Correlates a PAM request to a registered client |
119 | # This is done by checking the PAM request against a preconfigured | 112 | # This is done by checking the PAM request against a preconfigured |
@@ -127,9 +120,8 @@ def get_client_key(db, username,hostname,service): | |||
127 | c.execute("""SELECT * FROM applications WHERE username=? AND hostname=? | 120 | c.execute("""SELECT * FROM applications WHERE username=? AND hostname=? |
128 | AND service=?""",(username,hostname,service)) | 121 | AND service=?""",(username,hostname,service)) |
129 | application = c.fetchone() | 122 | application = c.fetchone() |
130 | # Return None if no results found | ||
131 | if application == None: | 123 | if application == None: |
132 | return application | 124 | return (None,None) |
133 | 125 | ||
134 | alias = application[DB_ALIAS_INDEX] | 126 | alias = application[DB_ALIAS_INDEX] |
135 | c.execute("SELECT * FROM clients WHERE alias=?",(alias,)) | 127 | c.execute("SELECT * FROM clients WHERE alias=?",(alias,)) |
@@ -142,6 +134,7 @@ def get_client_key(db, username,hostname,service): | |||
142 | 134 | ||
143 | 135 | ||
144 | def prompt_client(client_key, user, host, service, methods, timeout=10): | 136 | def prompt_client(client_key, user, host, service, methods, timeout=10): |
137 | print(client_connections.keys()) | ||
145 | # Prompts client for MFA | 138 | # Prompts client for MFA |
146 | timer = 0 | 139 | timer = 0 |
147 | while timer < timeout: | 140 | while timer < timeout: |
@@ -210,6 +203,10 @@ def handle_client(db, conn, addr): | |||
210 | conn.send(ACK_MESSAGE.encode(FORMAT)) | 203 | conn.send(ACK_MESSAGE.encode(FORMAT)) |
211 | client_connections[key] = (conn,addr) | 204 | client_connections[key] = (conn,addr) |
212 | print("client connected with key " + key) | 205 | print("client connected with key " + key) |
206 | poll_time = 5 | ||
207 | while True: | ||
208 | # Poll client | ||
209 | time.sleep(poll_time) | ||
213 | 210 | ||
214 | 211 | ||
215 | def parse_pam_data(data): | 212 | def parse_pam_data(data): |
@@ -229,15 +226,17 @@ def handle_pam(db, conn, addr): | |||
229 | 226 | ||
230 | # Correlate request to client | 227 | # Correlate request to client |
231 | client_key,mfa_methods = get_client_key(db, user,host,service) | 228 | client_key,mfa_methods = get_client_key(db, user,host,service) |
232 | mfa_methods = mfa_methods.split(' ') | ||
233 | if client_key == None: | 229 | if client_key == None: |
234 | print("No applications found for user="+user+" host="+host+" service="+service) | ||
235 | conn.send(str(DENIED).encode(FORMAT)) | 230 | conn.send(str(DENIED).encode(FORMAT)) |
236 | return | 231 | die("No applications found for user="+user+" host="+host+" service="+service) |
232 | mfa_methods = mfa_methods.split(' ') | ||
237 | 233 | ||
238 | # Prompt client | 234 | # Prompt client |
239 | response = prompt_client(client_key,user,host,service,mfa_methods) | 235 | response = prompt_client(client_key,user,host,service,mfa_methods) |
240 | 236 | if response == 0: | |
237 | conn.send(str(DENIED).encode(FORMAT)) | ||
238 | die("Did not receive response from client") | ||
239 | |||
241 | # Evaluate Response | 240 | # Evaluate Response |
242 | decision = eval_mfa(db, client_key, mfa_methods, response) | 241 | decision = eval_mfa(db, client_key, mfa_methods, response) |
243 | 242 | ||