Re: IIS Folder and file security. Impersonation does not work.
From: David Wang [Msft] (someone_at_online.microsoft.com)
Date: 07/08/04
- Next message: David Wang [Msft]: "Re: Problem with simplified chinese"
- Previous message: David Wang [Msft]: "Re: iis crashing... javascript?"
- In reply to: Razak: "IIS Folder and file security. Impersonation does not work."
- Messages sorted by: [ date ] [ thread ]
Date: Thu, 8 Jul 2004 00:18:19 -0700
You are trying to implement two things:
1. Custom URL navigation.
2. Custom authentication
First -- what you want to do does NOT need the impersonation DLL at all.
Let me explain a possible implementation shortly.
Second -- you are muddling HTML and IIS concepts together and hoping for the
best. You have to understand that sending a <img src> causes the client to
make a separate request which has NOTHING to do with this current request,
while making a FileSystemObject or ADO call on this request to stream a file
DOES use this current request's identity.
What you observe is absolutely by-design. Yes, the ActiveX Object is able
to change the impersonation token for the thread that is executing the ASP
page which ends up sending the <img src...> entity body to the client.
However, please realize that the client makes ANOTHER SEPARATE request for
the <img src> URL, which is handled by ANOTHER thread on IIS -- IIS is
multi-threaded. Thus, the impersonation that you did for this ASP page does
absolutely nothing for that <img src> request -- hence you see the password
dialog.
Meanwhile, if you chose to use FileSystemObject or ADO to open a file and
stream it to the client, then the impersonation token WILL be used on that
FileSystemObject/ADO call.
Finally -- it is NOT possible to change the user identity that IIS uses to
execute a request with ASP -- if you want IIS to serve up "files/00001.jpg"
as your UserX, you need to either:
1. Browser must authenticate as UserX when requesting files/00001.jpg
2. Only anonymous is allowed, and Anonymous User is configured as UserX (so
all anonymous users impersonate UserX)
3. Use an ISAPI Filter or ISAPI Extension to change the impersonation token
that IIS uses
None of these are possible with anything you do in ASP. You simply cannot
change the impersonation token that IIS uses with ASP -- as soon as your
page returns control to IIS, IIS will strip off the impersonation token on
the thread. So, you can only change the impersonation token of the thread
while that ASP page is running -- which is what the sample code does.
Now, with IIS6, we have a custom authentication sample ISAPI that should
work for you after you write a little bit of C code to customize it for your
specific needs.
Download the Platform SDK and get the IIS portion. The sample code is
called CustomAuth, and the Platform SDK includes necessary tools/compiler to
build it (if you do not have Visual Studio or comparable development tool).
http://www.microsoft.com/msdownload/platformsdk/sdkupdate/default.htm
It can be configured for any URL namespace, and it implements custom
authentication where you enter username/password in an HTML page. So, you
can easily configure CustomAuth to protect only content under the /Files
vdir and no-where else. The CustomAuth.INI file explains how to do this,
conceptually. Basically, the /Files vdir will have only anonymous
authentication enabled and this CustomAuth module loaded to implement custom
authentication.
What you'd need to do with this sample code is to implement verification of
the username/password entered from the HTML page as well as set the user
token for IIS to impersonate -- which is EXACTLY all you're trying to do in
the ASP page.
You will find in CustomAuth.cpp a single line containing "LogonUser", and
this is where you'll inject your code.
- pstrUser->QueryStr() contains the username from the form
- strPassword.QueryStr() contains the password from the form
- The hToken that is created by the LogonUser call is the impersonation
token that will be used by IIS to execute the subsequent request.
So, all you need to do is:
1. implement a username/password validation scheme using the values from
pstrUser and strPassword. If there's not a lot of users, I suggest using an
INI file -- one single call to GetPrivateProfileString should be sufficient
to lookup a username/password inside a plain-text INI file.
2. hardcode the LogonUser call to log in UserX
3. If username/password authenticates, then make the LogonUser call in #2
let the rest of the code use the hToken for UserX. If the username/password
fails to authenticate, then set fResult to FALSE and you're done.
Here's a code snippet for you to get started in CustomAuth.cpp. I haven't
compiled nor tested it, but it should get you most of the way there.
For example, suppose your INI file containing usernames/passwords are in
C:\passwords.txt (make sure that this file is accessible to the anonymous
user configured in IIS, since it's the user identity used to execute the
CustomAuth code.
passwords.txt looks like:
[passwords]
user1=password1
user2=password2
...
The code snippet looks something like this (I've added leading/trailing
comments so it is clear where to inject this bit of code in CustomAuth.cpp):
//
// Log on the user
//
DWORD dwPasswordSize;
CHAR szStoredPassword[MAX_PATH];
// lookup the username key under the "passwords" section
// user passwords are limited to MAX_PATH-1 in length. Read MSDN to figure
out how to allow larger passwords
dwPasswordSize = GetPrivateProfileString(
"passwords",
pstrUser->QueryStr(),
"",
szStoredPassword,
MAX_PATH,
"C:\\passwords.txt" );
if ( dwPasswordSize == 0 )
{
// Did not find username in password.txt, so deny access
fResult = FALSE;
SetLastError( ERROR_NO_SUCH_USER );
}
else if ( strcmp( strPassword.QueryStr(), szStoredPassword ) == 0 )
{
// The password from the form matches password for username in
password.txt,
// so allow access with impersonation token of UserX
fResult = LogonUser( "UserX",
NULL,
"UserX's password",
g_LogonType,
LOGON32_PROVIDER_DEFAULT,
&hToken );
}
else
{
// username was found, but password did not match, so deny access
fResult = FALSE;
SetLastError( ERROR_INVALID_PASSWORD );
}
//
// Regardless of the result, we are done with the password
//
Good luck.
-- //David IIS This posting is provided "AS IS" with no warranties, and confers no rights. // "Razak" <razak@mmsc.com.my> wrote in message news:%23wYzi%23IZEHA.3752@TK2MSFTNGP12.phx.gbl... I'm using WIndows server 2003 with IIS 6.0. My web consists of a folder named 'Files' which I would like to restrict access only to members. The folder contains various types of files such as images (jpg, png, bmp), flash animation (swf), videos (avi, mov), and audios (wav, mp3, aif). What I'm trying to achieve is that members will be alowed to view and download those files in 'Files' folder only through an ASP page since I want to track some statistics. So I have to avoid the files from being leeched or simply opened by typing the url to the file in the address bar. The only way I can think to achieve that is by securing the folder since it is on an NTFS drive. I don't want to create each user a Windows account on the server, instead I created a general user account 'Xuser' which is given the previllege to access the 'File' folder. BTW, the folder is set to allow only Administrators group and Xuser. For each succesfully logged in user will have access to the asp page (which displays the file, or play the movie/animation, so on), by linking to the requested file in the 'Files' folder using Impersonation method I created using VB (as sampled at http://support.microsoft.com/support/kb/articles/q248/1/87.asp ) and on the ASP page is as follows:- <% Dim objLogon Set objLogon = Server.CreateObject("LoginAdmin.ImpersonateUser") objLogon.Logon "Xuser", "1234", "" %> . . . . <IMG Src="files/00001.jpg"> . . . . <% objLogon.Logoff Set objLogon = Nothing %> The problem is, the above impersonation does not work. Everytime I open that page, IE still prompt for user/pwd. I know that the impersonation dll is OK since in other part of the website, I use it to manipulate (modifying/writing) the files in the 'Files' folder which otherwise I'm not allowed to (since 'IUSR_machinename' is not given the privillege at all to access/modify the 'File' folder). And the Impersonation works just fine. It just that it doesn't work when linking from a web page. I opted out locating the secured folder 'File' somewhere outside the web root and stream it using <img src="stream.asp?file=00001.jpg"> because it only works for image files, but doesn't work with shockwave flash, large audio and video files, etc. Hope that someone has done something similar to this to share their knowledge. Thanks.
- Next message: David Wang [Msft]: "Re: Problem with simplified chinese"
- Previous message: David Wang [Msft]: "Re: iis crashing... javascript?"
- In reply to: Razak: "IIS Folder and file security. Impersonation does not work."
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|