@@ -142,6 +142,7 @@ def map_config(config):
|
||||
"RQ_REDIS_URL": config["default"]["REDIS_URI"],
|
||||
"RQ_QUEUES": [config["default"]["RQ_QUEUES"]],
|
||||
"DISABLE_CRL_CHECK": config.getboolean("default", "DISABLE_CRL_CHECK"),
|
||||
"CRL_FAIL_OPEN": config.getboolean("default", "CRL_FAIL_OPEN"),
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
from atst.domain.exceptions import UnauthenticatedError, NotFoundError
|
||||
from atst.domain.users import Users
|
||||
from .utils import parse_sdn, email_from_certificate
|
||||
from .crl import CRLRevocationException
|
||||
from .crl import CRLRevocationException, CRLInvalidException
|
||||
|
||||
|
||||
class AuthenticationContext:
|
||||
|
@@ -2,9 +2,13 @@ import sys
|
||||
import os
|
||||
import re
|
||||
import hashlib
|
||||
from flask import current_app as app
|
||||
from datetime import datetime
|
||||
from OpenSSL import crypto, SSL
|
||||
|
||||
# error codes from OpenSSL: https://github.com/openssl/openssl/blob/2c75f03b39de2fa7d006bc0f0d7c58235a54d9bb/include/openssl/x509_vfy.h#L111
|
||||
CRL_EXPIRED_ERROR_CODE = 12
|
||||
|
||||
|
||||
def get_common_name(x509_name_object):
|
||||
for comp in x509_name_object.get_components():
|
||||
@@ -16,6 +20,12 @@ class CRLRevocationException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class CRLInvalidException(Exception):
|
||||
# CRL expired
|
||||
# CRL missing
|
||||
pass
|
||||
|
||||
|
||||
class CRLInterface:
|
||||
def __init__(self, *args, logger=None, **kwargs):
|
||||
self.logger = logger
|
||||
@@ -111,7 +121,7 @@ class CRLCache(CRLInterface):
|
||||
issuer_name = get_common_name(issuer)
|
||||
|
||||
if not crl_info:
|
||||
raise CRLRevocationException(
|
||||
raise CRLInvalidException(
|
||||
"Could not find matching CRL for issuer with Common Name {}".format(
|
||||
issuer_name
|
||||
)
|
||||
@@ -170,6 +180,16 @@ class CRLCache(CRLInterface):
|
||||
return True
|
||||
|
||||
except crypto.X509StoreContextError as err:
|
||||
if err.args[0][0] == CRL_EXPIRED_ERROR_CODE:
|
||||
if app.config.get("CRL_FAIL_OPEN"):
|
||||
self._log_info(
|
||||
"Encountered expired CRL for certificate with CN {} and issuer CN {}, failing open.".format(
|
||||
parsed.get_subject().CN, parsed.get_issuer().CN
|
||||
)
|
||||
)
|
||||
return True
|
||||
else:
|
||||
raise CRLInvalidException("CRL expired. Args: {}".format(err.args))
|
||||
raise CRLRevocationException(
|
||||
"Certificate revoked or errored. Error: {}. Args: {}".format(
|
||||
type(err), err.args
|
||||
|
@@ -8,6 +8,7 @@ from atst.domain.invitations import (
|
||||
ExpiredError as InvitationExpiredError,
|
||||
WrongUserError as InvitationWrongUserError,
|
||||
)
|
||||
from atst.domain.authnid.crl import CRLInvalidException
|
||||
from atst.domain.portfolios import PortfolioError
|
||||
from atst.utils.flash import formatted_flash as flash
|
||||
|
||||
@@ -32,6 +33,11 @@ def make_error_pages(app):
|
||||
def not_found(e):
|
||||
return handle_error(e)
|
||||
|
||||
@app.errorhandler(CRLInvalidException)
|
||||
# pylint: disable=unused-variable
|
||||
def missing_crl(e):
|
||||
return handle_error(e, message="Error Code 008", code=401)
|
||||
|
||||
@app.errorhandler(exceptions.UnauthenticatedError)
|
||||
# pylint: disable=unused-variable
|
||||
def unauthorized(e):
|
||||
|
Reference in New Issue
Block a user