Example #1
0
        /// <summary>
        /// Click to create a enroll a new authenticator
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void enrollAuthenticatorButton_Click(object sender, EventArgs e)
        {
            do
            {
                try
                {
                    newSerialNumberField.Text = "creating...";

                    BattleNetAuthenticator authenticator = new BattleNetAuthenticator();
#if DEBUG
                    authenticator.Enroll(System.Diagnostics.Debugger.IsAttached);
#else
                    authenticator.Enroll();
#endif
                    this.Authenticator.AuthenticatorData = authenticator;
                    newSerialNumberField.Text            = authenticator.Serial;
                    newLoginCodeField.Text   = authenticator.CurrentCode;
                    newRestoreCodeField.Text = authenticator.RestoreCode;

                    newAuthenticatorProgress.Visible = true;
                    newAuthenticatorTimer.Enabled    = true;

                    return;
                }
                catch (InvalidEnrollResponseException iere)
                {
                    if (WinAuthForm.ErrorDialog(this.Owner, "注册新的验证器时发生错误", iere, MessageBoxButtons.RetryCancel) != System.Windows.Forms.DialogResult.Retry)
                    {
                        break;
                    }
                }
            } while (true);

            clearAuthenticator(false);
        }
Example #2
0
        /// <summary>
        ///     Perform a verification of the restore code in the background by checking it with the servers
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void VerifyRestoreCode(object sender, DoWorkEventArgs e)
        {
            var auth = e.Argument as BattleNetAuthenticator;

            // check if this authenticator is too old to be restored
            try
            {
                var testrestore = new BattleNetAuthenticator();
                testrestore.Restore(auth.Serial, auth.RestoreCode);
                auth.RestoreCodeVerified = true;
                e.Result = null;
            }
            catch (InvalidRestoreCodeException)
            {
                e.Result =
                    "This authenticator was created before the restore capability existed and so the restore code will not work.\n\n"
                    + "You will need to remove this authenticator from your Battle.net account and create a new one.";
            }
            catch (InvalidRestoreResponseException)
            {
                // ignore the validation if servers are down
            }
            catch (Exception ex2)
            {
                e.Result = "Oops. An error (" + ex2.Message + ") occured whilst validating your restore code."
                           + "Please log a ticket at https://github.com/winauth/winauth/issues so we can fix this.";
            }
        }
Example #3
0
        /// <summary>
        /// Form loaded event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ShowRestoreCodeForm_Load(object sender, EventArgs e)
        {
            BattleNetAuthenticator authenticator = CurrentAuthenticator.AuthenticatorData as BattleNetAuthenticator;

            this.serialNumberField.SecretMode = true;
            this.restoreCodeField.SecretMode  = true;

            this.serialNumberField.Text = authenticator.Serial;
            this.restoreCodeField.Text  = authenticator.RestoreCode;

            // if needed start a background thread to verify the restore code
            if (authenticator.RestoreCodeVerified == false)
            {
                BackgroundWorker verify = new BackgroundWorker();
                verify.DoWork             += new DoWorkEventHandler(VerifyRestoreCode);
                verify.RunWorkerCompleted += new RunWorkerCompletedEventHandler(VerifyRestoreCodeCompleted);
                verify.RunWorkerAsync(CurrentAuthenticator.AuthenticatorData);
            }
        }
