Пример #1
0
        // TODO: Write tests for this. Possibly the whole current concept of how it's tested
        //       should be rethought. Maybe should simply tests against a fake server.
        public static Session Login(string username, string password, ClientInfo clientInfo, Ui ui, IWebClient webClient)
        {
            // 1. First we need to request PBKDF2 key iteration count.
            var keyIterationCount = RequestIterationCount(username, webClient);

            // 2. Knowing the iterations count we can hash the password and log in.
            //    One the first attempt simply with the username and password.
            var response = PerformSingleLoginRequest(username,
                                                     password,
                                                     keyIterationCount,
                                                     new NameValueCollection(),
                                                     clientInfo,
                                                     webClient);
            var session = ExtractSessionFromLoginResponse(response, keyIterationCount, clientInfo);

            if (session != null)
            {
                return(session);
            }

            // 3. The simple login failed. This is usually due to some error, invalid credentials or
            //    a multifactor authentication being enabled.
            var cause = GetOptionalErrorAttribute(response, "cause");

            // 3.1. One-time-password is required
            if (KnownOtpMethods.ContainsKey(cause))
            {
                return(LoginWithOtp(username,
                                    password,
                                    keyIterationCount,
                                    KnownOtpMethods[cause],
                                    clientInfo,
                                    ui,
                                    webClient));
            }

            // 3.2. Some out-of-bound authentication is enabled. This does not require any
            //      additional input from the user.
            if (cause == "outofbandrequired")
            {
                return(LoginWithOob(username,
                                    password,
                                    keyIterationCount,
                                    ExtractOobMethodFromLoginResponse(response),
                                    clientInfo,
                                    ui,
                                    webClient));
            }

            throw CreateLoginException(response);
        }
Пример #2
0
        //
        // Internal
        //

        internal static Session Login(string username, string password, ClientInfo clientInfo, IUi ui, RestClient rest)
        {
            // 1. First we need to request PBKDF2 key iteration count.
            //
            // We no longer request the iteration count from the server in a separate request because it
            // started to fail in weird ways. It seems there's a special combination or the UA and cookies
            // that returns the correct result. And that is not 100% reliable. After two or three attempts
            // it starts to fail again with an incorrect result.
            //
            // So we just went back a few years to the original way LastPass used to handle the iterations.
            // Namely, submit the default value and if it fails, the error would contain the correct value:
            // <response><error iterations="5000" /></response>
            var keyIterationCount = 100100;

            XDocument response = null;
            Session   session  = null;

            for (var i = 0; i < 2; i++)
            {
                // 2. Knowing the iterations count we can hash the password and log in.
                //    One the first attempt simply with the username and password.
                response = PerformSingleLoginRequest(username,
                                                     password,
                                                     keyIterationCount,
                                                     new Dictionary <string, object>(),
                                                     clientInfo,
                                                     rest);
                session = ExtractSessionFromLoginResponse(response, keyIterationCount, clientInfo);
                if (session != null)
                {
                    return(session);
                }

                // It's possible for the request above to come back with the correct iteration count.
                // In this case we have to parse and repeat.
                var correctIterationCount = GetOptionalErrorAttribute(response, "iterations");
                if (correctIterationCount == null)
                {
                    break;
                }

                if (!int.TryParse(correctIterationCount, out keyIterationCount))
                {
                    throw new InternalErrorException($"Failed to parse the iteration count, expected an integer value '{correctIterationCount}'");
                }
            }

            // 3. The simple login failed. This is usually due to some error, invalid credentials or
            //    a multifactor authentication being enabled.
            var cause = GetOptionalErrorAttribute(response, "cause");

            if (cause == null)
            {
                throw MakeLoginError(response);
            }

            // 3.1. One-time-password is required
            if (KnownOtpMethods.TryGetValue(cause, out var otpMethod))
            {
                session = LoginWithOtp(username,
                                       password,
                                       keyIterationCount,
                                       otpMethod,
                                       clientInfo,
                                       ui,
                                       rest);
            }

            // 3.2. Some out-of-bound authentication is enabled. This does not require any
            //      additional input from the user.
            else if (cause == "outofbandrequired")
            {
                session = LoginWithOob(username,
                                       password,
                                       keyIterationCount,
                                       GetAllErrorAttributes(response),
                                       clientInfo,
                                       ui,
                                       rest);
            }

            // Nothing worked
            if (session == null)
            {
                throw MakeLoginError(response);
            }

            return(session);
        }
Пример #3
0
        //
        // Internal
        //

        internal static Session Login(string username, string password, ClientInfo clientInfo, IUi ui, RestClient rest)
        {
            // 1. First we need to request PBKDF2 key iteration count.
            var keyIterationCount = RequestIterationCount(username, rest);

            // 2. Knowing the iterations count we can hash the password and log in.
            //    One the first attempt simply with the username and password.
            var response = PerformSingleLoginRequest(username,
                                                     password,
                                                     keyIterationCount,
                                                     new Dictionary <string, object>(),
                                                     clientInfo,
                                                     rest);
            var session = ExtractSessionFromLoginResponse(response, keyIterationCount, clientInfo);

            if (session != null)
            {
                return(session);
            }

            // 3. The simple login failed. This is usually due to some error, invalid credentials or
            //    a multifactor authentication being enabled.
            var cause = GetOptionalErrorAttribute(response, "cause");

            if (cause == null)
            {
                throw MakeLoginError(response);
            }

            // 3.1. One-time-password is required
            if (KnownOtpMethods.TryGetValue(cause, out var otpMethod))
            {
                session = LoginWithOtp(username,
                                       password,
                                       keyIterationCount,
                                       otpMethod,
                                       clientInfo,
                                       ui,
                                       rest);
            }

            // 3.2. Some out-of-bound authentication is enabled. This does not require any
            //      additional input from the user.
            else if (cause == "outofbandrequired")
            {
                session = LoginWithOob(username,
                                       password,
                                       keyIterationCount,
                                       GetAllErrorAttributes(response),
                                       clientInfo,
                                       ui,
                                       rest);
            }

            // Nothing worked
            if (session == null)
            {
                throw MakeLoginError(response);
            }

            return(session);
        }