예제 #1
0
def get_session_keys(username=None,
                     user_uid=None,
                     session_uid=None,
                     identity_url=None):
    """Function to return the session keys for the specified user"""
    if username is None and user_uid is None:
        raise ValueError("You must supply either the username or user_uid!")

    if session_uid is None:
        raise ValueError("You must supply a valid UID for a login session")

    if identity_url is None:
        identity_url = _get_identity_url()

    response = _call_function(identity_url,
                              "whois",
                              username=username,
                              user_uid=user_uid,
                              session_uid=session_uid)

    try:
        response["public_key"] = _PublicKey.from_data(response["public_key"])
    except:
        pass

    try:
        response["public_cert"] = _PublicKey.from_data(response["public_cert"])
    except:
        pass

    return response
예제 #2
0
def run(args):
    """This function will allow a user to request a new session
       that will be validated by the passed public key and public
       signing certificate. This will return a URL that the user
       must connect to to then log in and validate that request.

        Args:
            args (dict): containing login data such as username, password etc

        Returns:
            dict: containing status of login attempt
    """
    username = args["username"]
    public_key = PublicKey.from_data(args["public_key"])
    public_cert = PublicKey.from_data(args["public_certificate"])

    try:
        scope = args["scope"]
    except:
        scope = None

    try:
        permissions = args["permissions"]
    except:
        permissions = None

    try:
        hostname = args["hostname"]
    except:
        hostname = None

    try:
        ipaddr = args["ipaddr"]
    except:
        ipaddr = None

    try:
        login_message = args["login_message"]
    except:
        login_message = None

    # Generate a login session for this request
    login_session = LoginSession(username=username,
                                 public_key=public_key,
                                 public_cert=public_cert,
                                 ipaddr=ipaddr, hostname=hostname,
                                 login_message=login_message,
                                 scope=scope, permissions=permissions)

    return_value = {}

    return_value["login_url"] = login_session.login_url()
    return_value["short_uid"] = login_session.short_uid()
    return_value["session_uid"] = login_session.uid()

    return return_value
예제 #3
0
def test_keys():
    privkey = PrivateKey()
    pubkey = privkey.public_key()

    message = "Hello World"

    sig = privkey.sign(message.encode("utf-8"))
    pubkey.verify(sig, message.encode("utf-8"))

    c = pubkey.encrypt(message.encode("utf-8"))

    m = privkey.decrypt(c).decode("utf-8")
    assert (m == message)

    privkey2 = PrivateKey()
    sig2 = privkey2.sign(message.encode("utf-8"))

    with pytest.raises(SignatureVerificationError):
        pubkey.verify(sig2, message.encode("utf-8"))

    bytes = privkey.bytes("testPass32")

    PrivateKey.read_bytes(bytes, "testPass32")

    privkey.write("test.pem", "testPass32")

    PrivateKey.read("test.pem", "testPass32")

    bytes = pubkey.bytes()
    pubkey2 = PublicKey.read_bytes(bytes)

    assert (bytes == pubkey2.bytes())

    long_message = str([random.getrandbits(8)
                        for _ in range(4096)]).encode("utf-8")

    c = pubkey.encrypt(long_message)

    m = privkey.decrypt(c)

    assert (m == long_message)

    os.unlink("test.pem")

    data = pubkey.to_data()

    pubkey2 = PublicKey.from_data(data)

    assert (pubkey.bytes() == pubkey2.bytes())

    data = privkey.to_data("testPass33")

    privkey2 = PrivateKey.from_data(data, "testPass33")

    assert (privkey == privkey2)
예제 #4
0
    def from_data(data, password=None):
        """Deserialise this object from the passed data. This will
           only deserialise the private key, private certificate,
           and OTP if a valid password and passcode is supplied
        """

        service = Service()

        if password:
            # get the private info...
            service._privkey = _PrivateKey.from_data(data["private_key"],
                                                     password)

            service._privcert = _PrivateKey.from_data(
                                                data["private_certificate"],
                                                password)

            service._otpsecret = _string_to_bytes(data["otpsecret"])

            service._admin_password = _string_to_bytes(data["admin_password"])
        else:
            service._privkey = None
            service._privcert = None
            service._otpsecret = None

        service._uuid = data["uuid"]
        service._service_type = data["service_type"]
        service._service_url = data["service_url"]
        service._canonical_url = service._service_url

        service._pubkey = _PublicKey.from_data(data["public_key"])
        service._pubcert = _PublicKey.from_data(data["public_certificate"])

        if service.is_identity_service():
            from Acquire.Identity import IdentityService as _IdentityService
            return _IdentityService(service)
        elif service.is_access_service():
            from Acquire.Access import AccessService as _AccessService
            return _AccessService(service)
        elif service.is_accounting_service():
            from Acquire.Accounting import AccountingService \
                                        as _AccountingService
            return _AccountingService(service)
        else:
            return service
예제 #5
0
def run(args):
    """Open and return a new ChunkUploader that can be used
       to upload a file in lots of chunks
    """

    filename = str(args["filename"])
    drive_uid = str(args["drive_uid"])

    try:
        aclrules = ACLRules.from_data(args["aclrules"])
    except:
        aclrules = None

    try:
        authorisation = Authorisation.from_data(args["authorisation"])
    except:
        authorisation = None

    try:
        par_uid = str(args["par_uid"])
    except:
        par_uid = None

    try:
        secret = str(args["secret"])
    except:
        secret = None

    try:
        pubkey = PublicKey.from_data(args["encryption_key"])
    except:
        pubkey = None

    if par_uid is not None:
        registry = PARRegistry()
        (par, identifiers) = registry.load(par_uid=par_uid, secret=secret)
    else:
        par = None
        identifiers = None

    drive = DriveInfo(drive_uid=drive_uid)

    (filemeta, uploader) = drive.open_uploader(filename=filename,
                                               aclrules=aclrules,
                                               authorisation=authorisation,
                                               par=par,
                                               identifiers=identifiers)

    return {
        "filemeta": filemeta.to_data(),
        "uploader": uploader.to_data(pubkey=pubkey)
    }
예제 #6
0
def get_public_certs(identity_url, username, session_uid):
    """Call the identity_url to obtain the public keys
       and certificates of the user with 'username' logged
       in using the specified session_uid
    """

    response = _call_function(identity_url,
                              "get_keys",
                              username=username,
                              session_uid=session_uid)

    public_key = None
    public_cert = None

    if "public_key" in response:
        public_key = _PublicKey.read_bytes(
            _string_to_bytes(response["public_key"]))

    if "public_cert" in response:
        public_cert = _PublicKey.read_bytes(
            _string_to_bytes(response["public_cert"]))

    return (public_key, public_cert)
예제 #7
0
def run(args):
    """This function return the status and service info

       Args:
            args (dict): containing data on the service we want
            to trust

       Returns:
            dict: containing status, status message and passed in args  
    
    """
    try:
        service_url = args["service_url"]
    except:
        service_url = None

    try:
        public_cert = PublicKey.from_data(args["public_certificate"])
    except:
        public_cert = None

    try:
        authorisation = Authorisation.from_data(args["authorisation"])
    except:
        authorisation = None

    if service_url is not None:
        service = get_checked_remote_service(service_url, public_cert)
    else:
        service = None

    if service is not None:
        trust_service(service, authorisation)

    return_value = {}

    return_value["args"] = args

    return return_value
예제 #8
0
def _get_key(key, fingerprint=None):
    """The user may pass the key in multiple ways. It could just be
       a key. Or it could be a function that gets the key on demand.
       Or it could be a dictionary that has the key stored under
       "encryption_public_key"
    """
    from Acquire.Crypto import PublicKey as _PublicKey
    from Acquire.Crypto import PrivateKey as _PrivateKey

    if key is None:
        return None
    elif isinstance(key, _PublicKey) or isinstance(key, _PrivateKey):
        key = key
    elif isinstance(key, dict):
        try:
            key = key["encryption_public_key"]
        except:
            key = None

        if key is not None:
            from Acquire.ObjectStore import string_to_bytes as _string_to_bytes
            key = _PublicKey.read_bytes(_string_to_bytes(key))
    else:
        key = key(fingerprint=fingerprint)

    if fingerprint is not None:
        if key is None:
            from Acquire.Crypto import KeyManipulationError
            raise KeyManipulationError(
                "Cannot find the key with fingerprint %s!" % fingerprint)
        elif key.fingerprint() != fingerprint:
            from Acquire.Crypto import KeyManipulationError
            raise KeyManipulationError(
                "Cannot find a key with the required fingerprint (%s). "
                "The only key has fingerprint %s" %
                (fingerprint, key.fingerprint()))

    return key
예제 #9
0
async def handler(ctx, data=None, loop=None):
    """This function just reflects back the json that is supplied.
       This is useful for debugging clients that are calling this
       server
    """

    result = {}

    try:
        data = json.loads(data)

        privkey = get_service_private_key()

        encrypted = string_to_bytes(data["data"])

        decrypted = privkey.decrypt(encrypted).decode("utf-8")

        data = json.loads(decrypted)

        pem = data["encryption_public_key"]

        key = PublicKey.from_data(pem)

        result["key"] = str(key.to_data())
        result["status"] = -1

    except Exception as e:
        message = {"status": -1, "message": "Error packing results: %s" % e}
        return json.dumps(message)
    except:
        message = {
            "status": -1,
            "message": "Error packing results: Unknown error"
        }
        return json.dumps(message)

    return json.dumps(result)
예제 #10
0
def get_session_info(identity_url, session_uid, scope=None, permissions=None):
    """Call the identity_url to obtain information about the
       specified login session_uid. Optionally limit
       the scope and permissions for which these certs would
       be valid
    """
    from Acquire.Service import get_trusted_service as _get_trusted_service

    service = _get_trusted_service(identity_url)

    args = {"session_uid": session_uid}

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

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

    response = service.call_function(function="get_session_info", args=args)

    try:
        del response["status"]
    except:
        pass

    try:
        del response["message"]
    except:
        pass

    from Acquire.Crypto import PublicKey as _PublicKey

    for key in response.keys():
        if key in ["public_key", "public_certificate"]:
            response[key] = _PublicKey.from_data(response[key])

    return response
예제 #11
0
def _get_key(key):
    """The user may pass the key in multiple ways. It could just be
       a key. Or it could be a function that gets the key on demand.
       Or it could be a dictionary that has the key stored under
       "encryption_public_key"
    """
    if key is None:
        return None
    elif isinstance(key, _PublicKey):
        return key
    elif isinstance(key, dict):
        try:
            key = key["encryption_public_key"]
        except:
            return None

        key = _PublicKey.read_bytes(_string_to_bytes(key))
    else:
        try:
            key = key()
        except:
            pass

    return key
def get_trusted_registry_service(registry_uid=None,
                                 service_uid=None,
                                 service_url=None):
    """Return the trusted service info for the registry with specified
       registry_uid, or get any trusted registry service using either
       'service_uid' or 'service_url' as a starting hint to
       locate a suitable registry
    """
    if service_uid is not None:
        # for the moment, just try to get one registry. Eventually we should
        # try to get several in case this one is down
        registry_uid = get_primary_registry_uid(service_uid)
        return get_trusted_registry_service(registry_uid=registry_uid)

    if service_url is not None:
        if service_url.find(".") != -1:
            # try the main acquire registry first
            return get_trusted_registry_service(registry_uid="a0-a0")
        else:
            # this must be testing...
            return get_trusted_registry_service(registry_uid="Z9-Z9")

    if registry_uid is None:
        raise PermissionError(
            "You must specify one of registry_uid, service_uid "
            "or service_url")

    from Acquire.Service import get_trusted_service as _get_trusted_service

    try:
        registry_service = _get_trusted_service(service_uid=registry_uid,
                                                autofetch=False)
    except:
        registry_service = None

    if registry_service is not None:
        if not registry_service.is_registry_service():
            from Acquire.Service import ServiceError
            raise ServiceError("The requested service (%s) for %s is NOT a "
                               "registry service!" %
                               (registry_service, registry_uid))

        if registry_service.uid() != registry_uid:
            from Acquire.Service import ServiceError
            raise ServiceError(
                "Disagreement of UID (%s) is NOT the right registry service!" %
                registry_service)

        # everything is ok - we have seen this registry before
        return registry_service

    # boostrapping
    from Acquire.Registry import get_registry_details \
        as _get_registry_details

    details = _get_registry_details(registry_uid)

    from Acquire.Service import call_function as _call_function
    from Acquire.Service import Service as _Service
    from Acquire.Crypto import get_private_key as _get_private_key
    from Acquire.Crypto import PrivateKey as _PrivateKey
    from Acquire.Crypto import PublicKey as _PublicKey
    from Acquire.ObjectStore import bytes_to_string as _bytes_to_string
    from Acquire.ObjectStore import string_to_bytes as _string_to_bytes

    privkey = _get_private_key(key="registry")

    pubkey = _PublicKey.from_data(details["public_key"])
    pubcert = _PublicKey.from_data(details["public_certificate"])

    # ask the registry to return to us their latest details - use
    # a challenge-response to make sure that the response is
    # properly returned
    challenge = _PrivateKey.random_passphrase()
    encrypted_challenge = _bytes_to_string(pubkey.encrypt(challenge))
    args = {
        "challenge": encrypted_challenge,
        "fingerprint": pubkey.fingerprint()
    }

    result = _call_function(service_url=details["canonical_url"],
                            function=None,
                            args=args,
                            args_key=pubkey,
                            response_key=privkey,
                            public_cert=pubcert)

    if result["response"] != challenge:
        from Acquire.Service import ServiceError
        raise ServiceError(
            "The requested service (%s) failed to respond to the challenge!" %
            registry_service)

    registry_service = _Service.from_data(result["service_info"])

    if not registry_service.is_registry_service():
        from Acquire.Service import ServiceError
        raise ServiceError(
            "The requested service (%s) is NOT a registry service!" %
            registry_service)

    if registry_service.uid() != details["uid"]:
        from Acquire.Service import ServiceError
        raise ServiceError(
            "Disagreement of UID (%s) is NOT the right registry service!" %
            registry_service)

    # ok - we've got the registry - add this to the set of
    # trusted services so that we don't need to bootstrap from
    # the registry details again
    from Acquire.Service import trust_service as _trust_service
    _trust_service(registry_service)

    return registry_service
예제 #13
0
def run(args):
    """This function will allow a user to register an account with a
       username and password"""

    status = 0
    message = None
    provisioning_uri = None

    username = args["username"]
    password = args["password"]

    # generate a sanitised version of the username
    user_account = UserAccount(username)

    # generate the encryption keys and otp secret
    privkey = PrivateKey()
    pubkey = privkey.public_key()
    otp = OTP()

    provisioning_uri = otp.provisioning_uri(username)

    # save the encrypted private key (encrypted using the user's password)
    # and encrypted OTP secret (encrypted using the public key)
    user_account.set_keys(privkey.bytes(password), pubkey.bytes(),
                          otp.encrypt(pubkey))

    # remove the key and password from memory
    privkey = None
    password = None

    # now log into the central identity account to either register
    # the user, or to update to a new password
    bucket = login_to_service_account()
    account_key = "accounts/%s" % user_account.sanitised_name()

    try:
        existing_data = ObjectStore.get_object_from_json(bucket,
                                                         account_key)
    except:
        existing_data = None

    message = "Created a new account for '%s'" % username
    status = 0

    if existing_data is None:
        # save the new account details
        ObjectStore.set_object_from_json(bucket, account_key,
                                         user_account.to_data())

        # need to update the "whois" database with the uuid of this user
        ObjectStore.set_string_object(bucket,
                                      "whois/%s" % user_account.uuid(),
                                      user_account.username())
    else:
        # The account already exists. See if this is a password change
        # request
        old_password = None

        try:
            old_password = args["old_password"]
        except:
            raise ExistingAccountError(
                "An account by this name already exists!")

        if old_password != password:
            # this is a change of password request - validate that
            # the existing password unlocks the existing key
            user_account = UserAccount.from_data(existing_data)

            testkey = PrivateKey.read_bytes(user_account.private_key(),
                                            old_password)

            # decrypt the old secret
            old_secret = testkey.decrypt(user_account.otp_secret())

            # now encrypt the secret with the new key
            new_key = PublicKey.read_bytes(pubkey)
            new_secret = new_key.encrypt(old_secret)

            user_account.set_keys(privkey, pubkey, new_secret)

            # save the new account details
            ObjectStore.set_object_from_json(bucket, account_key,
                                             user_account.to_data())

            message = "Updated the password for '%s'" % username
        else:
            message = "No need to change account '%s'" % username

    return_value = create_return_value(status, message)

    if provisioning_uri:
        return_value["provisioning_uri"] = provisioning_uri

    return return_value
예제 #14
0
    def whois(self, username=None, user_uid=None, session_uid=None):
        """Do a whois lookup to map from username to user_uid or
           vice versa. If 'session_uid' is provided, then also validate
           that this is a correct login session, and return also
           the public key and signing certificate for this login session.

           This should return a dictionary with the following keys
           optionally contained;

           username = name of the user
           user_uid = uid of the user
           public_key = public key for the session with uid 'session_uid'
           public_cert = public certificate for that login session
        """

        if (username is None) and (user_uid is None):
            raise IdentityServiceError("You must supply either a username "
                                       "or a user's UID for a lookup")

        key = _PrivateKey()

        response = None

        if session_uid is None:
            args = {}
        else:
            args = {"session_uid": str(session_uid)}

        try:
            if username:
                args["username"] = str(username)
                response = _call_function(
                    self.service_url(),
                    "whois",
                    public_cert=self.public_certificate(),
                    response_key=key,
                    args=args)
                lookup_uid = response["user_uid"]
            else:
                lookup_uid = None

            if user_uid:
                args["user_uid"] = str(user_uid)
                response = _call_function(
                    self.service_url(),
                    "whois",
                    public_cert=self.public_certificate(),
                    response_key=key,
                    args=args)
                lookup_username = response["username"]
            else:
                lookup_username = None

        except Exception as e:
            raise IdentityServiceError("Failed whois lookup: %s" % str(e))

        if username is None:
            username = lookup_username

        elif (lookup_username is not None) and (username != lookup_username):
            raise IdentityServiceError(
                "Disagreement of the user who matches "
                "UID=%s. We think '%s', but the identity service says '%s'" %
                (user_uid, username, lookup_username))

        if user_uid is None:
            user_uid = lookup_uid

        elif (lookup_uid is not None) and (user_uid != lookup_uid):
            raise IdentityServiceError(
                "Disagreement of the user's UID for user "
                "'%s'. We think %s, but the identity service says %s" %
                (username, user_uid, lookup_uid))

        result = response

        try:
            result["public_key"] = _PublicKey.from_data(response["public_key"])
        except:
            pass

        try:
            result["public_cert"] = _PublicKey.from_data(
                response["public_cert"])
        except:
            pass

        return result
예제 #15
0
    def _get_user_public_cert(self, scope=None, permissions=None):
        """Internal function that returns the public certificate
           of the user who signed this authorisation. This will
           check that the authorisation was not signed after the
           user logged out, as well as validating the services
           that provide the user session keys etc.
        """
        must_fetch = False

        try:
            if scope != self._scope or permissions != self._permissions:
                must_fetch = True
        except:
            must_fetch = True

        if self._pubcert is not None:
            if not must_fetch:
                try:
                    return self._pubcert
                except:
                    pass

        try:
            testing_key = self._testing_key
        except:
            testing_key = None

        if testing_key is not None:
            if not self._is_testing:
                raise PermissionError(
                    "You cannot pass a test key to a non-testing "
                    "Authorisation")

            return testing_key

        # we need to get the public signing key for this session
        from Acquire.Service import get_trusted_service \
            as _get_trusted_service
        from Acquire.ObjectStore import get_datetime_now \
            as _get_datetime_now

        try:
            identity_service = _get_trusted_service(self._identity_url)
        except:
            raise PermissionError(
                "Unable to verify the authorisation as we do not trust "
                "the identity service at %s" % self._identity_url)

        if not identity_service.can_identify_users():
            raise PermissionError(
                "Cannot verify an Authorisation that does not use a "
                "valid identity service")

        if identity_service.uid() != self._identity_uid:
            raise PermissionError(
                "Cannot auth_once this Authorisation as the actual UID of "
                "the identity service at '%s' (%s) does not match "
                "the UID of the service that signed this authorisation "
                "(%s)" % (self._identity_url, identity_service.uid(),
                          self._identity_uid))

        response = identity_service.get_session_info(
            session_uid=self._session_uid,
            scope=scope,
            permissions=permissions)

        try:
            user_uid = response["user_uid"]
        except:
            pass

        if self._user_uid != user_uid:
            raise PermissionError(
                "Cannot verify the authorisation as there is "
                "disagreement over the UID of the user who signed "
                "the authorisation. %s versus %s" % (self._user_uid, user_uid))

        try:
            logout_datetime = _string_to_datetime(response["logout_datetime"])
        except:
            logout_datetime = None

        if logout_datetime:
            # the user has logged out from this session - ensure that
            # the authorisation was created before the user logged out
            if logout_datetime < self.signature_time():
                raise PermissionError(
                    "This authorisation was signed after the user logged "
                    "out. This means that the authorisation is not valid. "
                    "Please log in again and create a new authorisation.")

        from Acquire.Crypto import PublicKey as _PublicKey
        pubcert = _PublicKey.from_data(response["public_cert"])

        self._pubcert = pubcert
        self._scope = scope
        self._permissions = permissions
        return pubcert
예제 #16
0
    def from_data(data):
        """Return a LoginSession constructed from the passed data
           (dictionary)
        """
        l = LoginSession()

        if data is not None and len(data) > 0:
            from Acquire.ObjectStore import string_to_datetime \
                as _string_to_datetime
            from Acquire.Crypto import PublicKey as _PublicKey

            l._uid = data["uid"]
            l._username = data["username"]
            l._request_datetime = _string_to_datetime(data["request_datetime"])
            l._pubcert = _PublicKey.from_data(data["public_certificate"])
            l._status = data["status"]

            try:
                l._pubkey = _PublicKey.from_data(data["public_key"])
            except:
                l._pubkey = None

            try:
                l._login_datatime = _string_to_datetime(data["login_datetime"])
            except:
                pass

            try:
                l._logout_datetime = _string_to_datetime(
                    data["logout_datetime"])
            except:
                pass

            try:
                l._ipaddr = data["ipaddr"]
            except:
                pass

            try:
                l._hostname = data["hostname"]
            except:
                pass

            try:
                l._login_message = data["login_message"]
            except:
                pass

            try:
                l._scope = data["scope"]
            except:
                pass

            try:
                l._permissions = data["permissions"]
            except:
                pass

            try:
                l._user_uid = data["user_uid"]
            except:
                pass

            try:
                l._device_uid = data["device_uid"]
            except:
                pass

        return l
예제 #17
0
def run(args):
    """Call this function to initiate the two-step file-download process.

       Step 1: download - tells the service to download the file. If the
               file is small then the file will be in the response.
               Otherwise a OSPar will be returned that will let you
               download the file. If this is the case, then you must
               call step 2...

       Step 2: downloaded - after you have downloaded the file from the OSPar
               call OSPar.close() so that the service knows that the OSPar
               is no longer needed and can be deleted
    """

    drive_uid = args["drive_uid"]
    filename = args["filename"]

    try:
        authorisation = Authorisation.from_data(args["authorisation"])
    except:
        authorisation = None

    try:
        par_uid = args["par_uid"]
    except:
        par_uid = None

    try:
        secret = args["secret"]
    except:
        secret = None

    public_key = PublicKey.from_data(args["encryption_key"])

    if "version" in args:
        version = str(args["version"])
    else:
        version = None

    if "force_par" in args:
        force_par = args["force_par"]
    else:
        force_par = None

    if "must_chunk" in args:
        must_chunk = args["must_chunk"]
    else:
        must_chunk = False

    if must_chunk:
        must_chunk = True

    if force_par:
        force_par = True

    if par_uid is not None:
        registry = PARRegistry()
        (par, identifiers) = registry.load(par_uid=par_uid, secret=secret)
    else:
        par = None
        identifiers = None

    drive = DriveInfo(drive_uid=drive_uid)

    return_value = {}

    (filemeta, filedata, par,
     downloader) = drive.download(filename=filename,
                                  version=version,
                                  authorisation=authorisation,
                                  encrypt_key=public_key,
                                  force_par=force_par,
                                  must_chunk=must_chunk,
                                  par=par,
                                  identifiers=identifiers)

    if filemeta is not None:
        return_value["filemeta"] = filemeta.to_data()

    if filedata is not None:
        from Acquire.ObjectStore import bytes_to_string as _bytes_to_string
        return_value["filedata"] = _bytes_to_string(filedata)

    if par is not None:
        return_value["download_par"] = par.to_data()

    if downloader is not None:
        return_value["downloader"] = downloader.to_data(pubkey=public_key)

    return return_value
