Source code for rpcclient.ios.lockdown

import platform
import plistlib
import posixpath
import uuid
from datetime import datetime, timedelta
from typing import List, Mapping

from rpcclient.darwin.scpreferences import SCPreference

PAIR_RECORD_PATH = '/var/root/Library/Lockdown/pair_records'
DATA_ARK_PATH = '/var/root/Library/Lockdown/data_ark.plist'
FAR_FUTURE_DATE = datetime(9999, 1, 1)


[docs] class PairRecord: def __init__(self, client, host_id: str): self._client = client self._host_id = host_id @property def host_id(self) -> str: return self._host_id @property def record(self) -> Mapping: return plistlib.loads(self._client.fs.read_file(posixpath.join(PAIR_RECORD_PATH, f'{self._host_id}.plist'))) @property def date(self) -> datetime: return self._client.lockdown.pair_dates.get(self._host_id) @date.setter def date(self, value: datetime): self._client.lockdown.set_pair_date(self._host_id, value) @property def expiration_date(self) -> datetime: return self.date + timedelta(days=30)
[docs] def disable_expiration(self): self.date = FAR_FUTURE_DATE
def __repr__(self) -> str: return f'<{self.__class__.__name__} HOST_ID:{self.host_id} EXPIRATION:{self.expiration_date}>'
[docs] class Lockdown: def __init__(self, client): self._client = client
[docs] @staticmethod def get_host_id(hostname: str = None) -> str: hostname = platform.node() if hostname is None else hostname host_id = uuid.uuid3(uuid.NAMESPACE_DNS, hostname) return str(host_id).upper()
@property def pair_records(self) -> List[PairRecord]: """ list pair records """ result = [] for filename in self._client.fs.listdir(PAIR_RECORD_PATH): result.append(PairRecord(self._client, filename.split('.')[0])) return result @property def pair_dates(self) -> Mapping: result = {} raw = self._client.preferences.cf.get_dict('com.apple.mobile.ldpair', 'mobile', 'kCFPreferencesAnyHost') for host_id, timestmap in raw.items(): result[host_id] = datetime.fromtimestamp(timestmap) return result @property def data_ark(self) -> SCPreference: return self._client.preferences.sc.open(DATA_ARK_PATH)
[docs] def set_pair_date(self, host_id: str, date: datetime): self._client.preferences.cf.set(host_id, int(date.timestamp()), 'com.apple.mobile.ldpair', 'mobile', 'kCFPreferencesAnyHost')
[docs] def get_pair_record_by_host_id(self, host_id: str) -> PairRecord: return PairRecord(self._client, host_id)
[docs] def get_pair_record_by_hostname(self, hostname: str) -> PairRecord: return PairRecord(self._client, self.get_host_id(hostname))
[docs] def get_self_pair_record(self) -> PairRecord: return self.get_pair_record_by_host_id(self.get_host_id())
[docs] def add_pair_record(self, pair_record: Mapping, date: datetime, hostname: str = None): pair_record = dict(pair_record) # remove private key from pair record before adding it pair_record.pop('HostPrivateKey') host_id = self.get_host_id(hostname) self._client.fs.write_file(posixpath.join(PAIR_RECORD_PATH, f'{host_id}.plist'), plistlib.dumps(pair_record)) self.set_pair_date(host_id, date)
[docs] def disable_expiration_for_all_existing_pair_records(self): for record in self.pair_records: record.disable_expiration()