Пример #1
0
    def _enroll_machine(self):
        try:
            enrollment = (Enrollment.objects.select_related(
                "configuration",
                "secret").get(secret__secret=self.enrollment_secret_secret))
        except Enrollment.DoesNotExist:
            raise PermissionDenied("Unknown enrollment secret")
        if enrollment.configuration.client_certificate_auth and not self.client_cert_dn:
            raise PermissionDenied("Missing client certificate")
        try:
            verify_enrollment_secret(
                "santa_enrollment",
                self.enrollment_secret_secret,
                self.user_agent,
                self.ip,
                serial_number=self.request_data["serial_num"],
                udid=self.hardware_uuid,
            )
        except EnrollmentSecretVerificationFailed:
            raise PermissionDenied("Wrong enrollment secret")

        # get or create enrolled machine
        enrolled_machine, _ = EnrolledMachine.objects.update_or_create(
            enrollment=enrollment,
            hardware_uuid=self.hardware_uuid,
            defaults=self._get_enrolled_machine_defaults(),
        )

        # apply enrollment secret tags
        for tag in enrollment.secret.tags.all():
            MachineTag.objects.get_or_create(
                serial_number=enrolled_machine.serial_number, tag=tag)

        # delete other enrolled machines
        other_enrolled_machines = (EnrolledMachine.objects.exclude(
            pk=enrolled_machine.pk).filter(hardware_uuid=self.hardware_uuid))
        if other_enrolled_machines.count():
            self.enrollment_action = 're-enrollment'
            other_enrolled_machines.delete()
        else:
            self.enrollment_action = 'enrollment'

        # post event
        post_enrollment_event(
            enrolled_machine.serial_number, self.user_agent, self.ip, {
                'configuration':
                enrollment.configuration.serialize_for_event(),
                'action': self.enrollment_action
            })

        return enrolled_machine
Пример #2
0
    def post(self, request, *args, **kwargs):
        user_agent, ip = user_agent_and_ip_address_from_request(request)
        try:
            request_json = json.loads(request.body.decode("utf-8"))
            secret = request_json["secret"]
            serial_number = request_json["serial_number"]
            uuid = request_json["uuid"]
            es_request = verify_enrollment_secret("munki_enrollment", secret,
                                                  user_agent, ip,
                                                  serial_number, uuid)
        except (KeyError, ValueError, EnrollmentSecretVerificationFailed):
            raise SuspiciousOperation
        else:
            # get or create enrolled machine
            enrolled_machine, enrolled_machine_created = EnrolledMachine.objects.get_or_create(
                enrollment=es_request.enrollment_secret.munki_enrollment,
                serial_number=serial_number,
                defaults={"token": get_random_string(64)})

            # apply enrollment secret tags
            for tag in es_request.enrollment_secret.tags.all():
                MachineTag.objects.get_or_create(serial_number=serial_number,
                                                 tag=tag)

            # post event
            post_munki_enrollment_event(
                serial_number, user_agent, ip, {
                    'action':
                    "enrollment"
                    if enrolled_machine_created else "re-enrollment"
                })
            return JsonResponse({"token": enrolled_machine.token})
Пример #3
0
    def post(self, request, *args, **kwargs):
        self.user_agent, self.ip = user_agent_and_ip_address_from_request(request)
        try:
            request_json = json.loads(request.body.decode("utf-8"))
            secret = request_json["secret"]
            serial_number = request_json["serial_number"]
            es_request = verify_enrollment_secret(
                "filebeat_enrollment", secret,
                self.user_agent, self.ip,
                serial_number
            )
        except (ValueError, KeyError, EnrollmentSecretVerificationFailed):
            raise SuspiciousOperation
        else:
            enrollment_session = EnrollmentSession.objects.create_from_enrollment(
                enrollment=es_request.enrollment_secret.filebeat_enrollment,
                serial_number=serial_number
            )
            # response
            response = {
                "scep": {
                    "cn": enrollment_session.get_common_name(),
                    "org": enrollment_session.get_organization(),
                    "challenge": enrollment_session.get_challenge(),
                    "url": "{}/scep".format(settings["api"]["tls_hostname"]),  # TODO: hardcoded scep url
                },
                "secret": enrollment_session.enrollment_secret.secret,
            }

            # post event
            post_enrollment_event(serial_number, self.user_agent, self.ip, enrollment_session.serialize_for_event())
        return JsonResponse(response)
