diff options
author | Jean-Francois Mauguit <jfmauguit@mac.com> | 2024-09-24 09:03:25 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-24 09:03:25 -0400 |
commit | bab614c421ed7ae329d26bf028c4a3b1d2450f5a (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/auth/Loginbox/resultWinampAuth.cpp | |
parent | 4bde6044fddf053f31795b9eaccdd2a5a527d21f (diff) | |
parent | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (diff) | |
download | winamp-bab614c421ed7ae329d26bf028c4a3b1d2450f5a.tar.gz |
Merge pull request #5 from WinampDesktop/community
Merge to main
Diffstat (limited to 'Src/auth/Loginbox/resultWinampAuth.cpp')
-rw-r--r-- | Src/auth/Loginbox/resultWinampAuth.cpp | 574 |
1 files changed, 574 insertions, 0 deletions
diff --git a/Src/auth/Loginbox/resultWinampAuth.cpp b/Src/auth/Loginbox/resultWinampAuth.cpp new file mode 100644 index 00000000..4c04e0e4 --- /dev/null +++ b/Src/auth/Loginbox/resultWinampAuth.cpp @@ -0,0 +1,574 @@ +#include "./resultWinampAuth.h" +#include "./common.h" +#include "./commandWinampAuth.h" +#include "./loginData.h" +#include "./dataCredentials.h" +#include "./loginCredentials.h" +#include "./loginbox.h" + +#include "../resource.h" + +LoginResultWinampAuth::LoginResultWinampAuth(api_auth *auth, LoginDataCredentials *pInput, Callback fnCallback, void *pUser) + : ref(1), authApi(auth), input(pInput), callback(fnCallback), user(pUser), + thread(NULL), abort(NULL), completed(NULL), credentials(NULL), authCode(AUTH_NOT_AUTHORIZED), statusCookie(0) +{ + InitializeCriticalSection(&lock); + + authApi->AddRef(); + input->AddRef(); +} + +LoginResultWinampAuth::~LoginResultWinampAuth() +{ + if (NULL != abort) + CloseHandle(abort); + + if (NULL != completed) + CloseHandle(completed); + + if (NULL != thread) + CloseHandle(thread); + + authApi->Release(); + input->Release(); + + if (NULL != credentials) + credentials->Release(); + + DeleteCriticalSection(&lock); +} + +HRESULT LoginResultWinampAuth::CreateInstance(LoginData *input, Callback callback, void *user, LoginResultWinampAuth **instance) +{ + if (NULL == instance) return E_POINTER; + *instance = NULL; + + LoginDataCredentials *credentialsInput; + if (NULL == input || FAILED(input->QueryInterface(IID_LoginDataCredentials, (void**)&credentialsInput))) + return E_INVALIDARG; + + HRESULT hr; + api_auth *authApi; + + HWND hLoginbox = credentialsInput->GetLoginbox(); + if (NULL == hLoginbox || FALSE == LoginBox_GetAuthApi(hLoginbox, &authApi)) + hr = E_FAIL; + else + { + LoginResultWinampAuth *result = new LoginResultWinampAuth(authApi, credentialsInput, callback, user); + if (NULL == result) + hr = E_OUTOFMEMORY; + else + { + hr = result->Start(); + if (FAILED(hr)) + { + result->Release(); + result = NULL; + } + else + { + *instance = result; + } + } + + authApi->Release(); + } + credentialsInput->Release(); + return hr; +} + +STDMETHODIMP_(ULONG) LoginResultWinampAuth::AddRef(void) +{ + return InterlockedIncrement((LONG*)&ref); +} + +STDMETHODIMP_(ULONG) LoginResultWinampAuth::Release(void) +{ + if (0 == ref) + return ref; + + LONG r = InterlockedDecrement((LONG*)&ref); + if (0 == r) + delete(this); + + return r; +} + +STDMETHODIMP LoginResultWinampAuth::QueryInterface(REFIID riid, PVOID *ppvObject) +{ + if (NULL == ppvObject) + return E_POINTER; + + if (IsEqualIID(riid, LCUID_WINAMPAUTH)) + *ppvObject = static_cast<LoginResultWinampAuth*>(this); + else if (IsEqualIID(riid, IID_IUnknown)) + *ppvObject = static_cast<IUnknown*>(this); + else + { + *ppvObject = NULL; + return E_NOINTERFACE; + } + + if (NULL == *ppvObject) + return E_UNEXPECTED; + + AddRef(); + return S_OK; +} + +size_t LoginResultWinampAuth::Wasabi_AddRef() +{ + return AddRef(); +} + +size_t LoginResultWinampAuth::Wasabi_Release() +{ + return Release(); +} + +int LoginResultWinampAuth::Wasabi_QueryInterface(GUID iid, void **object) +{ + return QueryInterface(iid, object); +} + +HRESULT LoginResultWinampAuth::Start() +{ + //HRESULT hr; + HANDLE threadCopy = NULL; + + input->SetStatus(MAKEINTRESOURCE(IDS_STATUS_INITIALIZING)); + EnterCriticalSection(&lock); + if (NULL != thread) + { + //hr = E_PENDING; + } + else + { + AddRef(); + thread = CreateThread(NULL, 0, WinampAuth_ThreadProcCallback, this, CREATE_SUSPENDED, NULL); + if (NULL == thread) + { + Release(); + } + else + { + if (0 == DuplicateHandle(GetCurrentProcess(), thread, GetCurrentProcess(), &threadCopy, 0, FALSE, DUPLICATE_SAME_ACCESS)) + { + ResumeThread(thread); // grr... + threadCopy = NULL; + } + } + } + LeaveCriticalSection(&lock); + + if (NULL != threadCopy) + { + ResumeThread(threadCopy); + CloseHandle(threadCopy); + } + + return S_OK; +} +DWORD LoginResultWinampAuth::ThreadProc() +{ + Callback callbackCopy(NULL); + HANDLE completedCopy(NULL); + INT resultCode = AUTH_SUCCESS; + LPWSTR username(NULL), password(NULL); + + api_auth::AuthResults authResults; + SecureZeroMemory(&authResults, sizeof(authResults)); + + EnterCriticalSection(&lock); + authCode = AUTH_NOT_AUTHORIZED; + if (NULL != credentials) + { + credentials->Release(); + credentials = NULL; + } + LeaveCriticalSection(&lock); + + username = GetUsername(input->GetUsername(), &resultCode); + + if (AUTH_SUCCESS == resultCode) + password = GetPassword(input->GetPassword(), &resultCode); + + if (AUTH_SUCCESS == resultCode) + { + if (NULL == input->GetContext()) + { + resultCode = authApi->Login(username, password, &authResults, this); + } + else + { + LPWSTR passcode = GetPasscode(input->GetPasscode(), &resultCode); + if (AUTH_SUCCESS == resultCode) + { + resultCode = authApi->LoginSecurID(username, password, input->GetContext(), passcode, &authResults, this); + LoginBox_FreeStringSecure(passcode); + } + } + } + + EnterCriticalSection(&lock); + + authCode = resultCode; + switch(authCode) + { + case AUTH_SUCCESS: + { + GUID realm; + if (FAILED(input->GetRealm(&realm)) || + FAILED(LoginCredentials::CreateInstance(&realm, username, authResults.session_key, + authResults.token, authResults.expire, &credentials))) + { + authCode = AUTH_UNEXPECTED; + } + } + break; + case AUTH_SECURID: + if(FAILED(input->SetContext(authResults.context))) + authCode = AUTH_NOT_AUTHORIZED; + break; + } + + INT statusId; + switch(authCode) + { + case AUTH_SUCCESS: statusId = IDS_STATUS_SUCCEEDED; break; + case AUTH_SECURID: statusId = IDS_STATUS_PASSCODE_REQUIRED; break; + case AUTH_ABORT: statusId = IDS_STATUS_ABORTED; break; + default: statusId = IDS_STATUS_FAILED; break; + } + input->SetStatus(MAKEINTRESOURCE(statusId)); + + CloseHandle(thread); + thread = NULL; + callbackCopy = callback; + + if (NULL == completed || FALSE == DuplicateHandle(GetCurrentProcess(), completed, + GetCurrentProcess(), &completedCopy, 0, FALSE, DUPLICATE_SAME_ACCESS)) + { + completedCopy = NULL; + } + + LeaveCriticalSection(&lock); + + SecureZeroMemory(&authResults, sizeof(authResults)); + LoginBox_FreeStringSecure(username); + LoginBox_FreeStringSecure(password); + + if (NULL != completedCopy) + { + SetEvent(completedCopy); + CloseHandle(completedCopy); + } + + if (NULL != callbackCopy) + callbackCopy(this); + + return 0; +} + +HRESULT LoginResultWinampAuth::GetWaitHandle(HANDLE *handle) +{ + if (NULL == handle) + return E_POINTER; + + HRESULT hr = S_OK; + + EnterCriticalSection(&lock); + + if (NULL == completed) + { + completed = CreateEvent(NULL, TRUE, (S_OK == IsCompleted()), NULL); + if (NULL == completed) + { + *handle = NULL; + DWORD error = GetLastError(); + hr = HRESULT_FROM_WIN32(error); + } + } + + if (SUCCEEDED(hr) && + FALSE == DuplicateHandle(GetCurrentProcess(), completed, + GetCurrentProcess(), handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) + { + *handle = NULL; + DWORD error = GetLastError(); + hr = HRESULT_FROM_WIN32(error); + } + + LeaveCriticalSection(&lock); + return hr; +} + +HRESULT LoginResultWinampAuth::GetUser(void **pUser) +{ + if (NULL == pUser) return E_POINTER; + EnterCriticalSection(&lock); + *pUser = user; + LeaveCriticalSection(&lock); + return S_OK; +} + +HRESULT LoginResultWinampAuth::RequestAbort(BOOL fDrop) +{ + HRESULT hr; + EnterCriticalSection(&lock); + if (NULL == abort) + { + abort = CreateEvent(NULL, TRUE, FALSE, NULL); + if (NULL == abort) + { + DWORD error = GetLastError(); + hr = HRESULT_FROM_WIN32(error); + } + } + + if (NULL != abort && FALSE == SetEvent(abort)) + { + DWORD error = GetLastError(); + hr = HRESULT_FROM_WIN32(error); + } + else + { + input->SetStatus(MAKEINTRESOURCE(IDS_STATUS_ABORTING)); + } + + if (FALSE != fDrop) + { + callback = NULL; + user = NULL; + } + + LeaveCriticalSection(&lock); + return hr; +} + +HRESULT LoginResultWinampAuth::IsCompleted() +{ + return (NULL == thread) ? S_OK : S_FALSE; +} + +HRESULT LoginResultWinampAuth::IsAborting() +{ + return IsAbortingEx(0); +} + +HRESULT LoginResultWinampAuth::IsAbortingEx(UINT waitMs) +{ + return (NULL != abort && WAIT_OBJECT_0 == WaitForSingleObjectEx(abort, waitMs, TRUE))? + S_OK : S_FALSE; +} + +HRESULT LoginResultWinampAuth::GetLoginData(LoginData **loginData) +{ + if (NULL == loginData) return E_POINTER; + EnterCriticalSection(&lock); + + *loginData = input; + if (NULL != input) + input->AddRef(); + + LeaveCriticalSection(&lock); + return S_OK; +} + +HRESULT LoginResultWinampAuth::GetResult(INT *pAuthCode, LoginCredentials **ppCredentials) +{ + if (S_OK != IsCompleted()) + return E_PENDING; + + EnterCriticalSection(&lock); + + if (NULL != pAuthCode) + *pAuthCode = authCode; + + if (NULL != ppCredentials) + { + *ppCredentials = credentials; + if (NULL != credentials) + credentials->AddRef(); + } + + LeaveCriticalSection(&lock); + + return S_OK; +} + +int LoginResultWinampAuth::Event_AuthConnecting() +{ + if (S_OK == IsAbortingEx(0)) + return 1; + + input->SetStatus(MAKEINTRESOURCE(IDS_STATUS_CONNECTING)); + return 0; +} + +int LoginResultWinampAuth::Event_AuthSending() +{ + if (S_OK == IsAbortingEx(0)) + return 1; + + input->SetStatus(MAKEINTRESOURCE(IDS_STATUS_SENDING)); + return 0; +} + +int LoginResultWinampAuth::Event_AuthReceiving() +{ + if (S_OK == IsAbortingEx(0)) + return 1; + + input->SetStatus(MAKEINTRESOURCE(IDS_STATUS_RECEIVING)); + return 0; +} + +int LoginResultWinampAuth::Event_AuthIdle() +{ + if (S_OK == IsAbortingEx(50)) + return 1; + + return 0; +} + +LPWSTR LoginResultWinampAuth::GetUsername(LPCWSTR pszInput, INT *authError) +{ + return MakeAuthParam(pszInput, -1, 3, 48, TRUE, TRUE, (0xFFFF & ~C1_CNTRL), AUTH_USERNAME, authError); +} + +LPWSTR LoginResultWinampAuth::GetPassword(LPCWSTR pszInput, INT *authError) +{ + return MakeAuthParam(pszInput, -1, 6, 48, TRUE, FALSE, (0xFFFF & ~C1_CNTRL), AUTH_PASSWORD, authError); +} + +LPWSTR LoginResultWinampAuth::GetPasscode(LPCWSTR pszInput, INT *authError) +{ + return MakeAuthParam(pszInput, -1, 6, 6, FALSE, FALSE, C1_DIGIT, AUTH_PASSCODE, authError); +} + +LPWSTR LoginResultWinampAuth::MakeAuthParam(LPCWSTR pszInput, INT cchInput, INT min, INT max, BOOL removeSpaces, BOOL firstLetter, WORD typeMask, INT errorBase, INT *authError) +{ + if (cchInput < 0 || NULL == pszInput) + cchInput = (NULL != pszInput) ? lstrlen(pszInput) : 0; + + if (cchInput < min || (FALSE == removeSpaces && cchInput > max)) + { + if (NULL != authError) + *authError = errorBase + ((cchInput < min) ? AUTHPARAM_TOOSHORT : AUTHPARAM_TOOLONG); + return NULL; + } + + WORD *info = (WORD*)calloc(cchInput, sizeof(WORD)); + if (NULL == info) + { + if (NULL != authError) *authError = AUTH_UNEXPECTED; + return NULL; + } + + if (FALSE == GetStringTypeW(CT_CTYPE1, pszInput, cchInput, info)) + { + free(info); + if (NULL != authError) *authError = AUTH_UNEXPECTED; + return NULL; + } + + INT error = AUTH_SUCCESS; + LPWSTR dest = NULL; + + BOOL firstChecked = FALSE; + INT cchSpaces = 0; + for (INT i = 0; i < cchInput; i++) + { + if (FALSE != removeSpaces && 0 != (C1_SPACE & info[i])) + cchSpaces++; + else if (0 == (typeMask & info[i])) + { + error = errorBase + AUTHPARAM_BADFORMAT; + break; + } + else + { + if (FALSE != firstLetter && FALSE == firstChecked) + { + if (0 == (C1_ALPHA & info[i])) + { + error = errorBase + AUTHPARAM_BADFORMAT; + break; + } + firstChecked = TRUE; + } + } + } + + if (AUTH_SUCCESS == error) + { + INT cchTotal = cchInput - cchSpaces; + if (cchTotal < min) + error = errorBase + AUTHPARAM_TOOSHORT; + else if (cchTotal > max) + error = errorBase + AUTHPARAM_TOOLONG; + else + { + dest = LoginBox_MallocString(cchTotal + 1); + if (NULL == dest) + error = AUTH_UNEXPECTED; + else + { + if (FALSE != removeSpaces) + { + LPCWSTR s = pszInput; + LPWSTR d = dest; + for (INT i = 0; i < cchInput; i++, s++) + { + if (0 == (C1_SPACE & info[i])) + { + *d = *s; + d++; + } + } + *d = L'\0'; + } + else + { + CopyMemory(dest, pszInput, (cchInput * sizeof(WCHAR))); + dest[cchInput] = L'\0'; + } + } + } + } + + + free(info); + + if (NULL != authError) + *authError = error; + + return dest; +} + + +static DWORD WINAPI WinampAuth_ThreadProcCallback(void *param) +{ + LoginResultWinampAuth *result =(LoginResultWinampAuth*)param; + if (NULL == result) return 1; + + INT exitCode = result->ThreadProc(); + result->Release(); + return exitCode; +} + + +#define CBCLASS LoginResultWinampAuth +START_DISPATCH; +CB(ADDREF, Wasabi_AddRef) +CB(RELEASE, Wasabi_Release) +CB(QUERYINTERFACE, Wasabi_QueryInterface) +CB(ONCONNECTING, Event_AuthConnecting) +CB(ONSENDING, Event_AuthSending) +CB(ONRECEIVING, Event_AuthReceiving) +CB(ONIDLE, Event_AuthIdle) +END_DISPATCH; +#undef CBCLASS + |