You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
595 lines
17 KiB
595 lines
17 KiB
// ===========================================================================
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright 1996 Microsoft Corporation. All Rights Reserved.
|
|
// ===========================================================================
|
|
#include <windows.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <io.h>
|
|
#include <winhttp.h>
|
|
#define _UNICODE
|
|
#include <tchar.h>
|
|
|
|
//==============================================================================
|
|
BOOL NeedAuth (HINTERNET hRequest, DWORD dwStatus)
|
|
{
|
|
// Look for 401 or 407.
|
|
DWORD dwFlags;
|
|
switch (dwStatus)
|
|
{
|
|
case HTTP_STATUS_DENIED:
|
|
dwFlags = WINHTTP_QUERY_WWW_AUTHENTICATE;
|
|
break;
|
|
case HTTP_STATUS_PROXY_AUTH_REQ:
|
|
dwFlags = WINHTTP_QUERY_PROXY_AUTHENTICATE;
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
// Enumerate the authentication types.
|
|
BOOL fRet;
|
|
char szScheme[64];
|
|
DWORD dwIndex = 0;
|
|
do
|
|
{
|
|
DWORD cbScheme = sizeof(szScheme);
|
|
fRet = WinHttpQueryHeaders
|
|
(hRequest, dwFlags, NULL, szScheme, &cbScheme, &dwIndex);
|
|
if (fRet)
|
|
fprintf (stderr, "Found auth scheme: %s\n", szScheme);
|
|
}
|
|
while (fRet);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//==============================================================================
|
|
BOOL PromptForCreds (HINTERNET hRequest, DWORD dwTarget, LPVOID pAuthParams)
|
|
{
|
|
DWORD dwScheme = 0;
|
|
|
|
char szScheme[16];
|
|
|
|
fprintf (stderr, "Enter Scheme : ");
|
|
if (!fscanf (stdin, "%s", szScheme))
|
|
return FALSE;
|
|
if (!_stricmp(szScheme, "Basic"))
|
|
{
|
|
dwScheme = WINHTTP_AUTH_SCHEME_BASIC;
|
|
}
|
|
else if (!_stricmp(szScheme, "Digest"))
|
|
{
|
|
dwScheme = WINHTTP_AUTH_SCHEME_DIGEST;
|
|
}
|
|
else if (!_stricmp(szScheme, "NTLM"))
|
|
{
|
|
dwScheme = WINHTTP_AUTH_SCHEME_NTLM;
|
|
}
|
|
else if (!_stricmp(szScheme, "Negotiate"))
|
|
{
|
|
dwScheme = WINHTTP_AUTH_SCHEME_NEGOTIATE;
|
|
}
|
|
else if (!_stricmp(szScheme, "Passport1.4"))
|
|
{
|
|
dwScheme = WINHTTP_AUTH_SCHEME_PASSPORT;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Prompt username and password.
|
|
|
|
char szUser[64], szPass[64];
|
|
PWCHAR pwszUser = NULL;
|
|
WCHAR wszUser[128];
|
|
PWCHAR pwszPass = NULL;
|
|
WCHAR wszPass[128];
|
|
|
|
fprintf (stderr, "Enter Username: ");
|
|
if (!fscanf (stdin, "%s", szUser))
|
|
return FALSE;
|
|
|
|
if (_stricmp(szUser, "default"))
|
|
{
|
|
::MultiByteToWideChar(CP_ACP, 0, szUser, -1, &wszUser[0], 128);
|
|
pwszUser = &wszUser[0];
|
|
|
|
fprintf (stderr, "Enter Password: ");
|
|
if (!fscanf (stdin, "%s", szPass))
|
|
return FALSE;
|
|
|
|
::MultiByteToWideChar(CP_ACP, 0, szPass, -1, &wszPass[0], 128);
|
|
pwszPass = &wszPass[0];
|
|
}
|
|
|
|
|
|
DWORD dw_ret = WinHttpSetCredentials(hRequest,
|
|
dwTarget, dwScheme,
|
|
pwszUser, pwszPass, pAuthParams);
|
|
|
|
return dw_ret;
|
|
}
|
|
|
|
//==============================================================================
|
|
DWORD DoCustomUI (HINTERNET hRequest, BOOL fProxy)
|
|
{
|
|
// Prompt for username and password.
|
|
char szUser[64], szPass[64];
|
|
fprintf (stderr, "Enter Username: ");
|
|
if (!fscanf (stdin, "%s", szUser))
|
|
return ERROR_WINHTTP_LOGIN_FAILURE;
|
|
|
|
if (!_stricmp(szUser, "default"))
|
|
{
|
|
return ERROR_WINHTTP_RESEND_REQUEST;
|
|
}
|
|
|
|
fprintf (stderr, "Enter Password: ");
|
|
if (!fscanf (stdin, "%s", szPass))
|
|
return ERROR_WINHTTP_LOGIN_FAILURE;
|
|
|
|
WCHAR wszUser[128], wszPass[128];
|
|
::MultiByteToWideChar(CP_ACP, 0, szUser, -1, &wszUser[0], 128);
|
|
::MultiByteToWideChar(CP_ACP, 0, szPass, -1, &wszPass[0], 128);
|
|
|
|
// Set the values in the handle.
|
|
if (fProxy)
|
|
{
|
|
WinHttpSetOption
|
|
(hRequest, WINHTTP_OPTION_PROXY_USERNAME, wszUser, sizeof(wszUser));
|
|
WinHttpSetOption
|
|
(hRequest, WINHTTP_OPTION_PROXY_PASSWORD, wszPass, sizeof(wszPass));
|
|
}
|
|
else
|
|
{
|
|
WinHttpSetOption
|
|
(hRequest, WINHTTP_OPTION_USERNAME, wszUser, sizeof(wszUser));
|
|
WinHttpSetOption
|
|
(hRequest, WINHTTP_OPTION_PASSWORD, wszPass, sizeof(wszPass));
|
|
}
|
|
|
|
return ERROR_WINHTTP_RESEND_REQUEST;
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
int RequestLoop (int argc, char **argv)
|
|
{
|
|
HINTERNET hInternet = NULL;
|
|
HINTERNET hConnect = NULL;
|
|
HINTERNET hRequest = NULL;
|
|
|
|
DWORD dwAccessType = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
|
|
WCHAR szProxyServer[256];
|
|
WCHAR szProxyBypass[256];
|
|
|
|
DWORD dwConnectFlags = 0;
|
|
BOOL fPreAuth = FALSE;
|
|
|
|
PSTR pPostData = NULL;
|
|
DWORD cbPostData = 0;
|
|
|
|
PSTR pszErr = NULL;
|
|
BOOL fRet;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
DWORD dwTarget = WINHTTP_AUTH_TARGET_SERVER;
|
|
LPVOID pAuthParams = NULL;
|
|
|
|
|
|
#define CHECK_ERROR(cond, err) if (!(cond)) {pszErr=(err); goto done;}
|
|
|
|
// Parse options.
|
|
while (argc && argv[0][0] == '-')
|
|
{
|
|
switch (tolower(argv[0][1]))
|
|
{
|
|
case 'p':
|
|
dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
|
|
dwTarget = WINHTTP_AUTH_TARGET_PROXY;
|
|
::MultiByteToWideChar(CP_ACP, 0, argv[1], -1, &szProxyServer[0], 256);
|
|
// pszProxyServer = argv[1];
|
|
::MultiByteToWideChar(CP_ACP, 0, "<local>", -1, &szProxyBypass[0], 256);
|
|
// pszProxyBypass = "<local>";
|
|
argv++;
|
|
argc--;
|
|
break;
|
|
|
|
case 's':
|
|
dwConnectFlags = WINHTTP_FLAG_SECURE;
|
|
break;
|
|
|
|
case 'a':
|
|
fPreAuth = TRUE;
|
|
break;
|
|
|
|
default:
|
|
fprintf (stderr, "\nUsage: httpauth [-p <proxy>] [-s] <server> [<object> [<user> [<pass> [<POST-file>]]]]");
|
|
fprintf (stderr, "\n -s: Secure connection (ssl or pct)");
|
|
fprintf (stderr, "\n -p: specify proxy server. (\"<local>\" assumed for bypass.)");
|
|
exit (1);
|
|
}
|
|
|
|
argv++;
|
|
argc--;
|
|
}
|
|
|
|
// Parse host:port
|
|
PSTR pszHost = argv[0];
|
|
DWORD dwPort;
|
|
PSTR pszColon = strchr(pszHost, ':');
|
|
if (!pszColon)
|
|
dwPort = INTERNET_DEFAULT_PORT;
|
|
else
|
|
{
|
|
*pszColon++ = 0;
|
|
dwPort = atol (pszColon);
|
|
}
|
|
|
|
PSTR pszObject = argc >= 2 ? argv[1] : "/";
|
|
PSTR pszPostFile = argc >= 3 ? argv[2] : NULL;
|
|
|
|
// Read any POST data into a buffer.
|
|
if (pszPostFile)
|
|
{
|
|
HANDLE hf =
|
|
CreateFile
|
|
(
|
|
pszPostFile,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
|
|
NULL
|
|
);
|
|
if (hf != INVALID_HANDLE_VALUE)
|
|
{
|
|
cbPostData = GetFileSize (hf, NULL);
|
|
pPostData = (PSTR) LocalAlloc (LMEM_FIXED, cbPostData + 1);
|
|
if (pPostData)
|
|
ReadFile (hf, pPostData, cbPostData, &cbPostData, NULL);
|
|
pPostData[cbPostData] = 0;
|
|
CloseHandle (hf);
|
|
}
|
|
}
|
|
|
|
// Initialize wininet.
|
|
hInternet = WinHttpOpen
|
|
(
|
|
_T("HttpAuth Sample"), // user agent
|
|
// "Mozilla/4.0 (compatible; MSIE 4.0b2; Windows 95",
|
|
dwAccessType, // access type
|
|
NULL, // szProxyServer, // proxy server
|
|
NULL, // szProxyBypass, // proxy bypass
|
|
0 // flags
|
|
);
|
|
CHECK_ERROR (hInternet, "WinHttpOpen");
|
|
|
|
|
|
WCHAR szHost[256];
|
|
::MultiByteToWideChar(CP_ACP, 0, pszHost, -1, &szHost[0], 256);
|
|
|
|
// Connect to host.
|
|
hConnect = WinHttpConnect
|
|
(
|
|
hInternet, // session handle,
|
|
szHost, // host
|
|
(INTERNET_PORT) dwPort, // port
|
|
0 // flags
|
|
);
|
|
CHECK_ERROR (hConnect, "WinHttpConnect");
|
|
|
|
WCHAR szObject[256];
|
|
::MultiByteToWideChar(CP_ACP, 0, pszObject, -1, &szObject[0], 256);
|
|
|
|
// Create request.
|
|
hRequest = WinHttpOpenRequest
|
|
(
|
|
hConnect, // connect handle
|
|
pszPostFile? _T("POST") : _T("GET"), // request method
|
|
szObject, // object name
|
|
NULL, // version
|
|
NULL, // referer
|
|
NULL, // accept types
|
|
dwConnectFlags // flags
|
|
);
|
|
CHECK_ERROR (hRequest, "WinHttpOpenRequest");
|
|
|
|
if (fPreAuth)
|
|
{
|
|
fprintf (stderr, "Pre Authenticating...\n");
|
|
fprintf (stderr, "(Scheme = Basic, Digest, NTLM, Negotiate, or Passport1.4)\n");
|
|
PromptForCreds(hRequest, dwTarget, pAuthParams);
|
|
}
|
|
|
|
resend:
|
|
|
|
// Send request.
|
|
fRet = WinHttpSendRequest
|
|
(
|
|
hRequest, // request handle
|
|
_T(""), // header string
|
|
0, // header length
|
|
pPostData, // post data
|
|
cbPostData, // post data length
|
|
cbPostData, // total post length
|
|
0 // context
|
|
);
|
|
|
|
if (!fRet)
|
|
{
|
|
dwErr = GetLastError();
|
|
switch (dwErr)
|
|
{
|
|
case ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED:
|
|
break;
|
|
|
|
default:
|
|
printf ("HttpSendRequest failed err=%d\n", dwErr);
|
|
}
|
|
goto done;
|
|
}
|
|
else
|
|
{
|
|
fRet = WinHttpReceiveResponse(hRequest, NULL);
|
|
if (!fRet)
|
|
{
|
|
dwErr = GetLastError();
|
|
fprintf (stderr, "WinHttpReceiveResponse failed err=%d\n", dwErr);
|
|
// pContext->state = HTTP_SEND_FAIL_SYNC;
|
|
}
|
|
// goto sync;
|
|
}
|
|
|
|
// Get status code.
|
|
DWORD dwStatus, cbStatus;
|
|
cbStatus = sizeof(dwStatus);
|
|
WinHttpQueryHeaders
|
|
(
|
|
hRequest,
|
|
WINHTTP_QUERY_FLAG_NUMBER | WINHTTP_QUERY_STATUS_CODE,
|
|
WINHTTP_HEADER_NAME_BY_INDEX,
|
|
&dwStatus,
|
|
&cbStatus,
|
|
NULL
|
|
);
|
|
fprintf (stderr, "Status: %d\n", dwStatus);
|
|
|
|
// Check if the status code is 401 or 407
|
|
if (NeedAuth (hRequest, dwStatus))
|
|
{
|
|
char szChoice[16];
|
|
|
|
fprintf (stderr, "Set Credentials or Set Options? (C/O): ");
|
|
if (!fscanf (stdin, "%s", szChoice))
|
|
return FALSE;
|
|
|
|
if (!_stricmp(szChoice, "C"))
|
|
{
|
|
DWORD AllSchemes;
|
|
DWORD GoodScheme;
|
|
DWORD AuthTarget;
|
|
if (WinHttpQueryAuthSchemes(hRequest, &AllSchemes, &GoodScheme, &AuthTarget) != FALSE)
|
|
{
|
|
fprintf (stderr, "Proposed Schemes -> ");
|
|
if (AllSchemes & WINHTTP_AUTH_SCHEME_BASIC)
|
|
{
|
|
fprintf (stderr, "Basic ");
|
|
}
|
|
if (AllSchemes & WINHTTP_AUTH_SCHEME_DIGEST)
|
|
{
|
|
fprintf (stderr, "Digest ");
|
|
}
|
|
if (AllSchemes & WINHTTP_AUTH_SCHEME_NTLM)
|
|
{
|
|
fprintf (stderr, "NTLM ");
|
|
}
|
|
if (AllSchemes & WINHTTP_AUTH_SCHEME_NEGOTIATE)
|
|
{
|
|
fprintf (stderr, "Negotiate ");
|
|
}
|
|
if (AllSchemes & WINHTTP_AUTH_SCHEME_PASSPORT)
|
|
{
|
|
fprintf (stderr, "Passport1.4 ");
|
|
}
|
|
|
|
fprintf (stderr, "\n");
|
|
|
|
fprintf (stderr, "Preferred Schemes -> ");
|
|
if (GoodScheme == WINHTTP_AUTH_SCHEME_BASIC)
|
|
{
|
|
fprintf (stderr, "Basic ");
|
|
}
|
|
else if (GoodScheme == WINHTTP_AUTH_SCHEME_DIGEST)
|
|
{
|
|
fprintf (stderr, "Digest ");
|
|
}
|
|
else if (GoodScheme == WINHTTP_AUTH_SCHEME_NTLM)
|
|
{
|
|
fprintf (stderr, "NTLM ");
|
|
}
|
|
else if (GoodScheme == WINHTTP_AUTH_SCHEME_NEGOTIATE)
|
|
{
|
|
fprintf (stderr, "Negotiate ");
|
|
}
|
|
else if (GoodScheme == WINHTTP_AUTH_SCHEME_PASSPORT)
|
|
{
|
|
fprintf (stderr, "Passport1.4 ");
|
|
}
|
|
else
|
|
{
|
|
fprintf (stderr, "*Unknown* ");
|
|
}
|
|
|
|
fprintf (stderr, "\n");
|
|
|
|
fprintf (stderr, "Auth Target -> ");
|
|
if (AuthTarget == WINHTTP_AUTH_TARGET_PROXY)
|
|
{
|
|
fprintf (stderr, "Proxy ");
|
|
}
|
|
else if (AuthTarget == WINHTTP_AUTH_TARGET_SERVER)
|
|
{
|
|
fprintf (stderr, "Server ");
|
|
}
|
|
else
|
|
{
|
|
fprintf (stderr, "*Unknown* ");
|
|
}
|
|
|
|
fprintf (stderr, "\n");
|
|
|
|
// WinHttpQueryAuthParams(hRequest, GoodScheme, &pAuthParams);
|
|
|
|
if (PromptForCreds(hRequest, AuthTarget, pAuthParams) != FALSE)
|
|
goto resend;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf (stderr, "*You are using legacy WinHttp functionalities!*\n");
|
|
|
|
// Prompt for username and password.
|
|
if (DoCustomUI (hRequest, dwStatus != HTTP_STATUS_DENIED))
|
|
goto resend;
|
|
}
|
|
}
|
|
|
|
// Dump some bytes.
|
|
BYTE bBuf[1024];
|
|
DWORD cbBuf;
|
|
DWORD cbRead;
|
|
_setmode( _fileno( stdout ), _O_BINARY );
|
|
|
|
// #define QDA
|
|
#ifdef QDA
|
|
while (WinHttpQueryDataAvailable (hRequest, &cbRead) && cbRead)
|
|
{
|
|
cbBuf = cbRead > sizeof(bBuf)? sizeof(bBuf) : cbRead;
|
|
WinHttpReadData(hRequest, bBuf, cbRead, &cbRead);
|
|
fwrite (bBuf, 1, cbRead, stdout);
|
|
}
|
|
#else
|
|
cbBuf = sizeof(bBuf);
|
|
while (WinHttpReadData (hRequest, bBuf, cbBuf, &cbRead) && cbRead)
|
|
fwrite (bBuf, 1, cbRead, stdout);
|
|
#endif
|
|
|
|
done: // Clean up.
|
|
|
|
if (pszErr)
|
|
fprintf (stderr, "Failed on %s, last error %d\n", pszErr, GetLastError());
|
|
if (hRequest)
|
|
WinHttpCloseHandle (hRequest);
|
|
if (hConnect)
|
|
WinHttpCloseHandle (hConnect);
|
|
if (hInternet)
|
|
WinHttpCloseHandle (hInternet);
|
|
if (pPostData)
|
|
LocalFree (pPostData);
|
|
return 0;
|
|
}
|
|
|
|
//==============================================================================
|
|
void ParseArguments
|
|
(
|
|
LPSTR InBuffer,
|
|
LPSTR* CArgv,
|
|
DWORD* CArgc
|
|
)
|
|
{
|
|
LPSTR CurrentPtr = InBuffer;
|
|
DWORD i = 0;
|
|
DWORD Cnt = 0;
|
|
|
|
for ( ;; ) {
|
|
|
|
//
|
|
// skip blanks.
|
|
//
|
|
|
|
while( *CurrentPtr == ' ' ) {
|
|
CurrentPtr++;
|
|
}
|
|
|
|
if( *CurrentPtr == '\0' ) {
|
|
break;
|
|
}
|
|
|
|
CArgv[i++] = CurrentPtr;
|
|
|
|
//
|
|
// go to next space.
|
|
//
|
|
|
|
while( (*CurrentPtr != '\0') &&
|
|
(*CurrentPtr != '\n') ) {
|
|
if( *CurrentPtr == '"' ) { // Deal with simple quoted args
|
|
if( Cnt == 0 )
|
|
CArgv[i-1] = ++CurrentPtr; // Set arg to after quote
|
|
else
|
|
*CurrentPtr = '\0'; // Remove end quote
|
|
Cnt = !Cnt;
|
|
}
|
|
if( (Cnt == 0) && (*CurrentPtr == ' ') || // If we hit a space and no quotes yet we are done with this arg
|
|
(*CurrentPtr == '\0') )
|
|
break;
|
|
CurrentPtr++;
|
|
}
|
|
|
|
if( *CurrentPtr == '\0' ) {
|
|
break;
|
|
}
|
|
|
|
*CurrentPtr++ = '\0';
|
|
}
|
|
|
|
*CArgc = i;
|
|
return;
|
|
}
|
|
|
|
//==============================================================================
|
|
int __cdecl main (int argc, char **argv)
|
|
{
|
|
char * port ;
|
|
// Discard program arg.
|
|
argv++;
|
|
argc--;
|
|
|
|
if (argc)
|
|
RequestLoop (argc, argv);
|
|
|
|
else // Enter command prompt loop
|
|
{
|
|
fprintf (stderr, "\nUsage: [-p <proxy>] [-s] <host>[:port] [<object> [<POST-file>]]");
|
|
fprintf (stderr, "\n -s: use secure sockets layer");
|
|
fprintf (stderr, "\n -p: specify proxy server. (\"<local>\" assumed for bypass.)");
|
|
fprintf (stderr, "\nTo exit input loop, enter no params");
|
|
|
|
while (1)
|
|
{
|
|
char szIn[1024];
|
|
DWORD argcIn;
|
|
LPSTR argvIn[10];
|
|
|
|
fprintf (stderr, "\nhttpauth> ");
|
|
gets (szIn);
|
|
|
|
argcIn = 0;
|
|
ParseArguments (szIn, argvIn, &argcIn);
|
|
if (!argcIn)
|
|
break;
|
|
RequestLoop (argcIn, argvIn);
|
|
}
|
|
}
|
|
}
|
|
|