/*++ Copyright (c) 1994-2000 Microsoft Corporation Module Name: Creds.cxx Abstract: Contains the Creds APIs Contents: WinHttpSetCredentialsA WinHttpSetCredentials WinHttpQueryAuthSchemes Author: Biao Wang (biaow) 27-June-2000 Environment: Win32 user-mode DLL Revision History: 27-June-2000 biaow Created --*/ #include /* BOOLAPI WinHttpQueryAuthParams( IN HINTERNET hRequest, // HINTERNET handle returned by WinHttpOpenRequest IN DWORD AuthScheme, OUT LPVOID* pAuthParams // Scheme-specific Advanced auth parameters ) { //BUG-BUG Verify parameters // biaow: to implement this fully *pAuthParams = 0; return TRUE; } */ BOOLAPI WinHttpQueryAuthSchemes( IN HINTERNET hRequest, // HINTERNET handle returned by HttpOpenRequest. OUT LPDWORD lpdwSupportedSchemes,// a bitmap of available Authentication Schemes OUT LPDWORD lpdwPreferredScheme, // WinHttp's preferred Authentication Method OUT LPDWORD pdwAuthTarget ) { DEBUG_ENTER_API((DBG_API, Bool, "WinHttpQueryAuthSchemes", "%#x, %#x, %#x", hRequest, lpdwSupportedSchemes, lpdwPreferredScheme )); DWORD dwErr = ERROR_SUCCESS; HINTERNET hRequestMapped = NULL; BOOL fResult = FALSE; HINTERNET_HANDLE_TYPE HandleType; dwErr = ::MapHandleToAddress(hRequest, (LPVOID *)&hRequestMapped, FALSE); if ((dwErr != ERROR_SUCCESS) || (hRequestMapped == NULL)) { dwErr = ERROR_INVALID_HANDLE; goto cleanup; } HTTP_REQUEST_HANDLE_OBJECT * pRequest; if ((::RGetHandleType(hRequestMapped, &HandleType) != ERROR_SUCCESS) || (HandleType != TypeHttpRequestHandle)) { dwErr = ERROR_INVALID_HANDLE; goto cleanup; } pRequest = (HTTP_REQUEST_HANDLE_OBJECT *)hRequestMapped; if (::IsBadWritePtr(lpdwSupportedSchemes, sizeof(DWORD)) || ::IsBadWritePtr(lpdwPreferredScheme, sizeof(DWORD)) || ::IsBadWritePtr(pdwAuthTarget, sizeof(DWORD))) { dwErr = ERROR_INVALID_PARAMETER; goto cleanup; } if ((!pRequest->_SupportedSchemes) || (!pRequest->_PreferredScheme)) { dwErr = ERROR_INVALID_OPERATION; goto cleanup; } *lpdwSupportedSchemes = pRequest->_SupportedSchemes; *lpdwPreferredScheme = pRequest->_PreferredScheme; *pdwAuthTarget = pRequest->_AuthTarget; fResult = TRUE; cleanup: if (hRequestMapped) { DereferenceObject(hRequestMapped); } if (dwErr!= ERROR_SUCCESS) { ::SetLastError(dwErr); DEBUG_ERROR(HTTP, dwErr); } DEBUG_LEAVE_API(fResult); return fResult; } BOOL WinHttpSetCredentialsA ( IN HINTERNET hRequest, // HINTERNET handle returned by HttpOpenRequest. IN DWORD AuthTargets, // Only WINHTTP_AUTH_TARGET_SERVER and // WINHTTP_AUTH_TARGET_PROXY are supported // in this version and they are mutually // exclusive IN DWORD AuthScheme, // must be one of the supported Auth Schemes // returned from HttpQueryAuthSchemes(), Apps // should use the Preferred Scheme returned IN LPCSTR pszUserName, // 1) NULL if default creds is to be used, in // which case pszPassword will be ignored IN LPCSTR pszPassword, // 1) "" == Blank Passowrd; 2)Parameter ignored // if pszUserName is NULL; 3) Invalid to pass in // NULL if pszUserName is not NULL IN LPVOID pAuthParams ) { DEBUG_ENTER_API((DBG_API, Bool, "WinHttpSetCredentialsA", "%#x, %#x, %#x, %q, %q, %q", hRequest, AuthTargets, AuthScheme, pAuthParams, pszUserName, pszPassword )); // Note: we assume WinHttp will explose an Unicode only API, so this function // will not be called directly by Apps. If this assumption is no longer true // in future revisions, we need to add more elaborate parameter validation here. DWORD dwErr = ERROR_SUCCESS; BOOL fResult = FALSE; HINTERNET hRequestMapped = NULL; HTTP_REQUEST_HANDLE_OBJECT* pRequest; HINTERNET_HANDLE_TYPE HandleType; PSTR pszRealm = NULL; // validate API symantics if (pszUserName != NULL) { // in any case, it doesn't make sense (and therefore invalid) to pass // in a blank("") User Name if (::strlen(pszUserName) == 0) { dwErr = ERROR_INVALID_PARAMETER; goto cleanup; } else if (pszPassword == NULL) { // in any case, if an app passes in a UserName, it is invalid to // then pass in a NULL password (should use "" for blank passowrd) dwErr = ERROR_INVALID_PARAMETER; goto cleanup; } } // biaow: is blank scheme OK? // if an app picks BASIC auth, it must also supply an UserName and password if ((AuthScheme == WINHTTP_AUTH_SCHEME_BASIC) && (pszUserName == NULL)) { dwErr = ERROR_INVALID_PARAMETER; goto cleanup; } // default credentials (UserName/Password == NULL/NULL) are allowed only for // NTLM/NEGOTIATE/PASSPORT auth if (pszUserName == NULL) { if ((AuthScheme != WINHTTP_AUTH_SCHEME_NTLM) && (AuthScheme != WINHTTP_AUTH_SCHEME_NEGOTIATE) && (AuthScheme != WINHTTP_AUTH_SCHEME_PASSPORT)) { dwErr = ERROR_INVALID_PARAMETER; goto cleanup; } } dwErr = ::MapHandleToAddress(hRequest, (LPVOID *)&hRequestMapped, FALSE); if ((dwErr != ERROR_SUCCESS) || (hRequestMapped == NULL)) { dwErr = ERROR_INVALID_HANDLE; goto cleanup; } if ((::RGetHandleType(hRequestMapped, &HandleType) != ERROR_SUCCESS) || (HandleType != TypeHttpRequestHandle)) { dwErr = ERROR_INVALID_HANDLE; goto cleanup; } pRequest = reinterpret_cast(hRequestMapped); if (AuthScheme == WINHTTP_AUTH_SCHEME_DIGEST) { if (pAuthParams) { pszRealm = NewString((PCSTR)pAuthParams); } else { pszRealm = pRequest->_pszRealm; } if (pszRealm == NULL) { dwErr = ERROR_INVALID_PARAMETER; goto cleanup; } } if (AuthTargets == WINHTTP_AUTH_TARGET_PROXY) { delete pRequest->_pProxyCreds; pRequest->_pProxyCreds = New WINHTTP_REQUEST_CREDENTIALS(AuthScheme, pszRealm, pszUserName, pszPassword); if (pRequest->_pProxyCreds == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto cleanup; } } else { delete pRequest->_pServerCreds; pRequest->_pServerCreds = New WINHTTP_REQUEST_CREDENTIALS(AuthScheme, pszRealm, pszUserName, pszPassword); if (pRequest->_pServerCreds == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto cleanup; } } pRequest->_PreferredScheme = 0x00000000; pRequest->_SupportedSchemes = 0x00000000; pRequest->_AuthTarget = 0x00000000; if (pRequest->_pszRealm) { FREE_MEMORY(pRequest->_pszRealm); pRequest->_pszRealm = NULL; } fResult = TRUE; cleanup: if (hRequestMapped) { DereferenceObject(hRequestMapped); } if (dwErr!=ERROR_SUCCESS) { ::SetLastError(dwErr); DEBUG_ERROR(HTTP, dwErr); } DEBUG_LEAVE_API(fResult); return fResult; } BOOLAPI WinHttpSetCredentials( IN HINTERNET hRequest, // HINTERNET handle returned by HttpOpenRequest. IN DWORD AuthTargets, // Only WINHTTP_AUTH_TARGET_SERVER and // WINHTTP_AUTH_TARGET_PROXY are supported // in this version and they are mutually // exclusive IN DWORD AuthScheme, // must be one of the supported Auth Schemes // returned from HttpQueryAuthSchemes(), Apps // should use the Preferred Scheme returned IN LPCWSTR pwszUserName, // 1) NULL if default creds is to be used, in // which case pszPassword will be ignored IN LPCWSTR pwszPassword, // 1) "" == Blank Passowrd; 2)Parameter ignored // if pszUserName is NULL; 3) Invalid to pass in // NULL if pszUserName is not NULL IN LPVOID pAuthParams ) { DEBUG_ENTER_API((DBG_API, Bool, "WinHttpSetCredentials", "%#x, %#x, %#x, %wq, %wq, %wq", hRequest, AuthTargets, AuthScheme, pAuthParams, pwszUserName, pwszPassword )); DWORD dwErr = ERROR_SUCCESS; BOOL fResult = FALSE; LPCWSTR pwszRealm = NULL; MEMORYPACKET mpRealm, mpUserName, mpPassword; if (!hRequest) { dwErr = ERROR_INVALID_HANDLE; goto cleanup; } // make sure only one bit in AuthScheme is set if ((AuthScheme & (AuthScheme - 1)) != 0x00000000) { dwErr = ERROR_INVALID_PARAMETER; goto cleanup; } // make sure the input strings are valid if (pwszUserName && ::IsBadStringPtrW(pwszUserName, INTERNET_MAX_USER_NAME_LENGTH)) { dwErr = ERROR_INVALID_PARAMETER; goto cleanup; } if (pwszPassword && ::IsBadStringPtrW(pwszPassword, INTERNET_MAX_PASSWORD_LENGTH)) { dwErr = ERROR_INVALID_PARAMETER; goto cleanup; } if ((AuthScheme == WINHTTP_AUTH_SCHEME_DIGEST) && pAuthParams) { pwszRealm = (LPCWSTR)pAuthParams; } if (pwszRealm && ::IsBadStringPtrW(pwszRealm, INTERNET_MAX_REALM_LENGTH)) { dwErr = ERROR_INVALID_PARAMETER; goto cleanup; } // make sure AuthTargets are either Server or Proxy (not both) if ((AuthTargets != WINHTTP_AUTH_TARGET_SERVER) && (AuthTargets != WINHTTP_AUTH_TARGET_PROXY)) { dwErr = ERROR_INVALID_PARAMETER; goto cleanup; } // convert Unicode strings to Ansi if (pwszUserName) { ALLOC_MB(pwszUserName, 0, mpUserName); if (!mpUserName.psStr) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto cleanup; } UNICODE_TO_ANSI(pwszUserName, mpUserName); } if (pwszPassword) { ALLOC_MB(pwszPassword, 0, mpPassword); if (!mpPassword.psStr) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto cleanup; } UNICODE_TO_ANSI(pwszPassword, mpPassword); } if (pwszRealm) { ALLOC_MB(pwszRealm, 0, mpRealm); if (!mpRealm.psStr) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto cleanup; } UNICODE_TO_ANSI(pwszRealm, mpRealm); } fResult = ::WinHttpSetCredentialsA(hRequest, AuthTargets, AuthScheme, mpUserName.psStr, mpPassword.psStr, mpRealm.psStr); cleanup: if (dwErr!=ERROR_SUCCESS) { ::SetLastError(dwErr); DEBUG_ERROR(HTTP, dwErr); } DEBUG_LEAVE_API(fResult); return fResult; }