IIS Server - IE style NTLM/Kerberos auto-authentication against IIS?

This is Interesting: Free IT Magazines  
Home > Archive > IIS Server > January 2004 > IE style NTLM/Kerberos auto-authentication against IIS?





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author IE style NTLM/Kerberos auto-authentication against IIS?
Sten Westerback

2004-01-27, 6:34 pm

Hi

I have problems getting "IE style" automatic http authentication agains IIS5
to work using code like the following (with appropriate account & pw).
I get the error text "401.3 Unauthorized due to ACL on resource" from
the server even if i know the account and password works using IE.

#include <windows.h>
#include <Wininet.h>
#include <Lm.h>

char *Http_p_szPost(char *p_szURL, char *p_szObject, char *p_szBodyData)
{ // the p_szObject parameter is not currently used (in case you
wonder)
char *p_szBuff, *p_szB;
HINTERNET hInet, hInetS, hInetURL;
DWORD dw;
int n;
char *p_szX= "Content-Type: text/html;
charset=ISO-8859-4\r\nWWW-Authenticate: NTLM";

hInet=InternetOpen("MyApp", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (hInet==NULL) return NULL; // failure; error handling in calling routine
hInetS=InternetConnect(hInet, "server.xxxx.com",
INTERNET_DEFAULT_HTTP_PORT,
"myaccount", "mypassword", INTERNET_SERVICE_HTTP, 0, 1968);
if (hInetS==NULL)
hInetS=InternetConnect(hInet, "server.xxxx..com",
INTERNET_DEFAULT_HTTP_PORT,
NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1968);
if (hInetS==NULL) return NULL;

hInetURL=HttpOpenRequest(hInetS, "GET", "filename", NULL, NULL, "text/*",
INTERNET_FLAG_KEEP_CONNECTION, 1968);
if (hInetURL==NULL) // retry as someone suggested in old articles ("handled
internally by InternetAPI")

hInetURL=HttpOpenRequest(hInetS, "GET", "filename", NULL, NULL,
"text/*",
INTERNET_FLAG_KEEP_CONNECTION, 1968);
if (hInetURL==NULL) return NULL;

if (!HttpSendRequest(hInetURL, p_szX, strlen(p_szX), p_szBodyData,
p_szBodyData==NULL?0:strlen(p_szBodyData)))
{
if (!HttpSendRequest(hInetURL, p_szX, strlen(p_szX), p_szBodyData,
p_szBodyData==NULL?0:strlen(p_szBodyData))) return NULL;
}
p_szBuff=malloc(10000); p_szB=p_szBuff; dw=0; n=0;
while (InternetReadFile(hInetURL, p_szB, 10000, &dw))
{
if (dw==0)
{ n++; if (n>5) break; if (p_szB==p_szBuff) Sleep(1000); else
Sleep(500); }
p_szB+=dw; dw=p_szB-p_szBuff; p_szBuff=realloc(p_szBuff, dw+10010);
p_szB=p_szBuff+dw;
}
if ((dw=p_szB-p_szBuff)==0) { free(p_szBuff); p_szBuff=NULL; }
else { p_szBuff=realloc(p_szBuff, dw+1010); p_szBuff[dw]=0;
p_szBuff[dw+1]=0; }
HttpEndRequest(hInetURL, NULL, HSR_SYNC, 1968);
InternetCloseHandle(hInet);
return p_szBuff;
}

