예제 #1
0
        private readonly bool isLoaded;         // is the credential blob loaded

        #region -- Ctor/Dtor ----------------------------------------------------------

        /// <summary></summary>
        /// <param name="target"></param>
        /// <param name="realm"></param>
        /// <param name="showErrorMessage">The user will be informed of the type of error.</param>
        public PpsClientLogin(string target, string realm, bool showErrorMessage)
        {
            this.target           = target;
            this.realm            = realm;
            this.showErrorMessage = showErrorMessage;

            if (NativeMethods.CredRead(target, NativeMethods.CredentialType.Generic, 0, out var pCred))
            {
                credential = Marshal.PtrToStructure <NativeMethods.CREDENTIAL>(pCred);

                if (credential.CredentialBlob != IntPtr.Zero)                 // copy the password in our one memory area
                {
                    password       = Marshal.AllocCoTaskMem(credential.CredentialBlobSize);
                    passwordLength = (credential.CredentialBlobSize >> 1) - 1;
                    UnsafeNativeMethods.CopyMemory(password, credential.CredentialBlob, credential.CredentialBlobSize);
                }

                NativeMethods.CredFree(pCred);
                isLoaded    = true;
                saveOptions = passwordLength > 0
                                        ? PpsClientLoginSaveOptions.Password
                                        : PpsClientLoginSaveOptions.UserName;
            }
            else
            {
                isLoaded    = false;
                saveOptions = PpsClientLoginSaveOptions.None;
            }
        }         // ctor
예제 #2
0
        }         // proc Commit

        #endregion

        #region -- ShowWindowsLogin ---------------------------------------------------

        /// <summary>Show the default windows login dialog.</summary>
        /// <param name="hwndParent"></param>
        /// <returns></returns>
        public bool ShowWindowsLogin(IntPtr hwndParent)
        {
            int hr;
            var dwAuthPackage     = (uint)0;
            var inCredBuffer      = IntPtr.Zero;
            var inCredBufferSize  = 0;
            var outCredBuffer     = IntPtr.Zero;
            var outCredBufferSize = 0;

            var newPasswordLength = NativeMethods.CREDUI_MAX_PASSWORD_LENGTH;
            var newPassword       = Marshal.AllocCoTaskMem(newPasswordLength);

            try
            {
                // pack the arguments
                if (isLoaded)
                {
                    var emptyPasswordSet = false;
                    var emptyPassword    = IntPtr.Zero;
                    try
                    {
                        if (password == IntPtr.Zero)
                        {
                            emptyPassword = Marshal.AllocCoTaskMem(2);
                            UnsafeNativeMethods.ZeroMemory(emptyPassword, 2);

                            password         = emptyPassword;
                            emptyPasswordSet = true;
                        }

                        if (!NativeMethods.CredPackAuthenticationBuffer(4 /*CRED_PACK_GENERIC_CREDENTIALS*/, credential.UserName, password, inCredBuffer, ref inCredBufferSize))
                        {
                            hr = Marshal.GetLastWin32Error();
                            if (hr == 122)
                            {
                                inCredBuffer = Marshal.AllocCoTaskMem((int)inCredBufferSize);
                                if (!NativeMethods.CredPackAuthenticationBuffer(4, credential.UserName, password, inCredBuffer, ref inCredBufferSize))
                                {
                                    throw new Win32Exception();
                                }
                            }
                            else
                            {
                                throw new Win32Exception(hr);
                            }
                        }
                    }
                    finally
                    {
                        if (emptyPasswordSet)
                        {
                            password = IntPtr.Zero;
                            Marshal.FreeCoTaskMem(emptyPassword);
                        }
                    }
                }

                // properties of the dialog
                var authentifactionError = showErrorMessage ? 1326 /* LogonFailure */ : 0;
                var messageText          = target;
                if (messageText != null)
                {
                    var pos = messageText.IndexOf(':');
                    if (pos != -1)
                    {
                        messageText = messageText.Substring(pos + 1);
                    }
                }
                var info = new NativeMethods.CREDUI_INFO
                {
                    cbSize         = Marshal.SizeOf(typeof(NativeMethods.CREDUI_INFO)),
                    hwndParent     = hwndParent,
                    pszMessageText = String.Format("{0} ({1}).", messageText, realm),
                    pszCaptionText = "Anmeldung",
                    hbmBanner      = IntPtr.Zero
                };

                // show the dialog
                var flags  = NativeMethods.CredUIFlags.Generic | NativeMethods.CredUIFlags.CheckBox;
                var doSave = saveOptions != PpsClientLoginSaveOptions.None;
                hr = NativeMethods.CredUIPromptForWindowsCredentials(ref info, authentifactionError, ref dwAuthPackage, inCredBuffer, inCredBufferSize, out outCredBuffer, out outCredBufferSize, ref doSave, flags);
                if (hr != 0)
                {
                    if (hr == 1223)                     // ERROR_CANCELLED
                    {
                        return(false);
                    }
                    else
                    {
                        throw new Win32Exception(hr);
                    }
                }
                saveOptions = doSave ? PpsClientLoginSaveOptions.Password : PpsClientLoginSaveOptions.None;

                // unpack the result
                var userName         = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH);
                var domainName       = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH);
                var userNameLength   = userName.Capacity;
                var domainNameLength = domainName.Capacity;

                if (!NativeMethods.CredUnPackAuthenticationBuffer(0, outCredBuffer, outCredBufferSize, userName, ref userNameLength, domainName, ref domainNameLength, newPassword, ref newPasswordLength))
                {
                    throw new Win32Exception();
                }

                // set the user name
                if (domainName.Length > 0)
                {
                    credential.UserName = domainName.ToString() + "\\" + userName.ToString();
                }
                else
                {
                    credential.UserName = userName.ToString();
                }

                // release the old password
                var oldPassword       = password;
                var oldPasswordLength = passwordLength;

                if (newPasswordLength <= 1)
                {
                    password       = IntPtr.Zero;
                    passwordLength = 0;
                }
                else
                {
                    password       = newPassword;
                    passwordLength = newPasswordLength - 1;
                }

                // set the new one
                newPassword       = oldPassword;
                newPasswordLength = oldPasswordLength;

                return(true);
            }
            finally
            {
                SecureFreeCoTaskMem(ref newPassword, newPasswordLength);
                SecureFreeCoTaskMem(ref inCredBuffer, inCredBufferSize);
                SecureFreeCoTaskMem(ref outCredBuffer, outCredBufferSize);
            }
        }         // func ShowWindowsLogin