1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
| import uuid import base64 import plistlib
from absl import app from absl import flags
FLAGS = flags.FLAGS
flags.DEFINE_string("profile_rdns", None, "Not displayed, but can be used to replace old profile.") flags.DEFINE_string("vpn_rdns", None, "Not displayed. Can be arbitrary string.") flags.DEFINE_string("client_cert_rdns", None, "Not displayed. Can be arbitrary string.") flags.DEFINE_string("ca_cert_rdns", None, "Not displayed. Can be arbitrary string.")
flags.DEFINE_string("profile_display_name", None, "Arbitrary descriptive name.") flags.DEFINE_string("vpn_display_name", None, "Arbitrary descriptive name.") flags.DEFINE_string("client_cert_display_name", None, "Arbitrary descriptive name.") flags.DEFINE_string("client_cert_file_name", None, "Arbitrary descriptive name.") flags.DEFINE_string("ca_cert_display_name", None, "Arbitrary descriptive name.") flags.DEFINE_string("vpn_profile_name", None, "Arbitrary descriptive name.")
flags.DEFINE_string("server_addr", None, "Domain name of the server.") flags.DEFINE_string("server_id", None, "Remote id. iOS always send this as FQDN type.")
flags.DEFINE_string("client_cert_p12_file", None, "Client cert p12 file.") flags.DEFINE_string("client_cert_p12_pwd", None, "Password for client p12 cert.") flags.DEFINE_string("client_id", None, "Client's ID to be sent to the server. iOS always send this as FQDN type.")
flags.DEFINE_string("ca_cert_pem_file", None, "CA cert file, not p12 format.") flags.DEFINE_string("ca_common_name", None, "CA's Common name. iOS will send a CERTREQ iff this value MATCHES the CA's common name")
flags.DEFINE_bool("always_on_wifi", False, "Setup on-demand rules to always connect on WiFi")
flags.mark_flag_as_required("profile_rdns") flags.mark_flag_as_required("vpn_rdns") flags.mark_flag_as_required("client_cert_rdns") flags.mark_flag_as_required("ca_cert_rdns")
flags.mark_flag_as_required("profile_display_name") flags.mark_flag_as_required("vpn_display_name") flags.mark_flag_as_required("client_cert_display_name") flags.mark_flag_as_required("client_cert_file_name") flags.mark_flag_as_required("ca_cert_display_name") flags.mark_flag_as_required("vpn_profile_name")
flags.mark_flag_as_required("server_addr") flags.mark_flag_as_required("server_id")
flags.mark_flag_as_required("client_cert_p12_file") flags.mark_flag_as_required("client_id")
flags.mark_flag_as_required("ca_cert_pem_file") flags.mark_flag_as_required("ca_common_name")
def load_pem_file(fname:str)->bytes: with open(fname, "r") as f: lines = [l.strip() for l in f.read().split("\n")] lines = filter(lambda l:len(l) > 0 and '-----' not in l, lines) return base64.b64decode(''.join(lines))
def client_cert_payload(): ret = dict() ret["PayloadIdentifier"] = FLAGS.client_cert_rdns ret["PayloadDisplayName"] = FLAGS.client_cert_display_name ret["PayloadCertificateFileName"] = FLAGS.client_cert_file_name ret["PayloadUUID"] = str(uuid.uuid4()) ret["PayloadType"] = "com.apple.security.pkcs12" ret["PayloadVersion"] = 1 if FLAGS.client_cert_p12_pwd is not None: ret["Password"] = FLAGS.client_cert_p12_pwd ret["PayloadContent"] = load_pem_file(FLAGS.client_cert_p12_file) return ret
def ca_cert_payload(): ret = dict() ret["PayloadIdentifier"] = FLAGS.ca_cert_rdns ret["PayloadDisplayName"] = FLAGS.ca_cert_display_name ret["PayloadUUID"] = str(uuid.uuid4()) ret["PayloadType"] = "com.apple.security.root" ret["PayloadVersion"] = 1 ret["PayloadContent"] = load_pem_file(FLAGS.ca_cert_pem_file) return ret
def security_parameter_payload(): ret = dict() ret["EncryptionAlgorithm"] = "AES-256-GCM" ret["IntegrityAlgorithm"] = "SHA2-256" ret["DiffieHellmanGroup"] = 19 return ret
def ikev2_payload(client_cert_uuid:str): ret = dict() ret["RemoteAddress"] = FLAGS.server_addr ret["RemoteIdentifier"] = FLAGS.server_id ret["LocalIdentifier"] = FLAGS.client_id if FLAGS.ca_common_name is not None: ret["ServerCertificateIssuerCommonName"] = FLAGS.ca_common_name ret["AuthenticationMethod"] = "Certificate" ret["PayloadCertificateUUID"] = client_cert_uuid ret["CertificateType"] = "ECDSA256" ret["IKESecurityAssociationParameters"] = security_parameter_payload() ret["ChildSecurityAssociationParameters"] = security_parameter_payload() if FLAGS.always_on_wifi: ret["OnDemandEnabled"] = 1 ret["OnDemandRules"] = [ dict(InterfaceTypeMatch="WiFi", Action="Connect"), dict(Action="Ignore") ]
return ret
def vpn_payload(client_cert_uuid:str): ret = dict() ret["PayloadIdentifier"] = FLAGS.vpn_rdns ret["PayloadDisplayName"] = FLAGS.vpn_display_name ret["PayloadUUID"] = str(uuid.uuid4()) ret["PayloadType"] = "com.apple.vpn.managed" ret["PayloadVersion"] = 1 ret["UserDefinedName"] = FLAGS.vpn_profile_name ret["VPNType"] = "IKEv2" ret["IKEv2"] = ikev2_payload(client_cert_uuid) return ret
def mobileconfig_payload(): client_p = client_cert_payload() vpn_p = vpn_payload(client_p["PayloadUUID"]) ret = dict() ret["PayloadIdentifier"] = FLAGS.profile_rdns ret["PayloadDisplayName"] = FLAGS.profile_display_name ret["PayloadUUID"] = str(uuid.uuid4()) ret["PayloadType"] = "Configuration" ret["PayloadVersion"] = 1 ret["PayloadContent"] = [vpn_p, client_p]
if FLAGS.ca_cert_pem_file is not None: ca_p = ca_cert_payload() ret["PayloadContent"].append(ca_p) return ret
def main(argv): print(plistlib.dumps(mobileconfig_payload()).decode())
if __name__ == '__main__': app.run(main)
|