Example #4
0
        /// <summary>
        /// Verify and create the authenticator if needed
        /// </summary>
        /// <returns>true is successful</returns>
        private bool verifyAuthenticator(string privatekey)
        {
            if (string.IsNullOrEmpty(privatekey) == true)
            {
                return(false);
            }

            this.Authenticator.Name = nameField.Text;

            int digits = (this.Authenticator.AuthenticatorData != null ? this.Authenticator.AuthenticatorData.CodeDigits : GoogleAuthenticator.DEFAULT_CODE_DIGITS);

            if (string.IsNullOrEmpty(digitsField.Text) == true || int.TryParse(digitsField.Text, out digits) == false || digits <= 0)
            {
                return(false);
            }

            WinAuth.Authenticator.HMACTypes hmac = WinAuth.Authenticator.HMACTypes.SHA1;
#if NETFX_3
            try
            {
                hmac = (WinAuth.Authenticator.HMACTypes)Enum.Parse(typeof(WinAuth.Authenticator.HMACTypes), (string)hashField.SelectedItem, true);
            }
            catch (Exception) { }
#else
            Enum.TryParse <WinAuth.Authenticator.HMACTypes>((string)hashField.SelectedItem, out hmac);
#endif

            string authtype = timeBasedRadio.Checked == true ? TOTP : HOTP;

            int period = 0;
            if (string.IsNullOrEmpty(intervalField.Text) == true || int.TryParse(intervalField.Text, out period) == false || period <= 0)
            {
                return(false);
            }

            long counter = 0;

            // if this is a URL, pull it down
            Uri   uri;
            Match match;
            if (Regex.IsMatch(privatekey, "https?://.*") == true && Uri.TryCreate(privatekey, UriKind.Absolute, out uri) == true)
            {
                try
                {
                    var request = (HttpWebRequest)WebRequest.Create(uri);
                    request.AllowAutoRedirect = true;
                    request.Timeout           = 20000;
                    request.UserAgent         = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)";
                    using (var response = (HttpWebResponse)request.GetResponse())
                    {
                        if (response.StatusCode == HttpStatusCode.OK && response.ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase) == true)
                        {
                            using (Bitmap bitmap = (Bitmap)Bitmap.FromStream(response.GetResponseStream()))
                            {
                                IBarcodeReader reader = new BarcodeReader();
                                var            result = reader.Decode(bitmap);
                                if (result != null)
                                {
                                    privatekey = HttpUtility.UrlDecode(result.Text);
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "Cannot load QR code image from " + privatekey, ex);
                    return(false);
                }
            }
            else if ((match = Regex.Match(privatekey, @"data:image/([^;]+);base64,(.*)", RegexOptions.IgnoreCase)).Success == true)
            {
                byte[] imagedata = Convert.FromBase64String(match.Groups[2].Value);
                using (MemoryStream ms = new MemoryStream(imagedata))
                {
                    using (Bitmap bitmap = (Bitmap)Bitmap.FromStream(ms))
                    {
                        IBarcodeReader reader = new BarcodeReader();
                        var            result = reader.Decode(bitmap);
                        if (result != null)
                        {
                            privatekey = HttpUtility.UrlDecode(result.Text);
                        }
                    }
                }
            }
            else if (IsValidFile(privatekey) == true)
            {
                // assume this is the image file
                using (Bitmap bitmap = (Bitmap)Bitmap.FromFile(privatekey))
                {
                    IBarcodeReader reader = new BarcodeReader();
                    var            result = reader.Decode(bitmap);
                    if (result != null)
                    {
                        privatekey = result.Text;
                    }
                }
            }

            string issuer = null;
            string serial = null;

            // check for otpauth://, e.g. "otpauth://totp/[email protected]?secret=IHZJDKAEEC774BMUK3GX6SA"
            match = Regex.Match(privatekey, @"otpauth://([^/]+)/([^?]+)\?(.*)", RegexOptions.IgnoreCase);
            if (match.Success == true)
            {
                authtype = match.Groups[1].Value.ToLower();
                string label = match.Groups[2].Value;
                int    p     = label.IndexOf(":");
                if (p != -1)
                {
                    issuer = label.Substring(0, p);
                    label  = label.Substring(p + 1);
                }

                NameValueCollection qs = WinAuthHelper.ParseQueryString(match.Groups[3].Value);
                privatekey = qs["secret"] ?? privatekey;
                int querydigits;
                if (int.TryParse(qs["digits"], out querydigits) && querydigits != 0)
                {
                    digits = querydigits;
                }
                if (qs["counter"] != null)
                {
                    long.TryParse(qs["counter"], out counter);
                }
                issuer = qs["issuer"];
                if (string.IsNullOrEmpty(issuer) == false)
                {
                    label = issuer + (string.IsNullOrEmpty(label) == false ? " (" + label + ")" : string.Empty);
                }
                serial = qs["serial"];
                if (string.IsNullOrEmpty(label) == false)
                {
                    this.Authenticator.Name = this.nameField.Text = label;
                }
                string periods = qs["period"];
                if (string.IsNullOrEmpty(periods) == false)
                {
                    int.TryParse(periods, out period);
                }
                if (qs["algorithm"] != null)
                {
#if NETFX_3
                    try
                    {
                        hmac = (WinAuth.Authenticator.HMACTypes)Enum.Parse(typeof(WinAuth.Authenticator.HMACTypes), qs["algorithm"], true);
                        hashField.SelectedItem = hmac.ToString();
                    }
                    catch (Exception) { }
#else
                    if (Enum.TryParse <WinAuth.Authenticator.HMACTypes>(qs["algorithm"], true, out hmac) == true)
                    {
                        hashField.SelectedItem = hmac.ToString();
                    }
#endif
                }
            }

            // just get the hex chars
            privatekey = Regex.Replace(privatekey, @"[^0-9a-z]", "", RegexOptions.IgnoreCase);
            if (privatekey.Length == 0)
            {
                WinAuthForm.ErrorDialog(this.Owner, "The secret code is not valid");
                return(false);
            }

            try
            {
                Authenticator auth;
                if (authtype == TOTP)
                {
                    if (string.Compare(issuer, "BattleNet", true) == 0)
                    {
                        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();
                        ((BattleNetAuthenticator)auth).SecretKey = Base32.getInstance().Decode(privatekey);
                        ((BattleNetAuthenticator)auth).Serial    = serial;

                        issuer = string.Empty;
                    }
                    else if (issuer == "Steam")
                    {
                        auth = new SteamAuthenticator();
                        ((SteamAuthenticator)auth).SecretKey = Base32.getInstance().Decode(privatekey);
                        ((SteamAuthenticator)auth).Serial    = string.Empty;
                        ((SteamAuthenticator)auth).DeviceId  = string.Empty;
                        //((SteamAuthenticator)auth).RevocationCode = string.Empty;
                        ((SteamAuthenticator)auth).SteamData = string.Empty;

                        this.Authenticator.Skin = null;

                        issuer = string.Empty;
                    }
                    else
                    {
                        auth = new GoogleAuthenticator();
                        ((GoogleAuthenticator)auth).Enroll(privatekey);
                    }
                    timer.Enabled          = true;
                    codeProgress.Visible   = true;
                    timeBasedRadio.Checked = true;
                }
                else if (authtype == HOTP)
                {
                    auth = new HOTPAuthenticator();
                    if (counterField.Text.Trim().Length != 0)
                    {
                        long.TryParse(counterField.Text.Trim(), out counter);
                    }
                    ((HOTPAuthenticator)auth).Enroll(privatekey, counter); // start with the next code
                    timer.Enabled             = false;
                    codeProgress.Visible      = false;
                    counterBasedRadio.Checked = true;
                }
                else
                {
                    WinAuthForm.ErrorDialog(this.Owner, "Only TOTP or HOTP authenticators are supported");
                    return(false);
                }

                auth.HMACType   = hmac;
                auth.CodeDigits = digits;
                auth.Period     = period;
                this.Authenticator.AuthenticatorData = auth;

                if (digits > 5)
                {
                    codeField.SpaceOut = digits / 2;
                }
                else
                {
                    codeField.SpaceOut = 0;
                }

                //string key = Base32.getInstance().Encode(this.Authenticator.AuthenticatorData.SecretKey);
                this.codeField.Text = auth.CurrentCode;

                codeProgress.Maximum = period;

                if (!(auth is HOTPAuthenticator) && auth.ServerTimeDiff == 0L && SyncErrorWarned == false)
                {
                    SyncErrorWarned = true;
                    MessageBox.Show(this, string.Format(strings.AuthenticatorSyncError, "Google"), WinAuthMain.APPLICATION_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
            catch (Exception irre)
            {
                WinAuthForm.ErrorDialog(this.Owner, "Unable to create the authenticator. The secret code is probably invalid.", irre);
                return(false);
            }

            return(true);
        }
Example #5
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);
			}
		}
Example #6
0
        /// <summary>
        /// Verify and create the authenticator if needed
        /// </summary>
        /// <returns>true is successful</returns>
        private bool verifyAuthenticator()
        {
            this.Authenticator.Name = nameField.Text;

            if (this.tabControl1.SelectedIndex == 0)
            {
                if (this.Authenticator.AuthenticatorData == null)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "您需要创建身份验证器并将其附加到您的帐户");
                    return(false);
                }
            }
            else if (this.tabControl1.SelectedIndex == 1)
            {
                string serial  = this.restoreSerialNumberField.Text.Trim();
                string restore = this.restoreRestoreCodeField.Text.Trim();
                if (serial.Length == 0 || restore.Length == 0)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "请输入序列号和恢复代码");
                    return(false);
                }

                try
                {
                    BattleNetAuthenticator authenticator = new BattleNetAuthenticator();
                    authenticator.Restore(serial, restore);
                    this.Authenticator.AuthenticatorData = authenticator;
                }
                catch (InvalidRestoreResponseException irre)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "无法恢复验证器: " + irre.Message, irre);
                    return(false);
                }
            }
            else if (this.tabControl1.SelectedIndex == 2)
            {
                string privatekey = this.importPrivateKeyField.Text.Trim();
                if (privatekey.Length == 0)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "请输入私钥");
                    return(false);
                }
                // just get the hex chars
                privatekey = Regex.Replace(privatekey, @"0x", "", RegexOptions.IgnoreCase);
                privatekey = Regex.Replace(privatekey, @"[^0-9abcdef]", "", RegexOptions.IgnoreCase);
                if (privatekey.Length == 0 || privatekey.Length < 40)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "私钥必须是至少40个十六进制字符的序列, e.g. 7B0BFA82... or 0x7B, 0x0B, 0xFA, 0x82, ...");
                    return(false);
                }
                try
                {
                    BattleNetAuthenticator authenticator = new BattleNetAuthenticator();
                    if (privatekey.Length == 40)                     // 20 bytes which is key only
                    {
                        authenticator.SecretKey = WinAuth.Authenticator.StringToByteArray(privatekey);
                        authenticator.Serial    = "US-Imported";
                    }
                    else
                    {
                        authenticator.SecretData = privatekey;
                        if (string.IsNullOrEmpty(authenticator.Serial) == true)
                        {
                            authenticator.Serial = "US-Imported";
                        }
                    }
                    authenticator.Sync();
                    this.Authenticator.AuthenticatorData = authenticator;
                }
                catch (Exception irre)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "无法导入身份验证器。私钥可能无效。", irre);
                    return(false);
                }
            }

            return(true);
        }
