From 1062caaae6380fcf79ed11eb3ec5b015c0102e6a Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Jun 08 2020 05:35:02 +0000 Subject: Handle DatabaseError in RPC-Server connect() DatabaseError exceptions with 'account inactivated' message are turned into 401 Unauthorized errors. The problem occurs when a user is disabled but has a valid cookie. Other DatabaseErrors are turned into 503 Service Unavailable. They usually occur when LDAP server is not available or broken. Fixes: https://pagure.io/freeipa/issue/8352 Signed-off-by: Christian Heimes Reviewed-By: Alexander Bokovoy --- diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py index 05c6d3e..27850e8 100644 --- a/ipaserver/rpcserver.py +++ b/ipaserver/rpcserver.py @@ -73,6 +73,7 @@ logger = logging.getLogger(__name__) HTTP_STATUS_SUCCESS = '200 Success' HTTP_STATUS_SERVER_ERROR = '500 Internal Server Error' +HTTP_STATUS_SERVICE_UNAVAILABLE = "503 Service Unavailable" _not_found_template = """ @@ -122,6 +123,18 @@ _unauthorized_template = """ """ +_service_unavailable_template = """ + +503 Service Unavailable + + +

Service Unavailable

+

+%(message)s +

+ +""" + _success_template = """ 200 Success @@ -188,6 +201,20 @@ class HTTP_Status(plugable.Plugin): output = _unauthorized_template % dict(message=escape(message)) return [output.encode('utf-8')] + def service_unavailable(self, environ, start_response, message): + """ + Return a 503 Service Unavailable + """ + status = HTTP_STATUS_SERVICE_UNAVAILABLE + response_headers = [('Content-Type', 'text/html; charset=utf-8')] + + logger.error('%s: %s', status, message) + + start_response(status, response_headers) + output = _service_unavailable_template % dict(message=escape(message)) + return [output.encode('utf-8')] + + def read_input(environ): """ Read the request body from environ['wsgi.input']. @@ -858,6 +885,15 @@ class jsonserver_session(jsonserver, KerberosSession): self.create_context(ccache=ccache_name) except ACIError as e: return self.unauthorized(environ, start_response, str(e), 'denied') + except errors.DatabaseError as e: + # account is disable but user has a valid ticket + msg = str(e) + if "account inactivated" in msg.lower(): + return self.unauthorized( + environ, start_response, str(e), "account disabled" + ) + else: + return self.service_unavailable(environ, start_response, msg) try: response = super(jsonserver_session, self).__call__(environ, start_response)