Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.08.14;
Скачать: CL | DM;

Вниз

Некорректное поведение безопасности DCOM   Найти похожие ветки 

 
Krolik   (2004-10-30 15:40) [0]

Уважаемые Мастера, у меня возник следующий вопрос. Мне нужно поднять по DCOM такой продукт как Virtual Server 2005. Естественно в Delphi. Вообще то это не проблема, но нужно поднять (и использовать) этот самый объект под другим (отличным от залогиненного на клиенте пользователем).

Те комбинации методов и флагов безопасности, которые я использую при написании точно такого же клиента на VC++, не работают для Delphi - когда у залогиненного пользователя нет прав и я ломлюсь с его логином и паролем, то получаю ожидаемый Access Denided, но если в этом же случае я лезу под пользователем, который имеет права запуска и доступа, то обнаруживаю Interface not supported.

Самое пародоксальное, что в остальных случаях используемые механизмы (COAUTHINFO в CoCreateInstanceEx, CoSetProxyBlanket) работают - кого надо пускают, кого не надо не пускают.

Подразумеваю, что такая проблема - не только проблема Virtual Server"а, но добавлю, что для доступа к интерфейсам я импортировал библиотеку типов Virtual Server 2005.

Клиент: Windows XP (библиотека типов установлена)
Сервер: Windows 2003 Server (на других Virtual Server не работает)

Заранее спасибо.


 
VMcL ©   (2004-10-30 17:45) [1]

>>Krolik  (30.10.04 15:40)

Сразу сказать, в какой строке ошибка, или код приведешь?


 
Krolik   (2004-10-30 18:57) [2]

Это Delphi

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Label1: TLabel;
   procedure Button1Click(Sender: TObject);
 end;

var
 Form1: TForm1;

implementation
uses VS_TLB, ActiveX;
{$R *.dfm}

function VirtualServerConnection : WideString; forward;

procedure TForm1.Button1Click(Sender: TObject);
begin
 Label1.Caption := VirtualServerConnection;
end;

function VirtualServerConnection : WideString;
const
 wstrUserName    : WideString = "user";
 wstrDomainName  : WideString = "domain";
 wstrPassword    : WideString = "password";
 wstrServer      : WideString = "server";
type
 TCoAuthIdentity = packed record
   User:           PWideChar;
   UserLength:     DWORD;
   Domain:         PWideChar;
   DomainLength:   DWORD;
   Password:       PWideChar;
   PasswordLength: DWORD;
   Flags:          DWORD;
 end;
 TCoAuthInfo = packed record
   dwAuthnSvc:           DWORD;
   dwAuthzSvc:           DWORD;
   pwszServerPrincName:  LPWSTR;
   dwAuthnLevel:         DWORD;
   dwImpersonationLevel: DWORD;
   pAuthIdentityData:    ^TCoAuthIdentity;
   dwCapabilities:       DWORD;
 end;
var
 VS:           IVMVirtualServer;
 wstrVer:      WideString;
 ServerInfo:   TCoServerInfo;
 AuthInfo:     TCoAuthInfo;
 AuthIdentity: TCoAuthIdentity;
 IID_IUnknown: TGuid;
 MQI:          TMultiQI;
 Flags:        DWORD;
 hr:           HResult;
begin
 FillChar(AuthIdentity, sizeof(AuthIdentity), 0);
 AuthIdentity.User             := PWideChar(wstrUserName);
 AuthIdentity.UserLength       := Length(wstrUserName);
 AuthIdentity.Domain           := PWideChar(wstrDomainName);
 AuthIdentity.DomainLength     := Length(wstrDomainName);
 AuthIdentity.Password         := PWideChar(wstrPassword);
 AuthIdentity.PasswordLength   := Length(wstrPassword);
 AuthIdentity.Flags            := 2;//SEC_WINNT_AUTH_IDENTITY_UNICODE

 FillChar(AuthInfo, sizeof(AuthInfo), 0);
 AuthInfo.dwAuthnSvc           := 10;
 AuthInfo.dwAuthzSvc           := 0;
 AuthInfo.pwszServerPrincName  := nil;
 AuthInfo.dwAuthnLevel         := 6;
 AuthInfo.dwImpersonationLevel := 3;
 AuthInfo.pAuthIdentityData    := @AuthIdentity;
 AuthInfo.dwCapabilities       := 64;//EOAC_DYNAMIC_CLOAKING

 FillChar(ServerInfo, sizeof(ServerInfo), 0);
 ServerInfo.pwszName           := PWideChar(wstrServer);
 ServerInfo.pAuthInfo          := @AuthInfo;

 IID_IUnknown  := IUnknown;
 MQI.IID       := @IID_IUnknown;
 MQI.itf       := nil;
 MQI.hr        := 0;
 Flags         := CLSCTX_REMOTE_SERVER;

 VS := nil;
 hr := CoCreateInstanceEx(CLASS_VMVirtualServer, nil, Flags, @ServerInfo, 1, @MQI);
 if FAILED(hr) or FAILED(MQI.hr) then
 begin
   Result := "CoCreateInstanceEx failed!";
   exit;
 end;

 try
   VS := MQI.itf as IVMVirtualServer;;
 except
   Result := "Interface casting failed!";
   VS := nil;
   exit;
 end;

 hr := CoSetProxyBlanket
 (
   VS,
   9,//RPC_C_AUTHN_DEFAULT
   1,//RPC_C_AUTHZ_NONE
   nil,
   6,//RPC_C_AUTHN_LEVEL_PKT_PRIVACY
   3,//RPC_C_IMP_LEVEL_IMPERSONATE
   @AuthIdentity,
   64//EOAC_DYNAMIC_CLOAKING
 );
 if FAILED(hr) then
 begin
   Result := "CoSetProxyBlanket failed!";
   VS := nil;
   exit;
 end;

 try
   wstrVer := VS.Version;
 except
   Result := "get_Version failed!";
   VS := nil;
   exit;
 end;

 Result := wstrVer;
 VS := nil;
end;

initialization
 CoInitializeEx(nil, COINIT_MULTITHREADED);
 CoInitializeSecurity
 (
   nil,
   -1,
   nil,
   nil,
   6,//RPC_C_AUTHN_LEVEL_PKT_PRIVACY
   3,//RPC_C_IMP_LEVEL_IMPERSONATE
   nil,
   64,//EOAC_DYNAMIC_CLOAKING}
   nil
 );
finalization
 CoUninitialize;
end.


Это C++

#define _WIN32_DCOM
#include "VSComInterfaces.h"
#include <atlbase.h>
#include <comdef.h>

