locked
About KERB_CERTIFICATE_LOGON & KERB_SMARTCARD_CSP_INFO RRS feed

  • Question

  • Hi everyone,


    I am writing a program that allow to logon to Vista using a certificate. I found from MSDN that it is needed to serialize a  KERB_CERTIFICATE_LOGON structure,

     

    typedef struct _KERB_CERTIFICATE_LOGON
    {  
     

    KERB_LOGON_SUBMIT_TYPE MessageType; 
     UNICODE_STRING DomainName; 
     UNICODE_STRING UserName; 
     UNICODE_STRING Pin; 
     ULONG Flags; 
     ULONG CspDataLength; 
     PUCHAR CspData;

    } KERB_CERTIFICATE_LOGON,  *PKERB_CERTIFICATE_LOGON;

     

    in which, CspData is a pointer to a KERB_SMARTCARD_CSP_INFO structure that contains information about the smart card cryptographic service provider (CSP),

     

    typedef struct _KERB_SMARTCARD_CSP_INFO
    {   

    DWORD dwCspInfoLen; 
     DWORD MessageType; 
     union {     

    PVOID ContextInformation;    
    ULONG64 SpaceHolderForWow64;  
    }; 
     DWORD flags; 
     DWORD KeySpec; 
     ULONG nCardNameOffset; 
     ULONG nReaderNameOffset; 
     ULONG nContainerNameOffset; 
     ULONG nCSPNameOffset; 
     
    TCHAR bBuffer;

    } KERB_SMARTCARD_CSP_INFO,  *PKERB_SMARTCARD_CSP_INFO;

     

    In the KERB_SMARTCARD_CSP_INFO structure, I see bBuffer is defined that it is An array of characters initialized to a length of sizeof(DWORD).This buffer contains the names referred to by the nCardNameOffset, nReaderNameOffset, nContainerNameOffset, and nCSPNameOffset members, as well as any additional data provided by the CSP.

     

    This makes me a bit confused. Because the type of bBuffer is TCHAR (a single character type), how can it store an array of characters. Is its type PTCHAR?

     

    I tried to serialize the information corresponding to these structures and send to LSA, but always receicve result status STATUS_INVALID_PARAMETER from WinLogon. Does anyone experience from this. Please give me some advise . Thank you very much for any help.

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    Wednesday, January 23, 2008 8:04 AM

Answers

  •  

    Try like this :-

     

    Replace TCHAR bBuffer with TCHAR bBuffer[2];

     

    KERB_SMARTCARD_CSP_INFO* pInfo;

    ----

    ----

    ----

    WCHAR pwProviderName[] = L"##### Your Provider Name ######";

    WCHAR pwContainerName[] = L"##### Your Container Name ######";

    WCHAR pwReaderName[] = L"##### Your Reader Name ######";

    WCHAR pwCardName[] = L"##### Your Card Name ######";

     

    size_t cbCSPInfo = sizeof(KERB_SMARTCARD_CSP_INFO) - (sizeof(TCHAR)*2);

    size_t cbReaderName    = (wcslen(pwReaderName) + 1) * sizeof(WCHAR);
    size_t cbCardName      = (wcslen(pwCardName) + 1) * sizeof(WCHAR);
    size_t cbContainerName = (wcslen(pwContainerName) + 1) * sizeof(WCHAR);
    size_t cbProviderName  = (wcslen(pwProviderName) + 1) * sizeof(WCHAR);

     

    size_t cbCspDataLength = cbCSPInfo + cbCardName + cbReaderName + cbContainerName + cbProviderName;

     

    pInfo = (KERB_SMARTCARD_CSP_INFO*)CoTaskMemAlloc(cbCspDataLength);

    ZeroMemory(pInfo, cbCspDataLength);

     

    - Sudhanshu

    Tuesday, August 26, 2008 10:34 AM

