def remove(self, target):
        """
        Remove an item from Location Services. If no item is given, then disable
        Location Services globally.

        :param target: an application or file to modify permissions for
        """
        # If no application is given, then we're modifying the global Location
        # Services system.
        if not target:
            self.logger.info("Disabling service 'location' globally...")
            enable_global(False, self.logger)
            self.logger.info("Globally disabled successfully.")
            return

        if self.admin:
            name = target
            target = 'com.apple.locationd.executable-{}'.format(target)
        else:
            name = AppInfo(target).name
            target = AppInfo(target).bid

        # Verbosity
        self.logger.info(
            "Removing '{}' from service 'location'...".format(target))

        # Otherwise, just delete its entry in the plist.
        result = self.plist.delete(target)
        if result:
            raise RuntimeError("Failed to remove {}.".format(name))
        self.logger.info("Removed successfully.")
    def disable(self, target):
        """
        Mark the application or file as being disallowed from utilizing Location
        Services. If the target is not already in the plist, it will be added
        and then disabled.

        :param target: an application or file to modify permissions for
        """
        # If no application is given, then we're modifying the global Location
        # Services system.
        if not target:
            self.logger.info("Disabling service 'location' globally...")
            enable_global(False, self.logger)
            self.logger.info("Globally disabled successfully.")
            return

        if self.no_check:
            name   = target
            target = 'com.apple.locationd.executable-{}'.format(target)
        else:
            name   = AppInfo(target).name
            target = AppInfo(target).bid

        # Verboseness
        self.logger.info("Disabling '{}' in service 'location'...".format(target))

        # If the application isn't already in locationd, add it.
        if not self.plist.read(target):
            self.insert(target)

        # Then deauthorize the application.
        result = self.plist.dict_add(target, "Authorized", "FALSE", "bool")
        if result:
            raise RuntimeError("Failed to disable {}.".format(name))
        self.logger.info("Disabled successfully.")
    def __insert_app(self, target):
        """
        Inserts the specified target application into the locationd plist.
        """
        # Get the AppInfo object for more information.
        app = AppInfo(target)

        # Verbosity!
        self.logger.info("Inserting '{}' into service 'location'...".format(
            app.bid))

        # This is used for... something. Don't know what, but it's necessary.
        requirement = ("identifier \"{}\" and anchor {}".format(
            app.bid,
            app.bid.split('.')[1]))

        # Write the changes to the locationd plist.
        result = 0
        result += self.plist.dict_add(app.bid, "Authorized", "TRUE", "bool")
        result += self.plist.dict_add(app.bid, "BundleID", app.bid)
        result += self.plist.dict_add(app.bid, "BundleId", app.bid)
        result += self.plist.dict_add(app.bid, "BundlePath", app.path)
        result += self.plist.dict_add(app.bid, "Executable", app.executable)
        result += self.plist.dict_add(app.bid, "Registered", app.executable)
        result += self.plist.dict_add(app.bid, "Hide", 0, "int")
        result += self.plist.dict_add(app.bid, "Requirement", requirement)
        result += self.plist.dict_add(app.bid, "Whitelisted", "FALSE", "bool")
        if result:
            # Clearly there was an error...
            raise RuntimeError("Failed to insert {}.".format(app.name))
        self.logger.info("Inserted successfully.")
Ejemplo n.º 4
0
def main(args):
    for item in args[1:]:
        try:
            info = AppInfo(item)
        except ValueError, e:
            info = "Invalid application: '" + item + "'"
        print info
Ejemplo n.º 5
0
    def remove(self, target, service=None):
        """
        Remove an item from Privacy Services for the given service.

        :param target: an application or file to modify permissions for
        :param service: a particular service to modify the permissions within
        """
        # Validate that they didn't pass us something nonexistent.
        if target is None:
            return

        # If not using admin override mode, look up a bundle identifier.
        try:
            target = AppInfo(target).bid
        except ValueError:
            if self.admin:
                target = os.path.abspath(target)
            else:
                raise

        # If the service was not specified, get the original.
        if service is None and self.service:
            service = self.service
        else:
            return

        # Be nice to the user.
        service = service.lower()

        # Check the service is recognized.
        if not service in available_services.keys():
            raise ValueError("Invalid service provided: " + service)

        self.logger.info("Removing '{}' from service '{}'...".format(
            target, service))

        # Establish a connection with the TCC database.
        connection = self.connections[available_services[service][1]]

        # Validate that the connection was successful.
        if not connection:
            raise ValueError("Must be root to modify this service!")

        c = connection.cursor()

        # Perform the deletion.
        values = (available_services[service][0], target)
        c.execute('DELETE FROM access WHERE service IS ? AND client IS ?',
                  values)
        connection.commit()

        self.logger.info("Removed successfully.")
