mirror of
https://github.com/chris2511/xca.git
synced 2026-09-13 18:46:25 +05:00
Requests and certificates can display the extensions in the table and be sorted by them. make the key identifiers display in numerical style
505 lines
12 KiB
C++
505 lines
12 KiB
C++
/* vi: set sw=4 ts=4:
|
|
*
|
|
* Copyright (C) 2001 - 2010 Christian Hohnstaedt.
|
|
*
|
|
* All rights reserved.
|
|
*/
|
|
|
|
|
|
#include "pki_temp.h"
|
|
#include "func.h"
|
|
#include "db.h"
|
|
#include "exception.h"
|
|
#include "widgets/MainWindow.h"
|
|
#include <QtCore/QDir>
|
|
|
|
QPixmap *pki_temp::icon= NULL;
|
|
|
|
pki_temp::pki_temp(const pki_temp *pk)
|
|
:pki_x509name(pk->desc)
|
|
{
|
|
class_name = pk->class_name;
|
|
dataVersion=pk->dataVersion;
|
|
pkiType=pk->pkiType;
|
|
|
|
xname=pk->xname;
|
|
subAltName=pk->subAltName;
|
|
issAltName=pk->issAltName;
|
|
crlDist=pk->crlDist;
|
|
authInfAcc=pk->authInfAcc;
|
|
certPol=pk->certPol;
|
|
nsCertType=pk->nsCertType;
|
|
nsComment=pk->nsComment;
|
|
nsBaseUrl=pk->nsBaseUrl;
|
|
nsRevocationUrl=pk->nsRevocationUrl;
|
|
nsCARevocationUrl=pk->nsCARevocationUrl;
|
|
nsRenewalUrl=pk->nsRenewalUrl;
|
|
nsCaPolicyUrl=pk->nsCaPolicyUrl;
|
|
nsSslServerName=pk->nsSslServerName;
|
|
ca=pk->ca;
|
|
bcCrit=pk->bcCrit;
|
|
keyUseCrit=pk->keyUseCrit;
|
|
eKeyUseCrit=pk->eKeyUseCrit;
|
|
subKey=pk->subKey;
|
|
authKey=pk->authKey;
|
|
pathLen=pk->pathLen;
|
|
validN=pk->validN;
|
|
validM=pk->validM;
|
|
validMidn=pk->validMidn;
|
|
keyUse=pk->keyUse;
|
|
eKeyUse=pk->eKeyUse;
|
|
adv_ext=pk->adv_ext;
|
|
noWellDefined=pk->noWellDefined;
|
|
}
|
|
|
|
pki_temp::pki_temp(const QString d)
|
|
:pki_x509name(d)
|
|
{
|
|
class_name = "pki_temp";
|
|
dataVersion=6;
|
|
pkiType=tmpl;
|
|
|
|
subAltName="";
|
|
issAltName="";
|
|
crlDist="";
|
|
authInfAcc="";
|
|
certPol="";
|
|
nsCertType=0;
|
|
nsComment="xca certificate";
|
|
nsBaseUrl="";
|
|
nsRevocationUrl="";
|
|
nsCARevocationUrl="";
|
|
nsRenewalUrl="";
|
|
nsCaPolicyUrl="";
|
|
nsSslServerName="";
|
|
ca=0;
|
|
bcCrit=false;
|
|
keyUseCrit=false;
|
|
eKeyUseCrit=false;
|
|
subKey=false;
|
|
authKey=false;
|
|
validMidn=false;
|
|
pathLen="";
|
|
validN=365;
|
|
validM=0;
|
|
keyUse=0;
|
|
eKeyUse="";
|
|
adv_ext="";
|
|
noWellDefined=false;
|
|
}
|
|
|
|
QString pki_temp::getMsg(msg_type msg)
|
|
{
|
|
/*
|
|
* We do not construct english sentences from fragments
|
|
* to allow proper translations.
|
|
*
|
|
* %1 will be replaced by the internal name of the template
|
|
*/
|
|
switch (msg) {
|
|
case msg_import: return tr("Successfully imported the XCA template '%1'");
|
|
case msg_delete: return tr("Delete the XCA template '%1'?");
|
|
case msg_create: return tr("Successfully created the XCA template '%1'");
|
|
/* %1: Number of ktemplates; %2: list of templatenames */
|
|
case msg_delete_multi: return tr("Delete the %1 XCA templates: %2?");
|
|
}
|
|
return pki_base::getMsg(msg);
|
|
}
|
|
|
|
x509name pki_temp::getSubject() const
|
|
{
|
|
return xname;
|
|
}
|
|
|
|
static int bitsToInt(extList &el, int nid, bool *crit)
|
|
{
|
|
int ret = 0, i = el.idxByNid(nid);
|
|
|
|
if (i != -1) {
|
|
if (crit)
|
|
*crit = el[i].getCritical();
|
|
ASN1_BIT_STRING *bits;
|
|
bits = (ASN1_BIT_STRING *)el[i].d2i();
|
|
|
|
for (int j=0; j<9; j++) {
|
|
if (ASN1_BIT_STRING_get_bit(bits, j))
|
|
ret |= 1 << j;
|
|
}
|
|
el.removeAt(i);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
extList pki_temp::fromCert(pki_x509super *cert_or_req)
|
|
{
|
|
int i;
|
|
x509name n;
|
|
extList el = cert_or_req->getV3ext();
|
|
|
|
nsComment = "";
|
|
|
|
n = cert_or_req->getSubject();
|
|
for (i=0; i<EXPLICIT_NAME_CNT; i++) {
|
|
int nid = NewX509::name_nid[i];
|
|
QString ne = n.popEntryByNid(nid);
|
|
if (!ne.isNull())
|
|
xname.addEntryByNid(nid, ne);
|
|
}
|
|
for (int i=0; i<n.entryCount(); i++) {
|
|
int nid = n.nid(i);
|
|
if (nid != NID_undef)
|
|
xname.addEntryByNid(nid, n.getEntry(i));
|
|
}
|
|
|
|
el.genConf(NID_subject_alt_name, &subAltName, &adv_ext);
|
|
el.genConf(NID_issuer_alt_name, &issAltName, &adv_ext);
|
|
el.genConf(NID_crl_distribution_points, &crlDist, &adv_ext);
|
|
el.genConf(NID_info_access, &authInfAcc, &adv_ext);
|
|
|
|
el.genConf(NID_netscape_comment, &nsComment);
|
|
el.genConf(NID_netscape_base_url, &nsBaseUrl);
|
|
el.genConf(NID_netscape_revocation_url, &nsRevocationUrl);
|
|
el.genConf(NID_netscape_ca_revocation_url, &nsCARevocationUrl);
|
|
el.genConf(NID_netscape_renewal_url, &nsRenewalUrl);
|
|
el.genConf(NID_netscape_ca_policy_url, &nsCaPolicyUrl);
|
|
el.genConf(NID_netscape_ssl_server_name, &nsSslServerName);
|
|
|
|
QString r;
|
|
if (el.genConf(NID_basic_constraints, &r)) {
|
|
QStringList sl = r.split(",");
|
|
if (sl.contains("critical"))
|
|
bcCrit = true;
|
|
ca = sl.contains("CA:TRUE") ? 1 : 2;
|
|
pathLen = sl.filter("pathlen:").join("").mid(8, -1);
|
|
} else {
|
|
bcCrit = false;
|
|
ca = 0;
|
|
}
|
|
authKey = el.delByNid(NID_authority_key_identifier);
|
|
subKey = el.delByNid(NID_subject_key_identifier);
|
|
|
|
nsCertType = bitsToInt(el, NID_netscape_cert_type, NULL);
|
|
/* bit 4 is unused. Move higher bits down. */
|
|
nsCertType = (nsCertType & 0xf) | ((nsCertType & 0xf0) >> 1);
|
|
|
|
keyUse = bitsToInt(el, NID_key_usage, &keyUseCrit);
|
|
|
|
el.genConf(NID_ext_key_usage, &eKeyUse);
|
|
if (eKeyUse.startsWith("critical,")) {
|
|
eKeyUseCrit = true;
|
|
eKeyUse = eKeyUse.mid(9, -1);
|
|
}
|
|
el.genGenericConf(&adv_ext);
|
|
|
|
if (cert_or_req->getType() == x509) {
|
|
pki_x509 *cert = (pki_x509*)cert_or_req;
|
|
if (cert->getNotAfter().isUndefined()) {
|
|
noWellDefined = true;
|
|
} else {
|
|
a1time notBefore = cert->getNotBefore();
|
|
a1time notAfter = cert->getNotAfter();
|
|
|
|
if (notBefore.toPlain().endsWith("000000Z") &&
|
|
notAfter.toPlain().endsWith("235959Z"))
|
|
{
|
|
validMidn = true;
|
|
}
|
|
QDateTime nb = notBefore.qDateTime();
|
|
QDateTime na = notAfter.qDateTime();
|
|
|
|
int diff = nb.daysTo(na);
|
|
validM = 0;
|
|
if (diff > 60) {
|
|
validM = 1;
|
|
diff /= 30;
|
|
if (diff > 24) {
|
|
validM = 2;
|
|
diff /= 12;
|
|
}
|
|
}
|
|
validN = diff;
|
|
}
|
|
}
|
|
return el;
|
|
}
|
|
|
|
void pki_temp::fromData(const unsigned char *p, db_header_t *head )
|
|
{
|
|
int version, size;
|
|
|
|
size = head->len - sizeof(db_header_t);
|
|
version = head->version;
|
|
fromData(p, size, version);
|
|
}
|
|
|
|
static QString old_eKeyUse2QString(int old)
|
|
{
|
|
QStringList sl;
|
|
NIDlist eku_nid = *MainWindow::eku_nid;
|
|
|
|
for (int i=0; i<eku_nid.count(); i++) {
|
|
if (old & (1<<i)) {
|
|
sl << OBJ_nid2sn(eku_nid[i]);
|
|
}
|
|
}
|
|
return sl.join(", ");
|
|
}
|
|
|
|
void pki_temp::fromData(const unsigned char *p, int size, int version)
|
|
{
|
|
QByteArray ba((const char*)p, size);
|
|
|
|
destination = db::stringFromData(ba);
|
|
bcCrit = db::boolFromData(ba);
|
|
keyUseCrit = db::boolFromData(ba);
|
|
eKeyUseCrit = db::boolFromData(ba);
|
|
subKey = db::boolFromData(ba);
|
|
authKey = db::boolFromData(ba);
|
|
ca = db:: intFromData(ba);
|
|
if (version > 5) {
|
|
pathLen = db::stringFromData(ba);
|
|
} else {
|
|
pathLen = QString::number(db::intFromData(ba));
|
|
if (pathLen == "0")
|
|
pathLen = "";
|
|
}
|
|
validN = db::intFromData(ba);
|
|
validM = db::intFromData(ba);
|
|
keyUse = db::intFromData(ba);
|
|
if (version > 4) {
|
|
eKeyUse = db::stringFromData(ba);
|
|
} else {
|
|
int old = db::intFromData(ba);
|
|
eKeyUse = old_eKeyUse2QString(old);
|
|
}
|
|
nsCertType = db::intFromData(ba);
|
|
subAltName = db::stringFromData(ba);
|
|
issAltName = db::stringFromData(ba);
|
|
crlDist = db::stringFromData(ba);
|
|
nsComment = db::stringFromData(ba);
|
|
nsBaseUrl = db::stringFromData(ba);
|
|
nsRevocationUrl = db::stringFromData(ba);
|
|
nsCARevocationUrl = db::stringFromData(ba);
|
|
nsRenewalUrl = db::stringFromData(ba);
|
|
nsCaPolicyUrl = db::stringFromData(ba);
|
|
nsSslServerName = db::stringFromData(ba);
|
|
xname.d2i(ba);
|
|
authInfAcc = db::stringFromData(ba);
|
|
certPol = db::stringFromData(ba);
|
|
validMidn = db::boolFromData(ba);
|
|
if (version>2)
|
|
adv_ext = db::stringFromData(ba);
|
|
if (version>3)
|
|
noWellDefined = db::boolFromData(ba);
|
|
|
|
if (ba.count() > 0) {
|
|
my_error(tr("Wrong Size %1").arg(ba.count()));
|
|
}
|
|
}
|
|
|
|
QByteArray pki_temp::toData()
|
|
{
|
|
QByteArray ba;
|
|
|
|
ba += db::stringToData(destination);
|
|
ba += db::boolToData(bcCrit);
|
|
ba += db::boolToData(keyUseCrit);
|
|
ba += db::boolToData(eKeyUseCrit);
|
|
ba += db::boolToData(subKey);
|
|
ba += db::boolToData(authKey);
|
|
ba += db::intToData(ca);
|
|
ba += db::stringToData(pathLen);
|
|
ba += db::intToData(validN);
|
|
ba += db::intToData(validM);
|
|
ba += db::intToData(keyUse);
|
|
ba += db::stringToData(eKeyUse);
|
|
ba += db::intToData(nsCertType);
|
|
ba += db::stringToData(subAltName);
|
|
ba += db::stringToData(issAltName);
|
|
ba += db::stringToData(crlDist);
|
|
ba += db::stringToData(nsComment);
|
|
ba += db::stringToData(nsBaseUrl);
|
|
ba += db::stringToData(nsRevocationUrl);
|
|
ba += db::stringToData(nsCARevocationUrl);
|
|
ba += db::stringToData(nsRenewalUrl);
|
|
ba += db::stringToData(nsCaPolicyUrl);
|
|
ba += db::stringToData(nsSslServerName);
|
|
ba += xname.i2d();
|
|
ba += db::stringToData(authInfAcc);
|
|
ba += db::stringToData(certPol);
|
|
ba += db::boolToData(validMidn);
|
|
ba += db::stringToData(adv_ext);
|
|
ba += db::boolToData(noWellDefined);
|
|
|
|
return ba;
|
|
}
|
|
|
|
void pki_temp::writeDefault(const QString fname)
|
|
{
|
|
writeTemp(fname + QDir::separator() + getIntName() + ".xca");
|
|
}
|
|
|
|
void pki_temp::writeTemp(QString fname)
|
|
{
|
|
QByteArray data, header;
|
|
FILE *fp = fopen(QString2filename(fname),"w");
|
|
|
|
if (fp == NULL) {
|
|
fopen_error(fname);
|
|
return;
|
|
}
|
|
data = toData();
|
|
header = db::intToData(data.count());
|
|
header += db::intToData(dataVersion);
|
|
header += data;
|
|
fwrite_ba(fp, header, fname);
|
|
fclose(fp);
|
|
}
|
|
|
|
void pki_temp::fload(QString fname)
|
|
{
|
|
int size, s, version;
|
|
const int hsize = 2 * sizeof(uint32_t);
|
|
char buf[hsize];
|
|
unsigned char *p;
|
|
FILE *fp = fopen(QString2filename(fname),"r");
|
|
bool oldimport = false;
|
|
|
|
if (fp == NULL) {
|
|
fopen_error(fname);
|
|
return;
|
|
}
|
|
if (fread(buf, hsize, 1, fp) != 1) {
|
|
fclose(fp);
|
|
my_error(tr("Template file content error (too small): %1").
|
|
arg(fname));
|
|
}
|
|
|
|
QByteArray header(buf, hsize);
|
|
QByteArray backup = header;
|
|
|
|
size = db::intFromData(header);
|
|
version = db::intFromData(header);
|
|
|
|
if (size > 65535 || size <0) {
|
|
/* oldimport templates are prepended by its size in host endianess.
|
|
Set fp after the first int and recover the size */
|
|
fseek(fp, sizeof(int), SEEK_SET);
|
|
size = intFromData(backup);
|
|
if (size > 65535 || size <0) {
|
|
fclose(fp);
|
|
my_error(tr("Template file content error (bad size): %1 ").arg(fname));
|
|
}
|
|
oldimport = true;
|
|
}
|
|
p = (unsigned char *)OPENSSL_malloc(size);
|
|
if (p) {
|
|
if ((s=fread(p, 1, size, fp)) != size) {
|
|
OPENSSL_free(p);
|
|
fclose(fp);
|
|
my_error(tr("Template file content error (bad length) :%1").arg(fname));
|
|
}
|
|
}
|
|
if (oldimport)
|
|
oldFromData(p, size);
|
|
else
|
|
fromData(p, size, version);
|
|
OPENSSL_free(p);
|
|
|
|
setIntName(rmslashdot(fname));
|
|
fclose(fp);
|
|
}
|
|
|
|
pki_temp::~pki_temp()
|
|
{
|
|
|
|
}
|
|
|
|
bool pki_temp::compare(pki_base *)
|
|
{
|
|
// we don't care if templates with identical contents
|
|
// are stored in the database ...
|
|
return false;
|
|
}
|
|
|
|
QVariant pki_temp::column_data(dbheader *hd)
|
|
{
|
|
switch (hd->id) {
|
|
case HD_temp_type:
|
|
return QVariant(destination);
|
|
}
|
|
return pki_x509name::column_data(hd);
|
|
}
|
|
|
|
QVariant pki_temp::getIcon(dbheader *hd)
|
|
{
|
|
return hd->id == HD_internal_name ? QVariant(*icon) : QVariant();
|
|
}
|
|
|
|
void pki_temp::oldFromData(unsigned char *p, int size)
|
|
{
|
|
int version;
|
|
|
|
QByteArray ba((const char*)p, size);
|
|
|
|
version=intFromData(ba);
|
|
intFromData(ba); /* type */
|
|
if (version == 1) {
|
|
ca = 2;
|
|
bool mca = intFromData(ba);
|
|
if (mca) ca = 1;
|
|
}
|
|
bcCrit=db::boolFromData(ba);
|
|
keyUseCrit=db::boolFromData(ba);
|
|
eKeyUseCrit=db::boolFromData(ba);
|
|
subKey=db::boolFromData(ba);
|
|
authKey=db::boolFromData(ba);
|
|
db::boolFromData(ba);
|
|
db::boolFromData(ba);
|
|
if (version >= 2) {
|
|
ca = intFromData(ba);
|
|
}
|
|
pathLen = QString::number(db::intFromData(ba));
|
|
if (pathLen == "0")
|
|
pathLen = "";
|
|
validN = intFromData(ba);
|
|
validM = intFromData(ba);
|
|
keyUse=intFromData(ba);
|
|
int old=db::intFromData(ba);
|
|
eKeyUse = old_eKeyUse2QString(old);
|
|
nsCertType=intFromData(ba);
|
|
if (version == 1) {
|
|
xname.addEntryByNid(OBJ_sn2nid("C"), db::stringFromData(ba));
|
|
xname.addEntryByNid(OBJ_sn2nid("ST"), db::stringFromData(ba));
|
|
xname.addEntryByNid(OBJ_sn2nid("L"), db::stringFromData(ba));
|
|
xname.addEntryByNid(OBJ_sn2nid("O"), db::stringFromData(ba));
|
|
xname.addEntryByNid(OBJ_sn2nid("OU"), db::stringFromData(ba));
|
|
xname.addEntryByNid(OBJ_sn2nid("CN"), db::stringFromData(ba));
|
|
xname.addEntryByNid(OBJ_sn2nid("Email"),db::stringFromData(ba));
|
|
}
|
|
subAltName=db::stringFromData(ba);
|
|
issAltName=db::stringFromData(ba);
|
|
crlDist=db::stringFromData(ba);
|
|
nsComment=db::stringFromData(ba);
|
|
nsBaseUrl=db::stringFromData(ba);
|
|
nsRevocationUrl=db::stringFromData(ba);
|
|
nsCARevocationUrl=db::stringFromData(ba);
|
|
nsRenewalUrl=db::stringFromData(ba);
|
|
nsCaPolicyUrl=db::stringFromData(ba);
|
|
nsSslServerName=db::stringFromData(ba);
|
|
// next version:
|
|
if (version >= 2) {
|
|
xname.d2i(ba);
|
|
}
|
|
if (version >= 3) {
|
|
authInfAcc=db::stringFromData(ba);
|
|
certPol=db::stringFromData(ba);
|
|
validMidn=db::boolFromData(ba);
|
|
}
|
|
|
|
if (ba.count() > 0) {
|
|
my_error(tr("Wrong Size %1").arg(ba.count()));
|
|
}
|
|
}
|
|
|