diff options
| -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 | ||
