Discussion:
HttpSendRequest and authentication
(too old to reply)
Eric
2006-04-04 16:30:45 UTC
Permalink
Hello! I've got a TSP (Telephony Service Provider) that makes a Webservice
call. The code to call the Webservice has been auto-generated by Visual
Studio (uses WinINet, atlsoap.h, etc.). The problem is that on one machine
HttpSendRequest (within atlsoap.h) receives a 401 error and later in my code
I get an E_FAIL result. The thread that makes the call runs under a specific
user account, because I expect an NTLM auto-login. When I try the same code
with the same user account on another machine, it works. There are no
differences on the Webservice side based on the IP address or so. Using a
network analyzer I've seen that on the machine where it works the protocol
looks just fine (first anonymous call, answer 401 with NTLM support, second
call with NTLMSSP_NEGOTIATE, answer 401 with NTLMSSP_CHALLENGE, third call
with NTLMSSP_AUTH, with answer 200 OK). On the machine where it doesn't work
it looks like this: first anonymous call, answer 401 with NTLM support. But
no continuation. Both machines have same cookie-settings in IE, same proxy
settings in IE, same settings for auto-logon in intranet in IE.
Questions:
- How does the automatic logon procedure work within HttpSendRequest (there
is no code that calls HttpSendRequest a second time)?
- Why doesn't it even try to connect with NTLM?
- Any other ideas what I could check about what the difference on the two
machines is?
- Other suggestions?
Eric
Scherbina Vladimir
2006-04-05 09:54:33 UTC
Permalink
Eric,

AFAIR wininet api cannot be used when impersonating user, for this winhttp
is the right choice.
--
Vladimir
http://spaces.msn.com/vladimir-scherbina/
Post by Eric
Hello! I've got a TSP (Telephony Service Provider) that makes a Webservice
call. The code to call the Webservice has been auto-generated by Visual
Studio (uses WinINet, atlsoap.h, etc.). The problem is that on one machine
HttpSendRequest (within atlsoap.h) receives a 401 error and later in my
code I get an E_FAIL result. The thread that makes the call runs under a
specific user account, because I expect an NTLM auto-login. When I try the
same code with the same user account on another machine, it works. There
are no differences on the Webservice side based on the IP address or so.
Using a network analyzer I've seen that on the machine where it works the
protocol looks just fine (first anonymous call, answer 401 with NTLM
support, second call with NTLMSSP_NEGOTIATE, answer 401 with
NTLMSSP_CHALLENGE, third call with NTLMSSP_AUTH, with answer 200 OK). On
the machine where it doesn't work it looks like this: first anonymous
call, answer 401 with NTLM support. But no continuation. Both machines
have same cookie-settings in IE, same proxy settings in IE, same settings
for auto-logon in intranet in IE.
- How does the automatic logon procedure work within HttpSendRequest
(there is no code that calls HttpSendRequest a second time)?
- Why doesn't it even try to connect with NTLM?
- Any other ideas what I could check about what the difference on the two
machines is?
- Other suggestions?
Eric
Eric
2006-04-05 13:25:39 UTC
Permalink
Hi Vladimir! Thanks for your response!
I cannot find much documentation, but indeed Microsoft says somewhere
"...porting your WinINet application to WinHTTP....would benefit
from...Support for thread impersonation...".
Although I don't understand why there can be a problem. Or does this only
mean the API supports directly changing the user? If I start a new thread
and set the thread token to another user, why should WinINet have problems
with that? And why does it work on one machine and not on another?
You're suggesting that I convert my application from WinINet to WinHTTP.
Well, that would be a good idea, but I haven't written a single line of code
in WinINet. Everything has been generated by Visual Studio by clicking on
the project and selecting "Add Web Reference". The generated code uses
atlsoap.h which is also quite big (and buggy) and contains all the API
calls. I think it would be a lot of work to write a WebService call (SOAP
Request) all from scratch for WinHTTP. Don't you think?

Eric
Post by Scherbina Vladimir
Eric,
AFAIR wininet api cannot be used when impersonating user, for this winhttp
is the right choice.
--
Vladimir
http://spaces.msn.com/vladimir-scherbina/
Scherbina Vladimir
2006-04-05 13:52:40 UTC
Permalink
Eric,

I have never seen calling web services via wininet, so that's why I was
thinking the code was written by hands and porting to winhttp would be
easially.

OK, let's choose another way, what is the OS where code fails? Does it work
properly on the same OS on different machine? What is software installed on
machines? Does machine where the problem occures uses firewall?

You can post here the snippet of code to allow us analyze it and tell for
sure what's wrong with using wininet API
--
Vladimir
manage content: http://www.infostoria.com/
blog: http://spaces.msn.com/vladimir-scherbina/
Eric
2006-04-05 17:40:23 UTC
Permalink
Hi Vladimir, thanks for answering!
- "never seen calling web services via wininet": How have you seen it then?
If Visual Studio only supports WinInet directly by generating code for it, I
think most other users have done this too. Or have all the people written
this code by theirself?
- Same OS (Win2003 Server used as a client), almost similar software
installed, both in same network inside of our company's firewall (including
WebService), same relevant IE settings, etc. I cannot see any difference.
- code snippet:
RPC_STATUS rpcRet=RpcImpersonateClient(0);
if(rpcRet==RPC_S_OK){
//init COM
HRESULT hResult=CoInitialize(NULL);
if(SUCCEEDED(hResult)){
{ // ConnectWs encapsulate
//launch the webservice
Dial::CDialT<WEBSERVICE_PROTOCOL> DialWs;

DialWs.SetUrl(L"http://myurl_goes_here/Dial.asmx");

int nResult=0;
hResult=DialWs.OpenCall(L"270", _bstr_t(L"295"), &nResult);
if(SUCCEEDED(hResult))
hResult=LINEERR_SUCCESS;
DialWs.Cleanup();
DialWs.SetUrl(_T("dummy")); // calls CloseAll (to prevent resource leak)
} // ensure ConnectWs is destructed before CoUninitialize
CoUninitialize(); //unload COM
}
::RpcRevertToSelf(); // ignore any return codes
}

