summaryrefslogtreecommitdiff
path: root/login.py
diff options
context:
space:
mode:
authorYves Fischer <yvesf-git@xapek.org>2016-07-09 21:36:50 +0200
committerYves Fischer <yvesf-git@xapek.org>2016-07-09 21:48:26 +0200
commit045f9bc3b68f03d88b9623a0893eeca3ff1ff372 (patch)
tree043d0b4e261f8f41ae74938f210e5aa542652f9a /login.py
parent5d6a8c8939382c4c6fb9f3205a865606a28c9b42 (diff)
downloadauth-xmppmessage-045f9bc3b68f03d88b9623a0893eeca3ff1ff372.tar.gz
auth-xmppmessage-045f9bc3b68f03d88b9623a0893eeca3ff1ff372.zip
implement server for nginx auth_request
Diffstat (limited to 'login.py')
-rwxr-xr-xlogin.py92
1 files changed, 8 insertions, 84 deletions
diff --git a/login.py b/login.py
index 019cbf7..24f62a1 100755
--- a/login.py
+++ b/login.py
@@ -1,78 +1,7 @@
#!/usr/bin/env python3.4
import os
-import re
import sys
-import time
-import struct
-import hashlib
-from urllib.parse import quote as urlencode
-
-# To speed up start time load some modules only as needed
-
-if sys.version_info < (3, 0):
- raise Exception("Require python3+")
-
-
-def file_lock(lock_file):
- from contextlib import contextmanager
-
- @contextmanager
- def file_lock():
- try:
- with open(lock_file, "x") as fh:
- try:
- yield
- except:
- raise
- finally:
- fh.close()
- os.remove(lock_file)
- except FileExistsError:
- raise Exception("Locking failed on {}".format(lock_file))
- return file_lock()
-
-
-def send_message(jid, password, recipient, message):
- import sleekxmpp
-
- def start(event):
- cl.send_message(mto=recipient, mtype='chat', mbody=message)
- cl.disconnect(wait=True)
-
- cl = sleekxmpp.ClientXMPP(jid, password)
- cl.add_event_handler("session_start", start, threaded=True)
- if cl.connect():
- cl.process(block=True)
- else:
- raise Exception("Unable to connect to xmpp server")
-
-
-def generate_token(username, secret, time):
- input = "{}{}{}".format(secret, username, time).encode('utf-8')
- output = struct.unpack(b"<L", hashlib.md5(input).digest()[:4])[0]
- token = "{:02X}-{:02X}-{:02X}".format(
- (output >> 16) & 0xff, (output >> 8) & 0xff, output & 0xff)
- return token
-
-
-def token_message(username, secret, validsec):
- time_now = int(time.time())
- time_now_start = int(time_now - time_now % validsec)
- time_next_end = time_now_start + 2 * validsec
- token = generate_token(username, secret, time_now_start)
- message = "Username: {} Token: {}".format(username, token)
- message += "\nValid from: {} to: {}".format(
- time.strftime("%c %Z(%z)", time.gmtime(time_now_start)),
- time.strftime("%c %Z(%z)", time.gmtime(time_next_end)))
- message += "\nRequested by: {} for: {} on: {}".format(
- os.getenv("IP"), ascii(os.getenv("URI")), os.getenv("HTTP_HOST"))
- message += "\nhttps://{}:{}@{}{}".format(urlencode(username),
- token, os.getenv("HTTP_HOST"), urlencode(os.getenv("URI")))
- return message
-
-
-def normalize_token(token):
- return re.sub(r"[^A-F0-9]", "", token.upper())
+import functions
def run(config):
@@ -89,25 +18,20 @@ def run(config):
if password == "" and username in conf_users:
# avoid spamming by allowing only one message sent at a time
lockfile = os.path.basename(__file__)
- with file_lock("/tmp/lock." + lockfile):
- message = token_message(username, conf_secret, conf_validsec)
+ with functions.file_lock("/tmp/lock." + lockfile):
+ message = functions.token_message(username, conf_secret, conf_validsec,
+ os.getenv("URI"), os.getenv("HTTP_HOST"))
if os.getenv("SKIP_XMPP"): # used for testing
print(message)
else:
- send_message(conf_jid, conf_jid_pw, username, message)
+ functions.send_message(conf_jid, conf_jid_pw, username, message)
elif username in conf_users:
- time_now = int(time.time())
- time_now_start = int(time_now - time_now % conf_validsec)
- time_prev_start = time_now_start - conf_validsec
- valid_tokens = list(map(normalize_token, (
- generate_token(username, conf_secret, time_now_start),
- generate_token(username, conf_secret, time_prev_start)
- )))
- if normalize_token(password) in valid_tokens:
- return os.EX_OK # grant access
+ if functions.verify_token(username, password, conf_secret, conf_validsec):
+ return os.EX_OK
return os.EX_NOPERM # fail by default
+
if __name__ == "__main__":
config = dict(map(lambda kv: kv.split("="),
os.getenv("CONTEXT").split(";")))