2025-11-28 00:35:46 +09:00

294 lines
8.3 KiB
C++

// ===========================================================================
// 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 2000 Microsoft Corporation. All Rights Reserved.
// ===========================================================================
#define STRSAFE_WITH_GETS
#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <wininet.h>
#include <strsafe.h>
//==============================================================================
#define CHECK_ERROR(_cond, _err) \
do {if (!(_cond)) {pszErr=(_err); goto Done;}} while (FALSE, FALSE)
BOOL NeedAuth(
HINTERNET hRequest)
{
DWORD dwStatus = 0;
DWORD cbStatus = sizeof(dwStatus);
DWORD dwFlags = 0;
BOOL fRet = FALSE;
DWORD cbScheme = 0;
char szScheme[64] = {};
DWORD dwIndex = 0;
// Get status code.
HttpQueryInfo(hRequest,
HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE,
&dwStatus,
&cbStatus,
NULL);
fprintf(stderr, "Status: %d\n", dwStatus);
// Look for 401 or 407.
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:
fRet = FALSE;
goto Done;
}
// Enumerate the authentication types.
do
{
cbScheme = sizeof(szScheme);
fRet = HttpQueryInfo(hRequest, dwFlags, szScheme, &cbScheme, &dwIndex);
if (fRet)
{
fprintf(stderr, "Found auth scheme: %s\n", szScheme);
}
}
while (fRet);
Done:
return fRet;
}
//==============================================================================
DWORD DoCustomUI(
HINTERNET hConnect,
HINTERNET hRequest)
{
DWORD dwError = ERROR_SUCCESS;
char szUser[64] = {};
char szPass[64] = {};
BYTE rgbBuf[1024];
DWORD cbBuf = sizeof(rgbBuf);
DWORD cbRead = 0;
// Prompt for username and password.
fprintf(stderr, "Enter Username: ");
if (FAILED(StringCchGetsA(szUser, ARRAYSIZE(szUser))))
{
dwError = ERROR_INTERNET_LOGIN_FAILURE;
goto Done;
}
fprintf(stderr, "Enter Password: ");
if (FAILED(StringCchGetsA(szPass, ARRAYSIZE(szUser))))
{
dwError = ERROR_INTERNET_LOGIN_FAILURE;
goto Done;
}
// Set the values in the handle.
InternetSetOption(hConnect, INTERNET_OPTION_USERNAME, szUser, sizeof(szUser));
InternetSetOption(hConnect, INTERNET_OPTION_PASSWORD, szPass, sizeof(szPass));
// Drain the socket.
while (InternetReadFile(hRequest, rgbBuf, cbBuf, &cbRead))
{
if (cbRead == 0)
{
break;
}
}
dwError = ERROR_INTERNET_FORCE_RETRY;
Done:
return dwError;
}
//==============================================================================
int main(
int argc,
char **argv)
{
BOOL fRet = FALSE;
PSTR pszErr = NULL;
DWORD dwError = ERROR_SUCCESS;
BOOL fAllowCustomUI = FALSE;
HINTERNET hInternet = NULL;
HINTERNET hConnect = NULL;
HINTERNET hRequest = NULL;
PSTR pszHost = NULL;
PSTR pszObject = NULL;
PSTR pszUser = NULL;
PSTR pszPass = NULL;
BYTE rgbBuf[1024];
DWORD cbBuf = sizeof(rgbBuf);
DWORD cbRead = 0;
DWORD dwFlags = 0;
// Check usage.
if (argc < 2)
{
fprintf(stderr, "Usage: httpauth [-c] <server> [<object> [<user> [<pass>]]]\n");
fprintf(stderr, " -c: Use custom UI to prompt for user/pass");
exit(1);
}
// Parse arguments.
if (argc >= 2 && strcmp(argv[1], "-c") == 0)
{
fAllowCustomUI = TRUE;
argv++;
argc--;
}
pszHost = argv[1];
if (argc >= 3)
{
pszObject = argv[2];
}
else
{
pszObject = "/";
}
if (argc >= 4)
{
pszUser = argv[3];
}
if (argc >= 5)
{
pszPass = argv[4];
}
// Initialize wininet.
hInternet = InternetOpen("HttpAuth Sample", // app name
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
0, // port
pszUser, // user
NULL, // pass
INTERNET_SERVICE_HTTP, // service
0, // flags
0); // context
CHECK_ERROR(hConnect, "InternetConnect");
if (pszPass)
{
// Work around InternetConnect disallowing empty passwords.
InternetSetOption(hConnect,
INTERNET_OPTION_PASSWORD,
pszPass,
lstrlen(pszPass) + 1);
}
// Create request.
dwFlags = INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RELOAD;
hRequest = HttpOpenRequest(hConnect, // connect handle
"GET", // request method
pszObject, // object name
NULL, // version
NULL, // referrer
NULL, // accept types
dwFlags, // flags: keep-alive, bypass cache
0); // context
CHECK_ERROR(hRequest, "HttpOpenRequest");
do
{
// Send request.
fRet = HttpSendRequest(hRequest, // request handle
"", // header string
0, // header length
NULL, // post data
0); // post length
// Handle any authentication dialogs.
if (NeedAuth(hRequest) && fAllowCustomUI)
{
dwError = DoCustomUI(hConnect, hRequest);
}
else
{
dwFlags = FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS |
FLAGS_ERROR_UI_FLAGS_GENERATE_DATA;
dwError = InternetErrorDlg(GetDesktopWindow(),
hRequest,
fRet ? ERROR_SUCCESS : GetLastError(),
dwFlags,
NULL);
}
}
while (dwError == ERROR_INTERNET_FORCE_RETRY);
SetLastError(dwError);
CHECK_ERROR(dwError == ERROR_SUCCESS, "Authentication");
// Dump some bytes.
_setmode(_fileno(stdout), _O_BINARY);
while (InternetReadFile(hRequest, rgbBuf, cbBuf, &cbRead))
{
if (cbRead == 0)
{
break;
}
fwrite(rgbBuf, 1, cbRead, stdout);
}
Done:
if (pszErr)
{
fprintf(stderr, "Failed on %s, last error %d\n", pszErr, GetLastError());
}
// Clean up.
if (hRequest)
{
InternetCloseHandle(hRequest);
hRequest = NULL;
}
if (hConnect)
{
InternetCloseHandle(hConnect);
hConnect = NULL;
}
if (hInternet)
{
InternetCloseHandle(hInternet);
hInternet = NULL;
}
return 0;
}