/// <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(MainForm form, string configFile, string password) { WinAuthConfig config = new WinAuthConfig(); if (string.IsNullOrEmpty(configFile) == true) { configFile = GetLastFile(1); if (string.IsNullOrEmpty(configFile) == false && File.Exists(configFile) == false) { // ignore it if file does't exist 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), WinAuth.APPLICATION_NAME); Directory.CreateDirectory(configDirectory); // check the old 1.3 file name configFile = Path.Combine(configDirectory, CONFIG_FILE_NAME_1_3); if (File.Exists(configFile) == false) { // 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, "Unable to find your configuration file \"" + configFile + "\"", form.Text, MessageBoxButtons.OK, MessageBoxIcon.Error); return config; } DialogResult configloaded; do { configloaded = DialogResult.OK; try { XmlDocument doc = null; XmlNode node = null; try { doc = new XmlDocument(); doc.Load(configFile); // check and load older versions node = doc.SelectSingleNode("WinAuth"); } catch (XmlException ) { // cause by invalid format, so we try and load other type of authenticator } if (node == null) { // foreign file so we import (authenticator.xml from winauth_1.3, android BMA xml or Java rs) Authenticator auth = LoadAuthenticator(form, configFile); if (auth != null) { config.Authenticator = auth; } SetLastFile(configFile); // set this as the new last opened file return config; } // Show if BETA //if (new BetaForm().ShowDialog(form) != DialogResult.OK) //{ // return null; //} XmlAttribute versionAttr; decimal version = Authenticator.DEAFULT_CONFIG_VERSION; if ((versionAttr = node.Attributes["version"]) != null && (version = decimal.Parse(versionAttr.InnerText, System.Globalization.CultureInfo.InvariantCulture)) < (decimal)1.4) { // old version 1.3 file config = LoadConfig_1_3(form, configFile); if (string.IsNullOrEmpty(config.Filename) == true) { config.Filename = configFile; } else if (string.Compare(configFile, config.Filename, true) != 0) { // switch over from winauth.xml to authenticator.xml and remove old winauth.xml File.Delete(configFile); configFile = config.Filename; } SaveAuthenticator(form, configFile, config); SetLastFile(configFile); // set this as the new last opened file return config; } // set the filename as itself config.Filename = configFile; bool boolVal = false; node = doc.DocumentElement.SelectSingleNode("alwaysontop"); if (node != null && bool.TryParse(node.InnerText, out boolVal) == true) { config.AlwaysOnTop = boolVal; } node = doc.DocumentElement.SelectSingleNode("usetrayicon"); if (node != null && bool.TryParse(node.InnerText, out boolVal) == true) { config.UseTrayIcon = boolVal; } node = doc.DocumentElement.SelectSingleNode("startwithwindows"); if (node != null && bool.TryParse(node.InnerText, out boolVal) == true) { config.StartWithWindows = boolVal; } node = doc.DocumentElement.SelectSingleNode("autorefresh"); if (node != null && bool.TryParse(node.InnerText, out boolVal) == true) { config.AutoRefresh = boolVal; } node = doc.DocumentElement.SelectSingleNode("allowcopy"); if (node != null && bool.TryParse(node.InnerText, out boolVal) == true) { config.AllowCopy = boolVal; } node = doc.DocumentElement.SelectSingleNode("copyoncode"); if (node != null && bool.TryParse(node.InnerText, out boolVal) == true) { config.CopyOnCode = boolVal; } node = doc.DocumentElement.SelectSingleNode("hideserial"); if (node != null && bool.TryParse(node.InnerText, out boolVal) == true) { config.HideSerial = boolVal; } // load the authenticator(s) - may have multiple authenticators in future version XmlNodeList nodes = doc.DocumentElement.SelectNodes("authenticator"); if (nodes != null) { // get the local machine time diff long machineTimeDiff = GetMachineTimeDiff(); foreach (XmlNode authenticatorNode in nodes) { // load the data Authenticator auth = null; try { try { auth = new Authenticator(); auth.Load(authenticatorNode, password, version); config.Authenticator = auth; } catch (EncrpytedSecretDataException) { PasswordForm passwordForm = new PasswordForm(); int retries = 0; do { passwordForm.Password = string.Empty; DialogResult result = passwordForm.ShowDialog(form); if (result != System.Windows.Forms.DialogResult.OK) { break; } try { auth = new Authenticator(); auth.Load(authenticatorNode, passwordForm.Password, version); config.Authenticator = auth; break; } catch (BadPasswordException) { MessageBox.Show(form, "Invalid password", "Load Authenticator", MessageBoxButtons.OK, MessageBoxIcon.Error); if (retries++ >= MAX_PASSWORD_RETRIES - 1) { break; } } } while (true); } // adjust the time diff from the local machine if (auth != null && machineTimeDiff != 0) { auth.ServerTimeDiff = machineTimeDiff; } } catch (InvalidUserDecryptionException) { MessageBox.Show(form, "The authenticator was encrypted using a different Windows User account.", "Load Authenticator", MessageBoxButtons.OK, MessageBoxIcon.Error); } catch (InvalidMachineDecryptionException) { MessageBox.Show(form, "The authenticator was encrypted using a different Windows computer.", "Load Authenticator", MessageBoxButtons.OK, MessageBoxIcon.Error); } catch (InvalidConfigDataException) { MessageBox.Show(form, "The authenticator data in " + configFile + " is not valid", "Load Authenticator", MessageBoxButtons.OK, MessageBoxIcon.Error); } catch (Exception ex) { MessageBox.Show(form, "Unable to load authenticator from " + configFile + ": " + ex.Message, "Load Authenticator", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } // get the autologin node after we have gotten the pasword node = doc.DocumentElement.SelectSingleNode("autologin"); if (node != null && node.InnerText.Length != 0 && config.Authenticator != null) { config.AutoLogin = new HoyKeySequence(node, config.Authenticator.Password, version); } } catch (Exception ex) { configloaded = MessageBox.Show(form, "An error occured while loading your configuration file \"" + configFile + "\": " + ex.Message + "\n\nIt may be corrupted or in use by another application.", form.Text, MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error); if (configloaded == DialogResult.Abort) { return null; } } } while (configloaded == DialogResult.Retry); SetLastFile(configFile); // set this as the new last opened file return config; }
/// <summary> /// Import and authenticator file of different formats /// </summary> /// <param name="configFile">filename to load</param> /// <param name="password">optional password</param> /// <returns>new Authenticator</returns> public static Authenticator ImportAuthenticator(string configFile, string password) { using (FileStream fs = new FileStream(configFile, FileMode.Open)) { Authenticator auth = new Authenticator(); // read the file string ext = Path.GetExtension(configFile).ToLower(); if (ext == ".xml") { // load ours or the Android XML file auth.Load(fs, Authenticator.FileFormat.WinAuth, password); } else { // load the Java MIDP recordfile auth.Load(fs, Authenticator.FileFormat.Midp, password); } return auth; } }