Ejemplo n.º 6
0
    def disable(self, target, service=None):
        """
        Mark the application or file as being disallowed from utilizing Privacy
        Services. If the target is not already in the database, it will be added
        and then disabled.

        :param target: an application or file to modify permissions for
        :param service: the service to modify
        """
        # Validate that they didn't pass us something nonexistent.
        if target is None:
            return

        # If not using admin override mode, look up a bundle identifier.
        client_type = 0
        try:
            target = AppInfo(target).bid
        except ValueError:
            if self.admin:
                target = os.path.abspath(target)
                # We'll treat this as a command line executable.
                client_type = 1
            else:
                raise

        # If the service was not specified, get the original.
        if service is None and self.service:
            service = self.service
        else:
            return

        # Be nice to the user.
        service = service.lower()

        # Check the service is recognized.
        if not service in available_services.keys():
            raise ValueError("Invalid service provided: {}".format(service))

        self.logger.info("Disabling '{}' in service '{}'...".format(
            target, service))

        # Establish a connection with the TCC database.
        connection = self.connections[available_services[service][1]]

        # Validate that the connection was successful.
        if not connection:
            raise ValueError("Must be root to modify this service!")

        c = connection.cursor()

        # Disable the application for the given service.
        # The 'prompt_count' must be 1 or else the system will ask the user
        # anyway. This is the only time it seems to really matter.
        values = (available_services[service][0], target, client_type)
        c.execute(
            'SELECT count(*) FROM access WHERE service IS ? and client IS ?',
            values[0:2])
        count = c.fetchone()[0]
        if count:
            if self.version == 12:
                c.execute(
                    'INSERT or REPLACE into access values(?, ?, ?, 0, 1)',
                    values)
            elif 15 > self.version > 12:
                c.execute(
                    'INSERT or REPLACE into access values(?, ?, ?, 0, 1, NULL)',
                    values)
            elif self.version >= 15:
                c.execute(
                    'INSERT or REPLACE into access values(?, ?, ?, 0, 1, NULL, NULL)',
                    values)
        connection.commit()

        self.logger.info("Disabled successfully.")
Ejemplo n.º 7
0
    def insert(self, target, service=None):
        """
        Enable the specified target for the given service.
        
        :param target: an application or file to modify permissions for
        :param service: a service name to modify
        """
        # Validate that they didn't pass us something nonexistent.
        if target is None:
            return

        # If not using admin override mode, look up a bundle identifier.
        client_type = 0
        try:
            target = AppInfo(target).bid
        except ValueError:
            if self.admin:
                target = os.path.abspath(target)
                # We'll treat this as a command line executable.
                client_type = 1
            else:
                raise

        # If the service was not specified, get the original.
        if service is None and self.service:
            service = self.service
        else:
            return

        # Don't beat up the user for doing something like "AcCeSsIbILITy".
        service = service.lower()

        # Check that the service is known to the program; I do not intend to
        # support unsupported services here.
        if not service in available_services.keys():
            raise ValueError("Invalid service provided: {}".format(service))

        # Version checking for the current service.
        if self.version < available_services[service][2]:
            raise RuntimeError(
                "Service '{}' does not exist on this version of OS X.".format(
                    service))

        # Proceed.
        self.logger.info("Inserting '{}' in service '{}'...".format(
            target, service))

        # Establish a connection with the TCC database.
        connection = self.connections[available_services[service][1]]

        # Clearly you tried to modify something you weren't supposed to!
        # For shame.
        if not connection:
            if os.geteuid() != 0:
                raise ValueError("Must be root to modify '{}'".format(service))
            else:
                raise ValueError("Unable to connect to '{}'".format(service))

        c = connection.cursor()

        # Add the entry!
        # Prior to OS X 10.8 (Darwin 12) there was no TCC database.
        # In OS X 10.9 (Darwin 13) Apple added a 'csreq' field.
        # In OS X 10.11 (Darwin 15) Apple added a 'policy_id' field.
        values = (available_services[service][0], target, client_type)
        if self.version == 12:
            c.execute('INSERT or REPLACE into access values(?, ?, ?, 1, 0)',
                      values)
        elif 15 > self.version > 12:
            c.execute(
                'INSERT or REPLACE into access values(?, ?, ?, 1, 0, NULL)',
                values)
        elif self.version >= 15:
            c.execute(
                'INSERT or REPLACE into access values(?, ?, ?, 1, 0, NULL, NULL)',
                values)
        connection.commit()

        self.logger.info("Inserted successfully.")
    def insert(self, target, service=None):
        """
        Enable the specified target for the given service.
        
        :param target: an application or file to modify permissions for
        :param service: a service name to modify
        """
        # Validate that they didn't pass us something nonexistent.
        if target is None:
            return

        # If not using admin override mode, look up a bundle identifier.
        if not self.admin:
            target = AppInfo(target).bid
        else:
            target = os.path.abspath(target)

        # If the service was not specified, get the original.
        if service is None and self.service:
            service = self.service
        else:
            return

        # Don't beat up the user for doing something like "AcCeSsIbILITy".
        service = service.lower()

        # Check that the service is known to the program; I do not intend to
        # support unsupported services here.
        if not service in available_services.keys():
            raise ValueError("Invalid service provided: {}".format(service))

        # Version checking for the current service.
        if self.version < available_services[service][2]:
            raise RuntimeError(
                "Service '{}' does not exist on this version of OS X.".format(
                    service))

        # Proceed.
        self.logger.info("Inserting '{}' in service '{}'...".format(
            target, service))

        # Establish a connection with the TCC database.
        connection = self.connections[available_services[service][1]]

        # Clearly you tried to modify something you weren't supposed to!
        # For shame.
        if not connection:
            if os.geteuid() != 0:
                raise ValueError("Must be root to modify '{}'".format(service))
            else:
                raise ValueError("Unable to connect to '{}'".format(service))

        c = connection.cursor()

        # Add the entry!
        # In OS X 10.9 (Darwin 12), Apple introduced a "blob". It doesn't seem
        # to be very useful since you can just give it the value "NULL" with no
        # ill effects, but it is necessary in Darwin versions 13 and greater
        # (yet it cannot be given in previous versions without raising errors).
        values = (available_services[service][0], target)
        if self.version == 12:
            c.execute('INSERT or REPLACE into access values(?, ?, 0, 1, 0)',
                      values)
        else:
            c.execute(
                'INSERT or REPLACE into access values(?, ?, 0, 1, 0, NULL)',
                values)
        connection.commit()

        self.logger.info("Inserted successfully.")