Skip to content

Commit

Permalink
Close #518: Export certificates for ovpn file
Browse files Browse the repository at this point in the history
Create ovpn file with "ca", "cert" and "key"
Additionally put all intermediate CAs (if any)
tagged as "extra-certs".

"tls-auth" "OpenVPN Static key V1" not supported (yet)

Extend export-test by OpenVPN test case
  • Loading branch information
chris2511 committed Feb 10, 2024
1 parent 6d01928 commit 0a1a216
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 5 deletions.
29 changes: 28 additions & 1 deletion lib/db_x509.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,15 @@ int db_x509::exportFlags(const QModelIndex &idx) const
return disable_flags;
}

void db_x509::writeTaggedPEM(BioByteArray &b, const QString &tag, XFile &file)
{
if (b.size() > 0) {
file.write(QString("<%1>\n").arg(tag).toLatin1());
file.write(b);
file.write(QString("</%1>\n").arg(tag).toLatin1());
}
}

void db_x509::exportItems(const QModelIndexList &list,
const pki_export *xport, XFile &file) const
{
Expand All @@ -582,7 +591,25 @@ void db_x509::exportItems(const QModelIndexList &list,
}

if (xport->match_all(F_PEM)) {
if (xport->match_all(F_CHAIN)) {
if (xport->match_all(F_OVPN)) {
BioByteArray key, cert, extra, ca;
pki_evp *pkey = (pki_evp *)crt->getRefKey();
if (pkey)
pkey->pem(key, pki_export::by_id(20)); // PEM unencrypted
for (; crt && crt != oldcrt; oldcrt = crt, crt = crt->getSigner())
{
if (crt == crt->getSigner())
crt->pem(ca);
else if (cert.size() == 0)
crt->pem(cert);
else
crt->pem(extra);
}
writeTaggedPEM(ca, "ca", file);
writeTaggedPEM(extra, "extra-certs", file);
writeTaggedPEM(cert, "cert", file);
writeTaggedPEM(key, "key", file);
} else if (xport->match_all(F_CHAIN)) {
for (; crt && crt != oldcrt; oldcrt = crt, crt = crt->getSigner())
crt->writeCert(file, true);
} else if (xport->match_all(F_UNREVOKED)) {
Expand Down
2 changes: 2 additions & 0 deletions lib/db_x509.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class db_x509: public db_x509super
{
Q_OBJECT

static void writeTaggedPEM(BioByteArray &b,
const QString &tag, XFile &file);
protected:
dbheaderList getHeaders();
void dereferenceIssuer();
Expand Down
3 changes: 1 addition & 2 deletions lib/pki_evp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -768,11 +768,10 @@ QSqlError pki_evp::deleteSqlData()
return q.lastError();
}

bool pki_evp::pem(BioByteArray &b)
bool pki_evp::pem(BioByteArray &b, const pki_export *xport)
{
EVP_PKEY *pkey;
int keytype;
const pki_export *xport = pki_export::by_id(Settings["KeyFormat"]);

if (xport->match_all(F_PEM | F_PRIVATE)) {
pkey = decryptKey();
Expand Down
2 changes: 1 addition & 1 deletion lib/pki_evp.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class pki_evp: public pki_key
static QString removeTypeFromIntName(QString n);
void fromPEMbyteArray(const QByteArray &ba, const QString &name);
void fload(const QString &fname);
bool pem(BioByteArray &);
virtual bool pem(BioByteArray &b, const pki_export *xport);
EVP_PKEY *load_ssh_ed25519_privatekey(const QByteArray &ba,
const pass_info &p);
void writeDefault(const QString &dirname) const;
Expand Down
1 change: 1 addition & 0 deletions lib/pki_export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ QList<pki_export*> pki_export::elements {
new pki_export( 1, x509, "crt", "PEM", F_PEM | F_USUAL | F_SINGLE, tr("PEM Text format with headers")),
new pki_export( 3, x509, "pem", "PEM", F_PEM | F_MULTI, tr("Concatenated list of all selected items in one PEM text file")),
new pki_export( 2, x509, "pem", tr("PEM chain"), F_PEM | F_USUAL | F_CHAIN | F_SINGLE, tr("Concatenated text format of the complete certificate chain in one PEM file")),
new pki_export( 4, x509, "ovpn","OpenVPN", F_PEM | F_OVPN | F_CHAIN | F_PRIVATE | F_SINGLE, tr("The complete certificate chain and the private key of the selected certificate with tags usable in OpenVPN configuration files")),
new pki_export( 6, x509, "pem", tr("PEM + key"), F_PEM | F_PRIVATE| F_SINGLE, tr("Concatenation of the certificate and the unencrypted private key in one PEM file")),
new pki_export( 7, x509, "pem", "PEM + PKCS#8", F_PEM | F_PKCS8 | F_PRIVATE | F_CRYPT, tr("Concatenation of the certificate and the encrypted private key in PKCS#8 format in one file")),
new pki_export( 8, x509, "p7b", "PKCS #7", F_PKCS7 | F_USUAL | F_SINGLE, tr("PKCS#7 encoded single certificate")),
Expand Down
1 change: 1 addition & 0 deletions lib/pki_export.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ enum {
F_INDEX = BIT(17),
F_CAL = BIT(18),/* Calendar entry */
F_DER = BIT(19),/* DER format */
F_OVPN = BIT(20),/* OpenVPN format */
};

class pki_export : public QObject {
Expand Down
5 changes: 4 additions & 1 deletion lib/pki_key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,11 @@ void pki_key::write_SSH2_ed25519_private(BIO *b,

bool pki_key::pem(BioByteArray &b)
{
const pki_export *xport = pki_export::by_id(Settings["KeyFormat"]);
return pem(b, pki_export::by_id(Settings["KeyFormat"]));
}

bool pki_key::pem(BioByteArray &b, const pki_export *xport)
{
if (xport->match_all(F_PRIVATE))
return false;
if (xport->match_all(F_SSH2))
Expand Down
1 change: 1 addition & 0 deletions lib/pki_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ class pki_key: public pki_base
qFatal("generate in pki_key");
}
bool pem(BioByteArray &);
virtual bool pem(BioByteArray &b, const pki_export *xport);
QVariant column_data(const dbheader *hd) const;
QString modulus() const;
QString pubEx() const;
Expand Down
9 changes: 9 additions & 0 deletions test/export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,15 @@ void test_main::exportFormat()
export_by_id(7, file, list, certs);
verify_key(file, QList<unsigned> { END_HASH, ENDKEY_HASH }, true);
check_pems(file, 2, QStringList { " ENCRYPTED PRIVATE KEY-", " CERTIFICATE-" });
// Export OpenVPN format
file = AUTOFILE(OPENVPN)
export_by_id(4, file, list, certs);
verify_key(file, QList<unsigned> {
ROOT_HASH, INTER_HASH, END_HASH, ENDKEY_HASH }, true);
check_pems(file, 4, QStringList { " RSA PRIVATE KEY-",
" CERTIFICATE-", " CERTIFICATE-"," CERTIFICATE-",
"<ca>", "</ca>", "<extra-certs>", "</extra-certs>",
"<cert>", "</cert>", "<key>", "</key>" });
// Export Endentity as PKCS#7
file = AUTOFILE(CERTP7)
export_by_id(8, file, list, certs);
Expand Down

0 comments on commit 0a1a216

Please sign in to comment.