HOW: Copy files in network with authentication ??

  • Thread starter Thread starter Kristijan Marin
  • Start date Start date
K

Kristijan Marin

Hi,

Does anyone know how to copy files inside network from mashine one to
mashine2
if the mashine2 requires user/pass authentication ??

I need this for Windows platform.
Anyone did that ?

Thaks.
 
Kristijan Marin said:
Does anyone know how to copy files inside network from mashine one to
mashine2
if the mashine2 requires user/pass authentication ??

I need this for Windows platform.

Which Windows platform?

If it is one of NT/2K/XP/2K+3 that you are talking about you should be able
to use this sequence

LogonUser();
ImpersonateLoggedOnUser();
CopyFile();
RevertToSelf();
CloseHandle(); // on the token returned by LogonUser()

Prior to XP, the calling thread requires must be in the trusted computing
base which is to say it is the SE_TCB_NAME privilege which shows up in the
user manager as "Act as part of the operating system".

For that reason, this sequence is usually found in a server applications
which are implemented as services running under LocalSystem, having the
requisite privilege, and necessarily installed by an administrator.

Regards,
Will
 
If it is one of NT/2K/XP/2K+3 that you are talking about you should be able
to use this sequence

LogonUser();
ImpersonateLoggedOnUser();
CopyFile();
RevertToSelf();
CloseHandle(); // on the token returned by LogonUser()

LogonUser only logs you in to the local computer, and it can't be used
to log on to a remote computer. The user must exist locally. If the user
doesn't exist locally, than WNetAddConnection seems to be the only way
to go, which is not safe, because if the app crashes, the connection
remains open. I have yet to find a solution that works and is safe.
LogonUser is totally out of question, because on a typical network a
local computer only has 1 user, while a file server has numerous others.

Tom
 
Tamas Demjen said:
LogonUser only logs you in to the local computer, and it can't be used to
log on to a remote computer. The user must exist locally. If the user
doesn't exist locally, than WNetAddConnection seems to be the only way to
go, which is not safe, because if the app crashes, the connection remains
open. I have yet to find a solution that works and is safe. LogonUser is
totally out of question, because on a typical network a local computer
only has 1 user, while a file server has numerous others.

Tom

The purpose of LogonUser is to obtain an access token specifying the
credentials of a valid local or domain (remote) account. If you specify a
remote users credentials, the token obtained can be used to impersonate the
current thread and access the remote resource. Now, if you use non local
user credentials, accesses to local FS objects will fail (unless the remote
user is a shadow account of a local account), this can be solved by:
- specifying a domain user when calling LogonUser and granting this doamin
account access to the loacl FS resources, or,
- by specifying LOGON32_LOGON_NEW_CREDENTIALS as dwLogonType (W2K2 or
higher).

Willy.
 
Willy said:
The purpose of LogonUser is to obtain an access token specifying the
credentials of a valid local or domain (remote) account. If you specify a
remote users credentials, the token obtained can be used to impersonate the
current thread and access the remote resource. Now, if you use non local
user credentials, accesses to local FS objects will fail (unless the remote
user is a shadow account of a local account), this can be solved by:
- specifying a domain user when calling LogonUser and granting this doamin
account access to the loacl FS resources, or,
- by specifying LOGON32_LOGON_NEW_CREDENTIALS as dwLogonType (W2K2 or
higher).

Willy.

Thanks Willy, this seems to be solving a 2-year-old problem to me. The
following works nicely:

HANDLE token;
if(LogonUser(
"Tamas", "\\\\RemoteComputer",
"password",
LOGON32_LOGON_NEW_CREDENTIALS,
LOGON32_PROVIDER_DEFAULT,
&token))
{
if(ImpersonateLoggedOnUser(token))
{
CopyFile("c:\\0.txt", "\\\\RemoteComputer\\Share\\0.txt",
TRUE);
RevertToSelf();
}
CloseHandle(token);
}

Does the LOGON32_LOGON_NEW_CREDENTIALS flag require the server to be
W2k+, or the client (local) computer only?

I also tried this:
BOOL res = LogonUser(
"Tamas@RemoteComputer", NULL,
"password",
LOGON32_LOGON_NETWORK,
LOGON32_PROVIDER_DEFAULT,
&token);

and res was TRUE and the token was valid, but after the
ImpersonateLoggedOnUser call the remote FS was not accessible. Note that
RemoteComputer is not a true domain, it's just another computer in a
workgroup. I guess if I knew how to add access to the FS, that would
work too. <sigh> I'd spent days without success before.

Anyway, LOGON32_LOGON_NEW_CREDENTIALS does the trick, but only on W2k+.

Tom
 
Tamas,
Inline.
Willy.

