Ошибка аутентификации SslStream под учетной записью LOCAL SYSTEM

У меня есть такой код:

string certificateFilePath = @"C:\Users\Administrator\Documents\Certificate.pfx";

string certificateFilePassword = "Some Password Here";

X509Certificate clientCertificate = new X509Certificate(certificateFilePath, certificateFilePassword);

TcpClient client = new TcpClient(host, port);

SslStream stream = new SslStream(client.GetStream(), false, (sender, certificate, chain, errors) => true);

X509CertificateCollection clientCertificates = new X509CertificateCollection {clientCertificate};

stream.AuthenticateAsClient(host, clientCertificates, SslProtocols.Tls, false);

Когда я запускаю код в консольном приложении, все работает нормально, stream.IsAuthenticated и stream.IsMutuallyAuthenticated возвращают true, а stream.LocalCertificate содержит правильный объект сертификата.

Однако при выполнении того же самого кода в Windows Service (as LOCAL SYSTEM user), хотя stream.IsAuthenticated возвращает true, stream.IsMutuallyAuthenticated возвращает false, а stream.LocalCertificate возвращает null.

Это происходит, когда в обоих сценариях после запуска первой строки clientCertificate загружаются правильные данные сертификации и содержится правильная информация для Subject и Issuer сертификата.

Я также попытался заставить SslStream выбрать сертификат, используя этот код:

string certificateFilePath = @"C:\Users\Administrator\Documents\Certificate.pfx";

string certificateFilePassword = "Some Password Here";

X509Certificate clientCertificate = new X509Certificate(certificateFilePath, certificateFilePassword);

TcpClient client = new TcpClient(host, port);

SslStream stream = new SslStream(client.GetStream(), false, (sender, certificate, chain, errors) => true, (sender, host, certificates, certificate, issuers) => clientCertificate);

X509CertificateCollection clientCertificates = new X509CertificateCollection {clientCertificate};

stream.AuthenticateAsClient(host, clientCertificates, SslProtocols.Tls, false);

Однако код по-прежнему не работает, и stream.IsMutuallyAuthenticated возвращает false, а stream.LocalCertificate возвращает null.

Я изучаю это уже несколько дней и не могу понять. Любая помощь высоко ценится.

Изменить: после попытки получить сертификат с помощью инструмента WinHttpCertCfg оказалось, что в отличие от аналогичный вопрос (ы), учетная запись LOCAL SYSTEM уже имеет доступ к закрытому ключу для целевого сертификата, как вы можете видеть на рисунке ниже:  Вывод инструмента WinHttpCertCfg для  целевой сертификат Таким образом, проблема остается нерешенной.


person Rojan Gh.    schedule 10.07.2017    source источник
comment
Что произойдет, если вы попытаетесь запустить службу как NETWORK SERVICE или LOCAL SERVICE вместо LOCAL SYSTEM?   -  person Camilo Terevinto    schedule 10.07.2017
comment
@CamiloTerevinto Я попробую и вернусь к вам через несколько минут.   -  person Rojan Gh.    schedule 10.07.2017
comment
Точно такой же результат с NETWORK SERVICE, LOCAL SERVICE и LOCAL SYSTEM @CamiloTerevinto   -  person Rojan Gh.    schedule 10.07.2017
comment
Можете ли вы запустить его как администратор и сообщить нам об этом?   -  person JuanR    schedule 10.07.2017
comment
Он отлично работает как администратор @Juan   -  person Rojan Gh.    schedule 10.07.2017
comment
Я так и думал. Что вы сдаете на сертификациюFilePath? Можете ли вы скрыть данные и опубликовать образец того, что вы используете в качестве параметра?   -  person JuanR    schedule 10.07.2017
comment
Я передаю абсолютный путь к файлу. Я собираюсь обновить код примерами данных @Juan   -  person Rojan Gh.    schedule 10.07.2017
comment
Я обновил код некоторыми примерными настройками, аналогичными тем, которые я использую @Juan.   -  person Rojan Gh.    schedule 10.07.2017
comment
Понятно. Я считаю, что вам нужно предоставить учетной записи доступ к закрытому ключу. Я отмечу это как возможный дубликат. Проверьте это: stackoverflow.com/ questions / 4151401 /   -  person JuanR    schedule 10.07.2017
comment
Возможный дубликат Как избежать доступа администратора для SslStream.AuthenticateAsClient?   -  person JuanR    schedule 10.07.2017
comment
@Juan Я обновил вопрос, указав вывод инструмента WinHttpCertCfg, показывающий, что учетная запись LOCAL SYSTEM уже имела доступ к закрытым ключам, и поэтому это не вопрос, аналогичный тому, который вы предложили.   -  person Rojan Gh.    schedule 12.07.2017
comment
Понятно. Как насчет прав доступа к файлам? Проблема явно связана с безопасностью, поскольку он отлично работает как администратор.   -  person JuanR    schedule 12.07.2017
comment
LOCAL SYSTEM имеет полные разрешения для файла сертификата @Juan   -  person Rojan Gh.    schedule 13.07.2017