All replies

  • Hi,

     

    I am also wondering about this issue.

     

    Thanks

     

    Monday, February 11, 2008 2:32 PM
  • Hi ThuyLT

     

    Did you mange to make use of the KERB_CERTIFICATE_LOGON structure??

     

    If you managed, could you please post a sample of the LsaLogonUser using this structure.

     

    Ian

     

     

    Wednesday, February 27, 2008 9:26 AM
  •  

    Try like this :-

     

    Replace TCHAR bBuffer with TCHAR bBuffer[2];

     

    KERB_SMARTCARD_CSP_INFO* pInfo;

    ----

    ----

    ----

    WCHAR pwProviderName[] = L"##### Your Provider Name ######";

    WCHAR pwContainerName[] = L"##### Your Container Name ######";

    WCHAR pwReaderName[] = L"##### Your Reader Name ######";

    WCHAR pwCardName[] = L"##### Your Card Name ######";

     

    size_t cbCSPInfo = sizeof(KERB_SMARTCARD_CSP_INFO) - (sizeof(TCHAR)*2);

    size_t cbReaderName    = (wcslen(pwReaderName) + 1) * sizeof(WCHAR);
    size_t cbCardName      = (wcslen(pwCardName) + 1) * sizeof(WCHAR);
    size_t cbContainerName = (wcslen(pwContainerName) + 1) * sizeof(WCHAR);
    size_t cbProviderName  = (wcslen(pwProviderName) + 1) * sizeof(WCHAR);

     

    size_t cbCspDataLength = cbCSPInfo + cbCardName + cbReaderName + cbContainerName + cbProviderName;

     

    pInfo = (KERB_SMARTCARD_CSP_INFO*)CoTaskMemAlloc(cbCspDataLength);

    ZeroMemory(pInfo, cbCspDataLength);

     

    - Sudhanshu

    Tuesday, August 26, 2008 10:34 AM
  • You are right... this is quite confusing.

     

    Like the text says >> bBuffer is defined that it is An array of characters initialized to a length of sizeof(DWORD).

     

    so the definition of the member should really look this.


        TCHAR bBuffer [ sizeof(DWORD) ]; // an expandable placeholder for strings


    I believe it does not have really any special meaning as long as you account for whatever size of bBuffer you use (here sizeof(DWORD)) when calculating the offsets, i.e., the n***NameOffset members of the structure.

    Saturday, August 30, 2008 9:06 AM
  • Was there any progress made on this or any sample code released? I have tried this but LsaLogonUser is returning STATUS_INVALID_INFO_CLASS.

    I will be very thankful for any help or advice!
    Tuesday, August 25, 2009 11:50 AM
  • Hi,

    If you want to logon a user using a certificate on a smart card, then you can achieve that simply by using CredMarshalCredential and LogonUser : just choose the certificate you want to use, compute its SHA-1 hash in order to fill the CERT_CREDENTIAL_INFO needed by CredMarshalCredential , call CredMarshalCredential in order to obtain the marshaled credentials and then use the returned value a user name for LogonUser after setting the domain parameter to NULL and the password to the PIN value of the card. Of course, as for all cryptographic operations involving certificates on smatt card, the "MY" certificate store must be correctly filled.

    I have written a small sample that demonstrate this procedure. In it, I use CertFindCertificateInStore to find a smart card logon certificate. You can get the source from the following link :

    http://www.idrix.fr/Root/Samples/SmartCardLogon.cpp


    I hope this will help.

    Cheers,
    --
    Mounir IDRASSI
    IDRIX
    http://www.idrix.fr

    • Proposed as answer by Mounir IDRASSI Thursday, August 27, 2009 1:40 AM
    Thursday, August 27, 2009 1:40 AM
  • Hi Mounir,

    Firstly, I just wanted to thank you very much for this sample, it works perfectly to log a user in.

    The only problem is that I need to map one certificate to many users. I need to be able to specify the user when I call LogonUser - but as the marshalled credentials replace the username in the username parameter of LogonUser, I don't think it is possible unless I use LsaLogonUser :(

    With LsaLogonUser, you can specify the username in the KERB_CERTIFICATE_LOGON structure

    Again, thanks a lot for the help,

    John


    Thursday, August 27, 2009 8:14 AM
  • Hi,

    I finally managed to get LsaLogonUser to work with smart card certificates. In the course of my investigation, I discovered that the MSDN documentation for KERB_SMARTCARD_CSP_INFO is incomplete and even misleading. The main missing element is that this structure must be declared as 1-byte aligned. Also, the declaration of the member bBuffer is confusing: its only role is to remind the developer that he must append the data right after the last member nCSPNameOffset .

    You can get the source code of a working sample I have written by using the following link :

    http://www.idrix.fr/Root/Samples/LsaSmartCardLogon.cpp

    In it, the structure is declared as follows :

    #pragma pack(push, KerbCspInfo, 1)
    typedef struct _KERB_SMARTCARD_CSP_INFO
    {   
       DWORD dwCspInfoLen; 
       DWORD MessageType; 
       union {     
          PVOID ContextInformation;    
          ULONG64 SpaceHolderForWow64;  
       }; 
       DWORD flags; 
       DWORD KeySpec; 
       ULONG nCardNameOffset; 
       ULONG nReaderNameOffset; 
       ULONG nContainerNameOffset; 
       ULONG nCSPNameOffset; 
       TCHAR bBuffer;
    } KERB_SMARTCARD_CSP_INFO,  *PKERB_SMARTCARD_CSP_INFO;
    #pragma pack(pop, KerbCspInfo)

    I hope this will help.

    Cheers,
    --
    Mounir IDRASSI
    IDRIX
    http://www.idrix.fr
    • Proposed as answer by Mounir IDRASSI Friday, August 28, 2009 11:29 PM
    Friday, August 28, 2009 11:28 PM
  • Hello,

    Thank you very much for this - a very positive end to what has been a fustrating few days.

    All the best,

    John



    Sunday, August 30, 2009 2:43 PM
  • Very good sample. I am trying to get your sample to work with another certificate, not coming from a smart card so I replaced the line:

    strcpy(szSCLogonOID, szOID_KP_SMARTCARD_LOGON);

    with this one

    strcpy(szSCLogonOID, szOID_PKIX_KP_CLIENT_AUTH);

    Unfortunately LogonUser will fail with the infamous error 1326. The certificate was properly mapped through Active Directory certificate to account mapping.

    Any ideas?

    Cheers,

    Luke

    Wednesday, February 10, 2010 2:57 AM