Изменить стиль страницы

[in] SOLE_AUTHENTICATION_SERVICE *rgsAuthSvc, // SSP array

// массив SSP

[in] void *pReserved1, // reserved MBZ

// зарезервировано, должен быть О

[in] DWORD dwAuthnLevel, // auto, AUTHN_LEVEL

// аутентификация AUTHN_LEVEL

[in] DWORD dwImpLevel, // auto. IMP_LEVEL

// аутентификация IMP_LEVEL

[in] void *pReserved2, // reserved MBZ

// зарезервировано, должен быть О

[in] DWORD dwCapabilities, // misc flags

// различные флаги

[in] void *pReserved3 // reserved MBZ

// зарезервировано, должен быть О

);

Некоторые из этих параметров применяются только в тех случаях, когда процесс выступает как экспортер/сервер. Другие – только если процесс действует как импортер/клиент. Остальные применяются в обоих случаях.

Первый параметр функции CoInitializeSecurity, pSecDesc, применим только в случае, когда процесс выступает как экспортер. Этот параметр используется для контроля того, каким принципалам – пользователям или процессам, имеющим учетную запись (principals) – разрешен доступ к объектам, экспортируемым из данного процесса. В деталях этот параметр будет обсужден позже в данной главе. Второй и третий параметры функции CoInitializeSecurity, соответственно cAuthSvc и rgsAuthSvc, используются при работе процесса в качестве экспортера для регистрации одного или нескольких модулей защиты с помощью библиотеки COM. Эти два параметра ссылаются на массив описаний модулей защиты:

typedef struct tagSOLE_AUTHENTICATION_SERVICE {

DWORD dwAuthnSvc; // which authentication package?

// какой модуль защиты?

DWORD dwAuthzSvc; // which authorization service?

// какая служба авторизации?

OLECHAR *pPrincipalName; // server principal name?

// имя серверного принципала?

HRESULT hr; // result of registration

// результат регистрации

} SOLE_AUTHENTICATION_SERVICE;

В Windows NT 4.0 единственной установленной службой аутентификации является RPC_C_AUTHN_WINNT (NTLM). При использовании аутентификации NTLM служба авторизации (authorization service – сервис контроля доступа, определяющий права клиента) должна быть указана как RPC_C_AUTHZ_NONE, а имя серверного принципала не используется и должно быть нулевым[1]. Для тех процессов, которые просто хотят использовать пакет (пакеты) защиты по умолчанию на отдельной машине, следует использовать значения: cAuthSvc, равное -1, и rgsAuthSvc, равное нулю.

Пятый параметр функции CoInitializeSecurity, dwAuthnLevel, применим как к экспортируемым, так и к импортируемым объектным ссылкам. Величина, заданная для этого параметра, устанавливает предельно низкий уровень аутентификации для объектных ссылок, экспортируемых из этого процесса. Это означает, что поступающие ORPC-запросы должны иметь по крайней мере такой уровень аутентификации; в противном случае этот вызов будет отклонен. Эта величина определяет также минимальный уровень аутентификации, используемый новыми интерфейсными заместителями, которые возвращаются API-функциями или методами COM. Создавая новый интерфейсный заместитель во время демаршалинга, COM рассматривает число, обозначающее нижний уровень аутентификации, заданный экспортером, как часть разрешения OXID. Затем COM устанавливает уровень аутентификации нового заместителя равным или нижнему уровню экспортера, или нижнему уровню текущего процесса – в зависимости от того, какой из них выше. Если процесс, импортирующий объектную ссылку, имеет уровень аутентификации ниже, чем экспортирующий процесс, то для установки уровня аутентификации используется нижний уровень экспортера. Такой способ гарантирует, что любые ORPC-запросы, посылаемые интерфейсным заместителем, пройдут через нижний уровень экспортера. Далее в этой главе будет рассмотрено, как с целью более детального контроля можно явным образом изменить уровень аутентификации для отдельного интерфейсного заместителя[2].

Шестой параметр функции CoInitializeSecurity, dwImpLevel применяется для импортируемых объектных ссылок. Величина, определенная для этого параметра, устанавливает уровень заимствования прав (impersonation level), используемый для всех объектных ссылок, которые возвращаются функцией CoUnmarshalInterface. Уровень заимствования прав позволяет одному процессу заимствовать атрибуты защиты у другого процесса и отражает степень доверия, которое клиент испытывает к серверу. Этот параметр должен принимать одно из следующих четырех значений, характеризующих уровень заимствования прав:

enum {

// hide credentials of caller from object

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

RPC_C_IMP_LEVEL_ANONYMOUS = 1,

// allow object to query credentials of caller

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

RPC_C_IMP_LEVEL_IDENTIFY = 2,

// allow use of caller's credentials up to one-hop away

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

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

RPC_C_IMP_LEVEL_IMPERSONATE = 3,

// allow use of caller's credentials across multiple hops

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

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

RPC_C_IMP_LEVEL_DELEGATE = 4

};

