Leaked source code of windows server 2003
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

  1. // ===========================================================================
  2. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. // PARTICULAR PURPOSE.
  6. //
  7. // Copyright 1996 Microsoft Corporation. All Rights Reserved.
  8. // ===========================================================================
  9. #include <windows.h>
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <fcntl.h>
  13. #include <stdlib.h>
  14. #include <io.h>
  15. #include <wininet.h>
  16. BOOL g_fAllowCustomUI;
  17. DWORD g_dwConnectFlags;
  18. BOOL g_fPreload;
  19. BOOL g_fMonolithicUpload = TRUE;
  20. LPSTR g_szVerb = NULL;
  21. //==============================================================================
  22. BOOL NeedAuth (HINTERNET hRequest, DWORD *pdwStatus)
  23. {
  24. // Get status code.
  25. DWORD dwStatus;
  26. DWORD cbStatus = sizeof(dwStatus);
  27. HttpQueryInfo
  28. (
  29. hRequest,
  30. HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE,
  31. &dwStatus,
  32. &cbStatus,
  33. NULL
  34. );
  35. fprintf (stderr, "Status: %d\n", dwStatus);
  36. *pdwStatus = dwStatus;
  37. // Look for 401 or 407.
  38. DWORD dwFlags;
  39. switch (dwStatus)
  40. {
  41. case HTTP_STATUS_DENIED:
  42. dwFlags = HTTP_QUERY_WWW_AUTHENTICATE;
  43. break;
  44. case HTTP_STATUS_PROXY_AUTH_REQ:
  45. dwFlags = HTTP_QUERY_PROXY_AUTHENTICATE;
  46. break;
  47. default:
  48. return FALSE;
  49. }
  50. // Enumerate the authentication types.
  51. BOOL fRet;
  52. char szScheme[64];
  53. DWORD dwIndex = 0;
  54. do
  55. {
  56. DWORD cbScheme = sizeof(szScheme);
  57. fRet = HttpQueryInfo
  58. (hRequest, dwFlags, szScheme, &cbScheme, &dwIndex);
  59. if (fRet)
  60. fprintf (stderr, "Found auth scheme: %s\n", szScheme);
  61. }
  62. while (fRet);
  63. return TRUE;
  64. }
  65. //==============================================================================
  66. DWORD DoCustomUI (HINTERNET hRequest, BOOL fProxy)
  67. {
  68. // Prompt for username and password.
  69. char szUser[64], szPass[64];
  70. fprintf (stderr, "Enter Username: ");
  71. if (!fscanf (stdin, "%s", szUser))
  72. return ERROR_INTERNET_LOGIN_FAILURE;
  73. fprintf (stderr, "Enter Password: ");
  74. if (!fscanf (stdin, "%s", szPass))
  75. return ERROR_INTERNET_LOGIN_FAILURE;
  76. // Set the values in the handle.
  77. if (fProxy)
  78. {
  79. InternetSetOption
  80. (hRequest, INTERNET_OPTION_PROXY_USERNAME, szUser, sizeof(szUser));
  81. InternetSetOption
  82. (hRequest, INTERNET_OPTION_PROXY_PASSWORD, szPass, sizeof(szPass));
  83. }
  84. else
  85. {
  86. InternetSetOption
  87. (hRequest, INTERNET_OPTION_USERNAME, szUser, sizeof(szUser));
  88. InternetSetOption
  89. (hRequest, INTERNET_OPTION_PASSWORD, szPass, sizeof(szPass));
  90. }
  91. return ERROR_INTERNET_FORCE_RETRY;
  92. }
  93. //==============================================================================
  94. int RequestLoop (int argc, char **argv)
  95. {
  96. HINTERNET hInternet = NULL;
  97. HINTERNET hConnect = NULL;
  98. HINTERNET hRequest = NULL;
  99. PSTR pPostData = NULL;
  100. DWORD cbPostData = 0;
  101. PSTR pszErr = NULL;
  102. BOOL fRet;
  103. #define CHECK_ERROR(cond, err) if (!(cond)) {pszErr=(err); goto done;}
  104. // Parse host:port
  105. PSTR pszHost = argv[0];
  106. DWORD dwPort;
  107. PSTR pszColon = strchr(pszHost, ':');
  108. if (!pszColon)
  109. dwPort = INTERNET_INVALID_PORT_NUMBER;
  110. else
  111. {
  112. *pszColon++ = 0;
  113. dwPort = atol (pszColon);
  114. }
  115. PSTR pszObject = argc >= 2 ? argv[1] : "/";
  116. PSTR pszUser = argc >= 3 ? argv[2] : NULL;
  117. PSTR pszPass = argc >= 4 ? argv[3] : NULL;
  118. PSTR pszPostFile = argc >= 5 ? argv[4] : NULL;
  119. if (pszPostFile)
  120. g_dwConnectFlags |= INTERNET_FLAG_RELOAD;
  121. //#ifdef MONOLITHIC_UPLOAD
  122. if(g_fMonolithicUpload)
  123. {
  124. // Read any POST data into a buffer.
  125. if (pszPostFile)
  126. {
  127. HANDLE hf =
  128. CreateFile
  129. (
  130. pszPostFile,
  131. GENERIC_READ,
  132. FILE_SHARE_READ,
  133. NULL,
  134. OPEN_EXISTING,
  135. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  136. NULL
  137. );
  138. if (hf != INVALID_HANDLE_VALUE)
  139. {
  140. cbPostData = GetFileSize (hf, NULL);
  141. pPostData = (PSTR) LocalAlloc (LMEM_FIXED, cbPostData + 1);
  142. if (pPostData)
  143. ReadFile (hf, pPostData, cbPostData, &cbPostData, NULL);
  144. pPostData[cbPostData] = 0;
  145. CloseHandle (hf);
  146. }
  147. }
  148. } // g_fMonolithicUpload
  149. //#endif
  150. // Initialize wininet.
  151. hInternet = InternetOpen
  152. (
  153. //"HttpAuth Sample", // user agent
  154. "Mozilla/4.0 (compatible; MSIE 4.0b2; Windows 95",
  155. INTERNET_OPEN_TYPE_PRECONFIG, // access type
  156. NULL, // proxy server
  157. 0, // proxy port
  158. 0 // flags
  159. );
  160. CHECK_ERROR (hInternet, "InternetOpen");
  161. // Connect to host.
  162. hConnect = InternetConnect
  163. (
  164. hInternet, // wininet handle,
  165. pszHost, // host
  166. (INTERNET_PORT)dwPort, // port
  167. pszUser, // user
  168. NULL, // password
  169. INTERNET_SERVICE_HTTP, // service
  170. g_dwConnectFlags, // flags
  171. 0 // context
  172. );
  173. CHECK_ERROR (hConnect, "InternetConnect");
  174. // Use SetOption to set the password since it handles empty strings.
  175. if (pszPass)
  176. {
  177. InternetSetOption
  178. (hConnect, INTERNET_OPTION_PASSWORD, pszPass, lstrlen(pszPass)+1);
  179. }
  180. if(!g_szVerb)
  181. {
  182. if (pszPostFile)
  183. g_szVerb = "PUT";
  184. else
  185. g_szVerb = "GET";
  186. }
  187. // Create request.
  188. hRequest = HttpOpenRequest
  189. (
  190. hConnect, // connect handle
  191. g_szVerb, // pszPostFile? "PUT" : "GET", // request method
  192. pszObject, // object name
  193. NULL, // version
  194. NULL, // referer
  195. NULL, // accept types
  196. g_dwConnectFlags // flags
  197. | INTERNET_FLAG_KEEP_CONNECTION
  198. | SECURITY_INTERNET_MASK, // ignore SSL warnings
  199. 0 // context
  200. );
  201. CHECK_ERROR (hRequest, "HttpOpenRequest");
  202. resend:
  203. // if (!pszPostFile || pPostData)
  204. if (g_fMonolithicUpload)
  205. {
  206. // Send request.
  207. fRet = HttpSendRequest
  208. (
  209. hRequest, // request handle
  210. "", // header string
  211. 0, // header length
  212. pPostData, // post data
  213. cbPostData // post length
  214. );
  215. }
  216. else
  217. {
  218. HANDLE hf = CreateFile
  219. (
  220. pszPostFile,
  221. GENERIC_READ,
  222. FILE_SHARE_READ,
  223. NULL,
  224. OPEN_EXISTING,
  225. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  226. NULL
  227. );
  228. if (hf != INVALID_HANDLE_VALUE)
  229. {
  230. cbPostData = GetFileSize (hf, NULL);
  231. INTERNET_BUFFERS BufferIn;
  232. BufferIn.dwStructSize = sizeof( INTERNET_BUFFERSA );
  233. BufferIn.Next = NULL;
  234. BufferIn.lpcszHeader = NULL;
  235. BufferIn.dwHeadersLength = 0;
  236. BufferIn.dwHeadersTotal = 0;
  237. BufferIn.lpvBuffer = NULL;
  238. BufferIn.dwBufferLength = 0;
  239. BufferIn.dwBufferTotal = cbPostData;
  240. BufferIn.dwOffsetLow = 0;
  241. BufferIn.dwOffsetHigh = 0;
  242. fRet = HttpSendRequestEx (hRequest, &BufferIn, NULL, 0, 0);
  243. CHECK_ERROR (fRet, "HttpSendRequestEx");
  244. while (1)
  245. {
  246. CHAR szTemp[512];
  247. DWORD cbRead;
  248. fRet = ReadFile (hf, szTemp, sizeof(szTemp), &cbRead, 0);
  249. CHECK_ERROR (fRet, "ReadFile");
  250. if (!fRet || !cbRead)
  251. break;
  252. DWORD cbRead2;
  253. fRet = InternetWriteFile (hRequest, szTemp, cbRead, &cbRead2);
  254. CHECK_ERROR (fRet, "InternetWriteFile");
  255. }
  256. CloseHandle (hf);
  257. fRet = HttpEndRequest (hRequest, NULL, 0, 0);
  258. if (!fRet && GetLastError() == ERROR_INTERNET_FORCE_RETRY)
  259. goto resend;
  260. }
  261. }
  262. DWORD dwStatus;
  263. // Check if the status code is 401 or 407
  264. if (NeedAuth (hRequest, &dwStatus) && (g_fAllowCustomUI))
  265. {
  266. // Prompt for username and password.
  267. if (DoCustomUI (hRequest, dwStatus != HTTP_STATUS_DENIED))
  268. goto resend;
  269. }
  270. else
  271. {
  272. DWORD dwSendErr = fRet? ERROR_SUCCESS : GetLastError();
  273. DWORD dwDlgErr = InternetErrorDlg(
  274. GetDesktopWindow(),
  275. hRequest,
  276. dwSendErr,
  277. FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
  278. FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS |
  279. FLAGS_ERROR_UI_FLAGS_GENERATE_DATA,
  280. NULL
  281. );
  282. switch (dwSendErr)
  283. {
  284. case ERROR_SUCCESS:
  285. case ERROR_INTERNET_NAME_NOT_RESOLVED:
  286. case ERROR_INTERNET_CANNOT_CONNECT:
  287. if (dwDlgErr == ERROR_INTERNET_FORCE_RETRY)
  288. goto resend;
  289. else
  290. break;
  291. case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION:
  292. default:
  293. if (dwDlgErr == ERROR_SUCCESS)
  294. goto resend;
  295. else
  296. break;
  297. }
  298. }
  299. // Dump some bytes.
  300. BYTE bBuf[1024];
  301. DWORD cbBuf;
  302. DWORD cbRead;
  303. cbBuf = sizeof(bBuf);
  304. _setmode( _fileno( stdout ), _O_BINARY );
  305. while (InternetReadFile (hRequest, bBuf, cbBuf, &cbRead) && cbRead)
  306. fwrite (bBuf, 1, cbRead, stdout);
  307. done: // Clean up.
  308. if (pszErr)
  309. fprintf (stderr, "Failed on %s, last error %d\n", pszErr, GetLastError());
  310. if (hRequest)
  311. InternetCloseHandle (hRequest);
  312. if (hConnect)
  313. InternetCloseHandle (hConnect);
  314. if (hInternet)
  315. InternetCloseHandle (hInternet);
  316. if (pPostData)
  317. LocalFree (pPostData);
  318. return 0;
  319. }
  320. //==============================================================================
  321. void ParseArguments
  322. (
  323. LPSTR InBuffer,
  324. LPSTR* CArgv,
  325. DWORD* CArgc
  326. )
  327. {
  328. LPSTR CurrentPtr = InBuffer;
  329. DWORD i = 0;
  330. DWORD Cnt = 0;
  331. for ( ;; ) {
  332. //
  333. // skip blanks.
  334. //
  335. while( *CurrentPtr == ' ' ) {
  336. CurrentPtr++;
  337. }
  338. if( *CurrentPtr == '\0' ) {
  339. break;
  340. }
  341. CArgv[i++] = CurrentPtr;
  342. //
  343. // go to next space.
  344. //
  345. while( (*CurrentPtr != '\0') &&
  346. (*CurrentPtr != '\n') ) {
  347. if( *CurrentPtr == '"' ) { // Deal with simple quoted args
  348. if( Cnt == 0 )
  349. CArgv[i-1] = ++CurrentPtr; // Set arg to after quote
  350. else
  351. *CurrentPtr = '\0'; // Remove end quote
  352. Cnt = !Cnt;
  353. }
  354. if( (Cnt == 0) && (*CurrentPtr == ' ') || // If we hit a space and no quotes yet we are done with this arg
  355. (*CurrentPtr == '\0') )
  356. break;
  357. CurrentPtr++;
  358. }
  359. if( *CurrentPtr == '\0' ) {
  360. break;
  361. }
  362. *CurrentPtr++ = '\0';
  363. }
  364. *CArgc = i;
  365. return;
  366. }
  367. //==============================================================================
  368. int __cdecl main (int argc, char **argv)
  369. {
  370. g_fAllowCustomUI = 0; //FALSE;
  371. g_dwConnectFlags = 0;
  372. HMODULE hmodShlwapi = NULL;
  373. char * port ;
  374. // Discard program arg.
  375. argv++;
  376. argc--;
  377. // Parse options.
  378. while (argc && argv[0][0] == '-')
  379. {
  380. switch (tolower(argv[0][1]))
  381. {
  382. case 'c':
  383. g_fAllowCustomUI = TRUE;
  384. break;
  385. case 's':
  386. g_dwConnectFlags = INTERNET_FLAG_SECURE;
  387. break;
  388. case 'p':
  389. g_fPreload = TRUE;
  390. break;
  391. case 'v':
  392. port = *argv;
  393. port +=2;
  394. fprintf(stderr,"Verb: %s\n", port);
  395. if(port)
  396. g_szVerb = port;
  397. break;
  398. case 'm':
  399. g_fMonolithicUpload = TRUE;
  400. break;
  401. default:
  402. fprintf (stderr, "\nUsage: httpauth [-c] [-s] <server> [<object> [<user> [<pass> [<POST-file>]]]]");
  403. fprintf (stderr, "\n -c: Custom UI to prompt for user/pass");
  404. fprintf (stderr, "\n -s: Secure connection (ssl or pct)");
  405. fprintf (stderr, "\n -m: Monolithic upload");
  406. fprintf (stderr, "\n -o<port#> : Port Number");
  407. exit (1);
  408. }
  409. argv++;
  410. argc--;
  411. }
  412. if (g_fPreload)
  413. {
  414. //Get the current directory in case the user selects -p to preload shlwapi from current dir
  415. char buf[256];
  416. GetCurrentDirectory((DWORD)256, buf);
  417. strcat(buf,"\\shlwapi.dll");
  418. fprintf(stderr, "\nPreloading shlwapi.dll from %s", buf);
  419. if (!(hmodShlwapi=LoadLibrary(buf))) fprintf(stderr, "\nPreload of shlwapi.dll failed");
  420. }
  421. if (argc)
  422. RequestLoop (argc, argv);
  423. else // Enter command prompt loop
  424. {
  425. fprintf (stderr, "\nUsage: <server> [<object> [<user> [<pass> [<POST-file>]]]]");
  426. fprintf (stderr, "\n quit - exit the command loop");
  427. fprintf (stderr, "\n flush - flush pwd cache and authenticated sockets");
  428. while (1)
  429. {
  430. char szIn[1024];
  431. DWORD argcIn;
  432. LPSTR argvIn[10];
  433. fprintf (stderr, "\nhttpauth> ");
  434. gets (szIn);
  435. if (!lstrcmpi (szIn, "quit"))
  436. break;
  437. else if (!lstrcmpi (szIn, "flush"))
  438. {
  439. InternetSetOption
  440. (NULL, INTERNET_OPTION_END_BROWSER_SESSION, NULL, 0);
  441. continue;
  442. }
  443. argcIn = 0;
  444. ParseArguments (szIn, argvIn, &argcIn);
  445. if (!argcIn)
  446. break;
  447. RequestLoop (argcIn, argvIn);
  448. }
  449. }
  450. //unload shlwapi if loaded
  451. if (hmodShlwapi) FreeLibrary(hmodShlwapi);
  452. }