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.

469 lines
13 KiB

  1. /*++
  2. Copyright (c) 1994-2000 Microsoft Corporation
  3. Module Name:
  4. Creds.cxx
  5. Abstract:
  6. Contains the Creds APIs
  7. Contents:
  8. WinHttpSetCredentialsA
  9. WinHttpSetCredentials
  10. WinHttpQueryAuthSchemes
  11. Author:
  12. Biao Wang (biaow) 27-June-2000
  13. Environment:
  14. Win32 user-mode DLL
  15. Revision History:
  16. 27-June-2000 biaow
  17. Created
  18. --*/
  19. #include <wininetp.h>
  20. /*
  21. BOOLAPI WinHttpQueryAuthParams(
  22. IN HINTERNET hRequest, // HINTERNET handle returned by WinHttpOpenRequest
  23. IN DWORD AuthScheme,
  24. OUT LPVOID* pAuthParams // Scheme-specific Advanced auth parameters
  25. )
  26. {
  27. //BUG-BUG Verify parameters
  28. // biaow: to implement this fully
  29. *pAuthParams = 0;
  30. return TRUE;
  31. }
  32. */
  33. BOOLAPI WinHttpQueryAuthSchemes(
  34. IN HINTERNET hRequest, // HINTERNET handle returned by HttpOpenRequest.
  35. OUT LPDWORD lpdwSupportedSchemes,// a bitmap of available Authentication Schemes
  36. OUT LPDWORD lpdwPreferredScheme, // WinHttp's preferred Authentication Method
  37. OUT LPDWORD pdwAuthTarget
  38. )
  39. {
  40. DEBUG_ENTER_API((DBG_API,
  41. Bool,
  42. "WinHttpQueryAuthSchemes",
  43. "%#x, %#x, %#x",
  44. hRequest,
  45. lpdwSupportedSchemes,
  46. lpdwPreferredScheme
  47. ));
  48. DWORD dwErr = ERROR_SUCCESS;
  49. HINTERNET hRequestMapped = NULL;
  50. BOOL fResult = FALSE;
  51. HINTERNET_HANDLE_TYPE HandleType;
  52. dwErr = ::MapHandleToAddress(hRequest, (LPVOID *)&hRequestMapped, FALSE);
  53. if ((dwErr != ERROR_SUCCESS) || (hRequestMapped == NULL))
  54. {
  55. dwErr = ERROR_INVALID_HANDLE;
  56. goto cleanup;
  57. }
  58. HTTP_REQUEST_HANDLE_OBJECT * pRequest;
  59. if ((::RGetHandleType(hRequestMapped, &HandleType) != ERROR_SUCCESS)
  60. || (HandleType != TypeHttpRequestHandle))
  61. {
  62. dwErr = ERROR_INVALID_HANDLE;
  63. goto cleanup;
  64. }
  65. pRequest = (HTTP_REQUEST_HANDLE_OBJECT *)hRequestMapped;
  66. if (::IsBadWritePtr(lpdwSupportedSchemes, sizeof(DWORD))
  67. || ::IsBadWritePtr(lpdwPreferredScheme, sizeof(DWORD))
  68. || ::IsBadWritePtr(pdwAuthTarget, sizeof(DWORD)))
  69. {
  70. dwErr = ERROR_INVALID_PARAMETER;
  71. goto cleanup;
  72. }
  73. if (!pRequest->_KnowSupportedSchemes)
  74. {
  75. dwErr = ERROR_INVALID_OPERATION;
  76. goto cleanup;
  77. }
  78. *lpdwSupportedSchemes = pRequest->_SupportedSchemes;
  79. *lpdwPreferredScheme = pRequest->_PreferredScheme;
  80. *pdwAuthTarget = pRequest->_AuthTarget;
  81. fResult = TRUE;
  82. DEBUG_PRINT(API,
  83. INFO,
  84. ("Supported Scheme = %x; Preferred Scheme = %x; Auth Target = %x\n",
  85. *lpdwSupportedSchemes,
  86. *lpdwPreferredScheme,
  87. *pdwAuthTarget
  88. ));
  89. cleanup:
  90. if (hRequestMapped)
  91. {
  92. DereferenceObject(hRequestMapped);
  93. }
  94. if (dwErr!= ERROR_SUCCESS)
  95. {
  96. ::SetLastError(dwErr);
  97. DEBUG_ERROR(HTTP, dwErr);
  98. }
  99. DEBUG_LEAVE_API(fResult);
  100. return fResult;
  101. }
  102. BOOL WinHttpSetCredentialsA (
  103. IN HINTERNET hRequest, // HINTERNET handle returned by HttpOpenRequest.
  104. IN DWORD AuthTargets, // Only WINHTTP_AUTH_TARGET_SERVER and
  105. // WINHTTP_AUTH_TARGET_PROXY are supported
  106. // in this version and they are mutually
  107. // exclusive
  108. IN DWORD AuthScheme, // must be one of the supported Auth Schemes
  109. // returned from HttpQueryAuthSchemes(), Apps
  110. // should use the Preferred Scheme returned
  111. IN LPCSTR pszUserName, // 1) NULL if default creds is to be used, in
  112. // which case pszPassword will be ignored
  113. IN LPCSTR pszPassword, // 1) "" == Blank Passowrd; 2)Parameter ignored
  114. // if pszUserName is NULL; 3) Invalid to pass in
  115. // NULL if pszUserName is not NULL
  116. IN LPVOID pAuthParams
  117. )
  118. {
  119. DEBUG_ENTER_API((DBG_API,
  120. Bool,
  121. "WinHttpSetCredentialsA",
  122. "%#x, %#x, %#x, %q, %q, %q",
  123. hRequest,
  124. AuthTargets,
  125. AuthScheme,
  126. pAuthParams,
  127. pszUserName ? "<username>" : "NULL",
  128. pszPassword ? "<password>" : "NULL"
  129. ));
  130. // Note: we assume WinHttp will explose an Unicode only API, so this function
  131. // will not be called directly by Apps. If this assumption is no longer true
  132. // in future revisions, we need to add more elaborate parameter validation here.
  133. DWORD dwErr = ERROR_SUCCESS;
  134. BOOL fResult = FALSE;
  135. HINTERNET hRequestMapped = NULL;
  136. HTTP_REQUEST_HANDLE_OBJECT* pRequest;
  137. HINTERNET_HANDLE_TYPE HandleType;
  138. PCSTR pszRealm = NULL;
  139. // validate API symantics
  140. if (pszUserName != NULL)
  141. {
  142. // in any case, it doesn't make sense (and therefore invalid) to pass
  143. // in a blank("") User Name
  144. if (pszUserName[0] == '\0')
  145. {
  146. dwErr = ERROR_INVALID_PARAMETER;
  147. goto cleanup;
  148. }
  149. else if (pszPassword == NULL)
  150. {
  151. // in any case, if an app passes in a UserName, it is invalid to
  152. // then pass in a NULL password (should use "" for blank passowrd)
  153. dwErr = ERROR_INVALID_PARAMETER;
  154. goto cleanup;
  155. }
  156. }
  157. switch (AuthScheme)
  158. {
  159. case WINHTTP_AUTH_SCHEME_BASIC:
  160. case WINHTTP_AUTH_SCHEME_NTLM:
  161. case WINHTTP_AUTH_SCHEME_PASSPORT:
  162. case WINHTTP_AUTH_SCHEME_DIGEST:
  163. case WINHTTP_AUTH_SCHEME_NEGOTIATE:
  164. break;
  165. default:
  166. dwErr = ERROR_INVALID_PARAMETER;
  167. goto cleanup;
  168. }
  169. // if an app picks BASIC auth, it must also supply an UserName and password
  170. if ((AuthScheme == WINHTTP_AUTH_SCHEME_BASIC) && (pszUserName == NULL))
  171. {
  172. dwErr = ERROR_INVALID_PARAMETER;
  173. goto cleanup;
  174. }
  175. // default credentials (UserName/Password == NULL/NULL) are allowed only for
  176. // NTLM/NEGOTIATE/PASSPORT auth
  177. if (pszUserName == NULL)
  178. {
  179. if ((AuthScheme != WINHTTP_AUTH_SCHEME_NTLM)
  180. && (AuthScheme != WINHTTP_AUTH_SCHEME_NEGOTIATE)
  181. && (AuthScheme != WINHTTP_AUTH_SCHEME_PASSPORT))
  182. {
  183. dwErr = ERROR_INVALID_PARAMETER;
  184. goto cleanup;
  185. }
  186. }
  187. dwErr = ::MapHandleToAddress(hRequest, (LPVOID *)&hRequestMapped, FALSE);
  188. if ((dwErr != ERROR_SUCCESS) || (hRequestMapped == NULL)) {
  189. dwErr = ERROR_INVALID_HANDLE;
  190. goto cleanup;
  191. }
  192. if ((::RGetHandleType(hRequestMapped, &HandleType) != ERROR_SUCCESS)
  193. || (HandleType != TypeHttpRequestHandle))
  194. {
  195. dwErr = ERROR_INVALID_HANDLE;
  196. goto cleanup;
  197. }
  198. pRequest =
  199. reinterpret_cast<HTTP_REQUEST_HANDLE_OBJECT*>(hRequestMapped);
  200. if (AuthScheme == WINHTTP_AUTH_SCHEME_DIGEST)
  201. {
  202. if (pAuthParams)
  203. {
  204. pszRealm = (PCSTR)pAuthParams;
  205. }
  206. else
  207. {
  208. pszRealm = pRequest->_pszRealm;
  209. }
  210. }
  211. if (AuthTargets == WINHTTP_AUTH_TARGET_PROXY)
  212. {
  213. delete pRequest->_pProxyCreds;
  214. pRequest->_pProxyCreds = New WINHTTP_REQUEST_CREDENTIALS();
  215. if (pRequest->_pProxyCreds == NULL
  216. || !pRequest->_pProxyCreds->Initialize(AuthScheme, pszRealm, pszUserName, pszPassword))
  217. {
  218. if (pRequest->_pProxyCreds != NULL)
  219. {
  220. delete pRequest->_pProxyCreds;
  221. pRequest->_pProxyCreds = NULL;
  222. }
  223. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  224. goto cleanup;
  225. }
  226. }
  227. else
  228. {
  229. delete pRequest->_pServerCreds;
  230. pRequest->_pServerCreds = New WINHTTP_REQUEST_CREDENTIALS();
  231. if (pRequest->_pServerCreds == NULL
  232. || !pRequest->_pServerCreds->Initialize(AuthScheme, pszRealm, pszUserName, pszPassword))
  233. {
  234. if (pRequest->_pServerCreds != NULL)
  235. {
  236. delete pRequest->_pServerCreds;
  237. pRequest->_pServerCreds = NULL;
  238. }
  239. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  240. goto cleanup;
  241. }
  242. }
  243. pRequest->_KnowSupportedSchemes = FALSE;
  244. pRequest->_PreferredScheme = 0x00000000;
  245. pRequest->_SupportedSchemes = 0x00000000;
  246. pRequest->_AuthTarget = 0x00000000;
  247. if (pRequest->_pszRealm)
  248. {
  249. FREE_MEMORY(pRequest->_pszRealm);
  250. pRequest->_pszRealm = NULL;
  251. }
  252. fResult = TRUE;
  253. cleanup:
  254. if (hRequestMapped)
  255. {
  256. DereferenceObject(hRequestMapped);
  257. }
  258. if (dwErr!=ERROR_SUCCESS)
  259. {
  260. ::SetLastError(dwErr);
  261. DEBUG_ERROR(HTTP, dwErr);
  262. }
  263. DEBUG_LEAVE_API(fResult);
  264. return fResult;
  265. }
  266. BOOLAPI
  267. WinHttpSetCredentials(
  268. IN HINTERNET hRequest, // HINTERNET handle returned by HttpOpenRequest.
  269. IN DWORD AuthTargets, // Only WINHTTP_AUTH_TARGET_SERVER and
  270. // WINHTTP_AUTH_TARGET_PROXY are supported
  271. // in this version and they are mutually
  272. // exclusive
  273. IN DWORD AuthScheme, // must be one of the supported Auth Schemes
  274. // returned from HttpQueryAuthSchemes(), Apps
  275. // should use the Preferred Scheme returned
  276. IN LPCWSTR pwszUserName, // 1) NULL if default creds is to be used, in
  277. // which case pszPassword will be ignored
  278. IN LPCWSTR pwszPassword, // 1) "" == Blank Passowrd; 2)Parameter ignored
  279. // if pszUserName is NULL; 3) Invalid to pass in
  280. // NULL if pszUserName is not NULL
  281. IN LPVOID pAuthParams
  282. )
  283. {
  284. DEBUG_ENTER_API((DBG_API,
  285. Bool,
  286. "WinHttpSetCredentials",
  287. "%#x, %#x, %#x, %wq, %wq, %wq",
  288. hRequest,
  289. AuthTargets,
  290. AuthScheme,
  291. pAuthParams,
  292. pwszUserName ? L"<username>" : L"NULL",
  293. pwszPassword ? L"<password>" : L"NULL"
  294. ));
  295. DWORD dwErr = ERROR_SUCCESS;
  296. BOOL fResult = FALSE;
  297. LPCWSTR pwszRealm = NULL;
  298. MEMORYPACKET mpRealm, mpUserName, mpPassword;
  299. if (!hRequest)
  300. {
  301. dwErr = ERROR_INVALID_HANDLE;
  302. goto cleanup;
  303. }
  304. // make sure only one bit in AuthScheme is set
  305. if ((AuthScheme & (AuthScheme - 1)) != 0x00000000)
  306. {
  307. dwErr = ERROR_INVALID_PARAMETER;
  308. goto cleanup;
  309. }
  310. // make sure the input strings are valid
  311. if (pwszUserName
  312. && ::IsBadStringPtrW(pwszUserName, (UINT_PTR)-1))
  313. {
  314. dwErr = ERROR_INVALID_PARAMETER;
  315. goto cleanup;
  316. }
  317. if (pwszPassword
  318. && ::IsBadStringPtrW(pwszPassword, (UINT_PTR)-1))
  319. {
  320. dwErr = ERROR_INVALID_PARAMETER;
  321. goto cleanup;
  322. }
  323. if ((AuthScheme == WINHTTP_AUTH_SCHEME_DIGEST) && pAuthParams)
  324. {
  325. pwszRealm = (LPCWSTR)pAuthParams;
  326. }
  327. if (pwszRealm
  328. && ::IsBadStringPtrW(pwszRealm, (UINT_PTR)-1))
  329. {
  330. dwErr = ERROR_INVALID_PARAMETER;
  331. goto cleanup;
  332. }
  333. // make sure AuthTargets are either Server or Proxy (not both)
  334. if ((AuthTargets != WINHTTP_AUTH_TARGET_SERVER)
  335. && (AuthTargets != WINHTTP_AUTH_TARGET_PROXY))
  336. {
  337. dwErr = ERROR_INVALID_PARAMETER;
  338. goto cleanup;
  339. }
  340. // convert Unicode strings to Ansi
  341. if (pwszUserName)
  342. {
  343. ALLOC_MB(pwszUserName, 0, mpUserName);
  344. if (!mpUserName.psStr)
  345. {
  346. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  347. goto cleanup;
  348. }
  349. UNICODE_TO_ANSI(pwszUserName, mpUserName);
  350. }
  351. if (pwszPassword)
  352. {
  353. ALLOC_MB(pwszPassword, 0, mpPassword);
  354. if (!mpPassword.psStr)
  355. {
  356. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  357. goto cleanup;
  358. }
  359. UNICODE_TO_ANSI(pwszPassword, mpPassword);
  360. }
  361. if (pwszRealm)
  362. {
  363. ALLOC_MB(pwszRealm, 0, mpRealm);
  364. if (!mpRealm.psStr)
  365. {
  366. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  367. goto cleanup;
  368. }
  369. UNICODE_TO_ANSI(pwszRealm, mpRealm);
  370. }
  371. fResult = ::WinHttpSetCredentialsA(hRequest, AuthTargets,
  372. AuthScheme, mpUserName.psStr, mpPassword.psStr, mpRealm.psStr);
  373. cleanup:
  374. ZERO_MEMORY_ALLOC(mpUserName);
  375. ZERO_MEMORY_ALLOC(mpPassword);
  376. if (dwErr!=ERROR_SUCCESS)
  377. {
  378. ::SetLastError(dwErr);
  379. DEBUG_ERROR(HTTP, dwErr);
  380. }
  381. DEBUG_LEAVE_API(fResult);
  382. return fResult;
  383. }