Пример #4
0
 def verify_dep_profile_enrollment_secret(self):
     try:
         es_request = verify_enrollment_secret(
             "dep_profile", self.kwargs["dep_profile_secret"],
             self.user_agent, self.ip, self.serial_number, self.udid)
     except EnrollmentSecretVerificationFailed as e:
         self.abort("secret verification failed: '{}'".format(e.err_msg))
     else:
         return es_request, es_request.enrollment_secret.dep_profile
Пример #5
0
 def verify_enrollment_secret(self):
     try:
         es_request = verify_enrollment_secret("user_enrollment",
                                               self.kwargs["secret"],
                                               self.user_agent, self.ip)
     except EnrollmentSecretVerificationFailed as e:
         self.abort("secret verification failed: '{}'".format(e.err_msg))
     else:
         self.user_enrollment = es_request.enrollment_secret.user_enrollment
         if not self.user_enrollment.realm:
             self.abort("This user enrollment has no realm")
Пример #6
0
 def authenticate(self):
     self.serial_number = self.get_serial_number()
     try:
         self.es_request = verify_enrollment_secret(
             "osquery_enrollment",
             self.get_enroll_secret(),
             self.user_agent, self.ip,
             self.serial_number,
             self.get_uuid()
         )
     except EnrollmentSecretVerificationFailed:
         raise PermissionDenied("Wrong enrollment secret")
Пример #7
0
 def verify_enrollment_secret(self, enroll_secret, serial_number, uuid):
     try:
         es_request = verify_enrollment_secret("osquery_enrollment",
                                               enroll_secret,
                                               self.user_agent, self.ip,
                                               serial_number, uuid)
     except EnrollmentSecretVerificationFailed:
         raise APIAuthError("Unknown enrolled machine")
     else:
         self.enrollment = es_request.enrollment_secret.osquery_enrollment
         self.machine_serial_number = serial_number
         self.business_unit = self.enrollment.secret.get_api_enrollment_business_unit(
         )
Пример #8
0
    def post(self, request, *args, **kwargs):
        # DN => serial_number + meta_business_unit
        dn = request.META.get("HTTP_X_SSL_CLIENT_S_DN")
        if not dn:
            raise SuspiciousOperation("missing DN in request headers")

        dn_d = parse_dn(dn)

        cn = dn_d.get("CN")
        try:
            cn_prefix, enrollment_secret_secret = cn.split("$")
        except (AttributeError, ValueError):
            raise SuspiciousOperation("missing or bad CN in client certificate DN")

        # verify prefix
        if cn_prefix != "FLBT":
            raise SuspiciousOperation("bad CN prefix in client certificate")

        self.user_agent, self.ip = user_agent_and_ip_address_from_request(request)
        try:
            request_json = json.loads(request.body.decode("utf-8"))
            secret = request_json["secret"]
            serial_number = request_json["serial_number"]
            es_request = verify_enrollment_secret(
                "filebeat_enrollment_session", secret,
                self.user_agent, self.ip,
                serial_number,
                filebeat_enrollment_session__status__in=(EnrollmentSession.STARTED, EnrollmentSession.SCEP_VERIFIED)
            )
            certificate = request_json["certificate"]
            key = request_json["key"]
            certificate_authority = request_json["certificate_authority"]
        except (ValueError, KeyError, EnrollmentSecretVerificationFailed):
            raise SuspiciousOperation("Could not verify enrollment session secret")
        else:
            # update enrollment session
            enrollment_session = es_request.enrollment_secret.filebeat_enrollment_session
            enrolled_machine, _ = EnrolledMachine.objects.get_or_create(serial_number=serial_number)
            enrollment_session.set_completed(enrolled_machine)
            # apply enrollment secret tags
            for tag in es_request.enrollment_secret.tags.all():
                MachineTag.objects.get_or_create(serial_number=serial_number, tag=tag)
            # post event
            post_enrollment_event(serial_number, self.user_agent, self.ip, enrollment_session.serialize_for_event())
            # response
            response = {
                "filebeat.yml": build_filebeat_yml(enrollment_session.enrollment.configuration,
                                                   certificate=certificate, key=key,
                                                   certificate_authority=certificate_authority)
            }
            return JsonResponse(response)
