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.")
def main(args): for item in args[1:]: try: info = AppInfo(item) except ValueError, e: info = "Invalid application: '" + item + "'" print info
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.")
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.")
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.")