예제 #1
0
		/// <summary>
		/// Create a new AuthenticatorListitem
		/// </summary>
		/// <param name="auth">authenticator</param>
		/// <param name="index">index of item</param>
		public AuthenticatorListitem(WinAuthAuthenticator auth, int index)
		{
			Authenticator = auth;
			LastUpdate = DateTime.MinValue;
			Index = index;
			DisplayUntil = DateTime.MinValue;
		}
예제 #2
0
 /// <summary>
 /// Default constructor
 /// </summary>
 public ConfigChangedEventArgs(string propertyName, WinAuthAuthenticator authenticator = null, WinAuthAuthenticatorChangedEventArgs acargs = null)
     : base()
 {
     PropertyName  = propertyName;
     Authenticator = authenticator;
     AuthenticatorChangedEventArgs = acargs;
 }
예제 #3
0
        /// <summary>
        ///     Callback called by Form to initaite press of hotkey
        /// </summary>
        /// <param name="kea">KeyboardHookEventArgs event args</param>
        public void KeyCallback(KeyboardHookEventArgs kea)
        {
            // key and modifers match?
            WinAuthAuthenticator match = null;

            foreach (var auth in m_hooked)
            {
                if ((Keys)auth.HotKey.Key == kea.Key && auth.HotKey.Modifiers == kea.Modifiers)
                {
                    match = auth;
                    break;
                }
            }

            if (match == null)
            {
                return;
            }
            kea.Authenticator = match;

            // call user events
            if (KeyPressed != null)
            {
                KeyPressed(this, kea);
            }
        }
예제 #4
0
        /// <summary>
        /// Clone this authenticator
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            WinAuthAuthenticator clone = this.MemberwiseClone() as WinAuthAuthenticator;

            clone.Id = Guid.NewGuid();
            clone.OnWinAuthAuthenticatorChanged = null;
            clone.AuthenticatorData             = (this.AuthenticatorData != null ? this.AuthenticatorData.Clone() as Authenticator : null);

            return(clone);
        }
예제 #5
0
        /// <summary>
        /// Set up the hook into Windows
        /// </summary>
        protected void Hook()
        {
            for (int i = 0; i < m_hooked.Count; i++)
            {
                WinAuthAuthenticator auth = m_hooked[i];
                Keys key = (Keys)auth.HotKey.Key;
                WinAPI.KeyModifiers modifier = auth.HotKey.Modifiers;

                if (WinAPI.RegisterHotKey(m_form.Handle, i + 1, modifier | WinAPI.KeyModifiers.NoRepeat, key) == false)
                {
                    // the MOD_NOREPEAT flag is not support in XP or 2003 and we should get a fail, so we call again without it
                    WinAPI.RegisterHotKey(m_form.Handle, i + 1, modifier, key);
                }
            }
        }
예제 #6
0
		/// <summary>
		/// Process the pressed hotkey by performing the appropriate operation
		/// </summary>
		/// <param name="auth">Authenticator</param>
		private void HandleHotkey(WinAuthAuthenticator auth)
		{
			// 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)
			{
				// default to sending the code to the current window
				KeyboardSender keysend = new KeyboardSender(auth.HotKey.Window);
				string command = null;
				if (auth.HotKey.Action == HotKey.HotKeyActions.Notify)
				{
					if (auth.CopyOnCode)
					{
						auth.CopyCodeToClipboard(this, code);
					}
					if (code.Length > 5)
					{
						code = code.Insert(code.Length / 2, " ");
					}
					notifyIcon.ShowBalloonTip(10000, auth.Name, code, ToolTipIcon.Info);
				}
				if (auth.HotKey.Action == HotKey.HotKeyActions.Copy)
				{
					command = "{COPY}";
				}
				else if (auth.HotKey.Action == HotKey.HotKeyActions.Advanced)
				{
					command = auth.HotKey.Advanced;
				}
				else if (auth.HotKey.Action == HotKey.HotKeyActions.Inject)
				{
					command = "{CODE}";
				}
				if (command != null)
				{
					keysend.SendKeys(this, command, code);
				}
			}
	  }
