Как я могу заставить apache запрашивать SSL-сертификат клиента, не проверяя его по известному центру сертификации?

9

Я использую apache2 (2.2.3) для обслуживания сайта, где я хотел бы, чтобы клиенты проходили аутентификацию с помощью сертификатов. Поскольку мне нужно только проверить, что пользователь, представляющий конкретный сертификат, является тем же пользователем, который представлял этот сертификат в прошлом, центр сертификации, подписывающий сертификат, не имеет значения. Кажется, однако, что использование SSLVerifyClient requirerequire SSLCACertificateFile ...(или SSLCACertificatePath ...), и тогда apache будет принимать только сертификаты, подписанные CA в этом файле / пути. Есть ли способ заставить apache принять любой клиентский сертификат, независимо от выдающего / подписывающего CA? (т.е. убедитесь, что у клиента есть соответствующий закрытый ключ к представленному открытому ключу, но не пытайтесь проверить выдающий / подписывающий CA)

Исаак
источник
Как вы планируете отслеживать, какие сертификаты прошли проверку подлинности?
Шейн Мэдден
@ShaneMadden: что-то вроде таблицы сопоставления сертификатов с внутренними идентификаторами пользователей. Механика криптографии с открытым ключом должна была бы заменить обмен паролями.
Исаак
2
Правильно - я понимаю, что Apache не выполняет сопоставление таблиц сертификатов с внутренними идентификаторами пользователей. Если вы хотите, чтобы пользователи проходили аутентификацию с помощью клиентских сертификатов, почему бы не дать пользователям сертификаты, которые вы подписали? Как вы упомянули, есть провайдеры OpenID, которые делают именно это. Apache mod_sslбыл разработан для аутентификации пользователей на основе отношений подписи сертификатов; если вы по какой-то причине предпочитаете не обращать на это внимания, вам необходимо реализовать аутентификацию сертификата в своем собственном коде, который также обрабатывает сопоставление сертификата с пользователем.
Шейн Мэдден
@ShaneMadden: Я надеялся избежать выдачи сертификатов, и если я принимаю только те сертификаты, которые выдал, то сертификаты на основе смарт-карт отсутствуют. Независимо от того, что я делаю, какая-то часть системы будет mod_sslработать на уровне приложений, но, поскольку там есть все механизмы, я надеялся, что она позаботится о некоторых делах для меня.
Исаак
1
@ShaneMadden Одним из преимуществ optional_no_caявляется то, что он может быть лучше для пользовательского интерфейса, так как вы можете отобразить сообщение об ошибке HTTP, если что-то не так с сертификатом (иначе вы не могли бы, так как плохой клиентский сертификат прервал бы соединение до уровня HTTP ). Это также полезно, если вы хотите попробовать альтернативные способы проверки сертификата (например, WebID ). Вы правы, что хотите что-то сделать для проверки, и это действительно сработает только тогда, когда запрос обрабатывается кодом (например, в PHP / CGI / Java), а не столько с файлами.
Бруно

Ответы:

10

Как вы обнаружили, вы можете отключить проверку сертификата на уровне рукопожатия SSL / TLS в Apache Httpd с помощью SSLVerifyCLient optional_no_ca.

Вторая проблема, с которой вы столкнетесь, - заставить клиента отправить сертификат. Поскольку ваш сертификат не предназначен для использования в рамках PKI, он может быть самоподписанным и иметь разных эмитентов.

При запросе сертификата клиента сервер отправляет клиенту CertificateRequestсообщение TLS во время передачи запроса. Это сообщение содержит certificate_authoritiesсписок:

Список отличительных названий допустимых центров сертификации. Эти отличительные имена могут указывать желаемое отличительное имя для корневого ЦС или для подчиненного ЦС; таким образом, это сообщение может использоваться для описания как известных корней, так и желаемого пространства авторизации. Если список certificate_authorities пуст, то клиент МОЖЕТ отправить любой сертификат соответствующего ClientCertificateType, если только нет внешнего соглашения об обратном.

Браузеры используют это для выбора клиентского сертификата для отправки (если есть).

(Обратите внимание, что часть о пустом списке есть только в спецификации, начиная с TLS 1.1 и далее. В SSL 3.0 и TLS 1.0 об этом ничего не говорится, и на практике это также будет работать.)

Вы получаете два варианта для этого.

  • Если клиентские сертификаты, которые вы ожидаете, будут самозаверяющими, все они будут иметь разных эмитентов. Поскольку вы не будете знать, чего ожидать, серверу нужно будет отправить пустой список. Чтобы сделать это, используйте SSLCADNRequestFileдирективу и укажите ее в файле, который содержит только пустую строку (если я хорошо помню, он не работает с полностью пустым файлом).

  • Второй (менее чистый) вариант. Согласовать DN эмитента, общий для всех ожидаемых клиентских сертификатов, независимо от того, были ли они действительно выданы этим сертификатом CA (или даже существует этот CA). Поступая так, вы бы значительно нарушили модель PKI (подробнее).

    Если вы согласны с DN эмитента, например CN=Dummy CA(например). Любой может создать самозаверяющий сертификат, используя в CN=Dummy CAкачестве DN субъекта (и DN эмитента), возможно, с разными ключами. Хотя в SSLCADNRequestFileдирективе предполагается, что для создания списка будут настроены сертификаты, они вообще не используются для проверки сертификата клиента, это просто сложный (но естественный в контексте других директив) способ настройки certificate_authoritiesсписка. Если вы, как служба, поместите самоподписанный сертификат с этими именами SSLCADNRequestFile, это приведет к CertificateRequestиспользованию сообщения TLS CN=Dummy CAв certificate_authoritiesсписке (на данном этапе это просто имена, а не сертификаты). После этого клиент сможет получить свой собственный сертификат с DN эмитента.CN=Dummy CAнезависимо от того, может ли его подпись быть проверена этим сертификатом (теми же ключами) или нет, так как в любом случае проверка подписи не вовлечена в эти шаги.

При этом, помните, что с SSLVerifyCLient optional_no_ca, никакая реальная проверка сертификата не сделана (я полагаю, что вы могли бы проверить SSL_CLIENT_VERIFYпеременную, если ваша ручная проверка является просто резервным решением для PKI, который вы все равно настроили). Все, что вы будете знать на этом этапе, - это то, что у клиента есть закрытый ключ для сертификата открытого ключа, который он представил (гарантировано CertificateVerifyсообщением TLS ): вам потребуется выполнить некоторую форму проверки, если вы хотите, чтобы какая-то аутентификация была Сортировать. (Вы не можете доверять какому-либо содержимому сертификата, то есть любой привязке между его открытым ключом и именами / атрибутами, которые он содержит.)

Это не будет работать для файлов, но вы можете сделать это для приложения (например, PHP / CGI / ... даже Java, если вы передаете сертификат на прокси-сервер Java). Одним из основных способов было бы иметь заранее известный список открытых ключей, или вы можете посмотреть на идеи в FOAF + SSL / WebID .

Bruno
источник
2

Использование SSLVerifyCLient optional_no_ca(вместо require) заставляет apache не проверять выдающий CA (и, следовательно, не нужно файл или путь сертификата CA). Это позволяет клиенту / пользователю не предоставлять сертификат, поэтому проверка того, что сертификат вообще использовался, должна выполняться отдельно.

(Очевидно, я просто не смог полностью прочитать mod_sslдокументацию.)

Исаак
источник