xca/lib/oid.cpp
Christian Hohnstaedt 0212113424 Close #304 oids.txt not found etc if prefix non-standard
Add INSTALL_PREFIX to the header and add it to the search path
for OIDs, translations and documentation.
2024-08-25 00:47:49 +02:00

211 lines
5.3 KiB
C++

/* vi: set sw=4 ts=4:
*
* Copyright (C) 2001 - 2014 Christian Hohnstaedt.
*
* All rights reserved.
*/
/* here we have the possibility to add our own OIDS */
#include <openssl/objects.h>
#include <QStringList>
#include <QStandardPaths>
#include <QRegularExpression>
#include <QDebug>
#include <QDir>
#include "func.h"
#include "oid.h"
#include "XcaWarningCore.h"
int first_additional_oid = 0;
NIDlist extkeyuse_nid;
NIDlist distname_nid;
QMap<QString,const char*> oid_name_clash;
QMap<QString,int> oid_lower_map;
static QStringList searchdirs()
{
QStringList dirs = QStandardPaths::standardLocations(
QStandardPaths::AppDataLocation);
#ifdef INSTALL_DATA_PREFIX
dirs << QString(INSTALL_DATA_PREFIX);
#endif
return dirs;
}
static void addToLowerMap(int nid)
{
QString n = OBJ_nid2sn(nid);
QString l = n.toLower();
if (n != l)
oid_lower_map[l] = nid;
n = OBJ_nid2ln(nid);
l = n.toLower();
if (n != l)
oid_lower_map[l] = nid;
}
/* reads additional OIDs from a file: oid, sn, ln */
static void insert_new_oid(const QStringList &sl, QString fname, int line)
{
bool differs = false;
QByteArray in_use, oid, sn, ln;
if (sl.count() != 3) {
XCA_WARN(QObject::tr("Error reading config file %1 at line %2")
.arg(fname).arg(line));
return;
}
oid = sl[0].toLatin1();
sn = sl[1].toLatin1();
ln = sl[2].toLatin1();
int nid = OBJ_txt2nid(oid.constData());
if (nid != NID_undef) {
/* OID already known by OpenSSL */
if (sn != OBJ_nid2sn(nid)) {
/* ... but with a different ShortName */
qWarning() << "OID: " << oid << "SN differs: " << sn <<
" " << OBJ_nid2sn(nid);
oid_name_clash[sn] = OBJ_nid2sn(nid);
differs = true;
}
if (ln != OBJ_nid2ln(nid)) {
/* ... but with a different LongName */
qWarning() << "OID: " << oid << "LN differs: " << ln <<
" " << OBJ_nid2ln(nid);
oid_name_clash[ln] = OBJ_nid2ln(nid);
differs = true;
}
} else {
/* Check whether ShortName or LongName are already in use
* for a different OID */
if (OBJ_txt2nid(sn.constData()) != NID_undef)
in_use = sn;
if (OBJ_txt2nid(ln.constData()) != NID_undef)
in_use = ln;
}
ign_openssl_error();
if (differs) {
/* OID exists with different SN or LN. The differing names
* are added as "alias" in "oid_name_clash" used when loading
* dn.txt and eku.txt */
XCA_WARN(QObject::tr("The Object '%1' from file %2 line %3 is already known as '%4:%5:%6' and should be removed.")
.arg(sl.join(":")).arg(fname).arg(line)
.arg(OBJ_obj2QString(OBJ_nid2obj(nid), 1))
.arg(OBJ_nid2sn(nid)).arg(OBJ_nid2ln(nid))
);
} else if (!in_use.isEmpty()) {
/* OID does not exist, but SN or LN however do.
* Do NOT create OID and tell the user about */
nid = OBJ_txt2nid(in_use.constData());
XCA_WARN(QObject::tr("The identifier '%1' for OID %2 from file %3 line %4 is already used for a different OID as '%5:%6:%7' and should be changed to avoid conflicts.")
.arg(in_use.constData())
.arg(oid.constData())
.arg(fname).arg(line)
.arg(OBJ_obj2QString(OBJ_nid2obj(nid), 1))
.arg(OBJ_nid2sn(nid)).arg(OBJ_nid2ln(nid))
);
} else if (nid == NID_undef) {
nid=OBJ_create(oid.constData(), sn.constData(), ln.constData());
qDebug() << "Creating OID:" << fname << line <<
nid << oid << sn << ln;
try {
openssl_error();
addToLowerMap(nid);
} catch (errorEx &e) {
errorEx err(errorEx(e.getString() +
QString("%1:%2 OID: %3")
.arg(fname).arg(line).arg(oid.constData())));
XCA_ERROR(err);
}
}
}
static void readOIDs(const QString &fname)
{
int line = 0;
QFile file(fname);
if (!file.open(QIODevice::ReadOnly))
return;
qDebug() << "Read additional OIDs from" << fname;
QTextStream in(&file);
while (!in.atEnd()) {
QString entry = in.readLine().trimmed();
line++;
if (entry.startsWith('#') || entry.isEmpty())
continue;
insert_new_oid(entry.split(QRegularExpression("\\s*:\\s*")),
fname, line);
}
}
/* reads a list of OIDs/SNs from a file and turns them into a QValueList
* of integers, representing the NIDs. Usually to be used by NewX509 for
* the list of ExtendedKeyUsage and Distinguished Name
*/
static NIDlist readNIDlist(const QString &fname)
{
int line = 0, nid;
NIDlist nl;
QFile file(fname);
if (!file.open(QIODevice::ReadOnly))
return nl;
QTextStream in(&file);
while (!in.atEnd()) {
const char *userdefined;
QString entry = in.readLine().trimmed();
line++;
if (entry.startsWith('#') || entry.isEmpty())
continue;
userdefined = oid_name_clash[entry];
if (userdefined)
entry = userdefined;
nid = OBJ_txt2nid(CCHAR(entry));
if (nid == NID_undef)
XCA_WARN(QObject::tr("Unknown object '%1' in file %2 line %3")
.arg(entry).arg(fname).arg(line));
else
nl += nid;
}
openssl_error();
return nl;
}
/* creates a new nid list from the given filename */
static NIDlist read_nidlist(const QString &name)
{
NIDlist nl;
foreach(QString d, searchdirs())
{
nl = readNIDlist(d + "/" + name);
qDebug() << "Read" << nl.count() << "NIDs from"
<< d + "/" + name;
if (nl.count() > 0)
break;
}
return nl;
}
void initOIDs()
{
first_additional_oid = OBJ_new_nid(0);
openssl_error();
for (int i=0; i<first_additional_oid;i++)
addToLowerMap(i);
ign_openssl_error();
foreach(QString d, searchdirs())
readOIDs(d + "/oids.txt");
extkeyuse_nid = read_nidlist("eku.txt");
distname_nid = read_nidlist("dn.txt");
openssl_error();
}