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.
523 lines
15 KiB
523 lines
15 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 <wininet.h>
|
|
|
|
BOOL g_fAllowCustomUI;
|
|
DWORD g_dwConnectFlags;
|
|
BOOL g_fPreload;
|
|
BOOL g_fMonolithicUpload = TRUE;
|
|
LPSTR g_szVerb = NULL;
|
|
|
|
//==============================================================================
|
|
BOOL NeedAuth (HINTERNET hRequest, DWORD *pdwStatus)
|
|
{
|
|
// Get status code.
|
|
DWORD dwStatus;
|
|
DWORD cbStatus = sizeof(dwStatus);
|
|
HttpQueryInfo
|
|
(
|
|
hRequest,
|
|
HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE,
|
|
&dwStatus,
|
|
&cbStatus,
|
|
NULL
|
|
);
|
|
fprintf (stderr, "Status: %d\n", dwStatus);
|
|
*pdwStatus = dwStatus;
|
|
|
|
// Look for 401 or 407.
|
|
DWORD dwFlags;
|
|
switch (dwStatus)
|
|
{
|
|
case HTTP_STATUS_DENIED:
|
|
dwFlags = HTTP_QUERY_WWW_AUTHENTICATE;
|
|
break;
|
|
case HTTP_STATUS_PROXY_AUTH_REQ:
|
|
dwFlags = HTTP_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 = HttpQueryInfo
|
|
(hRequest, dwFlags, szScheme, &cbScheme, &dwIndex);
|
|
if (fRet)
|
|
fprintf (stderr, "Found auth scheme: %s\n", szScheme);
|
|
}
|
|
while (fRet);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
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_INTERNET_LOGIN_FAILURE;
|
|
fprintf (stderr, "Enter Password: ");
|
|
if (!fscanf (stdin, "%s", szPass))
|
|
return ERROR_INTERNET_LOGIN_FAILURE;
|
|
|
|
// Set the values in the handle.
|
|
if (fProxy)
|
|
{
|
|
InternetSetOption
|
|
(hRequest, INTERNET_OPTION_PROXY_USERNAME, szUser, sizeof(szUser));
|
|
InternetSetOption
|
|
(hRequest, INTERNET_OPTION_PROXY_PASSWORD, szPass, sizeof(szPass));
|
|
}
|
|
else
|
|
{
|
|
InternetSetOption
|
|
(hRequest, INTERNET_OPTION_USERNAME, szUser, sizeof(szUser));
|
|
InternetSetOption
|
|
(hRequest, INTERNET_OPTION_PASSWORD, szPass, sizeof(szPass));
|
|
}
|
|
|
|
return ERROR_INTERNET_FORCE_RETRY;
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
int RequestLoop (int argc, char **argv)
|
|
{
|
|
HINTERNET hInternet = NULL;
|
|
HINTERNET hConnect = NULL;
|
|
HINTERNET hRequest = NULL;
|
|
PSTR pPostData = NULL;
|
|
DWORD cbPostData = 0;
|
|
|
|
PSTR pszErr = NULL;
|
|
BOOL fRet;
|
|
|
|
#define CHECK_ERROR(cond, err) if (!(cond)) {pszErr=(err); goto done;}
|
|
|
|
// Parse host:port
|
|
PSTR pszHost = argv[0];
|
|
DWORD dwPort;
|
|
PSTR pszColon = strchr(pszHost, ':');
|
|
if (!pszColon)
|
|
dwPort = INTERNET_INVALID_PORT_NUMBER;
|
|
else
|
|
{
|
|
*pszColon++ = 0;
|
|
dwPort = atol (pszColon);
|
|
}
|
|
|
|
PSTR pszObject = argc >= 2 ? argv[1] : "/";
|
|
PSTR pszUser = argc >= 3 ? argv[2] : NULL;
|
|
PSTR pszPass = argc >= 4 ? argv[3] : NULL;
|
|
PSTR pszPostFile = argc >= 5 ? argv[4] : NULL;
|
|
|
|
if (pszPostFile)
|
|
g_dwConnectFlags |= INTERNET_FLAG_RELOAD;
|
|
|
|
|
|
//#ifdef MONOLITHIC_UPLOAD
|
|
|
|
if(g_fMonolithicUpload)
|
|
{
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
} // g_fMonolithicUpload
|
|
//#endif
|
|
|
|
// Initialize wininet.
|
|
hInternet = InternetOpen
|
|
(
|
|
//"HttpAuth Sample", // user agent
|
|
"Mozilla/4.0 (compatible; MSIE 4.0b2; Windows 95",
|
|
INTERNET_OPEN_TYPE_PRECONFIG, // access type
|
|
NULL, // proxy server
|
|
0, // proxy port
|
|
0 // flags
|
|
);
|
|
CHECK_ERROR (hInternet, "InternetOpen");
|
|
|
|
|
|
// Connect to host.
|
|
hConnect = InternetConnect
|
|
(
|
|
hInternet, // wininet handle,
|
|
pszHost, // host
|
|
(INTERNET_PORT)dwPort, // port
|
|
pszUser, // user
|
|
NULL, // password
|
|
INTERNET_SERVICE_HTTP, // service
|
|
g_dwConnectFlags, // flags
|
|
0 // context
|
|
);
|
|
CHECK_ERROR (hConnect, "InternetConnect");
|
|
|
|
// Use SetOption to set the password since it handles empty strings.
|
|
if (pszPass)
|
|
{
|
|
InternetSetOption
|
|
(hConnect, INTERNET_OPTION_PASSWORD, pszPass, lstrlen(pszPass)+1);
|
|
}
|
|
|
|
if(!g_szVerb)
|
|
{
|
|
if (pszPostFile)
|
|
g_szVerb = "PUT";
|
|
else
|
|
g_szVerb = "GET";
|
|
}
|
|
|
|
// Create request.
|
|
hRequest = HttpOpenRequest
|
|
(
|
|
hConnect, // connect handle
|
|
g_szVerb, // pszPostFile? "PUT" : "GET", // request method
|
|
pszObject, // object name
|
|
NULL, // version
|
|
NULL, // referer
|
|
NULL, // accept types
|
|
g_dwConnectFlags // flags
|
|
| INTERNET_FLAG_KEEP_CONNECTION
|
|
| SECURITY_INTERNET_MASK, // ignore SSL warnings
|
|
0 // context
|
|
);
|
|
CHECK_ERROR (hRequest, "HttpOpenRequest");
|
|
|
|
resend:
|
|
|
|
// if (!pszPostFile || pPostData)
|
|
if (g_fMonolithicUpload)
|
|
{
|
|
// Send request.
|
|
fRet = HttpSendRequest
|
|
(
|
|
hRequest, // request handle
|
|
"", // header string
|
|
0, // header length
|
|
pPostData, // post data
|
|
cbPostData // post length
|
|
);
|
|
}
|
|
else
|
|
{
|
|
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);
|
|
|
|
INTERNET_BUFFERS BufferIn;
|
|
BufferIn.dwStructSize = sizeof( INTERNET_BUFFERSA );
|
|
BufferIn.Next = NULL;
|
|
BufferIn.lpcszHeader = NULL;
|
|
BufferIn.dwHeadersLength = 0;
|
|
BufferIn.dwHeadersTotal = 0;
|
|
BufferIn.lpvBuffer = NULL;
|
|
BufferIn.dwBufferLength = 0;
|
|
BufferIn.dwBufferTotal = cbPostData;
|
|
BufferIn.dwOffsetLow = 0;
|
|
BufferIn.dwOffsetHigh = 0;
|
|
|
|
fRet = HttpSendRequestEx (hRequest, &BufferIn, NULL, 0, 0);
|
|
CHECK_ERROR (fRet, "HttpSendRequestEx");
|
|
|
|
while (1)
|
|
{
|
|
CHAR szTemp[512];
|
|
DWORD cbRead;
|
|
fRet = ReadFile (hf, szTemp, sizeof(szTemp), &cbRead, 0);
|
|
CHECK_ERROR (fRet, "ReadFile");
|
|
|
|
if (!fRet || !cbRead)
|
|
break;
|
|
|
|
DWORD cbRead2;
|
|
fRet = InternetWriteFile (hRequest, szTemp, cbRead, &cbRead2);
|
|
CHECK_ERROR (fRet, "InternetWriteFile");
|
|
}
|
|
|
|
CloseHandle (hf);
|
|
|
|
fRet = HttpEndRequest (hRequest, NULL, 0, 0);
|
|
if (!fRet && GetLastError() == ERROR_INTERNET_FORCE_RETRY)
|
|
goto resend;
|
|
}
|
|
}
|
|
|
|
|
|
DWORD dwStatus;
|
|
|
|
// Check if the status code is 401 or 407
|
|
if (NeedAuth (hRequest, &dwStatus) && (g_fAllowCustomUI))
|
|
{
|
|
// Prompt for username and password.
|
|
if (DoCustomUI (hRequest, dwStatus != HTTP_STATUS_DENIED))
|
|
goto resend;
|
|
}
|
|
else
|
|
{
|
|
DWORD dwSendErr = fRet? ERROR_SUCCESS : GetLastError();
|
|
|
|
DWORD dwDlgErr = InternetErrorDlg(
|
|
GetDesktopWindow(),
|
|
hRequest,
|
|
dwSendErr,
|
|
FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
|
|
FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS |
|
|
FLAGS_ERROR_UI_FLAGS_GENERATE_DATA,
|
|
NULL
|
|
);
|
|
switch (dwSendErr)
|
|
{
|
|
case ERROR_SUCCESS:
|
|
case ERROR_INTERNET_NAME_NOT_RESOLVED:
|
|
case ERROR_INTERNET_CANNOT_CONNECT:
|
|
if (dwDlgErr == ERROR_INTERNET_FORCE_RETRY)
|
|
goto resend;
|
|
else
|
|
break;
|
|
|
|
case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION:
|
|
default:
|
|
if (dwDlgErr == ERROR_SUCCESS)
|
|
goto resend;
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Dump some bytes.
|
|
BYTE bBuf[1024];
|
|
DWORD cbBuf;
|
|
DWORD cbRead;
|
|
cbBuf = sizeof(bBuf);
|
|
_setmode( _fileno( stdout ), _O_BINARY );
|
|
while (InternetReadFile (hRequest, bBuf, cbBuf, &cbRead) && cbRead)
|
|
fwrite (bBuf, 1, cbRead, stdout);
|
|
|
|
done: // Clean up.
|
|
|
|
if (pszErr)
|
|
fprintf (stderr, "Failed on %s, last error %d\n", pszErr, GetLastError());
|
|
if (hRequest)
|
|
InternetCloseHandle (hRequest);
|
|
if (hConnect)
|
|
InternetCloseHandle (hConnect);
|
|
if (hInternet)
|
|
InternetCloseHandle (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)
|
|
{
|
|
g_fAllowCustomUI = 0; //FALSE;
|
|
g_dwConnectFlags = 0;
|
|
HMODULE hmodShlwapi = NULL;
|
|
char * port ;
|
|
// Discard program arg.
|
|
argv++;
|
|
argc--;
|
|
|
|
// Parse options.
|
|
while (argc && argv[0][0] == '-')
|
|
{
|
|
switch (tolower(argv[0][1]))
|
|
{
|
|
case 'c':
|
|
g_fAllowCustomUI = TRUE;
|
|
break;
|
|
|
|
case 's':
|
|
g_dwConnectFlags = INTERNET_FLAG_SECURE;
|
|
break;
|
|
|
|
case 'p':
|
|
g_fPreload = TRUE;
|
|
break;
|
|
|
|
case 'v':
|
|
port = *argv;
|
|
port +=2;
|
|
fprintf(stderr,"Verb: %s\n", port);
|
|
if(port)
|
|
g_szVerb = port;
|
|
break;
|
|
|
|
case 'm':
|
|
g_fMonolithicUpload = TRUE;
|
|
break;
|
|
|
|
default:
|
|
fprintf (stderr, "\nUsage: httpauth [-c] [-s] <server> [<object> [<user> [<pass> [<POST-file>]]]]");
|
|
fprintf (stderr, "\n -c: Custom UI to prompt for user/pass");
|
|
fprintf (stderr, "\n -s: Secure connection (ssl or pct)");
|
|
fprintf (stderr, "\n -m: Monolithic upload");
|
|
fprintf (stderr, "\n -o<port#> : Port Number");
|
|
exit (1);
|
|
}
|
|
|
|
argv++;
|
|
argc--;
|
|
}
|
|
|
|
if (g_fPreload)
|
|
{
|
|
//Get the current directory in case the user selects -p to preload shlwapi from current dir
|
|
char buf[256];
|
|
GetCurrentDirectory((DWORD)256, buf);
|
|
strcat(buf,"\\shlwapi.dll");
|
|
fprintf(stderr, "\nPreloading shlwapi.dll from %s", buf);
|
|
if (!(hmodShlwapi=LoadLibrary(buf))) fprintf(stderr, "\nPreload of shlwapi.dll failed");
|
|
}
|
|
|
|
if (argc)
|
|
RequestLoop (argc, argv);
|
|
|
|
else // Enter command prompt loop
|
|
{
|
|
fprintf (stderr, "\nUsage: <server> [<object> [<user> [<pass> [<POST-file>]]]]");
|
|
fprintf (stderr, "\n quit - exit the command loop");
|
|
fprintf (stderr, "\n flush - flush pwd cache and authenticated sockets");
|
|
|
|
while (1)
|
|
{
|
|
char szIn[1024];
|
|
DWORD argcIn;
|
|
LPSTR argvIn[10];
|
|
|
|
fprintf (stderr, "\nhttpauth> ");
|
|
gets (szIn);
|
|
|
|
if (!lstrcmpi (szIn, "quit"))
|
|
break;
|
|
else if (!lstrcmpi (szIn, "flush"))
|
|
{
|
|
InternetSetOption
|
|
(NULL, INTERNET_OPTION_END_BROWSER_SESSION, NULL, 0);
|
|
continue;
|
|
}
|
|
|
|
argcIn = 0;
|
|
ParseArguments (szIn, argvIn, &argcIn);
|
|
if (!argcIn)
|
|
break;
|
|
RequestLoop (argcIn, argvIn);
|
|
}
|
|
}
|
|
|
|
//unload shlwapi if loaded
|
|
if (hmodShlwapi) FreeLibrary(hmodShlwapi);
|
|
}
|
|
|