예제 #1
0
        /// <summary>
        /// Form loaded event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ShowSecretKeyForm_Load(object sender, EventArgs e)
        {
            this.secretKeyField.SecretMode = true;

            string key = Base32.getInstance().Encode(CurrentAuthenticator.AuthenticatorData.SecretKey);

            this.secretKeyField.Text = Regex.Replace(key, ".{3}", "$0 ").Trim();

            string type    = CurrentAuthenticator.AuthenticatorData is HOTPAuthenticator ? "hotp" : "totp";
            long   counter = (CurrentAuthenticator.AuthenticatorData is HOTPAuthenticator ? ((HOTPAuthenticator)CurrentAuthenticator.AuthenticatorData).Counter : 0);
            string issuer  = CurrentAuthenticator.AuthenticatorData.Issuer;
            string url     = "otpauth://" + type + "/" + WinAuthHelper.HtmlEncode(CurrentAuthenticator.Name)
                             + "?secret=" + key
                             + "&digits=" + CurrentAuthenticator.AuthenticatorData.CodeDigits
                             + (counter != 0 ? "&counter=" + counter : string.Empty)
                             + (string.IsNullOrEmpty(issuer) == false ? "&issuer=" + WinAuthHelper.HtmlEncode(issuer) : string.Empty);

            BarcodeWriter writer = new BarcodeWriter();

            writer.Format  = BarcodeFormat.QR_CODE;
            writer.Options = new ZXing.Common.EncodingOptions {
                Width = qrImage.Width, Height = qrImage.Height
            };
            qrImage.Image = writer.Write(url);
        }
예제 #2
0
 /// <summary>
 /// Write a setting value into the Config
 /// </summary>
 /// <param name="name">name of setting value</param>
 /// <param name="value">setting value. If null, the setting is deleted.</param>
 public void WriteSetting(string name, string value)
 {
     if (this.IsPortable == true)
     {
         if (value == null)
         {
             if (_settings.ContainsKey(name) == true)
             {
                 _settings.Remove(name);
             }
         }
         else
         {
             _settings[name] = value;
         }
     }
     else
     {
         if (value == null)
         {
             WinAuthHelper.DeleteRegistryKey(name);
         }
         else
         {
             WinAuthHelper.WriteRegistryValue(name, value);
         }
     }
 }
예제 #3
0
 /// <summary>
 ///     Load the error report form
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void ErrorReportForm_Load(object sender, EventArgs e)
 {
     // build data
     try
     {
         dataText.Text = WinAuthHelper.PGPEncrypt(BuildDiagnostics(), WinAuthHelper.WINAUTH_PGP_PUBLICKEY);
     }
     catch (Exception ex)
     {
         dataText.Text = string.Format("{0}\n\n{1}", ex.Message, new StackTrace(ex));
     }
 }
예제 #4
0
 /// <summary>
 /// Load the error report form
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void ErrorReportForm_Load(object sender, EventArgs e)
 {
     // build data
     try
     {
         dataText.Text = WinAuthHelper.PGPEncrypt(BuildDiagnostics(), WinAuthHelper.WINAUTH_PGP_PUBLICKEY);
     }
     catch (EmptyReportException)
     {
         dataText.Text = "No data available for error report.";
     }
     catch (Exception ex)
     {
         dataText.Text = string.Format("{0}\n\n{1}", ex.Message, new System.Diagnostics.StackTrace(ex).ToString());
     }
 }
예제 #5
0
 /// <summary>
 /// Get all the settings keys beneath the specified key
 /// </summary>
 /// <param name="name">name of parent key</param>
 /// <returns>string array of all child (recursively) setting names. Empty is none.</returns>
 public string[] ReadSettingKeys(string name)
 {
     if (this.IsPortable == true)
     {
         List <string> keys = new List <string>();
         foreach (var entry in _settings)
         {
             if (entry.Key.StartsWith(name) == true)
             {
                 keys.Add(entry.Key);
             }
         }
         return(keys.ToArray());
     }
     else
     {
         return(WinAuthHelper.ReadRegistryKeys(name));
     }
 }
