/// <summary>
        /// Stores the specified credentials in the operating system's credential store for the currently logged on user.
        /// </summary>
        /// <param name="target">The target name for the credentials.</param>
        /// <param name="credential">The credentials to store.</param>
        /// <exception cref="ArgumentNullException">
        /// <para>
        ///   <paramref name="target"/> is <see langword="null" />.
        /// </para>
        /// <para>
        ///   -or-
        /// </para>
        /// <para>
        ///   <paramref name="credential"/> is <see langword="null" />.
        /// </para>
        /// </exception>
        /// <exception cref="ArgumentException"><paramref name="target"/> is an empty string ("").</exception>
        /// <exception cref="CredentialException">An error occurred storing the credentials.</exception>
        /// <remarks>
        /// <note>
        ///   The <see cref="NetworkCredential.Domain"/> property is ignored and will not be stored, even if it is
        ///   not <see langword="null" />.
        /// </note>
        /// <para>
        ///   If the credential manager already contains credentials for the specified <paramref name="target"/>, they
        ///   will be overwritten; this can even overwrite credentials that were stored by another application. Therefore 
        ///   it is strongly recommended that you prefix the target name to ensure uniqueness, e.g. using the
        ///   form "Company_ApplicationName_www.example.com".
        /// </para>
        /// </remarks>
        public static void StoreCredential(string target, NetworkCredential credential)
        {
            if( target == null )
                throw new ArgumentNullException("target");
            if( target.Length == 0 )
                throw new ArgumentException(Properties.Resources.CredentialEmptyTargetError, "target");
            if( credential == null )
                throw new ArgumentNullException("credential");

            NativeMethods.CREDENTIAL c = new NativeMethods.CREDENTIAL();
            c.UserName = credential.UserName;
            c.TargetName = target;
            c.Persist = NativeMethods.CredPersist.Enterprise;
            byte[] encryptedPassword = EncryptPassword(credential.Password);
            c.CredentialBlob = System.Runtime.InteropServices.Marshal.AllocHGlobal(encryptedPassword.Length);
            try
            {
                System.Runtime.InteropServices.Marshal.Copy(encryptedPassword, 0, c.CredentialBlob, encryptedPassword.Length);
                c.CredentialBlobSize = (uint)encryptedPassword.Length;
                c.Type = NativeMethods.CredTypes.CRED_TYPE_GENERIC;
                if( !NativeMethods.CredWrite(ref c, 0) )
                    throw new CredentialException(System.Runtime.InteropServices.Marshal.GetLastWin32Error());
            }
            finally
            {
                System.Runtime.InteropServices.Marshal.FreeCoTaskMem(c.CredentialBlob);
            }
        }
        /// <summary>
        /// Retrieves credentials for the specified target from the operating system's credential store for the current user.
        /// </summary>
        /// <param name="target">The target name for the credentials.</param>
        /// <param name="additionalEntropy">The same entropy value that was used when storing the credentials.</param>
        /// <returns>The credentials if they were found; otherwise, <see langword="null" />.</returns>
        /// <remarks>
        /// <para>
        ///   If the requested credential was not originally stored using the <see cref="CredentialDialog"/> class (but e.g. by
        ///   another application), the password may not be decoded correctly.
        /// </para>
        /// <para>
        ///   This function does not check the application instance credential cache for the credentials; for that you can use
        ///   the <see cref="RetrieveCredentialFromApplicationInstanceCache"/> function.
        /// </para>
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="target"/> is <see langword="null" />.</exception>
        /// <exception cref="ArgumentException"><paramref name="target"/> is an empty string ("").</exception>
        /// <exception cref="CredentialException">An error occurred retrieving the credentials.</exception>
        public static NetworkCredential RetrieveCredential(string target, byte[] additionalEntropy = null)
        {
            if (target == null)
            {
                throw new ArgumentNullException("target");
            }
            if (target.Length == 0)
            {
                throw new ArgumentException(Properties.Resources.CredentialEmptyTargetError, "target");
            }

            NetworkCredential cred = RetrieveCredentialFromApplicationInstanceCache(target);

            if (cred != null)
            {
                return(cred);
            }

            IntPtr credential;
            bool   result = NativeMethods.CredRead(target, NativeMethods.CredTypes.CRED_TYPE_GENERIC, 0, out credential);
            int    error  = System.Runtime.InteropServices.Marshal.GetLastWin32Error();

            if (result)
            {
                try
                {
                    NativeMethods.CREDENTIAL c = (NativeMethods.CREDENTIAL)System.Runtime.InteropServices.Marshal.PtrToStructure(credential, typeof(NativeMethods.CREDENTIAL));
                    byte[] encryptedPassword   = new byte[c.CredentialBlobSize];
                    System.Runtime.InteropServices.Marshal.Copy(c.CredentialBlob, encryptedPassword, 0, encryptedPassword.Length);
                    cred = new NetworkCredential(c.UserName, DecryptPassword(encryptedPassword, additionalEntropy));
                }
                finally
                {
                    NativeMethods.CredFree(credential);
                }
                return(cred);
            }
            else
            {
                if (error == (int)NativeMethods.CredUIReturnCodes.ERROR_NOT_FOUND)
                {
                    return(null);
                }
                else
                {
                    throw new CredentialException(error);
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Stores the specified credentials in the operating system's credential store for the currently logged on user.
        /// </summary>
        /// <param name="target">The target name for the credentials.</param>
        /// <param name="credential">The credentials to store.</param>
        /// <exception cref="ArgumentNullException">
        /// <para>
        ///   <paramref name="target"/> is <see langword="null" />.
        /// </para>
        /// <para>
        ///   -or-
        /// </para>
        /// <para>
        ///   <paramref name="credential"/> is <see langword="null" />.
        /// </para>
        /// </exception>
        /// <exception cref="ArgumentException"><paramref name="target"/> is an empty string ("").</exception>
        /// <exception cref="CredentialException">An error occurred storing the credentials.</exception>
        /// <remarks>
        /// <note>
        ///   The <see cref="NetworkCredential.Domain"/> property is ignored and will not be stored, even if it is
        ///   not <see langword="null" />.
        /// </note>
        /// <para>
        ///   If the credential manager already contains credentials for the specified <paramref name="target"/>, they
        ///   will be overwritten; this can even overwrite credentials that were stored by another application. Therefore 
        ///   it is strongly recommended that you prefix the target name to ensure uniqueness, e.g. using the
        ///   form "Company_ApplicationName_www.example.com".
        /// </para>
        /// </remarks>
        public static void StoreCredential(string target, NetworkCredential credential)
        {
            if( target == null )
                throw new ArgumentNullException("target");
            if( target.Length == 0 )
                throw new ArgumentException(Properties.Resources.CredentialEmptyTargetError, "target");
            if( credential == null )
                throw new ArgumentNullException("credential");

            NativeMethods.CREDENTIAL c = new NativeMethods.CREDENTIAL();
            c.UserName = credential.UserName;
            c.TargetName = target;
            c.Persist = NativeMethods.CredPersist.Enterprise;
            byte[] encryptedPassword = EncryptPassword(credential.Password);
            c.CredentialBlob = System.Runtime.InteropServices.Marshal.AllocHGlobal(encryptedPassword.Length);
            try
            {
                System.Runtime.InteropServices.Marshal.Copy(encryptedPassword, 0, c.CredentialBlob, encryptedPassword.Length);
                c.CredentialBlobSize = (uint)encryptedPassword.Length;
                c.Type = NativeMethods.CredTypes.CRED_TYPE_GENERIC;
                if( !NativeMethods.CredWrite(ref c, 0) )
                    throw new CredentialException(System.Runtime.InteropServices.Marshal.GetLastWin32Error());
            }
            finally
            {
                System.Runtime.InteropServices.Marshal.FreeCoTaskMem(c.CredentialBlob);
            }
        }