2015-07-03 1 views
21

Я работаю над сервисом WCF, который должен быть использован клиентом, который не разработан мной, а также не .NET (возможно, Java).Взаимная аутентификация SSL с WCF: нет CertificateRequest и CertificateVerify в момент установления связи

В любом случае служба должна поддерживать взаимную аутентификацию SSL, когда служба и клиент аутентифицируются сертификатами сертификатов X.509 на транспортном уровне. Сертификаты были обменены между сторонами в предыдущий момент.

Моя проблема заключается в том, что я не могу получить правильную конфигурацию WCF, чтобы проверка подлинности сертификата клиента работала правильно. Что я ожидаю, что, как часть рукопожатия TLS, сервер также включает в себя Certificate Request, как показано ниже:

enter image description here

После этого клиент должен ответить с `Сертификат Проверка» среди прочего:

enter image description here

The (последняя) конфигурация службы это одна. Я использую настраиваемую привязку, с режимом аутентификации, установленным на MutualSslNegotiated.

<bindings> 
    <customBinding> 
    <binding name="CarShareSecureHttpBindingCustom"> 
     <textMessageEncoding messageVersion="Soap11" /> 
     <security authenticationMode="MutualSslNegotiated"/> 
     <httpsTransport requireClientCertificate="true" /> 
    </binding> 
    </customBinding> 
</bindings> 

... 

<serviceBehaviors> 
    <behavior name="ServiceBehavior"> 
    <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" /> 
    <serviceDebug includeExceptionDetailInFaults="false" httpHelpPageEnabled="false" /> 
    <serviceCredentials> 
     <serviceCertificate findValue="..." storeLocation="LocalMachine" x509FindType="FindByIssuerName" storeName="My" /> 
     <clientCertificate> 
     <certificate findValue="..." storeName="My" storeLocation="LocalMachine" x509FindType="FindByIssuerName"/> 
     </clientCertificate> 
    </serviceCredentials> 
    </behavior> 
</serviceBehaviors> 

Сервер Здравствуйте часть рукопожатия выглядит следующим образом для всех конфигураций услуг, которые я попробовал, не CertificateRequest. enter image description here

Другие вещи, которые я должен упомянуть:

  • Услуга самодостаточно и прослушивает не по умолчанию порт (не 443). Сертификат SSL сервера привязан к этому порту.
  • Я также пробовал basicHttpBinding и wsHttpBidning с режимом безопасности, установленным на Transport, и аутентификацию клиента, установленную на Certificate, без результатов (фактически на самом деле).

Любые идеи были бы оценены.

+0

Вы пытаетесь включить трассировку WCF и посмотреть, есть ли какие-либо подробные ошибки есть? – UserControl

+0

@UserControl: Да, трассировка включена, но к сожалению нет связанных ошибок. –

+0

Wild shot - Есть ли какие-то корневые сертификаты из цепочки доверия сертификатов клиентов, отсутствующие на стороне сервера? То есть у вас есть сертификат клиента, но некоторые корневые сертификаты в цепочке отсутствуют ...? –

ответ

11

ОК, после нескольких попыток я понял это. Отправляя это, если другие сталкиваются с той же проблемой.

Я должен продолжить, отметив, что это поведение действительно нужно упомянуть где-то в MSDN в месте, которое действительно доступно для всех, кто ищет информацию о безопасности WCF и не зарывается глубоко в документацию какого-либо инструмента.

Платформы, на которых я смог воспроизвести и исправить это: Windows 8.1 x64 и Windows Server 2008 R2 Standard.

Как я уже упоминал, моя проблема заключалась в том, что я не мог настроить защиту WCF таким образом, чтобы для службы требовались клиентские сертификаты. Общая путаница, которую я заметил при поиске решения, заключается в том, что многие люди считают, что клиент может отправить сертификат, если он есть, без ответа. Это, конечно, не тот случай - сервер должен сначала запросить его, и, кроме того, указать, какие CA разрешены through a CertificateRequest reply.

Подводя итог, моя ситуация:

  • Сервис резидентных.
  • Служба работает на HTTPS, на нестандартном порту (не 443, а 9000).

Это означало, что мне пришлось создать привязку SSL-сертификата для порта 9000 с помощью netsh.exe http add sslcert. Ну, привязка была создана, но был улов. Я только нашел этот вопрос после запуска netsh http show sslcert просто проверить мои привязки:

IP:port      : 0.0.0.0:9000 
Certificate Hash    : ... 
Application ID    : ... 
Certificate Store Name  : MY 
Verify Client Certificate Revocation : Enabled 
Verify Revocation Using Cached Client Certificate Only : Disabled 
Usage Check     : Enabled 
Revocation Freshness Time : 0 
URL Retrieval Timeout  : 0 
Ctl Identifier    : (null) 
Ctl Store Name    : (null) 
DS Mapper Usage    : Disabled 
-->Negotiate Client Certificate : Disabled 

Преступник был последним свойством связывания, «Согласование сертификата клиента», документально here. По-видимому, по умолчанию это свойство отключено. Вам нужно включить его явно при создании привязки.

Воссоздание связывание с утверждением ниже решен вопрос:

netsh.exe http add sslcert ipport=0.0.0.0:9000 certhash=... appid=... certstorename=MY verifyclientcertrevocation=Enable VerifyRevocationWithCachedClientCertOnly=Disable UsageCheck=Enable clientcertnegotiation=Enable 

Перед проверкой привязок я пытался хостинг простой службы WCF в IIS и включить проверку подлинности сертификата клиента там. Было очень любопытно увидеть, что, хотя не было CertificateRequest, выпущенного IIS, он все еще не справился с 403,7. Даже IIS не создавал привязку с соответствующими параметрами.

В любом случае, теперь это работает, и вы можете это исправить.

Не следует забывать, конфигурацию службы изменилась, а также (связывание безопасности) для того, чтобы обеспечить согласование сертификата:

<customBinding> 
    <binding name="CustomHttpBindingCustom" receiveTimeout="01:00:00"> 
    <textMessageEncoding messageVersion="Soap11" /> 
    <security authenticationMode="SecureConversation" requireSecurityContextCancellation="true"> 
     <secureConversationBootstrap allowInsecureTransport="false" authenticationMode="MutualSslNegotiated" requireSecurityContextCancellation="true"></secureConversationBootstrap> 
    </security> 
    <httpsTransport requireClientCertificate="true" /> 
    </binding> 
</customBinding>