-->

Сущность технологии СОМ. Библиотека программиста

На нашем литературном портале можно бесплатно читать книгу Сущность технологии СОМ. Библиотека программиста, Бокс Дональд-- . Жанр: Программирование. Онлайн библиотека дает возможность прочитать весь текст и даже без регистрации и СМС подтверждения на нашем литературном портале bazaknig.info.
Сущность технологии СОМ. Библиотека программиста
Название: Сущность технологии СОМ. Библиотека программиста
Дата добавления: 16 январь 2020
Количество просмотров: 276
Читать онлайн

Сущность технологии СОМ. Библиотека программиста читать книгу онлайн

Сущность технологии СОМ. Библиотека программиста - читать бесплатно онлайн , автор Бокс Дональд

В этой книге СОМ исследуется с точки зрения разработчика C++. Написанная ведущим специалистом по модели компонентных объектов СОМ, она раскрывает сущность СОМ, помогая разработчикам правильно понять не только методы модели программирования СОМ, но и ее основу. Понимание мотивов создания СОМ и ее аспектов, касающихся распределенных систем, чрезвычайно важно для тех разработчиков, которые желают пойти дальше простейших приложений СОМ и стать по-настоящему эффективными СОМ-программистами. Показывая, почему СОМ для распределенных систем (Distributed СОМ) работает именно так, а не иначе, Дон Бокс дает вам возможность применять эту модель творчески и эффективно для ежедневных задач программирования.

Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала

1 ... 88 89 90 91 92 93 94 95 96 ... 118 ВПЕРЕД
Перейти на страницу:

Напоминаем, что контекстный объект вызова сопоставляется с потоком, когда ORPC-запрос направляется на интерфейсную заглушку. Разработчики объекта получают доступ к контексту вызова через API-функцию CoGetCallContext. Контекстный объект вызова реализует интерфейс IServerSecurity:

[local, object, uuid(0000013E-0000-0000-C000-000000000046)]

interface IServerSecurity : IUnknown {

// get caller's security settings

// получаем установки защиты вызывающей программы HRESULT

QueryBlanket(

[out] DWORD *pAuthnSvc, // authentication pkg

// модуль аутентификации

[out] DWORD *pAuthzSvc, // authorization pkg

// модуль авторизации

[out] OLECHAR **pServerName, // server principal

// серверный принципал

[out] DWORD *pAuthnLevel, // authentication level

// уровень аутентификации

[out] DWORD *pImpLevel, // impersonation level

// уровень заимствования прав

[out] void **pPrivs, // client principal

// клиентский принципал

[out] DWORD *pCaps // EOAC flags

// флаги EOAC

);

// start running with credentials of caller

// начинаем выполнение с полномочиями вызывающей программы

HRESULT ImpersonateClient(void);

// stop running with credentials of caller

// заканчиваем выполнение с полномочиями вызывающей программы

HRESULT RevertToSelf(void);

// test for impersonation

// проверка заимствования прав

BOOL IsImpersonating(void);

}

В одном из предыдущих разделов этой главы уже рассматривался метод QueryBlanket. Остальные три метода используются для управления маркерами потока во время выполнения метода. Метод ImpersonateClient создает маркер доступа, основанный на полномочиях клиента, и присваивает этот маркер текущему потоку. Как только возвращается IServerSecurity::ImpersonateClient, все попытки доступа к ресурсам операционной системы будут разрешаться или запрещаться в соответствии с полномочиями клиента, а не объекта. Метод RevertToSelf заставляет текущий процесс вернуться к использованию маркера доступа, принадлежащего процессу. Если текущий вызов метода заканчивает работу во время режима заимствования прав, то COM неявно вернет поток к использованию маркера процесса. И наконец, метод IServerSecurity::IsImpersonating показывает, что использует текущий поток: полномочия клиента или маркер процесса объекта. Подобно методу QueryBlanket, два метода IServerSecurity также имеют удобные оболочки, которые вызывают CoGetCallContext изнутри и затем вызывают соответствующий метод:

HRESULT CoImpersonateClient(void);

HRESULT CoRevertToSelf(void);

В общем случае, если будет использоваться более одного метода IServerSecurity, то эффективнее было бы вызвать CoGetCallContext один раз, а для вызова каждого метода использовать результирующий интерфейс IServerSecurity.

Следующий код демонстрирует использование контекстного объекта вызова для выполнения части кода метода с полномочиями клиента:

STDMETHODIMP MyClass::ReadWrite(DWORD dwNew, DWORD *pdw0ld)

