/// <summary> /// Read the encrpyted backup registry entries to be sent within the diagnostics report /// </summary> public static string ReadBackupFromRegistry(WinAuthConfig config) { StringBuilder buffer = new StringBuilder(); foreach (string name in config.ReadSettingKeys(WINAUTHREGKEY_BACKUP)) { object val = ReadRegistryValue(name); if (val != null) { buffer.Append(name + "=" + Convert.ToString(val)).Append(Environment.NewLine); } } return buffer.ToString(); }
/// <summary> /// Save a PGP encrypted version of the config into the registry for recovery /// /// Issue#133: this just compounds each time we load, and is really pointless so we are removing it /// but in the meantime we have to clear it out /// </summary> /// <param name="config"></param> private static void SaveToRegistry(WinAuthConfig config) { config.WriteSetting(WINAUTHREGKEY_CONFIGBACKUP, null); }
/// <summary> /// Save a PGP encrypted version of an authenticator into the registry for recovery /// </summary> /// <param name="wa">WinAuthAuthenticator instance</param> public static void SaveToRegistry(WinAuthConfig config, WinAuthAuthenticator wa) { if (config == null || wa == null || wa.AuthenticatorData == null) { return; } using (SHA256 sha = new SHA256Managed()) { // get a hash based on the authenticator key string authkey = Convert.ToBase64String(sha.ComputeHash(Encoding.UTF8.GetBytes(wa.AuthenticatorData.SecretData))); // save the PGP encrypted key using (EncodedStringWriter sw = new EncodedStringWriter(Encoding.UTF8)) { XmlWriterSettings xmlsettings = new XmlWriterSettings(); xmlsettings.Indent = true; using (XmlWriter xw = XmlWriter.Create(sw, xmlsettings)) { xw.WriteStartElement("WinAuth"); xw.WriteAttributeString("version", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(2)); wa.WriteXmlString(xw); xw.WriteEndElement(); } string pgpkey = string.IsNullOrEmpty(config.PGPKey) == false ? config.PGPKey : WinAuthHelper.WINAUTH_PGP_PUBLICKEY; config.WriteSetting(WINAUTHREGKEY_BACKUP + "\\" + authkey, PGPEncrypt(sw.ToString(), pgpkey)); } } }
/// <summary> /// Save the authenticator /// </summary> /// <param name="configFile">filename to save to</param> /// <param name="config">current settings to save</param> public static void SaveConfig(WinAuthConfig config) { // create the xml XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.Encoding = Encoding.UTF8; // Issue 41 (http://code.google.com/p/winauth/issues/detail?id=41): saving may crash leaving file corrupt, so write into memory stream first before an atomic file write using (MemoryStream ms = new MemoryStream()) { // save config into memory using (XmlWriter writer = XmlWriter.Create(ms, settings)) { config.WriteXmlString(writer); } // if no config file yet, use default if (string.IsNullOrEmpty(config.Filename) == true) { string configDirectory = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), WinAuthMain.APPLICATION_NAME); Directory.CreateDirectory(configDirectory); config.Filename = Path.Combine(configDirectory, DEFAULT_AUTHENTICATOR_FILE_NAME); } FileInfo fi = new FileInfo(config.Filename); if (!fi.Exists || !fi.IsReadOnly) { // write memory stream to file try { byte[] data = ms.ToArray(); using (FileStream fs = new FileStream(config.Filename, FileMode.Create, FileAccess.Write, FileShare.None)) { fs.Write(data, 0, data.Length); } } catch (UnauthorizedAccessException ) { // fail silently if read only if (fi.IsReadOnly) { config.IsReadOnly = true; return; } throw; } } } }
/// <summary> /// Load the authenticator and configuration settings /// </summary> /// <param name="form">parent winform</param> /// <param name="configFile">name of configfile or null for auto</param> /// <param name="password">optional supplied password or null to prompt if necessatu</param> /// <returns>new WinAuthConfig settings</returns> public static WinAuthConfig LoadConfig(Form form, string configFile, string password = null) { WinAuthConfig config = new WinAuthConfig(); if (string.IsNullOrEmpty(password) == false) { config.Password = password; } if (string.IsNullOrEmpty(configFile) == true) { // check for file in current directory configFile = Path.Combine(Environment.CurrentDirectory, DEFAULT_AUTHENTICATOR_FILE_NAME); if (File.Exists(configFile) == false) { configFile = null; } } if (string.IsNullOrEmpty(configFile) == true) { // check for file in exe directory configFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), DEFAULT_AUTHENTICATOR_FILE_NAME); if (File.Exists(configFile) == false) { configFile = null; } } if (string.IsNullOrEmpty(configFile) == true) { // do we have a file specific in the registry? string configDirectory = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), WinAuthMain.APPLICATION_NAME); // check for default authenticator configFile = Path.Combine(configDirectory, DEFAULT_AUTHENTICATOR_FILE_NAME); // if no config file, just return a blank config if (File.Exists(configFile) == false) { return config; } } // if no config file when one was specified; report an error if (File.Exists(configFile) == false) { //MessageBox.Show(form, // strings.CannotFindConfigurationFile + ": " + configFile, // form.Text, MessageBoxButtons.OK, MessageBoxIcon.Error); // return config; throw new ApplicationException(strings.CannotFindConfigurationFile + ": " + configFile); } // check if readonly FileInfo fi = new FileInfo(configFile); if (fi.Exists && fi.IsReadOnly) { config.IsReadOnly = true; } bool changed = false; try { using (FileStream fs = new FileStream(configFile, FileMode.Open, FileAccess.Read)) { XmlReader reader = XmlReader.Create(fs); changed = config.ReadXml(reader, password); } config.Filename = configFile; if (config.Version < WinAuthConfig.CURRENTVERSION) { // set new created values foreach (WinAuthAuthenticator wa in config) { wa.Created = fi.CreationTime; } config.Upgraded = true; } if (changed == true && config.IsReadOnly == false) { SaveConfig(config); } } catch (EncrpytedSecretDataException ) { // we require a password throw; } catch (BadPasswordException) { // we require a password throw; } catch (Exception ) { throw; } SaveToRegistry(config); return config; }
/// <summary> /// Run an action on the authenticator /// </summary> /// <param name="auth">Authenticator to use</param> /// <param name="action">Action to perform</param> private void RunAction(WinAuthAuthenticator auth, WinAuthConfig.NotifyActions action) { // get the code string code = null; try { code = auth.CurrentCode; } catch (EncrpytedSecretDataException) { // if the authenticator is current protected we display the password window, get the code, and reprotect it // with a bit of window jiggling to make sure we get focus and then put it back // save the current window var fgwindow = WinAPI.GetForegroundWindow(); Screen screen = Screen.FromHandle(fgwindow); IntPtr activewindow = IntPtr.Zero; if (this.Visible == true) { activewindow = WinAPI.SetActiveWindow(this.Handle); BringToFront(); } var item = authenticatorList.Items.Cast<AuthenticatorListitem>().Where(i => i.Authenticator == auth).FirstOrDefault(); code = authenticatorList.GetItemCode(item, screen); // restore active window if (activewindow != IntPtr.Zero) { WinAPI.SetActiveWindow(activewindow); } WinAPI.SetForegroundWindow(fgwindow); } if (code != null) { KeyboardSender keysend = new KeyboardSender(auth.HotKey != null ? auth.HotKey.Window : null); string command = null; if (action == WinAuthConfig.NotifyActions.CopyToClipboard) { command = "{COPY}"; } else if (action == WinAuthConfig.NotifyActions.HotKey) { command = auth.HotKey != null ? auth.HotKey.Advanced : null; } else // if (this.Config.NotifyAction == WinAuthConfig.NotifyActions.Notification) { if (code.Length > 5) { code = code.Insert(code.Length / 2, " "); } notifyIcon.ShowBalloonTip(10000, auth.Name, code, ToolTipIcon.Info); } if (command != null) { keysend.SendKeys(this, command, code); } } }
/// <summary> /// Create the version checker instance /// </summary> public WinAuthUpdater(WinAuthConfig config) { Config = config; // read the update interval and last known latest version from the registry TimeSpan interval; if (TimeSpan.TryParse(Config.ReadSetting(WINAUTHREGKEY_CHECKFREQUENCY, string.Empty), out interval) == true) { _autocheckInterval = interval; } long lastCheck = 0; if (long.TryParse(Config.ReadSetting(WINAUTHREGKEY_LASTCHECK, null), out lastCheck) == true) { _lastCheck = new DateTime(lastCheck); } Version version; #if NETFX_4 if (Version.TryParse(Config.ReadSetting(WINAUTHREGKEY_LATESTVERSION, string.Empty), out version) == true) { _latestVersion = version; } #endif #if NETFX_3 try { version = new Version(Config.ReadSetting(WINAUTHREGKEY_LATESTVERSION, string.Empty)); _latestVersion = version; } catch (Exception) { } #endif }
/// <summary> /// Save the authenticator /// </summary> /// <param name="configFile">filename to save to</param> /// <param name="config">current settings to save</param> public static void SaveConfig(WinAuthConfig config) { // create the xml XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.Encoding = Encoding.UTF8; // Issue 41 (http://code.google.com/p/winauth/issues/detail?id=41): saving may crash leaving file corrupt, so write into memory stream first before an atomic file write using (MemoryStream ms = new MemoryStream()) { // save config into memory using (XmlWriter writer = XmlWriter.Create(ms, settings)) { config.WriteXmlString(writer); } // if no config file yet, use default if (string.IsNullOrEmpty(config.Filename) == true) { string configDirectory = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), WinAuthMain.APPLICATION_NAME); Directory.CreateDirectory(configDirectory); config.Filename = Path.Combine(configDirectory, DEFAULT_AUTHENTICATOR_FILE_NAME); } FileInfo fi = new FileInfo(config.Filename); if (!fi.Exists || !fi.IsReadOnly) { // write memory stream to file try { byte[] data = ms.ToArray(); // getting instance of zerod files, so do some sanity checks if (data.Length == 0 || data[0] == 0) { throw new ApplicationException("Zero data when saving config"); } using (FileStream fs = new FileStream(config.Filename, FileMode.Create, FileAccess.Write, FileShare.None)) { fs.Write(data, 0, data.Length); fs.Flush(); } // read it back var verify = File.ReadAllBytes(config.Filename); if (verify.Length != data.Length || verify.SequenceEqual(data) == false) { throw new ApplicationException("Save config doesn't compare with memory: " + Convert.ToBase64String(data)); } } catch (UnauthorizedAccessException ) { // fail silently if read only if (fi.IsReadOnly) { config.IsReadOnly = true; return; } throw; } } } }