• Welf Alberts started the topic Smart card runas authentication in IT Administration Forum 1 month, 3 weeks ago

    Hi.

    Imagine you are using a SmartCard to logon to windows, a SmartCard with different Credentials on it.

    When you want to run something as different user, you press shift while right-clicking the executable to select “run as different user”, enter you SmartCard PIN and that’s it.

    I would like to script that process to have a 1-click experience. The script should ask for the SmartCard-PIN and start my executable. I already have a script and it works as long as I use a Yubikey-like device, that is, a SmardCardreader that utilizes the laptop keyboard. However, I prefer to use an external SmartCard reader that has its own Pin-Pad, but with that thing, the script does not work.

    Expected behavior: the Pin Pad activates and asks for the PIN. Observed behavior: the PIN needs to be entered using the keyboard.

    Question: who of you PowerShell heroes understands what needs to be changed here to make this work:

    Function Get-SmartCardCred{
    
    
    
    [cmdletbinding()]
    
    param()
    
     
    
    $SmartCardCode = @”
    
    // Copyright (c) Microsoft Corporation. All rights reserved.
    
    // Licensed under the MIT License.
    
     
    
    using System;
    
    using System.Management.Automation;
    
    using System.Runtime.InteropServices;
    
    using System.Security;
    
    using System.Security.Cryptography.X509Certificates;
    
     
    
     
    
    namespace SmartCardLogon{
    
     
    
    static class NativeMethods
    
    {
    
     
    
    public enum CRED_MARSHAL_TYPE
    
    {
    
    CertCredential = 1,
    
    UsernameTargetCredential
    
    }
    
     
    
    [StructLayout(LayoutKind.Sequential)]
    
    internal struct CERT_CREDENTIAL_INFO
    
    {
    
    public uint cbSize;
    
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
    
    public byte[] rgbHashOfCert;
    
    }
    
     
    
    [DllImport(“advapi32.dll”, CharSet = CharSet.Unicode, SetLastError = true)]
    
    public static extern bool CredMarshalCredential(
    
    CRED_MARSHAL_TYPE CredType,
    
    IntPtr Credential,
    
    out IntPtr MarshaledCredential
    
    );
    
     
    
    [DllImport(“advapi32.dll”, SetLastError = true)]
    
    public static extern bool CredFree([In] IntPtr buffer);
    
     
    
    }
    
     
    
    public class Certificate
    
    {
    
     
    
    public static PSCredential MarshalFlow(string thumbprint, SecureString pin)
    
    {
    
    //
    
    // Set up the data struct
    
    //
    
    NativeMethods.CERT_CREDENTIAL_INFO certInfo = new NativeMethods.CERT_CREDENTIAL_INFO();
    
    certInfo.cbSize = (uint)Marshal.SizeOf(typeof(NativeMethods.CERT_CREDENTIAL_INFO));
    
     
    
    //
    
    // Locate the certificate in the certificate store
    
    //
    
    X509Certificate2 certCredential = new X509Certificate2();
    
    X509Store userMyStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    
    userMyStore.Open(OpenFlags.ReadOnly);
    
    X509Certificate2Collection certsReturned = userMyStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
    
    userMyStore.Close();
    
     
    
    if (certsReturned.Count == 0)
    
    {
    
    throw new Exception(“Unable to find the specified certificate.”);
    
    }
    
     
    
    //
    
    // Marshal the certificate
    
    //
    
    certCredential = certsReturned[0];
    
    certInfo.rgbHashOfCert = certCredential.GetCertHash();
    
    int size = Marshal.SizeOf(certInfo);
    
    IntPtr pCertInfo = Marshal.AllocHGlobal(size);
    
    Marshal.StructureToPtr(certInfo, pCertInfo, false);
    
    IntPtr marshaledCredential = IntPtr.Zero;
    
    bool result = NativeMethods.CredMarshalCredential(NativeMethods.CRED_MARSHAL_TYPE.CertCredential, pCertInfo, out marshaledCredential);
    
     
    
    string certBlobForUsername = null;
    
    PSCredential psCreds = null;
    
     
    
    if (result)
    
    {
    
    certBlobForUsername = Marshal.PtrToStringUni(marshaledCredential);
    
    psCreds = new PSCredential(certBlobForUsername, pin);
    
    }
    
     
    
    Marshal.FreeHGlobal(pCertInfo);
    
    if (marshaledCredential != IntPtr.Zero)
    
    {
    
    NativeMethods.CredFree(marshaledCredential);
    
    }
    
     
    
    return psCreds;
    
    }
    
    }
    
    }
    
    “@
    
     
    
    Add-Type -TypeDefinition $SmartCardCode -Language CSharp
    
    Add-Type -AssemblyName System.Security
    
     
    
    $ValidCerts = [System.Security.Cryptography.X509Certificates.X509Certificate2[]](Get-ChildItem ‘Cert:CurrentUserMy’)
    
    $Cert = [System.Security.Cryptography.X509Certificates.X509Certificate2UI]::SelectFromCollection($ValidCerts, ‘Choose a certificate’, ‘Choose a certificate’, 0)
    
     
    
    $Pin = Read-Host “Enter your PIN: ” -AsSecureString
    
     
    
    Write-Output ([SmartCardLogon.Certificate]::MarshalFlow($Cert.Thumbprint, $Pin))
    
    }
    
    $cred=Get-SmartCardCred
    
    $StartInfo = New-Object System.Diagnostics.ProcessStartInfo
    
    $StartInfo.FileName = ‘cmd.exe’
    
    $StartInfo.UseShellExecute = $false
    
    $StartInfo.UserName = $Cred.Username
    
    $StartInfo.Password = $Cred.Password
    
    $StartInfo.WorkingDirectory = $env:windir
    
    $Process = New-Object System.Diagnostics.Process
    
    $Process.StartInfo = $StartInfo
    
    $Process.Start()
    
    $Cred = $null

    How do code tags work here?

© 4sysops 2006 - 2022

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account