int main(int nArgs, char *p_szArgs[])
{
char szPCname[50], szParams[1000],;
...
sprintf(szParams, " go:2\r\ncomputer:%s\r\nconfirm:%s\r\nsub
mit:Confirm
computername\r\n\r\n",
szPCname, szPCname);
p_sz=Http_p_szPost(http://server.xxxx.com/filename, "filename", szParams);
}

As you read this far i hope you have successfully made code
that read protected Intranet pages.. or have other ideas.
My questions are:
- is automatic logon supported by the Internet*() and Http*()
functions or does IE do some (undocumented) tricks? Which?

- is the username=NULL and password=NULL parameters to
InternetConnect() valid for this special purpose despite the
documentation? I have tried both NULL,NULL and the
actual values but still authentication fails.

- if InternetOpenUrl() supports NTLM/Kerberos auto-
authentication, is it possible to make it POST? And
what is the correct POST format with HttpSendRequest ?

- most important of all, what would be an API function call
sequence that works?

One more question. What is the purpose of InternetCheckConnection()
which always seem to return NULL when connected to a LAN.
Is it supposed to fail unless there is a dialup connection is can
autoconnect?
GetLastError() returns 2250 Network connection does not exist.
Thanks for any ideas and code snipets you can provide.

- Sten



David Wang [Msft]

2004-01-28, 12:36 pm

Read this URL for an explanation of how some authentication protocols work:
http://support.microsoft.com/?id=264921

What exactly are you trying to do with your code?

I do not understand why you do every operation twice, send a GET request
with entity body, whether the resource URL handles entity body and sends a
response, send WWW-Authenticate, a response header, on a request, nor why
you think there is something "undocumented" going on.

Authentication is mutually negotiated between the client and server and
depends on their configuration. What basically happens is:
1. Client sends an anonymous request
2. Server is configured to require certain authentication, including
anonymous. If Anonymous is ok, the request goes through. Else, the server
returns 401.2 and adds WWW-Authenticate headers indicating the
authentication type(s) that the server is willing to support
3. The client gets the response from #2. If it suceeds, great. If it's a
401.2, the browser/client should look at WWW-Authenticated, decide amongst
them which it is willing to use, and start negotiating using the
authentication protocol.
4. IE will try to auto-logon a couple of times for you, and if they are all
rejected by 401.x, then it pops up the username/password dialog box.

I would suggest you first figure out how to get a single anonymous GET
request without entity body working, then add authentication, then add SSL,
and finally, change to POST with entity body. I would also make sure to
configure the server properly to respond appropriatly to entity body, SSL,
and authentication.

Finally, realize that WinInet is old code that is documented to be not
performant enough for server-usage -- try WinHTTP or newer.

--
//David
IIS
This posting is provided "AS IS" with no warranties, and confers no rights.
//
"Sten Westerback" <sten.westerback@NO_SPAMnokia.com> wrote in message
news:5SJRb.7884$g4.163661@news2.nokia.com...
Hi

I have problems getting "IE style" automatic http authentication agains IIS5
to work using code like the following (with appropriate account & pw).
I get the error text "401.3 Unauthorized due to ACL on resource" from
the server even if i know the account and password works using IE.

#include <windows.h>
#include <Wininet.h>
#include <Lm.h>

char *Http_p_szPost(char *p_szURL, char *p_szObject, char *p_szBodyData)
{ // the p_szObject parameter is not currently used (in case you
wonder)
char *p_szBuff, *p_szB;
HINTERNET hInet, hInetS, hInetURL;
DWORD dw;
int n;
char *p_szX= "Content-Type: text/html;
charset=ISO-8859-4\r\nWWW-Authenticate: NTLM";

hInet=InternetOpen("MyApp", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (hInet==NULL) return NULL; // failure; error handling in calling routine
hInetS=InternetConnect(hInet, "server.xxxx.com",
INTERNET_DEFAULT_HTTP_PORT,
"myaccount", "mypassword", INTERNET_SERVICE_HTTP, 0, 1968);
if (hInetS==NULL)
hInetS=InternetConnect(hInet, "server.xxxx..com",
INTERNET_DEFAULT_HTTP_PORT,
NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1968);
if (hInetS==NULL) return NULL;

hInetURL=HttpOpenRequest(hInetS, "GET", "filename", NULL, NULL, "text/*",
INTERNET_FLAG_KEEP_CONNECTION, 1968);
if (hInetURL==NULL) // retry as someone suggested in old articles ("handled
internally by InternetAPI")

hInetURL=HttpOpenRequest(hInetS, "GET", "filename", NULL, NULL,
"text/*",
INTERNET_FLAG_KEEP_CONNECTION, 1968);
if (hInetURL==NULL) return NULL;

if (!HttpSendRequest(hInetURL, p_szX, strlen(p_szX), p_szBodyData,
p_szBodyData==NULL?0:strlen(p_szBodyData)))
{
if (!HttpSendRequest(hInetURL, p_szX, strlen(p_szX), p_szBodyData,
p_szBodyData==NULL?0:strlen(p_szBodyData))) return NULL;
}
p_szBuff=malloc(10000); p_szB=p_szBuff; dw=0; n=0;
while (InternetReadFile(hInetURL, p_szB, 10000, &dw))
{
if (dw==0)
{ n++; if (n>5) break; if (p_szB==p_szBuff) Sleep(1000); else
Sleep(500); }
p_szB+=dw; dw=p_szB-p_szBuff; p_szBuff=realloc(p_szBuff, dw+10010);
p_szB=p_szBuff+dw;
}
if ((dw=p_szB-p_szBuff)==0) { free(p_szBuff); p_szBuff=NULL; }
else { p_szBuff=realloc(p_szBuff, dw+1010); p_szBuff[dw]=0;
p_szBuff[dw+1]=0; }
HttpEndRequest(hInetURL, NULL, HSR_SYNC, 1968);
InternetCloseHandle(hInet);
return p_szBuff;
}

int main(int nArgs, char *p_szArgs[])
{
char szPCname[50], szParams[1000],;
...
sprintf(szParams, " go:2\r\ncomputer:%s\r\nconfirm:%s\r\nsub
mit:Confirm
computername\r\n\r\n",
szPCname, szPCname);
p_sz=Http_p_szPost(http://server.xxxx.com/filename, "filename", szParams);
}

As you read this far i hope you have successfully made code
that read protected Intranet pages.. or have other ideas.
My questions are:
- is automatic logon supported by the Internet*() and Http*()
functions or does IE do some (undocumented) tricks? Which?

- is the username=NULL and password=NULL parameters to
InternetConnect() valid for this special purpose despite the
documentation? I have tried both NULL,NULL and the
actual values but still authentication fails.

- if InternetOpenUrl() supports NTLM/Kerberos auto-
authentication, is it possible to make it POST? And
what is the correct POST format with HttpSendRequest ?

- most important of all, what would be an API function call
sequence that works?

One more question. What is the purpose of InternetCheckConnection()
which always seem to return NULL when connected to a LAN.
Is it supposed to fail unless there is a dialup connection is can
autoconnect?
GetLastError() returns 2250 Network connection does not exist.
Thanks for any ideas and code snipets you can provide.

- Sten




Sten Westerback

2004-01-29, 1:41 am


"David Wang [Msft]" <someone@online.microsoft.com> wrote in message
news:Owm5Beg5DHA.1040@TK2MSFTNGP10.phx.gbl...
quote:

> Read this URL for an explanation of how some authentication protocols


work:
quote:

> http://support.microsoft.com/?id=264921



Thanks for responding.
quote:

> What exactly are you trying to do with your code?


The initial purpose of the code is to automatically get a page from
an server in intranet using my own code in the same way as IE
does it as you desribed in your response. Later i'm supposed to
POST a form to another URL in the same server.
quote:

> I do not understand why you do every operation twice,


Because this trick was suggested in some old news articles
i read. They claimed that the Internet API function will fail
the first time but that it would handle the response to authentication
automatically on the second attempt.
quote:

>send a GET request with entity body,


do you mean the p_szBodyData parameter? I have tried it
being NULL ... but isn't it here where the POST data goes?
quote:

>whether the resource URL handles entity body and sends a response


Well... in my code it only fails... But IE gladly just give me the html page
without asking anything. ;)
quote:

> send WWW-Authenticate, a response header, on a request,


I have also tried without any additional headers (p_szX="") in the
request. But i suppose that i really would have to add some
headers but can't figure out which. I have also tried a few other
ones but i haven't seen any document specifying what IIS requires
in a request.
quote:

>nor why you think there is something "undocumented" going on.


That "statement" was based on the fact that autoauthentication
doesn't seem to be specified anywhere but there are still news
articles claiming that they have done it (but they don't remember
how ;).. so it seems that only IE knows how to do it.
quote:

> 4. IE will try to auto-logon a couple of times for you, and if they are


all
quote:

> rejected by 401.x, then it pops up the username/password dialog box.


I would like to repeat that my code is not IE... ;)
quote:

