locked
How to use CredPackAuthenticationBuffer & CredUnPackAuthenticationBuffer RRS feed

  • Question

  • I used the following code to get user credentials and verify domain user. But I get two problems:

    (1) I can prefill username/password(empty string) into system verification dialog through calling CredPackAuthenticationBuffer to get an authentication package and pass the authentication package to CredUIPromptForWindowsCredentials. But even I set empty password, CredUIPromptForWindowsCredentials still show password field with characters.

    Even I set empty password when calling CredPackAuthenticationBuffer to create authentication package,  after passing the authentication package to CredUIPromptForWindowsCredentials, the system verification dialog also show password field.

    (2) If there has password when calling CredPackAuthenticationBuffer, after showing verification dialog, if I append some input(such as “test”), then I will get password: SAVED_PASSWORDtest.

    If I originally use username("demo.corp\jason.yang") and password string "demo" to create authentication package through calling CredPackAuthenticationBuffer. And after I passed the authentication package to CredUIPromptForWindowsCredentials. On verification dialog pop up from CredUIPromptForWindowsCredentials, if I append string "test" to its password filed, then I will get password as "SAVED_PASSWORDtest" through calling CredUnPackAuthenticationBuffer.

    using System;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Diagnostics;
    using System.DirectoryServices.AccountManagement;
    using System.Runtime.InteropServices;
    using System.Windows.Interop;
    using System.Security;
    
    namespace DemoTest
    {
        public partial class VerifyDomainUserUtil : Window
        {
            [DllImport("ole32.dll")]
            public static extern void CoTaskMemFree(IntPtr ptr);
    
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
            private struct CREDUI_INFO
            {
                public int cbSize;
                public IntPtr hwndParent;
                public string pszMessageText;
                public string pszCaptionText;
                public IntPtr hbmBanner;
            }
    
            [DllImport("credui.dll", CharSet = CharSet.Auto)]
            private static extern bool CredUnPackAuthenticationBuffer(int dwFlags,
                                                                       IntPtr pAuthBuffer,
                                                                       uint cbAuthBuffer,
                                                                       StringBuilder pszUserName,
                                                                       ref int pcchMaxUserName,
                                                                       StringBuilder pszDomainName,
                                                                       ref int pcchMaxDomainame,
                                                                       StringBuilder pszPassword,
                                                                       ref int pcchMaxPassword);
    
            [DllImport("credui.dll", CharSet = CharSet.Auto)]
            private static extern int CredUIPromptForWindowsCredentials(ref CREDUI_INFO notUsedHere,
                                                                         int authError,
                                                                         ref uint authPackage,
                                                                         IntPtr InAuthBuffer,
                                                                         uint InAuthBufferSize,
                                                                         out IntPtr refOutAuthBuffer,
                                                                         out uint refOutAuthBufferSize,
                                                                         ref bool fSave,
                                                                         int flags);
    
            [DllImport("credui.dll", CharSet = CharSet.Auto)]
            private static extern int CredUIPromptForCredentials(ref CREDUI_INFO creditUR,
                                                                        string targetName,
                                                                        IntPtr reserved1,
                                                                        int iError,
                                                                        StringBuilder userName,
                                                                        int maxUserName,
                                                                        StringBuilder password,
                                                                        int maxPassword,
                                                                        [MarshalAs(UnmanagedType.Bool)] ref bool pfSave,
                                                                        CREDUI_FLAGS flags);
    
            [DllImport("credui.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            private static extern Boolean CredPackAuthenticationBuffer(
                                                                        int dwFlags,
                                                                        string pszUserName,
                                                                        string pszPassword,
                                                                        IntPtr pPackedCredentials,
                                                                        ref int pcbPackedCredentials);
    
            enum CREDUI_FLAGS
            {
                INCORRECT_PASSWORD = 0x1,
                DO_NOT_PERSIST = 0x2,
                REQUEST_ADMINISTRATOR = 0x4,
                EXCLUDE_CERTIFICATES = 0x8,
                REQUIRE_CERTIFICATE = 0x10,
                SHOW_SAVE_CHECK_BOX = 0x40,
                ALWAYS_SHOW_UI = 0x80,
                REQUIRE_SMARTCARD = 0x100,
                PASSWORD_ONLY_OK = 0x200,
                VALIDATE_USERNAME = 0x400,
                COMPLETE_USERNAME = 0x800,
                PERSIST = 0x1000,
                SERVER_CREDENTIAL = 0x4000,
                EXPECT_CONFIRMATION = 0x20000,
                GENERIC_CREDENTIALS = 0x40000,
                USERNAME_TARGET_CREDENTIALS = 0x80000,
                KEEP_USERNAME = 0x100000,
            }
    
            const int BUFFER_SIZE = 0x100;
            const int ERROR_CANCELLED = 0x4c7;
            const int CREDUIWIN_GENERIC = 0x01;
            const int CREDUIWIN_CHECKBOX = 0x2;
            const int CREDUIWIN_ENUMERATE_CURRENT_USER = 0x200;
            const int CREDUIWIN_IN_CRED_ONLY = 0x20;
            const int CREDUIWIN_AUTHPACKAGE_ONLY = 0x10;
            const int CREDUIWIN_ENUMERATE_ADMINS = 0x100;
    
            const int CRED_PACK_PROTECTED_CREDENTIALS = 0x01;
            const int CRED_PACK_GENERIC_CREDENTIALS = 0x04;
    
            private string strInputADCredUsername = "";
            private string strInputADCredPassword = "";
    
            public void VerifyDomainUser()
            {
                int iRet = 0;
                bool bBreakLoop = false;
                string temp = "";
                string strmsg = "";
    
                try
                {
                    while (bBreakLoop == false)
                    {
                        iRet = GetCredentials();
    
                        if (iRet == 0)
                        {
                            if (VerifyDomainUserCredentials())
                            {
                                bBreakLoop = true;
                                bVerificationResult = true;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("exception: {0}", ex.ToString());
                }
            }
    
            private int GetCredentials()
            {
                int iRet = 0;
                CREDUI_INFO credui = new CREDUI_INFO();
    
                Window window = Window.GetWindow(this.Owner);
                var wih = new WindowInteropHelper(window);
                IntPtr hWnd = wih.Handle;
                credui.hwndParent = hWnd;
    
                string temp = "";
                credui.pszCaptionText = "Demo";
                credui.pszMessageText = "Demo Message";
    
                credui.cbSize = Marshal.SizeOf(credui);
                uint authPackage = 0;
                IntPtr outCredBuffer = new IntPtr();
                uint outCredSize = 0;
                bool save = false;
                int result = ERROR_CANCELLED;
                int flags = CREDUIWIN_GENERIC;
    
                string username = strInputADCredUsername;
                string password = strInputADCredPassword;
                int inCredSize = 0;
                IntPtr inCredBuffer = IntPtr.Zero;
                bool bCredPack = false;
    
                if (!string.IsNullOrEmpty(username))
                {
                    bCredPack = CredPackAuthenticationBuffer(CRED_PACK_PROTECTED_CREDENTIALS, username, password, inCredBuffer, ref inCredSize);
                    if (!bCredPack)
                    {
                        inCredBuffer = Marshal.AllocCoTaskMem(inCredSize);
                        bCredPack = CredPackAuthenticationBuffer(0, username, password, inCredBuffer, ref inCredSize);
                        if (!bCredPack)
                        {
                            Console.WriteLine("Pack authentication buffer failed");
                        }
                    }
                }
    
                try
                {
                    if (bCredPack)
                    {
                        result = CredUIPromptForWindowsCredentials(ref credui,
                                                                        0,
                                                                        ref authPackage,
                                                                        inCredBuffer,
                                                                        (uint)inCredSize,
                                                                        out outCredBuffer,
                                                                        out outCredSize,
                                                                        ref save,
                                                                        flags);
    
                        if (inCredBuffer != IntPtr.Zero)
                        {
                            Marshal.FreeCoTaskMem(inCredBuffer);
                        }
                    }
    
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Get credentials input failed");
                }
    
                if (result == 0)
                {
                    var usernameBuf = new StringBuilder(0x100);
                    var passwordBuf = new StringBuilder(0x100);
                    var domainBuf = new StringBuilder(0x100);
    
                    int maxUserName = 0x100;
                    int maxDomain = 0x100;
                    int maxPassword = 0x100;
    
                    if (CredUnPackAuthenticationBuffer(CRED_PACK_PROTECTED_CREDENTIALS, outCredBuffer, outCredSize, usernameBuf, ref maxUserName,
                                                       domainBuf, ref maxDomain, passwordBuf, ref maxPassword))
                    {
                        CoTaskMemFree(outCredBuffer);
                        bSaveCredentials = save;
                        strDomainUserName = usernameBuf.ToString();
                        strDomainUserPWD = passwordBuf.ToString();
                        strDomainName = domainBuf.ToString();
    
                        // If appending string "test" into password in credential dialog,
                        // then here I will get "SAVED_PASSWORDtest" string
                        strInputADCredUsername = strDomainUserName;
                        strInputADCredPassword = strDomainUserPWD;
                    }
                }
            }
    
            private bool VerifyDomainUserCredentials()
            {
                bool bVerifyDomainUser = false;
    
                try
                {
                    PrincipalContext pc = new PrincipalContext(ContextType.Domain, strDomainName, strDomainUserName, strDomainUserPWD);
                    bVerifyDomainUser = pc.ValidateCredentials(strDomainUserName, strDomainUserPWD, ContextOptions.Negotiate);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("exception: {0}", ex.ToString());
                }
    
                return bVerifyDomainUser;
            }
        }
    }

    So could you give me some hint for the two problems?

    • Moved by Bob Shen Tuesday, April 30, 2013 5:38 AM
    Saturday, April 27, 2013 5:57 AM

All replies

  • Hi jixuyang,

    I am moving your question to more appropriate forum for better responses.


    Bob Shen
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, April 30, 2013 5:38 AM
  • I'm also having the same problem with the empty password in C++ Win32.

    Has anyone found a solution? Obviously, there should exist a flag for the CredUIPromptForWindowsCredentials that tells it to ONLY ask for the password and leave the field empty. The flags CREDUIWIN_IN_CRED_ONLY and CREDUIWIN_ENUMERATE_CURRENT_USER do basically absolutely nothing.


    Monday, October 6, 2014 12:08 PM