pypush-plus-plus/demo.py

185 lines
5.6 KiB
Python
Raw Normal View History

2023-05-02 07:39:11 -05:00
import getpass
import json
2023-05-02 19:53:18 -05:00
import ids
from ids import *
2023-05-02 07:39:11 -05:00
# Open config
try:
with open("config.json", "r") as f:
2023-05-02 12:40:06 -05:00
CONFIG = json.load(f)
2023-05-02 07:39:11 -05:00
except FileNotFoundError:
2023-05-02 12:40:06 -05:00
CONFIG = {}
2023-05-02 07:39:11 -05:00
2023-05-02 19:53:18 -05:00
2023-05-02 13:10:13 -05:00
def input_multiline(prompt):
print(prompt)
lines = []
while True:
line = input()
if line == "":
break
lines.append(line)
return "\n".join(lines)
2023-05-02 19:53:18 -05:00
2023-05-02 12:40:06 -05:00
def refresh_token():
# If no username is set, prompt for it
if "username" not in CONFIG:
CONFIG["username"] = input("Enter iCloud username: ")
# If no password is set, prompt for it
if "password" not in CONFIG:
CONFIG["password"] = getpass.getpass("Enter iCloud password: ")
# If grandslam authentication is not set, prompt for it
if "use_gsa" not in CONFIG:
CONFIG["use_gsa"] = input("Use grandslam authentication? [y/N] ").lower() == "y"
2023-05-02 07:39:11 -05:00
2023-05-02 12:40:06 -05:00
def factor_gen():
return input("Enter iCloud 2FA code: ")
2023-05-02 07:39:11 -05:00
2023-05-02 12:40:06 -05:00
CONFIG["user_id"], CONFIG["token"] = ids._get_auth_token(
CONFIG["username"], CONFIG["password"], CONFIG["use_gsa"], factor_gen=factor_gen
)
2023-05-02 07:39:11 -05:00
2023-05-02 19:53:18 -05:00
2023-05-02 12:40:06 -05:00
def refresh_cert():
CONFIG["key"], CONFIG["auth_cert"] = ids._get_auth_cert(
CONFIG["user_id"], CONFIG["token"]
)
2023-05-02 07:39:11 -05:00
2023-05-02 19:53:18 -05:00
def create_connection():
2023-05-02 12:40:06 -05:00
conn = apns.APNSConnection()
token = conn.connect()
2023-05-02 19:53:18 -05:00
# conn.filter(['com.apple.madrid'])
CONFIG["push"] = {
"token": b64encode(token).decode(),
"cert": conn.cert,
"key": conn.private_key,
2023-05-02 12:40:06 -05:00
}
return conn
2023-05-02 07:39:11 -05:00
2023-05-02 19:53:18 -05:00
2023-05-02 12:40:06 -05:00
def restore_connection():
2023-05-02 19:53:18 -05:00
conn = apns.APNSConnection(CONFIG["push"]["key"], CONFIG["push"]["cert"])
conn.connect(True, b64decode(CONFIG["push"]["token"]))
# conn.filter(['com.apple.madrid', 'com.apple.private.alloy.facetime.multi'])
2023-05-02 12:40:06 -05:00
return conn
2023-05-02 07:39:11 -05:00
2023-05-02 19:53:18 -05:00
def refresh_ids_cert():
2023-05-02 12:40:06 -05:00
info = {
"uri": "mailto:" + CONFIG["username"],
2023-05-02 19:53:18 -05:00
"user_id": CONFIG["user_id"],
2023-05-02 12:40:06 -05:00
}
2023-05-02 07:39:11 -05:00
2023-05-02 12:40:06 -05:00
resp = None
try:
if "validation_data" in CONFIG:
resp = ids._register_request(
2023-05-02 19:53:18 -05:00
CONFIG["push"]["token"],
2023-05-02 12:40:06 -05:00
info,
2023-05-02 19:53:18 -05:00
CONFIG["auth_cert"],
CONFIG["key"],
CONFIG["push"]["cert"],
CONFIG["push"]["key"],
2023-05-02 12:40:06 -05:00
CONFIG["validation_data"],
)
except Exception as e:
print(e)
resp = None
2023-05-02 07:39:11 -05:00
2023-05-02 12:40:06 -05:00
if resp is None:
print(
"Note: Validation data can be obtained from @JJTech, or intercepted using a HTTP proxy."
)
validation_data = (
input_multiline("Enter validation data: ")
.replace("\n", "")
.replace(" ", "")
)
2023-05-02 07:39:11 -05:00
resp = ids._register_request(
2023-05-02 19:53:18 -05:00
CONFIG["push"]["token"],
2023-05-02 07:39:11 -05:00
info,
2023-05-02 19:53:18 -05:00
CONFIG["auth_cert"],
CONFIG["key"],
CONFIG["push"]["cert"],
CONFIG["push"]["key"],
2023-05-02 12:40:06 -05:00
validation_data,
2023-05-02 07:39:11 -05:00
)
2023-05-02 12:40:06 -05:00
CONFIG["validation_data"] = validation_data
2023-05-02 07:39:11 -05:00
2023-05-02 19:53:18 -05:00
ids_cert = x509.load_der_x509_certificate(resp["services"][0]["users"][0]["cert"])
ids_cert = ids_cert.public_bytes(serialization.Encoding.PEM).decode("utf-8").strip()
2023-05-02 07:39:11 -05:00
CONFIG["ids_cert"] = ids_cert
2023-05-02 12:40:06 -05:00
2023-05-02 19:53:18 -05:00
if not "push" in CONFIG:
print("No existing APNs credentials, creating new ones...")
2023-05-02 19:53:18 -05:00
# print("No push conn")
2023-05-02 13:10:13 -05:00
conn = create_connection()
else:
print("Restoring APNs credentials...")
2023-05-02 13:10:13 -05:00
conn = restore_connection()
print("Connected to APNs!")
2023-05-02 13:10:13 -05:00
2023-05-02 19:53:18 -05:00
if not "ids_cert" in CONFIG:
print("No existing IDS certificate, creating new one...")
2023-05-02 19:53:18 -05:00
if not "key" in CONFIG:
print("No existing authentication certificate, creating new one...")
2023-05-02 19:53:18 -05:00
if not "token" in CONFIG:
print("No existing authentication token, creating new one...")
2023-05-02 12:40:06 -05:00
refresh_token()
print("Got authentication token!")
2023-05-02 12:40:06 -05:00
refresh_cert()
print("Got authentication certificate!")
refresh_ids_cert()
print("Got IDS certificate!")
2023-05-02 19:53:18 -05:00
ids_keypair = ids.KeyPair(CONFIG["key"], CONFIG["ids_cert"])
2023-05-02 19:53:18 -05:00
def lookup(topic: str, users: list[str]):
print(f"Looking up users {users} for topic {topic}...")
2023-05-02 19:53:18 -05:00
resp = ids.lookup(conn, CONFIG["username"], ids_keypair, topic, users)
2023-05-02 19:53:18 -05:00
# print(resp)
# r = list(resp['results'].values())[0]
for k, v in resp["results"].items():
print(f"Result for user {k} topic {topic}:")
2023-05-02 19:53:18 -05:00
i = v["identities"]
print(f"IDENTITIES: {len(i)}")
for iden in i:
print("IDENTITY", end=" ")
print(f"Push Token: {b64encode(iden['push-token']).decode()}", end=" ")
2023-05-02 19:53:18 -05:00
if "client-data" in iden:
print(f"Client Data: {len(iden['client-data'])}")
2023-05-02 19:53:18 -05:00
else:
print("No client data")
2023-05-02 19:53:18 -05:00
# Hack to make sure that the requests and responses match up
# This filter MUST contain all the topics you are looking up
2023-05-02 19:53:18 -05:00
# conn.filter(['com.apple.madrid', 'com.apple.private.alloy.facetime.multi', 'com.apple.private.alloy.multiplex1', 'com.apple.private.alloy.screensharing'])
# import time
# print("...waiting for queued messages... (this is a hack)")
# time.sleep(5) # Let the server send us any messages it was holding
# conn.sink() # Dump the messages
2023-05-02 19:51:51 -05:00
lookup("com.apple.madrid", ["mailto:jjtech@jjtech.dev"])
lookup("com.apple.private.alloy.facetime.multi", ["mailto:jjtech@jjtech.dev"])
2023-05-02 19:51:51 -05:00
lookup("com.apple.private.alloy.facetime.multi", ["mailto:user_test2@icloud.com"])
lookup("com.apple.madrid", ["mailto:user_test2@icloud.com"])
2023-05-02 07:39:11 -05:00
2023-05-02 19:51:51 -05:00
lookup("com.apple.private.alloy.multiplex1", ["mailto:user_test2@icloud.com"])
2023-05-02 17:36:13 -05:00
2023-05-02 19:51:02 -05:00
lookup("com.apple.private.alloy.screensharing", ["mailto:user_test2@icloud.com"])
2023-05-02 19:53:18 -05:00
# time.sleep(4)
2023-05-02 07:39:11 -05:00
# Save config
with open("config.json", "w") as f:
2023-05-02 19:53:18 -05:00
json.dump(CONFIG, f, indent=4)