> I would suggest you first figure out how to get a single anonymous GET
> request without entity body working,


GET's are working perfectly using InternetOpenUrl() but i
suppose i have to try some other site. The only question is, what
are you supposed to use as account & password in InternetConnect()
when you aren't suppose to have to give any?
quote:

>then add authentication


I hope you mean "enable it on IIS testserver" or "switch to a domain
protected site" and not "add authentication handshake code yourself"?
quote:

>, then add SSL,


SSL is not currently used by this site.
quote:

> and finally, change to POST with entity body.


Sure...
quote:

>I would also make sure to
> configure the server properly to respond appropriatly to entity body,
>SSL, and authentication.


One would guess that if IE can then my could should be able to?
quote:

> Finally, realize that WinInet is old code that is documented to be not
> performant enough for server-usage -- try WinHTTP or newer.


I just rechecked these functions after looking at them briefly
some years ago. I then thought that they were meant primarily for
use in service code. But i'm delighted to see that they allows NULL
for the username in WinHTTPSetCredentials(). I'm of to do some
rewrite now and will report how it goes. Thanks.

- Sten
quote:

> "Sten Westerback" <sten.westerback@NO_SPAMnokia.com> wrote in message
> news:5SJRb.7884$g4.163661@news2.nokia.com...
> Hi
>
> I have problems getting "IE style" automatic http authentication agains


