четверг, 30 декабря 2010 г.

AddMandatoryAce

а вот например на старости лет потребовалось мне зарегистрировать под vista rpc интерфейс на named pipes. И все оно замечательно работает, за исключением клиентов с low integrity level - при вызове методов моего интерфейса они обламывались с ошибкой 5 (ERROR_ACCESS_DENIED)
Гугл сказал что нужно в RpcServerUseProtseqEp отдавать правильно настроенный security descriptor, но как его правильно настраивать для указания integrity level не особо помог
Соотв-но ниже небольшой кусок кода, который таки работает
Обработка ошибок и освобождение всей выделенной памяти выкушены для сокращения размера кода. Никогда так не делайте !

// потому что  AddMandatoryAce появилась только с висты
typedef BOOL (WINAPI *TAddMandatoryAce)(
  PACL pAcl,
  DWORD dwAceRevision,
  DWORD AceFlags,
  DWORD MandatoryPolicy,
  PSID pLabelSid
);

// потырено из книжки Writing Secure Code for Windows Vista
SID LowIntegritySid = {
  SID_REVISION, 1,
  { SECURITY_MANDATORY_LABEL_AUTHORITY },
  SECURITY_MANDATORY_LOW_RID
};

// проверяем наличие функции AddMandatoryAce
TAddMandatoryAce add_mace = NULL;

HMODULE hmod = ::GetModuleHandle(L"advapi32.dll");
if ( hmod != NULL )
  add_mace = (TAddMandatoryAce)::GetProcAddress(hmod, "AddMandatoryAce");
// мастерим sacl
PACL  sACL = NULL;
if ( add_mace != NULL )
{

  // откуда берется размер ACLа неизвестно - опыты показали что 256 байт вполне достаточно
  sACL = (PACL)LocalAlloc(LPTR, 256);
  if ( sACL != NULL )
  {
    if (InitializeAcl(sACL, 256, ACL_REVISION))
    {
      if ( !add_mace(sACL, ACL_REVISION_DS, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &LowIntegritySid) )
      {
        LocalFree(sACL);
        sACL = NULL;
      }
    } else
    {
      LocalFree(sACL);
      sACL = NULL;
    }
  }
}
// мастерим security descriptor
PSECURITY_DESCRIPTOR m_sd = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (NULL == m_sd)
{
  res = ::GetLastError();
  return res;
}
if (!InitializeSecurityDescriptor(m_sd, SECURITY_DESCRIPTOR_REVISION))
{
  res = ::GetLastError();
  return res;
}
// тут можно с помощью SetSecurityDescriptorDacl добавить dacl по вкусу
...
// проверим есть ли у нас sacl
if ( sACL != NULL )
{

  // если есть - добавим его
  if (!SetSecurityDescriptorSacl(m_sd,TRUE,sACL,FALSE))
  {
    res = ::GetLastError();
    return res;
  }
}
// дальше получившийся m_sd можно использовать в RpcServerUseProtseqEp
// и только после этого можно освободить все выделенную память

Комментариев нет:

Отправить комментарий