Send Client Certificate authentication packet to LSALogonUser to get windows session

185 views Asked by At

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, &quotaLimits, 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   
0

There are 0 answers