Beispiel #1
0
def _get_identity_service(identity_url=None):
    """Function to return the identity service for the system"""
    if identity_url is None:
        identity_url = _get_identity_url()

    from Acquire.Service import is_running_service as _is_running_service
    if _is_running_service():
        from Acquire.Service import get_trusted_service \
            as _get_trusted_service
        return _get_trusted_service(service_url=identity_url,
                                    service_type='identity')

    from Acquire.Client import LoginError

    try:
        from Acquire.Client import Wallet as _Wallet
        wallet = _Wallet()
        service = wallet.get_service(service_url=identity_url,
                                     service_type="identity")
    except Exception as e:
        from Acquire.Service import exception_to_string
        raise LoginError("Have not received the identity service info from "
                         "the identity service at '%s'\n\nCAUSE: %s" %
                         (identity_url, exception_to_string(e)))

    if not service.can_identify_users():
        raise LoginError(
            "You can only use a valid identity service to log in! "
            "The service at '%s' is a '%s'" %
            (identity_url, service.service_type()))

    return service
Beispiel #2
0
    def identity_service(self):
        """Return the identity service info object for the identity
           service used to validate the identity of this user
        """
        if self._identity_service:
            return self._identity_service

        identity_service = _get_identity_service(
                                identity_url=self.identity_service_url())

        # if the user supplied the UID then validate this is correct
        # pylint: disable=assignment-from-none
        if self._identity_uid:
            if identity_service.uid() != self._identity_uid:
                from Acquire.Client import LoginError
                raise LoginError(
                    "The UID of the identity service at '%s', which is "
                    "%s, does not match that supplied by the user, '%s'. "
                    "You should double-check that the UID is correct, or "
                    "that you have supplied the correct identity_url" %
                    (self.identity_service_url(), identity_service.uid(),
                     self._identity_uid))
        else:
            self._identity_uid = identity_service.uid()
        # pylint: enable=assignment-from-none

        self._identity_service = identity_service

        return self._identity_service
Beispiel #3
0
 def _check_for_error(self):
     """Call to ensure that this object is not in an error
        state. If it is in an error state then raise an
        exception"""
     if self._status == _LoginStatus.ERROR:
         from Acquire.Client import LoginError
         raise LoginError(self._error_string)
Beispiel #4
0
def _get_accounting_service(accounting_url=None):
    """Function to return the accounting service for the system

       Args:
            accounting_url (str, default=None): Accounting URL
       Returns:
            Service: Accounting service for system
    """
    if accounting_url is None:
        accounting_url = _get_accounting_url()

    from Acquire.Client import Service as _Service
    service = _Service(accounting_url, service_type="accounting")

    if not service.is_accounting_service():
        from Acquire.Client import LoginError
        raise LoginError(
            "You can only use a valid accounting service to get account info! "
            "The service at '%s' is a '%s'" %
            (accounting_url, service.service_type()))

    return service
Beispiel #5
0
def _get_storage_service(storage_url=None):
    """Function to return the storage service for the system

       Args:
            storage_url (str, default=None): Storage URL to use
       Returns:
            Service: Service object
    """
    if storage_url is None:
        storage_url = _get_storage_url()

    from Acquire.Client import Service as _Service
    service = _Service(storage_url, service_type="storage")

    if not service.is_storage_service():
        from Acquire.Client import LoginError
        raise LoginError(
            "You can only use a valid storage service to get CloudDrive info! "
            "The service at '%s' is a '%s'" %
            (storage_url, service.service_type()))

    assert (service is not None)

    return service
Beispiel #6
0
    def request_login(self, login_message=None):
        """Request to authenticate as this user. This returns a login URL that
           you must connect to to supply your login credentials

           If 'login_message' is supplied, then this is passed to
           the identity service so that it can be displayed
           when the user accesses the login page. This helps
           the user validate that they have accessed the correct
           login page. Note that if the message is None,
           then a random message will be generated.
        """
        self._check_for_error()

        from Acquire.Client import LoginError

        if not self.is_empty():
            raise LoginError("You cannot try to log in twice using the same "
                             "User object. Create another object if you want "
                             "to try to log in again.")

        if self._username is None or len(self._username) == 0:
            raise LoginError("Please supply a valid username!")

        # first, create a private key that will be used
        # to sign all requests and identify this login
        from Acquire.Client import PrivateKey as _PrivateKey
        session_key = _PrivateKey(name="user_session_key %s" % self._username)
        signing_key = _PrivateKey(name="user_session_cert %s" % self._username)

        args = {"username": self._username,
                "public_key": session_key.public_key().to_data(),
                "public_certificate": signing_key.public_key().to_data(),
                "scope": self._scope,
                "permissions": self._permissions
                }

        # get information from the local machine to help
        # the user validate that the login details are correct
        try:
            hostname = _socket.gethostname()
            ipaddr = _socket.gethostbyname(hostname)
            args["hostname"] = hostname
            args["ipaddr"] = ipaddr
        except:
            pass

        if login_message is None:
            try:
                login_message = _get_random_sentence()
            except:
                pass

        if login_message is not None:
            args["login_message"] = login_message

        identity_service = self.identity_service()

        result = identity_service.call_function(
                        function="request_login", args=args)

        try:
            login_url = result["login_url"]
        except:
            login_url = None

        if login_url is None:
            error = "Failed to login. Could not extract the login URL! " \
                    "Result is %s" % (str(result))
            self._set_error_state(error)
            raise LoginError(error)

        try:
            session_uid = result["session_uid"]
        except:
            session_uid = None

        if session_uid is None:
            error = "Failed to login. Could not extract the login " \
                    "session UID! Result is %s" % (str(result))

            self._set_error_state(error)
            raise LoginError(error)

        # now save all of the needed data
        self._login_url = result["login_url"]
        self._session_key = session_key
        self._signing_key = signing_key
        self._session_uid = session_uid
        self._status = _LoginStatus.LOGGING_IN
        self._user_uid = None

        _output("Login by visiting: %s" % self._login_url)

        if login_message is not None:
            _output("(please check that this page displays the message '%s')"
                    % login_message)

        from Acquire.Identity import LoginSession as _LoginSession

        return {"login_url": self._login_url,
                "session_uid": session_uid,
                "short_uid": _LoginSession.to_short_uid(session_uid)}
