Я пытаюсь добиться двух вещей с помощью DCOM (вне процесса)
Мои мысли:
AFAIK в информационной структуре auth содержит информацию об аутентификации по умолчанию (например, имя пользователя и пароль для RPC_C_AUTHN_WINNT) для всех новых COM-вызовов. Поэтому вместо маркера процесса информация в структуре auth должна использоваться COM. Однако все COM-вызовы/соединения всегда используют идентификатор процесса вместо применяемого по умолчанию.
Обычно можно использовать CoSetProxyBlanket для изменения информации auth для прокси. Это работает для меня. Мой вопрос здесь в том, должен ли он работать или не должен работать, если я сам выдачу токен и вызову функцию COM. Я читал в различных статьях MSDN, что применение EOAC_DYNAMIC_CLOAKING к CoInitializeSecurity должно заставить его работать. Однако мои ручные "олицетворенные COM-вызовы" всегда показывают идентификатор процесса на стороне сервера.
Клиент выглядит так (Delphi)
var
authList : SOLE_AUTHENTICATION_LIST;
authidentity : SEC_WINNT_AUTH_IDENTITY_W;
authInfo : array[0..1] of SOLE_AUTHENTICATION_INFO;
pcAuthSvc : DWORD;
asAuthSvc : array[0..0] of SOLE_AUTHENTICATION_SERVICE;
Token : TJwSecurityToken;
begin
ZeroMemory( @authidentity, sizeof(authidentity) );
authidentity.User := 'Testbenutzer';
authidentity.UserLength := Length('Testbenutzer');
authidentity.Domain := '';
authidentity.DomainLength := 0;
authidentity.Password := 'test';
authidentity.PasswordLength := 4;
authidentity.Flags := SEC_WINNT_AUTH_IDENTITY_UNICODE;
ZeroMemory( @authInfo, sizeof( authInfo ) );
// NTLM Settings
authInfo[0].dwAuthnSvc := RPC_C_AUTHN_WINNT;
authInfo[0].dwAuthzSvc := RPC_C_AUTHZ_NONE;
authInfo[0].pAuthInfo := @authidentity;
authList.cAuthInfo := 1;
authList.aAuthInfo := @authInfo;
OleCheck(CoInitializeSecurity(
NULL, // Security descriptor
-1, // Count of entries in asAuthSvc
NULL, // asAuthSvc array
NULL, // Reserved for future use
RPC_C_AUTHN_LEVEL_CONNECT, // Authentication level
RPC_C_IMP_LEVEL_IMPERSONATE, // Impersonation level
@authList, // Authentication Information
DWORd(EOAC_DYNAMIC_CLOAKING), // Additional capabilities
NULL // Reserved
));
//create COM object
int := CoSecurityTestObj.Create;
int.TestCall;
Сервер также установил флаг EOAC_DYNAMIC_CLOAKING. Он использует CoImpersonateClient для получения токена потока и имени пользователя. Он также использует CoQueryClientBlanket для получения authInfo (как SEC_WINNT_AUTH_IDENTITY_W структуры). Однако оба вызова всегда возвращают идентификатор процесса клиента.
Также выдавать себя за руки вручную не работает (2.):
Token := TJwSecurityToken.CreateLogonUser(authidentity.User, '', authidentity.Password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT);
Token.ImpersonateLoggedOnUser;
int := CoSecurityTestObj.Create;
int.TestCall;
Вопросы снова:
Я ошибаюсь, или почему структура данных аутентификации по умолчанию (WinNT с именем пользователя и паролем) не используется в качестве аутентификации по умолчанию в каждом COM-соединении/вызове?
Я ошибаюсь или почему не работает ручная олицетворение? Имейте в виду, что я тестировал номер 2. отдельно, поэтому номер 1. не может вмешиваться.
Это основная работа для библиотеки кода безопасности JEDI Windows, которую я распространяю для поддержки безопасности COM. Поэтому ваша помощь будет идти GPL/MPL.
Литература:
Cloaking:
CoInitializeSecurity и pAuthInfo
Получение защитного покрытия (на стороне сервера)
Пробовали ли вы вызов CoInitializeSecurity() с помощью RPC_C_AUTHN_LEVEL_CALL вместо RPC_C_AUTHN_LEVEL_CONNECT?
Обычно, когда я создаю клиенты DCOM, я создаю COSERVERINFO и передаю CoCreateInstanceEx() с учетными данными безопасности, не забывая вызывать CoSetProxyBlanket() на всех интерфейсах.