12.1.2002 NTLM library was released
As far as you are using a connection based on socket (in MFC CSocket a CAsyncSocket class) in your applications and as far as the Microsoft Proxy Server stands in your application with the turned on Windows NT Challenge/Response authentication, your application will probably not be able to be authorize because NTLM authorization is not documented.
In this situation you can use the library ntlm.dll, which provides the above mentioned service. The library exports two functions:
int AuthOne( char* domain, char* host, char* reply );
int AuthTwo( const char* authcode, char* domain, char* host, char* user, char* passwd, char* reply );
The authorization is divided into two steps. Lets give an example. Imagine you would like to download the content of the internet address http://www.geniuz.cz. In the first step you call the function AuthOne with the parameter of domain, where you have the account, for instance "GENIUZDOMAIN" and with the parameter of guest where you want to get, so "www.geniuz.cz". In reply the NTLM code returns which we put as a headline of requirement: Proxy-Authorization: NTLM reply. The whole headline will look as follows:
GET http://www.geniuz.cz:80/ HTTP/1.0
Accept: * / *
Host: www.geniuz.cz:80
Proxy-Connection: keep-alive
Proxy-Authorization: NTLM TlRMTVNTUAABAAAAB7IAAAsACwAtAAAA...
______ empty line
The returning headline looks like this:
Proxy-Authenticate: NTLM TlRMTVNTUAACAAAAFAAUADAAAAA...
The returned NTLM authentification code is called authcode. In this case we call the second exported function AuthTwo with parameter authcode (for example-"TlRMTVNTUAACAAAAFAAUADAAAAA..."), domain "GENIUZDOMAIN", guest in our case www.geniuz.cz, user e.g. "jankral" and password for instance "jan148#ca". In parameter reply function AuthTwo returns the second NTLM code, which we insert in the headline and afterwards the Proxy returns the demanded page.
The library is compiled for OS Windows 32 with or without usage of MFC. Recompilation for other platform than Windows is possible. Furthermore, it is possible to obtain a source code. Please do not hesitate to e-mail me on my address for more information concerning the order of the library.
Library price is 249 EUR
Source code price is 499 EUR
geniuz@geniuz.cz
You can download test program here.
For a better orientation and imagination most of the source code is presented on this case which is using the library ntlm.dll:
//*** ntlm.dll export functions
int AuthOne( char* domain, char* host, char* reply );
int AuthTwo( const char* authcode, char* domain, char* host, char* user, char* passwd, char* reply );
#define MAX_BUFFER_LENGTH 64000
//*** desiderative header line getting
CString GetHeaderStr(CString parsedName, CString header, CString parser = "\r\n", CString spacer = ": ")
{
int index = -1;
parsedName += spacer;
int len = parsedName.GetLength();
int parslen = parser.GetLength();
do index = header.Find( parsedName, index + 1 );
while (( index > 0 ? header.Mid(index-parslen,parslen) != parser : false ));
if( index >= 0 )
{
index += len;
int last = header.Find(parser, index);
if( last < 0 ) return -1;
return header.Mid(index, last - index );
}
else
return "";
}
//*** basic header mask
char header_mask[] =
"GET http://%s:%d/ HTTP/1.0\r\n"
"Accept: * /*\r\n"
"Host: %s:%d\r\n"
"Proxy-Connection: keep-alive\r\n"
"Proxy-Authorization: NTLM %s\r\n"
"\r\n";
//*** socket data sending and receiving
bool SendAndReceive( CSocket& socket, char* proxy, int port, CString& header, char* buffer )
{
if( header.GetLength() != socket.Send( header, header.GetLength() ) )
{
AfxMessageBox( "Send error" );
return false;
}
if( 0 > socket.Receive( buffer, MAX_BUFFER_LENGTH ) )
{
AfxMessageBox( "Receive error" );
return false;
}
return true;
}
//*** NTLM authorization preview
void Ntlm()
{
CString header;
//*** fictive authentication data
char domain[] = "GENIUZDOMAIN";
char user[] = "jankral";
char passwd[] = "jan148#ca";
char host[] = "www.geniuz.cz";
char hostport = 80;
char proxy[] = "PROXY";
char proxyport = 80;
char buffer[ MAX_BUFFER_LENGTH ] = "\x00";
char ntlm[256];
//*** socket creating
CSocket socket;
if( !socket.Create() )
{ AfxMessageBox( "Create error" ); return; }
if( !socket.Connect( proxy, proxyport ) )
{ AfxMessageBox( "Connect error" ); return; }
//*** first ntlm.dll authetication
AuthOne( domain, host, ntlm );
//*** header formating
header.Format( header_mask, host, hostport, host, hostport, ntlm );
//*** header sending and reply receiving
if( !SendAndReceive(socket, proxy, proxyport, header, buffer) ) return;
//*** authentication code getting from returned header
CString response = GetHeaderStr( "Proxy-Authenticate", buffer );
//*** second ntlm.dll authetication
AuthTwo( response.Mid(5), domain, host, user, passwd, ntlm );
//*** header formating
header.Format( header_mask, host, hostport, host, hostport, ntlm );
//*** header sending and reply receiving
if( !SendAndReceive(socket, proxy, proxyport, header, buffer) ) return;
socket.Close();
//*** right page is in buffer
AfxMessageBox( buffer );
}
|