Навигация
Главная
Поиск
Форум
FAQ's
Ссылки
Карта сайта
Чат программистов

Статьи
-Delphi
-C/C++
-Turbo Pascal
-Assembler
-Java/JS
-PHP
-Perl
-DHTML
-Prolog
-GPSS
-Сайтостроительство
-CMS: PHP Fusion
-Инвестирование

Файлы
-Для программистов
-Компонеты для Delphi
-Исходники на Delphi
-Исходники на C/C++
-Книги по Delphi
-Книги по С/С++
-Книги по JAVA/JS
-Книги по Basic/VB/.NET
-Книги по PHP/MySQL
-Книги по Assembler
-PHP Fusion MOD'ы
-by Kest
Professional Download System
Реклама
Услуги

Автоматическое добавление статей на сайты на Wordpress, Joomla, DLE
Заказать продвижение сайта
Программа для рисования блок-схем
Инженерный калькулятор онлайн
Таблица сложения онлайн
Популярные статьи
OpenGL и Delphi... 65535
Форум на вашем ... 65535
HACK F.A.Q 65535
Бип из системно... 65535
Гостевая книга ... 65535
Invision Power ... 65535
Пример работы с... 65535
Содержание сайт... 65535
ТЕХНОЛОГИИ ДОСТ... 65535
Организация зап... 65535
Вызов хранимых ... 65535
Создание отчето... 65535
Программируемая... 65535
Эмулятор микроп... 65535
Подключение Mic... 65535
Создание потоко... 65535
Приложение «Про... 65535
Оператор выбора... 65535
Модуль Forms 65535
21 ошибка прогр... 63851
Реклама
Сейчас на сайте
Гостей: 4
На сайте нет зарегистрированных пользователей

Пользователей: 13,135
новичок: Kalqkwm
Новости
Реклама
Выполняем курсовые и лабораторные по разным языкам программирования
Подробнее - курсовые и лабораторные на заказ
Delphi, Turbo Pascal, Assembler, C, C++, C#, Visual Basic, Java, GPSS, Prolog, 3D MAX, Компас 3D
Заказать программу для Windows Mobile, Symbian

Компьютерный магазин на Turbo Pascal (База данных) + Пояснительная записка
Моделирование работы аэропорта на GPSS + Пояснительная записка
База данных междугородних телефонных разговоров на Delphi

Реклама



Подписывайся на YouTube канал о программировании, что бы не пропустить новые видео!

ПОДПИСЫВАЙСЯ на канал о программировании
Контроль доступа



