def log_on(self):
        """ Logs on to a website, using an url.

        First checks if the channel requires log on. If so and it's not already
        logged on, it should handle the log on. That part should be implemented
        by the specific channel.

        More arguments can be passed on, but must be handled by custom code.

        After a successful log on the self.loggedOn property is set to True and
        True is returned.

        :return: indication if the login was successful.
        :rtype: bool

        """

        if self.__idToken:
            return True

        # check if there is a refresh token
        # refresh token: viervijfzes_refresh_token
        refresh_token = AddonSettings.get_setting("viervijfzes_refresh_token")
        client = AwsIdp("eu-west-1_dViSsKM5Y",
                        "6s1h851s8uplco5h6mqh1jac8m",
                        proxy=self.proxy,
                        logger=Logger.instance())
        if refresh_token:
            id_token = client.renew_token(refresh_token)
            if id_token:
                self.__idToken = id_token
                return True
            else:
                Logger.info("Extending token for VierVijfZes failed.")

        # username: viervijfzes_username
        username = AddonSettings.get_setting("viervijfzes_username")
        # password: viervijfzes_password
        v = Vault()
        password = v.get_setting("viervijfzes_password")
        if not username or not password:
            XbmcWrapper.show_dialog(
                title=None,
                lines=LanguageHelper.get_localized_string(
                    LanguageHelper.MissingCredentials),
            )
            return False

        id_token, refresh_token = client.authenticate(username, password)
        if not id_token or not refresh_token:
            Logger.error("Error getting a new token. Wrong password?")
            return False

        self.__idToken = id_token
        AddonSettings.set_setting("viervijfzes_refresh_token", refresh_token)
        return True
    def __get_application_key(self):
        """ Gets the decrypted application key that is used for all the encryption.

        :return: The decrypted application key that is used for all the encryption.
        :rtype: bytes

        """

        application_key_encrypted = AddonSettings.get_setting(
            Vault.__APPLICATION_KEY_SETTING, store=LOCAL)
        # The key was never in the local store the value was None. It was "" if it was reset.
        if application_key_encrypted is None:
            application_key_encrypted = AddonSettings.get_setting(
                Vault.__APPLICATION_KEY_SETTING, store=KODI)
            if not application_key_encrypted:
                return None

            Logger.info("Moved ApplicationKey to local storage")
            AddonSettings.set_setting(Vault.__APPLICATION_KEY_SETTING,
                                      application_key_encrypted,
                                      store=LOCAL)

        # Still no application key? Then there was no key!
        if application_key_encrypted == "" or application_key_encrypted is None:
            return None

        vault_incorrect_pin = LanguageHelper.get_localized_string(
            LanguageHelper.VaultIncorrectPin)
        pin = XbmcWrapper.show_key_board(
            heading=LanguageHelper.get_localized_string(
                LanguageHelper.VaultInputPin),
            hidden=True)
        if not pin:
            XbmcWrapper.show_notification("", vault_incorrect_pin,
                                          XbmcWrapper.Error)
            raise RuntimeError("Incorrect Retrospect PIN specified")
        pin_key = self.__get_pbk(pin)
        application_key = self.__decrypt(application_key_encrypted, pin_key)
        if not application_key.startswith(Vault.__APPLICATION_KEY_SETTING):
            Logger.critical("Invalid Retrospect PIN")
            XbmcWrapper.show_notification("", vault_incorrect_pin,
                                          XbmcWrapper.Error)
            raise RuntimeError("Incorrect Retrospect PIN specified")

        application_key_value = application_key[
            len(Vault.__APPLICATION_KEY_SETTING) + 1:]
        Logger.info("Successfully decrypted the ApplicationKey.")
        if PY2:
            return application_key_value

        # We return bytes on Python 3
        return application_key_value.encode()
Beispiel #3
0
    def log_off(self, username):
        """ Check if the user with the given name is currently authenticated.

        :param str username:    The username to log off

        :returns: Indication of success
        :rtype: bool

        """

        # clean older data
        UriHandler.delete_cookie(domain=".sso.rtl.nl")
        AddonSettings.set_setting(self.__setting_signature, "", store=LOCAL)
        return True
