lib/lastpass/fetcher.rb in lastpass-1.0.1 vs lib/lastpass/fetcher.rb in lastpass-1.1.0
- old
+ new
@@ -1,17 +1,17 @@
# Copyright (C) 2013 Dmitry Yakimenko (detunized@gmail.com).
# Licensed under the terms of the MIT license. See LICENCE for details.
module LastPass
class Fetcher
- def self.login username, password
+ def self.login username, password, multifactor_password = nil
key_iteration_count = request_iteration_count username
- request_login username, password, key_iteration_count
+ request_login username, password, key_iteration_count, multifactor_password
end
def self.fetch session, web_client = HTTParty
- response = web_client.get "https://lastpass.com/getaccts.php?mobile=1&b64=1&hash=0.0",
+ response = web_client.get "https://lastpass.com/getaccts.php?mobile=1&b64=1&hash=0.0&hasplugin=3.0.23&requestsrc=android",
format: :plain,
cookies: {"PHPSESSID" => URI.encode(session.id)}
raise NetworkError unless response.response.is_a? Net::HTTPOK
@@ -25,34 +25,43 @@
raise NetworkError unless response.response.is_a? Net::HTTPOK
begin
count = Integer response.parsed_response
rescue ArgumentError
- raise InvalidResponse, "Key iteration count is invalid"
+ raise InvalidResponseError, "Key iteration count is invalid"
end
- raise InvalidResponse, "Key iteration count is not positive" unless count > 0
+ raise InvalidResponseError, "Key iteration count is not positive" unless count > 0
count
end
- def self.request_login username, password, key_iteration_count, web_client = HTTParty
+ def self.request_login username,
+ password,
+ key_iteration_count,
+ multifactor_password = nil,
+ web_client = HTTParty
+
+ body = {
+ method: "mobile",
+ web: 1,
+ xml: 1,
+ username: username,
+ hash: make_hash(username, password, key_iteration_count),
+ iterations: key_iteration_count
+ }
+
+ body[:otp] = multifactor_password if multifactor_password
+
response = web_client.post "https://lastpass.com/login.php",
format: :xml,
- body: {
- method: "mobile",
- web: 1,
- xml: 1,
- username: username,
- hash: make_hash(username, password, key_iteration_count),
- iterations: key_iteration_count
- }
+ body: body
raise NetworkError unless response.response.is_a? Net::HTTPOK
parsed_response = response.parsed_response
- raise InvalidResponse unless parsed_response.is_a? Hash
+ raise InvalidResponseError unless parsed_response.is_a? Hash
create_session parsed_response, key_iteration_count or
raise login_error parsed_response
end
@@ -68,23 +77,26 @@
nil
end
def self.login_error parsed_response
error = (parsed_response["response"] || {})["error"]
- return UnknownResponseSchema unless error.is_a? Hash
+ return UnknownResponseSchemaError unless error.is_a? Hash
exceptions = {
- "unknownemail" => LastPassUnknownUsername,
- "unknownpassword" => LastPassInvalidPassword,
+ "unknownemail" => LastPassUnknownUsernameError,
+ "unknownpassword" => LastPassInvalidPasswordError,
+ "googleauthrequired" => LastPassIncorrectGoogleAuthenticatorCodeError,
+ "googleauthfailed" => LastPassIncorrectGoogleAuthenticatorCodeError,
+ "yubikeyrestricted" => LastPassIncorrectYubikeyPasswordError,
}
cause = error["cause"]
message = error["message"]
if cause
(exceptions[cause] || LastPassUnknownError).new message || cause
else
- InvalidResponse.new message
+ InvalidResponseError.new message
end
end
def self.decode_blob blob
# TODO: Check for invalid base64