HTTPAUTH.CPP

// =========================================================================== 
// 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 1997 Microsoft Corporation. All Rights Reserved.
// ===========================================================================
#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <wininet.h>

//==============================================================================
BOOL NeedAuth (HINTERNET hRequest)
{
// 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);

// 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 hConnect, HINTERNET hRequest)
{
// 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.
InternetSetOption
(hConnect, INTERNET_OPTION_USERNAME, szUser, sizeof(szUser));
InternetSetOption
(hConnect, INTERNET_OPTION_PASSWORD, szPass, sizeof(szPass));

// Drain the socket.
BYTE bBuf[1000];
DWORD cbBuf = sizeof(bBuf);
DWORD cbRead;
while (InternetReadFile (hRequest, bBuf, cbBuf, &cbRead) && cbRead);

return ERROR_INTERNET_FORCE_RETRY;
}


//==============================================================================
int main (int argc, char **argv)
{
HINTERNET hInternet = NULL;
HINTERNET hConnect = NULL;
HINTERNET hRequest = NULL;
PSTR pszErr = NULL;
BOOL fRet;

#define CHECK_ERROR(cond, err) if (!(cond)) {pszErr=(err); goto done;}

// 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.
BOOL fAllowCustomUI = FALSE;
if (argc >= 2 && argv[1][0] == '-')
{
fAllowCustomUI = TRUE;
argv++;
argc--;
}
PSTR pszHost = argv[1];
PSTR pszObject = argc >= 3 ? argv[2] : "/";
PSTR pszUser = argc >= 4 ? argv[3] : NULL;
PSTR pszPass = argc >= 5 ? argv[4] : NULL;

// 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.
hRequest = HttpOpenRequest
(
hConnect, // connect handle
"GET", // request method
pszObject, // object name
NULL, // version
NULL, // referer
NULL, // accept types
INTERNET_FLAG_KEEP_CONNECTION // flags: keep-alive
| INTERNET_FLAG_RELOAD, // flags: bypass cache
0 // context
);
CHECK_ERROR (hRequest, "HttpOpenRequest");

resend:

// 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)
{
if (DoCustomUI (hConnect, hRequest) == ERROR_INTERNET_FORCE_RETRY)
goto resend;
}
else
{
DWORD dwErr;
dwErr = InternetErrorDlg
(
GetDesktopWindow(),
hRequest,
fRet ? ERROR_SUCCESS : GetLastError(),
FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS |
FLAGS_ERROR_UI_FLAGS_GENERATE_DATA,
NULL
);

if (dwErr == ERROR_INTERNET_FORCE_RETRY)
goto resend;
}

// 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);
return 0;
}