// COM INITIALIZATION routine
//
void main ()
{
const LPWSTR wstrServerName = L"server";
const LPWSTR wstrUserName = L"user";
const LPWSTR wstrDomainName = L"domain";
const LPWSTR wstrPassword = L"password";
IVMVirtualServer* pIVS = NULL;

HRESULT hr = CoInitializeEx(NULL,COINIT_MULTITHREADED);
  if (FAILED(hr)) return;

hr = CoInitializeSecurity
(
 NULL,
 -1,
 NULL,
 NULL,
 RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
 RPC_C_IMP_LEVEL_IMPERSONATE,
 NULL,
 EOAC_DYNAMIC_CLOAKING,
 NULL
);
if (FAILED(hr)) return;
 
REFCLSID classID = _uuidof(VMVirtualServer);

   COAUTHIDENTITY AuthIdentity;
AuthIdentity.User = wstrUserName;
AuthIdentity.UserLength = wcslen(wstrUserName);
AuthIdentity.Domain = wstrDomainName;
AuthIdentity.DomainLength = wcslen(wstrDomainName);
AuthIdentity.Password = wstrPassword;
AuthIdentity.PasswordLength = wcslen(wstrPassword);
AuthIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;

COAUTHINFO AuthInfo;
AuthInfo.dwAuthnSvc = 10;//RPC_C_AUTHN_WINNT
AuthInfo.dwAuthzSvc = 0;//RPC_C_AUTHZ_NONE
AuthInfo.dwAuthnLevel = 6;//RPC_C_AUTHN_LEVEL_PKT_PRIVACY
AuthInfo.dwImpersonationLevel = 3;//RPC_C_IMP_LEVEL_IMPERSONATE
AuthInfo.pAuthIdentityData = &AuthIdentity;
AuthInfo.pwszServerPrincName = NULL;
AuthInfo.dwCapabilities = EOAC_DYNAMIC_CLOAKING;

COSERVERINFO serverInfo = { 0, wstrServerName, &AuthInfo, 0 };
   MULTI_QI multiQI = { &IID_IVMVirtualServer, NULL, NOERROR };
hr = CoCreateInstanceEx(classID, NULL, CLSCTX_REMOTE_SERVER, &serverInfo, 1, &multiQI);

// get interface pointer
if (FAILED(hr) || FAILED(multiQI.hr))
{
 printf("CoCreateInstanceEx failed!");
 return;
}
pIVS = (IVMVirtualServer*)(multiQI.pItf);
hr = CoSetProxyBlanket
(
 pIVS,
 9,//RPC_C_AUTHN_GSS_NEGOTIATE
 1,//RPC_C_AUTHZ_DEFAULT
 NULL,
 6,//RPC_C_AUTHN_LEVEL_PKT_PRIVACY
 3,//RPC_C_IMP_LEVEL_IMPERSONATE
 &AuthIdentity,
 64//EOAC_DYNAMIC_CLOAKING
);
if (FAILED(hr))
{
 printf("CoSetProxyBlanket failed!");
 pIVS->Release();
 return;
}

_bstr_t bVer;
   hr = pIVS->get_Version(bVer.GetAddress());
if (FAILED(hr))
{
 printf("get_Version failed!");
 pIVS->Release();
 return;
}
printf("%ls", (wchar_t*)bVer);
pIVS->Release();
CoUninitialize();
}

HELP, PLEASE


 
Krolik   (2004-10-30 18:59) [3]

Ошибка, соответственно, происходит при кастовании
VS := MQI.itf as IVMVirtualServer


 
VMcL ©   (2004-10-31 02:34) [4]

Хм. Попробуй вызвать QueryInterface вручную:
hr := MQI.itf.QueryInterface(IVMVirtualServer, VS);
if Failed(hr) then
begin
 SetLastError(hr);
 RaiseLastOSError;
end;


 
Krolik   (2004-10-31 17:10) [5]

Спасибо, обязательно попробую, когда пойду на работу (дома не могу весь контекст (Win2003, 2*PC, Virtual Server) реализовать).
Хотя в VC++ я тоже кастую, а не зову QI:
pIVS = (IVMVirtualServer*)(multiQI.pItf);

Я хотел бы понять почему такое происходит, ведь в том случае если я поднимаю объект под другим пользователем на клиенте, где залогиненный пользователь имеет все права, этот код проходит без проблем.
COM - вещь прекрасная, но его нужно и понимать...

Может быть дело в Delphi?
Может эта среда работает с комовским контекстом не так, как надо. Хотя... она вроде экспортирует функции из системной ole32.dll. Есть идеи? Заранее спасибо.


 
VMcL ©   (2004-10-31 20:56) [6]

>>Krolik  (31.10.04 17:10) [5]

>Хотя в VC++ я тоже кастую, а не зову QI:
pIVS = (IVMVirtualServer*)(multiQI.pItf);


Это не тоже, что as. Это как:
pIVS = IVMVirtualServer(multiQI.pItf);
в Delphi.

"as", в принципе, для интерфейсов автоматически вызывает QueryInterface.

