providers/saml: add verification_kp when verifying assertions against certificates without private key

This commit is contained in:
Jens Langhammer 2020-11-08 22:24:50 +01:00
parent 5cb7f0794e
commit 1edcda58ba
5 changed files with 48 additions and 4 deletions

View File

@ -25,6 +25,7 @@ class SAMLProviderSerializer(ModelSerializer):
"signature_algorithm", "signature_algorithm",
"signing_kp", "signing_kp",
"require_signing", "require_signing",
"verification_kp",
] ]

View File

@ -34,11 +34,12 @@ class SAMLProviderForm(forms.ModelForm):
"assertion_valid_not_before", "assertion_valid_not_before",
"assertion_valid_not_on_or_after", "assertion_valid_not_on_or_after",
"session_valid_not_on_or_after", "session_valid_not_on_or_after",
"property_mappings",
"digest_algorithm", "digest_algorithm",
"require_signing", "require_signing",
"signature_algorithm", "signature_algorithm",
"signing_kp", "signing_kp",
"verification_kp",
"property_mappings",
] ]
widgets = { widgets = {
"name": forms.TextInput(), "name": forms.TextInput(),

View File

@ -0,0 +1,28 @@
# Generated by Django 3.1.3 on 2020-11-08 21:22
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("passbook_crypto", "0002_create_self_signed_kp"),
("passbook_providers_saml", "0006_remove_samlprovider_name"),
]
operations = [
migrations.AddField(
model_name="samlprovider",
name="verification_kp",
field=models.ForeignKey(
default=None,
help_text="If selected, incoming assertion's Signatures will be validated.",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="+",
to="passbook_crypto.certificatekeypair",
verbose_name="Verification Keypair",
),
),
]

View File

@ -87,6 +87,15 @@ class SAMLProvider(Provider):
default="rsa-sha256", default="rsa-sha256",
) )
verification_kp = models.ForeignKey(
CertificateKeyPair,
default=None,
null=True,
help_text=_("If selected, incoming assertion's Signatures will be validated."),
on_delete=models.SET_NULL,
verbose_name=_("Verification Keypair"),
related_name="+",
)
signing_kp = models.ForeignKey( signing_kp = models.ForeignKey(
CertificateKeyPair, CertificateKeyPair,
default=None, default=None,

View File

@ -69,10 +69,11 @@ class AuthNRequestParser:
"""Validate and parse raw request with enveloped signautre.""" """Validate and parse raw request with enveloped signautre."""
decoded_xml = decode_base64_and_inflate(saml_request) decoded_xml = decode_base64_and_inflate(saml_request)
if self.provider.signing_kp: if self.provider.verification_kp:
try: try:
XMLVerifier().verify( XMLVerifier().verify(
decoded_xml, x509_cert=self.provider.signing_kp.certificate_data decoded_xml,
x509_cert=self.provider.verification_kp.certificate_data,
) )
except InvalidSignature as exc: except InvalidSignature as exc:
raise CannotHandleAssertion("Failed to verify signature") from exc raise CannotHandleAssertion("Failed to verify signature") from exc
@ -98,7 +99,11 @@ class AuthNRequestParser:
querystring += f"RelayState={quote_plus(relay_state)}&" querystring += f"RelayState={quote_plus(relay_state)}&"
querystring += f"SigAlg={sig_alg}" querystring += f"SigAlg={sig_alg}"
public_key = self.provider.signing_kp.private_key.public_key() if not self.provider.verification_kp:
raise CannotHandleAssertion(
"Provider does not have a Validation Certificate configured."
)
public_key = self.provider.verification_kp.private_key.public_key()
try: try:
public_key.verify( public_key.verify(
b64decode(signature), b64decode(signature),