Close #239: Check existing Name Constraints

This check is performed before the certificate is
issued and signed. Like all the other checks
regarding validity, extensions and other things.

Issuing certificates that violate the Name Constraints
of any CA in the chain is still be possible.

But there will be a warning now with the name of the affected
CA-Certificate and the violated constraint.

The Issuer can then decide whether to issue the
certificate or not.
This commit is contained in:
Christian Hohnstaedt 2024-09-29 01:18:01 +02:00
parent 2e7cb9f2b1
commit 5f4308245c
3 changed files with 64 additions and 1 deletions

View File

@ -18,8 +18,9 @@
#include "pass_info.h"
#include <openssl/rand.h>
#include <openssl/x509_vfy.h>
#include <openssl/err.h>
#include <openssl/x509_vfy.h>
#include <openssl/x509v3.h>
pki_x509::pki_x509(X509 *c)
:pki_x509super(), cert(c)
@ -1242,3 +1243,27 @@ QList<X509_PURPOSE *> pki_x509::purposes() const
}
return purposes;
}
int pki_x509::name_constraint_check(pki_x509 *issuer) const
{
int rc = X509_V_OK;
if (!issuer || issuer == this)
return rc;
x509v3ext e = issuer->getExtByNid(NID_name_constraints);
if (e.nid() != NID_name_constraints)
return rc;
NAME_CONSTRAINTS *nc = (NAME_CONSTRAINTS *)e.d2i();
Q_CHECK_PTR(nc);
rc = NAME_CONSTRAINTS_check(cert, nc);
#ifndef LIBRESSL_VERSION_NUMBER
if (!isCA() && rc == X509_V_OK)
rc = NAME_CONSTRAINTS_check_CN(cert, nc);
#endif
NAME_CONSTRAINTS_free(nc);
pki_openssl_error();
qDebug() << getIntName() << issuer->getIntName() << get_ossl_verify_error(rc);
return rc;
}

View File

@ -170,6 +170,7 @@ class pki_x509 : public pki_x509super
QList<int> ossl_verify() const;
bool check_ca() const;
QList<X509_PURPOSE *> purposes() const;
int name_constraint_check(pki_x509 *issuer) const;
};
Q_DECLARE_METATYPE(pki_x509 *);

View File

@ -36,6 +36,7 @@
#include "lib/db_temp.h"
#include "lib/oid.h"
#include "lib/func.h"
#include "lib/pki_evp.h"
void NewX509::setupExplicitDN(NIDlist my_dn_nid = NIDlist())
{
@ -932,6 +933,8 @@ void NewX509::setupTmpCtx()
ctx_cert->setIssuer(ctx_cert->getSubject());
}
ctx_cert->setSerial(serial);
ctx_cert->setNotBefore(notBefore->getDate());
ctx_cert->setNotAfter(notAfter->getDate());
initCtx(ctx_cert, signcert, req);
}
@ -1476,6 +1479,40 @@ void NewX509::accept()
break;
}
}
if (foreignSignRB->isChecked()) {
setupTmpCtx();
// Update SAN and BC of ctx_cert
getBasicConstraints();
getSubAltName();
for (pki_x509 *crt = getSelectedSigner(), *oldcrt = nullptr;
crt && crt != oldcrt;
oldcrt = crt, crt = crt->getSigner())
{
int rc = ctx_cert->name_constraint_check(crt);
qDebug() << ctx_cert->getIntName() << "Issuer"
<< crt->getIntName()<< get_ossl_verify_error(rc);
if (rc == X509_V_OK)
continue;
gotoTab(2);
xcaWarningBox msg(this, tr("A name constraint of the issuer '%1' is violated: %2")
.arg(crt->getIntName()).arg(get_ossl_verify_error(rc)));
msg.setInformativeText(crt->getExtByNid(NID_name_constraints).getValue());
msg.addButton(QMessageBox::Ok, tr("Edit extensions"));
msg.addButton(QMessageBox::Close, tr("Abort rollout"));
msg.addButton(QMessageBox::Apply, tr("Continue rollout"));
switch (msg.exec())
{
case QMessageBox::Ok:
case QMessageBox::Cancel:
return;
case QMessageBox::Close:
reject();
return;
case QMessageBox::Apply:
break;
}
}
}
XcaDetail::accept();
}