xca/lib/db_x509.cpp
Adam Dawidowski 0d34bc1c1c Extend generating an OpenSSL "index.txt"
Updated patch adds another export option automating the creation
of multiple index.txt files to be used with multiple ocsp responders.

New export option is available via command line (-I index.txt) and
the Extras menu (Extra->Export Certificate Index hierarchy).

The option causes the creation of an index.txt file containing
index records for all the children certificates of a parent.
The filenames are generated using the supplied name as prefix
and append a dot and the simplified Internal Name
(the Internal Name stripped of non-alphanumeric characters except underscores).
2016-09-06 20:03:55 +02:00

1168 lines
27 KiB
C++

/* vi: set sw=4 ts=4:
*
* Copyright (C) 2001 - 2014 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include "db_x509.h"
#include "pki_pkcs12.h"
#include "pki_pkcs7.h"
#include "pki_evp.h"
#include "pki_scard.h"
#include "pass_info.h"
#include "widgets/CertDetail.h"
#include "widgets/CertExtend.h"
#include "widgets/ExportDialog.h"
#include "widgets/MainWindow.h"
#include "widgets/PwDialog.h"
#include "widgets/RevocationList.h"
#include "ui_TrustState.h"
#include "ui_CaProperties.h"
#include "ui_About.h"
#include <QMessageBox>
#include <QContextMenuEvent>
#include <QAction>
bool db_x509::treeview = true;
db_x509::db_x509(QString DBfile, MainWindow *mw)
:db_x509super(DBfile, mw)
{
rootItem->setIntName("[x509 root]");
class_name = "certificates";
pkitype << x509;
updateHeaders();
loadContainer();
}
void db_x509::updateAfterCrlLoad(pki_x509 *pki)
{
if (pki->revList.merged) {
updatePKI(pki);
pki->revList.merged = false;
}
}
void db_x509::updateAfterDbLoad()
{
FOR_ALL_pki(pki, pki_x509) {
updateAfterCrlLoad(pki);
}
}
dbheaderList db_x509::getHeaders()
{
dbheaderList h = db_x509super::getHeaders();
h << new dbheader(HD_cert_ca, true, tr("CA"),
tr("reflects the basic Constraints extension")) <<
new dbheader(HD_cert_serial, true, tr("Serial")) <<
new dbheader(HD_cert_md5fp, false,tr("MD5 fingerprint")) <<
new dbheader(HD_cert_sha1fp, false,tr("SHA1 fingerprint")) <<
new dbheader(HD_cert_sha256fp, false,tr("SHA256 fingerprint")) <<
new dbheader(HD_cert_notBefore, false,tr("Start date"),
tr("Not before")) <<
new dbheader(HD_cert_notAfter, true, tr("Expiry date"),
tr("Not after")) <<
new dbheader(HD_cert_trust, false,tr("Trust state")) <<
new dbheader(HD_cert_revocation,false, tr("Revocation")) <<
new dbheader(HD_cert_crl_expire,true, tr("CRL Expiration"));
return h;
}
pki_base *db_x509::newPKI(db_header_t *)
{
return new pki_x509();
}
pki_x509 *db_x509::findSigner(pki_x509 *client)
{
pki_x509 *signer;
if ((signer = client->getSigner()) != NULL)
return signer;
// first check for self-signed
if (client->verify(client)) {
return client;
}
FOR_ALL_pki(pki, pki_x509) {
if (client->verify(pki)) {
return pki;
}
}
return NULL;
}
QStringList db_x509::getPrivateDesc()
{
QStringList x;
FOR_ALL_pki(pki, pki_x509)
if (pki->getRefKey())
x.append(pki->getIntName());
return x;
}
QStringList db_x509::getSignerDesc()
{
QStringList x;
FOR_ALL_pki(pki, pki_x509)
if (pki->canSign())
x.append(pki->getIntName());
return x;
}
void db_x509::remFromCont(QModelIndex &idx)
{
int row;
pki_base *pki = static_cast<pki_base*>(idx.internalPointer());
pki_base *parent_pki = pki->getParent();
row = pki->row();
pki_x509 *child;
pki_base *new_parent;
QModelIndex new_idx;
beginRemoveRows(parent(idx), row, row);
parent_pki->takeChild(pki);
endRemoveRows();
while (pki->childCount()) {
child = (pki_x509*)pki->childItems.takeFirst();
child->delSigner((pki_x509*)pki);
new_parent = findSigner(child);
insertChild(new_parent, child);
}
mainwin->crls->removeSigner(pki);
pki_key *pub = ((pki_x509*)pki)->getPubKey();
if (pub) {
if (mainwin->certs->findByPubKey(pub).count() == 0) {
QList<pki_x509super *> reqs;
reqs = mainwin->reqs->findByPubKey(pub);
foreach(pki_x509super *r, reqs)
((pki_x509req*)r)->setDone(false);
}
delete pub;
}
return;
}
void db_x509::changeView()
{
pki_base *temproot;
int rows = rowCount(QModelIndex());
if (!rows)
return;
temproot = new pki_base();
beginRemoveRows(QModelIndex(), 0, rows -1);
pki_base *pki = rootItem;
pki_base *parent;
while(pki->childCount()) {
pki = pki->takeFirst();
while(pki != rootItem && !pki->childCount()) {
parent = pki->getParent();
temproot->append(pki);
pki = parent;
}
}
endRemoveRows();
treeview = !treeview;
if (treeview)
mainwin->BNviewState->setText(tr("Plain View"));
else
mainwin->BNviewState->setText(tr("Tree View"));
while ((temproot->childCount())) {
pki = temproot->takeFirst();
inToCont(pki);
}
delete temproot;
}
void db_x509::calcEffTrust()
{
FOR_ALL_pki(pki, pki_x509)
pki->calcEffTrust();
}
static bool recursiveSigning(pki_x509 *cert, pki_x509 *client)
{
/* recursive signing check */
for (pki_x509 *s = cert->getSigner(); s; s = s->getSigner()) {
if (s == s->getSigner()) {
return false;
}
if (s == client) {
printf("Recursive signing: '%s' <-> '%s'\n",
CCHAR(s->getIntName()),
CCHAR(cert->getIntName()));
return true;
}
}
return false;
}
void db_x509::inToCont(pki_base *pki)
{
pki_x509 *cert = (pki_x509*)pki;
cert->setParent(NULL);
cert->delSigner(cert->getSigner());
findSigner(cert);
pki_base *root = cert->getSigner();
if (!treeview || root == cert || root == NULL)
root = rootItem;
insertChild(root, cert);
QList<pki_x509 *> childs;
/* Search for another certificate (name and key)
* and use its childs if we are newer */
FOR_ALL_pki(client, pki_x509) {
if (client == cert)
continue;
if (!client->compareNameAndKey(cert))
continue;
if (cert->getNotAfter() < client->getNotAfter())
continue;
foreach(pki_base *_child, client->childItems) {
pki_x509 *child = static_cast<pki_x509*>(_child);
child->delSigner(client);
childs << child;
}
}
/* Search rootItem childs, whether they are ours */
foreach(pki_base *_child, rootItem->childItems) {
pki_x509 *child = static_cast<pki_x509*>(_child);
if (child == cert || child->getSigner() == child)
continue;
if (child->verify_only(cert))
childs << child;
}
/* move collected childs to us */
foreach(pki_x509 *child, childs) {
int row;
if (recursiveSigning(cert, child))
continue;
if (!child->verify(cert))
continue;
row = child->row();
beginRemoveRows(index(child), row, row);
child->getParent()->takeChild(child);
endRemoveRows();
if (treeview)
insertChild(cert, child);
else
insertChild(rootItem, child);
}
findKey(cert);
pki_key *pub = cert->getPubKey();
if (pub) {
QList<pki_x509super *> reqs = mainwin->reqs->findByPubKey(pub);
delete pub;
foreach(pki_x509super *r, reqs) {
((pki_x509req*)r)->setDone();
}
}
calcEffTrust();
}
pki_x509 *db_x509::getBySubject(const x509name &xname, pki_x509 *last)
{
bool lastfound = false;
if (last == NULL) lastfound = true;
FOR_ALL_pki(pki, pki_x509) {
if ( pki->getSubject() == xname) {
if (lastfound) {
return pki;
}
}
if (pki == last) {
lastfound = true;
}
}
return NULL;
}
void db_x509::writeAllCerts(const QString fname, bool onlyTrusted)
{
bool append = false;
FOR_ALL_pki(pki, pki_x509) {
if (onlyTrusted && pki->getTrust() != 2) continue;
pki->writeCert(fname.toLatin1(), true, append);
append = true;
}
}
QList<pki_x509*> db_x509::getCerts(bool onlyTrusted)
{
QList<pki_x509*> c;
c.clear();
FOR_ALL_pki(pki, pki_x509) {
if (onlyTrusted && pki->getTrust() != 2) continue;
c.append(pki);
}
return c;
}
void db_x509::writeIndex(const QString fname, bool hierarchy)
{
bool append = false;
if (hierarchy) {
FOR_ALL_pki(pki, pki_x509) {
if (pki->childCount()) {
QString newfname = fname + "." + pki->getIntName().replace(QRegExp("[^a-zA-Z0-9]"),QString(""));;
append = false;
foreach(pki_base *_child, pki->childItems) {
pki_x509 *child = static_cast<pki_x509*>(_child);
child->writeIndexEntry(newfname, append);
append = true;
}
}
}
} else {
FOR_ALL_pki(pki, pki_x509) {
pki->writeIndexEntry(fname, append);
append = true;
}
}
}
a1int db_x509::searchSerial(pki_x509 *signer)
{
// returns the highest certificate serial
// of all certs with this signer (itself too)
a1int sserial, myserial;
if (!signer)
return sserial;
sserial = signer->getCaSerial();
FOR_ALL_pki(pki, pki_x509)
if (pki->getSigner() == signer) {
myserial = pki->getSerial();
if (sserial < myserial) {
sserial = myserial;
}
}
return sserial;
}
a1int db_x509::getUniqueSerial(pki_x509 *signer)
{
// returnes an unused unique serial
a1int serial;
x509rev rev;
while (true) {
serial = signer->getIncCaSerial();
rev.setSerial(serial);
if (signer->revList.contains(rev))
continue;
if (signer->getBySerial(serial))
continue;
break;
}
if (!signer->usesRandomSerial())
updatePKI(signer);
return serial;
}
pki_base *db_x509::insert(pki_base *item)
{
pki_x509 *cert = (pki_x509 *)item;
pki_x509 *oldcert = (pki_x509 *)getByReference(cert);
if (oldcert) {
XCA_INFO(tr("The certificate already exists in the database as:\n'%1'\nand so it was not imported").arg(oldcert->getIntName()));
delete(cert);
return NULL;
}
cert->setCaSerial((cert->getSerial()));
insertPKI(cert);
a1int serial;
// check the CA serial of the CA of this cert to avoid serial doubles
if (cert->getSigner() != cert && cert->getSigner()) {
serial = cert->getSerial();
if (cert->getSigner()->getCaSerial() < ++serial ) {
cert->getSigner()->setCaSerial(serial);
updatePKI(cert->getSigner());
}
}
// check CA serial of this cert
serial = searchSerial(cert);
if ( ++serial > cert->getCaSerial()) {
cert->setCaSerial(serial);
}
if (mainwin->crls) {
mainwin->crls->updateRevocations(cert);
}
updatePKI(cert);
return cert;
}
void db_x509::load(void)
{
load_cert c;
load_default(c);
}
pki_x509 *db_x509::get1SelectedCert()
{
QModelIndexList indexes = mainwin->certView->getSelectedIndexes();
QModelIndex index;
if (indexes.count())
index = indexes[0];
if (index == QModelIndex())
return NULL;
return static_cast<pki_x509*>(index.internalPointer());
}
void db_x509::newItem()
{
NewX509 *dlg = new NewX509(mainwin);
emit connNewX509(dlg);
dlg->setCert();
pki_x509 *sigcert = get1SelectedCert();
dlg->defineSigner((pki_x509*)sigcert);
if (dlg->exec()) {
newCert(dlg);
}
delete dlg;
}
void db_x509::newCert(pki_x509req *req)
{
NewX509 *dlg = new NewX509(mainwin);
emit connNewX509(dlg);
pki_x509 *sigcert = get1SelectedCert();
dlg->setCert();
dlg->defineRequest(req);
dlg->defineSigner(sigcert);
if (dlg->exec()) {
newCert(dlg);
}
delete dlg;
}
void db_x509::newCert(pki_temp *temp)
{
NewX509 *dlg = new NewX509(mainwin);
emit connNewX509(dlg);
dlg->setCert();
dlg->defineTemplate(temp);
if (dlg->exec()) {
newCert(dlg);
}
delete dlg;
}
void db_x509::newCert(pki_x509 *cert)
{
NewX509 *dlg = new NewX509(mainwin);
emit connNewX509(dlg);
dlg->setCert();
dlg->defineCert(cert);
if (dlg->exec()) {
newCert(dlg);
}
delete dlg;
}
void db_x509::newCert(NewX509 *dlg)
{
pki_x509 *cert = NULL;
pki_x509 *signcert = NULL;
pki_x509req *req = NULL;
pki_key *signkey = NULL, *clientkey = NULL, *tempkey = NULL;
a1int serial;
x509name subject;
QString intname;
try {
// Step 1 - Subject and key
if (!dlg->fromReqCB->isChecked()) {
clientkey = dlg->getSelectedKey();
if (!clientkey)
return;
subject = dlg->getX509name();
intname = dlg->description->text();
} else {
// A PKCS#10 Request was selected
req = dlg->getSelectedReq();
if (!req)
return;
clientkey = req->getRefKey();
if (clientkey == NULL) {
clientkey = req->getPubKey();
tempkey = clientkey;
}
if (dlg->reqSubChange->isChecked())
subject = dlg->getX509name();
else
subject = req->getSubject();
intname = req->getIntName();
}
if (clientkey == NULL)
throw errorEx(tr("Invalid public key"));
// initially create cert
cert = new pki_x509();
cert->setIntName(intname);
cert->setSubject(subject);
cert->setPubKey(clientkey);
// Step 2 - select Signing
if (dlg->foreignSignRB->isChecked()) {
signcert = dlg->getSelectedSigner();
if (!signcert)
return;
serial = getUniqueSerial(signcert);
signkey = signcert->getRefKey();
cert->setTrust(1);
#ifdef WG_QA_SERIAL
} else if (dlg->selfQASignRB->isChecked()){
Passwd pass;
pass_info p(XCA_TITLE, tr("Please enter the new hexadecimal secret number for the QA process."));
if (PwDialog::execute(&p, &pass, true) != 1)
throw errorEx(tr("The QA process has been terminated by the user."));
signcert = cert;
signkey = clientkey;
serial.setHex(pass);
cert->setTrust(2);
#endif
} else {
signcert = cert;
signkey = clientkey;
serial.setHex(dlg->serialNr->text());
cert->setTrust(2);
}
dlg->initCtx(cert, signcert, NULL);
// if we can not sign
if (! signkey || signkey->isPubKey()) {
free(cert);
throw errorEx(tr("The key you selected for signing is not a private one."));
}
// set the issuers name
cert->setIssuer(signcert->getSubject());
cert->setSerial(serial);
// Step 3 - Choose the Date
// Date handling
cert->setNotBefore(dlg->notBefore->getDate());
a1time a;
if (dlg->noWellDefinedExpDate->isChecked())
a.setUndefined();
else
a = dlg->notAfter->getDate();
cert->setNotAfter(a);
// STEP 4 handle extensions
// apply all extensions to the subject cert in the context
dlg->getAllExt();
// apply extensions from CSR if requested
if (dlg->copyReqExtCB->isChecked() && dlg->fromReqCB->isChecked()) {
extList el = req->getV3ext();
int m = el.count();
for (int i=0; i<m; i++)
cert->addV3ext(el[i], true);
}
const EVP_MD *hashAlgo = dlg->hashAlgo->currentHash();
#ifdef WG_QA_SERIAL
if (dlg->selfQASignRB->isChecked()) {
// sign the request intermediately in order to finally fill
// up the cert_info substructure.
cert->sign(signkey, hashAlgo);
// now set the QA serial.
cert->setSerial(cert->hashInfo(EVP_md5()));
}
#endif
// and finally sign the request
cert->sign(signkey, hashAlgo);
cert = (pki_x509*)insert(cert);
createSuccess(cert);
updatePKI(signcert);
if (cert && clientkey->isToken()) {
pki_scard *card = (pki_scard*)clientkey;
if (XCA_YESNO(tr("Store the certificate to the key on the token '%1 (#%2)' ?").
arg(card->getCardLabel()).arg(card->getSerial())))
{
try {
cert->store_token(false);
} catch (errorEx &err) {
mainwin->Error(err);
}
}
}
if (tempkey != NULL)
delete(tempkey);
tempkey = NULL;
}
catch (errorEx &err) {
mainwin->Error(err);
delete cert;
if (tempkey != NULL)
delete(tempkey);
}
}
void db_x509::showPki(pki_base *pki)
{
pki_x509 *crt = (pki_x509 *)pki;
CertDetail *dlg;
dlg = new CertDetail(mainwin);
if (dlg) {
dlg->setCert(crt);
connect(dlg->privKey, SIGNAL(doubleClicked(QString)),
mainwin->keys, SLOT(showItem(QString)));
connect(dlg->signature, SIGNAL(doubleClicked(QString)),
this, SLOT( showItem(QString) ));
dlg->exec();
delete dlg;
}
}
void db_x509::store(QModelIndex idx)
{
QModelIndexList l;
l << idx;
store(l);
}
void db_x509::store(QModelIndexList list)
{
QStringList filt;
bool append, chain;
QList<exportType> types, usual;
if (list.size() == 0)
return;
pki_x509 *crt = static_cast<pki_x509*>(list[0].internalPointer());
pki_x509 *oldcrt = NULL;
if (!crt)
return;
pki_key *privkey = crt->getRefKey();
pki_evp *pkey;
chain = crt->getSigner() && crt->getSigner() != crt;
usual <<
exportType(exportType::PEM, "crt", "PEM") <<
exportType(exportType::PKCS7, "p7b", "PKCS #7");
types << exportType(exportType::DER, "cer", "DER");
if (list.size() > 1) {
usual <<
exportType(exportType::PEM_selected, "pem",
"PEM selected") <<
exportType(exportType::PKCS7_selected, "pem",
"PKCS7 selected");
}
if (chain) {
types <<
exportType(exportType::PEM_chain, "pem",
tr("PEM chain")) <<
exportType(exportType::PKCS7_chain, "p7b",
tr("PKCS#7 chain"));
}
if (privkey && privkey->isPrivKey() && !privkey->isToken()) {
if (chain) {
usual << exportType(exportType::PKCS12_chain, "p12",
tr("PKCS#12 chain"));
types << exportType(exportType::PKCS12, "p12",
"PKCS #12");
} else {
usual << exportType(exportType::PKCS12, "p12",
"PKCS #12");
}
types <<
exportType(exportType::PEM_cert_key, "pem",
tr("PEM + key")) <<
exportType(exportType::PEM_cert_pk8, "pem",
"PEM + PKCS#8");
}
types << exportType() <<
exportType(exportType::PKCS7_trusted, "p7b",
tr("PKCS#7 trusted")) <<
exportType(exportType::PKCS7_all, "p7b",
tr("PKCS#7 all")) <<
exportType(exportType::PEM_trusted, "pem",
tr("PEM trusted")) <<
exportType(exportType::PEM_all, "pem",
tr("PEM all")) <<
exportType(exportType::Index, "txt",
tr("Certificate Index file"));
types = usual << exportType() << types;
ExportDialog *dlg = new ExportDialog(mainwin, tr("Certificate export"),
tr("X509 Certificates ( *.pem *.cer *.crt *.p12 *.p7b )"), crt,
MainWindow::certImg, types);
if (!dlg->exec()) {
delete dlg;
return;
}
QString fname = dlg->filename->text();
enum exportType::etype type = dlg->type();
delete dlg;
try {
switch (type) {
case exportType::PEM:
crt->writeCert(fname, true, false);
break;
case exportType::PEM_chain:
append = false;
while(crt && crt != oldcrt) {
crt->writeCert(fname, true, append);
append = true;
oldcrt = crt;
crt = crt->getSigner();
}
break;
case exportType::PEM_selected:
append = false;
foreach(QModelIndex idx, list) {
crt = static_cast<pki_x509*>(idx.internalPointer());
crt->writeCert(fname, true, append);
append = true;
}
break;
case exportType::PEM_trusted:
writeAllCerts(fname,true);
break;
case exportType::PEM_all:
writeAllCerts(fname,false);
break;
case exportType::DER:
crt->writeCert(fname,false,false);
break;
case exportType::PKCS7:
case exportType::PKCS7_chain:
case exportType::PKCS7_trusted:
case exportType::PKCS7_selected:
case exportType::PKCS7_all:
writePKCS7(crt, fname, type, list);
break;
case exportType::PKCS12:
writePKCS12(crt, fname,false);
break;
case exportType::PKCS12_chain:
writePKCS12(crt, fname,true);
break;
case exportType::PEM_cert_pk8:
case exportType::PEM_cert_key:
pkey = (pki_evp *)crt->getRefKey();
if (!pkey || pkey->isPubKey()) {
XCA_WARN(tr("There was no key found for the Certificate: '%1'").
arg(crt->getIntName()));
return;
}
if (pkey->isToken()) {
XCA_WARN(tr("Not possible for a token key: '%1'").
arg(crt->getIntName()));
return;
}
if (type == exportType::PEM_cert_pk8) {
pkey->writePKCS8(fname, EVP_des_ede3_cbc(),
PwDialog::pwCallback, true);
} else {
pkey->writeKey(fname, NULL, NULL, true);
}
crt->writeCert(fname, true, true);
break;
case exportType::Index:
append = false;
foreach(QModelIndex idx, list) {
crt = static_cast<pki_x509*>(idx.internalPointer());
crt->writeIndexEntry(fname, append);
append = true;
}
break;
default:
exit(1);
}
}
catch (errorEx &err) {
MainWindow::Error(err);
}
}
void db_x509::writePKCS12(pki_x509 *cert, QString s, bool chain)
{
QStringList filt;
try {
pki_evp *privkey = (pki_evp *)cert->getRefKey();
if (!privkey || privkey->isPubKey()) {
XCA_WARN(tr("There was no key found for the Certificate: '%1'").arg(cert->getIntName()));
return;
}
if (privkey->isToken()) {
XCA_WARN(tr("Not possible for the token-key Certificate '%1'").
arg(cert->getIntName()));
return;
}
if (s.isEmpty())
return;
s = nativeSeparator(s);
pki_pkcs12 *p12 = new pki_pkcs12(cert->getIntName(), cert, privkey);
pki_x509 *signer = cert->getSigner();
while ((signer != NULL ) && (signer != cert) && chain) {
p12->addCaCert(signer);
cert=signer;
signer=signer->getSigner();
}
p12->writePKCS12(s);
delete p12;
}
catch (errorEx &err) {
MainWindow::Error(err);
}
}
void db_x509::writePKCS7(pki_x509 *cert, QString s, exportType::etype type,
QModelIndexList list)
{
pki_pkcs7 *p7 = NULL;
try {
p7 = new pki_pkcs7("");
switch (type) {
case exportType::PKCS7_chain:
while (cert != NULL) {
p7->addCert(cert);
if (cert->getSigner() == cert)
cert = NULL;
else
cert = cert->getSigner();
}
break;
case exportType::PKCS7:
p7->addCert(cert);
break;
case exportType::PKCS7_selected:
foreach(QModelIndex idx, list) {
cert = static_cast<pki_x509*>(idx.internalPointer());
p7->addCert(cert);
}
break;
case exportType::PKCS7_trusted:
case exportType::PKCS7_all:
FOR_ALL_pki(cer, pki_x509) {
if ((type == exportType::PKCS7_all) ||
(cer->getTrust() == 2))
p7->addCert(cer);
}
break;
default:
exit(1);
}
p7->writeP7(s, false);
}
catch (errorEx &err) {
MainWindow::Error(err);
}
if (p7 != NULL )
delete p7;
}
void db_x509::manageRevocations(QModelIndex idx)
{
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
if (!cert)
return;
RevocationList *dlg = new RevocationList(mainwin);
dlg->setRevList(cert->revList, cert);
connect(dlg, SIGNAL(genCRL(pki_x509*)),
mainwin->crls, SLOT(newItem(pki_x509*)));
if (dlg->exec()) {
cert->setRevocations(dlg->getRevList());
updatePKI(cert);
emit columnsContentChanged();
}
}
void db_x509::setTrust(QModelIndexList indexes)
{
int newstate = -1;
Ui::TrustState ui;
pki_x509 *cert = NULL;
if (indexes.size() == 0)
return;
if (indexes.size() == 1)
cert = static_cast<pki_x509*>(indexes[0].internalPointer());
QDialog *dlg = new QDialog(mainwin);
ui.setupUi(dlg);
ui.image->setPixmap(*MainWindow::certImg);
if (cert) {
int state = cert->getTrust();
if (cert->getSigner() == cert) {
if (state == 1)
state = 0;
ui.trust1->setDisabled(true);
}
if (state == 0 ) ui.trust0->setChecked(true);
if (state == 1 ) ui.trust1->setChecked(true);
if (state == 2 ) ui.trust2->setChecked(true);
}
if (!dlg->exec()) {
delete dlg;
return;
}
if (ui.trust0->isChecked()) newstate = 0;
if (ui.trust1->isChecked()) newstate = 1;
if (ui.trust2->isChecked()) newstate = 2;
delete dlg;
if (newstate == -1) {
return;
}
foreach(QModelIndex idx, indexes) {
cert = static_cast<pki_x509*>(idx.internalPointer());
if (newstate != cert->getTrust()) {
cert->setTrust(newstate);
updatePKI(cert);
}
}
}
void db_x509::certRenewal(QModelIndexList indexes)
{
pki_x509 *oldcert = NULL, *signer = NULL, *newcert =NULL;
pki_key *signkey = NULL;
a1time time;
a1int serial;
CertExtend *dlg = NULL;
x509rev r;
bool doRevoke = false;
if (indexes.size() == 0)
return;
QModelIndex idx = indexes[0];
try {
oldcert = static_cast<pki_x509*>(idx.internalPointer());
if (!oldcert ||
!(signer = oldcert->getSigner()) ||
!(signkey = signer->getRefKey()) ||
signkey->isPubKey())
return;
CertExtend *dlg = new CertExtend(mainwin, signer);
if (!dlg->exec()) {
delete dlg;
return;
}
if (dlg->revoke->isChecked()) {
Revocation *revoke = new Revocation(mainwin, indexes);
doRevoke = revoke->exec();
r = revoke->getRevocation();
delete revoke;
}
foreach(idx, indexes) {
oldcert = static_cast<pki_x509*>
(idx.internalPointer());
newcert = new pki_x509(oldcert);
serial = getUniqueSerial(signer);
newcert->setRevoked(x509rev());
// change date and serial
newcert->setSerial(serial);
newcert->setNotBefore(dlg->notBefore->getDate());
a1time a;
if (dlg->noWellDefinedExpDate->isChecked())
a.setUndefined();
else
a = dlg->notAfter->getDate();
newcert->setNotAfter(a);
// and finally sign the cert
newcert->sign(signkey, oldcert->getDigest());
newcert = (pki_x509 *)insert(newcert);
createSuccess(newcert);
}
if (doRevoke)
do_revoke(indexes, r);
}
catch (errorEx &err) {
MainWindow::Error(err);
if (newcert)
delete newcert;
}
if (dlg)
delete dlg;
emit columnsContentChanged();
}
void db_x509::revoke(QModelIndexList indexes)
{
if (indexes.size() == 0)
return;
Revocation *revoke = new Revocation(mainwin, indexes);
if (revoke->exec()) {
do_revoke(indexes, revoke->getRevocation());
}
emit columnsContentChanged();
}
void db_x509::do_revoke(QModelIndexList indexes, const x509rev &r)
{
pki_x509 *parent = NULL, *cert, *iss;
x509revList revlist;
foreach(QModelIndex idx, indexes) {
cert = static_cast<pki_x509*>(idx.internalPointer());
iss = cert->getSigner();
if (parent == NULL) {
parent = iss;
} else if (parent != iss) {
parent = NULL;
break;
}
}
if (!parent) {
qWarning("%s(%d): Certs have different/no signer\n",
__func__, __LINE__);
}
foreach(QModelIndex idx, indexes) {
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
x509rev rev(r);
rev.setSerial(cert->getSerial());
cert->setRevoked(rev);
revlist << rev;
}
parent->mergeRevList(revlist);
updatePKI(parent);
}
void db_x509::unRevoke(QModelIndexList indexes)
{
pki_x509 *parent = NULL;
foreach(QModelIndex idx, indexes) {
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
if (!cert)
return;
pki_x509 *iss = cert->getSigner();
if (parent == NULL) {
parent = iss;
} else if (parent != iss) {
parent = NULL;
break;
}
}
if (!parent) {
qWarning("%s(%d): Certs have different/no signer\n",
__func__, __LINE__);
}
foreach(QModelIndex idx, indexes) {
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
int i;
x509rev rev;
cert->setRevoked(x509rev());
rev.setSerial(cert->getSerial());
i = parent->revList.indexOf(rev);
if (i != -1)
parent->revList.takeAt(i);
}
updatePKI(parent);
emit columnsContentChanged();
}
void db_x509::toCertificate(QModelIndex index)
{
pki_x509 *cert = static_cast<pki_x509*>(index.internalPointer());
if (!cert)
return;
if (!cert->getRefKey() && cert->getSigner() != cert)
extractPubkey(index);
newCert(cert);
}
void db_x509::toRequest(QModelIndex idx)
{
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
if (!cert)
return;
try {
pki_x509req *req = new pki_x509req();
check_oom(req);
req->setIntName(cert->getIntName());
req->createReq(cert->getRefKey(), cert->getSubject(),
cert->getRefKey()->getDefaultMD(), cert->getV3ext());
createSuccess(mainwin->reqs->insert(req));
}
catch (errorEx &err) {
mainwin->Error(err);
}
}
void db_x509::toToken(QModelIndex idx, bool alwaysSelect)
{
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
if (!cert)
return;
try {
cert->store_token(alwaysSelect);
} catch (errorEx &err) {
mainwin->Error(err);
}
}
void db_x509::caProperties(QModelIndex idx)
{
Ui::CaProperties ui;
int i;
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
if (!cert)
return;
QDialog *dlg = new QDialog(mainwin);
ui.setupUi(dlg);
ui.serial->setText(cert->getCaSerial().toHex());
ui.serial->setDisabled(cert->usesRandomSerial());
ui.randomSerial->setChecked(cert->usesRandomSerial());
ui.days->setSuffix(tr(" days"));
ui.days->setMaximum(1000000);
ui.days->setValue(cert->getCrlDays());
ui.image->setPixmap(*MainWindow::certImg);
QString templ = cert->getTemplate();
QStringList tempList = mainwin->temps->getDesc();
for (i=0; i<tempList.count(); i++) {
if (tempList[i] == templ)
break;
}
ui.temp->addItems(tempList);
ui.temp->setCurrentIndex(i);
ui.certName->setTitle(cert->getIntName());
if (dlg->exec()) {
a1int nserial;
cert->setCrlDays(ui.days->value());
nserial.setHex(ui.serial->text());
cert->setCaSerial(nserial);
cert->setTemplate(ui.temp->currentText());
cert->setUseRandomSerial(ui.randomSerial->isChecked());
updatePKI(cert);
}
delete dlg;
}