IIS5
quote:

> to work using code like the following (with appropriate account & pw).
> I get the error text "401.3 Unauthorized due to ACL on resource" from
> the server even if i know the account and password works using IE.
>
> #include <windows.h>
> #include <Wininet.h>
> #include <Lm.h>
>
> char *Http_p_szPost(char *p_szURL, char *p_szObject, char *p_szBodyData)
> { // the p_szObject parameter is not currently used (in case you
> wonder)
> char *p_szBuff, *p_szB;
> HINTERNET hInet, hInetS, hInetURL;
> DWORD dw;
> int n;
> char *p_szX= "Content-Type: text/html;
> charset=ISO-8859-4\r\nWWW-Authenticate: NTLM";
>
> hInet=InternetOpen("MyApp", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
> if (hInet==NULL) return NULL; // failure; error handling in calling


routine
quote:

> hInetS=InternetConnect(hInet, "server.xxxx.com",
> INTERNET_DEFAULT_HTTP_PORT,
> "myaccount", "mypassword", INTERNET_SERVICE_HTTP, 0, 1968);
> if (hInetS==NULL)
> hInetS=InternetConnect(hInet, "server.xxxx..com",
> INTERNET_DEFAULT_HTTP_PORT,
> NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1968);
> if (hInetS==NULL) return NULL;
>
> hInetURL=HttpOpenRequest(hInetS, "GET", "filename", NULL, NULL, "text/*",
> INTERNET_FLAG_KEEP_CONNECTION, 1968);
> if (hInetURL==NULL) // retry as someone suggested in old articles


("handled
quote:

> internally by InternetAPI")
>
> hInetURL=HttpOpenRequest(hInetS, "GET", "filename", NULL, NULL,
> "text/*",
> INTERNET_FLAG_KEEP_CONNECTION, 1968);
> if (hInetURL==NULL) return NULL;
>
> if (!HttpSendRequest(hInetURL, p_szX, strlen(p_szX), p_szBodyData,
> p_szBodyData==NULL?0:strlen(p_szBodyData)))
> {
> if (!HttpSendRequest(hInetURL, p_szX, strlen(p_szX), p_szBodyData,
> p_szBodyData==NULL?0:strlen(p_szBodyData))) return NULL;
> }
> p_szBuff=malloc(10000); p_szB=p_szBuff; dw=0; n=0;
> while (InternetReadFile(hInetURL, p_szB, 10000, &dw))
> {
> if (dw==0)
> { n++; if (n>5) break; if (p_szB==p_szBuff) Sleep(1000); else
> Sleep(500); }
> p_szB+=dw; dw=p_szB-p_szBuff; p_szBuff=realloc(p_szBuff, dw+10010);
> p_szB=p_szBuff+dw;
> }
> if ((dw=p_szB-p_szBuff)==0) { free(p_szBuff); p_szBuff=NULL; }
> else { p_szBuff=realloc(p_szBuff, dw+1010); p_szBuff[dw]=0;
> p_szBuff[dw+1]=0; }
> HttpEndRequest(hInetURL, NULL, HSR_SYNC, 1968);
> InternetCloseHandle(hInet);
> return p_szBuff;
> }
>
> int main(int nArgs, char *p_szArgs[])
> {
> char szPCname[50], szParams[1000],;
> ...
> sprintf(szParams, " go:2\r\ncomputer:%s\r\nconfirm:%s\r\nsub
mit:Confirm
> computername\r\n\r\n",
> szPCname, szPCname);
> p_sz=Http_p_szPost(http://server.xxxx.com/filename, "filename", szParams);
> }
>
> As you read this far i hope you have successfully made code
> that read protected Intranet pages.. or have other ideas.
> My questions are:
> - is automatic logon supported by the Internet*() and Http*()
> functions or does IE do some (undocumented) tricks? Which?
>
> - is the username=NULL and password=NULL parameters to
> InternetConnect() valid for this special purpose despite the
> documentation? I have tried both NULL,NULL and the
> actual values but still authentication fails.
>
> - if InternetOpenUrl() supports NTLM/Kerberos auto-
> authentication, is it possible to make it POST? And
> what is the correct POST format with HttpSendRequest ?
>
> - most important of all, what would be an API function call
> sequence that works?
>
> One more question. What is the purpose of InternetCheckConnection()
> which always seem to return NULL when connected to a LAN.
> Is it supposed to fail unless there is a dialup connection is can
> autoconnect?
> GetLastError() returns 2250 Network connection does not exist.
> Thanks for any ideas and code snipets you can provide.
>
> - Sten
>
>
>
>




Sten Westerback

2004-01-29, 7:34 pm

Hi

I now have a "cleaned" version of the old code that works properly
if i enter my account and password in the code.
But the question is still how, if at all possible, this should be changed
to support automatic logon? I omitted error checking in this post.

hInet=InternetOpen("MyApp", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
hInetURL=InternetOpenUrl(hInet, p_szURL, NULL, 0,
INTERNET_FLAG_KEEP_CONNECTION, 1968);
hInetS=InternetConnect(hInet, "server.site.com", INTERNET_DEFAULT_HTTP_PORT,
"domain\account", "mypassword", INTERNET_SERVICE_HTTP, 0, 1968);
hInetURL=HttpOpenRequest(hInetS, "GET", "/folder/page.asp", "HTTP/1.1",
NULL, "text/*",

INTERNET_FLAG_KEEP_CONNECTION|INTERNET_F
LAG_NO_CACHE_WRITE|INTERNET_FLAG_PRA
GMA_NOCACHE, 1968);
HttpSendRequest(hInetURL, NULL, 0, NULL, 0);
....

I also tried with just "account" and with various combinations of
NULL and "" for the username and password parameters. One
possibility that i didn't yet try would be to use HttpAddRequestHeader
to remove the password (and username) header completely. Or do
i perhaps need to replace "MyApp" with the string used by IE to
make IIS believe it is IE?

I will later make a WinHttp equivalent which might work OK.
But the problem is that at the instance the tool will be used
there is no guarantie that Service Pack 3, which seems to be
a requirement for this, is already installed. But i guess i can use
LoadLibrary to find out if the API is available and if not i could
ask for the password and use the old API (and notify about SP
level). Or would the API's work with SP2?

- Sten

"Sten Westerback" <sten.westerback@NO_SPAMnokia.com> wrote in message
news:bf9Sb.7969$k4.174588@news1.nokia.com...
quote:

>
> "David Wang [Msft]" <someone@online.microsoft.com> wrote in message
> news:Owm5Beg5DHA.1040@TK2MSFTNGP10.phx.gbl...
> work:
>
> Thanks for responding.
>
> The initial purpose of the code is to automatically get a page from
> an server in intranet using my own code in the same way as IE
> does it as you desribed in your response. Later i'm supposed to
> POST a form to another URL in the same server.
>
> Because this trick was suggested in some old news articles
> i read. They claimed that the Internet API function will fail
> the first time but that it would handle the response to authentication
> automatically on the second attempt.
>
> do you mean the p_szBodyData parameter? I have tried it
> being NULL ... but isn't it here where the POST data goes?
>
> Well... in my code it only fails... But IE gladly just give me the html


page
quote:

> without asking anything. ;)
>
> I have also tried without any additional headers (p_szX="") in the
> request. But i suppose that i really would have to add some
> headers but can't figure out which. I have also tried a few other
> ones but i haven't seen any document specifying what IIS requires
> in a request.
>
> That "statement" was based on the fact that autoauthentication
> doesn't seem to be specified anywhere but there are still news
> articles claiming that they have done it (but they don't remember
> how ;).. so it seems that only IE knows how to do it.
>
> all
> I would like to repeat that my code is not IE... ;)
>
> GET's are working perfectly using InternetOpenUrl() but i
> suppose i have to try some other site. The only question is, what
> are you supposed to use as account & password in InternetConnect()
> when you aren't suppose to have to give any?
>
> I hope you mean "enable it on IIS testserver" or "switch to a domain
> protected site" and not "add authentication handshake code yourself"?
>
> SSL is not currently used by this site.
>
> Sure...
>
> One would guess that if IE can then my could should be able to?
>
> I just rechecked these functions after looking at them briefly
> some years ago. I then thought that they were meant primarily for
> use in service code. But i'm delighted to see that they allows NULL
> for the username in WinHTTPSetCredentials(). I'm of to do some
> rewrite now and will report how it goes. Thanks.
>
> - Sten
>
> IIS5
> routine
"text/*",[QUOTE][color=darkred]
> ("handled
szParams);[QUOTE][color=darkred]
>
>




Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com