Ответы (2)


Я наконец заставил код работать, играя с классами X509.

Вот код, который мне подходит:

string host = "The Host";

int port = 777;

string certificateFilePath = @"C:\Users\Administrator\Documents\Certificate.pfx";

string certificateFilePassword = "Some Password Here";

X509Certificate clientCertificate = new X509Certificate(certificateFilePath, certificateFilePassword);

X509Certificate2 clientCertificate2 = new X509Certificate2(clientCertificate); //<== Create a X509Certificate2 object from the X509Certificate which was loaded from the file. The clientCertificate2 loads the proper data

TcpClient client = new TcpClient(host, port);

SslStream stream = new SslStream(client.GetStream(), false, (sender, certificate, chain, errors) => true);

X509CertificateCollection clientCertificates = new X509CertificateCollection { clientCertificate2 }; //<== Using the clientCertificate2 which has loaded the proper data instead of the clientCertificate object

stream.AuthenticateAsClient(host, clientCertificates, SslProtocols.Tls, false);

Таким образом, мой код находит в системе правильный X509Store, сертификат и закрытый ключ.

Я понял это на собственном опыте. Однако я не смог найти четких объяснений, почему это должно быть так на MSDN.

person Rojan Gh.    schedule 17.07.2017

Один из методов отладки, который мы используем для решения таких проблем с сервисом, - это использование такой утилиты, как PsExec . Это позволит вам запускать интерактивный процесс в качестве необходимой учетной записи службы.

-s Запустить процесс в системной учетной записи.

В справке будет написано «удаленный процесс», но его также можно использовать для локального процесса.

Например, в приведенном ниже примере вы получите командную строку в качестве системной учетной записи после выполнения приведенного ниже в командной строке с правами администратора.

PsExec.exe -s cmd

В командном окне вы можете проверить с помощью команды WhoAmI

C:\Windows\system32>whoami
nt authority\system

Это позволит вам провести несколько интерактивных тестов, чтобы попробовать различные комбинации.

Учетная запись SYSTEM имеет максимально возможные привилегии. на локальной машине.

Вы также могли видеть, что создание настраиваемой учетной записи для запуска службы является рекомендуемым вариантом. Но это связано с необходимостью сохранения другого пароля. В более новых версиях Windows есть управляемые учетные записи служб. Это может быть лучшим вариантом.

управляемая учетная запись службы и виртуальная учетная запись - предназначены для обеспечения изоляции приложений от их собственных учетных записей, устраняя при этом необходимость для администратора вручную администрировать SPN и учетные данные для этих учетных записей.

person Subbu    schedule 14.07.2017
comment
Если вы читаете комментарии к моему вопросу, я уже пытался запустить процесс в NETWORK SERVICE, LOCAL SERVICE и LOCAL SYSTEM, чтобы узнать, есть ли какие-либо проблемы с разрешениями и т.д., и я использовал PsExec.exe либо с флагом -s, либо с другими командами для этого , но это не помогло. - person Rojan Gh.; 14.07.2017