Beispiel #4
0
    def __extract_session_data(self, logon_data):
        """

        :param logon_data:
        :return:
        :rtype: AuthenticationResult

        """

        logon_json = json.loads(logon_data)
        result_code = logon_json.get("statusCode")
        Logger.trace("Logging in returned: %s", result_code)
        if result_code != 200:
            Logger.error("Error loging in: %s - %s",
                         logon_json.get("errorMessage"),
                         logon_json.get("errorDetails"))
            return AuthenticationResult(None)

        user_name = logon_json.get("profile", {}).get("email") or None

        signature_setting = logon_json.get("sessionInfo",
                                           {}).get("login_token")
        if signature_setting:
            Logger.info("Found 'login_token'. Saving it.")
            AddonSettings.set_setting(self.__setting_signature,
                                      signature_setting.split("|")[0],
                                      store=LOCAL)

        self.__signature = logon_json.get("UIDSignature")
        self.__user_id = logon_json.get("UID")
        self.__signature_timestamp = logon_json.get("signatureTimestamp")

        # TODO: is this correct?
        has_premium = logon_json.\
            get("data", {}).\
            get("authorization", {}).\
            get("rtlxl_premium", {}).\
            get("subscription", {}).\
            get("id") == "premium"

        # The channels are not interesting
        # premium_channels = logon_json.get_value(
        #     "data", "authorization", "Stievie_free", "channels")
        return AuthenticationResult(user_name, has_premium=has_premium)
    def reset():
        """ Resets the Vault and Retrospect Machine key, making all encrypted values
        useless.

        :rtype: None

        """

        ok = XbmcWrapper.show_yes_no(LanguageHelper.get_localized_string(LanguageHelper.VaultReset),
                                     LanguageHelper.get_localized_string(LanguageHelper.VaultResetConfirm))
        if not ok:
            Logger.debug("Aborting Reset Vault")
            return

        Logger.info("Resetting the vault to a new initial state.")
        AddonSettings.set_setting(Vault.__APPLICATION_KEY_SETTING, "", store=LOCAL)

        # create a vault instance so we initialize a new one with a new PIN.
        Vault()
        return
    def set_setting(self,
                    setting_id,
                    setting_name=None,
                    setting_action_id=None):
        """ Reads a value for a setting from the keyboard and encrypts it in the Kodi
        Add-on settings.

        The settingActionId defaults to <settingId>_set

        :param str setting_id:          The ID for the Kodi Add-on setting to set.
        :param str setting_name:        The name to display in the keyboard.
        :param str setting_action_id:   The name of setting that shows the ***** if an value was
                                         encrypted.

        :rtype: None

        """

        Logger.info("Encrypting value for setting '%s'", setting_id)
        input_value = XbmcWrapper.show_key_board(
            "",
            LanguageHelper.get_localized_string(
                LanguageHelper.VaultSpecifySetting) %
            (setting_name or setting_id, ))

        if input_value is None:
            Logger.debug("Setting of encrypted value cancelled.")
            return

        value = "%s=%s" % (setting_id, input_value)
        encrypted_value = self.__encrypt(value, Vault.__Key)

        if setting_action_id is None:
            setting_action_id = "%s_set" % (setting_id, )

        Logger.debug("Updating '%s' and '%s'", setting_id, setting_action_id)
        AddonSettings.set_setting(setting_id, encrypted_value)
        if input_value:
            AddonSettings.set_setting(setting_action_id, "******")
        else:
            AddonSettings.set_setting(setting_action_id, "")
        Logger.info("Successfully encrypted value for setting '%s'",
                    setting_id)
        return
    def change_pin(self, application_key=None):
        """ Stores an existing ApplicationKey using a new PIN.

        :param bytes application_key: an existing ApplicationKey that will be stored. If none
                                      specified, the existing ApplicationKey of the Vault will
                                      be used.

        :return: Indication of success.
        :rtype: bool

        """

        Logger.info("Updating the ApplicationKey with a new PIN")

        if self.__newKeyGeneratedInConstructor:
            Logger.info("A key was just generated, no need to change PINs.")
            return True

        if application_key is None:
            Logger.debug("Using the ApplicationKey from the vault.")
            application_key = Vault.__Key
        else:
            Logger.debug("Using the ApplicationKey from the input parameter.")

        if not application_key:
            raise ValueError("No ApplicationKey specified.")

        # Now we get a new PIN and (re)encrypt

        pin = XbmcWrapper.show_key_board(
            heading=LanguageHelper.get_localized_string(
                LanguageHelper.VaultNewPin),
            hidden=True)
        if not pin:
            XbmcWrapper.show_notification(
                "",
                LanguageHelper.get_localized_string(LanguageHelper.VaultNoPin),
                XbmcWrapper.Error)
            return False

        pin2 = XbmcWrapper.show_key_board(
            heading=LanguageHelper.get_localized_string(
                LanguageHelper.VaultRepeatPin),
            hidden=True)
        if pin != pin2:
            Logger.critical("Mismatch in PINs")
            XbmcWrapper.show_notification(
                "",
                LanguageHelper.get_localized_string(
                    LanguageHelper.VaultPinsDontMatch), XbmcWrapper.Error)
            return False

        if PY2:
            encrypted_key = "%s=%s" % (self.__APPLICATION_KEY_SETTING,
                                       application_key)
        else:
            # make it text to store
            encrypted_key = "%s=%s" % (self.__APPLICATION_KEY_SETTING,
                                       application_key.decode())

        # let's generate a pin using the scrypt password-based key derivation
        pin_key = self.__get_pbk(pin)
        encrypted_key = self.__encrypt(encrypted_key, pin_key)
        AddonSettings.set_setting(Vault.__APPLICATION_KEY_SETTING,
                                  encrypted_key,
                                  store=LOCAL)
        Logger.info("Successfully updated the Retrospect PIN")
        return True