예제 #6
0
 /// <summary>
 /// Read a setting value.
 /// </summary>
 /// <param name="name">name of setting</param>
 /// <param name="defaultValue">default value if setting doesn't exist</param>
 /// <returns>setting value or default value</returns>
 public string ReadSetting(string name, string defaultValue = null)
 {
     if (this.IsPortable == true)
     {
         // read setting from _settings
         string value;
         if (_settings.TryGetValue(name, out value) == true)
         {
             return(value);
         }
         else
         {
             return(defaultValue);
         }
     }
     else
     {
         return(WinAuthHelper.ReadRegistryValue(name, defaultValue) as string);
     }
 }
예제 #7
0
        /// <summary>
        /// Load the error report form
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ExceptionForm_Load(object sender, EventArgs e)
        {
            errorIcon.Image = SystemIcons.Error.ToBitmap();
            this.Height     = detailsButton.Top + detailsButton.Height + 45;

            this.errorLabel.Text = string.Format(this.errorLabel.Text, (ErrorException != null ? ErrorException.Message : strings.UnknownError));

            // build data
#if DEBUG
            dataText.Text = string.Format("{0}\n\n{1}", this.ErrorException.Message, new System.Diagnostics.StackTrace(this.ErrorException).ToString());
#else
            try
            {
                dataText.Text = WinAuthHelper.PGPEncrypt(BuildDiagnostics(), WinAuthHelper.WINAUTH_PGP_PUBLICKEY);
            }
            catch (Exception ex)
            {
                dataText.Text = string.Format("{0}\n\n{1}", ex.Message, new System.Diagnostics.StackTrace(ex).ToString());
            }
#endif
        }
예제 #8
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);
        }
예제 #9
0
        /// <summary>
        /// Decode the secret field
        /// </summary>
        private void DecodeSecretCode()
        {
            Uri   uri;
            Match match;

            if (Regex.IsMatch(secretCodeField.Text, "https?://.*") == true && Uri.TryCreate(secretCodeField.Text, 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 && string.IsNullOrEmpty(result.Text) == false)
                                {
                                    secretCodeField.Text = HttpUtility.UrlDecode(result.Text);
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "Cannot load QR code image from " + secretCodeField.Text, ex);
                    return;
                }
            }

            match = Regex.Match(secretCodeField.Text, @"otpauth://([^/]+)/([^?]+)\?(.*)", RegexOptions.IgnoreCase);
            if (match.Success == true)
            {
                string authtype = match.Groups[1].Value.ToLower();
                string label    = match.Groups[2].Value;

                if (authtype == HOTP)
                {
                    counterBasedRadio.Checked = true;
                }
                else if (authtype == TOTP)
                {
                    timeBasedRadio.Checked = true;
                    counterField.Text      = string.Empty;
                }

                NameValueCollection qs = WinAuthHelper.ParseQueryString(match.Groups[3].Value);
                if (qs["counter"] != null)
                {
                    long counter;
                    if (long.TryParse(qs["counter"], out counter) == true)
                    {
                        counterField.Text = counter.ToString();
                    }
                }

                string issuer = qs["issuer"];
                if (string.IsNullOrEmpty(issuer) == false)
                {
                    label = issuer + (string.IsNullOrEmpty(label) == false ? " (" + label + ")" : string.Empty);
                }
                this.nameField.Text = label;

                int period;
                if (int.TryParse(qs["period"], out period) == true && period > 0)
                {
                    this.intervalField.Text = period.ToString();
                }

                int digits;
                if (int.TryParse(qs["digits"], out digits) == true && digits > 0)
                {
                    this.digitsField.Text = digits.ToString();
                }

                WinAuth.Authenticator.HMACTypes hmac;
#if NETFX_3
                try
                {
                    hmac = (WinAuth.Authenticator.HMACTypes)Enum.Parse(typeof(WinAuth.Authenticator.HMACTypes), qs["algorithm"], true);
                    this.hashField.SelectedItem = hmac.ToString();
                }
                catch (Exception) { }
#else
                if (Enum.TryParse <WinAuth.Authenticator.HMACTypes>(qs["algorithm"], true, out hmac) == true)
                {
                    this.hashField.SelectedItem = hmac.ToString();
                }
#endif
            }
        }
예제 #10
0
        /// <summary>
        ///     Verify and create the authenticator if needed
        /// </summary>
        /// <returns>true is successful</returns>
        private bool verifyAuthenticator(string privatekey)
        {
            if (string.IsNullOrEmpty(privatekey))
            {
                return(false);
            }

            Authenticator.Name = nameField.Text;

            var authtype = "totp";

            // if this is a URL, pull it down
            Uri   uri;
            Match match;

            if (Regex.IsMatch(privatekey, "https?://.*") && Uri.TryCreate(privatekey, UriKind.Absolute, out uri))
            {
                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))
                        {
                            using (var bitmap = (Bitmap)Image.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(Owner, "Cannot load QR code image from " + privatekey, ex);
                    return(false);
                }
            }
            else if ((match = Regex.Match(privatekey, @"data:image/([^;]+);base64,(.*)", RegexOptions.IgnoreCase))
                     .Success)
            {
                var imagedata = Convert.FromBase64String(match.Groups[2].Value);
                using (var ms = new MemoryStream(imagedata))
                {
                    using (var bitmap = (Bitmap)Image.FromStream(ms))
                    {
                        IBarcodeReader reader = new BarcodeReader();
                        var            result = reader.Decode(bitmap);
                        if (result != null)
                        {
                            privatekey = HttpUtility.UrlDecode(result.Text);
                        }
                    }
                }
            }
            else if (IsValidFile(privatekey))
            {
                // assume this is the image file
                using (var bitmap = (Bitmap)Image.FromFile(privatekey))
                {
                    IBarcodeReader reader = new BarcodeReader();
                    var            result = reader.Decode(bitmap);
                    if (result != null)
                    {
                        privatekey = result.Text;
                    }
                }
            }

            // check for otpauth://, e.g. "otpauth://totp/[email protected]?secret=IHZJDKAEEC774BMUK3GX6SA"
            match = Regex.Match(privatekey, @"otpauth://([^/]+)/([^?]+)\?(.*)", RegexOptions.IgnoreCase);
            if (match.Success)
            {
                authtype = match.Groups[1].Value; // @todo we only handle totp (not hotp)
                if (string.Compare(authtype, "totp", true) != 0)
                {
                    WinAuthForm.ErrorDialog(Owner,
                                            "Only time-based (TOTP) authenticators are supported when adding a Google Authenticator. Use the general \"Add Authenticator\" for counter-based (HOTP) authenticators.");
                    return(false);
                }

                var label = match.Groups[2].Value;
                if (string.IsNullOrEmpty(label) == false)
                {
                    Authenticator.Name = nameField.Text = label;
                }

                var qs = WinAuthHelper.ParseQueryString(match.Groups[3].Value);
                privatekey = qs["secret"] ?? privatekey;
            }

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

            try
            {
                var auth = new GoogleAuthenticator();
                auth.Enroll(privatekey);
                Authenticator.AuthenticatorData = auth;

                codeProgress.Visible = true;

                var key = Base32.getInstance().Encode(Authenticator.AuthenticatorData.SecretKey);
                secretCodeField.Text = Regex.Replace(key, ".{3}", "$0 ").Trim();
                codeField.Text       = auth.CurrentCode;

                if (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(Owner,
                                        "Unable to create the authenticator. The secret code is probably invalid.", irre);
                return(false);
            }

            return(true);
        }
예제 #11
0
        /// <summary>
        /// Click the button to convert any secret code
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void secretCodeButton_Click(object sender, EventArgs e)
        {
            Uri   uri;
            Match match;

            if (Regex.IsMatch(secretCodeField.Text, "https?://.*") == true && Uri.TryCreate(secretCodeField.Text, 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 && string.IsNullOrEmpty(result.Text) == false)
                                {
                                    secretCodeField.Text = HttpUtility.UrlDecode(result.Text);
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "无法从中加载QR码图像 " + secretCodeField.Text, ex);
                    return;
                }
            }

            match = Regex.Match(secretCodeField.Text, @"otpauth://([^/]+)/([^?]+)\?(.*)", RegexOptions.IgnoreCase);
            if (match.Success == true)
            {
                string authtype = match.Groups[1].Value.ToLower();
                string label    = match.Groups[2].Value;

                if (authtype == HOTP)
                {
                    counterBasedRadio.Checked = true;

                    NameValueCollection qs = WinAuthHelper.ParseQueryString(match.Groups[3].Value);
                    if (qs["counter"] != null)
                    {
                        long counter;
                        if (long.TryParse(qs["counter"], out counter) == true)
                        {
                            counterField.Text = counter.ToString();
                        }
                    }

                    string issuer = qs["issuer"];
                    if (string.IsNullOrEmpty(issuer) == false)
                    {
                        label = issuer + (string.IsNullOrEmpty(label) == false ? " (" + label + ")" : string.Empty);
                    }

                    this.nameField.Text = label;
                }
                else if (authtype == TOTP)
                {
                    timeBasedRadio.Checked = true;
                    counterField.Text      = string.Empty;
                }
            }
        }
예제 #12
0
        /// <summary>
        ///     Build a diagnostics string for the current Config and any exception that had been thrown
        /// </summary>
        /// <returns>diagnostics information</returns>
        private string BuildDiagnostics()
        {
            var diag = new StringBuilder();

            if (Config != null)
            {
                // clone the current config so we can extract key in case machine/user encrypted
                var clone = Config.Clone() as WinAuthConfig;
                clone.PasswordType = Authenticator.PasswordTypes.None;

                // add the config and authenticator
                try
                {
                    var xml      = new StringBuilder();
                    var settings = new XmlWriterSettings();
                    settings.Indent = true;
                    using (var writer = XmlWriter.Create(xml, settings))
                    {
                        clone.WriteXmlString(writer);
                    }

                    diag.Append("--CURRENT CONFIG--").Append(Environment.NewLine);
                    diag.Append(xml).Append(Environment.NewLine).Append(Environment.NewLine);
                }
                catch (Exception ex)
                {
                    diag.Append(ex.Message).Append(Environment.NewLine).Append(Environment.NewLine);
                }
            }

            // add each of the entries from the registry
            if (Config != null)
            {
                diag.Append("--REGISTRY--").Append(Environment.NewLine);
                diag.Append(WinAuthHelper.ReadBackupFromRegistry(Config)).Append(Environment.NewLine)
                .Append(Environment.NewLine);
            }

            // add current config file
            if (string.IsNullOrEmpty(ConfigFileContents) == false)
            {
                diag.Append("--CONFIGFILE--").Append(Environment.NewLine);
                diag.Append(ConfigFileContents).Append(Environment.NewLine).Append(Environment.NewLine);
            }

            // add winauth log
            var dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
                                   WinAuthMain.APPLICATION_NAME);
            var winauthlog = Path.Combine(dir, "winauth.log");

            if (File.Exists(winauthlog))
            {
                diag.Append("--WINAUTH.LOG--").Append(Environment.NewLine);
                diag.Append(File.ReadAllText(winauthlog)).Append(Environment.NewLine).Append(Environment.NewLine);
            }

            // add the exception
            if (ErrorException != null)
            {
                diag.Append("--EXCEPTION--").Append(Environment.NewLine);

                var ex = ErrorException;
                while (ex != null)
                {
                    diag.Append("Stack: ").Append(ex.Message).Append(Environment.NewLine).Append(new StackTrace(ex))
                    .Append(Environment.NewLine);
                    ex = ex.InnerException;
                }

                if (ErrorException is InvalidEncryptionException)
                {
                    diag.Append("Plain: " + ((InvalidEncryptionException)ErrorException).Plain)
                    .Append(Environment.NewLine);
                    diag.Append("Password: "******"Encrypted: " + ((InvalidEncryptionException)ErrorException).Encrypted)
                    .Append(Environment.NewLine);
                    diag.Append("Decrypted: " + ((InvalidEncryptionException)ErrorException).Decrypted)
                    .Append(Environment.NewLine);
                }
                else if (ErrorException is InvalidSecretDataException)
                {
                    diag.Append("EncType: " + ((InvalidSecretDataException)ErrorException).EncType)
                    .Append(Environment.NewLine);
                    diag.Append("Password: "******"Data: " + data).Append(Environment.NewLine);
                    }
                }
            }

            return(diag.ToString());
        }
        /// <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;

            string authtype = "totp";

            // 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, "无法从中加载QR码图像 " + 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;
                    }
                }
            }

            // 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;                 // @todo we only handle totp (not hotp)
                if (string.Compare(authtype, "totp", true) != 0)
                {
                    WinAuthForm.ErrorDialog(this.Owner, "添加Google Authenticator时,仅支持基于时间的(TOTP)验证器。使用普通 \"添加身份验证器\" 进行计数器(Hotp)验证器。");
                    return(false);
                }

                string label = match.Groups[2].Value;
                if (string.IsNullOrEmpty(label) == false)
                {
                    this.Authenticator.Name = this.nameField.Text = label;
                }

                NameValueCollection qs = WinAuthHelper.ParseQueryString(match.Groups[3].Value);
                privatekey = qs["secret"] ?? privatekey;
            }

            // just get the hex chars
            privatekey = Regex.Replace(privatekey, @"[^0-9a-z]", "", RegexOptions.IgnoreCase);
            if (privatekey.Length == 0)
            {
                WinAuthForm.ErrorDialog(this.Owner, "密钥无效");
                return(false);
            }

            try
            {
                MicrosoftAuthenticator authenticator = new MicrosoftAuthenticator();
                authenticator.Enroll(privatekey);
                this.Authenticator.AuthenticatorData = authenticator;
                this.Authenticator.Name = this.nameField.Text;

                codeField.Text = authenticator.CurrentCode;
                newAuthenticatorProgress.Visible = true;
                newAuthenticatorTimer.Enabled    = true;
            }
            catch (Exception ex)
            {
                WinAuthForm.ErrorDialog(this.Owner, "无法创建验证器: " + ex.Message, ex);
                return(false);
            }

            return(true);
        }
예제 #14
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;
                    }
                }
            }

            // 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;

                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);
                }
                string issuer = qs["issuer"];
                if (string.IsNullOrEmpty(issuer) == false)
                {
                    label = issuer + (string.IsNullOrEmpty(label) == false ? " (" + label + ")" : string.Empty);
                }

                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)
                {
                    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;

                codeField.SpaceOut = digits / 2;

                string key = Base32.getInstance().Encode(this.Authenticator.AuthenticatorData.SecretKey);
                //this.secretCodeField.Text = Regex.Replace(key, ".{3}", "$0 ").Trim();
                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);
        }
예제 #15
0
        /// <summary>
        /// Decode the secret field
        /// </summary>
        private void DecodeSecretCode()
        {
            Match match;

            if (Regex.IsMatch(secretCodeField.Text, "https?://.*") && Uri.TryCreate(secretCodeField.Text, UriKind.Absolute, out var uri))
            {
                try
                {
                    var request = WebRequest.CreateHttp(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))
                        {
                            using (var bitmap = (Bitmap)Image.FromStream(response.GetResponseStream()))
                            {
                                var reader = new BarcodeReader();
                                var result = reader.Decode(bitmap);
                                if (result != null && !string.IsNullOrEmpty(result.Text))
                                {
                                    secretCodeField.Text = HttpUtility.UrlDecode(result.Text);
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    WinAuthForm.ErrorDialog(Owner, "Cannot load QR code image from " + secretCodeField.Text, ex);
                    return;
                }
            }

            match = Regex.Match(secretCodeField.Text, @"otpauth://([^/]+)/([^?]+)\?(.*)", RegexOptions.IgnoreCase);
            if (match.Success)
            {
                var authtype = match.Groups[1].Value.ToLower();
                var label    = match.Groups[2].Value;

                if (authtype == HOTP)
                {
                    counterBasedRadio.Checked = true;
                }
                else if (authtype == TOTP)
                {
                    timeBasedRadio.Checked = true;
                    counterField.Text      = string.Empty;
                }

                var qs = WinAuthHelper.ParseQueryString(match.Groups[3].Value);
                if (qs["counter"] != null)
                {
                    if (long.TryParse(qs["counter"], out var counter))
                    {
                        counterField.Text = counter.ToString();
                    }
                }

                var issuer = qs["issuer"];
                if (!string.IsNullOrEmpty(issuer))
                {
                    label = issuer + (string.IsNullOrEmpty(label) ? string.Empty : " (" + label + ")");
                }
                nameField.Text = label;

                if (int.TryParse(qs["period"], out var period) && period > 0)
                {
                    intervalField.Text = period.ToString();
                }

                if (int.TryParse(qs["digits"], out var digits) && digits > 0)
                {
                    digitsField.Text = digits.ToString();
                }

                if (Enum.TryParse <Authenticator.HMACTypes>(qs["algorithm"], true, out var hmac))
                {
                    hashField.SelectedItem = hmac.ToString();
                }
            }
        }