def authenticate( username, password, cookie_directory=None, raise_error_on_2sa=False, client_id=None ): """Authenticate with iCloud username and password""" logger = setup_logger() logger.debug("Authenticating...") try: # If password not provided on command line variable will be set to None # and PyiCloud will attempt to retrieve from it's keyring icloud = pyicloud.PyiCloudService( username, password, cookie_directory=cookie_directory, client_id=client_id) except pyicloud.exceptions.NoStoredPasswordAvailable: # Prompt for password if not stored in PyiCloud's keyring password = click.prompt("iCloud Password", hide_input=True) icloud = pyicloud.PyiCloudService( username, password, cookie_directory=cookie_directory, client_id=client_id) if icloud.requires_2sa: if raise_error_on_2sa: raise TwoStepAuthRequiredError( "Two-step/two-factor authentication is required!" ) logger.info("Two-step/two-factor authentication is required!") request_2sa(icloud, logger) return icloud
def authenticate(username, password, \ smtp_username, smtp_password, smtp_host, smtp_port, smtp_no_tls, \ notification_email): try: # If password not provided on command line variable will be set to None # and PyiCloud will attempt to retrieve from it's keyring icloud = pyicloud.PyiCloudService(username, password) except pyicloud.exceptions.NoStoredPasswordAvailable: # Prompt for password if not stored in PyiCloud's keyring password = getpass.getpass() icloud = pyicloud.PyiCloudService(username, password) if icloud.requires_2sa: if smtp_username and smtp_password: # If running in the background, send a notification email. send_two_step_expired_notification(smtp_username, smtp_password, \ smtp_host, smtp_port, smtp_no_tls, notification_email) exit() print("Two-step/two-factor authentication is required.") devices = icloud.trusted_devices devices_count = len(devices) if devices_count == 0: device_index = 0 else: for i, device in enumerate(devices): print(" %s: %s" % (i, device.get('deviceName', "SMS to %s" % device.get('phoneNumber')))) print(" %s: Enter two-factor authentication code" % devices_count) device_index = click.prompt('Please choose an option:', default=0, type=click.IntRange(0, devices_count)) if device_index == devices_count: # We're using the 2FA code that was automatically sent to the user's device, # so can just use an empty dict() device = dict() else: device = devices[device_index] if not icloud.send_verification_code(device): print("Failed to send two-factor authentication code") sys.exit(1) code = click.prompt('Please enter two-factor authentication code') if not icloud.validate_verification_code(device, code): print("Failed to verify two-factor authentication code") sys.exit(1) print( "Great, you're all set up. The script can now be run without user interaction." ) print( "You can also set up email notifications for when the two-step authentication expires." ) print("(Use --help to view information about SMTP options.)") return icloud
def authenticate(username, password): print("Signing in...") icloud = pyicloud.PyiCloudService(username, password) if icloud.requires_2sa: print("Two-factor authentication required. Your trusted devices are:") devices = icloud.trusted_devices for i, device in enumerate(devices): print(" %s: %s" % (i, device.get('deviceName', "SMS to %s" % device.get('phoneNumber')))) device = click.prompt('Which device would you like to use?', default=0) device = devices[device] if not icloud.send_verification_code(device): print("Failed to send verification code") sys.exit(1) code = click.prompt('Please enter validation code') if not icloud.validate_verification_code(device, code): print("Failed to verify verification code") sys.exit(1) return icloud
def get_location_data(self): api = pyicloud.PyiCloudService( self.user_settings.icloud_username, self.user_settings.icloud_password, ) started = time.time() while time.time() - started < SETTINGS['icloud']['max_wait_seconds']: try: device = api.devices[self.user_settings.icloud_device_id] except KeyError: raise UnknownDeviceException( 'Device %s not found.' % (self.user_settings.icloud_device_id, )) data = device.location() logger.debug( 'Gathered data %s from device %s.', data, self.user_settings.icloud_device_id, ) if self.data_is_accurate(data): return data time.sleep(SETTINGS['icloud']['request_interval_seconds']) raise LocationUnavailableException( 'Unable to acquire location of device %s within %s seconds', api.devices[self.user_settings.icloud_device_id], SETTINGS['icloud']['max_wait_seconds'], )
def handle(self, *args, **kwargs): icloud_username = args[0] icloud_password = args[1] api = pyicloud.PyiCloudService(icloud_username, icloud_password) for id, device in api.devices.items(): print 'Name: %s -- ID: %s' % ( str(device), str(id), )
def main(args=None): """Main commandline entrypoint""" if args is None: args = sys.argv[1:] parser = argparse.ArgumentParser( description="Find My iPhone CommandLine Tool") parser.add_argument("--username", action="store", dest="username", default="", help="Apple ID to Use") parser.add_argument( "--password", action="store", dest="password", default="", help=("Apple ID Password to Use; if unspecified, password will be " "fetched from the system keyring.")) parser.add_argument("-n", "--non-interactive", action="store_false", dest="interactive", default=True, help="Disable interactive prompts.") parser.add_argument( "--delete-from-keyring", action="store_true", dest="delete_from_keyring", default=False, help="Delete stored password in system keyring for this username.", ) parser.add_argument( "--list", action="store_true", dest="list", default=False, help="Short Listings for Device(s) associated with account", ) parser.add_argument( "--llist", action="store_true", dest="longlist", default=False, help="Detailed Listings for Device(s) associated with account", ) parser.add_argument( "--locate", action="store_true", dest="locate", default=False, help="Retrieve Location for the iDevice (non-exclusive).", ) # Restrict actions to a specific devices UID / DID parser.add_argument( "--device", action="store", dest="device_id", default=False, help="Only effect this device", ) # Trigger Sound Alert parser.add_argument( "--sound", action="store_true", dest="sound", default=False, help="Play a sound on the device", ) # Trigger Message w/Sound Alert parser.add_argument( "--message", action="store", dest="message", default=False, help="Optional Text Message to display with a sound", ) # Trigger Message (without Sound) Alert parser.add_argument( "--silentmessage", action="store", dest="silentmessage", default=False, help="Optional Text Message to display with no sounds", ) # Lost Mode parser.add_argument( "--lostmode", action="store_true", dest="lostmode", default=False, help="Enable Lost mode for the device", ) parser.add_argument( "--lostphone", action="store", dest="lost_phone", default=False, help="Phone Number allowed to call when lost mode is enabled", ) parser.add_argument( "--lostpassword", action="store", dest="lost_password", default=False, help="Forcibly active this passcode on the idevice", ) parser.add_argument( "--lostmessage", action="store", dest="lost_message", default="", help="Forcibly display this message when activating lost mode.", ) # Output device data to an pickle file parser.add_argument( "--outputfile", action="store_true", dest="output_to_file", default="", help="Save device data to a file in the current directory.", ) command_line = parser.parse_args(args) username = command_line.username password = command_line.password if username and command_line.delete_from_keyring: utils.delete_password_in_keyring(username) failure_count = 0 while True: # Which password we use is determined by your username, so we # do need to check for this first and separately. if not username: parser.error('No username supplied') if not password: password = utils.get_password(username, interactive=command_line.interactive) if not password: parser.error('No password supplied') try: api = pyicloud.PyiCloudService(username.strip(), password.strip()) if (not utils.password_exists_in_keyring(username) and command_line.interactive and confirm("Save password in keyring? ")): utils.store_password_in_keyring(username, password) break except pyicloud.exceptions.PyiCloudFailedLoginException: # If they have a stored password; we just used it and # it did not work; let's delete it if there is one. if utils.password_exists_in_keyring(username): utils.delete_password_in_keyring(username) message = "Bad username or password for {username}".format( username=username, ) password = None failure_count += 1 if failure_count >= 3: raise RuntimeError(message) print(message, file=sys.stderr) for dev in api.devices: if (not command_line.device_id or (command_line.device_id.strip().lower() == dev.content["id"].strip().lower())): # List device(s) if command_line.locate: dev.location() if command_line.output_to_file: create_pickled_data( dev, filename=(dev.content["name"].strip().lower() + ".fmip_snapshot")) contents = dev.content if command_line.longlist: print("-" * 30) print(contents["name"]) for x in contents: print("%20s - %s" % (x, contents[x])) elif command_line.list: print("-" * 30) print("Name - %s" % contents["name"]) print("Display Name - %s" % contents["deviceDisplayName"]) print("Location - %s" % contents["location"]) print("Battery Level - %s" % contents["batteryLevel"]) print("Battery Status- %s" % contents["batteryStatus"]) print("Device Class - %s" % contents["deviceClass"]) print("Device Model - %s" % contents["deviceModel"]) # Play a Sound on a device if command_line.sound: if command_line.device_id: dev.play_sound() else: raise RuntimeError( "\n\n\t\t%s %s\n\n" % ("Sounds can only be played on a singular device.", DEVICE_ERROR)) # Display a Message on the device if command_line.message: if command_line.device_id: dev.display_message(subject='A Message', message=command_line.message, sounds=True) else: raise RuntimeError("%s %s" % ("Messages can only be played " "on a singular device.", DEVICE_ERROR)) # Display a Silent Message on the device if command_line.silentmessage: if command_line.device_id: dev.display_message(subject='A Silent Message', message=command_line.silentmessage, sounds=False) else: raise RuntimeError("%s %s" % ("Silent Messages can only be played " "on a singular device.", DEVICE_ERROR)) # Enable Lost mode if command_line.lostmode: if command_line.device_id: dev.lost_device( number=command_line.lost_phone.strip(), text=command_line.lost_message.strip(), newpasscode=command_line.lost_password.strip()) else: raise RuntimeError("%s %s" % ("Lost Mode can only be activated " "on a singular device.", DEVICE_ERROR))
monitor_devices = [] for device_to_monitor in devices_to_monitor: name_and_url = device_to_monitor.split(',') monitor_device = MonitorDevice(name_and_url[0], name_and_url[1]) monitor_device.set_home_period(low_updates_when_home_timespan) monitor_devices.append(monitor_device) MonitorDevice.set_logger(logger) MonitorDevice.set_send_to_server(send_to_server) sleep_time = MIN_SLEEP_TIME icloud = None while keep_running: try: if icloud is None: icloud = pyicloud.PyiCloudService(apple_id, apple_password, "~/.iCloudLocationFetcher") if icloud.requires_2sa: logger.error( "Two-step authentication required. Please run twostep.py" ) sleep_time = ACTION_NEEDED_ERROR_SLEEP_TIME icloud = None else: sleep_time = MIN_SLEEP_TIME icloud_devices = icloud.devices # set corresponding devices for monitor_device in monitor_devices: logger.info("Searching for '%s' in iCloud devices" % monitor_device.name) apple_device = get_apple_device( icloud_devices, monitor_device.name)