Пример #9
0
    def do_post(self, data):
        csr_data = base64.b64decode(data["csr"].encode("ascii"))
        csr_info = csr.CertificationRequest.load(
            csr_data)["certification_request_info"]

        csr_d = {}

        # subject
        for rdn_idx, rdn in enumerate(csr_info["subject"].chosen):
            for type_val_idx, type_val in enumerate(rdn):
                csr_d[type_val["type"].native] = type_val['value'].native

        kwargs = {"user_agent": self.user_agent, "public_ip_address": self.ip}
        serial_number = csr_d.pop(
            "serial_number",
            None)  # TODO: better system to find this attr in csr_d
        if serial_number:
            kwargs["serial_number"] = serial_number

        # meta business
        organization_name = csr_d.get("organization_name")
        if not organization_name or not organization_name.startswith("MBU$"):
            self.abort("Unknown organization name format")
        meta_business_unit_id = int(organization_name.split("$", 1)[-1])
        kwargs["meta_business_unit"] = get_object_or_404(
            MetaBusinessUnit, pk=meta_business_unit_id)

        # type and session secret
        try:
            cn_prefix, kwargs["secret"] = csr_d["common_name"].rsplit("$", 1)
        except (KeyError, ValueError, AttributeError):
            self.abort("Unknown common name format")

        model, status, update_status_method = self.get_enrollment_session_info(
            cn_prefix)
        kwargs["model"] = model
        kwargs["{}__status".format(model)] = status
        try:
            es_request = verify_enrollment_secret(**kwargs)
        except EnrollmentSecretVerificationFailed as e:
            self.abort("secret verification failed: '{}'".format(e.err_msg))
        else:
            # update the enrollment session status
            enrollment_session = getattr(es_request.enrollment_secret, model)
            getattr(enrollment_session, update_status_method)(es_request)
            self.post_event("success",
                            **enrollment_session.serialize_for_event())

        # OK
        return {"status": 0}
Пример #10
0
    def enroll_machine(self, data):
        try:
            enrollment = (Enrollment.objects.select_related(
                "configuration",
                "secret").get(secret__secret=self.enrollment_secret_secret))
        except Enrollment.DoesNotExist:
            raise PermissionDenied("Unknown enrollment secret")
        if enrollment.configuration.client_certificate_auth and self.get_client_cert(
        ) is None:
            raise PermissionDenied("Missing client certificate")
        try:
            verify_enrollment_secret(
                "santa_enrollment",
                self.enrollment_secret_secret,
                self.user_agent,
                self.ip,
                serial_number=self.machine_serial_number,
                udid=self.hardware_uuid,
            )
        except EnrollmentSecretVerificationFailed:
            raise PermissionDenied("Wrong enrollment secret")

        # get or create enrolled machine
        self.enrolled_machine, _ = EnrolledMachine.objects.get_or_create(
            enrollment=enrollment,
            hardware_uuid=self.hardware_uuid,
            defaults={"serial_number": self.machine_serial_number})

        # apply enrollment secret tags
        for tag in enrollment.secret.tags.all():
            MachineTag.objects.get_or_create(
                serial_number=self.machine_serial_number, tag=tag)

        # post event
        post_enrollment_event(self.machine_serial_number, self.user_agent,
                              self.ip, {'action': 'enrollment'})
Пример #11
0
    def post(self, request, *args, **kwargs):
        self.user_agent, self.ip = user_agent_and_ip_address_from_request(
            request)
        try:
            request_json = json.loads(request.body.decode("utf-8"))
            secret = request_json["secret"]
            serial_number = request_json["serial_number"]
            uuid = request_json["uuid"]
            es_request = verify_enrollment_secret("santa_enrollment", secret,
                                                  self.user_agent, self.ip,
                                                  serial_number, uuid)
        except (ValueError, KeyError, EnrollmentSecretVerificationFailed):
            raise SuspiciousOperation
        else:
            # get or create enrolled machine
            enrolled_machine, enrolled_machine_created = EnrolledMachine.objects.get_or_create(
                enrollment=es_request.enrollment_secret.santa_enrollment,
                serial_number=serial_number,
                defaults={"machine_id": get_random_string(64)})

            # apply enrollment secret tags
            for tag in es_request.enrollment_secret.tags.all():
                MachineTag.objects.get_or_create(serial_number=serial_number,
                                                 tag=tag)

            # response
            response = {"machine_id": enrolled_machine.machine_id}
            cp_name, cp_content = build_configuration_profile(enrolled_machine)
            cp_content = base64.b64encode(cp_content).decode("utf-8")
            response["configuration_profile"] = {
                "name": cp_name,
                "content": cp_content
            }
            cpl_name, cpl_content = build_config_plist(enrolled_machine)
            response["config_plist"] = {
                "name": cpl_name,
                "content": cpl_content
            }

            # post event
            post_enrollment_event(
                serial_number, self.user_agent, self.ip, {
                    'action':
                    "enrollment"
                    if enrolled_machine_created else "re-enrollment"
                })
        return JsonResponse(response)
