search
Japanese Chinese Nederlands Espanol Italiano Deutsch Francais Twitter Rss Feeds
.NET Framework GroupsView
Deployment Server
.NET Distributed_Apps
.NET
.NET ADO.NET
.NET ASP.NET
.NET ASP.NET Security
.NET ASP.NET Webcontrols
.NET ASP.NET Web Services
.NET Clr
.NET Compact Framework
.NET Drawing
.NET Interop
.NET Micro Porting
.NET Performance
.NET Web Services
.NET Windows Forms
.NET Windows Forms Controls
.NET General
.NET Csharp
.NET Visual Basic
.NET Vc
.NET Security
.NET Xml
Scripting Jscript
Scripting Visual Basicscript
Scripting Wsh
Smartphone Developer
Visual Basic Com
Visual Basic Controls
Visual Basic Crystal
Visual Basic Database Ado
Visual Basic Syntax
Visual Basic Vista Compatibility
Visual Basic Winapi
Vc Atl
Vc Debugger
Vc Language
Vc Mfc
Vc Stl
Visio Developer Visual Basica
Vsnet Debugging
Windows Powershell
Windowsce Embedded Vc
Xml
Xsl

Group SummariesView
.NET Framework
Access
BizTalk
Certifications
CRM
DDK
Exchange Server
FoxPro
French
French .NET
Games
German
German .NET
Graphic Design
IIS
Internet
ISA Server
Italian
Italian .NET
Maps
MCIS
Miscellaneous
Mobile Application Development
Money
MSN
Networking
Office
Ops Mgr
Publisher
Security
SharePoint
Small Business
Spanish
Spanish .NET
SQL Server
Systems Management Server
Transaction Server
Virtual PC / Virtual Server
Visual Studio
Win32
Windows 2000
Windows 2003 Server
Windows 7
Windows Live
Windows Media
Windows Update
Windows Vista
Windows XP
 

View All Microsoft NET Csharp Posts  Ask A New Question 

Remote call to COM impersonating another user - JCav

Monday, January 07, 2008 9:19 AM

I need to call a COM object from a remote machine using C#. I also need to
pass on a different userID and password to the call. Has anyone done this?
I've used Java to do this using JIntegra, but the application I'm using
requires .NET.

Any advice?
reply
 

