Форум: "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 };
vsMQI.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