Как уже упоминалось ранее в этой главе, каждый процесс COM может защитить сам себя от несанкционированного доступа. COM рассматривает контроль доступа на двух уровнях: права запуска (launch permissions) и права доступа (access permissions). Права запуска используются, чтобы определить, какие пользователи могут запускать серверные процессы при осуществлении активационных вызовов к SCM. Права доступа определяют, какие пользователи могут обращаться к объектам процесса после того, как сервер уже запущен. Оба типа контроля доступа можно сконфигурировать при помощи DCOMCNFG.EXE, но только права доступа могут быть заданы программно на этапе выполнения (поскольку после того, как сервер запущен, уже слишком поздно отказывать пользователю в правах запуска). Вместо этого право запуска предоставляется диспетчеру управления сервнсами SCM во время активации.
Когда SCM решает, что должен быть запущен новый серверный процесс, он пытается получить дескриптор защиты NT SECURITY_DESCRIPTOR, описывающий, каким пользователям разрешено запускать серверный процесс. В первую очередь SCM проверяет AppID класса для явной установки прав запуска. Эта установка приходит в форме сериализованного дескриптора защиты NT, который хранится в именованной величине LaunchPermission AppID:
[HKCR\AppID\{27EE6A4D-DF65-1d0-8C5F-0080C73925BA}]
LaunchPermission=
Если эта именованная величина отсутствует, SCM пытается прочитать общие для всей машины права запуска из такой именованной величины:
[HKEY_LOCAL_MACHINE\Software\Microsoft\OLE]
DefaultLaunchPermission=
Обе эти установки могут быть модифицированы с помощью DCOMCNFG.EXE. Если не найден ни один из этих ключей реестра, то COM запретит запуск кому бы то ни было. Если же SECURITY_DESCRIPTOR найден, SCM проверяет идентификатор защиты активизирующей вызывающей программы (формально называемой активизатором – actiuator) по списку разграничительного контроля доступа DACL (Discretionary Access Control List), имеющемуся в дескрипторе, чтобы определить, имеет ли активизатор полномочия на запуск сервера. Если активизатор не имеет необходимых полномочий, то следует отказ на активационный вызов с HRESULT E_ACCESSDENIED, и никаких процессов не запускается. В случае успешной проверки SCM запускает серверный процесс и продолжает выполнение активационного запроса.
Права запуска определяют только, какие пользователи могут или не могут начинать серверные процессы во время активации. Эта проверка всегда выполняется SCM на основе информации, записанной в реестре. Права доступа определяют, какие пользователи могут действительно связываться с объектами серверного процесса. Эта проверка осуществляется библиотекой COM при каждом запросе на установку соединения, приходящем от клиента. Для контроля установок прав доступа к процессу разработчики могут использовать API-функцию CoIntializeSecurity.
Напомним, что процессы, не вызывающие явно функцию CoInitializeSecurity, автоматически используют список контроля доступа, записанный под ключом реестра AppID приложения:
[HKCR\AppIO\{27EE6A4D-DF65-11d0-8C5F-0080C73925BA}]
AccessPermission=
Ранее объяснялось, что если этот элемент реестра отсутствует, то COM ищет установку по умолчанию для всей машины, а если она также отсутствует, то создается новый список контроля доступа, который включает только принципала серверных процессов и встроенной учетной записи SYSTEM.
Приложения, явно вызывающие CoInitializeSecurity, могут вручную контролировать, каким вызывающим программам разрешен доступ к объектам, экспортируемым данным процессом. По умолчанию первый параметр CoIntializeSecurity принимает указатель на SECURITY_DESCRIPTOR NT. Если вызывающая программа передает в качестве этого параметра нулевой указатель, то COM не будет осуществлять никакого контроля входящих вызовов. Это разрешает вызовы от любого аутентифицированного принципала защиты. Если и клиент, и сервер укажут RPC_C_AUTHN_LEVEL_NONE, то COM разрешит вызовы от кого угодно, независимо от его аутентификации. Если же в вызывающей программе имеется легальный указатель на дескриптор защиты, то COM с помощью DACL этого дескриптора защиты определит, каким вызывающим программам разрешен доступ к объектам процесса. Заголовки SDK определяют так называемый флаг прав (COM_RIGHTS_EXECUTE), который используется при создании DACL для явного разрешения или запрета пользователям на связь с объектами процесса.
Хотя и допускается использовать API-функции Win32 для создания SECURITY_DESCRIPTOR с целью передачи его в CoInitializeSecurity, этот способ контроля доступа к объектам процесса не является предпочтительным, в основном по причине темной природы API-функций защиты Win32. Для упрощения программирования в COM контроля доступа в реализации COM для Windows NT 4.0 Service Pack 2 разработчикам разрешено указывать тот объект COM, который будет использоваться для выполнения проверки доступа при установке новых соединений. Этот объект регистрируется библиотекой COM во время выполнения CoInitializeSecurity и должен реализовать интерфейс IAccessControl:
[object, uuid(EEDD23EO-8410-11CE-A1C3-08002B2B8D8F)]
interface IAccessControl : IUnknown {
// add access allowed rights for a list of users
// добавляем разрешенные права доступа для списка пользователей
HRESULT GrantAccessRights([in] PACTRL_ACCESSW pAccessList);
// explicitly set the access rights for a list of users
// явно устанавливаем права доступа для списка пользователей
HRESULT SetAccessRights([in] PACTRL_ACCESSW pAccessList
// users+rights
// пользователи + Права
);
// set the owner/group IDs of the descriptor
// устанавливаем идентификаторы владельца/группы для дескриптора
HRESULT Set0wner(
[in] PTRUSTEEW pOwner, // owner ID
// ID владельца
[in] PTRUSTEEW pGroup // group ID
// ID группы
);
// remove access rights for a list of users
// удаляем права доступа для списка пользователей
HRESULT RevokeAccessRights(
[in] LPWSTR lpProperty, // not used
// не используется
[in] ULONG cTrustees, // how many users
// сколько имеется пользователей
[in, size_is(cTrustees)] TRUSTEEW prgTrustees[] // users
// пользователи
);
// get list of users and their rights
// получаем список пользователей и их прав
HRESULT GetAllAccessRights(
[in] LPWSTR lpProperty, // not used
// не используется
[out] PACTRL_ACCESSW *ppAccessList, // users+rights
// пользователи + права
[out] PTRUSTEEW *ppOwner, // owner ID
// ID владельца
[out] PTRUSTEEW *ppGroup // group ID
// ID группы
);
// called by COM to allow/deny access to an object
// вызывается COM для разрешения/запрета доступа к объекту
HRESULT IsAccessAllowed(
[in] PTRUSTEEW pTrustee, // caller's ID
// ID вызывающей программы
[in] LPWSTR lpProperty, // not used
// не используется
[in] ACCESS_RIGHTS Rights, // COM_RIGHTS_EXECUTE
[out] BOOL *pbAllowed // yes/no!
// да/нет!
);
}



Этот интерфейс предназначен для того, чтобы разработчики могли создавать объекты контроля доступа на основе статических таблиц данных, преобразующих имена принципалов в права доступа. Интерфейс основывается на новом Windows NT 4.0 API защиты на базе опекуна (trustee), то есть пользователя, обладающего правами доступа к объекту. Основным типом данных, используемым этим API, является TRUSTEE:
typedef struct _TRUSTEE_W {
struct _TRUSTEE_W *pMultipleTrustee;
MULTIPLE_TRUSTEE_OPERATION MultipleTrusteeOperation;
TRUSTEE_FORM TrusteeForm;
TRUSTEE_TYPE TrusteeType;
switch_is(TrusteeForm)]
union {
[case(TRUSTEE_IS_NAME)]
LPWSTR ptstrName;
[case(TRUSTEE_IS_SID)]
SID *pSid;
};
} TRUSTEE_W, *PTRUSTEE_W, TRUSTEEW, *PTRUSTEEW;



Этот тип данных используется для описания принципала защиты. Первые два параметра, pMultipleTrustee и MultipleTrusteeOperation, позволяют вызывающей программе отличать настоящие регистрационные имена (logins – логины) от попыток заимствования прав. Пятый параметр, ptstrName/pSid, содержит либо идентификатор защиты NT (security identifier – SID), либо текстовое имя учетной записи, подлежащее идентификации. При этом третий параметр, TrusteeForm, указывает, какой именно член объединения (union member) используется. Четвертый параметр, TrusteeType, указывает, является ли данный принципал учетной записью пользователя или группы.
Для связывания опекуна с полномочиями, которые ему даны или в которых ему отказано, в Win32 API предусмотрен тип данных ACTRL_ACCESS_ENTRY:
typedef struct _ACTRL_ACCESS_ENTRYW {
TRUSTEE_W Trustee; // who?
// кто?
ULONG fAccessFlags; // allowed/denied?
// разрешено/запрещено?
ACCESSRIGHTS Access;// which rights?
// какие права?
ACCESSRIGHTS ProvSpecificAccess; // not used by COM
// в COM не используется
INHERIT_FLAGS Inheritance; // not used by COM
// в COM не используется
LPWSTR lpInheritProperty; // not used by COM
// в COM не используется
} ACTRL_ACCESS_ENTRYW, *PACTRL_ACCESS_ENTRYW;



а также тип данных для создания списков элементов для опекунов/полномочий:
typedef struct _ACTRL_ACCESS_ENTRY_LISTW {
ULONG cEntries;
[size_is(cEntries)] ACTRL_ACCESS_ENTRYW *pAccessList;
} ACTRL_ACCESS_ENTRY_LISTW, *PACTRL_ACCESS_ENTRY_LISTW;



И наконец, в Win32 предусмотрено еще два дополнительных типа данных, которые позволяют связывать элементы списков доступа с именованными признаками.
typedef struct _ACTRL_PROPERTY_ENTRYW {
LPWSTR lpProperty; // not used by COM
// не используется в COM
ACTRL_ACCESS_ENTRY_LISW *pAccessEntryList;
ULONG fListFlags; // not used by COM
// не используется в COM
} ACTRL_PROPERTY_ENTRYW, *PACTRL_PROPERTY_ENTRYW;
typedef struct _ACTRL_ALISTW {
ULONG cEntries;
[size_is(cEntries)]
ACTRL_PROPERTY_ENTRYW *pPropertyAccessList;
} ACTRL_ACCESSW, *PACTRL_ACCESSW;



