more changes, including ability to look up facetime keys

This commit is contained in:
JJTech0130 2023-05-02 16:36:50 -04:00
parent ff20a7cb49
commit d8fc26bcb2
No known key found for this signature in database
GPG key ID: 23C92EBCCF8F93D6
2 changed files with 41 additions and 31 deletions

44
demo.py
View file

@ -46,7 +46,7 @@ def refresh_cert():
def create_connection():
conn = apns.APNSConnection()
token = conn.connect()
conn.filter(['com.apple.madrid'])
#conn.filter(['com.apple.madrid'])
CONFIG['push'] = {
'token': b64encode(token).decode(),
'cert': conn.cert,
@ -57,10 +57,10 @@ def create_connection():
def restore_connection():
conn = apns.APNSConnection(CONFIG['push']['key'], CONFIG['push']['cert'])
conn.connect(True, b64decode(CONFIG['push']['token']))
conn.filter(['com.apple.madrid'])
#conn.filter(['com.apple.madrid', 'com.apple.private.alloy.facetime.multi'])
return conn
def refresh_madrid_cert():
def refresh_ids_cert():
info = {
"uri": "mailto:" + CONFIG["username"],
"user_id": CONFIG['user_id'],
@ -102,38 +102,44 @@ def refresh_madrid_cert():
)
CONFIG["validation_data"] = validation_data
madrid_cert = x509.load_der_x509_certificate(
ids_cert = x509.load_der_x509_certificate(
resp["services"][0]["users"][0]["cert"]
)
madrid_cert = (
madrid_cert.public_bytes(serialization.Encoding.PEM).decode("utf-8").strip()
ids_cert = (
ids_cert.public_bytes(serialization.Encoding.PEM).decode("utf-8").strip()
)
CONFIG["madrid_cert"] = madrid_cert
CONFIG["ids_cert"] = ids_cert
if not 'push' in CONFIG:
print("No push conn")
print("No existing APNs credentials, creating new ones...")
#print("No push conn")
conn = create_connection()
else:
print("restoring push conn")
print("Restoring APNs credentials...")
conn = restore_connection()
print("Connected to APNs!")
if not 'madrid_cert' in CONFIG:
print("No madrid cert")
if not 'ids_cert' in CONFIG:
print("No existing IDS certificate, creating new one...")
if not 'key' in CONFIG:
print("No auth cert")
print("No existing authentication certificate, creating new one...")
if not 'token' in CONFIG:
print("No auth token")
print("No existing authentication token, creating new one...")
refresh_token()
print("Got authentication token!")
refresh_cert()
refresh_madrid_cert()
print("Got new madrid cert")
print("Doing lookup")
print(ids.lookup(conn, ['mailto:jjtech@jjtech.dev'], (CONFIG['key'], CONFIG['madrid_cert']), CONFIG['username']))
print("Got authentication certificate!")
refresh_ids_cert()
print("Got IDS certificate!")
print("Done")
# This is the actual lookup!
print("Looking up user...")
ids_keypair = ids.KeyPair(CONFIG['key'], CONFIG['ids_cert'])
resp = ids.lookup(conn, CONFIG['username'], ids_keypair, 'com.apple.madrid', ['mailto:textgpt@icloud.com'])
print("Got response!")
print(resp)
# Save config
with open("config.json", "w") as f:

28
ids.py
View file

@ -11,17 +11,15 @@ from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from cryptography.x509.oid import NameOID
from collections import namedtuple
import apns
import bags
import gsa
USER_AGENT = "com.apple.madrid-lookup [macOS,13.2.1,22D68,MacBookPro18,3]"
# NOTE: The push token MUST be registered with the account for self-uri!
# This is an actual valid one for my account, since you can look it up anyway.
#PUSH_TOKEN = "5V7AY+ikHr4DiSfq1W2UBa71G3FLGkpUSKTrOLg81yk="
#SELF_URI = "mailto:jjtech@jjtech.dev"
KeyPair = namedtuple("KeyPair", ["key", "cert"])
# Nonce Format:
# 01000001876bd0a2c0e571093967fce3d7
@ -80,17 +78,16 @@ def sign_payload(
# global_key, global_cert = load_keys()
def _send_request(conn: apns.APNSConnection, bag_key: str, body: bytes, id_key: str, id_cert, username: str) -> bytes:
def _send_request(conn: apns.APNSConnection, bag_key: str, topic: str, body: bytes, keypair: KeyPair, username: str) -> bytes:
body = zlib.compress(body, wbits=16 + zlib.MAX_WBITS)
push_token = b64encode(conn.token).decode()
# Sign the request
signature, nonce = sign_payload(id_key, bag_key, "", push_token, body)
signature, nonce = sign_payload(keypair.key, bag_key, "", push_token, body)
headers = {
"x-id-cert": id_cert.replace("-----BEGIN CERTIFICATE-----", "")
"x-id-cert": keypair.cert.replace("-----BEGIN CERTIFICATE-----", "")
.replace("-----END CERTIFICATE-----", "")
.replace("\n", ""),
"x-id-nonce": b64encode(nonce).decode(),
@ -101,7 +98,7 @@ def _send_request(conn: apns.APNSConnection, bag_key: str, body: bytes, id_key:
"x-protocol-version": "1630",
}
print(headers)
#print(headers)
req = {
"cT": "application/x-apple-plist",
@ -114,7 +111,7 @@ def _send_request(conn: apns.APNSConnection, bag_key: str, body: bytes, id_key:
"b": body,
}
conn.send_message("com.apple.madrid", plistlib.dumps(req, fmt=plistlib.FMT_BINARY))
conn.send_message(topic, plistlib.dumps(req, fmt=plistlib.FMT_BINARY))
resp = conn.wait_for_packet(0x0A)
resp_body = apns._get_field(resp[1], 3)
@ -125,9 +122,16 @@ def _send_request(conn: apns.APNSConnection, bag_key: str, body: bytes, id_key:
return resp_body
def lookup(conn: apns.APNSConnection, query: list[str], id_pair: tuple[str, str], self_user: str) -> any:
# Performs an IDS lookup
# conn: an active APNs connection. must be connected and have a push token. will be filtered to the IDS topic
# self: the user's email address
# keypair: a KeyPair object containing the user's private key and certificate
# topic: the IDS topic to query
# query: a list of URIs to query
def lookup(conn: apns.APNSConnection, self: str, keypair: KeyPair, topic: str, query: list[str]) -> any:
conn.filter([topic])
query = {"uris": query}
resp = _send_request(conn, "id-query", plistlib.dumps(query), id_pair[0], id_pair[1], self_user)
resp = _send_request(conn, "id-query", topic, plistlib.dumps(query), keypair, self)
resp = plistlib.loads(resp)
resp = zlib.decompress(resp["b"], 16 + zlib.MAX_WBITS)
resp = plistlib.loads(resp)