I have a client authentication certificate which has private key and public key. Using this certificate I am able to perform certificate based authentication to Azure AD portal by using these configurations: https://learn.microsoft.com/en-us/azure/active-directory/authentication/how-to-certificate-based-authentication
Now I need to pass same certificate to windows LSA using LSALogonUser function and get a windows session, but I am not getting how can I do that. I am able to load the certificate contents but how should I create an authentication packet using the user certificate? user1 is Azure AD user. I have already uploaded CA certificate in Azure and made configurations from the link above.
#define SECURITY_WIN32
#ifndef WIN32_NO_STATUS
#include <ntstatus.h>
#define WIN32_NO_STATUS
#endif
#include <Windows.h>
#include <Ntsecapi.h>
#include <iostream>
#include <string>
#include <windows.h>
#include <ntsecapi.h>
#include <security.h>
#include <wincred.h>
#include <vector>
using namespace std;
PCCERT_CONTEXT FindCertificateInStore()
{
HCERTSTORE hCertStore = NULL;
PCCERT_CONTEXT pCertContext = NULL;
BYTE* pbThumbprint = NULL;
DWORD cbThumbprint = 0;
DWORD subjectNameSize;
WCHAR subjectName[MAX_PATH];
pCertContext = CertFindCertificateInStore(
hCertStore,
X509_ASN_ENCODING,
0,
CERT_FIND_SUBJECT_STR,
L"[email protected]",
NULL
);
if (pCertContext == NULL)
{
printf("CertFindCertificateInStore failed with error 0x%x\n", GetLastError());
goto cleanup;
}
cleanup:
if (pbThumbprint)
{
delete[] pbThumbprint;
}
if (hCertStore)
{
CertCloseStore(hCertStore, 0);
}
return pCertContext;
}
int main()
{
DWORD error = ERROR_SUCCESS;
HANDLE lsa = NULL;
NTSTATUS subStatus = ERROR_SUCCESS, status = ERROR_SUCCESS;
HMODULE secur32 = LoadLibrary(TEXT("Secur32.dll"));
if (secur32 == NULL) {
cout << "Error while loading Secure32" << endl;
return 1;
}
HMODULE crypt32 = LoadLibrary(TEXT("Crypt32.dll"));
if (crypt32 == NULL) {
cout << "Error while loading crypt32" << endl;
return 1;
}
//Get a handle to the LSA subsystem :
LSA_HANDLE lsaHandle;
LSA_OBJECT_ATTRIBUTES objAttr;
status = LsaConnectUntrusted(&lsaHandle);
if (status != STATUS_SUCCESS) {
// handle error
error = LsaNtStatusToWinError(status);
cout<<"LsaConnectUntrusted failed : status"<< status<<"error: "<<error;
if (lsa)
{
status = LsaDeregisterLogonProcess(lsa);
if (status != STATUS_SUCCESS)
{
cout<<"LsaDeregisterLogonProcess failed : status"<< status<<"error:"<<LsaNtStatusToWinError(status);
}
}
return 1;
}
//Create an LSA authentication package :
char packageNameRaw[] = NEGOSSP_NAME_A;
LSA_STRING packageName;
packageName.Buffer = packageNameRaw;
packageName.Length = packageName.MaximumLength = (USHORT)strlen(packageName.Buffer);
packageName.Length = (USHORT)strlen(packageName.Buffer);
packageName.MaximumLength = packageName.Length + 1;
ULONG packageId;
status = LsaLookupAuthenticationPackage(lsaHandle, &packageName, &packageId);
if (status != STATUS_SUCCESS) {
// handle error
error = LsaNtStatusToWinError(status);
cout << "LsaLookupAuthenticationPackage failed : status" << status << "error" << error;
if (lsa)
{
status = LsaDeregisterLogonProcess(lsa);
if (status != STATUS_SUCCESS)
{
cout<<"LsaDeregisterLogonProcess failed : status"<<status<<"error :"<<LsaNtStatusToWinError(status);
}
}
return error;
}
// Get the client authentication certificate from the certificate store
PCCERT_CONTEXT pCertContext = FindCertificateInStore();
if (pCertContext == NULL)
{
cout << "Certificate is NULL";
return 1;
}
// LsaLogonUser : Need to use LSALogonUser to get Token and then use that token to impersonate...Stuck here
HANDLE tokenHandle = NULL;
/*status = LsaLogonUser(lsaHandle, &packageName, logonType, packageId,
&cred, sizeof(cred), NULL, &tokenSource, &profileBuffer, &profileBufferSize, &logonId, &tokenHandle, "aLimits, NULL);*/
// Example: Impersonate the user and open a file
BOOL result = ImpersonateLoggedOnUser(tokenHandle);
if (!result) {
cout << "impersonate failed" << endl;
return 1;
}
HANDLE fileHandle = CreateFile(TEXT("C:\\myfile.txt"), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
cout << "file create failed" << endl;
return 1;
}
// Do something with the file...
CloseHandle(fileHandle);
RevertToSelf();
return 0;
}
How should I send pCertContext to LSALogonUser, can someone please help? https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-lsalogonuser.
Certificate file is user1.p12, generated using following commands:
step 1) openssl req -new -sha256 -key user1.key -subj "/[email protected]" -out user1.csr
step 2) openssl x509 -req -in user1.csr -CA rootCA.crt -CAkey rootCA.key -out user1.crt -CAcreateserial -days 365 -sha256 -extfile openssl.cnf
openssl.cnf:
basicConstraints = CA:FALSE
nsCertType = client
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
subjectAltName=otherName:msUPN;UTF8:[email protected]
step 3) openssl pkcs12 -export -in user1.crt -inkey user1.key -out user1.p12