Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Corba";
Текущий архив: 2005.08.14;
Скачать: [xml.tar.bz2];

Вниз

Некорректное поведение безопасности 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 вся ветка

Форум: "Corba";
Текущий архив: 2005.08.14;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.5 MB
Время: 0.012 c
6-1115076223
Algo
2005-05-03 03:23
2005.08.14
Как из программы установить соединение?


3-1120461930
Draught
2005-07-04 11:25
2005.08.14
suser_id()


14-1122138485
Kerk
2005-07-23 21:08
2005.08.14
Кто убил Киру?


4-1119508902
Grief
2005-06-23 10:41
2005.08.14
Окошко из трея (не знаю как назвать)


4-1118495711
Juk
2005-06-11 17:15
2005.08.14
Позиция и форма окна.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский