Exemplo n.º 1
0
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
Exemplo n.º 2
0
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
Exemplo n.º 4
0
    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'],
        )
Exemplo n.º 5
0
    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),
            )
Exemplo n.º 6
0
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)