Хотя в настоящее время COM не использует возможности контроля по каждому признаку, заключенному в этих двух типах данных, тип данных ACTRL_ACCESSW все же используется в интерфейсе IAccessControl для представления списков контроля доступа. Дело в том, что этот интерфейс широко используется также в службе директорий Windows NT 5.0, где требуется контроль доступа по каждому признаку.
В COM предусмотрена реализация интерфейса IAccessControl (CLSID_DCOMAccessControl), которую вызывающие программы могут заполнять явными именами учетных записей и правами доступа, используя типы данных контроля доступа NT 4.0 [1] . Следующий фрагмент кода использует эту реализацию для создания объекта контроля доступа, разрешающего доступ для встроенной учетной записи SYSTEM и для пользователей в группе Sales\Managers, но запрещающего доступ для отдельного пользователя Sales\Bob:
HRESULT CreateAccessControl(IAccessControl * &rpac)
{
rpac = 0;
// create default access control object
// создаем объект контроля доступа по умолчанию
HRESULT hr = CoCreateInstance(CLSID_DCOMAccessControl,
0, CLSCTX_ALL, IID_IaccessControl,
(void**)&rpac);
if (SUCCEEDED(hr)) {
// build list of users/rights using NT4 security data types
// создаем списов пользователей/прав, используя типы данных защиты из NT4
ACTRL_ACCESS_ENTRYW rgaae[] = {
{ { 0, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_NAME,
TRUSTEE_IS_USER, L"Sales\\Bob" },
ACTRL_ACCESS_DENIED, COM_RIGHTS_EXECUTE, 0,
NO_INHERITANCE, 0 },
{ { 0, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_NAME,
TRUSTEE_IS_GROUP, L"Sales\\Managers" },
ACTRL_ACCESS_ALLOWED, COM_RIGHTS_EXECUTE, 0,
NO_INHERITANCE, 0 },
{ { 0, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_NAME,
TRUSTEE_IS_USER, L"NT AUTHORITY\\SYSTEM" },
ACTRL_ACCESS_ALLOWED, COM_RIGHTS_EXECUTE, 0,
NO_INHERITANCE, 0 }
};
ACTRL_ACCESS_ENTRY_LISTW aael =
{ sizeof(rgaae)/sizeof(*rgaae), rgaae };
ACTRL_PROPERTY_ENTRYW ape = { 0, &aael, 0 };
ACTRL_ACCESSW aa = { 1, &ape };
// present list of users+rights to Access Control object
// представляем список пользователей + прав объекту контроля доступа
hr = rpac->SetAccessRights(&aa);
}
return hr;
}



Имея эту функцию, приложение может связать вновь созданный объект контроля доступа с его процессом следующим образом:
IAccessControl *pac = 0;
HRESULT hr = CreateAccessControl(pac);
assert(SUCCEEDED(hr));
hr = CoInitializeSecurity(pac, -1, 0, 0,
RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IDENTIFY, 0,
EOAC_ACCESS_CONTROL,
// use IAccessControl
// используем IAccessControl
0);
assert(SUCCEEDED(hr));
pac->Release();
// COM holds reference until last CoUninitialize
// COM сохраняет ссылку до последнего CoUninitialize



Флаг EOAC_ACCESS_CONTROL показывает, что первый параметр в функции СоInitializeSecurity является указателем на интерфейс IAccessControl, а не указателем на SECURITY_DESCRIPTOR NT. При каждом поступающем запросе на связь COM будет использовать метод этого объекта IsAccessAllowed для определения того, разрешен или запрещен доступ к объектам процесса. Отметим, что хотя этот код должен исполняться до первого интересного вызова COM, вызов CoCreateInstance для получения реализации по умолчанию IAccessControl является допустимым, так как COM не рассматривает его как интересный.
Если список авторизованных пользователей не может быть известен во время запуска процесса, то можно зарегистрировать специальную (custom) реализацию IAccessControl, которая выполняет определенного рода проверку доступа во время выполнения в своей реализации метода IsAccessAllowed. Поскольку сама COM использует только метод IsAccessAllowed, то такая специальная реализация могла бы безошибочно возвращать E_NOTIMPL для всех других методов IAccessControl. Ниже приведена простая реализация IAccessControl, позволяющая получить доступ к объектам процесса только пользователям с символом "x" в именах своих учетных записей:
class XOnly : public IAccessControl {
// Unknown methods
// методы IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) {
if (riid == IID_IAccessControl || riid == IID_IUnknown)
*ppv = static_cast(this);
else
return (*ppv = 0), E_NOINTERFACE;
((IUnknown*)*ppv)->AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG) AddRef(void) { return 2; }
STDMETHODIMP_(ULONG) Release(void) { return 1; }
// IAccessControl methods
// методы IAccessControl
STDMETHODIMP GrantAccessRights(ACTRL_ACCESSW *)
{ return E_NOTIMPL; }
STDMETHODIMP SetAccessRights(ACTRL_ACCESSW *)
{ return E_NOTIMPL; }
STDMETHODIMP SetOwner(PTRUSTEEW, PTRUSTEEW)
{ return E_NOTIMPL; }
STDMETHODIMP RevokeAccessRights(LPWSTR, ULONG, TRUSTEEW[])
{ return E_NOTIMPL; }
STDMETHODIMP GetAllAccessRights(LPWSTR, PACTRL_ACCESSW_ALLOCATE_ALL_NODES *,
PTRUSTEEW *, PTRUSTEEW *)
{ return E_NOTIMPL; }
// this is the only IAccessControl method called by COM
// это единственный метод IAccessControl, вызванный COM
STDMETHODIMP IsAccessAllowed(
PTRUSTEEW pTrustee,
LPWSTR lpProperty,
ACCESS_RIGHTS AccessRights,
BOOL *pbIsAllowed)
{
// verify that trustee contains a string
// удостоверяемся, что опекун содержит строку
if (pTrustee == 0 || pTrustee->TrusteeForm != TRUSTEE_IS_NAME)
return E_UNEXPECTED;
// look for X or x and grant/deny based on presence
// ищем "X" или "x" и в зависимости от его наличия
// предоставляем или запрещаем
*pbIsAllowed = wcsstr(pTrustee->ptstrName, L"x") != 0 ||
wcsstr(pTrustee->ptstrName, L"X") != 0;
return S_OK;
}
}