Пример #12
0
    def post(self, request, *args, **kwargs):
        # Verify payload signature, extract signed payload
        try:
            certificates, payload = verify_signed_payload(request.read())
        except ValueError as error:
            self.abort("posted data is not signed", signature_error=str(error))

        for certificate_i_cn, certificate_bytes, signing_certificate in certificates:
            if verify_apple_iphone_device_ca_issuer_openssl(certificate_bytes):
                break

        payload = plistlib.loads(payload)
        self.serial_number = payload["SERIAL"]
        self.udid = payload["UDID"]

        try:
            es_request = verify_enrollment_secret(
                "dep_profile", self.kwargs["dep_profile_secret"],
                self.user_agent, self.ip, self.serial_number, self.udid)
        except EnrollmentSecretVerificationFailed as e:
            self.abort("secret verification failed: '{}'".format(e.err_msg))

        # Start a DEP enrollment session
        dep_enrollment_session = DEPEnrollmentSession.objects.create_from_dep_profile(
            es_request.enrollment_secret.dep_profile, self.serial_number,
            self.udid, payload)

        # Get the MDM push certificate
        push_certificate = (
            dep_enrollment_session.enrollment_secret.meta_business_unit.
            metabusinessunitpushcertificate.push_certificate)

        configuration_profile = build_mdm_configuration_profile(
            dep_enrollment_session, push_certificate)
        configuration_profile_filename = "zentral_mdm"
        self.post_event("success",
                        **dep_enrollment_session.serialize_for_event())
        return build_configuration_profile_response(
            configuration_profile, configuration_profile_filename)
Пример #13
0
    def enroll_machine(self):
        try:
            request = verify_enrollment_secret(
                "jamf_protect_enrollment",
                self.token,
                self.user_agent,
                self.ip,
                serial_number=self.serial_number)
        except EnrollmentSecretVerificationFailed:
            raise PermissionDenied("Invalid enrollment secret")
        else:
            # get or create enrolled machine
            enrollment_secret = request.enrollment_secret
            self.enrolled_machine, _ = EnrolledMachine.objects.get_or_create(
                enrollment=enrollment_secret.jamf_protect_enrollment,
                serial_number=self.serial_number)

            # apply enrollment secret tags
            for tag in enrollment_secret.tags.all():
                MachineTag.objects.get_or_create(
                    serial_number=self.serial_number, tag=tag)
            post_enrollment_event(self.serial_number, self.user_agent, self.ip,
                                  {'action': 'enrollment'})
