2
0
mirror of https://github.com/tenrok/Rfid-Credential-Provider.git synced 2026-05-21 13:24:13 +03:00
Files
2019-11-29 15:55:40 +03:00

434 lines
8.6 KiB
C++

//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) 2006 Microsoft Corporation. All rights reserved.
//
// RfidProvider implements ICredentialProvider, which is the main
// interface that logonUI uses to decide which tiles to display.
#include <credentialprovider.h>
#include "RfidProvider.h"
#include "RfidCredential.h"
#include "guid.h"
#include <iostream>
#include "Serial.h"
#include "common.h"
#include <stdio.h>
#include "Registry.h"
#include "Logger.h"
#include "Encryption.h"
#include "SHA1.h"
// RfidProvider ////////////////////////////////////////////////////////
RfidProvider::RfidProvider() :
_cRef(1),
_dwNumCreds(0)
{
DllAddRef();
ZeroMemory(_rgpCredentials, sizeof(_rgpCredentials));
}
RfidProvider::~RfidProvider()
{
for (size_t i = 0; i < _dwNumCreds; i++)
{
if (_rgpCredentials[i] != NULL)
{
_rgpCredentials[i]->Release();
}
}
DllRelease();
}
char* sanatizeRfidReading(char* read)
{
char* out = new char[strlen(read)];
memset(out, '\0', strlen(read));
bool hasTransmissionStarted = false;
//HKEY hKey;
//if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, s2ws("SOFTWARE\\KORNET\\WinLogin").c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
//{
// delete hKey;
// return new char;
//}
char start = 0x45; // "E" - Em-Marine... (Z-2 USB Reader)
//DWORD dStart;
//LONG sError = GetDWORDRegKey(hKey, L"Message Start", dStart, 0x00);
//start = (char)dStart;
char end = 0x0D;
//DWORD dEnd;
//GetDWORDRegKey(hKey, L"Message End", dEnd, 0x00);
//end = (char)dEnd;
//if (sError == 2)
//{
// hasTransmissionStarted = true;
//}
int c = 0;
for (int i = 0; i < strlen(read); i++)
{
if (read[i] == start)
{
hasTransmissionStarted = true;
//continue;
}
if (!hasTransmissionStarted)
{
continue;
}
if (read[i] == end)
{
break;
}
out[c++] = read[i];
}
return out;
}
HANDLE hThread;
bool rfidThreadRunning = true;
RfidProvider* prp;
bool doAutoLogin = false;
void getCredentials(char* token)
{
HKEY hKey;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\KORNET\\WinLogin\\Keys", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
{
delete hKey;
return; // Token not recognized.
}
std::wstring keySalt;
GetStringRegKey(hKey, L"Salt", keySalt, L"bad");
CSHA1* sha1 = new CSHA1();
sha1->Update((unsigned char*)token, strlen(token));
sha1->Update((unsigned char*)s2cs(ws2s(keySalt)), wcslen(keySalt.c_str()));
sha1->Final();
std::wstring hash;
sha1->ReportHashStl(hash, CSHA1::REPORT_HEX_SHORT);
delete sha1;
std::string key = std::string("SOFTWARE\\KORNET\\WinLogin\\Keys\\");
key += ws2s(hash);
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, s2ws(key).c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
{
delete hKey;
return; // Token not recognized.
}
std::wstring salt;
std::wstring username;
std::wstring password;
std::wstring domain;
char* cUsername = s2cs(GetCharRegKey(hKey, L"Username"));
char* cPassword = s2cs(GetCharRegKey(hKey, L"Password"));
char* cDomain = s2cs(GetCharRegKey(hKey, L"Domain"));
GetStringRegKey(hKey, L"Salt", salt, L"");
unsigned char* cSalt = (unsigned char*)s2cs(ws2s(salt));
std::wstring decryptionKey;
sha1 = new CSHA1();
sha1->Update((unsigned char*)token, strlen(token));
sha1->Update(cSalt, strlen((char*)cSalt));
sha1->Final();
sha1->ReportHashStl(decryptionKey, CSHA1::REPORT_HEX_SHORT);
delete sha1;
char* cDecryptionKey = s2cs(ws2s(decryptionKey));
decrypt(cUsername, cDecryptionKey);
decrypt(cPassword, cDecryptionKey);
decrypt(cDomain, cDecryptionKey);
username = s2ws(std::string(cUsername));
password = s2ws(std::string(cPassword));
domain = s2ws(std::string(cDomain));
delete cSalt;
delete cUsername;
delete cPassword;
delete cDomain;
delete cDecryptionKey;
prp->_dwNumCreds -= 1;
wchar_t* wUsername = wcs2cs(username);
wchar_t* wPassword = wcs2cs(password);
wchar_t* wDomain = wcs2cs(domain);
RfidCredential::lastLoginFailed = false;
doAutoLogin = true;
prp->_EnumerateOneCredential(prp->_dwNumCreds, wUsername, wPassword, wDomain);
prp->Pcpe->CredentialsChanged(prp->UpAdviseContext);
}
DWORD WINAPI _RfidReader(LPVOID lpParameter)
{
//Serial* s = new Serial();
auto s = std::make_unique<Serial>();
char* lastTag = new char[128];
memset(lastTag, '\0', 128);
while (lastTag[0] != '\0');
int tagCount = 0;
while (rfidThreadRunning)
{
Sleep(50);
char* id = new char[128];
memset(id, '\0', 128);
while (id[0] != '\0');
if (tagCount >= 128)
{
tagCount = 0;
memset(lastTag, '\0', 128);
while (lastTag[0] != '\0');
}
s->ReadData(id, 1);
if (strlen(id) > 0)
{
for (int i = 0; i < strlen(id); i++)
{
lastTag[tagCount++] = id[i];
}
}
delete id;
for (int i = 0; i < strlen(lastTag); i++)
{
if (lastTag[i] == /*0x03*/0x0A)
{
char* fullTag = sanatizeRfidReading(lastTag);
printf(fullTag);
//int n;
//for (n = 0; fullTag[n] != '\0'; n++)
// printf("%02x", (unsigned char)fullTag[n]);
getCredentials(fullTag);
tagCount = 0;
memset(lastTag, '\0', 128);
while (lastTag[0] != '\0');
delete fullTag;
break;
}
}
}
delete lastTag;
//delete s;
return 0;
}
void InitRfidReader()
{
rfidThreadRunning = true;
hThread = ::CreateThread(nullptr, 0, _RfidReader, nullptr, 0, nullptr);
}
void StopRfidReader()
{
rfidThreadRunning = false;
}
HRESULT RfidProvider::SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, DWORD dwFlags)
{
UNREFERENCED_PARAMETER(dwFlags);
HRESULT hr;
static bool s_bCredsEnumerated = false;
switch (cpus)
{
case CPUS_LOGON:
case CPUS_CREDUI:
RfidCredential::lockType = KerbInteractiveLogon;
break;
case CPUS_UNLOCK_WORKSTATION:
RfidCredential::lockType = KerbWorkstationUnlockLogon;
break;
case CPUS_CHANGE_PASSWORD:
hr = E_NOTIMPL;
break;
default:
hr = E_INVALIDARG;
break;
}
if (!s_bCredsEnumerated)
{
prp = this;
hr = this->_EnumerateCredentials();
s_bCredsEnumerated = true;
}
else
{
hr = S_OK;
}
return hr;
}
STDMETHODIMP RfidProvider::SetSerialization(const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs)
{
UNREFERENCED_PARAMETER(pcpcs);
return E_NOTIMPL;
}
ICredentialProviderEvents* Pcpe;
UINT_PTR UpAdviseContext;
HRESULT RfidProvider::Advise(ICredentialProviderEvents* pcpe, UINT_PTR upAdviseContext)
{
InitRfidReader();
Pcpe = pcpe;
Pcpe->AddRef();
UpAdviseContext = upAdviseContext;
return S_OK;
}
HRESULT RfidProvider::UnAdvise()
{
StopRfidReader();
if (Pcpe)
{
Pcpe->Release();
Pcpe = nullptr;
}
UpAdviseContext = NULL;
return S_OK;
}
HRESULT RfidProvider::GetFieldDescriptorCount(DWORD* pdwCount)
{
*pdwCount = SFI_NUM_FIELDS;
return S_OK;
}
HRESULT RfidProvider::GetFieldDescriptorAt(DWORD dwIndex, CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR** ppcpfd)
{
HRESULT hr;
if ((dwIndex < SFI_NUM_FIELDS) && ppcpfd)
{
hr = FieldDescriptorCoAllocCopy(s_rgCredProvFieldDescriptors[dwIndex], ppcpfd);
}
else
{
hr = E_INVALIDARG;
}
return hr;
}
HRESULT RfidProvider::GetCredentialCount(DWORD* pdwCount, DWORD* pdwDefault, BOOL* pbAutoLogonWithDefault)
{
HRESULT hr;
if (doAutoLogin && _dwNumCreds > 0 && !RfidCredential::lastLoginFailed)
{
*pdwDefault = _dwNumCreds - 1;
*pbAutoLogonWithDefault = TRUE;
}
else
{
*pdwDefault = CREDENTIAL_PROVIDER_NO_DEFAULT;
*pbAutoLogonWithDefault = FALSE;
}
*pdwCount = _dwNumCreds;
if (*pdwCount > 0)
{
hr = S_OK;
}
else
{
hr = E_FAIL;
}
return hr;
}
HRESULT RfidProvider::GetCredentialAt(DWORD dwIndex, ICredentialProviderCredential** ppcpc)
{
HRESULT hr;
if ((dwIndex < _dwNumCreds) && ppcpc)
{
hr = _rgpCredentials[dwIndex]->QueryInterface(IID_ICredentialProviderCredential, reinterpret_cast<void**>(ppcpc));
}
else
{
hr = E_INVALIDARG;
}
return hr;
}
HRESULT RfidProvider::_EnumerateOneCredential(DWORD dwCredentialIndex, PWSTR pwzUsername, PWSTR pwzPassword, PWSTR pwzDomain)
{
HRESULT hr;
RfidCredential* ppc = new RfidCredential();
if (ppc)
{
hr = ppc->Initialize(s_rgCredProvFieldDescriptors, s_rgFieldStatePairs, pwzUsername, pwzPassword, pwzDomain);
ppc->lastLoginFailed = false;
if (SUCCEEDED(hr))
{
_rgpCredentials[dwCredentialIndex] = ppc;
_dwNumCreds++;
}
else
{
ppc->Release();
}
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}
HRESULT RfidProvider::_EnumerateCredentials()
{
HRESULT hr = _EnumerateOneCredential(0, NULL, NULL, NULL);
return hr;
}
HRESULT RfidProvider_CreateInstance(REFIID riid, void** ppv)
{
HRESULT hr;
RfidProvider* pProvider = new RfidProvider();
if (pProvider)
{
hr = pProvider->QueryInterface(riid, ppv);
pProvider->Release();
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}