Если экземпляр вышеприведенного класса C++ зарегистрирован c CoInitializeSecurity:
XOnly xo;
// declare an instance of the C++ class
// объявляем экземпляр класса C++
hr = CoInitializeSecurity(static_cast(&xo),
–1, 0, 0, RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IDENTIFY, 0,
EOAC_ACCESS_CONTROL,
// use IAccessControl
// используем IAccessControl
0);
assert(SUCCEEDED(hr));



то от пользователей, не имеющих "x" в именах своих учетных записей, никакие поступающие вызовы не будут приняты. Поскольку имя опекуна содержит в качестве префикса имя домена, этот простой тест также предоставит доступ учетным записям пользователей, принадлежащих к доменам, содержащим "x" в своих именах. Хотя этот тест доступа вряд ли будет слишком полезен, он демонстрирует технологию использования специального объекта IAccessControl с CoInitializeSecurity.
Опубликовал Kest Июль 13 2009 17:33:23 · 0 Комментариев · 8217 Прочтений · Для печати

• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •


Комментарии
Нет комментариев.
Добавить комментарий
Имя:



smiley smiley smiley smiley smiley smiley smiley smiley smiley
Запретить смайлики в комментариях

Введите проверочный код:* =
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Поделиться ссылкой
Фолловь меня в Твиттере! • Смотрите канал о путешествияхКак приготовить мидии в тайланде?
Загрузки
Новые загрузки
iChat v.7.0 Final...
iComm v.6.1 - выв...
Visual Studio 200...
CodeGear RAD Stud...
Шаблон для новост...

Случайные загрузки
Delphi и технолог...
SearchAndReplace
Векторный редакто...
Visual Basic Script
Иллюстрированный ...
ADVstatusbar
PCX
Керниган Б.В., Ри...
Черный круг двига...
Borland Delphi 8 ...
SUIPack
Win-Prolog 3.618
GamesBase 3.0
netBIOS
Crystal Button
Converter AMR<->W...
С. Г. Горнаков - ...
Программирование ...
CarGame [Исходник...
Архив Апгрейтов с...

Топ загрузок
Приложение Клие... 100577
Delphi 7 Enterp... 93891
Converter AMR<-... 20129
GPSS World Stud... 16149
Borland C++Buil... 13495
Borland Delphi ... 9474
Turbo Pascal fo... 7152
Калькулятор [Ис... 5361
Visual Studio 2... 5060
FreeSMS v1.3.1 3580
Случайные статьи
Доступ к записям в...
POD-типы
Символы, используе...
Просмотр состояния...
Язык С: оператор s...
Лучшие игры в кази...
Процедура ShowMessage
Анализ продвижения...
Линейная задача
Определение функци...
Пример приложения ...
Дальнейшее развити...
Оперативно доступн...
Использование сред...
Перечисляемый тип
Обзор панели управ...
• определите, каки...
Слоты 777
Интерфейс аппаратн...
Настройка параметр...
Обзор истории язык...
Основные недостатк...
должна иметь разре...
Как сделать схему ...
Стандартные потоки
Статистика



Друзья сайта
Программы, игры


Полезно
В какую объединенную сеть входит классовая сеть? Суммирование маршрутов Занимают ли таблицы память маршрутизатора?