Example #7
0
		public static Authenticator ReadXmlv2(XmlReader reader, string password = null)
    {
      Authenticator authenticator = null;
      string authenticatorType = reader.GetAttribute("type");
      if (string.IsNullOrEmpty(authenticatorType) == false)
      {
        authenticatorType = authenticatorType.Replace("WindowsAuthenticator.", "WinAuth.");
        Type type = System.Reflection.Assembly.GetExecutingAssembly().GetType(authenticatorType, false, true);
        authenticator = Activator.CreateInstance(type) as Authenticator;
      }
      if (authenticator == null)
      {
        authenticator = new BattleNetAuthenticator();
      }

      reader.MoveToContent();
      if (reader.IsEmptyElement)
      {
        reader.Read();
        return null;
      }

      reader.Read();
      while (reader.EOF == false)
      {
        if (reader.IsStartElement())
        {
          switch (reader.Name)
          {
            case "servertimediff":
              authenticator.ServerTimeDiff = reader.ReadElementContentAsLong();
              break;

						//case "restorecodeverified":
						//	authenticator.RestoreCodeVerified = reader.ReadElementContentAsBoolean();
						//	break;

            case "secretdata":
              string encrypted = reader.GetAttribute("encrypted");
              string data = reader.ReadElementContentAsString();

							PasswordTypes passwordType = DecodePasswordTypes(encrypted);

              if (passwordType != PasswordTypes.None)
              {
								// this is an old version so there is no hash
								data = DecryptSequence(data, passwordType, password, null);
              }

              authenticator.PasswordType = PasswordTypes.None;
              authenticator.SecretData = data;

              break;

            default:
							if (authenticator.ReadExtraXml(reader, reader.Name) == false)
							{
								reader.Skip();
							}
              break;
          }
        }
        else
        {
          reader.Read();
          break;
        }
      }

      return authenticator;
    }
