private bool WriteCredential(string key, string userName, string secret)
{
var byteArray = Encoding.Unicode.GetBytes(secret);
if (byteArray.Length > 512)
{
throw Log.ErrorAndCreateException(x => new ArgumentOutOfRangeException("secret", x), "The secret message has exceeded 512 bytes.");
}
Log.Debug("Writing credentials with username '{0}' for key '{1}'", userName, key);
var cred = new CredUi.Credential();
cred.TargetName = key;
cred.UserName = userName;
cred.CredentialBlob = secret;
cred.CredentialBlobSize = (uint)Encoding.Unicode.GetBytes(secret).Length;
cred.AttributeCount = 0;
cred.Attributes = IntPtr.Zero;
cred.Comment = null;
cred.TargetAlias = null;
cred.Type = CredUi.CredTypes.CRED_TYPE_GENERIC;
cred.Persist = CredUi.IsWindowsVistaOrEarlier ? CredUi.CredPersistance.Session : CredUi.CredPersistance.LocalMachine;
Log.Debug("Persisting credentials as '{0}'", cred.Persist);
var ncred = CredUi.NativeCredential.GetNativeCredential(cred);
var written = CredUi.CredWrite(ref ncred, 0);
var lastError = Marshal.GetLastWin32Error();
if (!written)
{
throw Log.ErrorAndCreateException(x => new CredentialException(lastError, x), "CredWrite failed with the error code '{0}'", lastError);
}
// Note: immediately read it for ORCOMP-229
var credential = ReadCredential(key, false);
if (credential == null || string.IsNullOrWhiteSpace(credential.Password))
{
var configurationKey = GetPasswordConfigurationKey(key, cred.UserName);
var encryptionKey = GetEncryptionKey(key, cred.UserName);
Log.Debug("Failed to write credentials to vault, probably a company policy. Falling back to writing configuration key '{0}'", configurationKey);
var encryptedPassword = EncryptionHelper.Encrypt(secret, encryptionKey);
_configurationService.SetRoamingValue(configurationKey, encryptedPassword);
}
Log.Debug("Successfully written credentials for key '{0}'", key);
return true;
}