예제 #7
0
		/// <summary>
		/// Load the authenticators into the display list
		/// </summary>
		/// <param name="added">authenticator we just added</param>
		private void loadAuthenticatorList(WinAuthAuthenticator added = null)
		{
			// set up list
			authenticatorList.Items.Clear();

			int index = 0;
			foreach (var auth in Config)
			{
				var ali = new AuthenticatorListitem(auth, index);
				if (added != null && added == auth && auth.AutoRefresh == false && !(auth.AuthenticatorData is HOTPAuthenticator))
				{
					ali.LastUpdate = DateTime.Now;
					ali.DisplayUntil = DateTime.Now.AddSeconds(10);
				}
				authenticatorList.Items.Add(ali);
				index++;
			}

			authenticatorList.Visible = (authenticatorList.Items.Count != 0);
		}
예제 #8
0
			/// <summary>
			/// Create a new HotKeyLauncher object
			/// </summary>
			/// <param name="form">owning Form</param>
			/// <param name="auth">Authenticator</param>
			public HotKeyLauncher(WinAuthForm form, WinAuthAuthenticator auth)
			{
				Started = DateTime.Now;
				Form = form;
				Authenticator = auth;
			}
예제 #9
0
		/// <summary>
		/// Click on a choice of new authenticator
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void addAuthenticatorMenu_Click(object sender, EventArgs e)
		{
			ToolStripItem menuitem = (ToolStripItem)sender;
			RegisteredAuthenticator registeredauth = menuitem.Tag as RegisteredAuthenticator;
			if (registeredauth != null)
			{
				// add the new authenticator
				WinAuthAuthenticator winauthauthenticator = new WinAuthAuthenticator();
				bool added = false;

				if (registeredauth.AuthenticatorType == RegisteredAuthenticator.AuthenticatorTypes.BattleNet)
				{
					int existing = 0;
					string name;
					do
					{
						name = "Battle.net" + (existing != 0 ? " (" + existing + ")" : string.Empty);
						existing++;
					} while (authenticatorList.Items.Cast<AuthenticatorListitem>().Where(a => a.Authenticator.Name == name).Count() != 0);

					winauthauthenticator.Name = name;
					winauthauthenticator.AutoRefresh = false;

					// create the Battle.net authenticator
					AddBattleNetAuthenticator form = new AddBattleNetAuthenticator();
					form.Authenticator = winauthauthenticator;
					added = (form.ShowDialog(this) == System.Windows.Forms.DialogResult.OK);
				}
				else if (registeredauth.AuthenticatorType == RegisteredAuthenticator.AuthenticatorTypes.Trion)
				{
					// create the Trion authenticator
					int existing = 0;
					string name;
					do
					{
						name = "Trion" + (existing != 0 ? " (" + existing + ")" : string.Empty);
						existing++;
					} while (authenticatorList.Items.Cast<AuthenticatorListitem>().Where(a => a.Authenticator.Name == name).Count() != 0);

					winauthauthenticator.Name = name;
					winauthauthenticator.AutoRefresh = false;

					AddTrionAuthenticator form = new AddTrionAuthenticator();
					form.Authenticator = winauthauthenticator;
					added = (form.ShowDialog(this) == System.Windows.Forms.DialogResult.OK);
				}
				else if (registeredauth.AuthenticatorType == RegisteredAuthenticator.AuthenticatorTypes.Steam)
				{
					// create the authenticator
					int existing = 0;
					string name;
					do
					{
						name = "Steam" + (existing != 0 ? " (" + existing + ")" : string.Empty);
						existing++;
					} while (authenticatorList.Items.Cast<AuthenticatorListitem>().Where(a => a.Authenticator.Name == name).Count() != 0);

					winauthauthenticator.Name = name;
					winauthauthenticator.AutoRefresh = false;

					AddSteamAuthenticator form = new AddSteamAuthenticator();
					form.Authenticator = winauthauthenticator;
					added = (form.ShowDialog(this) == System.Windows.Forms.DialogResult.OK);
				}
				else if (registeredauth.AuthenticatorType == RegisteredAuthenticator.AuthenticatorTypes.Google)
				{
					// create the Google authenticator
					// add the new authenticator
					int existing = 0;
					string name;
					do
					{
						name = "Google" + (existing != 0 ? " (" + existing + ")" : string.Empty);
						existing++;
					} while (authenticatorList.Items.Cast<AuthenticatorListitem>().Where(a => a.Authenticator.Name == name).Count() != 0);
					winauthauthenticator.Name = name;
					winauthauthenticator.AutoRefresh = false;

					AddGoogleAuthenticator form = new AddGoogleAuthenticator();
					form.Authenticator = winauthauthenticator;
					added = (form.ShowDialog(this) == System.Windows.Forms.DialogResult.OK);
				}
				else if (registeredauth.AuthenticatorType == RegisteredAuthenticator.AuthenticatorTypes.GuildWars)
				{
					// create the GW2 authenticator
					int existing = 0;
					string name;
					do
					{
						name = "GuildWars" + (existing != 0 ? " (" + existing + ")" : string.Empty);
						existing++;
					} while (authenticatorList.Items.Cast<AuthenticatorListitem>().Where(a => a.Authenticator.Name == name).Count() != 0);
					winauthauthenticator.Name = name;
					winauthauthenticator.AutoRefresh = false;

					AddGuildWarsAuthenticator form = new AddGuildWarsAuthenticator();
					form.Authenticator = winauthauthenticator;
					added = (form.ShowDialog(this) == System.Windows.Forms.DialogResult.OK);
				}
				else if (registeredauth.AuthenticatorType == RegisteredAuthenticator.AuthenticatorTypes.Microsoft)
				{
					// create the Microsoft authenticator
					int existing = 0;
					string name;
					do
					{
						name = "Microsoft" + (existing != 0 ? " (" + existing + ")" : string.Empty);
						existing++;
					} while (authenticatorList.Items.Cast<AuthenticatorListitem>().Where(a => a.Authenticator.Name == name).Count() != 0);
					winauthauthenticator.Name = name;
					winauthauthenticator.AutoRefresh = false;

					AddMicrosoftAuthenticator form = new AddMicrosoftAuthenticator();
					form.Authenticator = winauthauthenticator;
					added = (form.ShowDialog(this) == System.Windows.Forms.DialogResult.OK);
				}
				else if (registeredauth.AuthenticatorType == RegisteredAuthenticator.AuthenticatorTypes.RFC6238_TIME)
				{
					// create the Google authenticator
					// add the new authenticator
					int existing = 0;
					string name;
					do
					{
						name = "Authenticator" + (existing != 0 ? " (" + existing + ")" : string.Empty);
						existing++;
					} while (authenticatorList.Items.Cast<AuthenticatorListitem>().Where(a => a.Authenticator.Name == name).Count() != 0);
					winauthauthenticator.Name = name;
					winauthauthenticator.AutoRefresh = false;
					winauthauthenticator.Skin = "WinAuthIcon.png";

					AddAuthenticator form = new AddAuthenticator();
					form.Authenticator = winauthauthenticator;
					added = (form.ShowDialog(this) == System.Windows.Forms.DialogResult.OK);
				}
				else
				{
					throw new NotImplementedException(strings.AuthenticatorNotImplemented + ": " + registeredauth.AuthenticatorType.ToString());
				}

				if (added == true)
				{
					// save off any new authenticators as a backup
					WinAuthHelper.SaveToRegistry(this.Config, winauthauthenticator);

					// first time we prompt for protection
					if (this.Config.Count == 0)
					{
						ChangePasswordForm form = new ChangePasswordForm();
						form.PasswordType = Authenticator.PasswordTypes.Explicit;
						if (form.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
						{
							this.Config.Yubi = form.Yubikey;
							this.Config.PasswordType = form.PasswordType;
							if ((this.Config.PasswordType & Authenticator.PasswordTypes.Explicit) != 0 && string.IsNullOrEmpty(form.Password) == false)
							{
								this.Config.Password = form.Password;
							}
						}
					}

					this.Config.Add(winauthauthenticator);
					SaveConfig(true);
					loadAuthenticatorList(winauthauthenticator);

					// reset UI
					setAutoSize();
					introLabel.Visible = (this.Config.Count == 0);

					// reset hotkeeys
					HookHotkeys();
				}
			}
		}
예제 #10
0
		/// <summary>
		/// Import a file containing authenticators in the KeyUriFormat. The file might be plain text, encrypted zip or encrypted pgp.
		/// </summary>
		/// <param name="parent">parent Form</param>
		/// <param name="file">file name to import</param>
		/// <returns>list of imported authenticators</returns>
		public static List<WinAuthAuthenticator> ImportAuthenticators(Form parent, string file)
		{
			List<WinAuthAuthenticator> authenticators = new List<WinAuthAuthenticator>();

			string password = null;
			string pgpKey = null;

			StringBuilder lines = new StringBuilder();
			bool retry;
			do
			{
				retry = false;
				lines.Length = 0;

				// open the zip file
				if (string.Compare(Path.GetExtension(file), ".zip", true) == 0)
				{
					using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
					{
						ZipFile zip = null;
						try
						{
							zip = new ZipFile(fs);
							if (string.IsNullOrEmpty(password) == false)
							{
								zip.Password = password;
							}

							byte[] buffer = new byte[4096];
							foreach (ZipEntry entry in zip)
							{
								if (entry.IsFile == false || string.Compare(Path.GetExtension(entry.Name), ".txt", true) != 0)
								{
									continue;
								}

								// read file out
								Stream zs = zip.GetInputStream(entry);
								using (var ms = new MemoryStream())
								{
									StreamUtils.Copy(zs, ms, buffer);

									// get as string and append
									ms.Seek(0, SeekOrigin.Begin);
									using (var sr = new StreamReader(ms))
									{
										lines.Append(sr.ReadToEnd()).Append(Environment.NewLine);
									}
								}
							}
						}
						catch (ZipException ex)
						{
							if (ex.Message.IndexOf("password") != -1)
							{
								// already have a password
								if (string.IsNullOrEmpty(password) == false)
								{
									WinAuthForm.ErrorDialog(parent, strings.InvalidPassword, ex.InnerException, MessageBoxButtons.OK);
								}

								// need password
								GetPasswordForm form = new GetPasswordForm();
								if (form.ShowDialog(parent) == DialogResult.Cancel)
								{
									return null;
								}
								password = form.Password;
								retry = true;
								continue;
							}

							throw;
						}
						finally
						{
							if (zip != null)
							{
								zip.IsStreamOwner = true;
								zip.Close();
							}
						}
					}
				}
				else if (string.Compare(Path.GetExtension(file), ".pgp", true) == 0)
				{
					string encoded = File.ReadAllText(file);
					if (string.IsNullOrEmpty(pgpKey) == true)
					{
						// need password
						GetPGPKeyForm form = new GetPGPKeyForm();
						if (form.ShowDialog(parent) == DialogResult.Cancel)
						{
							return null;
						}
						pgpKey = form.PGPKey;
						password = form.Password;
						retry = true;
						continue;
					}
					try
					{
						string line = PGPDecrypt(encoded, pgpKey, password);
						lines.Append(line);
					}
					catch (Exception ex)
					{
						WinAuthForm.ErrorDialog(parent, strings.InvalidPassword, ex.InnerException, MessageBoxButtons.OK);

						pgpKey = null;
						password = null;
						retry = true;
						continue;
					}
				}
				else // read a plain text file
				{
					lines.Append(File.ReadAllText(file));
				}
			} while (retry);

			int linenumber = 0;
			try
			{
				using (var sr = new StringReader(lines.ToString()))
				{
					string line;
					while ((line = sr.ReadLine()) != null)
					{
						linenumber++;

						// ignore blank lines or comments
						line = line.Trim();
						if (line.Length == 0 || line.IndexOf("#") == 0)
						{
							continue;
						}

						// parse and validate URI
						var uri = new Uri(line);

						// we only support "otpauth"
						if (uri.Scheme != "otpauth")
						{
							throw new ApplicationException("Import only supports otpauth://");
						}
						// we only support totp (not hotp)
						if (uri.Host != "totp" && uri.Host != "hotp")
						{
							throw new ApplicationException("Import only supports otpauth://totp/ or otpauth://hotp/");
						}

						// get the label and optional issuer
						string issuer = string.Empty;
						string label = (string.IsNullOrEmpty(uri.LocalPath) == false ? uri.LocalPath.Substring(1) : string.Empty); // skip past initial /
						int p = label.IndexOf(":");
						if (p != -1)
						{
							issuer = label.Substring(0, p);
							label = label.Substring(p + 1);
						}
						// + aren't decoded
						label = label.Replace("+", " ");

						var query = HttpUtility.ParseQueryString(uri.Query);
						string secret = query["secret"];
						if (string.IsNullOrEmpty(secret) == true)
						{
							throw new ApplicationException("Authenticator does not contain secret");
						}

						string counter = query["counter"];
						if (uri.Host == "hotp" && string.IsNullOrEmpty(counter) == true)
						{
							throw new ApplicationException("HOTP authenticator should have a counter");
						}

						WinAuthAuthenticator importedAuthenticator = new WinAuthAuthenticator();
						importedAuthenticator.AutoRefresh = false;
						//
						Authenticator auth;
						if (string.Compare(issuer, "BattleNet", true) == 0)
						{
							string serial = query["serial"];
							if (string.IsNullOrEmpty(serial) == true)
							{
								throw new ApplicationException("Battle.net Authenticator does not have a serial");
							}
							serial = serial.ToUpper();
							if (Regex.IsMatch(serial, @"^[A-Z]{2}-?[\d]{4}-?[\d]{4}-?[\d]{4}$") == false)
							{
								throw new ApplicationException("Invalid serial for Battle.net Authenticator");
							}
							auth = new BattleNetAuthenticator();
							//char[] decoded = Base32.getInstance().Decode(secret).Select(c => Convert.ToChar(c)).ToArray(); // this is hex string values
							//string hex = new string(decoded);
							//((BattleNetAuthenticator)auth).SecretKey = Authenticator.StringToByteArray(hex);

							((BattleNetAuthenticator)auth).SecretKey = Base32.getInstance().Decode(secret);

							((BattleNetAuthenticator)auth).Serial = serial;

							issuer = string.Empty;
						}
						else if (string.Compare(issuer, "Steam", true) == 0)
						{
							auth = new SteamAuthenticator();
							((SteamAuthenticator)auth).SecretKey = Base32.getInstance().Decode(secret);
							((SteamAuthenticator)auth).Serial = string.Empty;
							((SteamAuthenticator)auth).DeviceId = string.Empty;
							((SteamAuthenticator)auth).RevocationCode = string.Empty;
							issuer = string.Empty;
						}
						else if (uri.Host == "hotp")
						{
							auth = new HOTPAuthenticator();
							((HOTPAuthenticator)auth).SecretKey = Base32.getInstance().Decode(secret);
							((HOTPAuthenticator)auth).Counter = int.Parse(counter);
							
							if (string.IsNullOrEmpty(issuer) == false)
							{
								auth.Issuer = issuer;
							}
						}
						else // if (string.Compare(issuer, "Google", true) == 0)
						{
							auth = new GoogleAuthenticator();
							((GoogleAuthenticator)auth).Enroll(secret);

							if (string.Compare(issuer, "Google", true) == 0)
							{
								issuer = string.Empty;
							}
							else if (string.IsNullOrEmpty(issuer) == false)
							{
								auth.Issuer = issuer;
							}
						}
						//
						int digits = 0;
						int.TryParse(query["digits"], out digits);
						if (digits != 0)
						{
							auth.CodeDigits = digits;
						}
						//
						if (label.Length != 0)
						{
							importedAuthenticator.Name = (issuer.Length != 0 ? issuer + " (" + label + ")" : label);
						}
						else if (issuer.Length != 0)
						{
							importedAuthenticator.Name = issuer;
						}
						else
						{
							importedAuthenticator.Name = "Imported";
						}
						//
						importedAuthenticator.AuthenticatorData = auth;

						// set the icon
						string icon = query["icon"];
						if (string.IsNullOrEmpty(icon) == false)
						{
							if (icon.StartsWith("base64:") == true)
							{
								string b64 = Convert.ToBase64String(Base32.getInstance().Decode(icon.Substring(7)));
								importedAuthenticator.Skin = "base64:" + b64;
							}
							else
							{
								importedAuthenticator.Skin = icon + "Icon.png";
							}
						}

						// sync
						importedAuthenticator.Sync();

						authenticators.Add(importedAuthenticator);
					}
				}

				return authenticators;
			}
			catch (UriFormatException ex)
			{
				throw new ImportException(string.Format(strings.ImportInvalidUri, linenumber), ex);
			}
			catch (Exception ex)
			{
				throw new ImportException(string.Format(strings.ImportError, linenumber, ex.Message), ex);
			}
		}
예제 #11
0
		/// <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));
				}
			}
		}
예제 #12
0
		/// <summary>
		/// Display a new Notification for a Trading confirmation
		/// </summary>
		/// <param name="auth"></param>
		/// <param name="title"></param>
		/// <param name="message"></param>
		/// <param name="extraHeight"></param>
		public void ShowNotification(WinAuthAuthenticator auth, string title, string message, bool openOnClick, int extraHeight)
		{
			var notify = new Notification(title, message, 10000);
			if (extraHeight != 0)
			{
				notify.Height += extraHeight;
			}
			notify.Tag = auth;
			if (openOnClick == true)
			{
				notify.OnNotificationClicked += Notify_Click;
			}
			notify.Show();
		}
예제 #13
0
		/// <summary>
		/// Default constructor
		/// </summary>
		public AuthenticatorListDoubleClickEventArgs(WinAuthAuthenticator auth)
			: base()
		{
			Authenticator = auth;
		}