1
votes

I have a simple client socket application that I want to access an website with. In order to access the Internet, my client must go through a HTTP proxy server (I'm using Microsoft Forefront Threat Management Gateway). The proxy server requires authentication and it is configured to accept Kerberos via GSSAPI.

In my client, I use Microsoft's SSPI:

First, I call AcquireCredentialsHandle which succeeds and returns SEC_E_OK

Next, I call InitializeSecurityContext which also succeeds and returns SEC_E_OK

So far so good. But now, I need to submit the token to the proxy server for authorization and this is the part that is giving me problems.

If I connect to my proxy server using Internet Explorer, I can watch the packet exchanges via Wireshark. IE negotiates a ticket with Kerberos and appears to submit it via a Proxy-Authorization header. The header contents appear to be base64 encoded.

If I simply take the token that is returned from InitializeSecurityContext, base64 encode it and send the result to the proxy server via a header like Proxy-Authorization: Negotiate <base64Data>, the authentication fails.

I feel like I'm close, but still missing something. One site discussed using EncryptMessage on a token before sending it. Another discussed using Mutual Authentication (I don't think IE is using Mutual Authentication because the client only seems to send authorization once and there is no feedback data from the server (with which to call InitializeSecurityContext a second time) Another site outlined sandwiching the token with different SEC_BUFFER types (padding, data, etc.) and encrypting. I suspect this is what I need to do as I am not finding much documentation on how to do it.

Any insights or suggestions you may have would be appreciated.

UPDATE 7/19/2014: To be clear, I am asking how to use SSPI to calculate the "base64Data" field (as referenced above). While computing the base64 encoding the contents contained in the SECBUFFER_TOKEN's buffer had been my initial guess, the server does not accept the result so it is clearly invalid.

Further research suggests that the token must be "wrapped" (a.k.a. "EncryptMessage" via SSPI) and to encrypt in a manner that is compatible with GSSAPI, three buffers must be used (in the order: SECBUFFER_TOKEN, SECBUFFER_DATA, and SECBUFFER_PADDING) I tried this yesterday, but did not find success.

http://msdn.microsoft.com/en-us/library/ms995352.aspx

http://msdn.microsoft.com/en-us/magazine/cc301890.aspx

1

1 Answers

0
votes

Do you really want to code the proxy interaction yourself? I would rather recommend to use libcurl on Windows. That works fine with TMG here at work.

The reason why your copy and paste does fail is that the accept detects you resend as a reply. Kerberos is replay-proof. You cannot steal a ticket and reuse it.

Consider you have called InitializeSecurityContext and receive on successful call SEC_E_OK a pointer to a SecBufferDesc. You must access the included array, read the PSecBuffer struct, access the pvBuffer element and pass that void* casted to a unsigned char* to a function which converts unsigned char* (hex bytes) to base64 to a char*. Do not forget to pass in cbBuffer length. Then you dont. This is the base64 encoded ticket for your HTTP proxy.

You can use EncryptMessage but not with HTTP. HTTP uses TLS. If you want to use EncryptMessage, use plain sockets. EncryptMessage will transparently encrypt your entire traffic between your client and the server.

Btw: The proxy will return a ticket to IE because I always inquires a mutual auth. You should do the case. Therefore, you must look the init context until you receive OK and not CONTINUE_NEEDED.