Пример #14
0
    def post(self, request, *args, **kwargs):
        # Verify payload signature, extract signed payload
        try:
            certificates, payload = verify_signed_payload(request.read())
        except ValueError:
            self.abort("posted data is not signed")

        # find out which CA signed the certificate used to sign the payload
        # if iPhone CA: phase 2
        # if SCEP CA: phase 3
        for certificate_i_cn, certificate_bytes, signing_certificate in certificates:
            if verify_apple_iphone_device_ca_issuer(certificate_bytes):
                phase = 2
                break
            elif verify_zentral_scep_ca_issuer(certificate_bytes):
                phase = 3
                break
        else:
            self.abort(
                f"Unknown signing certificate issuer: {certificate_i_cn}")

        payload = plistlib.loads(payload)
        self.serial_number = payload["SERIAL"]
        self.udid = payload["UDID"]

        if phase == 2:
            # Verify the challenge
            challenge = payload.get("CHALLENGE")
            if not challenge:
                self.abort("missing challenge", phase=phase)

            # Pre-authenticated session ?
            session_enrollment = kwargs.pop("session")
            if session_enrollment:
                # running off a realm user authenticated existing ota enrollment session
                try:
                    es_request = verify_enrollment_secret(
                        "ota_enrollment_session", challenge, self.user_agent,
                        self.ip, self.serial_number, self.udid)
                except EnrollmentSecretVerificationFailed as e:
                    self.abort("secret verification failed: '{}'".format(
                        e.err_msg),
                               phase=phase)

                ota_enrollment_session = es_request.enrollment_secret.ota_enrollment_session

                # for PostEventMixin
                self.realm_user = ota_enrollment_session.realm_user

                # update the OTA enrollment session
                ota_enrollment_session.set_phase2_status(
                    es_request, self.serial_number, self.udid)

            else:
                # running off a simple ota enrollment
                try:
                    es_request = verify_enrollment_secret(
                        "ota_enrollment", challenge, self.user_agent, self.ip,
                        self.serial_number, self.udid)
                except EnrollmentSecretVerificationFailed as e:
                    self.abort("secret verification failed: '{}'".format(
                        e.err_msg),
                               phase=phase)

                ota_enrollment = es_request.enrollment_secret.ota_enrollment
                if ota_enrollment.realm:
                    self.abort(
                        "cannot use ota enrollment secret on ota enrollment with realm",
                        phase=phase)

                # Start an OTA enrollment session directly in phase 2
                ota_enrollment_session = OTAEnrollmentSession.objects.create_from_machine_info(
                    ota_enrollment, self.serial_number, self.udid)

            configuration_profile = build_ota_scep_configuration_profile(
                ota_enrollment_session)
            configuration_profile_filename = "zentral_ota_scep"

        elif phase == 3:
            # get the serial number from the DN of the payload signing certificate
            serial_number = signing_certificate.subject.get_attributes_for_oid(
                NameOID.SERIAL_NUMBER)[0].value
            if self.serial_number != serial_number:
                self.abort(
                    "signing certificate DN serial number != payload serial number",
                    phase=phase)

            # get the ota enrollment session from the DN of the payload signing certificate
            cn = signing_certificate.subject.get_attributes_for_oid(
                NameOID.COMMON_NAME)[0].value
            _, ota_enrollment_session_secret = cn.split("$")
            try:
                ota_enrollment_session = (
                    OTAEnrollmentSession.objects.select_for_update(
                    ).select_related("ota_enrollment",
                                     "enrollment_secret__meta_business_unit").
                    get(enrollment_secret__secret=ota_enrollment_session_secret
                        ))
            except OTAEnrollmentSession.DoesNotExist:
                self.abort(
                    "could not find ota enrollment session from payload signing certificate",
                    phase=phase)

            # for PostEventMixin
            self.realm_user = ota_enrollment_session.realm_user

            # verify and update ota enrollment session status
            try:
                ota_enrollment_session.set_phase3_status()
            except EnrollmentSessionStatusError:
                self.abort("ota enrollment session has wrong status",
                           phase=phase)

            # verify DN mbu
            ota_enrollment_session_mbu = ota_enrollment_session.enrollment_secret.meta_business_unit
            o = signing_certificate.subject.get_attributes_for_oid(
                NameOID.ORGANIZATION_NAME)[0]
            if int(o.value.split("$")[-1]) != ota_enrollment_session_mbu.pk:
                self.abort("DN mbu doesn't match ota enrollment session mbu",
                           phase=phase)

            # Get the MDM push certificate
            push_certificate = ota_enrollment_session.ota_enrollment.push_certificate

            configuration_profile = build_mdm_configuration_profile(
                ota_enrollment_session, push_certificate)
            configuration_profile_filename = "zentral_mdm"

        self.post_event("success", phase=phase)

        return build_configuration_profile_response(
            configuration_profile, configuration_profile_filename)