Example #8
0
        private bool HandleBattleNetToken()
        {
            var serial = _wowManager.Settings.AuthenticatorSerial;
            var restoreCode = _wowManager.Settings.AuthenticatorRestoreCode;

            if (string.IsNullOrEmpty(serial) || string.IsNullOrEmpty(restoreCode))
                return false;

            if (string.IsNullOrEmpty(_wowManager.Settings.AuthenticatorSerial))
                return false;

            var frame = UIObject.GetUIObjectByName<Frame>(_wowManager, "TokenEnterDialogBackgroundEdit");
            if (frame == null || !frame.IsVisible || !frame.IsShown) return false;

            var editBox = UIObject.GetUIObjectByName<EditBox>(_wowManager, "AccountLoginTokenEdit");

            var auth = new BattleNetAuthenticator();

            try
            {
                auth.Restore(serial, restoreCode);
            }
            catch (Exception ex)
            {
                _wowManager.Profile.Err("Could not get auth token: {0}", ex.Message);
                return false;
            }

            if (!string.IsNullOrEmpty(editBox.Text))
            {
                Utility.SendBackgroundKey(_wowManager.GameProcess.MainWindowHandle, (char)Keys.End, false);
                Utility.SendBackgroundString(_wowManager.GameProcess.MainWindowHandle, new string('\b', "AccountLoginTokenEdit".Length * 2), false);
                _wowManager.Profile.Log("Pressing 'end' + delete keys to remove contents from {0}", "AccountLoginTokenEdit");
            }

            Utility.SendBackgroundString(_wowManager.GameProcess.MainWindowHandle, auth.CurrentCode);
            Utility.SendBackgroundKey(_wowManager.GameProcess.MainWindowHandle, (char)Keys.Enter, false);
            _wowManager.Profile.Log("Accepting Battle net token.");
            return true;
        }