Well, you are more than likely going to have to call through DCOM/COM+. - Nicholas Paldino [.NET/C# MVP]

Monday, January 07, 2008 10:17 AM

Well, you are more than likely going to have to call through DCOM/COM+.
Assuming you have it set up correctly on the other machine, and you have an
interface definition for the COM object you want to call, you can call the
GetTypeFromProgID (or GetTypeFromCLSID), using the overload which will take
a remote machine name.  You would then create an instance of that type
through a call to CreateInstance on the Activator class, and cast to your
interface type.

Mind you, the semantics of making a remote call are different than just
making a regular COM call (activation contexts, instancing, and the like).

Do you already have the object set up for remote calls?

--
- Nicholas Paldino [.NET/C# MVP]
- mvp@spam.guard.caspershouse.com
reply

It's set up for remote calls - I am able to make these calls remotely using - JCav

Monday, January 07, 2008 10:46 AM

It's set up for remote calls - I am able to make these calls remotely using
JIntegra. I guess what I need is to duplicate what JIntegra does. I get
authentication errors which leads me to believe that I need the mechanism
that sets up the call with credentials - in this case userID, password.
reply

Well, you can always impersonate that caller on the client thread, and then - Nicholas Paldino [.NET/C# MVP]

Monday, January 07, 2008 10:57 AM

Well, you can always impersonate that caller on the client thread, and
then call the CoImpersonateClient API function through the P/Invoke layer
(make sure to call CoRevertToSelf).

--
- Nicholas Paldino [.NET/C# MVP]
- mvp@spam.guard.caspershouse.com
reply

Remote call to COM impersonating another user - Willy Denoyette [MVP]

Monday, January 07, 2008 12:23 PM

The client needs to set the security context for the DCOM call at the very
beginning of the start of the process (before creating the first (D)COM
instance).
This can be done by calling "CoInitializeSecurity" using PInvoke,  when
calling CoInitializeSecurity  you'll have to set  "DynamicCloaking" and the
Note that the client needs to impersonate "the" windows client before
calling into the DCOM server, this again requires you to use PInvoke to call
obtained from LogonUser.

Herewith the CoInitializeSecurity PInvoke stuff to get you started.


public enum RpcAuthnLevel
{
Default = 0,
None,
Connect,
Call,
Pkt,
PktIntegrity,
PktPrivacy
}

public enum RpcImpLevel
{
Default = 0,
Anonymous,
Identify,
Impersonate,
Delegate
}


public enum EoAuthnCap
{
None = 0x00,
MutualAuth = 0x01,
StaticCloaking = 0x20,
DynamicCloaking = 0x40,
AnyAuthority = 0x80,
MakeFullSIC = 0x100,
Default = 0x800,
SecureRefs = 0x02,
AccessControl = 0x04,
AppID = 0x08,
Dynamic = 0x10,
RequireFullSIC = 0x200,
AutoImpersonate = 0x400,
NoCustomMarshal = 0x2000,
DisableAAA = 0x1000
}

[DllImport("Ole32.dll",
ExactSpelling = true,
EntryPoint = "CoInitializeSecurity",
CallingConvention = CallingConvention.StdCall,
SetLastError = false,
PreserveSig = false)]

private static extern void CoInitializeSecurity(
IntPtr pVoid,
int cAuthSvc,
IntPtr asAuthSvc,
IntPtr pReserved1,
uint dwAuthnLevel,
uint dwImpLevel,
IntPtr pAuthList,
uint dwCapabilities,
IntPtr pReserved3);

// Usage
...
// Initialize COM security for the process specifying impersonate for the
outgoing calls
CoInitializeSecurity(IntPtr.Zero,
-1,
IntPtr.Zero,
IntPtr.Zero,
(uint)RpcAuthnLevel.Connect,
(uint)RpcImpLevel.Impersonate,
IntPtr.Zero,
(uint)EoAuthnCap.DynamicCloaking,
IntPtr.Zero);
...
// Impersonate a windows client (LogonUser & Impersonate) and call the
server here.
// Create/Create remote instance ...


Willy.
reply

My situation is I'm the C# client. I don't have access to the server code. - JCav

Monday, January 07, 2008 1:48 PM

My situation is I'm the C# client. I don't have access to the server code. I
know the credentials I need to access the COM server. When my client calls
the COM object it gets rejected. When I use JIntegra, I set the credentials
before I make the call, and the COM server is happy. CoImpersonateClient
seems to be something the server calls.

Since JIntegra can do it, there's obviously a way. I just don't know what
calls they make to do it, and they're not telling.
reply

Remote call to COM impersonating another user - Willy Denoyette [MVP]

Monday, January 07, 2008 2:20 PM

I told you what you need to do, see my other reply.

Willy.
reply

JCav, You are right. Willy actually posted the correct answer just below. - Nicholas Paldino [.NET/C# MVP]

Monday, January 07, 2008 2:23 PM

JCav,

You are right.  Willy actually posted the correct answer just below.


--
- Nicholas Paldino [.NET/C# MVP]
- mvp@spam.guard.caspershouse.com
reply

I'm new to this, so bear with me. I seem to be missing something. - JCav

Tuesday, January 08, 2008 11:13 AM

I'm new to this, so bear with me.  I seem to be missing something.

When I call LogonUser, it fails, I think because the domain I need to log
into is not available from the machine I run this from. When I use
the local domain it works fine - I become the other user when I impersonate
him. This is how far I got before the original post. Is there a call
that sends this information to the server and tells it to do this? As I
said, this works with whatever JIntegra does it.
reply

Remote call to COM impersonating another user - Willy Denoyette [MVP]

Tuesday, January 08, 2008 11:42 AM

You don't have to send this information to the server, it's the role of COM
to authenticate the client and pass the security context to the server.
When you call CoInitializeSecurity, specifying DynamicCloaking (or
StaticCloacking) very early in the process, COM will automatically pass the
impersonation token of the client to the server, the server will use this
token when impersonating (the server needs to call CoImpersonateClient for
this).
What you need to take care of is that the token passed is an impersonating
token, so be carefull when calling LogonUser, the token sent must be an
impersonation token not a direct token.
That means that you'll have to specify a "batch" or "interactive" logon type
when calling LogonUser, before calling Impersonate. Another option is to use
a "network" logon type and call "DuplicateToken" before using the duplicated
token in the Impersonate call.




Willy.
reply

Remote call to COM impersonating another user - Willy Denoyette [MVP]

Tuesday, January 08, 2008 6:14 PM

And you function declaration looks like:

[DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool LogonUser(
string lpszUserName,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr hToken);

bool result = LogonUser(name, domain, passwd,
LOGON32_LOGON_INTERACTIVE ,
LOGON32_PROVIDER_DEFAULT,
ref tokenHandle);
if (result == false) // If failed
{
}
else // success
{

Note that you should use LOGON32_LOGON_INTERACTIVE or LOGON32_LOGON_BATCH
(value 4) as logon type, other types will not return a token that can be
used to impersonate unless you are running in the context of an
administrator (or an account with "SeImpersonatePrivileges" enabled) .


Willy.
reply

Remote call to COM impersonating another user - JCav

Thursday, January 10, 2008 11:57 AM

I call LogonUser just the way you specified and I'm still getting the 1326:

int ret = CoInitializeSecurity(IntPtr.Zero,-1,IntPtr.Zero,IntPtr.Zero,
RpcAuthnLevel.Connect,RpcImpLevel.Impersonate, IntPtr.Zero,
(int)EoAuthnCap.DynamicCloaking, IntPtr.Zero);

ret is zero ...
bool returnValue = LogonUser("UID",  "Domain",  "password",
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,  ref tokenHandle);



returns false with a code of 1326

I can connect to the machine in question using these values and mstsc.exe.
The domain I use to log into my machine is different from the domain I use
above. Is this an issue? Is there some kind of administrative flag keeping
me from doing this? Am I calling CoInitializeSecurity with the wrong values?
I'm using the definitions you sent in an earlier post.
reply

Previous Microsoft NET Csharp conversation.