Beispiel #7
0
    def send_password(self, url, username=None, password=None,
                      otpcode=None, remember_password=True,
                      remember_device=None, dryrun=None):
        """Send a password and one-time code to the supplied login url"""
        if not remember_password:
            remember_device = False

        # the login URL is http[s]://something.com?id=XXXX/YY.YY.YY.YY
        # where XXXX is the service_uid of the service we should
        # connect with, and YY.YY.YY.YY is the short_uid of the login
        try:
            from urllib.parse import urlparse as _urlparse
            from urllib.parse import parse_qs as _parse_qs
            idcode = _parse_qs(_urlparse(url).query)["id"][0]
        except Exception as e:
            from Acquire.Client import LoginError
            raise LoginError(
                "Cannot identify the session or service information from "
                "the login URL '%s'. This should have id=XX-XX/YY.YY.YY.YY "
                "as a query parameter. <%s> %s" %
                (url, e.__class__.__name__, str(e)))

        try:
            (service_uid, short_uid) = idcode.split("/")
        except:
            from Acquire.Client import LoginError
            raise LoginError(
                "Cannot extract the service_uid and short_uid from the "
                "login ID code '%s'. This should be in the format "
                "XX-XX/YY.YY.YY.YY" % idcode)

        # now get the service
        try:
            service = self.get_service(service_uid=service_uid)
        except Exception as e:
            from Acquire.Client import LoginError
            raise LoginError(
                "Cannot find the service with UID %s: <%s> %s" %
                (service_uid, e.__class__.__name__, str(e)))

        if not service.can_identify_users():
            from Acquire.Client import LoginError
            raise LoginError(
                "Service '%s' is unable to identify users! "
                "You cannot log into something that is not "
                "a valid identity service!" % (service))

        userinfo = self._find_userinfo(username=username,
                                       password=password,
                                       service_uid=service_uid)

        if username is None:
            username = userinfo["username"]

        if "user_uid" in userinfo:
            user_uid = userinfo["user_uid"]
        else:
            user_uid = None

        _output("Logging in using username '%s'" % username)

        try:
            device_uid = userinfo["device_uid"]
        except:
            device_uid = None

        if password is None:
            password = self._get_user_password(userinfo=userinfo)

        if otpcode is None:
            otpcode = self._get_otpcode(userinfo=userinfo)
        else:
            # user is providing the primary OTP, so this is not a device
            device_uid = None

        _output("\nLogging in to '%s', session '%s'..." % (
                service.canonical_url(), short_uid), end="")

        _flush_output()

        if dryrun:
            print("Calling %s with username=%s, password=%s, otpcode=%s, "
                  "remember_device=%s, device_uid=%s, short_uid=%s "
                  "user_uid=%s" %
                  (service.canonical_url(), username, password, otpcode,
                   remember_device, device_uid, short_uid, user_uid))
            return

        try:
            from Acquire.Client import Credentials as _Credentials

            creds = _Credentials(username=username, password=password,
                                 otpcode=otpcode, short_uid=short_uid,
                                 device_uid=device_uid)

            args = {"credentials": creds.to_data(identity_uid=service.uid()),
                    "user_uid": user_uid,
                    "remember_device": remember_device,
                    "short_uid": short_uid}

            response = service.call_function(function="login", args=args)
            _output("SUCCEEDED!")
            _flush_output()
        except Exception as e:
            _output("FAILED!")
            _flush_output()
            from Acquire.Client import LoginError
            raise LoginError("Failed to log in. %s" % e.args)

        if not remember_password:
            return

        try:
            returned_user_uid = response["user_uid"]

            if returned_user_uid != user_uid:
                # change of user?
                userinfo = {}
                user_uid = returned_user_uid
        except:
            # no user_uid, so nothing to save
            return

        if user_uid is None:
            # can't save anything
            return

        userinfo["username"] = username
        userinfo["password"] = password

        try:
            userinfo["device_uid"] = response["device_uid"]
        except:
            pass

        try:
            userinfo["otpsecret"] = response["otpsecret"]
        except:
            pass

        self._set_userinfo(userinfo=userinfo,
                           user_uid=user_uid,
                           service_uid=service.uid())