{

// execute using server's token to let anyone read the value

// выполняем с использованием маркера сервера, чтобы

// все могли прочитать данное значение

ULONG cb;

HANDLE hfile = CreateFile(«C:\file1.bin», GENERIC_READ,

0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

if (hfile == INVALID_HANDLE_VALUE)

return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());

ReadFile(hfile, pdwOld, sizeof(DWORD), &cb, 0);

CloseHandle(hfile);

// get call context object

// получаем контекстный объект вызова

IServerSecurlty *pss = 0;

HRESULT hr = CoGetCallContext(IID_IServerSecurity, (void**)&pss);

if (FAILED(hr)) return hr;

// set thread token to use caller's credentials

// устанавливаем маркер потока для использования

// полномочий вызывающей программы

hr = pss->ImpersonateClient();

assert(SUCCEEDED(hr));

// execute using client's token to let only users that can

// write to the file change the value

// выполняем с использованием маркера клиента, чтобы

// изменять это значение могли только те пользователи,

// которые имеют право записывать в файл

hfile = CreateFile(«C:\file2.bin»,

GENERIC_READ | GENERIC_WRITE, 0, 0,

OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

if (hfile == INVALID_HANDLE_VALUE)

hr = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());

else {

WriteFile(hfile, &dwNew, sizeof(DWORD), &cb, 0);

CloseHandle(hfile);

}

// restore thread to use process-level token

// восстанавливаем режим использования потоком маркера процесса

pss->RevertToSelf();

// release call context

// освобождаем контекст вызова

pss->Release();

return hr;

}

Отметим, что первый вызов CreateFile выполняется с использованием полномочий процесса объекта, в то время как второй вызов – с полномочиями клиента. Если клиент имеет права доступа для чтения/записи в соответствующий файл, то второй вызов метода CreateFile может быть успешным, даже если обычно процесс объекта не имеет доступа к этому файлу.

Важно, что хотя методы IServerSecurity::ImpersonateClient всегда достигают цели, исключая катастрофический сбой, клиент объекта контролирует уровень заимствования прав, допускаемый результирующим маркером. Каждый интерфейсный заместитель имеет свой уровень заимствования прав, который должен быть равным одной из четырех констант (RPC_C_IMP_LEVEL_ANONYMOUS, RPC_C_IMP_LEVEL_IDENTIFY, RPC_C_IMP_LEVEL_IMPERSONATE или RPC_C_IMP_LEVEL_DELEGATE). Во время демаршалинга COM устанавливает этот уровень равным величине, определенной в клиентском вызове CoInitializeSecurity; однако данная установка может быть изменена вручную с помощью IClientSecurity::SetBlanket. Когда объект вызывает IServerSecurity::ImpersonateClient, новый маркер будет ограничен уровнем, заданном в интерфейсном заместителе, который использовался в данном вызове. Это означает, что если клиент задал только уровень RPC_C_IMP_LEVEL_IDENTIFY, то объект не может получить доступ к ресурсам ядра во время выполнения с полномочиями клиента. Объект, однако, может применить API-функции Win32 OpenThreadToken или GetTokenInformation для чтения информации о клиенте (например, ID защиты, групповое членство) из маркера режима анонимного воплощения (impersonation token). Важно отметить, что пока клиент не задал уровень RPC_C_IMP_LEVEL_DELEGATE, объект не может получить доступ ни к одному из удаленных ресурсов защиты, используя полномочия клиента. В их число входят открытие файлов в удаленной файловой системе, а также выполнение аутентифицированных COM-вызовов к удаленным объектам. К сожалению, протокол аутентификации NTLM не поддерживает уровень RPC_C_IMP_LEVEL_DELEGATE, так что под Windows NT 4.0 делегирование невозможно.

Во время предыдущего обсуждения акцент делался на том, что в нормальном режиме методы объекта выполняются с использованием маркера доступа процесса объекта. Однако не обсуждался вопрос о том, как проконтролировать, какой принципал защиты должен использоваться для создания начального маркера серверного процесса. Когда SCM запускает серверный процесс, то он присваивает новому серверному процессу маркер, основанный на конфигурации именованной величины RunAs из AppID. Если же в AppID нет величины RunAs, то считается, что сервер неправильно сконфигурирован для работы в режиме распределенного доступа. Для того чтобы этот тип серверного процесса не внедрял указанные «дыры» в защите в систему, SCM запускает такие процессы с использованием того принципала защиты, который произвел запрос на активацию. Такой тип активации часто называют активацией «как активизатор» («As Activator»), так как серверный процесс выполняет тот же принципал защиты, что и запускающий пользователь. Активация типа «как активизатор» предназначена для поддержки удаленной активации старых серверов и содержит несколько ловушек. Во-первых, чтобы придерживаться семантики типа «как активизатор», COM запустит отдельный серверный процесс для каждой активационной учетной записи пользователя, независимо от того, используется ли REGCLS_MULTIPLEUSE в CoRegisterClassObject. Это вступает в серьезный конфликт с принципом расширяемости и вдобавок делает невозможным сохранение всех экземпляров класса в одном и том же процессе. Во-вторых, каждый серверный процесс запускается с маркером, ограниченным уровнем RPC_C_IMP_LEVEL_IMPERSONATE, из чего следует, что серверные процессы не имеют доступа ни к каким удаленным ресурсам или объектам [1].

1 ... 88 89 90 91 92 93 94 95 96 ... 118 ВПЕРЕД
Перейти на страницу:
Комментариев (0)
название