Предыстория:
- Компьютер
mycomputer
работает под управлением Windows 10 и присоединен к доменуmydomain.com
. - Пользователь зарегистрирован с локальной учетной записью
mycomputer\localuser
наmycomputer
. - Пользователь также знает пароль учетной записи домена
mydomain\domainuser
. - Имя субъекта-службы
myprotocol/domainuser
зарегистрировано в Active Directory и сопоставляется с учетной записью доменаmydomain\domainuser
. - Локальному пользователю
mycomputer\localuser
не разрешено запускать процесс какmydomain\domainuser
.
Пользователь хочет запустить серверный процесс под локальной учетной записью, который затем будет использовать учетную запись домена для аутентификации входящих соединений с помощью Kerberos.
Я хочу написать код этого сервера.
Код клиента:
Код клиента прост и состоит из вызова AcquireCredentialsHandle
, за которым следует вызов InitializeSecurityContext
:
AcquireCredentialsHandle(
nullptr,
"Kerberos",
SECPKG_CRED_OUTBOUND,
nullptr,
nullptr,
nullptr,
nullptr,
&credentials,
&lifetime);
InitializeSecurityContext(
&credentials,
nullptr,
"myprotocol/myport",
ISC_REQ_CONFIDENTIALITY,
0,
SECURITY_NATIVE_DREP,
nullptr,
0,
&securityContext,
&outBufferArray,
&contextAttributes,
&lifetime);
Обратите внимание на упрощенное использование строк во фрагментах кода. Реальность, в которой приходится иметь дело с wchar_t
и const
правильностью, несколько уродливее.
Также обратите внимание, что этот код работает при запуске локальным пользователем, если соответствующие учетные данные хранятся в диспетчере учетных данных панели управления, то есть с именем хоста domainuser
(sic.)
Код сервера:
У меня уже есть код, который работает, когда процесс запущен mydomain\domainuser
:
AcquireCredentialsHandle(
nullptr,
"Kerberos",
SECPKG_CRED_INBOUND,
nullptr,
nullptr,
nullptr,
nullptr,
&credentials,
&lifetime);
AcceptSecurityContext(
&credentials,
nullptr,
&inBufferArray,
attribs,
SECURITY_NATIVE_DREP,
&securityContext,
nullptr,
&attribs,
&lifetime);
Но когда сервер запускается mycomputer\localuser
, вызов AcquireCredentialsHandle
завершается с ошибкой с кодом SEC_E_NO_CREDENTIALS
.
- Я попытался изменить первый аргумент этого вызова на
"myprotocol/domainuser"
,"domainuser"
,"mydomain\domainuser"
или даже"[email protected]"
. - Я попытался добавить необходимые учетные данные в диспетчере учетных данных панели управления, используя имя хоста
mycomputer
и дажеdomainuser
.
Что я могу сделать, чтобы получить дескриптор учетных данных mydomain\domainuser
в процессе, запущенном mycomputer\localuser
?
Компиляция фрагмента кода:
#include <string>
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define SECURITY_WIN32
#include <sspi.h>//Requires linking on Secur32.lib
int main(){
CredHandle credentials;
TimeStamp lifetime;
std::string package="Kerberos";
std::string principal="myprotocol/domainuser";
auto res=AcquireCredentialsHandle(
principal.data(),
package.data(),
SECPKG_CRED_INBOUND,
nullptr,
nullptr,
nullptr,
nullptr,
&credentials,
&lifetime);
if(res==SEC_E_OK){
std::printf("Success\n");
FreeCredentialsHandle(&credentials);
return 0;}
else{
std::printf("Failure\n");
return res;}}
AcquireCredentialsHandle
должен инициализироватьcredentials
, но это не удается из-заSECPKG_CRED_INBOUND
. На стороне клиента тот же вызов сSECPKG_CRED_OUTBOUND
работает отлично. - person Arnaud   schedule 29.09.2020