Example #9
0
        public static Authenticator ReadXmlv2(XmlReader reader, string password = null)
        {
            Authenticator authenticator     = null;
            string        authenticatorType = reader.GetAttribute("type");

            if (string.IsNullOrEmpty(authenticatorType) == false)
            {
                authenticatorType = authenticatorType.Replace("WindowsAuthenticator.", "WinAuth.");
                Type type = Assembly.GetExecutingAssembly().GetType(authenticatorType, false, true);
                authenticator = Activator.CreateInstance(type) as Authenticator;
            }
            if (authenticator == null)
            {
                authenticator = new BattleNetAuthenticator();
            }

            reader.MoveToContent();
            if (reader.IsEmptyElement)
            {
                reader.Read();
                return(null);
            }

            reader.Read();
            while (reader.EOF == false)
            {
                if (reader.IsStartElement())
                {
                    switch (reader.Name)
                    {
                    case "servertimediff":
                        authenticator.ServerTimeDiff = reader.ReadElementContentAsLong();
                        break;

                    //case "restorecodeverified":
                    //	authenticator.RestoreCodeVerified = reader.ReadElementContentAsBoolean();
                    //	break;

                    case "secretdata":
                        string encrypted = reader.GetAttribute("encrypted");
                        string data      = reader.ReadElementContentAsString();

                        PasswordTypes passwordType = DecodePasswordTypes(encrypted);

                        if (passwordType != PasswordTypes.None)
                        {
                            // this is an old version so there is no hash
                            data = DecryptSequence(data, passwordType, password);
                        }

                        authenticator.PasswordType = PasswordTypes.None;
                        authenticator.SecretData   = data;

                        break;

                    default:
                        if (authenticator.ReadExtraXml(reader, reader.Name) == false)
                        {
                            reader.Skip();
                        }
                        break;
                    }
                }
                else
                {
                    reader.Read();
                    break;
                }
            }

            return(authenticator);
        }
Example #10
0
		/// <summary>
		/// Perform a verification of the restore code in the background by checking it with the servers
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void VerifyRestoreCode(object sender, DoWorkEventArgs e)
		{
			BattleNetAuthenticator auth = e.Argument as BattleNetAuthenticator;

			// check if this authenticator is too old to be restored
			try
			{
				BattleNetAuthenticator testrestore = new BattleNetAuthenticator();
				testrestore.Restore(auth.Serial, auth.RestoreCode);
				auth.RestoreCodeVerified = true;
				e.Result = null;
			}
			catch (InvalidRestoreCodeException)
			{
				e.Result = "This authenticator was created before the restore capability existed and so the restore code will not work.\n\n"
						+ "You will need to remove this authenticator from your Battle.net account and create a new one.";
			}
			catch (InvalidRestoreResponseException)
			{
				// ignore the validation if servers are down
			}
			catch (Exception ex2)
			{
				e.Result = "Oops. An error (" + ex2.Message + ") occured whilst validating your restore code."
						+ "Please log a ticket at https://github.com/winauth/winauth/issues so we can fix this.";
			}
		}
