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.

438 lines
12 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->_SupportedSchemes) || (!pRequest->_PreferredScheme))
  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. cleanup:
  83. if (hRequestMapped)
  84. {
  85. DereferenceObject(hRequestMapped);
  86. }
  87. if (dwErr!= ERROR_SUCCESS)
  88. {
  89. ::SetLastError(dwErr);
  90. DEBUG_ERROR(HTTP, dwErr);
  91. }
  92. DEBUG_LEAVE_API(fResult);
  93. return fResult;
  94. }
  95. BOOL WinHttpSetCredentialsA (
  96. IN HINTERNET hRequest, // HINTERNET handle returned by HttpOpenRequest.
  97. IN DWORD AuthTargets, // Only WINHTTP_AUTH_TARGET_SERVER and
  98. // WINHTTP_AUTH_TARGET_PROXY are supported
  99. // in this version and they are mutually
  100. // exclusive
  101. IN DWORD AuthScheme, // must be one of the supported Auth Schemes
  102. // returned from HttpQueryAuthSchemes(), Apps
  103. // should use the Preferred Scheme returned
  104. IN LPCSTR pszUserName, // 1) NULL if default creds is to be used, in
  105. // which case pszPassword will be ignored
  106. IN LPCSTR pszPassword, // 1) "" == Blank Passowrd; 2)Parameter ignored
  107. // if pszUserName is NULL; 3) Invalid to pass in
  108. // NULL if pszUserName is not NULL
  109. IN LPVOID pAuthParams
  110. )
  111. {
  112. DEBUG_ENTER_API((DBG_API,
  113. Bool,
  114. "WinHttpSetCredentialsA",
  115. "%#x, %#x, %#x, %q, %q, %q",
  116. hRequest,
  117. AuthTargets,
  118. AuthScheme,
  119. pAuthParams,
  120. pszUserName,
  121. pszPassword
  122. ));
  123. // Note: we assume WinHttp will explose an Unicode only API, so this function
  124. // will not be called directly by Apps. If this assumption is no longer true
  125. // in future revisions, we need to add more elaborate parameter validation here.
  126. DWORD dwErr = ERROR_SUCCESS;
  127. BOOL fResult = FALSE;
  128. HINTERNET hRequestMapped = NULL;
  129. HTTP_REQUEST_HANDLE_OBJECT* pRequest;
  130. HINTERNET_HANDLE_TYPE HandleType;
  131. PSTR pszRealm = NULL;
  132. // validate API symantics
  133. if (pszUserName != NULL)
  134. {
  135. // in any case, it doesn't make sense (and therefore invalid) to pass
  136. // in a blank("") User Name
  137. if (::strlen(pszUserName) == 0)
  138. {
  139. dwErr = ERROR_INVALID_PARAMETER;
  140. goto cleanup;
  141. }
  142. else if (pszPassword == NULL)
  143. {
  144. // in any case, if an app passes in a UserName, it is invalid to
  145. // then pass in a NULL password (should use "" for blank passowrd)
  146. dwErr = ERROR_INVALID_PARAMETER;
  147. goto cleanup;
  148. }
  149. }
  150. // biaow: is blank scheme OK?
  151. // if an app picks BASIC auth, it must also supply an UserName and password
  152. if ((AuthScheme == WINHTTP_AUTH_SCHEME_BASIC) && (pszUserName == NULL))
  153. {
  154. dwErr = ERROR_INVALID_PARAMETER;
  155. goto cleanup;
  156. }
  157. // default credentials (UserName/Password == NULL/NULL) are allowed only for
  158. // NTLM/NEGOTIATE/PASSPORT auth
  159. if (pszUserName == NULL)
  160. {
  161. if ((AuthScheme != WINHTTP_AUTH_SCHEME_NTLM)
  162. && (AuthScheme != WINHTTP_AUTH_SCHEME_NEGOTIATE)
  163. && (AuthScheme != WINHTTP_AUTH_SCHEME_PASSPORT))
  164. {
  165. dwErr = ERROR_INVALID_PARAMETER;
  166. goto cleanup;
  167. }
  168. }
  169. dwErr = ::MapHandleToAddress(hRequest, (LPVOID *)&hRequestMapped, FALSE);
  170. if ((dwErr != ERROR_SUCCESS) || (hRequestMapped == NULL)) {
  171. dwErr = ERROR_INVALID_HANDLE;
  172. goto cleanup;
  173. }
  174. if ((::RGetHandleType(hRequestMapped, &HandleType) != ERROR_SUCCESS)
  175. || (HandleType != TypeHttpRequestHandle))
  176. {
  177. dwErr = ERROR_INVALID_HANDLE;
  178. goto cleanup;
  179. }
  180. pRequest =
  181. reinterpret_cast<HTTP_REQUEST_HANDLE_OBJECT*>(hRequestMapped);
  182. if (AuthScheme == WINHTTP_AUTH_SCHEME_DIGEST)
  183. {
  184. if (pAuthParams)
  185. {
  186. pszRealm = NewString((PCSTR)pAuthParams);
  187. }
  188. else
  189. {
  190. pszRealm = pRequest->_pszRealm;
  191. }
  192. if (pszRealm == NULL)
  193. {
  194. dwErr = ERROR_INVALID_PARAMETER;
  195. goto cleanup;
  196. }
  197. }
  198. if (AuthTargets == WINHTTP_AUTH_TARGET_PROXY)
  199. {
  200. delete pRequest->_pProxyCreds;
  201. pRequest->_pProxyCreds = New WINHTTP_REQUEST_CREDENTIALS(AuthScheme,
  202. pszRealm, pszUserName, pszPassword);
  203. if (pRequest->_pProxyCreds == NULL)
  204. {
  205. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  206. goto cleanup;
  207. }
  208. }
  209. else
  210. {
  211. delete pRequest->_pServerCreds;
  212. pRequest->_pServerCreds = New WINHTTP_REQUEST_CREDENTIALS(AuthScheme,
  213. pszRealm, pszUserName, pszPassword);
  214. if (pRequest->_pServerCreds == NULL)
  215. {
  216. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  217. goto cleanup;
  218. }
  219. }
  220. pRequest->_PreferredScheme = 0x00000000;
  221. pRequest->_SupportedSchemes = 0x00000000;
  222. pRequest->_AuthTarget = 0x00000000;
  223. if (pRequest->_pszRealm)
  224. {
  225. FREE_MEMORY(pRequest->_pszRealm);
  226. pRequest->_pszRealm = NULL;
  227. }
  228. fResult = TRUE;
  229. cleanup:
  230. if (hRequestMapped)
  231. {
  232. DereferenceObject(hRequestMapped);
  233. }
  234. if (dwErr!=ERROR_SUCCESS)
  235. {
  236. ::SetLastError(dwErr);
  237. DEBUG_ERROR(HTTP, dwErr);
  238. }
  239. DEBUG_LEAVE_API(fResult);
  240. return fResult;
  241. }
  242. BOOLAPI
  243. WinHttpSetCredentials(
  244. IN HINTERNET hRequest, // HINTERNET handle returned by HttpOpenRequest.
  245. IN DWORD AuthTargets, // Only WINHTTP_AUTH_TARGET_SERVER and
  246. // WINHTTP_AUTH_TARGET_PROXY are supported
  247. // in this version and they are mutually
  248. // exclusive
  249. IN DWORD AuthScheme, // must be one of the supported Auth Schemes
  250. // returned from HttpQueryAuthSchemes(), Apps
  251. // should use the Preferred Scheme returned
  252. IN LPCWSTR pwszUserName, // 1) NULL if default creds is to be used, in
  253. // which case pszPassword will be ignored
  254. IN LPCWSTR pwszPassword, // 1) "" == Blank Passowrd; 2)Parameter ignored
  255. // if pszUserName is NULL; 3) Invalid to pass in
  256. // NULL if pszUserName is not NULL
  257. IN LPVOID pAuthParams
  258. )
  259. {
  260. DEBUG_ENTER_API((DBG_API,
  261. Bool,
  262. "WinHttpSetCredentials",
  263. "%#x, %#x, %#x, %wq, %wq, %wq",
  264. hRequest,
  265. AuthTargets,
  266. AuthScheme,
  267. pAuthParams,
  268. pwszUserName,
  269. pwszPassword
  270. ));
  271. DWORD dwErr = ERROR_SUCCESS;
  272. BOOL fResult = FALSE;
  273. LPCWSTR pwszRealm = NULL;
  274. MEMORYPACKET mpRealm, mpUserName, mpPassword;
  275. if (!hRequest)
  276. {
  277. dwErr = ERROR_INVALID_HANDLE;
  278. goto cleanup;
  279. }
  280. // make sure only one bit in AuthScheme is set
  281. if ((AuthScheme & (AuthScheme - 1)) != 0x00000000)
  282. {
  283. dwErr = ERROR_INVALID_PARAMETER;
  284. goto cleanup;
  285. }
  286. // make sure the input strings are valid
  287. if (pwszUserName
  288. && ::IsBadStringPtrW(pwszUserName, INTERNET_MAX_USER_NAME_LENGTH))
  289. {
  290. dwErr = ERROR_INVALID_PARAMETER;
  291. goto cleanup;
  292. }
  293. if (pwszPassword
  294. && ::IsBadStringPtrW(pwszPassword, INTERNET_MAX_PASSWORD_LENGTH))
  295. {
  296. dwErr = ERROR_INVALID_PARAMETER;
  297. goto cleanup;
  298. }
  299. if ((AuthScheme == WINHTTP_AUTH_SCHEME_DIGEST) && pAuthParams)
  300. {
  301. pwszRealm = (LPCWSTR)pAuthParams;
  302. }
  303. if (pwszRealm
  304. && ::IsBadStringPtrW(pwszRealm, INTERNET_MAX_REALM_LENGTH))
  305. {
  306. dwErr = ERROR_INVALID_PARAMETER;
  307. goto cleanup;
  308. }
  309. // make sure AuthTargets are either Server or Proxy (not both)
  310. if ((AuthTargets != WINHTTP_AUTH_TARGET_SERVER)
  311. && (AuthTargets != WINHTTP_AUTH_TARGET_PROXY))
  312. {
  313. dwErr = ERROR_INVALID_PARAMETER;
  314. goto cleanup;
  315. }
  316. // convert Unicode strings to Ansi
  317. if (pwszUserName)
  318. {
  319. ALLOC_MB(pwszUserName, 0, mpUserName);
  320. if (!mpUserName.psStr)
  321. {
  322. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  323. goto cleanup;
  324. }
  325. UNICODE_TO_ANSI(pwszUserName, mpUserName);
  326. }
  327. if (pwszPassword)
  328. {
  329. ALLOC_MB(pwszPassword, 0, mpPassword);
  330. if (!mpPassword.psStr)
  331. {
  332. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  333. goto cleanup;
  334. }
  335. UNICODE_TO_ANSI(pwszPassword, mpPassword);
  336. }
  337. if (pwszRealm)
  338. {
  339. ALLOC_MB(pwszRealm, 0, mpRealm);
  340. if (!mpRealm.psStr)
  341. {
  342. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  343. goto cleanup;
  344. }
  345. UNICODE_TO_ANSI(pwszRealm, mpRealm);
  346. }
  347. fResult = ::WinHttpSetCredentialsA(hRequest, AuthTargets,
  348. AuthScheme, mpUserName.psStr, mpPassword.psStr, mpRealm.psStr);
  349. cleanup:
  350. if (dwErr!=ERROR_SUCCESS)
  351. {
  352. ::SetLastError(dwErr);
  353. DEBUG_ERROR(HTTP, dwErr);
  354. }
  355. DEBUG_LEAVE_API(fResult);
  356. return fResult;
  357. }