예제 #18
0
def run(args):
    """Call this function to initiate the two-step file-upload process.

       Step 1: upload - tells the service that a file of specific
               size and checksum will be uploaded. This gives the service
               the chance to decide whether this will be allowed. If the
               file is small, and was thus included in the FileHandle,
               then it is uploaded immediately and the operation completes.
               If the file is large, then we now returns a OSPar
               that can be used for this upload (Step 2)

       Step 2: after the user has used the OSPar to upload
               the file, they should call OSPar.close() to notify
               the service that the file has been successfully uploaded.
               This will verify that the file has been uploaded correctly,
               will receipt the storage cost and will delete the OSPar
    """

    filehandle = FileHandle.from_data(args["filehandle"])

    try:
        authorisation = Authorisation.from_data(args["authorisation"])
    except:
        authorisation = None

    try:
        par_uid = args["par_uid"]
    except:
        par_uid = None

    try:
        secret = args["secret"]
    except:
        secret = None

    try:
        public_key = PublicKey.from_data(args["encryption_key"])
    except:
        public_key = None

    if par_uid is not None:
        registry = PARRegistry()
        (par, identifiers) = registry.load(par_uid=par_uid, secret=secret)
    else:
        par = None
        identifiers = None

    drive_uid = filehandle.drive_uid()

    drive = DriveInfo(drive_uid=drive_uid)

    return_value = {}

    (filemeta, par) = drive.upload(filehandle=filehandle,
                                   authorisation=authorisation,
                                   encrypt_key=public_key,
                                   par=par,
                                   identifiers=identifiers)

    if filemeta is not None:
        return_value["filemeta"] = filemeta.to_data()

    if par is not None:
        return_value["upload_par"] = par.to_data()

    return return_value
예제 #19
0
def run(args):
    """This function will allow a user to request a new session
       that will be validated by the passed public key and public
       signing certificate. This will return a URL that the user
       must connect to to then log in and validate that request.
    """

    status = 0
    message = None
    login_url = None
    login_uid = None
    user_uid = None

    username = args["username"]
    public_key = PublicKey.from_data(args["public_key"])
    public_cert = PublicKey.from_data(args["public_certificate"])

    ip_addr = None
    hostname = None
    login_message = None

    try:
        ip_addr = args["ipaddr"]
    except:
        pass

    try:
        hostname = args["hostname"]
    except:
        pass

    try:
        login_message = args["message"]
    except:
        pass

    # generate a sanitised version of the username
    user_account = UserAccount(username)

    # Now generate a login session for this request
    login_session = LoginSession(public_key, public_cert, ip_addr, hostname,
                                 login_message)

    # now log into the central identity account to record
    # that a request to open a login session has been opened
    bucket = login_to_service_account()

    # first, make sure that the user exists...
    account_key = "accounts/%s" % user_account.sanitised_name()

    try:
        existing_data = ObjectStore.get_object_from_json(bucket, account_key)
    except:
        existing_data = None

    if existing_data is None:
        raise InvalidLoginError("There is no user with name '%s'" % username)

    user_account = UserAccount.from_data(existing_data)
    user_uid = user_account.uid()

    # first, make sure that the user doens't have too many open
    # login sessions at once - this prevents denial of service
    user_session_root = "sessions/%s" % user_account.sanitised_name()

    open_sessions = ObjectStore.get_all_object_names(bucket, user_session_root)

    # take the opportunity to prune old user login sessions
    prune_expired_sessions(bucket, user_account, user_session_root,
                           open_sessions)

    # this is the key for the session in the object store
    user_session_key = "%s/%s" % (user_session_root, login_session.uuid())

    ObjectStore.set_object_from_json(bucket, user_session_key,
                                     login_session.to_data())

    # we will record a pointer to the request using the short
    # UUID. This way we can give a simple URL. If there is a clash,
    # then we will use the username provided at login to find the
    # correct request from a much smaller pool (likely < 3)
    request_key = "requests/%s/%s" % (login_session.short_uuid(),
                                      login_session.uuid())

    ObjectStore.set_string_object(bucket, request_key, user_account.name())

    status = 0
    # the login URL is the URL of this identity service plus the
    # short UID of the session
    login_url = "%s/s?id=%s" % (get_service_info().service_url(),
                                login_session.short_uuid())

    login_uid = login_session.uuid()

    message = "Success: Login via %s" % login_url

    return_value = create_return_value(status, message)

    if login_uid:
        return_value["session_uid"] = login_uid

    if login_url:
        return_value["login_url"] = login_url
    else:
        return_value["login_url"] = None

    if user_uid:
        return_value["user_uid"] = user_uid

    return return_value