Esempio n. 1
0
        public NetworkCredential Read(string target)
        {
            Trace.Entering();
            ArgUtil.NotNullOrEmpty(target, nameof(target));
            IntPtr credPtr = IntPtr.Zero;

            try
            {
                if (CredRead(target, CredentialType.Generic, 0, out credPtr))
                {
                    Credential credStruct     = (Credential)Marshal.PtrToStructure(credPtr, typeof(Credential));
                    int        passwordLength = (int)credStruct.CredentialBlobSize;
                    string     password       = passwordLength > 0 ? Marshal.PtrToStringUni(credStruct.CredentialBlob, passwordLength / sizeof(char)) : String.Empty;
                    string     username       = Marshal.PtrToStringUni(credStruct.UserName);
                    Trace.Info($"Credentials for '{target}' read from windows credential store.");

                    // delete from .credential_store file since we are able to read it from windows credential store
                    if (_credStore.Remove(target))
                    {
                        Trace.Info($"Delete credentials for '{target}' from credential store file.");
                        SyncCredentialStoreFile();
                    }

                    return(new NetworkCredential(username, password));
                }
                else
                {
                    // Can't read from Windows Credential Store, fail back to .credential_store file
                    if (_credStore.ContainsKey(target) && !string.IsNullOrEmpty(_credStore[target]))
                    {
                        Trace.Info($"Credentials for '{target}' read from credential store file.");

                        // Base64Decode -> DP-API machine level decrypt -> Base64Username:Base64Password -> Base64Decode
                        string decryptedUsernamePassword = Encoding.UTF8.GetString(ProtectedData.Unprotect(Convert.FromBase64String(_credStore[target]), null, DataProtectionScope.LocalMachine));

                        string[] credential = decryptedUsernamePassword.Split(':');
                        if (credential.Length == 2 && !string.IsNullOrEmpty(credential[0]) && !string.IsNullOrEmpty(credential[1]))
                        {
                            string username = Encoding.UTF8.GetString(Convert.FromBase64String(credential[0]));
                            string password = Encoding.UTF8.GetString(Convert.FromBase64String(credential[1]));

                            // store back to windows credential store for current user
                            NetworkCredential creds = WriteInternal(target, username, password);

                            // delete from .credential_store file since we are able to write the credential to windows credential store for current user.
                            if (_credStore.Remove(target))
                            {
                                Trace.Info($"Delete credentials for '{target}' from credential store file.");
                                SyncCredentialStoreFile();
                            }

                            return(creds);
                        }
                        else
                        {
                            throw new ArgumentOutOfRangeException(nameof(decryptedUsernamePassword));
                        }
                    }

                    throw new Win32Exception(Marshal.GetLastWin32Error(), $"CredRead throw an error for '{target}'");
                }
            }
            finally
            {
                if (credPtr != IntPtr.Zero)
                {
                    CredFree(credPtr);
                }
            }
        }
Esempio n. 2
0
 internal static extern bool CredWrite([In] ref Credential userCredential, [In] UInt32 flags);