mirror of
https://github.com/Sneed-Group/pypush-plus-plus
synced 2024-12-24 03:42:43 -06:00
more changes, including ability to look up facetime keys
This commit is contained in:
parent
ff20a7cb49
commit
d8fc26bcb2
2 changed files with 41 additions and 31 deletions
44
demo.py
44
demo.py
|
@ -46,7 +46,7 @@ def refresh_cert():
|
||||||
def create_connection():
|
def create_connection():
|
||||||
conn = apns.APNSConnection()
|
conn = apns.APNSConnection()
|
||||||
token = conn.connect()
|
token = conn.connect()
|
||||||
conn.filter(['com.apple.madrid'])
|
#conn.filter(['com.apple.madrid'])
|
||||||
CONFIG['push'] = {
|
CONFIG['push'] = {
|
||||||
'token': b64encode(token).decode(),
|
'token': b64encode(token).decode(),
|
||||||
'cert': conn.cert,
|
'cert': conn.cert,
|
||||||
|
@ -57,10 +57,10 @@ def create_connection():
|
||||||
def restore_connection():
|
def restore_connection():
|
||||||
conn = apns.APNSConnection(CONFIG['push']['key'], CONFIG['push']['cert'])
|
conn = apns.APNSConnection(CONFIG['push']['key'], CONFIG['push']['cert'])
|
||||||
conn.connect(True, b64decode(CONFIG['push']['token']))
|
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
|
return conn
|
||||||
|
|
||||||
def refresh_madrid_cert():
|
def refresh_ids_cert():
|
||||||
info = {
|
info = {
|
||||||
"uri": "mailto:" + CONFIG["username"],
|
"uri": "mailto:" + CONFIG["username"],
|
||||||
"user_id": CONFIG['user_id'],
|
"user_id": CONFIG['user_id'],
|
||||||
|
@ -102,38 +102,44 @@ def refresh_madrid_cert():
|
||||||
)
|
)
|
||||||
CONFIG["validation_data"] = validation_data
|
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"]
|
resp["services"][0]["users"][0]["cert"]
|
||||||
)
|
)
|
||||||
madrid_cert = (
|
ids_cert = (
|
||||||
madrid_cert.public_bytes(serialization.Encoding.PEM).decode("utf-8").strip()
|
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:
|
if not 'push' in CONFIG:
|
||||||
print("No push conn")
|
print("No existing APNs credentials, creating new ones...")
|
||||||
|
#print("No push conn")
|
||||||
conn = create_connection()
|
conn = create_connection()
|
||||||
else:
|
else:
|
||||||
print("restoring push conn")
|
print("Restoring APNs credentials...")
|
||||||
conn = restore_connection()
|
conn = restore_connection()
|
||||||
|
print("Connected to APNs!")
|
||||||
|
|
||||||
if not 'madrid_cert' in CONFIG:
|
if not 'ids_cert' in CONFIG:
|
||||||
print("No madrid cert")
|
print("No existing IDS certificate, creating new one...")
|
||||||
if not 'key' in CONFIG:
|
if not 'key' in CONFIG:
|
||||||
print("No auth cert")
|
print("No existing authentication certificate, creating new one...")
|
||||||
if not 'token' in CONFIG:
|
if not 'token' in CONFIG:
|
||||||
print("No auth token")
|
print("No existing authentication token, creating new one...")
|
||||||
refresh_token()
|
refresh_token()
|
||||||
|
print("Got authentication token!")
|
||||||
refresh_cert()
|
refresh_cert()
|
||||||
refresh_madrid_cert()
|
print("Got authentication certificate!")
|
||||||
print("Got new madrid cert")
|
refresh_ids_cert()
|
||||||
print("Doing lookup")
|
print("Got IDS certificate!")
|
||||||
print(ids.lookup(conn, ['mailto:jjtech@jjtech.dev'], (CONFIG['key'], CONFIG['madrid_cert']), CONFIG['username']))
|
|
||||||
|
|
||||||
|
# This is the actual lookup!
|
||||||
print("Done")
|
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
|
# Save config
|
||||||
with open("config.json", "w") as f:
|
with open("config.json", "w") as f:
|
||||||
|
|
28
ids.py
28
ids.py
|
@ -11,17 +11,15 @@ from cryptography.hazmat.backends import default_backend
|
||||||
from cryptography.hazmat.primitives import hashes, serialization
|
from cryptography.hazmat.primitives import hashes, serialization
|
||||||
from cryptography.hazmat.primitives.asymmetric import padding, rsa
|
from cryptography.hazmat.primitives.asymmetric import padding, rsa
|
||||||
from cryptography.x509.oid import NameOID
|
from cryptography.x509.oid import NameOID
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
import apns
|
import apns
|
||||||
import bags
|
import bags
|
||||||
import gsa
|
import gsa
|
||||||
|
|
||||||
USER_AGENT = "com.apple.madrid-lookup [macOS,13.2.1,22D68,MacBookPro18,3]"
|
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:
|
# Nonce Format:
|
||||||
# 01000001876bd0a2c0e571093967fce3d7
|
# 01000001876bd0a2c0e571093967fce3d7
|
||||||
|
@ -80,17 +78,16 @@ def sign_payload(
|
||||||
|
|
||||||
# global_key, global_cert = load_keys()
|
# global_key, global_cert = load_keys()
|
||||||
|
|
||||||
|
def _send_request(conn: apns.APNSConnection, bag_key: str, topic: str, body: bytes, keypair: KeyPair, username: str) -> bytes:
|
||||||
def _send_request(conn: apns.APNSConnection, bag_key: str, body: bytes, id_key: str, id_cert, username: str) -> bytes:
|
|
||||||
body = zlib.compress(body, wbits=16 + zlib.MAX_WBITS)
|
body = zlib.compress(body, wbits=16 + zlib.MAX_WBITS)
|
||||||
|
|
||||||
push_token = b64encode(conn.token).decode()
|
push_token = b64encode(conn.token).decode()
|
||||||
|
|
||||||
# Sign the request
|
# 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 = {
|
headers = {
|
||||||
"x-id-cert": id_cert.replace("-----BEGIN CERTIFICATE-----", "")
|
"x-id-cert": keypair.cert.replace("-----BEGIN CERTIFICATE-----", "")
|
||||||
.replace("-----END CERTIFICATE-----", "")
|
.replace("-----END CERTIFICATE-----", "")
|
||||||
.replace("\n", ""),
|
.replace("\n", ""),
|
||||||
"x-id-nonce": b64encode(nonce).decode(),
|
"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",
|
"x-protocol-version": "1630",
|
||||||
}
|
}
|
||||||
|
|
||||||
print(headers)
|
#print(headers)
|
||||||
|
|
||||||
req = {
|
req = {
|
||||||
"cT": "application/x-apple-plist",
|
"cT": "application/x-apple-plist",
|
||||||
|
@ -114,7 +111,7 @@ def _send_request(conn: apns.APNSConnection, bag_key: str, body: bytes, id_key:
|
||||||
"b": body,
|
"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 = conn.wait_for_packet(0x0A)
|
||||||
|
|
||||||
resp_body = apns._get_field(resp[1], 3)
|
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
|
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}
|
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 = plistlib.loads(resp)
|
||||||
resp = zlib.decompress(resp["b"], 16 + zlib.MAX_WBITS)
|
resp = zlib.decompress(resp["b"], 16 + zlib.MAX_WBITS)
|
||||||
resp = plistlib.loads(resp)
|
resp = plistlib.loads(resp)
|
||||||
|
|
Loading…
Reference in a new issue