Уровень RPC_C_IMP_LEVEL_ANONYMOUS не позволяет реализации объекта обнаружить идентификатор безопасности вызывающей программы[3]. Уровень доверия RPC_C_IMP_LEVEL_IDENTIFY указывает, что реализация объекта может программно определить идентификатор защиты вызывающей программы. Уровень доверия RPC_C_IMP_LEVEL_IMPERSONATE указывает, что сервер может не только определить идентификатор защиты вызывающей программы, но также выполнить операции на уровне операционной системы с использованием полномочий вызывающей программы. На этом уровне доверия объекты могут использовать полномочия вызывающей программы, но имеют доступ только к локальным ресурсам[4]. В противоположность этому, уровень доверия RPC_C_IMP_LEVEL_DELEGATE разрешает серверу доступ как к локальным, так и к удаленным ресурсам с использованием полномочий вызывающей программы. Этот уровень доверия не поддерживается протоколом аутентификации NTLM, но поддерживается протоколом аутентификации Kerberos.

Восьмой параметр функции CoInitializeSecurity, dwCapabilities применим к импортируемым и к экспортируемым объектным ссылкам. Этот параметр является битовой маской, которая может состоять из нуля или более следующих битов:

typedef enum tagEOLE_AUTHENTICATION_CAPABILITIES {

EOAC_NONE = 0х0,

EOAC_MUTUAL_AUTH = 0х1,

// These are only valid for CoInitializeSecurity

// только эти допустимы для CoInitializeSecurity

EOAC_SECURE_REFS = 0х2,

EOAC_ACCESS_CONTROL = 0х4,

EOAC_APPID = 0х8

} EOLE_AUTHENTICATION_CAPABILITIES;

Взаимная аутентификация (EOAC_MUTUAL_AUTH) под NTLM не поддерживается. Она используется для проверки того, что сервер исполняется как ожидаемый принципал. Ссылки защиты (EOAC_MUTUAL_AUTH) указывают, что распределенные вызовы подсчета ссылок COM будут аутентифицироваться для гарантии того, что никакие вражеские агенты не могут испортить счетчик ссылок, используемый OR и администраторами заглушек для управления жизненным циклом. EOAC_ACCESS_CONTROL и EOAC_APPID используются для управления семантикой первого параметра функции CoInitializeSecurity и будут обсуждаться далее в этой главе.

Как было установлено ранее в этом разделе, CoInitializeSecurity вызывается один раз на процесс, явно или неявно. Приложения, желающие вызвать CoInitializeSecurity явно, должны делать это после первого вызова CoInitializeEx, но перед «первым интересным вызовом COM» (first interesting COM call). Фраза «первый интересный вызов COM» относится к любой API-функции, которой может понадобиться OXID. Сюда относятся CoMarshalInterface и CoUnmarshalInterface, а также любые API-вызовы, неявно вызывающие эти функции. Поскольку вызовы CoRegisterClassObject связывают объекты класса с апартаментами, то CoInitializeSecurity должна быть вызвана до регистрации объектов класса. API-функции активации (например, CoCreateInstanceEx) являются любопытным исключением. Активация API-функций для определенных внутренних классов, которые являются частью COM API (например, глобальная интерфейсная таблица, COM-объект контроля доступа по умолчанию) может быть произведена до вызова CoInitializeSecurity. Тем не менее, функция CoInitializeSecurity должна быть вызвана раньше, чем любые активационные вызовы, которые фактически консультируются с реестром и загружают другие DLL или контактируют с другими серверами. Если приложение не вызывает функцию CoInitializeSecurity явно, то COM вызовет ее неявно в качестве первого интересного вызова COM.

вернуться

1 Эти два параметра могут использоваться в других модулях аутентификации.

вернуться

2 Отдельный модуль защиты может увеличить уровень, заданный для клиента/сервера, в зависимости от используемого транспортного протокола. В частности, NTML будет использовать уровень RPC_C_AUTHN_LEVEL_PRIVACY для всех вызовов с той же машины. Кроме того, NTLM будет повышать уровни RPC_AUTHN_LEVEL_CONNECT и RPC_C_AUTHN_LEVEL_CALL до RPC_AUTHN_LEVEL_PKT для транспортировки дэйтаграмм (datagram transports) (например, UDP). Для транспортировок, ориентированных на связь (connection-oriented transport) (например, TCP), NTLM будет повышать уровень с RPC_С_AUTHN_LEVEL_CALL дo RPC_C_AUTHN_LEVEL_PKT.

вернуться

3 Во время написания данного текста оба SSP – NTLM и Kerberos – молча принимали это значение, но в действительности повышали его до RPC_C_IMP_LEVEL_IDENTIFY, если имело место соединение с удаленной машиной.

вернуться

4 Формально уровень RPC_C_IMP_LEVEL_IMPERSONATE разрешает сохранять полномочия вызывающей программы не более чем в течение одной сетевой передачи. Это эффективно ограничивает доступ для удаленных объектов ресурсами только локальной машины объекта.