01.10.2003 14:11:31КриптоПро возвращает невалидный SECURITY_DESCRIPTOR Ответов: 3
Maxim Egorushkin
Я пытаюсь получить DACL машинного кейсета так:

::CryptGetProvParam(x1, PP_KEYSET_SEC_DESCR, x2, x3, DACL_SECURITY_INFORMATION); // вызов успешен

Полученный таким образом DACL от КриптоПро (2.0 Build 2049) не проходит проверку функцией ::IsValidSecurityDescriptor(); DACL от MS провайдера такую проверку проходит успешно. OC - WinXP SP1. В чем проблема?

Вот код (успешно работает с MS провайдерами):

void AddKeysetUser(const string_t& user_name)
{
// blob === vector<BYTE>
// blob_ptr === auto_ptr<vector<BYTE> >
// blob_cast<T>(b) === reinterpret_cast<T>(&b[0])
// provider_ - хэндл провайдера

// get the keyset&rsquo;s security descriptor in the self-related form

blob_ptr sd_blob(
get_blob_param(provider_, PP_KEYSET_SEC_DESCR, DACL_SECURITY_INFORMATION));
PSECURITY_DESCRIPTOR sd(blob_cast<PSECURITY_DESCRIPTOR>(sd_blob));
if(!::IsValidSecurityDescriptor(sd))
throw crypto_api_runtime_error("the keyset security descriptor is invalid");

// get the descriptor&rsquo;s DACL

BOOL acl_present, acl_defaulted;
PACL current_acl;
if(!::GetSecurityDescriptorDacl(sd, &acl_present, &current_acl, &acl_defaulted)
|| !acl_present)
throw crypto_api_runtime_error("::GetSecurityDescriptorDacl() failed");

EXPLICIT_ACCESS ea;
::BuildExplicitAccessWithName(
&ea,
const_cast<string_t::pointer>(user_name.c_str()),
GENERIC_ALL,
GRANT_ACCESS,
SUB_CONTAINERS_AND_OBJECTS_INHERIT
);

// add the new user to a new DACL merged with current DACL

util::hlocal new_acl;
if(ERROR_SUCCESS != ::SetEntriesInAcl(
1, &ea, current_acl, reinterpret_cast<PACL*>(&new_acl.get_ref())))
throw crypto_api_runtime_error("::SetEntriesInAcl() failed");

// convert the security descriptor to the absolute form

DWORD asd_size(0), s1(0), s2(0), s3(0), s4(0);
::MakeAbsoluteSD(sd, 0, &asd_size, 0, &s1, 0, &s2, 0, &s3, 0, &s4);
blob asd_blob(asd_size), b1(s1), b2(s2), b3(s3), b4(s4);
PSECURITY_DESCRIPTOR asd(blob_cast<PSECURITY_DESCRIPTOR>(asd_blob));
if(!::MakeAbsoluteSD(
sd,
asd, &asd_size,
blob_cast<PACL>(b1), &s1,
blob_cast<PACL>(b2), &s2,
blob_cast<PSID>(b3), &s3,
blob_cast<PSID>(b4), &s4))
throw crypto_api_runtime_error("::MakeAbsoluteSD() failed");

// renew the descriptor&rsquo;s DACL

if(!::SetSecurityDescriptorDacl(asd, true, reinterpret_cast<PACL>(new_acl.get()), false))
throw crypto_api_runtime_error("::SetSecurityDescriptorDacl() failed");

// set the renewed descriptor to the keyset

set_blob_param(provider_, PP_KEYSET_SEC_DESCR, asd_blob, DACL_SECURITY_INFORMATION);
}
 
Ответы:
01.10.2003 15:40:51Maxim Egorushkin
Правильно ли я понимаю, что КриптоПро не поддерживает получение DACL кейсета, так как функция CryptGetProvParam(..., PP_KEYSET_SEC_DESCR, ..., DACL_SECURITY_INFORMATION) всегда возвращает нулевую длину записаных в буфер данных?
02.10.2003 13:00:16Василий
Да, параметр не поддерживается.
Это связано с тем, что в нашем провайдере, в отличие от Microsoft-овского, контейнеры могут располагаться не только в реестре, но и на съёмных носителях.
02.10.2003 13:14:22Maxim Egorushkin
Можно справедливо заметить, что равно как и таблетки, ни память, ни жесткий диск не умеют работать с SECURITY_DESCRIPTOR. Это ПО реализует эту возможность.

Очень жаль, что ваше ПО не реализует этой возможности, и вводит в заблуждение небрежной документацией.