mirror of https://github.com/OpenVPN/openvpn-gui
178 lines
5.8 KiB
C++
178 lines
5.8 KiB
C++
/*
|
|
* OpenVPN-PLAP-Provider
|
|
*
|
|
* Copyright (C) 2019-2022 Selva Nair <selva.nair@gmail.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program (see the file COPYING included with this
|
|
* distribution); if not, write to the Free Software Foundation, Inc.,
|
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#undef WIN32_LEAN_AND_MEAN
|
|
|
|
#include <initguid.h>
|
|
#include "plap_common.h"
|
|
#include <windows.h>
|
|
#include <credentialprovider.h>
|
|
#include <fcntl.h>
|
|
#include <io.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <time.h>
|
|
|
|
#define error_return(fname, hr) do { fwprintf(stdout, L"Error in %ls: status = 0x%08x", fname, hr);\
|
|
return 1;} while (0)
|
|
typedef HRESULT (WINAPI * f_func)(REFCLSID rclsid, REFIID riid, LPVOID* ppv);
|
|
|
|
class MyQueryContinue : public IQueryContinueWithStatus
|
|
{
|
|
public:
|
|
STDMETHODIMP_(ULONG) AddRef() {
|
|
return InterlockedIncrement(&ref_count);
|
|
}
|
|
STDMETHODIMP_(ULONG) Release() {
|
|
int count = InterlockedDecrement(&ref_count);
|
|
if (ref_count == 0) delete this;
|
|
return count;
|
|
}
|
|
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { return E_FAIL; }
|
|
STDMETHODIMP QueryContinue() {return time(NULL) > timeout ? S_FALSE : S_OK;}
|
|
STDMETHODIMP SetStatusMessage(const wchar_t *ws) { wprintf(L"%ls\r", ws); return S_OK; }
|
|
MyQueryContinue() : ref_count(1) {};
|
|
time_t timeout;
|
|
|
|
private:
|
|
~MyQueryContinue()=default;
|
|
LONG ref_count;
|
|
};
|
|
|
|
static int test_provider(IClassFactory *cf)
|
|
{
|
|
assert(cf != NULL);
|
|
ICredentialProvider *o = NULL;
|
|
HRESULT hr;
|
|
|
|
hr = cf->CreateInstance(NULL, IID_ICredentialProvider, (void**) &o);
|
|
|
|
if (!SUCCEEDED(hr)) error_return(L"IID_ICredentialProvider", hr);
|
|
|
|
hr = o->SetUsageScenario(CPUS_PLAP, 0);
|
|
if (!SUCCEEDED(hr)) error_return(L"SetUsageScenario", hr);
|
|
|
|
DWORD count, def;
|
|
BOOL auto_def;
|
|
hr = o->GetCredentialCount(&count, &def, &auto_def);
|
|
if (!SUCCEEDED(hr)) error_return(L"GetCredentialCount", hr);
|
|
|
|
fwprintf(stdout, L"credential count = %lu, default = %d, autologon = %d\n", count, (int) def, auto_def);
|
|
if (count < 1) fwprintf(stdout, L"No persistent configs found!\n");
|
|
|
|
ICredentialProviderCredential *c = NULL;
|
|
MyQueryContinue *qc = new MyQueryContinue();
|
|
for (DWORD i = 0; i < count; i++)
|
|
{
|
|
hr = o->GetCredentialAt(i, &c);
|
|
if (!SUCCEEDED(hr)) error_return(L"GetCredentialAt", hr);
|
|
|
|
fwprintf(stdout, L"credential # = %lu: ", i);
|
|
wchar_t *ws;
|
|
|
|
for (DWORD j = 0; j < 4; j++)
|
|
{
|
|
hr = c->GetStringValue(j, &ws);
|
|
if (!SUCCEEDED(hr)) error_return(L"GetStringValue", hr);
|
|
CoTaskMemFree(ws);
|
|
}
|
|
|
|
/* test getbitmap */
|
|
HBITMAP bmp;
|
|
hr = c->GetBitmapValue(0, &bmp);
|
|
if (!SUCCEEDED(hr))
|
|
fwprintf(stdout, L"Warning: could not get bitmap"); /* not fatal */
|
|
else
|
|
DeleteObject(bmp);
|
|
|
|
/* set a time out so that we can move to next config in case */
|
|
qc->timeout = time(NULL) + 20;
|
|
|
|
/* get a connection instance and call connect on it */
|
|
IConnectableCredentialProviderCredential *c1 = NULL;
|
|
hr = c->QueryInterface(IID_IConnectableCredentialProviderCredential, (void**)&c1);
|
|
|
|
fwprintf(stdout, L"\nConnecting connection # <%lu>\n", i);
|
|
c1->Connect(qc); /* this will return when connected/failed or qc timesout */
|
|
|
|
fwprintf(stdout, L"\nsleep for 2 sec\n");
|
|
Sleep(2000);
|
|
c1->Release();
|
|
}
|
|
|
|
assert(o->Release() == 0); /* check refcount */
|
|
assert(qc->Release() == 0);
|
|
return 0;
|
|
}
|
|
|
|
int wmain()
|
|
{
|
|
HRESULT hr;
|
|
_setmode(_fileno(stdout), _O_U16TEXT);
|
|
_setmode(_fileno(stderr), _O_U16TEXT);
|
|
|
|
IClassFactory *cf = NULL;
|
|
DWORD ctx = CLSCTX_INPROC_SERVER;
|
|
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
|
if (!SUCCEEDED(hr)) error_return(L"CoIntialize", hr);
|
|
|
|
/* Test by loading the dll */
|
|
fwprintf(stdout, L"Test plap dll direct loading\n");
|
|
|
|
HMODULE lib = LoadLibraryW(L"C:\\Program Files\\OpenVPN\\bin\\libopenvpn_plap.dll");
|
|
f_func func = NULL;
|
|
if (lib == NULL)
|
|
{
|
|
fwprintf(stderr, L"Failed to load the dll: error = 0x%08x\n", GetLastError());
|
|
}
|
|
else {
|
|
func = (f_func) GetProcAddress(lib, "DllGetClassObject");
|
|
if (!func)
|
|
fwprintf(stderr, L"Failed to find DllGetClassObject in dll: error = 0x%08x\n", GetLastError());
|
|
}
|
|
if (func) {
|
|
hr = func(CLSID_OpenVPNProvider, IID_IClassFactory, (void **)&cf);
|
|
if (!SUCCEEDED(hr)) fwprintf(stdout, L"Error in DllGetClassObject: status = 0x%08x\n", hr);
|
|
else {
|
|
fwprintf(stdout, L"Success: found ovpn provider class factory by direct access\n");
|
|
cf->Release();
|
|
}
|
|
}
|
|
|
|
/* Test by finding the class through COM's registration mechanism */
|
|
fwprintf(stdout, L"Testing plap using CoGetclassobject -- requires proper dll registration\n");
|
|
|
|
hr = CoGetClassObject(CLSID_OpenVPNProvider, ctx, NULL, IID_IClassFactory, (void **)&cf);
|
|
if (SUCCEEDED(hr)) {
|
|
test_provider(cf);
|
|
cf->Release();
|
|
}
|
|
else {
|
|
fwprintf(stdout, L"CoGetClassObject (class not registered?): error = 0x%08x\n", hr);
|
|
}
|
|
|
|
CoUninitialize();
|
|
if (lib) {
|
|
FreeLibrary(lib);
|
|
}
|
|
return 0;
|
|
}
|