>Может эта среда работает с комовским контекстом не так, как надо.

Сомневаюсь. Проверь GUID интерфейса IVMVirtualServer в Delphi"йском модуле.

Кстати, меня смущает вот это:
MULTI_QI multiQI = { &IID_IVMVirtualServer, NULL, NOERROR };
vs
MQI.IID    := @IID_IUnknown;
MQI.itf    := nil;
MQI.hr     := 0;


?


 
Krolik   (2004-11-01 11:57) [7]


> VMcL ©   (31.10.04 20:56) [6]



> Кстати, меня смущает вот это:
> MULTI_QI multiQI = { &IID_IVMVirtualServer, NULL, NOERROR
> };
> vs
> MQI.IID    := @IID_IUnknown;
> MQI.itf    := nil;
> MQI.hr     := 0;

Меня теперь это тоже очень сильно смутило, хотя, откровенно говоря этот код почти полностью списан из дельфовой функции CreateRemoteComObject, которая принимает только classID и имя удаленной машины, а следовательно не знает об интерфейсе IID_IVMVirtualServer, отправляя в структуру MULTI_QI именно IID_IUnknown.
Значит, если воспользуемся борландовской функцией и сделаем as, который

> в принципе, для интерфейсов автоматически вызывает QueryInterface.

то должны получить ожидаемое поведение.
И опять-таки остается непонятным, почему только в одном единственном случае (когда у залогиненного пользователя нет прав, а я стучусь по DCOM пользователем у которого права есть) код заваливается.
И если бы, как ты пишешь, в импортированной
библиотеке типов был не тот GUID, то сервер бы ни разу не поднялся, в то время как во всех случаях за исключением указанной ситуации код работает прекрасно.

Я замучил поисковики, но к сожалению ничего по этой теме не нашел. Скорее всего это означает, что проблема в моем коде. Но где же?

VMcL, спасибо тебе за оказываемую помощь.


 
VMcL ©   (2004-11-01 20:03) [8]

>>Krolik  (01.11.04 11:57) [7]

>Меня теперь это тоже очень сильно смутило

Попробуй всё-таки сразу получить IID_IVMVirtualServer. Мне кажется, проблема в этом.

>VMcL, спасибо тебе за оказываемую помощь.

URW.


 
Krolik   (2004-11-01 21:22) [9]


> VMcL ©   (01.11.04 20:03) [8]


Обязательно попробую, но о результатах сообщу в среду. Работа такая.

:) Признавая собственную серость, заявляю, что не знаю, что такое URW. Может UnReal World? :)


 
VMcL ©   (2004-11-01 23:28) [10]

>>Krolik  (01.11.04 21:22) [9]

URW --> U (You) R (are) Welcome.


 
Krolik   (2004-11-03 17:42) [11]


> VMcL ©   (01.11.04 23:28) [10]

Есть две новости: отличная (1) и грустная (2).

[1] Ура!
Все оказалось, как ты и предсказывал. Действительно, надо было всего лишь написать

MQI.IID := @IID_IVMVirtualServer;

Все работает. Не пришлось даже бубен с полки доставать.

[2] Неура...
Непонятно, почему все заваливалось только в случае когда...(надоело писать в каком случае).

Но все работает. А это главное.

Еще раз спасибо.



Страницы: 1 вся ветка

Текущий архив: 2005.08.14;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.041 c
14-1122237834
Kerk
2005-07-25 00:43
2005.08.14
Любопытно :)


1-1121922698
Mefodiy
2005-07-21 09:11
2005.08.14
Как определить "графическое быстрдействия" компьютера


4-1118771362
Unknown user
2005-06-14 21:49
2005.08.14
Утечка памяти -помогите!


1-1122368068
dddim
2005-07-26 12:54
2005.08.14
winexec


5-1092222402
far
2004-08-11 15:06
2005.08.14
Перехват изменения набора полей DataSet-а в design-time (2)