Пример #15
0
    def do_post(self, data):
        csr_data = base64.b64decode(data["csr"].encode("ascii"))
        csr_info = csr.CertificationRequest.load(
            csr_data)["certification_request_info"]

        csr_d = {}

        # subject
        for rdn_idx, rdn in enumerate(csr_info["subject"].chosen):
            for type_val_idx, type_val in enumerate(rdn):
                csr_d[type_val["type"].native] = type_val['value'].native

        kwargs = {"user_agent": self.user_agent, "public_ip_address": self.ip}

        # serial number
        self.serial_number = csr_d.get("serial_number")
        if not self.serial_number:
            self.abort("Could not get serial number")
        kwargs["serial_number"] = self.serial_number

        # meta business
        organization_name = csr_d.get("organization_name")
        if not organization_name or not organization_name.startswith("MBU$"):
            self.abort("Unknown organization name format")
        meta_business_unit_id = int(organization_name.split("$", 1)[-1])
        kwargs["meta_business_unit"] = get_object_or_404(
            MetaBusinessUnit, pk=meta_business_unit_id)

        # type and session secret
        try:
            cn_prefix, kwargs["secret"] = csr_d["common_name"].rsplit("$", 1)
        except (KeyError, ValueError, AttributeError):
            self.abort("Unknown common name format")

        # CN prefix => OTA enrollment phase
        if cn_prefix == "OTA" or cn_prefix == "MDM$OTA":
            kwargs["model"] = "ota_enrollment_session"
            if cn_prefix == "OTA":
                kwargs[
                    "ota_enrollment_session__status"] = OTAEnrollmentSession.PHASE_2
                update_status_method = "set_phase2_scep_verified_status"
            else:
                kwargs[
                    "ota_enrollment_session__status"] = OTAEnrollmentSession.PHASE_3
                update_status_method = "set_phase3_scep_verified_status"
        elif cn_prefix == "MDM$DEP":
            kwargs["model"] = "dep_enrollment_session"
            kwargs[
                "dep_enrollment_session__status"] = DEPEnrollmentSession.STARTED
            update_status_method = "set_scep_verified_status"
        else:
            self.abort("Unknown CN prefix {}".format(cn_prefix))

        try:
            es_request = verify_enrollment_secret(**kwargs)
        except EnrollmentSecretVerificationFailed as e:
            self.abort("secret verification failed: '{}'".format(e.err_msg))
        else:
            # update the enrollment session status
            enrollment_session = getattr(es_request.enrollment_secret,
                                         kwargs["model"])
            getattr(enrollment_session, update_status_method)(es_request)
            self.post_event("success",
                            **enrollment_session.serialize_for_event())

        # OK
        return {"status": 0}
Пример #16
0
    def post(self, request, *args, **kwargs):
        # Verify payload signature, extract signed payload
        try:
            certificates, payload = verify_signed_payload(request.read())
        except ValueError:
            self.abort("posted data is not signed")

        # find out which CA signed the certificate used to sign the payload
        # if iPhone CA: phase 2
        # if SCEP CA: phase 3
        # if unknown: phase 2  # TODO: verify. seen with self signed cert in 10.13 beta in VMWare.
        for certificate_i_cn, certificate_bytes, signing_certificate in certificates:
            if verify_apple_iphone_device_ca_issuer_openssl(certificate_bytes):
                phase = 2
                break
            elif verify_zentral_scep_ca_issuer_openssl(certificate_bytes):
                phase = 3
                break
            else:
                self.post_event(
                    "warning",
                    reason="unknown signing certificate issuer '{}'".format(
                        certificate_i_cn))
                phase = 2

        payload = plistlib.loads(payload)
        self.serial_number = payload["SERIAL"]
        self.udid = payload["UDID"]

        if phase == 2:
            # Verify the challenge
            challenge = payload.get("CHALLENGE")
            if not challenge:
                self.abort("missing challenge", phase=phase)
            try:
                es_request = verify_enrollment_secret("ota_enrollment",
                                                      challenge,
                                                      self.user_agent, self.ip,
                                                      self.serial_number,
                                                      self.udid)
            except EnrollmentSecretVerificationFailed as e:
                self.abort("secret verification failed: '{}'".format(
                    e.err_msg),
                           phase=phase)

            # Start an OTA enrollment session
            ota_enrollment_session = OTAEnrollmentSession.objects.create_from_ota_enrollment(
                es_request.enrollment_secret.ota_enrollment,
                self.serial_number, self.udid, payload)

            payload = build_ota_scep_payload(ota_enrollment_session)
            filename = "zentral_ota_scep"

        elif phase == 3:
            # get the serial number from the DN of the payload signing certificate
            serial_number = signing_certificate.subject.get_attributes_for_oid(
                NameOID.SERIAL_NUMBER)[0].value
            if self.serial_number != serial_number:
                self.abort(
                    "signing certificate DN serial number != payload serial number",
                    phase=phase)

            # get the ota enrollment session from the DN of the payload signing certificate
            cn = signing_certificate.subject.get_attributes_for_oid(
                NameOID.COMMON_NAME)[0].value
            _, ota_enrollment_session_secret = cn.split("$")
            try:
                ota_enrollment_session = (
                    OTAEnrollmentSession.objects.select_for_update(
                    ).select_related("ota_enrollment",
                                     "enrollment_secret__meta_business_unit").
                    get(enrollment_secret__secret=ota_enrollment_session_secret
                        ))
            except OTAEnrollmentSession.DoesNotExist:
                self.abort(
                    "could not find ota enrollment session from payload signing certificate",
                    phase=phase)

            # verify and update ota enrollment session status
            try:
                ota_enrollment_session.set_phase3_status()
            except EnrollmentSessionStatusError:
                self.abort("ota enrollment session has wrong status",
                           phase=phase)

            # verify DN mbu
            ota_enrollment_session_mbu = ota_enrollment_session.enrollment_secret.meta_business_unit
            o = signing_certificate.subject.get_attributes_for_oid(
                NameOID.ORGANIZATION_NAME)[0]
            if int(o.value.split("$")[-1]) != ota_enrollment_session_mbu.pk:
                self.abort("DN mbu doesn't match ota enrollment session mbu",
                           phase=phase)

            # Get the MDM push certificate
            push_certificate = ota_enrollment_session_mbu.metabusinessunitpushcertificate.push_certificate

            payload = build_mdm_payload(ota_enrollment_session,
                                        push_certificate)
            filename = "zentral_mdm"

        self.post_event("success", phase=phase)

        return build_payload_response(sign_payload_openssl(payload), filename)
        return HttpResponse()