I've been debugging this TSP for many weeks now and this problem is only one
of many problems I face (I've got currently two Microsoft support incidents
open). Your idea to rewrite everything to support WinHTTP isn't a bad idea.
I think I'll try this too. I think I'll be faster than researching every
Microsoft bug, especially if WinHTTP supports server-side components better
and is better documented.

Regards,
Eric
Scherbina Vladimir
2006-04-06 11:51:15 UTC
Permalink
Hello there, Eric!
Post by Eric
Hi Vladimir, thanks for answering!
- "never seen calling web services via wininet": How have you seen it then?
I just did not payed attention to unmanaged way of calling webservices, Java
& C# is enought for me :)
Post by Eric
If Visual Studio only supports WinInet directly by generating code for it,
I think most other users have done this too. Or have all the people
written this code by theirself?
Most likely the people uses this feature from time to time
Post by Eric
- Same OS (Win2003 Server used as a client), almost similar software
installed, both in same network inside of our company's firewall
(including WebService), same relevant IE settings, etc. I cannot see any
difference.
RPC_STATUS rpcRet=RpcImpersonateClient(0);
if(rpcRet==RPC_S_OK){
//init COM
HRESULT hResult=CoInitialize(NULL);
if(SUCCEEDED(hResult)){
{ // ConnectWs encapsulate
//launch the webservice
Dial::CDialT<WEBSERVICE_PROTOCOL> DialWs;
DialWs.SetUrl(L"http://myurl_goes_here/Dial.asmx");
int nResult=0;
hResult=DialWs.OpenCall(L"270", _bstr_t(L"295"), &nResult);
if(SUCCEEDED(hResult))
hResult=LINEERR_SUCCESS;
DialWs.Cleanup();
DialWs.SetUrl(_T("dummy")); // calls CloseAll (to prevent resource leak)
} // ensure ConnectWs is destructed before CoUninitialize
CoUninitialize(); //unload COM
}
::RpcRevertToSelf(); // ignore any return codes
}
I've been debugging this TSP for many weeks now and this problem is only
one of many problems I face (I've got currently two Microsoft support
incidents open). Your idea to rewrite everything to support WinHTTP isn't
a bad idea. I think I'll try this too. I think I'll be faster than
researching every Microsoft bug, especially if WinHTTP supports
server-side components better and is better documented.
Regards,
Eric
just a hint, when you get E_FAIL what is the return value of GetLastError ?
--
Vladimir
manage content: http://www.infostoria.com/
blog: http://spaces.msn.com/vladimir-scherbina/
Eric
2006-04-10 09:37:55 UTC
Permalink
Hi! Thanks for your answer.

- Ok, with managed code it is easy. Sorry, I forgot this completely, because
I cannot use managed code within a TSP (or it would make it more difficult).
- GetLastError: I didn't try that, but because I can step into all the code
(in atlsoap.h etc.) I think I knew what exact error code was causing to
return E_FAIL, but it didn't help.

Current situation is: I'm writing all Webservice access new (from scratch)
to use WinHTTP. First tests were successful. This was a good hint from you.
Thanks again. Although this is a lot of work, I think this is the correct
approach to avoid all these problems. It's a shame that the newest Visual
Studio 2005 doesn't support WinHTTP WebService connections when
auto-generating an interface. I've filed this on MSDN Suggestions. Please
vote for this suggestion there if you think it's important. Link:
http://lab.msdn.microsoft.com/ProductFeedback/viewfeedback.aspx?feedbackid=44629cc4-a620-4e83-aaea-d69a8bd4af47

Eric
Scherbina Vladimir
2006-04-10 10:08:51 UTC
Permalink
Glad to hear that I helped you with advice. OK, I will take a look at that
suggestion later.
--
Vladimir
manage content: http://www.infostoria.com/
blog: http://spaces.msn.com/vladimir-scherbina/
Post by Eric
Hi! Thanks for your answer.
- Ok, with managed code it is easy. Sorry, I forgot this completely,
because I cannot use managed code within a TSP (or it would make it more
difficult).
- GetLastError: I didn't try that, but because I can step into all the
code (in atlsoap.h etc.) I think I knew what exact error code was causing
to return E_FAIL, but it didn't help.
Current situation is: I'm writing all Webservice access new (from scratch)
to use WinHTTP. First tests were successful. This was a good hint from
you. Thanks again. Although this is a lot of work, I think this is the
correct approach to avoid all these problems. It's a shame that the newest
Visual Studio 2005 doesn't support WinHTTP WebService connections when
auto-generating an interface. I've filed this on MSDN Suggestions. Please
http://lab.msdn.microsoft.com/ProductFeedback/viewfeedback.aspx?feedbackid=44629cc4-a620-4e83-aaea-d69a8bd4af47
Eric
Scherbina Vladimir
2006-04-12 10:12:48 UTC
Permalink
another way is to use another web services provider: take a look at:
http://sourceforge.net/projects/gsoap2
--
Vladimir
manage content: http://www.infostoria.com/
blog: http://spaces.msn.com/vladimir-scherbina/
Loading...