Example #11
0
		/// <summary>
		/// Verify and create the authenticator if needed
		/// </summary>
		/// <returns>true is successful</returns>
		private bool verifyAuthenticator(string privatekey)
		{
			if (string.IsNullOrEmpty(privatekey) == true)
			{
				return false;
			}

			this.Authenticator.Name = nameField.Text;

			int digits = (this.Authenticator.AuthenticatorData != null ? this.Authenticator.AuthenticatorData.CodeDigits : GoogleAuthenticator.DEFAULT_CODE_DIGITS);

			string authtype = timeBasedRadio.Checked == true ? TOTP : HOTP;

			long counter = 0;

			// if this is a URL, pull it down
			Uri uri;
			Match match;
			if (Regex.IsMatch(privatekey, "https?://.*") == true && Uri.TryCreate(privatekey, UriKind.Absolute, out uri) == true)
			{
				try
				{
					var request = (HttpWebRequest)WebRequest.Create(uri);
					request.AllowAutoRedirect = true;
					request.Timeout = 20000;
					request.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)";
					using (var response = (HttpWebResponse)request.GetResponse())
					{
						if (response.StatusCode == HttpStatusCode.OK && response.ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase) == true)
						{
							using (Bitmap bitmap = (Bitmap)Bitmap.FromStream(response.GetResponseStream()))
							{
								IBarcodeReader reader = new BarcodeReader();
								var result = reader.Decode(bitmap);
								if (result != null)
								{
									privatekey = HttpUtility.UrlDecode(result.Text);
								}
							}
						}
					}
				}
				catch (Exception ex)
				{
					WinAuthForm.ErrorDialog(this.Owner, "Cannot load QR code image from " + privatekey, ex);
					return false;
				}
			}
			else if ((match = Regex.Match(privatekey, @"data:image/([^;]+);base64,(.*)", RegexOptions.IgnoreCase)).Success == true)
			{
				byte[] imagedata = Convert.FromBase64String(match.Groups[2].Value);
				using (MemoryStream ms = new MemoryStream(imagedata))
				{
					using (Bitmap bitmap = (Bitmap)Bitmap.FromStream(ms))
					{
						IBarcodeReader reader = new BarcodeReader();
						var result = reader.Decode(bitmap);
						if (result != null)
						{
							privatekey = HttpUtility.UrlDecode(result.Text);
						}
					}
				}
			}
			else if (IsValidFile(privatekey) == true)
			{
				// assume this is the image file
				using (Bitmap bitmap = (Bitmap)Bitmap.FromFile(privatekey))
				{
					IBarcodeReader reader = new BarcodeReader();
					var result = reader.Decode(bitmap);
					if (result != null)
					{
						privatekey = result.Text;
					}
				}
			}

			string issuer = null;
			string serial = null;

			// check for otpauth://, e.g. "otpauth://totp/[email protected]?secret=IHZJDKAEEC774BMUK3GX6SA"
			match = Regex.Match(privatekey, @"otpauth://([^/]+)/([^?]+)\?(.*)", RegexOptions.IgnoreCase);
			if (match.Success == true)
			{
				authtype = match.Groups[1].Value.ToLower();
				string label = match.Groups[2].Value;
				int p = label.IndexOf(":");
				if (p != -1)
				{
					issuer = label.Substring(0, p);
					label = label.Substring(p + 1);
				}

				NameValueCollection qs = WinAuthHelper.ParseQueryString(match.Groups[3].Value);
				privatekey = qs["secret"] ?? privatekey;
				int querydigits;
				if (int.TryParse(qs["digits"], out querydigits) && querydigits != 0)
				{
					digits = querydigits;
				}
				if (qs["counter"] != null)
				{
					long.TryParse(qs["counter"], out counter);
				}
				issuer = qs["issuer"];
				if (string.IsNullOrEmpty(issuer) == false)
				{
					label = issuer + (string.IsNullOrEmpty(label) == false ? " (" + label + ")" : string.Empty);
				}
				serial = qs["serial"];

				if (string.IsNullOrEmpty(label) == false)
				{
					this.Authenticator.Name = this.nameField.Text = label;
				}
			}

			// just get the hex chars
			privatekey = Regex.Replace(privatekey, @"[^0-9a-z]", "", RegexOptions.IgnoreCase);
			if (privatekey.Length == 0)
			{
				WinAuthForm.ErrorDialog(this.Owner, "The secret code is not valid");
				return false;
			}

			try
			{
				Authenticator auth;
				if (authtype == TOTP)
				{
					if (string.Compare(issuer, "BattleNet", true) == 0)
					{
						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();
						((BattleNetAuthenticator)auth).SecretKey = Base32.getInstance().Decode(privatekey);
						((BattleNetAuthenticator)auth).Serial = serial;

						issuer = string.Empty;
					}
					else if (issuer == "Steam")
					{
						auth = new SteamAuthenticator();
						((SteamAuthenticator)auth).SecretKey = Base32.getInstance().Decode(privatekey);
						((SteamAuthenticator)auth).Serial = string.Empty;
						((SteamAuthenticator)auth).DeviceId = string.Empty;
						//((SteamAuthenticator)auth).RevocationCode = string.Empty;
						((SteamAuthenticator)auth).SteamData = string.Empty;

						this.Authenticator.Skin = null;

						issuer = string.Empty;
					}
					else
					{
						auth = new GoogleAuthenticator();
						((GoogleAuthenticator)auth).Enroll(privatekey);
					}
					timer.Enabled = true;
					codeProgress.Visible = true;
					timeBasedRadio.Checked = true;
				}
				else if (authtype == HOTP)
				{
					auth = new HOTPAuthenticator();
					if (counterField.Text.Trim().Length != 0)
					{
						long.TryParse(counterField.Text.Trim(), out counter);
					}
					((HOTPAuthenticator)auth).Enroll(privatekey, counter); // start with the next code
					timer.Enabled = false;
					codeProgress.Visible = false;
					counterBasedRadio.Checked = true;
				}
				else
				{
					WinAuthForm.ErrorDialog(this.Owner, "Only TOTP or HOTP authenticators are supported");
					return false;
				}

				auth.CodeDigits = digits;
				this.Authenticator.AuthenticatorData = auth;

				if (digits > 5)
				{
					codeField.SpaceOut = digits / 2;
				}
				else
				{
					codeField.SpaceOut = 0;
				}

				//string key = Base32.getInstance().Encode(this.Authenticator.AuthenticatorData.SecretKey);
				this.codeField.Text = auth.CurrentCode;

				if (!(auth is HOTPAuthenticator) && auth.ServerTimeDiff == 0L && SyncErrorWarned == false)
				{
					SyncErrorWarned = true;
					MessageBox.Show(this, string.Format(strings.AuthenticatorSyncError, "Google"), WinAuthMain.APPLICATION_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Warning);
				}
			}
			catch (Exception irre)
			{
				WinAuthForm.ErrorDialog(this.Owner, "Unable to create the authenticator. The secret code is probably invalid.", irre);
				return false;
			}

			return true;
		}
		/// <summary>
		/// Click to create a enroll a new authenticator
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void enrollAuthenticatorButton_Click(object sender, EventArgs e)
		{
			do
			{
				try
				{
					newSerialNumberField.Text = "creating...";

					BattleNetAuthenticator authenticator = new BattleNetAuthenticator();
#if DEBUG
					authenticator.Enroll(System.Diagnostics.Debugger.IsAttached);
#else
					authenticator.Enroll();
#endif
					this.Authenticator.AuthenticatorData = authenticator;
					newSerialNumberField.Text = authenticator.Serial;
					newLoginCodeField.Text = authenticator.CurrentCode;
					newRestoreCodeField.Text = authenticator.RestoreCode;

					newAuthenticatorProgress.Visible = true;
					newAuthenticatorTimer.Enabled = true;

					return;
				}
				catch (InvalidEnrollResponseException iere)
				{
					if (WinAuthForm.ErrorDialog(this.Owner, "An error occured while registering a new authenticator", iere, MessageBoxButtons.RetryCancel) != System.Windows.Forms.DialogResult.Retry)
					{
						break;
					}
				}
			} while (true);

			clearAuthenticator(false);
		}
		/// <summary>
		/// Verify and create the authenticator if needed
		/// </summary>
		/// <returns>true is successful</returns>
		private bool verifyAuthenticator()
		{
			this.Authenticator.Name = nameField.Text;

			if (this.tabControl1.SelectedIndex == 0)
			{
				if (this.Authenticator.AuthenticatorData == null)
				{
					WinAuthForm.ErrorDialog(this.Owner, "You need to create an authenticator and attach it to your account");
					return false;
				}
			}
			else if (this.tabControl1.SelectedIndex == 1)
			{
				string serial = this.restoreSerialNumberField.Text.Trim();
				string restore = this.restoreRestoreCodeField.Text.Trim();
				if (serial.Length == 0 || restore.Length == 0)
				{
					WinAuthForm.ErrorDialog(this.Owner, "Please enter the Serial number and Restore code");
					return false;
				}

				try
				{
					BattleNetAuthenticator authenticator = new BattleNetAuthenticator();
					authenticator.Restore(serial, restore);
					this.Authenticator.AuthenticatorData = authenticator;
				}
				catch (InvalidRestoreResponseException irre)
				{
					WinAuthForm.ErrorDialog(this.Owner, "Unable to restore the authenticator: " + irre.Message, irre);
					return false;
				}
			}
			else if (this.tabControl1.SelectedIndex == 2)
			{
				string privatekey = this.importPrivateKeyField.Text.Trim();
				if (privatekey.Length == 0)
				{
					WinAuthForm.ErrorDialog(this.Owner, "Please enter the Private key");
					return false;
				}
				// just get the hex chars
				privatekey = Regex.Replace(privatekey, @"0x", "", RegexOptions.IgnoreCase);
				privatekey = Regex.Replace(privatekey, @"[^0-9abcdef]", "", RegexOptions.IgnoreCase);
				if (privatekey.Length == 0 || privatekey.Length < 40)
				{
					WinAuthForm.ErrorDialog(this.Owner, "The private key must be a sequence of at least 40 hexadecimal characters, e.g. 7B0BFA82... or 0x7B, 0x0B, 0xFA, 0x82, ...");
					return false;
				}
				try
				{
					BattleNetAuthenticator authenticator = new BattleNetAuthenticator();
					if (privatekey.Length == 40) // 20 bytes which is key only
					{
						authenticator.SecretKey = WinAuth.Authenticator.StringToByteArray(privatekey);
						authenticator.Serial = "US-Imported";
					}
					else
					{
						authenticator.SecretData = privatekey;
						if (string.IsNullOrEmpty(authenticator.Serial) == true)
						{
							authenticator.Serial = "US-Imported";
						}
					}
					authenticator.Sync();
					this.Authenticator.AuthenticatorData = authenticator;
				}
				catch (Exception irre)
				{
					WinAuthForm.ErrorDialog(this.Owner, "Unable to import the authenticator. The private key is probably invalid.", irre);
					return false;
				}
			}

			return true;
		}
        /// <summary>
        /// Verify and create the authenticator if needed
        /// </summary>
        /// <returns>true is successful</returns>
        private bool verifyAuthenticator()
        {
            this.Authenticator.Name = nameField.Text;

            if (this.tabControl1.SelectedIndex == 0)
            {
                if (this.Authenticator.AuthenticatorData == null)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "You need to create an authenticator and attach it to your account");
                    return(false);
                }
            }
            else if (this.tabControl1.SelectedIndex == 1)
            {
                string serial  = this.restoreSerialNumberField.Text.Trim();
                string restore = this.restoreRestoreCodeField.Text.Trim();
                if (serial.Length == 0 || restore.Length == 0)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "Please enter the Serial number and Restore code");
                    return(false);
                }

                try
                {
                    BattleNetAuthenticator authenticator = new BattleNetAuthenticator();
                    authenticator.Restore(serial, restore);
                    this.Authenticator.AuthenticatorData = authenticator;
                }
                catch (InvalidRestoreResponseException irre)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "Unable to restore the authenticator: " + irre.Message, irre);
                    return(false);
                }
            }
            else if (this.tabControl1.SelectedIndex == 2)
            {
                string privatekey = this.importPrivateKeyField.Text.Trim();
                if (privatekey.Length == 0)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "Please enter the Private key");
                    return(false);
                }
                // just get the hex chars
                privatekey = Regex.Replace(privatekey, @"0x", "", RegexOptions.IgnoreCase);
                privatekey = Regex.Replace(privatekey, @"[^0-9abcdef]", "", RegexOptions.IgnoreCase);
                if (privatekey.Length == 0 || privatekey.Length < 40)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "The private key must be a sequence of at least 40 hexadecimal characters, e.g. 7B0BFA82... or 0x7B, 0x0B, 0xFA, 0x82, ...");
                    return(false);
                }
                try
                {
                    BattleNetAuthenticator authenticator = new BattleNetAuthenticator();
                    if (privatekey.Length == 40)                     // 20 bytes which is key only
                    {
                        authenticator.SecretKey = WinAuth.Authenticator.StringToByteArray(privatekey);
                        authenticator.Serial    = "US-Imported";
                    }
                    else
                    {
                        authenticator.SecretData = privatekey;
                        if (string.IsNullOrEmpty(authenticator.Serial) == true)
                        {
                            authenticator.Serial = "US-Imported";
                        }
                    }
                    authenticator.Sync();
                    this.Authenticator.AuthenticatorData = authenticator;
                }
                catch (Exception irre)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "Unable to import the authenticator. The private key is probably invalid.", irre);
                    return(false);
                }
            }

            return(true);
        }