1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Shadow Auth Demo
An example of a Circuits Component that requires users authenticate
against /etc/passwd or /etc/shadow before letting them into the web site.
"""
from os import path
from crypt import crypt
from socket import gethostname
from re import compile as compile_regex
from circuits import handler, Component
from circuits.web import _httpauth, Server, Controller
from circuits.web.errors import HTTPError, Unauthorized
def check_auth(user, password):
salt_pattern = compile_regex(r"\$.*\$.*\$")
passwd = "/etc/shadow" if path.exists("/etc/shadow") else "/etc/passwd"
with open(passwd, "r") as f:
rows = (line.strip().split(":") for line in f)
records = [row for row in rows if row[0] == user]
hash = records and records[0][1]
salt = salt_pattern.match(hash).group()
return crypt(password, salt) == hash
class PasswdAuth(Component):
channel = "web"
def init(self, realm=None):
self.realm = realm or gethostname()
@handler("request", priority=1.0)
def _on_request(self, event, request, response):
if "authorization" in request.headers:
ah = _httpauth.parseAuthorization(request.headers["authorization"])
if ah is None:
event.stop()
return HTTPError(request, response, 400)
username, password = ah["username"], ah["password"]
if check_auth(username, password):
request.login = username
return
response.headers["WWW-Authenticate"] = _httpauth.basicAuth(self.realm)
event.stop()
return Unauthorized(request, response)
class Root(Controller):
def index(self):
return "Hello, {0:s}".format(self.request.login)
app = Server(("0.0.0.0", 8000))
PasswdAuth().register(app)
Root().register(app)
app.run()
|