def connect_to_icloud( self, config: Dict[str, Union[str, bool, None]]) -> PyiCloudService: self.logger.info("Connecting to iCloud…") if config["password"] == "": api = PyiCloudService(config["username"]) else: api = PyiCloudService(config["username"], config["password"]) if api.requires_2sa: print("Two-step authentication required.") if click.confirm( "Have you received authentication request on any of your devices?" ): verification_function = lambda code: api.validate_2fa_code(code ) else: print("Fallback to SMS verification.") print("Your trusted devices are:") devices = api.trusted_devices for i, device in enumerate(devices): print(" {}: {}".format( i, device.get( "deviceName", "SMS to {}".format(device.get("phoneNumber")), ), )) device = click.prompt("Which device would you like to use?", default=0) device = devices[device] if not api.send_verification_code(device): raise Exception("Failed to send verification code") verification_function = lambda code: api.validate_verification_code( device, code) verified = False while not verified: code = click.prompt("Please enter validation code") verified = verification_function(code) self.logger.debug("Verification result: %s", verified) if verified: print("Succeed") else: print( "Failed to verify verification code, retry (Ctrl-C to cancel)" ) return api
def authenticate(username, password): """attempt to authenticate user using provided credentials""" api = PyiCloudService(username, password) if api.requires_2fa: print("Two-factor authentication required.") code = input( "Enter the code you received of one of your approved devices: ") result = api.validate_2fa_code(code) print("Code validation result: %s" % result) if not result: print("Failed to verify security code") sys.exit(1) if not api.is_trusted_session: print("Session is not trusted. Requesting trust...") result = api.trust_session() print("Session trust result %s" % result) if not result: print( "Failed to request trust. You will likely be prompted for the code again in the coming weeks" ) elif api.requires_2sa: import click print("Two-step authentication required. Your trusted devices are:") devices = api.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 api.send_verification_code(device): print("Failed to send verification code") sys.exit(1) code = click.prompt('Please enter validation code') if not api.validate_verification_code(device, code): print("Failed to verify verification code") sys.exit(1) return api
def login(self, username, password): api = PyiCloudService(username, password) if api.requires_2fa: logging.info( f"ICloud with mail {username} required Two-factor authentication!" ) result = api.validate_2fa_code(self.__get_2fa_code()) if not result: logging.critical( f"Failed to verify security code of ICloud-Account with mail {username}" ) self.connected = False if not api.is_trusted_session: logging.info( f"Session for mail, {username} is not trusted. Requesting trust..." ) result = api.trust_session() print(f"Session trust for mail {username} result '{result}'") if not result: logging.critical( "Failed to request trust. You will likely be prompted for the code again in the coming weeks!" ) self.connected = False elif api.requires_2sa: import click devices = api.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 api.send_verification_code(device): logging.critical("Failed to send verification code") code = click.prompt('Please enter validation code') if not api.validate_verification_code(device, code): logging.critical("Failed to verify verification code!") self.connected = False return api
class iCloud: def __init__(self): creds = self.__load_creds(os.getcwd() + "/Secrets.txt") self.api = PyiCloudService(creds[0], creds[1]) self.__two_factor_routine() self.phone = self.Phone() self.update_phone() self.lats, self.longs = self.__load_location() def __load_location(self): with open("location.txt", "r") as f: temp = f.readlines() out = [] for i in temp: i = i.strip() i = i.split(",") out.append([float(j) for j in i]) return out[0], out[1] def update_phone(self): _phone = self.api.devices[1] status = _phone.status() self.phone.update(_phone.content, status) def __load_creds(self, path): with open(path, "r") as f: creds = f.readlines() return [i.strip() for i in creds] # Not my code. This was ripped from pycloud docs. def __two_factor_routine(self): if self.api.requires_2fa: print("Two-factor authentication required.") code = input( "Enter the code you received of one of your approved devices: " ) result = self.api.validate_2fa_code(code) print("Code validation result: %s" % result) if not result: print("Failed to verify security code") sys.exit(1) if not self.api.is_trusted_session: print("Session is not trusted. Requesting trust...") result = self.api.trust_session() print("Session trust result %s" % result) if not result: print( "Failed to request trust. You will likely be prompted for the code again in the coming weeks" ) elif self.api.requires_2sa: import click print( "Two-step authentication required. Your trusted devices are:") devices = self.api.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 self.api.send_verification_code(device): print("Failed to send verification code") sys.exit(1) code = click.prompt('Please enter validation code') if not self.api.validate_verification_code(device, code): print("Failed to verify verification code") sys.exit(1) def is_charging(self): first = self.api.devices[1].status()["batteryLevel"] count = 0 while True: time.sleep(20) second = self.api.devices[1].status()["batteryLevel"] print("First {} --> Second {}".format(first, second)) if second != first: break count += 1 if second - first > 0.0: return True else: return False def is_home(self): lat_fence = self.lats long_fence = self.longs lat_check = self.phone.location[0] > lat_fence[ 0] and self.phone.location[0] < lat_fence[1] long_check = self.phone.location[1] < long_fence[ 0] and self.phone.location[1] > long_fence[1] return lat_check and long_check class Phone: def __init__(self): self.battery = 0.0 self.location = [] self.id = "" self.timestamp = None def update(self, content, status): self.timestamp = datetime.datetime.now() self.battery = status["batteryLevel"] self.id = content["id"] lat = content["location"]["latitude"] long = content["location"]["longitude"] self.location = [lat, long]
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 = 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) if api.requires_2fa: # fmt: off print( "\nTwo-step authentication required.", "\nPlease enter validation code" ) # fmt: on code = input("(string) --> ") if not api.validate_2fa_code(code): print("Failed to verify verification code") sys.exit(1) print("") elif api.requires_2sa: # fmt: off print( "\nTwo-step authentication required.", "\nYour trusted devices are:" ) # fmt: on devices = api.trusted_devices for i, device in enumerate(devices): print( " %s: %s" % ( i, device.get( "deviceName", "SMS to %s" % device.get("phoneNumber") ), ) ) print("\nWhich device would you like to use?") device = int(input("(number) --> ")) device = devices[device] if not api.send_verification_code(device): print("Failed to send verification code") sys.exit(1) print("\nPlease enter validation code") code = input("(string) --> ") if not api.validate_verification_code(device, code): print("Failed to verify verification code") sys.exit(1) print("") break except 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 key in contents: print("%20s - %s" % (key, contents[key])) 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, ) ) sys.exit(0)
appleid_email = '' appleid_password = '' lostmode_phonenumber = '' lostmode_message = '' from pyicloud import PyiCloudService #api = PyiCloudService(appleid_email, appleid_password) api = PyiCloudService(appleid_email, appleid_password) if api.requires_2fa: print("Two-factor authentication required.") code = input( "Enter the code you received of one of your approved devices: ") result = api.validate_2fa_code(code) print("Code validation result: %s" % result) if not result: print("Failed to verify security code") sys.exit(1) if not api.is_trusted_session: print("Session is not trusted. Requesting trust...") result = api.trust_session() print("Session trust result %s" % result) if not result: print( "Failed to request trust. You will likely be prompted for the code again in the coming weeks" ) elif api.requires_2sa: import click