diff --git a/warden3/warden_server/warden_server.py b/warden3/warden_server/warden_server.py index 92e1cef185ea00af85ee61aa50c87c19c7090604..21adb83ad7a5ac9cf329e5b44354667d5bb927e1 100755 --- a/warden3/warden_server/warden_server.py +++ b/warden3/warden_server/warden_server.py @@ -384,26 +384,40 @@ class X509NameAuthenticator(PlainAuthenticator): return PlainAuthenticator.authenticate(self, env, args) - return commons[0] + +class X509MixMatchAuthenticator(PlainAuthenticator): + + def __init__(self, req, db): + PlainAuthenticator.__init__(self, req, db) + self.hostname_auth = X509Authenticator(req, db) + self.name_auth = X509Authenticator(req, db) def authenticate(self, env, args): try: - name = self.get_cert_name(env["SSL_CLIENT_CERT"]) + cert_name = env["SSL_CLIENT_S_DN_CN"] except: exception = self.req.error(message="authenticate: cannot get or parse certificate from env", error=403, exc=sys.exc_info(), env=env) exception.log(logging.getLogger(__name__)) return None + name = args.get("client", [None])[0] + secret = args.get("secret", [None])[0] - client = self.db.get_client_by_name(None, name, None) + # Client names are in reverse notation than DNS, client name should + # thus never be the same as machine hostname (if it is, client + # admin does something very amiss). - if not client: - logging.info("authenticate: client not found by name: \"%s\"" % (name)) - return None + # So, if client sends the same name in query as in the certificate, + # or sends no name or secret (which is necessary for hostname auth), + # use X509NameAuthenticator. Otherwise (names are different and there + # is name and/or secret in query) use (hostname) X509Authenticator. - logging.info("authenticate: %s" % str(client)) + if name == cert_name or (name is None and secret is None): + auth = self.name_auth + else: + auth = self.hostname_auth - return client + return auth.authenticate(self, env, args) class NoValidator(ObjectReq): @@ -1208,7 +1222,7 @@ def build_server(conf): section_def = { "log": ["FileLogger", "SysLogger"], "db": ["MySQL"], - "auth": ["X509Authenticator", "PlainAuthenticator", "X509NameAuthenticator"], + "auth": ["X509Authenticator", "PlainAuthenticator", "X509NameAuthenticator", "X509MixMatchAuthenticator"], "validator": ["JSONSchemaValidator", "NoValidator"], "handler": ["WardenHandler"], "server": ["Server"]