Подтвердить что ты не робот

Как проверить сертификат клиента с помощью Snap

Я знаю, что он редко используется, но можно ли получить доступ к сертификату клиента в Snap?

Если нет, возможно ли использовать другой веб-стек?

4b9b3361

Ответ 1

Это недоступно для вас в пакете Snap snap-server, который, как я предполагаю, является тем, как вы используете свой сервер.

Buuuuut это не сложно построить, либо путем разметки, либо как отдельный модуль (вам придется скопировать некоторый код, хотя, поскольку некоторые внутренние значения вам понадобятся, не экспортируются). bindHttps, расположенный в Snap.Internal.Http.Server.TLS, это то, что вы хотите настроить. Эта функция в основном является оберткой вокруг вызовов OpenSSL.Session из библиотеки HsOpenSSL, которая сама по себе является свободной оболочкой библиотеки OpenSSL.

К счастью для нас OpenSSL имеет полную поддержку клиентских сертификатов. Вам просто нужно установить режим проверки на SSL_VERIFY_PEER. Есть и другие кнопки, с которыми вы можете играть. Вы также должны убедиться, что вы установили цепочку сертификатов для фактического подтверждения сертификата клиента. Цепочка доверия и весь этот джаз. Для справки см., Как nginx делает это.

Еще лучше, эта функция показана в HsOpenSSL как функция contextSetVerificationMode :: SSLContext -> VerificationMode -> IO (). Вы заметите, что ctx :: SSLContext существует в определении Snap bindHttps. Все, что вам нужно сделать, это либо скопировать, либо переделать этот модуль и ввести ваши вызовы.

Он будет выглядеть примерно так (предупреждение непроверенного кода):

± % diff -u /tmp/{old,new}
--- /tmp/old    2016-04-11 11:02:42.000000000 -0400
+++ /tmp/new    2016-04-11 11:02:56.000000000 -0400
@@ -19,6 +19,7 @@

      ctx <- SSL.context
      SSL.contextSetPrivateKeyFile ctx key
+     SSL.contextSetVerificationMode ctx (SSL.VerifyPeer True True (Just (\_ _ -> return True)))
      if chainCert
        then SSL.contextSetCertificateChainFile ctx cert
        else SSL.contextSetCertificateFile ctx cert

Первый логический параметр указывает, что OpenSSL завершится с ошибкой, если сертификат клиента отсутствует. Второе логическое значение указывает OpenSSL, что сертификат клиента требуется только по первому запросу и больше не нужен для повторных переговоров. Третье значение - это обратный вызов. Я думаю, что правильная вещь - просто вернуть True в обратном вызове. Это то, что nginx делает, в любом случае.