Tamas Demjen said:
Thanks Willy, this seems to be solving a 2-year-old problem to me. The
following works nicely:

HANDLE token;
if(LogonUser(
"Tamas", "\\\\RemoteComputer",
"password",
LOGON32_LOGON_NEW_CREDENTIALS,
LOGON32_PROVIDER_DEFAULT,
&token))
{
if(ImpersonateLoggedOnUser(token))
{
CopyFile("c:\\0.txt", "\\\\RemoteComputer\\Share\\0.txt",
TRUE);
RevertToSelf();
}
CloseHandle(token);
}

Does the LOGON32_LOGON_NEW_CREDENTIALS flag require the server to be W2k+,
or the client (local) computer only?

The computer calling LogonUser() needs W2K or higer (that is all, OS that
run Kerberos security providers).
I also tried this:
BOOL res = LogonUser(
"Tamas@RemoteComputer", NULL,
"password",
LOGON32_LOGON_NETWORK,
LOGON32_PROVIDER_DEFAULT,
&token);

and res was TRUE and the token was valid, but after the
ImpersonateLoggedOnUser call the remote FS was not accessible. Note that
RemoteComputer is not a true domain, it's just another computer in a
workgroup. I guess if I knew how to add access to the FS, that would work
too. <sigh> I'd spent days without success before.

This is by design, the logontype LOGON32_LOGON_NETWORK returns an access
token that has NO network access.
Anyway, LOGON32_LOGON_NEW_CREDENTIALS does the trick, but only on W2k+.
Yep, no need to map shares to local drives anymore, or to impersonate domain
accounts to access SQL server, just create a logon session with "split
identity" and you can access the server while keeping you local access token
to access local resources.
 
Willy said:
This is by design, the logontype LOGON32_LOGON_NETWORK returns an access
token that has NO network access.

Thanks again. LOGON32_LOGON_NEW_CREDENTIALS is my only choice, as every
other logintype fails to authenitcate the remote-only user (returns
ERROR_LOGON_FAILURE). It's alright, because the app in question is
always runnin on XP. The remote computer we connect to may be running
some older Windows, but we alway call LogonUser from an XP box.
Yep, no need to map shares to local drives anymore

That's exactly what I wanted, because mapping a UNC share enables a
system-wide access, which is a potential security threat. I only want an
application-wide CopyFile. It's so much safer now.

If I had to implement this with OSes older than W2k, it seems I would
have no choice but to map the share (or implement a TCP/IP based secure
server to send files).

Tom
 
Tamas Demjen said:
LogonUser only logs you in to the local computer, and it can't be used to
log on to a remote computer.

I guess that depends on what you mean by "log on to a remote computer".

I can tell you that, just as the docs specify, if on a machine in a domain,
you specify the credentials of a domain user, then you can certainly get a
token and use it to impersonate that user.

And of course, you can also use the function to get a token representing a
user local to the machine.

Regards,
Will
 
William said:
I guess that depends on what you mean by "log on to a remote computer".

I can tell you that, just as the docs specify, if on a machine in a domain,
you specify the credentials of a domain user, then you can certainly get a
token and use it to impersonate that user.

And of course, you can also use the function to get a token representing a
user local to the machine.

My conclusion is that LOGON32_LOGON_NEW_CREDENTIALS seems to be the only
way to go when the local machine is not in a domain, or when it is in a
different domain than the remote machine. It works now (I posted the
sample code earlier).

LOGON32_LOGON_NEW_CREDENTIALS is not required to impersonate users on
the local machine, or on a remote machine in the same domain as the
local one.

It seems to me that LogonUser was originally designed to support
impersonation of local and domain users, and later (in W2k) MS has
introduced the LOGON32_LOGON_NEW_CREDENTIALS logontype to support
foreign domains and machines not in a domain.

Tom
 
Tamas Demjen said:
LOGON32_LOGON_NEW_CREDENTIALS is not required to impersonate users on the
local machine, or on a remote machine in the same domain as the local one.

It seems to me that LogonUser was originally designed to support
impersonation of local and domain users, and later (in W2k) MS has
introduced the LOGON32_LOGON_NEW_CREDENTIALS logontype to support foreign
domains and machines not in a domain.

Perhaps. But the docs seem clear:

<quote>
Windows 2000/XP: This logon type allows the caller to clone its current
token and specify new credentials for outbound connections. The new logon
session has the same local identify, but uses different credentials for
other network connections.
This logon type is supported only by the LOGON32_PROVIDER_WINNT50 logon
provider
</quote>

Unlike the other options, this one allows for a "split personality" with one
set of credentials for local use and another for remote.

Regards,
Will
 
Back
Top