1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
|
/* 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();
}
|