Создать процесс как другой пользователь с Java и Kerberos - PullRequest
0 голосов
/ 11 сентября 2018

Я работаю над приложением на сервере Java (работающем под Windows в качестве службы) и хочу реализовать следующий сценарий:

  • Пользователь отправляет POST-запрос на сервер.Пользователь проходит проверку подлинности с помощью Kerberos (SPNEGO, SSO в корпоративной среде).
  • Служба создает новый процесс Java.Процесс должен выполняться как аутентифицированный пользователь, а , а не пользователь сервиса (олицетворение / делегирование).
  • Новый процесс должен выполняться в контексте безопасности пользователя.Он должен взаимодействовать с другими удаленными системами, требующими аутентификации Kerberos (например, общие папки, другие веб-службы, ...).

Рабочее подтверждение концепции:

  • Приложение Spring Boot с Waffle для аутентификации Kerberos.
  • Создайте новый процесс для аутентифицированного пользователя.Я использую JNA и встроенную функцию Windows CreateProcessAsUser .
  • Процесс создается как аутентифицированный пользователь.Я могу проверить это с помощью утилиты Process Explorer.

Что отсутствует и не работает :

  • Процесс не может запрашивать другие билеты Kerberos (например,вызывая InitializeSecurityContext ())
  • Процесс не может получить доступ к сетевым ресурсам.
  • Процесс не может обмениваться данными с другими веб-службами, для которых требуется проверка подлинности Kerberos.

Мои вопросы:

  • Что мне не хватает или что возможно не так с моим кодом?
  • Возможно ли вообще реализовать то, чего я хочу достичь?

Сервер - Аутентификация (сокращена, извлечена из Waffle):

final byte[] tokenBuffer = authorizationHeader.getTokenBytes();
CredHandle serverCredHandle = new CredHandle();
TimeStamp clientLifetime = new TimeStamp();
int rc = Secur32.INSTANCE.AcquireCredentialsHandle(
                                null, 
                                "Negotiate", 
                                Sspi.SECPKG_CRED_INBOUND, 
                                null, 
                                null, 
                                null, 
                                null, 
                                serverCredHandle, 
                                clientLifetime);

SecBufferDesc pbClientToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, tokenBuffer);
CtxtHandle phNewServerContext = new CtxtHandle();
SecBufferDesc pbServerToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
IntByReference pfClientContextAttr = new IntByReference();

rc = Secur32.INSTANCE.AcceptSecurityContext(
                                serverCredHandle, 
                                null, 
                                pbClientToken, 
                                Sspi.ISC_REQ_CONNECTION, 
                                Sspi.SECURITY_NATIVE_DREP, 
                                phNewServerContext, 
                                pbServerToken, 
                                pfClientContextAttr, 
                                null);


rc = Advapi32.INSTANCE.ImpersonateLoggedOnUser(/* provide the security context token */)

Сервер - CreateProcessAsUser:

// get impersonation token of user
WinNT.HANDLEByReference threadToken = new WinNT.HANDLEByReference();
WinNT.HANDLE threadHandle = Kernel32.INSTANCE.GetCurrentThread();

boolean threadTokenResult = Advapi32.INSTANCE.OpenThreadToken(
        threadHandle,
        WinNT.TOKEN_QUERY | WinNT.TOKEN_DUPLICATE | WinNT.TOKEN_ASSIGN_PRIMARY,
        false, /* TRUE if the access check is to be made against the process-level security context. FALSE if the access check is to be made against the current security context of the thread calling the OpenThreadToken function. */
        threadToken);

// create primary token by duplicating impersonation token
WinNT.HANDLEByReference primaryToken = new WinNT.HANDLEByReference();

boolean primaryTokenResult = Advapi32.INSTANCE.DuplicateTokenEx(
        threadToken.getValue(),                                     /* hExistingToken */
        WinNT.TOKEN_DUPLICATE | WinNT.TOKEN_QUERY | WinNT.TOKEN_ASSIGN_PRIMARY, /* dwDesiredAccess */
        null,                                           /* lpTokenAttributes */
        WinNT.SECURITY_IMPERSONATION_LEVEL.SecurityDelegation,      /* ImpersonationLevel */
        WinNT.TOKEN_TYPE.TokenPrimary,                              /* TokenType */
        primaryToken);                                              /* phNewToken */

String environment = createEnvironment(primaryToken);

WinBase.STARTUPINFO startupInfo = new WinBase.STARTUPINFO();
WinBase.PROCESS_INFORMATION processInfo = new WinBase.PROCESS_INFORMATION();

boolean createProcessResult = Advapi32.INSTANCE.CreateProcessAsUser(
        primaryToken.getValue(),    /* hToken */
        null,           /* lpApplicationName */
        command,                    /* lpCommandLine */
        null,       /* lpProcessAttributes */
        null,           /* lpThreadAttributes */
        false,          /* bInheritHandles */
        WinNT.CREATE_NEW_CONSOLE | WinNT.CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */
        environment,                /* lpEnvironment */
        processDirectory,           /* lpCurrentDirectory */
        startupInfo,                /* lpStartupInfo */
        processInfo);               /* lpProcessInformation */
...