Пример #17
0
    def do_post(self, data):
        csr_data = base64.b64decode(data["csr"].encode("ascii"))
        csr_info = csr.CertificationRequest.load(
            csr_data)["certification_request_info"]

        csr_d = {}

        # subject
        for rdn_idx, rdn in enumerate(csr_info["subject"].chosen):
            for type_val_idx, type_val in enumerate(rdn):
                csr_d[type_val["type"].native] = type_val['value'].native

        kwargs = {"user_agent": self.user_agent, "public_ip_address": self.ip}

        # serial number
        serial_number = csr_d.get("serial_number")
        if not serial_number:
            raise SuspiciousOperation("Could not get serial number")
        kwargs["serial_number"] = serial_number

        # meta business
        organization_name = csr_d.get("organization_name")
        if not organization_name or not organization_name.startswith("MBU$"):
            raise SuspiciousOperation("Unknown organization name format")
        meta_business_unit_id = int(organization_name.split("$", 1)[-1])
        kwargs["meta_business_unit"] = get_object_or_404(
            MetaBusinessUnit, pk=meta_business_unit_id)

        # type and session secret
        try:
            cn_prefix, ota_enrollment_session_secret = csr_d[
                "common_name"].split("$")
        except (KeyError, ValueError, AttributeError):
            raise SuspiciousOperation("Unknown common name format")

        # CN prefix => OTA enrollment phase
        if cn_prefix == "OTA":
            ota_enrollment_session_status = OTAEnrollmentSession.PHASE_2
        elif cn_prefix == "MDM":
            ota_enrollment_session_status = OTAEnrollmentSession.PHASE_3
        else:
            raise SuspiciousOperation("Unknown CN prefix {}".format(cn_prefix))

        kwargs["model"] = "ota_enrollment_session"
        kwargs[
            "ota_enrollment_session__status"] = ota_enrollment_session_status
        kwargs["secret"] = ota_enrollment_session_secret

        try:
            es_request = verify_enrollment_secret(**kwargs)
        except EnrollmentSecretVerificationFailed as e:
            raise SuspiciousOperation(
                "secret verification failed: '{}'".format(e.err_msg))
        else:
            # update ota enrollment session
            ota_enrollment_session = es_request.enrollment_secret.ota_enrollment_session
            if ota_enrollment_session_status == OTAEnrollmentSession.PHASE_2:
                ota_enrollment_session.set_phase2_scep_verified_status(
                    es_request)
            if ota_enrollment_session_status == OTAEnrollmentSession.PHASE_3:
                ota_enrollment_session.set_phase3_scep_verified_status(
                    es_request)

        # OK
        return {"status": 0}