// =========================================================================== // 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 #include #include #include #include #include #include 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] [ [ [ []]]]"); 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 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: [ [ [ []]]]"); 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); }