CH-J Server Managerуправление серверами через SSH
Меню
Публикуемый источник

CH-J Server Manager

Просмотр каталогов и файлов для конкретного выпуска приложения.

Загрузка источника ZIP
CH-J / Server Manager 377 файлы
core-20261019T111616Z-160a00bfcddc Добавлено: · Построено:
windows.cpp Добавлено: Дата нерегистрации 8,5 KB · 117 Линии
Код Загрузить файл
1#define WIN32_LEAN_AND_MEAN
2#define NOMINMAX
3#include <windows.h>
4#include <wincred.h>
5#include <wincrypt.h>
6#include <UserConsentVerifierInterop.h>
7#include <winrt/base.h>
8#include <winrt/Windows.Foundation.h>
9#include <winrt/Windows.Data.Json.h>
10#include <winrt/Windows.Security.Credentials.UI.h>
11#include <iostream>
12#include <string>
13#include <vector>
14#include <stdexcept>
15using namespace winrt;
16using namespace Windows::Foundation;
17using namespace Windows::Data::Json;
18using namespace Windows::Security::Credentials::UI;
19struct Failure : std::runtime_error { using std::runtime_error::runtime_error; };
20void fail(char const* code) { throw Failure(code); }
21std::vector<BYTE> decode(hstring const& value) {
22 DWORD size=0;
23 if(!CryptStringToBinaryW(value.c_str(),static_cast<DWORD>(value.size()),CRYPT_STRING_BASE64|CRYPT_STRING_STRICT,nullptr,&size,nullptr,nullptr) || size!=32) fail("BIOMETRIC_INVALID_KEY");
24 std::vector<BYTE> data(size);
25 if(!CryptStringToBinaryW(value.c_str(),static_cast<DWORD>(value.size()),CRYPT_STRING_BASE64|CRYPT_STRING_STRICT,data.data(),&size,nullptr,nullptr)) fail("BIOMETRIC_INVALID_KEY");
26 return data;
28std::string encode(BYTE const* data,DWORD size) {
29 DWORD count=0;check_bool(CryptBinaryToStringA(data,size,CRYPT_STRING_BASE64|CRYPT_STRING_NOCRLF,nullptr,&count));
30 std::string out(count,'\0');check_bool(CryptBinaryToStringA(data,size,CRYPT_STRING_BASE64|CRYPT_STRING_NOCRLF,out.data(),&count));out.resize(count-1);return out;
32LRESULT CALLBACK promptProc(HWND window,UINT message,WPARAM wparam,LPARAM lparam) {return DefWindowProcW(window,message,wparam,lparam);}
33// UserConsentVerifier must be parented to a window of the calling process: the Electron
34// HWND belongs to another process, so Hello may fail or open behind the app. Create an
35// invisible helper-owned window over the app window instead. The helper was started by
36// the foreground app, so Windows lets it take the foreground for the Hello dialog.
37HWND promptWindow(HWND owner) {
38 WNDCLASSEXW type{sizeof(type)};type.lpfnWndProc=promptProc;type.hInstance=GetModuleHandleW(nullptr);type.lpszClassName=L"CHJBiometricPrompt";RegisterClassExW(&type);
39 RECT bounds{};GetWindowRect(owner,&bounds);
40 HWND window=CreateWindowExW(WS_EX_TOOLWINDOW|WS_EX_LAYERED|WS_EX_TOPMOST,type.lpszClassName,L"CH-J Server Manager",WS_POPUP,(bounds.left+bounds.right)/2,(bounds.top+bounds.bottom)/2,1,1,nullptr,nullptr,type.hInstance,nullptr);
41 if(!window)fail("BIOMETRIC_FAILED");
42 SetLayeredWindowAttributes(window,0,0,LWA_ALPHA);ShowWindow(window,SW_SHOWNORMAL);SetForegroundWindow(window);
43 return window;
45template<typename Operation> void pumpUntilDone(Operation const& operation) {
46 HANDLE done=CreateEventW(nullptr,TRUE,FALSE,nullptr);if(!done)fail("BIOMETRIC_FAILED");
47 operation.Completed([done](auto&&,auto&&){SetEvent(done);});
48 for(int tick=0;;tick++) {
49 DWORD wait=MsgWaitForMultipleObjects(1,&done,FALSE,100,QS_ALLINPUT);
50 if(wait==WAIT_OBJECT_0)break;
51 MSG message;while(PeekMessageW(&message,nullptr,0,0,PM_REMOVE)){TranslateMessage(&message);DispatchMessageW(&message);}
52 // Bring the Hello dialog to the front once it appears (first ~3 s).
53 if(tick<30){HWND dialog=FindWindowW(L"Credential Dialog Xaml Host",nullptr);if(dialog)SetForegroundWindow(dialog);}
54 }
55 CloseHandle(done);
57void authenticate(JsonObject const& request) {
58 HWND hwnd=reinterpret_cast<HWND>(std::stoull(to_string(request.GetNamedString(L"hwnd"))));
59 DWORD owner=0;GetWindowThreadProcessId(hwnd,&owner);
60 if(!IsWindow(hwnd) || owner!=static_cast<DWORD>(request.GetNamedNumber(L"pid"))) fail("BIOMETRIC_CANCELLED");
61 HWND window=promptWindow(hwnd);
62 UserConsentVerificationResult result;
63 try {
64 auto interop=get_activation_factory<UserConsentVerifier,IUserConsentVerifierInterop>();
65 IAsyncOperation<UserConsentVerificationResult> operation{nullptr};
66 auto reason=request.GetNamedString(L"reason");
67 check_hresult(interop->RequestVerificationForWindowAsync(window,reinterpret_cast<HSTRING>(get_abi(reason)),guid_of<decltype(operation)>(),put_abi(operation)));
68 pumpUntilDone(operation);result=operation.GetResults();
69 } catch(hresult_error const&) {DestroyWindow(window);fail("BIOMETRIC_FAILED");}
70 DestroyWindow(window);
71 if(result==UserConsentVerificationResult::Verified) return; // Includes Hello PIN.
72 if(result==UserConsentVerificationResult::Canceled) fail("BIOMETRIC_CANCELLED");
73 if(result==UserConsentVerificationResult::DeviceBusy) fail("BIOMETRIC_DEVICE_UNAVAILABLE");
74 if(result==UserConsentVerificationResult::RetriesExhausted) fail("BIOMETRIC_DEVICE_UNAVAILABLE");
75 if(result==UserConsentVerificationResult::NotConfiguredForUser) fail("BIOMETRIC_NO_ENROLLMENT");
76 fail("BIOMETRIC_FAILED");
78JsonObject run(JsonObject const& request) {
79 auto op=request.GetNamedString(L"op");JsonObject response;response.SetNamedValue(L"ok",JsonValue::CreateBooleanValue(true));
80 if(op==L"status") {
81 auto result=UserConsentVerifier::CheckAvailabilityAsync().get();
82 response.SetNamedValue(L"available",JsonValue::CreateBooleanValue(result==UserConsentVerifierAvailability::Available));
83 response.SetNamedValue(L"code",JsonValue::CreateStringValue(result==UserConsentVerifierAvailability::Available?L"BIOMETRIC_AVAILABLE":result==UserConsentVerifierAvailability::NotConfiguredForUser?L"BIOMETRIC_NO_ENROLLMENT":result==UserConsentVerifierAvailability::DeviceBusy?L"BIOMETRIC_DEVICE_UNAVAILABLE":L"BIOMETRIC_UNAVAILABLE"));return response;
84 }
85 if(op==L"authenticate") {authenticate(request);return response;}
86 auto entry=request.GetNamedString(L"entryId");if(entry.size()!=64 || std::wstring(entry).find_first_not_of(L"0123456789abcdef")!=std::wstring::npos)fail("BIOMETRIC_FAILED");
87 auto target=L"CHJ.ServerManager.Vault.Biometry.v1:"+std::wstring(entry);
88 DATA_BLOB entropy{static_cast<DWORD>(entry.size()*sizeof(wchar_t)),reinterpret_cast<BYTE*>(const_cast<wchar_t*>(entry.c_str()))};
89 if(op==L"remove") {if(!CredDeleteW(target.c_str(),CRED_TYPE_GENERIC,0) && GetLastError()!=ERROR_NOT_FOUND)fail("BIOMETRIC_CREDENTIAL_FAILED");return response;}
90 if(op==L"store") {
91 auto bytes=decode(request.GetNamedString(L"key"));DATA_BLOB input{static_cast<DWORD>(bytes.size()),bytes.data()},output{};
92 if(!CryptProtectData(&input,L"CH-J Vault",&entropy,nullptr,nullptr,CRYPTPROTECT_UI_FORBIDDEN,&output)){SecureZeroMemory(bytes.data(),bytes.size());fail("BIOMETRIC_CREDENTIAL_FAILED");}
93 SecureZeroMemory(bytes.data(),bytes.size());
94 CREDENTIALW credential{};credential.Type=CRED_TYPE_GENERIC;credential.TargetName=target.data();credential.CredentialBlobSize=output.cbData;credential.CredentialBlob=output.pbData;credential.Persist=CRED_PERSIST_LOCAL_MACHINE;credential.UserName=const_cast<LPWSTR>(L"CH-J Server Manager");
95 BOOL ok=CredWriteW(&credential,0);SecureZeroMemory(output.pbData,output.cbData);LocalFree(output.pbData);if(!ok)fail("BIOMETRIC_CREDENTIAL_FAILED");return response;
96 }
97 if(op==L"retrieve") {
98 authenticate(request);PCREDENTIALW credential=nullptr;
99 if(!CredReadW(target.c_str(),CRED_TYPE_GENERIC,0,&credential))fail(GetLastError()==ERROR_NOT_FOUND?"BIOMETRIC_ENROLLMENT_INVALIDATED":"BIOMETRIC_CREDENTIAL_FAILED");
100 DATA_BLOB input{credential->CredentialBlobSize,credential->CredentialBlob},output{};
101 BOOL ok=CryptUnprotectData(&input,nullptr,&entropy,nullptr,nullptr,CRYPTPROTECT_UI_FORBIDDEN,&output);CredFree(credential);
102 if(!ok)fail("BIOMETRIC_CREDENTIAL_FAILED");
103 if(output.cbData!=32){SecureZeroMemory(output.pbData,output.cbData);LocalFree(output.pbData);fail("BIOMETRIC_INVALID_KEY");}
104 auto encoded=encode(output.pbData,output.cbData);SecureZeroMemory(output.pbData,output.cbData);LocalFree(output.pbData);
105 response.SetNamedValue(L"key",JsonValue::CreateStringValue(to_hstring(encoded)));SecureZeroMemory(encoded.data(),encoded.size());return response;
106 }
107 fail("BIOMETRIC_FAILED");return response;
109int main() {
110 try {
111 init_apartment(apartment_type::multi_threaded);
112 std::string input;std::getline(std::cin,input);if(input.size()>4096)fail("BIOMETRIC_FAILED");
113 auto request=JsonObject::Parse(to_hstring(input));SecureZeroMemory(input.data(),input.size());
114 auto response=run(request);std::cout<<to_string(response.Stringify());return 0;
115 } catch(Failure const& e) {std::cout<<"{\"ok\":false,\"code\":\""<<e.what()<<"\"}";return 1;}
116 catch(...) {std::cout<<"{\"ok\":false,\"code\":\"BIOMETRIC_UNAVAILABLE\"}";return 1;}
SHA-256571d72e78c05f8c51d15f60fbdc073e8c762c5e0bae01ded5687b8a58ebd4918

CH-J Proprietary Software License 1.14 · Источник представлен в CH-J Proprietary Software License 1.14. Его наличие не изменяет лицензионных условий и не предоставляет дополнительных прав.

Архив SHA-256a9605c0870a223b6a8542bb0705edd51d8b04f3069582653417a8397fabcc09a
Файлы