Switch database format to SQL(ite)

This is a large squash of many small commits.

Allow porting data from the legacy format to SQL.
Store Binaries base64 encoded and use db->transaction
Update password hash to be 8000 x SHA512 with 8 byte Salt
Add revocations table and fixup CRL generation
Add comment and insertion date columns

Fix column saving, remove trust, add XcaDialog
Allow changing the internal name and comment in Cert/Req details view
Extend Comment functionality, Replace About.ui by XcaDialog.ui
This commit is contained in:
Christian Hohnstaedt 2015-09-26 18:18:10 +02:00
parent e52263e4a3
commit 4b3ee2c705
85 changed files with 3929 additions and 2986 deletions

View File

@ -110,7 +110,7 @@ if test "${WANT_QT_VERSION}" = detect -o "${WANT_QT_VERSION}" = 5; then
QT_UIC="${_QT_HOST_BINS}/uic"
if test -n "$DARWIN"; then
FRAMEDIR=`pkg-config --variable=libdir Qt5Core`
Qt5_CFLAGS="$Qt5_CFLAGS -std=c++11 -F${FRAMEDIR} -I${FRAMEDIR}/QtCore.framework/Headers -I${FRAMEDIR}/QtGui.framework/Headers -I${FRAMEDIR}/QtWdgets.framework/Headers -Xlinker -rpath -Xlinker ${FRAMEDIR}"
Qt5_CFLAGS="$Qt5_CFLAGS -std=c++11 -F${FRAMEDIR} -I${FRAMEDIR}/QtCore.framework/Headers -I${FRAMEDIR}/QtGui.framework/Headers -I${FRAMEDIR}/QtWdgets.framework/Headers -I${FRAMEDIR}/QtSql.framework/Headers -Xlinker -rpath -Xlinker ${FRAMEDIR}"
fi
WANT_QT_VERSION=5
QT_VERSION=5
@ -128,7 +128,7 @@ if test "${WANT_QT_VERSION}" = detect -o "${WANT_QT_VERSION}" = 4; then
fi
if test -n "$DARWIN"; then
FRAMEDIR=`pkg-config --variable=libdir QtCore`
Qt4_CFLAGS="$Qt4_CFLAGS -F${FRAMEDIR} -I${FRAMEDIR}/QtCore.framework/Headers -I${FRAMEDIR}/QtGui.framework/Headers -Xlinker -rpath -Xlinker ${FRAMEDIR}"
Qt4_CFLAGS="$Qt4_CFLAGS -F${FRAMEDIR} -I${FRAMEDIR}/QtCore.framework/Headers -I${FRAMEDIR}/QtGui.framework/Headers -I${FRAMEDIR}/QtSql.framework/Headers -Xlinker -rpath -Xlinker ${FRAMEDIR}"
fi
WANT_QT_VERSION=4
QT_VERSION=4
@ -146,7 +146,7 @@ if test -z "${QT_VERSION}"; then
QT_UIC="${_QT_HOST_BINS}/uic"
FRAMEDIR=${_QTDIR}/lib
QT_LIBS=" -framework QtGui -framework QtCore -framework QtWidgets -Xlinker -rpath -Xlinker ${FRAMEDIR}"
QT_CFLAGS="-std=c++11 -F${FRAMEDIR} -I${FRAMEDIR}/QtCore.framework/Headers -I${FRAMEDIR}/QtGui.framework/Headers -I${FRAMEDIR}/QtCore.framework/Headers -I${FRAMEDIR}/QtWidgets.framework/Headers"
QT_CFLAGS="-std=c++11 -F${FRAMEDIR} -I${FRAMEDIR}/QtCore.framework/Headers -I${FRAMEDIR}/QtGui.framework/Headers -I${FRAMEDIR}/QtCore.framework/Headers -I${FRAMEDIR}/QtWidgets.framework/Headers -I${FRAMEDIR}/QtSql.framework/Headers"
fi
AC_MSG_WARN([Qt pkg-config failed, using fallback defaults (${QT_LIBS})]);
fi

View File

@ -8,7 +8,7 @@ MOCNAMES=db_crl db_key db_temp db_x509 db_x509req db_x509super db_base db_token\
pki_temp pki_x509 pki_crl pki_x509req pki_key pki_x509super pki_pkcs12 \
pki_base pki_multi pki_evp pki_scard pass_info pki_pkcs7 main
NAMES=$(MOCNAMES) asn1int oid x509rev asn1time version \
x509v3ext func load_obj x509name db import \
x509v3ext func load_obj x509name db \
pk11_attribute pkcs11 pkcs11_lib Passwd builtin_curves entropy

View File

@ -51,9 +51,14 @@ int a1time::from_asn1(const ASN1_TIME *a)
setUndefined();
return 0;
}
*this = QDateTime::fromString(t, GEN_FORMAT);
return fromPlain(t);
}
int a1time::fromPlain(QString plain)
{
*this = QDateTime::fromString(plain, GEN_FORMAT);
setTimeSpec(Qt::UTC);
return 0;
return isValid() ? 0 : -1;
}
int a1time::set_asn1(QString str, int type)
@ -101,6 +106,12 @@ a1time::a1time(const ASN1_TIME *a)
from_asn1(a);
}
a1time::a1time(QString plain)
{
atime = NULL;
fromPlain(plain);
}
a1time::~a1time()
{
if (atime)

View File

@ -26,9 +26,11 @@ class a1time : public QDateTime
a1time(const QDateTime &a);
a1time(const ASN1_TIME *a);
a1time(const a1time &a);
a1time(QString plain);
a1time &operator = (const a1time &a);
~a1time();
a1time &set(const ASN1_TIME *a);
int fromPlain(QString plain);
void setUndefined();
bool isUndefined() const;
QString toPretty() const;

View File

@ -16,12 +16,16 @@
#include <QMimeData>
#include "widgets/MainWindow.h"
#include "widgets/ImportMulti.h"
#include "widgets/XcaDialog.h"
db_base::db_base(QString db, MainWindow *mw)
QHash<quint64, pki_base*> db_base::lookup;
db_base::db_base(MainWindow *mw)
:QAbstractItemModel(NULL)
{
dbName = db;
rootItem = newPKI();
rootItem->setIntName(rootItem->getClassName());
mainwin = mw;
colResizing = 0;
currentIdx = QModelIndex();
@ -34,8 +38,9 @@ db_base::~db_base()
delete rootItem;
}
pki_base *db_base::newPKI(db_header_t *)
pki_base *db_base::newPKI(enum pki_type type)
{
(void)type;
return new pki_base("rootItem");
}
@ -64,139 +69,75 @@ void db_base::remFromCont(QModelIndex &idx)
emit columnsContentChanged();
}
int db_base::handleBadEntry(unsigned char *p, db_header_t *head)
QString db_base::sqlItemSelector()
{
QString name = QString::fromUtf8(head->name);
QString txt = tr("Bad database item\nName: %1\nType: %2\nSize: %3\n%4")
.arg(name).arg(class_name)
.arg(head->len - sizeof(db_header_t))
.arg(tr("Do you want to delete the item from the database? The bad item may be extracted into a separate file."));
QStringList sl;
QString selector;
xcaWarning msg(mainwin, txt);
msg.addButton(QMessageBox::Ok)->setText(tr("Delete"));
msg.addButton(QMessageBox::Apply)->setText(tr("Delete and extract"));
msg.addButton(QMessageBox::Cancel)->setText(tr("Continue"));
foreach(enum pki_type pt, pkitype)
sl << QString("type=%1").arg(pt);
switch (msg.exec()) {
case QMessageBox::Ok:
return 1;
case QMessageBox::Cancel:
default:
return 0;
case QMessageBox::Apply:
break;
return sl.join(" OR ");
}
QList<pki_base *> db_base::sqlSELECTpki(QString query, QList<QVariant> values)
{
QList<pki_base *> x;
XSqlQuery q;
int i, num_values = values.size();
SQL_PREPARE(q, query);
for (i=0; i < num_values; i++) {
q.bindValue(i, values[i]);
}
QString s = QFileDialog::getSaveFileName(mainwin, QString(), name,
QString(), NULL, QFileDialog::DontConfirmOverwrite);
size_t l;
db_header_t h;
FILE *fp = fopen_write(s);
if (!fp) {
throw errorEx(tr("Error opening file: '%1': %2").
arg(s).arg(strerror(errno)), class_name);
}
h.magic = xntohl(head->magic);
h.len = xntohl(head->len);
h.headver = xntohs(head->headver);
h.type = xntohs(head->type);
h.version = xntohs(head->version);
h.flags = xntohs(head->flags);
memcpy(h.name, head->name, NAMELEN);
l = fwrite(&h, sizeof h, 1, fp);
l += fwrite(p, head->len - sizeof h, 1, fp);
fclose(fp);
return (l == 2);
q.exec();
mainwin->dbSqlError(q.lastError());
while (q.next())
x << lookupPki(q.value(0).toULongLong());
return x;
}
void db_base::loadContainer()
{
db mydb(dbName);
unsigned char *p = NULL;
db_header_t head;
pki_base *pki;
XSqlQuery q;
QSqlError e;
QString stmt;
for (int i=0; i < pkitype.count(); i++) {
mydb.first();
while (mydb.find(pkitype[i], QString()) == 0) {
QString s;
p = mydb.load(&head);
if (!p) {
qWarning("Load was empty !");
goto next;
}
pki = newPKI(&head);
if (pki->getVersion() < head.version) {
qWarning("Item[%s]: Version %d "
"> known version: %d -> ignored",
head.name, head.version,
pki->getVersion()
);
free(p);
delete pki;
goto next;
}
pki->setIntName(QString::fromUtf8(head.name));
stmt = QString("SELECT id, type FROM items WHERE ") + sqlItemSelector();
q.exec(stmt);
e = q.lastError();
mainwin->dbSqlError(e);
try {
pki->fromData(p, &head);
}
catch (errorEx &err) {
err.appendString(pki->getIntName());
mainwin->Error(err);
delete pki;
pki = NULL;
try {
if (handleBadEntry(p, &head)) {
mydb.erase();
}
} catch (errorEx &err) {
mainwin->Error(err);
}
}
free(p);
if (pki) {
inToCont(pki);
}
next:
if (mydb.next())
break;
while (q.next()) {
enum pki_type t = (enum pki_type)q.value(1).toInt();
pki_base *pki = newPKI(t);
e = pki->restoreSql(q.value(0));
if (!e.isValid()) {
insertChild(rootItem, pki);
lookup[q.value(0).toULongLong()] = pki;
} else {
mainwin->dbSqlError(e);
}
}
mydb.first();
if (!mydb.find(setting, class_name + "_hdView")) {
QByteArray ba;
char *p;
if ((p = (char *)mydb.load(&head))) {
ba = QByteArray(p, head.len - sizeof(db_header_t));
free(p);
}
if (head.version != 5)
return;
try {
allHeaders.fromData(ba);
} catch (errorEx()) {
for (int i=0; i< allHeaders.count(); i++) {
allHeaders[i]->reset();
}
QString view = mainwin->getSetting(class_name + "_hdView");
if (view.isEmpty()) {
for (int i=0; i< allHeaders.count(); i++) {
allHeaders[i]->reset();
}
} else {
allHeaders.fromData(view);
}
emit columnsContentChanged();
return;
}
void db_base::updateHeaders()
{
QByteArray ba = allHeaders.toData();
QString s = allHeaders.toData();
foreach(dbheader *h, allHeaders)
delete h;
allHeaders = getHeaders();
allHeaders.fromData(ba);
allHeaders.fromData(s);
}
dbheaderList db_base::getHeaders()
@ -204,19 +145,20 @@ dbheaderList db_base::getHeaders()
dbheaderList h;
/* "No." handled in XcaProxyModel */
h << new dbheader(HD_internal_name, true, tr("Internal name"))
<< new dbheader(HD_counter, false, tr("No."));
<< new dbheader(HD_counter, false, tr("No."))
<< new dbheader(HD_creation, false, tr("Date"),
tr("Date of creation or insertion"))
<< new dbheader(HD_comment, false, tr("Comment"),
tr("First line of the comment field"));
return h;
}
void db_base::saveHeaderState()
{
if (dbName.isEmpty())
return;
QByteArray ba = allHeaders.toData();
db mydb(dbName);
mydb.set((const unsigned char *)ba.constData(), ba.size(), 5,
setting, class_name + "_hdView");
QSqlDatabase *db = mainwin->getDb();
if (db->isOpen())
mainwin->storeSetting(class_name + "_hdView",
allHeaders.toData());
}
void db_base::setVisualIndex(int i, int visualIndex)
@ -267,19 +209,26 @@ void db_base::sortIndicatorChanged(int logicalIndex, Qt::SortOrder order)
allHeaders[logicalIndex]->sortIndicator = order;
}
QSqlError db_base::insertPKI_noTransaction(pki_base *pki)
{
QSqlError e = pki->insertSql();
lookup[pki->getSqlItemId().toULongLong()] = pki;
inToCont(pki);
mainwin->dbSqlError(e);
emit columnsContentChanged();
return e;
}
void db_base::insertPKI(pki_base *pki)
{
QString name;
db mydb(dbName);
QByteArray ba = pki->toData();
if (ba.count() > 0) {
name = mydb.uniq_name(pki->getIntName(), pkitype);
pki->setIntName(name);
mydb.add((const unsigned char*)ba.constData(), ba.count(),
pki->getVersion(), pki->getType(), name);
QSqlDatabase *db = mainwin->getDb();
if (db->transaction()) {
QSqlError e = insertPKI_noTransaction(pki);
if (e.isValid())
db->rollback();
else
db->commit();
}
inToCont(pki);
emit columnsContentChanged();
}
@ -319,6 +268,7 @@ void db_base::pem2clipboard(QModelIndexList indexes) const
void db_base::deletePKI(QModelIndex idx)
{
pki_base *pki = static_cast<pki_base*>(idx.internalPointer());
QSqlDatabase *db = mainwin->getDb();
try {
try {
pki->deleteFromToken();
@ -326,12 +276,16 @@ void db_base::deletePKI(QModelIndex idx)
MainWindow::Error(err);
}
remFromCont(idx);
db mydb(dbName);
mydb.find(pki->getType(), pki->getIntName());
mydb.erase();
delete pki;
if (db->transaction()) {
QSqlError e = pki->deleteSql();
remFromCont(idx);
mainwin->dbSqlError(e);
if (e.isValid())
db->rollback();
else
db->commit();
mainwin->dbSqlError(e);
}
} catch (errorEx &err) {
MainWindow::Error(err);
}
@ -339,14 +293,9 @@ void db_base::deletePKI(QModelIndex idx)
void db_base::updatePKI(pki_base *pki)
{
db mydb(dbName);
QByteArray ba = pki->toData();
if (ba.count() > 0) {
mydb.set((const unsigned char*)ba.constData(), ba.count(),
pki->getVersion(), pki->getType(), pki->getIntName());
}
(void)pki;
#warning UPDATING updatePKI
fprintf(stderr, "UUUUUUUUUUUUPDATE MIT SQL FEHLER\n");
}
void db_base::showItem(const QModelIndex &index)
@ -356,7 +305,7 @@ void db_base::showItem(const QModelIndex &index)
void db_base::showItem(const QString name)
{
pki_base *pki = getByName(name);
pki_base *pki = lookupPki(name.toULongLong());
if (pki)
showPki(pki);
}
@ -376,6 +325,10 @@ void db_base::insertChild(pki_base *parent, pki_base *child)
endInsertRows();
}
/* Does all the linking from existing keys, crls, certs
* to the new imported or generated item
* called before the new item will be inserted into the database
*/
void db_base::inToCont(pki_base *pki)
{
insertChild(rootItem, pki);
@ -394,7 +347,10 @@ pki_base *db_base::getByReference(pki_base *refpki)
{
if (refpki == NULL)
return NULL;
FOR_ALL_pki(pki, pki_base) {
QList<pki_base*> list = sqlSELECTpki(
QString("SELECT item FROM %1 WHERE hash=?").arg(sqlHashTable),
QList<QVariant>() << QVariant(refpki->hash()));
foreach(pki_base *pki, list) {
if (refpki->compare(pki))
return pki;
}
@ -444,6 +400,8 @@ QModelIndex db_base::index(int row, int column, const QModelIndex &parent)
{
pki_base *parentItem;
if(column <0)
abort();
if (!parent.isValid())
parentItem = rootItem;
else
@ -569,19 +527,52 @@ bool db_base::setData(const QModelIndex &index, const QVariant &value, int role)
on = item->getIntName();
if (nn == on)
return true;
db mydb(dbName);
try {
mydb.rename(item->getType(), on, nn);
item->setIntName(nn);
emit dataChanged(index, index);
return true;
} catch (errorEx &err) {
mainwin->Error(err);
}
updateItem(item, nn, item->getComment());
return true;
}
return false;
}
void db_base::updateItem(pki_base *pki, QString name, QString comment)
{
XSqlQuery q;
QSqlError e;
SQL_PREPARE(q, "UPDATE items SET name=?, comment=? WHERE id=?");
q.bindValue(0, name);
q.bindValue(1, comment);
q.bindValue(2, pki->getSqlItemId());
q.exec();
e = q.lastError();
mainwin->dbSqlError(e);
if (e.isValid())
return;
pki->setIntName(name);
pki->setComment(comment);
QModelIndex i, j;
i = index(pki);
j = index(i.row(), allHeaders.size(), i.parent());
emit dataChanged(i, j);
}
void db_base::editComment(const QModelIndex &index)
{
pki_base *item = static_cast<pki_base*>(index.internalPointer());
if (!index.isValid() || !item)
return;
QTextEdit *t = new QTextEdit(mainwin);
t->setAutoFormatting(QTextEdit::AutoNone);
t->setAcceptRichText(false);
t->setPlainText(item->getComment());
XcaDialog *d = new XcaDialog(mainwin, item->getType(), t,
tr("Edit comment"), item->getIntName());
if (d->exec())
updateItem(item, item->getIntName(), t->toPlainText());
delete d;
}
void db_base::load_default(load_base &load)
{
QString s;

View File

@ -16,6 +16,7 @@
#include <QContextMenuEvent>
#include <QStringList>
#include <QAbstractItemModel>
#include <QHash>
#include "widgets/ExportDialog.h"
#include "pki_base.h"
#include "headerlist.h"
@ -35,7 +36,7 @@ class db_base: public QAbstractItemModel
Q_OBJECT
protected:
QString dbName;
static QHash<quint64, pki_base*> lookup;
QModelIndex currentIdx;
void _writePKI(pki_base *pki, bool overwrite);
void _removePKI(pki_base *pki );
@ -43,10 +44,13 @@ class db_base: public QAbstractItemModel
QList<enum pki_type> pkitype;
MainWindow *mainwin;
QString class_name;
/* Sql table containing the 'hash' of this items */
QString sqlHashTable;
dbheaderList allHeaders;
virtual dbheaderList getHeaders();
int colResizing;
int handleBadEntry(unsigned char *p, db_header_t *head);
QString sqlItemSelector();
void updateItem(pki_base *pki, QString name, QString comment);
virtual exportType::etype clipboardFormat(QModelIndexList) const
{
return exportType::Separator;
@ -54,12 +58,23 @@ class db_base: public QAbstractItemModel
bool isValidCol(int col) const;
public:
static pki_base *lookupPki(quint64 i)
{
return lookup[i];
}
static void flushLookup()
{
lookup.clear();
}
QList<pki_base *> sqlSELECTpki(QString query,
QList<QVariant> values = QList<QVariant>());
virtual pki_base *newPKI(enum pki_type type = none);
pki_base *rootItem;
db_base(QString db, MainWindow *mw);
db_base(MainWindow *mw);
virtual void updateHeaders();
virtual ~db_base();
virtual pki_base *newPKI(db_header_t *head = NULL);
virtual void insertPKI(pki_base *pki);
virtual QSqlError insertPKI_noTransaction(pki_base *pki);
virtual void updatePKI(pki_base *pki);
pki_base *getByName(QString desc);
pki_base *getByReference(pki_base *refpki);
@ -89,7 +104,7 @@ class db_base: public QAbstractItemModel
void createSuccess(pki_base *pki);
bool columnHidden(int col) const;
bool isNumericCol(int col) const;
void saveHeaderState();
virtual void saveHeaderState();
void initHeaderView(QHeaderView *hv);
void setVisualIndex(int i, int visualIndex);
bool fixedHeaderSize(int sect);
@ -111,7 +126,7 @@ class db_base: public QAbstractItemModel
void deletePKI(QModelIndex idx);
QMimeData *mimeData(const QModelIndexList &indexes) const;
void editComment(const QModelIndex &index);
public slots:
virtual void newItem() { }

View File

@ -13,13 +13,15 @@
#include "widgets/NewCrl.h"
#include <QMessageBox>
#include <QContextMenuEvent>
#include <QInputDialog>
#include "widgets/XcaDialog.h"
#include "widgets/ItemCombo.h"
#include "ui_NewCrl.h"
db_crl::db_crl(QString db, MainWindow *mw)
:db_x509name(db,mw)
db_crl::db_crl(MainWindow *mw)
:db_x509name(mw)
{
class_name = "crls";
sqlHashTable = "crls";
pkitype << revocation;
updateHeaders();
loadContainer();
@ -38,8 +40,9 @@ dbheaderList db_crl::getHeaders()
return h;
}
pki_base *db_crl::newPKI(db_header_t *)
pki_base *db_crl::newPKI(enum pki_type type)
{
(void)type;
return new pki_crl();
}
@ -69,40 +72,28 @@ void db_crl::revokeCerts(pki_crl *crl)
void db_crl::removeSigner(pki_base *signer)
{
#warning FIXME ......
FOR_ALL_pki(crl, pki_crl) {
if (crl->getIssuer() == signer)
if (crl->getIssuer() == signer) {
crl->setIssuer(NULL);
}
}
}
void db_crl::inToCont(pki_base *pki)
{
pki_crl *crl = (pki_crl *)pki;
if (crl->getIssuer() == NULL) {
pki_x509 *iss = NULL, *last = NULL, *newest = NULL;
x509name issname = crl->getSubject();
while (1) {
iss = mainwin->certs->getBySubject(issname, last);
if (!iss)
break;
last = iss;
pki_key *key = iss->getPubKey();
if (!key)
continue;
unsigned hash = crl->getSubject().hashNum();
QList<pki_base *> items;
if (!crl->verify(key)) {
delete key;
continue;
}
delete key;
if (!newest) {
newest = iss;
} else {
if (newest->getNotAfter() < iss->getNotAfter())
newest = iss;
}
}
crl->setIssuer(newest);
items = sqlSELECTpki( "SELECT x509super.item FROM x509super "
"JOIN certs ON certs.item = x509super.item "
"WHERE x509super.subj_hash=? AND certs.ca=1",
QList<QVariant>() << QVariant(hash));
foreach(pki_base *b, items) {
fprintf(stderr, "Possible Crl issuer: '%s'\n",
CCHAR(b->getIntName()));
crl->verify(static_cast<pki_x509*>(b));
}
db_base::inToCont(pki);
}
@ -130,13 +121,22 @@ void db_crl::showPki(pki_base *pki)
CrlDetail *dlg;
dlg = new CrlDetail(mainwin);
if (dlg) {
dlg->setCrl(crl);
connect( dlg->issuerIntName, SIGNAL( doubleClicked(QString) ),
mainwin->certs, SLOT( showItem(QString) ));
dlg->exec();
delete dlg;
if (!dlg)
return;
dlg->setCrl(crl);
connect( dlg->issuerIntName, SIGNAL( doubleClicked(QString) ),
mainwin->certs, SLOT( showItem(QString) ));
if (dlg->exec()) {
QString newname = dlg->descr->text();
QString newcomment = dlg->comment->toPlainText();
if (newname != pki->getIntName() ||
newcomment != pki->getComment())
{
updateItem(pki, newname, newcomment);
}
}
delete dlg;
}
void db_crl::store(QModelIndex index)
@ -170,6 +170,7 @@ void db_crl::store(QModelIndex index)
delete dlg;
}
#if 0
void db_crl::updateRevocations(pki_x509 *cert)
{
x509name issname = cert->getSubject();
@ -203,82 +204,116 @@ void db_crl::updateRevocations(pki_x509 *cert)
cert->setCrlNumber(latest->getCrlNumber());
}
}
#endif
void db_crl::newItem()
{
bool ok = false;
QStringList sl = mainwin->certs->getSignerDesc();
QString ca;
QList<pki_base *> cas = mainwin->certs->getAllIssuers();
pki_base *ca = NULL;
switch (sl.size()) {
switch (cas.size()) {
case 0:
XCA_INFO(tr("There are no CA certificates for CRL generation"));
break;
case 1:
ca = sl[0];
ok = true;
break;
default:
ca = QInputDialog::getItem(mainwin, XCA_TITLE,
tr("Select CA certificate"), sl, 0, false, &ok, 0);
}
if (!ok)
return;
pki_x509 *cert = static_cast<pki_x509*>
(mainwin->certs->getByName(ca));
newItem(cert);
case 1:
ca = cas[0];
break;
default: {
itemCombo *c = new itemCombo(NULL);
XcaDialog *d = new XcaDialog(mainwin, revocation, c,
tr("Select CA certificate"), QString());
c->insertPkiItems(cas);
if (!d->exec()) {
delete d;
return;
}
ca = c->currentPkiItem();
delete d;
}
}
newItem(static_cast<pki_x509*>(ca));
}
void db_crl::newItem(pki_x509 *cert)
{
bool transact = false;
if (!cert)
return;
pki_crl *crl = NULL;
NewCrl *dlg = new NewCrl(mainwin, cert);
NewCrl *widget = new NewCrl(NULL, cert);
XcaDialog *dlg = new XcaDialog(mainwin, revocation, widget,
tr("Create CRL"), QString());
if (!dlg->exec()) {
delete dlg;
return;
}
QSqlDatabase *db = mainwin->getDb();
try {
x509v3ext e;
X509V3_CTX ext_ctx;
X509V3_set_ctx(&ext_ctx, cert->getCert(), NULL, NULL, NULL, 0);
X509V3_set_ctx_nodb(&ext_ctx);
XSqlQuery q;
crl = new pki_crl();
crl->createCrl(cert->getIntName(), cert);
bool withReason = dlg->revocationReasons->isChecked();
bool withReason = widget->revocationReasons->isChecked();
foreach(x509rev rev, cert->revList)
crl->addRev(rev, withReason);
if (dlg->authKeyId->isChecked()) {
if (widget->authKeyId->isChecked()) {
crl->addV3ext(e.create(NID_authority_key_identifier,
"keyid,issuer", &ext_ctx));
}
if (dlg->subAltName->isChecked()) {
if (widget->subAltName->isChecked()) {
if (cert->hasExtension(NID_subject_alt_name)) {
crl->addV3ext(e.create(NID_issuer_alt_name,
"issuer:copy", &ext_ctx));
}
}
if (dlg->setCrlNumber->isChecked()) {
QSqlError err;
if (widget->setCrlNumber->isChecked()) {
a1int num;
num.setDec(dlg->crlNumber->text());
num.setDec(widget->crlNumber->text());
crl->setCrlNumber(num);
cert->setCrlNumber(num);
}
crl->setLastUpdate(dlg->lastUpdate->getDate());
crl->setNextUpdate(dlg->nextUpdate->getDate());
crl->sign(cert->getRefKey(), dlg->hashAlgo->currentHash());
cert->setCrlExpiry(dlg->nextUpdate->getDate());
mainwin->certs->updatePKI(cert);
createSuccess(insert(crl));
crl->setIssuer(cert);
crl->setLastUpdate(widget->lastUpdate->getDate());
crl->setNextUpdate(widget->nextUpdate->getDate());
crl->sign(cert->getRefKey(), widget->hashAlgo->currentHash());
if (!db->transaction())
throw errorEx(tr("Failed to initiate DB transaction"));
transact = true;
cert->setCrlExpire(widget->nextUpdate->getDate());
SQL_PREPARE(q, "UPDATE certs set crlNo=?, crlExpire=? WHERE item=?");
q.bindValue(0, (uint)cert->getCrlNumber().getLong());
q.bindValue(1, widget->nextUpdate->getDate().toPlain());
q.bindValue(2, cert->getSqlItemId());
q.exec();
err = q.lastError();
if (err.isValid())
throw errorEx(tr("Database error: ").arg(err.text()));
SQL_PREPARE(q, "UPDATE revocations set crlNo=? "
"WHERE crlNo IS NULL AND caId=?");
q.bindValue(0, (uint)crl->getCrlNumber().getLong());
q.bindValue(1, cert->getSqlItemId());
q.exec();
err = q.lastError();
if (err.isValid())
throw errorEx(tr("Database error: ").arg(err.text()));
insertPKI_noTransaction(crl);
err = db->lastError();
if (err.isValid())
throw errorEx(tr("Database error: ").arg(err.text()));
db->commit();
createSuccess((crl));
}
catch (errorEx &err) {
if (transact)
db->rollback();
MainWindow::Error(err);
if (crl)
delete crl;

View File

@ -22,8 +22,8 @@ class db_crl: public db_x509name
QPixmap *crlicon;
dbheaderList getHeaders();
public:
db_crl(QString db, MainWindow *mw);
pki_base *newPKI(db_header_t *head = NULL);
db_crl(MainWindow *mw);
pki_base *newPKI(enum pki_type type);
void revokeCerts(pki_crl *crl);
void inToCont(pki_base *pki);
pki_base *insert(pki_base *item);
@ -32,7 +32,6 @@ class db_crl: public db_x509name
void load();
void showPki(pki_base *pki);
void updateCertView();
void updateRevocations(pki_x509 *cert);
public slots:
void newItem();

View File

@ -28,11 +28,11 @@
#include "widgets/KeyDetail.h"
#include "widgets/NewKey.h"
db_key::db_key(QString db, MainWindow *mw)
:db_base(db, mw)
db_key::db_key(MainWindow *mw)
:db_base(mw)
{
rootItem->setIntName("[key root]");
class_name = "keys";
sqlHashTable = "public_keys";
pkitype << asym_key << smartCard;
updateHeaders();
loadContainer();
@ -51,45 +51,66 @@ dbheaderList db_key::getHeaders()
return h;
}
pki_base *db_key::newPKI(db_header_t *head)
pki_base *db_key::newPKI(enum pki_type type)
{
if (!head || head->type == asym_key)
if (type == asym_key)
return new pki_evp("");
return new pki_scard("");
}
QStringList db_key::getPrivateDesc()
QList<pki_base *> db_key::getAllKeys()
{
QStringList x;
x.clear();
FOR_ALL_pki(pki, pki_key)
if (pki->isPrivKey())
x.append(pki->getIntName());
return x;
return sqlSELECTpki("SELECT item from public_keys");
}
QStringList db_key::get0KeyDesc(bool all)
QList<pki_base *> db_key::getUnusedKeys()
{
QStringList x;
FOR_ALL_pki(pki, pki_key) {
if ((pki->getUcount() == 0) || all)
x.append(pki->getIntNameWithType());
}
return x;
return sqlSELECTpki("SELECT public_keys.item FROM public_keys "
"LEFT OUTER JOIN x509super ON x509super.key = public_keys.item "
"WHERE x509super.item IS NULL");
}
void db_key::remFromCont(QModelIndex &idx)
{
db_base::remFromCont(idx);
pki_base *pki = static_cast<pki_base*>(idx.internalPointer());
emit delKey((pki_key *)pki);
XSqlQuery q;
pki_key *pki = static_cast<pki_key*>(idx.internalPointer());
QList<pki_base*> items = sqlSELECTpki(
"SELECT item FROM x509super WHERE key=?",
QList<QVariant>() << QVariant(pki->getSqlItemId()));
foreach(pki_base *b, items) {
pki_x509super *x509s = static_cast<pki_x509super*>(b);
x509s->setRefKey(NULL);
}
SQL_PREPARE(q, "UPDATE x509super SET key=NULL WHERE item=?");
q.bindValue(0, pki->getSqlItemId());
q.exec();
mainwin->dbSqlError(q.lastError());
}
void db_key::inToCont(pki_base *pki)
{
db_base::inToCont(pki);
emit newKey((pki_key *)pki);
pki_key *key = static_cast<pki_key*>(pki);
unsigned hash = key->hash();
QList<pki_base*> items = sqlSELECTpki(
"SELECT item FROM x509super WHERE key IS NULL AND key_hash=?",
QList<QVariant>() << QVariant(hash));
XSqlQuery q;
SQL_PREPARE(q, "UPDATE x509super SET key=? WHERE item=?");
q.bindValue(0, key->getSqlItemId());
foreach(pki, items) {
pki_x509super *x509s = static_cast<pki_x509super*>(pki);
if (!x509s->compareRefKey(key))
continue;
/* Found item matching this key */
x509s->setRefKey(key);
q.bindValue(1, x509s->getSqlItemId());
q.exec();
mainwin->dbSqlError(q.lastError());
}
}
pki_base* db_key::insert(pki_base *item)
@ -162,7 +183,7 @@ void db_key::newItem(QString name)
dlg->getKeyCurve_nid());
}
key = (pki_key*)insert(key);
emit keyDone(key->getIntNameWithType());
emit keyDone(key);
createSuccess(key);
} catch (errorEx &err) {
@ -172,7 +193,7 @@ void db_key::newItem(QString name)
if (dlg->rememberDefault->isChecked()) {
QString def = dlg->getAsString();
if (dlg->setDefault(def) == 0)
mainwin->setDefaultKey(def);
mainwin->storeSetting("defaultkey", def);
}
status->removeWidget(bar);
delete bar;
@ -203,7 +224,7 @@ exportType::etype db_key::clipboardFormat(QModelIndexList indexes) const
foreach(QModelIndex idx, indexes) {
pki_key *key = static_cast<pki_key*>
(idx.internalPointer());
(idx.internalPointer());
if (key->isPubKey() || key->isToken())
allPriv = false;
if (key->getKeyType() != EVP_PKEY_RSA &&
@ -334,5 +355,4 @@ void db_key::setOwnPass(QModelIndex idx, enum pki_key::passType x)
throw errorEx(tr("Tried to change password of a token"));
}
targetKey->setOwnPass(x);
updatePKI(targetKey);
}

View File

@ -25,10 +25,10 @@ class db_key: public db_base
virtual dbheaderList getHeaders();
exportType::etype clipboardFormat(QModelIndexList indexes) const;
public:
db_key(QString db, MainWindow *mw);
QStringList getPrivateDesc();
QStringList get0KeyDesc(bool all = false);
pki_base *newPKI(db_header_t *head = NULL);
db_key(MainWindow *mw);
QList<pki_base*> getUnusedKeys();
QList<pki_base*> getAllKeys();
pki_base *newPKI(enum pki_type type = none);
void inToCont(pki_base *pki);
void remFromCont(QModelIndex &idx);
pki_base* insert(pki_base *item);
@ -45,7 +45,7 @@ class db_key: public db_base
signals:
void delKey(pki_key *delkey);
void newKey(pki_key *newkey);
void keyDone(QString name);
void keyDone(pki_key *nkey);
};
#endif

View File

@ -9,6 +9,7 @@
#include "db_temp.h"
#include "func.h"
#include <widgets/NewX509.h>
#include <widgets/XcaDialog.h>
#include <widgets/MainWindow.h>
#include <QFileDialog>
#include <QDir>
@ -17,23 +18,26 @@
#include <QInputDialog>
#include <QMessageBox>
db_temp::db_temp(QString DBfile, MainWindow *mw)
:db_x509name(DBfile, mw)
db_temp::db_temp(MainWindow *mw)
:db_x509name(mw)
{
class_name = "templates";
sqlHashTable = "templates";
pkitype << tmpl;
updateHeaders();
loadContainer();
predefs = newPKI();
QDir dir;
if (!dir.cd(getPrefix()))
return;
dir.setFilter(QDir::Files | QDir::NoSymLinks);
QFileInfoList list = dir.entryInfoList();
load_temp l;
pki_base *tmpl;
pki_temp *tmpl = new pki_temp(tr("Empty template"));
tmpl->setAsPreDefined();
predefs << tmpl;
for (int i = 0; i < list.size(); ++i) {
QFileInfo fileInfo = list.at(i);
QString name = getPrefix() + QDir::separator() +
@ -41,55 +45,33 @@ db_temp::db_temp(QString DBfile, MainWindow *mw)
if (!name.endsWith(".xca", Qt::CaseInsensitive))
continue;
try {
tmpl = l.loadItem(name);
if (tmpl)
predefs->append(tmpl);
tmpl = (pki_temp*)l.loadItem(name);
if (tmpl) {
tmpl->setAsPreDefined();
predefs << tmpl;
}
} catch(errorEx &err) {
XCA_WARN(tr("Bad template: %1").arg(name));
}
}
}
dbheaderList db_temp::getHeaders()
{
dbheaderList h = db_x509name::getHeaders();
h << new dbheader(HD_temp_type, true, tr("Type"));
return h;
}
db_temp::~db_temp()
{
delete predefs;
return;
while (!predefs.isEmpty())
delete predefs.takeFirst();
}
pki_base *db_temp::newPKI(db_header_t *)
pki_base *db_temp::newPKI(enum pki_type type)
{
(void)type;
return new pki_temp("");
}
QStringList db_temp::getDescPredefs()
QList<pki_base *> db_temp::getDescPredefs()
{
QStringList x;
x.clear();
for(pki_temp *pki=(pki_temp*)predefs->iterate(); pki;
pki=(pki_temp*)pki->iterate()) {
x.append(QString("[default] ") + pki->getIntName());
}
x += getDesc();
return x;
}
pki_base *db_temp::getByName(QString desc)
{
if (!desc.startsWith("[default] "))
return db_base::getByName(desc);
desc.remove(0, 10); // "[default] "
for(pki_temp *pki=(pki_temp*)predefs->iterate(); pki;
pki=(pki_temp*)pki->iterate()) {
if (pki->getIntName() == desc)
return pki;
}
return NULL;
return predefs << sqlSELECTpki("SELECT item FROM templates");;
}
bool db_temp::runTempDlg(pki_temp *temp)
@ -98,7 +80,6 @@ bool db_temp::runTempDlg(pki_temp *temp)
emit connNewX509(dlg);
dlg->setTemp(temp);
dlg->fromTemplate(temp);
if (!dlg->exec()) {
delete dlg;
return false;
@ -111,39 +92,24 @@ bool db_temp::runTempDlg(pki_temp *temp)
void db_temp::newItem()
{
pki_temp *temp = NULL;
QStringList sl;
QString type;
bool ok;
int i, len;
len = predefs->childCount();
sl << tr("Nothing");
for (i=0; i<len; i++) {
sl << predefs->child(i)->getIntName();
}
type = QInputDialog::getItem(mainwin, XCA_TITLE,
tr("Preset Template values"), sl, 0, false, &ok, 0);
if (ok) {
if (type == sl[0]) {
temp = new pki_temp("");
} else {
for (i=0; i<len; i++) {
pki_temp *t = (pki_temp *)predefs->child(i);
if (type == t->getIntName()) {
temp = new pki_temp(t);
break;
}
itemCombo *ic = new itemCombo(NULL);
ic->insertPkiItems(predefs);
XcaDialog *dlg = new XcaDialog(mainwin, tmpl, ic,
tr("Preset Template values"), QString());
if (dlg->exec()) {
temp = new pki_temp((pki_temp*)ic->currentPkiItem());
if (temp) {
if (runTempDlg(temp)) {
insertPKI(temp);
createSuccess(temp);
} else {
delete temp;
}
}
if (!temp)
return;
temp->setIntName("--");
if (runTempDlg(temp)) {
insertPKI(temp);
createSuccess(temp);
return;
}
}
delete temp;
delete dlg;
}
void db_temp::showPki(pki_base *pki)
{
@ -182,8 +148,27 @@ void db_temp::store(QModelIndex index)
bool db_temp::alterTemp(pki_temp *temp)
{
XSqlQuery q;
QSqlError e;
QSqlDatabase *db = mainwin->getDb();
if (!runTempDlg(temp))
return false;
updatePKI(temp);
if (!db->transaction())
return false;
SQL_PREPARE(q, "UPDATE templates SET version=?, template=? WHERE item=?");
q.bindValue(0, TMPL_VERSION);
q.bindValue(1, temp->toData().toBase64());
q.bindValue(2, temp->getSqlItemId());
q.exec();
e = q.lastError();
mainwin->dbSqlError(e);
if (e.isValid()) {
db->rollback();
return false;
}
updateItem(temp, temp->getIntName(), temp->getComment());
db->commit();
return true;
}

View File

@ -20,18 +20,16 @@ class db_temp: public db_x509name
Q_OBJECT
protected:
QPixmap *keyicon;
pki_base *predefs;
dbheaderList getHeaders();
QList<pki_base*> predefs;
public:
db_temp(QString DBfile, MainWindow *mw);
db_temp(MainWindow *mw);
~db_temp();
pki_base *newPKI(db_header_t *head = NULL);
pki_base *newPKI(enum pki_type type = none);
bool runTempDlg(pki_temp *temp);
bool alterTemp(pki_temp *temp);
void fillContextMenu(QMenu *menu, const QModelIndex &index);
pki_base *getByName(QString desc);
QStringList getDescPredefs();
QList<pki_base*> getDescPredefs();
void newItem();
void showPki(pki_base *pki);
void load();

View File

@ -3,13 +3,17 @@
#include "exception.h"
#include "widgets/MainWindow.h"
db_token::db_token(QString db, MainWindow *mw)
:db_base(db, mw)
db_token::db_token(MainWindow *mw)
:db_base(mw)
{
class_name = "manageTokens";
updateHeaders();
}
void db_token::saveHeaderState()
{
}
bool db_token::setData(const QModelIndex &index, const QVariant &value, int role)
{
QString on, nn;

View File

@ -21,13 +21,14 @@ class db_token: public db_base
private:
slotid slot;
public:
db_token(QString db, MainWindow *mw);
db_token(MainWindow *mw);
bool setData(const QModelIndex &index,
const QVariant &value, int role);
void setSlot(slotid s)
{
slot = s;
}
void saveHeaderState();
};
#endif

View File

@ -11,29 +11,52 @@
#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)
db_x509::db_x509(MainWindow *mw)
:db_x509super(mw)
{
rootItem->setIntName("[x509 root]");
class_name = "certificates";
sqlHashTable = "certs";
pkitype << x509;
updateHeaders();
loadContainer();
dereferenceIssuer();
}
void db_x509::dereferenceIssuer()
{
XSqlQuery q("SELECT item, issuer FROM certs");
while (q.next()) {
pki_base *root = rootItem;
pki_x509 *cert = static_cast<pki_x509*>(
lookupPki(q.value(0).toULongLong()));
pki_x509 *issuer = static_cast<pki_x509*>(
lookupPki(q.value(1).toULongLong()));
if (cert && issuer) {
cert->setSigner(issuer);
if (cert != issuer)
root = issuer;
}
if (cert->getParent() != root) {
fprintf(stderr, "MOVE '%s' from '%s' to '%s'\n",
CCHAR(cert->getIntName()),
CCHAR(cert->getParent()->getIntName()),
CCHAR(root->getIntName()));
cert->getParent()->takeChild(cert);
insertChild(root, cert);
}
}
}
void db_x509::updateAfterCrlLoad(pki_x509 *pki)
@ -64,85 +87,41 @@ dbheaderList db_x509::getHeaders()
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 *)
pki_base *db_x509::newPKI(enum pki_type type)
{
(void)type;
return new pki_x509();
}
pki_x509 *db_x509::findSigner(pki_x509 *client)
QList<pki_base *> db_x509::getAllIssuers()
{
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;
/* Select X509 CA certificates with available private key */
return sqlSELECTpki("SELECT x509super.item FROM x509super "
"JOIN private_keys ON x509super.key = private_keys.item "
"JOIN certs ON certs.item = x509super.item "
"WHERE certs.ca=1");
}
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;
db_x509super::remFromCont(idx);
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);
new_parent = child->findIssuer();
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()
@ -157,9 +136,9 @@ void db_x509::changeView()
beginRemoveRows(QModelIndex(), 0, rows -1);
pki_base *pki = rootItem;
pki_base *parent;
while(pki->childCount()) {
while (pki->childCount()) {
pki = pki->takeFirst();
while(pki != rootItem && !pki->childCount()) {
while (pki != rootItem && !pki->childCount()) {
parent = pki->getParent();
temproot->append(pki);
pki = parent;
@ -174,18 +153,15 @@ void db_x509::changeView()
mainwin->BNviewState->setText(tr("Tree View"));
while ((temproot->childCount())) {
pki_base *parent = rootItem;
pki = temproot->takeFirst();
inToCont(pki);
if (treeview)
parent = static_cast<pki_x509*>(pki)->getSigner();
insertChild(parent, 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 */
@ -207,8 +183,6 @@ 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;
@ -216,30 +190,45 @@ void db_x509::inToCont(pki_base *pki)
insertChild(root, cert);
QList<pki_x509 *> childs;
QList<pki_base *> items;
unsigned pubhash = cert->pubHash();
unsigned namehash = cert->getSubject().hashNum();
/* Search for another certificate (name and key)
* and use its childs if we are newer */
FOR_ALL_pki(client, pki_x509) {
if (client == cert)
items = sqlSELECTpki(
"SELECT x509super.item FROM x509super "
"JOIN public_keys ON x509super.key = public_keys.item "
"JOIN certs ON certs.item = x509super.item "
"WHERE certs.ca=1 AND x509super.subj_hash=? "
"AND x509super.key_hash=?",
QList<QVariant>() << namehash << pubhash);
foreach(pki_base *b, items) {
pki_x509 *other = static_cast<pki_x509*>(b);
if (other == cert)
continue;
if (!client->compareNameAndKey(cert))
if (!other->compareNameAndKey(cert))
continue;
if (cert->getNotAfter() < client->getNotAfter())
if (cert->getNotAfter() < other->getNotAfter())
continue;
foreach(pki_base *_child, client->childItems) {
pki_x509 *child = static_cast<pki_x509*>(_child);
child->delSigner(client);
foreach(pki_base *b, other->childItems) {
pki_x509 *child = static_cast<pki_x509*>(b);
child->delSigner(other);
childs << child;
}
}
/* Search rootItem childs, whether they are ours */
foreach(pki_base *_child, rootItem->childItems) {
pki_x509 *child = static_cast<pki_x509*>(_child);
foreach(pki_base *b, rootItem->childItems) {
pki_x509 *child = static_cast<pki_x509*>(b);
if (child == cert || child->getSigner() == child)
continue;
if (child->verify_only(cert))
childs << child;
}
/* move collected childs to us */
XSqlQuery q;
SQL_PREPARE(q, "UPDATE certs SET issuer=? WHERE item=?");
q.bindValue(0, cert->getSqlItemId());
foreach(pki_x509 *child, childs) {
int row;
if (recursiveSigning(cert, child))
@ -247,61 +236,51 @@ void db_x509::inToCont(pki_base *pki)
if (!child->verify(cert))
continue;
row = child->row();
beginRemoveRows(index(child), row, row);
child->getParent()->takeChild(child);
endRemoveRows();
if (treeview)
if (treeview) {
beginRemoveRows(index(child->getParent()), row, row);
child->getParent()->takeChild(child);
endRemoveRows();
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();
}
q.bindValue(1, child->getSqlItemId());
q.exec();
mainwin->dbSqlError(q.lastError());
}
/* Update CRLs */
items = sqlSELECTpki( "SELECT item FROM crls WHERE iss_hash=?",
QList<QVariant>() << namehash);
SQL_PREPARE(q, "UPDATE crls SET issuer=? WHERE item=?");
foreach(pki_base *b, items) {
pki_crl *crl = static_cast<pki_crl*>(b);
crl->verify(cert);
cert = crl->getIssuer();
if (!cert)
continue;
q.bindValue(0, cert->getSqlItemId());
q.bindValue(1, crl->getSqlItemId());
q.exec();
mainwin->dbSqlError(q.lastError());
}
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)
void db_x509::writeAllCerts(const QString fname, bool unrevoked)
{
bool append = false;
FOR_ALL_pki(pki, pki_x509) {
if (onlyTrusted && pki->getTrust() != 2) continue;
if (unrevoked && pki->isRevoked())
continue;
pki->writeCert(fname.toLatin1(), true, append);
append = true;
}
}
QList<pki_x509*> db_x509::getCerts(bool onlyTrusted)
QList<pki_x509*> db_x509::getCerts(bool unrevoked)
{
QList<pki_x509*> c;
c.clear();
FOR_ALL_pki(pki, pki_x509) {
if (onlyTrusted && pki->getTrust() != 2) continue;
if (unrevoked && pki->isRevoked())
continue;
c.append(pki);
}
return c;
@ -396,9 +375,6 @@ pki_base *db_x509::insert(pki_base *item)
if ( ++serial > cert->getCaSerial()) {
cert->setCaSerial(serial);
}
if (mainwin->crls) {
mainwin->crls->updateRevocations(cert);
}
updatePKI(cert);
return cert;
}
@ -521,7 +497,6 @@ void db_x509::newCert(NewX509 *dlg)
return;
serial = getUniqueSerial(signcert);
signkey = signcert->getRefKey();
cert->setTrust(1);
#ifdef WG_QA_SERIAL
} else if (dlg->selfQASignRB->isChecked()){
Passwd pass;
@ -531,13 +506,11 @@ void db_x509::newCert(NewX509 *dlg)
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);
@ -588,6 +561,9 @@ void db_x509::newCert(NewX509 *dlg)
// and finally sign the request
cert->sign(signkey, hashAlgo);
// set the comment field
cert->setComment(dlg->comment->toPlainText());
cert = (pki_x509*)insert(cert);
createSuccess(cert);
updatePKI(signcert);
@ -615,22 +591,6 @@ void db_x509::newCert(NewX509 *dlg)
}
}
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;
@ -694,12 +654,12 @@ void db_x509::store(QModelIndexList list)
"PEM + PKCS#8");
}
types << exportType() <<
exportType(exportType::PKCS7_trusted, "p7b",
tr("PKCS#7 trusted")) <<
exportType(exportType::PKCS7_unrevoked, "p7b",
tr("PKCS#7 unrevoked")) <<
exportType(exportType::PKCS7_all, "p7b",
tr("PKCS#7 all")) <<
exportType(exportType::PEM_trusted, "pem",
tr("PEM trusted")) <<
exportType(exportType::PEM_unrevoked, "pem",
tr("PEM unrevoked")) <<
exportType(exportType::PEM_all, "pem",
tr("PEM all")) <<
exportType(exportType::Index, "txt",
@ -738,7 +698,7 @@ void db_x509::store(QModelIndexList list)
append = true;
}
break;
case exportType::PEM_trusted:
case exportType::PEM_unrevoked:
writeAllCerts(fname,true);
break;
case exportType::PEM_all:
@ -749,7 +709,7 @@ void db_x509::store(QModelIndexList list)
break;
case exportType::PKCS7:
case exportType::PKCS7_chain:
case exportType::PKCS7_trusted:
case exportType::PKCS7_unrevoked:
case exportType::PKCS7_selected:
case exportType::PKCS7_all:
writePKCS7(crt, fname, type, list);
@ -858,11 +818,11 @@ void db_x509::writePKCS7(pki_x509 *cert, QString s, exportType::etype type,
p7->addCert(cert);
}
break;
case exportType::PKCS7_trusted:
case exportType::PKCS7_unrevoked:
case exportType::PKCS7_all:
FOR_ALL_pki(cer, pki_x509) {
if ((type == exportType::PKCS7_all) ||
(cer->getTrust() == 2))
(!cer->isRevoked()))
p7->addCert(cer);
}
break;
@ -879,6 +839,19 @@ void db_x509::writePKCS7(pki_x509 *cert, QString s, exportType::etype type,
}
void db_x509::storeRevocations(pki_x509 *cert)
{
QSqlDatabase *db = mainwin->getDb();
if (db->transaction()) {
QSqlError e;
e = cert->revList.sqlUpdate(cert->getSqlItemId());
if (e.isValid())
db->rollback();
else
db->commit();
}
}
void db_x509::manageRevocations(QModelIndex idx)
{
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
@ -890,56 +863,11 @@ void db_x509::manageRevocations(QModelIndex idx)
mainwin->crls, SLOT(newItem(pki_x509*)));
if (dlg->exec()) {
cert->setRevocations(dlg->getRevList());
updatePKI(cert);
storeRevocations(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;
@ -1048,7 +976,7 @@ void db_x509::do_revoke(QModelIndexList indexes, const x509rev &r)
revlist << rev;
}
parent->mergeRevList(revlist);
updatePKI(parent);
storeRevocations(parent);
}
void db_x509::unRevoke(QModelIndexList indexes)
@ -1081,7 +1009,7 @@ void db_x509::unRevoke(QModelIndexList indexes)
if (i != -1)
parent->revList.takeAt(i);
}
updatePKI(parent);
storeRevocations(parent);
emit columnsContentChanged();
}
@ -1130,6 +1058,7 @@ void db_x509::caProperties(QModelIndex idx)
{
Ui::CaProperties ui;
int i;
#warning FIXME for Policies
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
if (!cert)
@ -1144,7 +1073,7 @@ void db_x509::caProperties(QModelIndex idx)
ui.days->setMaximum(1000000);
ui.days->setValue(cert->getCrlDays());
ui.image->setPixmap(*MainWindow::certImg);
QString templ = cert->getTemplate();
QString templ; //cert->getTemplate()->getIntName();
QStringList tempList = mainwin->temps->getDesc();
for (i=0; i<tempList.count(); i++) {
if (tempList[i] == templ)
@ -1153,12 +1082,28 @@ void db_x509::caProperties(QModelIndex idx)
ui.temp->addItems(tempList);
ui.temp->setCurrentIndex(i);
ui.certName->setTitle(cert->getIntName());
QStringList sl;
sl << tr("Type") << tr("Action");
ui.subjectManager->initCols(sl);
sl.clear();
foreach(int nid, *MainWindow::dn_nid)
sl << QString(OBJ_nid2ln(nid));
ui.subjectManager->setKeys(sl, 0);
sl.clear();
sl << "From request" << "From template" << "Erase" << "Match"
<< "Template as regex";
ui.subjectManager->setKeys(sl, 1);
if (dlg->exec()) {
a1int nserial;
cert->setCrlDays(ui.days->value());
nserial.setHex(ui.serial->text());
cert->setCaSerial(nserial);
cert->setTemplate(ui.temp->currentText());
#warning Fixme, too
// cert->setTemplate(ui.temp->currentText());
cert->setUseRandomSerial(ui.randomSerial->isChecked());
updatePKI(cert);
}

View File

@ -27,12 +27,13 @@ class db_x509: public db_x509super
QPixmap *certicon[4];
pki_x509 *get1SelectedCert();
dbheaderList getHeaders();
void dereferenceIssuer();
public:
static bool treeview;
db_x509(QString DBfile, MainWindow *mw);
pki_base *newPKI(db_header_t *head = NULL);
pki_x509 *findSigner(pki_x509 *client);
db_x509(MainWindow *mw);
pki_base *newPKI(enum pki_type type = none);
pki_x509 *findIssuer(pki_x509 *client);
void updateAfterDbLoad();
void updateAfterCrlLoad(pki_x509 *pki);
@ -40,15 +41,11 @@ class db_x509: public db_x509super
void updateViewAll();
void updateViewPKI(pki_base *pki);
void remFromCont(QModelIndex &idx);
QStringList getPrivateDesc();
QStringList getSignerDesc();
void calcEffTrust();
QList<pki_x509*> getCerts(bool onlyTrusted);
QList<pki_base*> getAllIssuers();
QList<pki_x509*> getCerts(bool unrevoked);
a1int searchSerial(pki_x509 *signer);
void writeAllCerts(const QString fname, bool onlyTrusted);
void writeIndex(const QString fname, bool hierarchy);
pki_x509 *getByIssSerial(const pki_x509 *issuer, const a1int &a);
pki_x509 *getBySubject(const x509name &xname, pki_x509 *last = NULL);
void writeAllCerts(const QString fname, bool unrevoked);
pki_base *insert(pki_base *item);
void newCert(NewX509 *dlg);
void newCert(pki_x509 *cert);
@ -63,7 +60,6 @@ class db_x509: public db_x509super
void toRequest(QModelIndex idx);
void store(QModelIndex idx);
void store(QModelIndexList list);
void showPki(pki_base *pki);
void load();
void caProperties(QModelIndex idx);
void toCertificate(QModelIndex index);
@ -72,7 +68,7 @@ class db_x509: public db_x509super
void revoke(QModelIndexList indexes);
void do_revoke(QModelIndexList indexes, const x509rev &r);
void unRevoke(QModelIndexList indexes);
void setTrust(QModelIndexList indexes);
void storeRevocations(pki_x509 *cert);
public slots:
void newItem();

View File

@ -8,17 +8,17 @@
#include "db_x509req.h"
#include "pki_x509req.h"
#include "widgets/CertDetail.h"
#include "widgets/MainWindow.h"
#include <QMessageBox>
#include <QContextMenuEvent>
#include <QAction>
db_x509req::db_x509req(QString DBfile, MainWindow *mw)
:db_x509super(DBfile, mw)
db_x509req::db_x509req(MainWindow *mw)
:db_x509super(mw)
{
class_name = "requests";
sqlHashTable = "requests";
pkitype << x509_req;
updateHeaders();
loadContainer();
@ -36,8 +36,9 @@ dbheaderList db_x509req::getHeaders()
return h;
}
pki_base *db_x509req::newPKI(db_header_t *)
pki_base *db_x509req::newPKI(enum pki_type type)
{
(void)type;
return new pki_x509req();
}
@ -86,6 +87,9 @@ void db_x509req::newItem(pki_temp *temp, pki_x509req *orig)
dlg->initCtx(NULL, NULL, req);
dlg->getReqAttributes(req);
req->createReq(key, xn, dlg->hashAlgo->currentHash(), dlg->getAllExt());
// set the comment field
req->setComment(dlg->comment->toPlainText());
createSuccess(insert(req));
}
catch (errorEx &err) {
@ -103,43 +107,12 @@ void db_x509req::toRequest(QModelIndex index)
newItem(NULL, req);
}
void db_x509req::inToCont(pki_base *pki)
{
pki_x509req *req = (pki_x509req *)pki;
db_base::inToCont(pki);
findKey(req);
if (!mainwin->certs)
return;
pki_key *pub = req->getPubKey();
if (pub) {
int certs = mainwin->certs->findByPubKey(pub).count();
delete pub;
if (certs > 0) {
req->setDone();
}
}
}
void db_x509req::load(void)
{
load_req l;
load_default(l);
}
void db_x509req::showPki(pki_base *pki)
{
pki_x509req *req = (pki_x509req *)pki;
CertDetail *dlg;
dlg = new CertDetail(mainwin);
if (dlg) {
dlg->setReq(req);
connect(dlg->privKey, SIGNAL( doubleClicked(QString) ),
mainwin->keys, SLOT( showItem(QString) ));
dlg->exec();
delete dlg;
}
}
void db_x509req::store(QModelIndex index)
{
QList<exportType> types;
@ -174,3 +147,8 @@ void db_x509req::signReq(QModelIndex index)
pki_x509req *req = static_cast<pki_x509req*>(index.internalPointer());
emit newCert(req);
}
QList<pki_base *> db_x509req::getAllRequests()
{
return sqlSELECTpki("SELECT item FROM requests");
}

View File

@ -21,16 +21,16 @@ class db_x509req: public db_x509super
protected:
dbheaderList getHeaders();
public:
db_x509req(QString DBfile, MainWindow *mw);
db_x509req(MainWindow *mw);
pki_base* insert(pki_base *item);
pki_base *newPKI(db_header_t *head = NULL);
pki_base *newPKI(enum pki_type type = none);
void fillContextMenu(QMenu *menu, const QModelIndex &index);
void inToCont(pki_base *pki);
// void inToCont(pki_base *pki);
void store(QModelIndex index);
void signReq(QModelIndex index);
void toRequest(QModelIndex index);
void load();
void showPki(pki_base *pki);
QList<pki_base*> getAllRequests();
public slots:
void newItem(pki_temp *temp, pki_x509req *orig = NULL);

View File

@ -8,12 +8,13 @@
#include "pki_base.h"
#include "db_x509super.h"
#include "widgets/MainWindow.h"
#include "ui_About.h"
#include "widgets/CertDetail.h"
#include "widgets/XcaDialog.h"
#include "oid.h"
#include <QMessageBox>
db_x509name::db_x509name(QString db, MainWindow *mw)
:db_base(db, mw)
db_x509name::db_x509name(MainWindow *mw)
:db_base(mw)
{
}
@ -30,11 +31,26 @@ dbheaderList db_x509name::getHeaders()
return h;
}
db_x509super::db_x509super(QString db, MainWindow *mw)
:db_x509name(db, mw)
db_x509super::db_x509super(MainWindow *mw)
:db_x509name(mw)
{
}
void db_x509super::loadContainer()
{
db_x509name::loadContainer();
/* Resolve Key references */
FOR_ALL_pki(pki, pki_x509super) {
QVariant keySqlId = pki->getKeySqlId();
if (!keySqlId.isValid())
continue;
quint64 id = keySqlId.toULongLong();
if (!lookup.contains(id))
continue;
pki->setRefKey(static_cast<pki_key*>(lookup[id]));
}
}
dbheaderList db_x509super::getHeaders()
{
dbheaderList h = db_x509name::getHeaders();
@ -71,16 +87,6 @@ dbheaderList db_x509super::getHeaders()
return h;
}
void db_x509super::delKey(pki_key *delkey)
{
FOR_ALL_pki(pki, pki_x509super) { pki->delRefKey(delkey); }
}
void db_x509super::newKey(pki_key *newkey)
{
FOR_ALL_pki(pki,pki_x509super) { pki->setRefKey(newkey); }
}
pki_key *db_x509super::findKey(pki_x509super *ref)
{
pki_key *key, *refkey;
@ -158,18 +164,15 @@ void db_x509super::toTemplate(QModelIndex index)
temp->setIntName(pki->getIntName());
extList el = temp->fromCert(pki);
if (el.size()) {
Ui::About ui;
QString etext;
QDialog *d = new QDialog(mainwin, 0);
ui.setupUi(d);
etext = QString("<h3>") +
tr("The following extensions were not ported into the template") +
QString("</h3><hr>") +
el.getHtml("<br>");
ui.textbox->setHtml(etext);
d->setWindowTitle(XCA_TITLE);
ui.image->setPixmap(*MainWindow::tempImg);
ui.image1->setPixmap(*MainWindow::certImg);
QTextEdit *textbox = new QTextEdit(etext);
XcaDialog *d = new XcaDialog(mainwin, x509, textbox,
QString(), QString());
d->aboutDialog(MainWindow::tempImg);
d->exec();
delete d;
}
@ -180,3 +183,33 @@ void db_x509super::toTemplate(QModelIndex index)
}
}
void db_x509super::showPki(pki_base *pki)
{
pki_x509super *x = (pki_x509req *)pki;
CertDetail *dlg;
dlg = new CertDetail(mainwin);
if (!dlg)
return;
switch (x->getType()) {
case x509_req: dlg->setReq((pki_x509req*)x); break;
case x509: dlg->setCert((pki_x509*)x); break;
default:
delete dlg;
return;
}
connect(dlg->privKey, SIGNAL(doubleClicked(QString)),
mainwin->keys, SLOT(showItem(QString)));
connect(dlg->signature, SIGNAL(doubleClicked(QString)),
this, SLOT(showItem(QString)));
if (dlg->exec()) {
QString newname = dlg->descr->text();
QString newcomment = dlg->comment->toPlainText();
if (newname != pki->getIntName() ||
newcomment != pki->getComment())
{
updateItem(pki, newname, newcomment);
}
}
delete dlg;
}

View File

@ -21,7 +21,7 @@ class db_x509name: public db_base
protected:
dbheaderList getHeaders();
public:
db_x509name(QString db, MainWindow *mw);
db_x509name(MainWindow *mw);
};
class db_x509super: public db_x509name
@ -30,17 +30,15 @@ class db_x509super: public db_x509name
protected:
dbheaderList getHeaders();
void loadContainer();
public:
db_x509super(QString db, MainWindow *mw);
db_x509super(MainWindow *mw);
pki_key *findKey(pki_x509super *ref);
QList<pki_x509super *> findByPubKey(pki_key *refkey);
void extractPubkey(QModelIndex index);
void toTemplate(QModelIndex index);
void toOpenssl(QModelIndex index) const;
public slots:
void delKey(pki_key *delkey);
void newKey(pki_key *newKey);
void showPki(pki_base *pki);
};
#endif

View File

@ -23,11 +23,13 @@
#define HD_x509key_name -5
#define HD_counter -6
#define HD_x509_sigalg -7
#define HD_creation -8
#define HD_comment -9
#define HD_cert_serial -10
#define HD_cert_notBefore -11
#define HD_cert_notAfter -12
#define HD_cert_trust -13
//#define HD_cert_trust -13
#define HD_cert_revocation -14
#define HD_cert_ca -15
#define HD_cert_md5fp -16
@ -38,7 +40,7 @@
#define HD_req_signed -20
#define HD_req_unstr_name -21
#define HD_req_chall_pass -22
#define HD_temp_type -30
//#define HD_temp_type -30
#define HD_crl_signer -40
#define HD_crl_revoked -42
@ -92,7 +94,7 @@ class dbheader
name = aname;
}
#endif
dbheader(int aid, bool ashow,
dbheader(int aid, bool ashow = false,
QString aname = QString(), QString atip = QString())
{
init();
@ -135,21 +137,22 @@ class dbheader
}
return false;
}
QByteArray toData()
QString toData()
{
QByteArray ba;
ba += db::intToData(visualIndex);
ba += db::intToData(sortIndicator);
ba += db::intToData(size);
ba += db::boolToData(show);
return ba;
QStringList sl; sl
<< QString::number(visualIndex)
<< QString::number(sortIndicator)
<< QString::number(size)
<< QString::number(show);
return sl.join(" ");
}
void fromData(QByteArray &ba)
void fromData(QString s)
{
visualIndex = db::intFromData(ba);
sortIndicator = db::intFromData(ba);
size = db::intFromData(ba);
show = db::boolFromData(ba);
QStringList sl = s.split(" ");
visualIndex = sl[0].toInt();
sortIndicator = sl[1].toInt();
size = sl[2].toInt();
show = sl[3].toInt();
}
void setupHeaderView(int sect, QHeaderView *hv)
{
@ -207,43 +210,40 @@ class dbheaderList: public QList<dbheader*>
}
dbheaderList() :QList<dbheader*>() {
}
QByteArray toData()
QString toData()
{
QByteArray ba;
QStringList sl;
for (int i=0; i<count(); i++) {
QStringList seq;
dbheader *h = at(i);
if (!h->mustSave())
continue;
ba += db::intToData(h->id);
seq << QString("%1").arg(h->id);
if (h->id > 0) {
ASN1_OBJECT *o = OBJ_nid2obj(h->id);
ba += i2d_bytearray(I2D_VOID(i2d_ASN1_OBJECT), o);
seq << OBJ_obj2QString(
OBJ_nid2obj(h->id), 1);
}
ba += h->toData();
seq << h->toData();
sl << seq.join(":");
}
return ba;
return sl.join(",");
}
void fromData(QByteArray &ba)
void fromData(QString s)
{
while (ba.size()) {
int id = db::intFromData(ba);
QStringList sl = s.split(",");
foreach(QString hd, sl) {
QStringList sl1 = hd.split(":");
int id = sl1.takeFirst().toInt();
if (id > 0) {
ASN1_OBJECT *o = (ASN1_OBJECT*)d2i_bytearray(D2I_VOID(d2i_ASN1_OBJECT), ba);
id = OBJ_obj2nid(o);
ASN1_OBJECT_free(o);
id = OBJ_txt2nid(CCHAR(sl1.takeFirst()));
}
for (int i=0; i<count(); i++) {
dbheader *h = at(i);
if (h->id == id) {
h->fromData(ba);
id = 0;
h->fromData(sl1.takeFirst());
break;
}
}
if (id != 0) {
dbheader h("dummy");
h.fromData(ba);
}
}
}
};

View File

@ -1,181 +0,0 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2001 - 2007 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include "exception.h"
#include "db_base.h"
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <QFile>
#define RESIZE 1024
#define RDBUF 256
static int database = -1;
static int h2n(const char c)
{
if (c>='0' && c<='9')
return c-'0';
if (c>='a' && c<='f')
return c-'a'+10;
if (c>='A' && c<='F')
return c-'A'+10;
return 0;
}
static char *read_data(const char *asc, int *retlen)
{
char *p;
int len=0, binlen=0, alloclen=RESIZE;
p = (char*)malloc(alloclen);
if (!p)
return NULL;
*retlen = 0;
while(asc[len] != '\0') {
p[binlen] = (h2n(asc[len])<<4) + h2n(asc[len+1]);
len +=2;
binlen++;
if (binlen == alloclen) {
alloclen +=RESIZE;
p = (char *)realloc(p, alloclen);
}
}
*retlen = binlen;
return p;
}
QString readLine(QFile *file)
{
QString data;
qint64 begin;
char buffer[RDBUF], *p;
int ret, len;
while ((ret = file->read(buffer, RDBUF-1)) >0) {
p = strchr(buffer, '\n');
if (p) {
begin = file->pos() - ret;
len = p - buffer;
file->seek(begin + len + 1);
//printf("Begin: %ld len=%d\n", begin,len);
if (p > buffer && p[-1] == '\r')
p--;
*p = '\0';
data += buffer;
return data;
}
buffer[ret] = '\0';
data += buffer;
continue;
}
return data;
}
static int set_db(const char *name)
{
QStringList sl;
sl << "keydb" << "reqdb" << "certdb" << "tempdb" << "crldb" << "settings";
for (int i=0; i<sl.count(); i++) {
if (sl[i] == name)
return i;
}
return -1;
}
static void handle_option(QString opt)
{
QStringList sl = opt.split('=');
if (sl.count() != 2) {
printf("No '=' found in: '%s'\n", CCHAR(opt));
return;
}
if (!sl[0].compare("database")) {
database = set_db(CCHAR(sl[1]));
}
}
int read_dump(const char *filename, db_base **dbs, char *md5, int md5_len)
{
char *p;
int ret = -1, retlen = 0;
int kv=0;
bool md5sum = false;
pki_base *pki = NULL;
db_base *db;
QFile file;
QString line;
file.setFileName(filename);
if (! file.open(QIODevice::ReadOnly)) {
throw errorEx(filename, strerror(errno));
return -1;
}
for (;;) {
line = readLine(&file);
//printf("Line: '%s'\n", CCHAR(line));
if (line.isNull()) {
ret = 0;
break;
}
//printf("FIRST char = '%c'\n", CCHAR(line)[0]);
if (line[0] == ' ') {
if (database >= 0 && database < 5)
db = dbs[database];
else
db = NULL;
kv ^= 1;
p = read_data(CCHAR(line.trimmed()), &retlen);
if (db && !md5) {
if (kv) {
pki = db->newPKI();
if (!pki) {
break;
}
pki->setIntName(p);
} else {
try {
pki->oldFromData((unsigned char*)p, retlen);
db->insert(pki);
} catch (errorEx &err) {
printf("Error caught for '%s'\n", CCHAR(pki->getIntName()));
}
}
} else if (md5) {
if (database == 5) {
p = read_data(CCHAR(line.trimmed()), &retlen);
if (kv)
md5sum = (!strcmp(p, "pwhash")) ? true : false;
if (!kv && md5sum) {
strncpy(md5, p, md5_len);
ret = 0;
break;
}
}
}
free(p);
} else {
if (kv) {
printf("Binary value expected\n");
break;
}
handle_option(line);
}
}
file.close();
if (ret <0) {
throw errorEx(filename, strerror(errno));
return -1;
}
return 0;
}

View File

@ -256,13 +256,6 @@ int main_extract(int argc, char *argv[])
case revocation: pki = new pki_crl(name); break;
default: return usage_extract(argv);
}
if (pki->getVersion() < head.version) {
fprintf(stderr, "Item[%s]: Version %d > known version: %d",
head.name, head.version, pki->getVersion());
free(p);
delete pki;
return usage_extract(argv);
}
pki->setIntName(QString::fromUtf8(head.name));
try {
pki->fromData(p, &head);
@ -301,7 +294,7 @@ static void segv_handler_gui(int)
int main( int argc, char *argv[] )
{
int ret = 0, pkictr;
int ret = 0;
MainWindow *mw;
QDir d;
@ -332,9 +325,5 @@ int main( int argc, char *argv[] )
}
delete mw;
pkictr = pki_base::get_pki_counter();
if (pkictr)
fprintf(stderr, "PKI Counter (%d)\n", pkictr);
return ret;
}

View File

@ -10,50 +10,41 @@
#include "pki_base.h"
#include "exception.h"
#include <QString>
#include <openssl/evp.h>
#include <openssl/sha.h>
int pki_base::pki_counter = 0;
int pki_base::suppress_messages = 0;
QRegExp pki_base::limitPattern;
pki_base::pki_base(const QString name, pki_base *p)
{
desc = name;
class_name = "pki_base";
parent = p;
pki_counter++;
childItems.clear();
dataVersion=0;
pkiType=none;
}
int pki_base::getVersion()
{
return dataVersion;
}
enum pki_type pki_base::getType()
{
return pkiType;
}
pki_base::~pki_base(void)
{
while (childItems.size() > 0)
delete takeFirst();
pki_counter--;
}
QString pki_base::getIntName() const
QString pki_base::comboText() const
{
return desc;
}
QString pki_base::getUnderlinedName() const
void pki_base::deleteFromToken() { };
void pki_base::deleteFromToken(slotid) { };
void pki_base::writeDefault(const QString) { }
void pki_base::fromPEM_BIO(BIO *, QString) { }
void pki_base::fload(const QString) { }
int pki_base::renameOnToken(slotid, QString)
{
return getIntName().replace(QRegExp("[ &;`/\\\\]+"), "_");
return 0;
}
bool pki_base::visible()
{
if (limitPattern.isEmpty())
@ -61,20 +52,26 @@ bool pki_base::visible()
return getIntName().contains(limitPattern);
}
int pki_base::get_pki_counter()
QString pki_base::getMsg(msg_type msg)
{
return pki_counter;
return tr("Internal error: Unexpected message: %1 %2")
.arg(getClassName()).arg(msg);
}
QString pki_base::getClassName()
QByteArray pki_base::i2d()
{
QString x = class_name;
return x;
return QByteArray();
}
void pki_base::setIntName(const QString &d)
BIO *pki_base::pem(BIO *, int format)
{
desc = d;
(void)format;
return NULL;
}
const char *pki_base::getClassName() const
{
return "pki_base";
}
void pki_base::fopen_error(const QString fname)
@ -97,7 +94,7 @@ void pki_base::my_error(const QString error) const
{
if (!error.isEmpty()) {
fprintf(stderr, "%s\n", CCHAR(tr("Error: ") + error));
throw errorEx(error, class_name);
throw errorEx(error, getClassName());
}
}
@ -117,6 +114,78 @@ QString pki_base::rmslashdot(const QString &s)
return s.mid(l+1,r-l-1);
}
QSqlError pki_base::insertSql()
{
XSqlQuery q;
QString insert;
QSqlError e;
insertion_date.now();
SQL_PREPARE(q, "INSERT INTO items "
"(name, type, date, comment) "
"VALUES (?, ?, ?, ?)");
q.bindValue(0, getIntName());
q.bindValue(1, getType());
q.bindValue(2, insertion_date.toPlain());
q.bindValue(3, getComment());
q.exec();
e = q.lastError();
if (!e.isValid()) {
sqlItemId = q.lastInsertId();
e = insertSqlData();
}
return e;
}
QSqlError pki_base::restoreSql(QVariant sqlId)
{
XSqlQuery q;
QSqlError e;
SQL_PREPARE(q, "SELECT name, date, comment FROM items WHERE id=?");
q.bindValue(0, sqlId);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
if (!q.first())
return sqlItemNotFound(sqlId);
desc = q.value(0).toString();
insertion_date.fromPlain(q.value(1).toString());
comment = q.value(2).toString();
sqlItemId = sqlId;
return e;
}
QSqlError pki_base::deleteSql()
{
XSqlQuery q;
QString insert;
QSqlError e;
if (!sqlItemId.isValid()) {
qDebug("INVALID sqlItemId (DELETE %s)", CCHAR(getIntName()));
return sqlItemNotFound(QVariant());
}
SQL_PREPARE(q, "DELETE FROM items WHERE id=?");
q.bindValue(0, sqlItemId);
q.exec();
e = q.lastError();
if (!e.isValid())
e = deleteSqlData();
return e;
}
QSqlError pki_base::sqlItemNotFound(QVariant sqlId) const
{
return QSqlError(QString("XCA SQL database inconsistent"),
QString("Item %2 not found %1")
.arg(getClassName())
.arg(sqlId.toString()),
QSqlError::UnknownError);
}
pki_base *pki_base::getParent()
{
return parent;
@ -187,6 +256,10 @@ QVariant pki_base::column_data(dbheader *hd)
switch (hd->id) {
case HD_internal_name:
return QVariant(getIntName());
case HD_creation:
return QVariant(insertion_date.toSortable());
case HD_comment:
return QVariant(comment.section('\n', 0, 0));
}
return QVariant();
}
@ -197,23 +270,26 @@ QVariant pki_base::getIcon(dbheader *hd)
return QVariant();
}
uint32_t pki_base::intFromData(QByteArray &ba)
{
/* For import "oldFromData" use the endian dependent version */
uint32_t ret;
if ((unsigned)(ba.count()) < sizeof(uint32_t)) {
ba.clear();
return 0;
}
memcpy(&ret, ba.constData(), sizeof(uint32_t));
ba = ba.mid(sizeof(uint32_t));
return ret;
}
bool pki_base::compare(pki_base *refcrl)
bool pki_base::compare(pki_base *ref)
{
bool ret;
ret = (i2d() == refcrl->i2d());
ret = (i2d() == ref->i2d());
pki_openssl_error();
return ret;
}
/* Signed 32 bit interger */
unsigned pki_base::hash(QByteArray ba)
{
unsigned char md[EVP_MAX_MD_SIZE];
SHA1((const unsigned char *)ba.constData(), ba.length(), md);
return (((unsigned)md[0] ) | ((unsigned)md[1]<<8L) |
((unsigned)md[2]<<16L) | ((unsigned)md[3]<<24L)
) & 0x7fffffffL;
}
unsigned pki_base::hash()
{
return hash(i2d());
}

View File

@ -11,24 +11,92 @@
#include <openssl/err.h>
#include <QString>
#include <QListView>
#include <QtSql>
#include "asn1time.h"
#include "pkcs11_lib.h"
#include "db.h"
#include "base.h"
#include "headerlist.h"
#define __ME QString("(%1:%2)").arg(class_name).arg(getIntName())
#define __ME QString("(%1:%2)").arg(getClassName()).arg(getIntName())
#define pki_openssl_error() _openssl_error(__ME, C_FILE, __LINE__)
#define pki_ign_openssl_error() _ign_openssl_error(__ME, C_FILE, __LINE__)
#define SQL_PREPARE(q,cmd) do { \
(q).prepare(cmd); \
(q).location(__FILE__,__LINE__); \
} while (0);
class XSqlQuery: public QSqlQuery
{
QString lastq;
const char *file;
int line;
public:
QString query_details()
{
QString lq = lastq;
QList<QVariant> list = boundValues().values();
QStringList sl;
for (int i = 0; i < list.size(); ++i)
sl << list.at(i).toString();
if (sl.size())
lq += QString("[%1]").arg(sl.join(", "));
return QString("%1:%2 (%3)")
.arg(file).arg(line).arg(lq);
}
QSqlError lastError()
{
QSqlError e = QSqlQuery::lastError();
if (!e.isValid())
return e;
QString dt = e.driverText();
e.setDriverText(QString("%1 - %2")
.arg(dt).arg(query_details()));
return e;
}
XSqlQuery() : QSqlQuery() { }
XSqlQuery(QString q) : QSqlQuery(q)
{
file = ""; line = 0;
lastq = q;
}
bool exec(QString q)
{
lastq = q;
file = ""; line = 0;
return QSqlQuery::exec(q);
}
bool exec()
{
fprintf(stderr, "QUERY: %s\n", CCHAR(query_details()));
return QSqlQuery::exec();
}
bool prepare(QString q)
{
lastq = q;
return QSqlQuery::prepare(q);
}
void location(const char *f, int l)
{
file = f; line = l;
}
};
class pki_base : public QObject
{
Q_OBJECT
private:
static int pki_counter;
public: /* static */
static int suppress_messages;
static QRegExp limitPattern;
static QString rmslashdot(const QString &fname);
static unsigned hash(QByteArray ba);
protected:
const char *class_name;
QString desc;
int dataVersion;
QVariant sqlItemId;
QString desc, comment;
a1time insertion_date;
enum pki_type pkiType;
/* model data */
pki_base *parent;
@ -42,74 +110,99 @@ class pki_base : public QObject
msg_delete_multi,
msg_create,
};
static int suppress_messages;
static QRegExp limitPattern;
QList<pki_base*> childItems;
pki_base(const QString d = "", pki_base *p = NULL);
virtual void fload(const QString) {};
virtual void writeDefault(const QString) {};
static int get_pki_counter(void);
virtual void fromData(const unsigned char *, db_header_t *) {};
virtual void oldFromData(unsigned char *, int ) {};
virtual QByteArray toData()
{
return QByteArray();
}
virtual bool compare(pki_base *);
virtual bool visible();
virtual ~pki_base();
QString getIntName() const;
QString getUnderlinedName() const;
void setIntName(const QString &d);
QString getClassName();
static QString rmslashdot(const QString &fname);
virtual QString getMsg(msg_type msg)
QString getIntName() const
{
return tr("Internal error: Unexpected message: %1 %2").
arg(class_name).arg(msg);
};
int getVersion();
enum pki_type getType();
return desc;
}
virtual QString comboText() const;
QString getUnderlinedName() const
{
return getIntName().replace(
QRegExp("[ &;`/\\\\]+"), "_");
}
void setIntName(const QString &d)
{
desc = d;
}
QString getComment() const
{
return comment;
}
void setComment(QString c)
{
comment = c;
}
QVariant getSqlItemId()
{
return sqlItemId;
}
enum pki_type getType() const
{
return pkiType;
}
virtual QByteArray i2d();
virtual bool compare(pki_base *);
virtual QString getMsg(msg_type msg);
virtual const char *getClassName() const;
/* Tree View management */
void setParent(pki_base *p);
virtual pki_base *getParent();
pki_base *child(int row);
void append(pki_base *item);
void insert(int row, pki_base *item);
int childCount();
int row() const;
pki_base *iterate(pki_base *pki = NULL);
void takeChild(pki_base *pki);
pki_base *takeFirst();
virtual QVariant column_data(dbheader *hd);
virtual QVariant getIcon(dbheader *hd);
const char *className()
{
return class_name;
};
uint32_t intFromData(QByteArray &ba);
virtual void fromPEM_BIO(BIO *, QString) {};
/* Token handling */
virtual void deleteFromToken();
virtual void deleteFromToken(slotid);
virtual int renameOnToken(slotid, QString);
/* Import / Export management */
virtual BIO *pem(BIO *, int format=0);
virtual void fromPEM_BIO(BIO *, QString);
virtual void fromPEMbyteArray(QByteArray &, QString);
virtual void deleteFromToken() { };
virtual void deleteFromToken(slotid) { };
virtual int renameOnToken(slotid, QString)
{
return 0;
};
virtual QByteArray i2d()
{
return QByteArray();
}
virtual BIO *pem(BIO *, int format=0)
{
(void)format;
return NULL;
}
void fwrite_ba(FILE *fp, QByteArray ba, QString fname);
virtual void fload(const QString);
virtual void writeDefault(const QString);
/* Old database management methods */
virtual void fromData(const unsigned char *, db_header_t *) {};
/* Qt Model-View methods */
virtual QVariant bg_color(dbheader *hd)
{
(void)hd;
return QVariant();
}
int row() const;
virtual QVariant column_data(dbheader *hd);
virtual QVariant getIcon(dbheader *hd);
virtual bool visible();
/* SQL management methods */
QSqlError insertSql();
virtual QSqlError insertSqlData()
{
return QSqlError();
}
QSqlError deleteSql();
virtual QSqlError deleteSqlData()
{
return QSqlError();
}
virtual QSqlError restoreSql(QVariant sqlId);
QSqlError sqlItemNotFound(QVariant sqlId) const;
unsigned hash();
};
Q_DECLARE_METATYPE(pki_base *);
#endif

View File

@ -9,6 +9,7 @@
#include "pki_crl.h"
#include "func.h"
#include "exception.h"
#include "db_base.h"
#include <QDir>
#include "openssl_compat.h"
@ -20,12 +21,15 @@ pki_crl::pki_crl(const QString name )
{
issuer = NULL;
crl = X509_CRL_new();
class_name="pki_crl";
pki_openssl_error();
dataVersion=1;
pkiType=revocation;
}
const char *pki_crl::getClassName() const
{
return "pki_crl";
}
void pki_crl::fromPEM_BIO(BIO *bio, QString name)
{
X509_CRL *_crl;
@ -54,6 +58,74 @@ QString pki_crl::getMsg(msg_type msg)
return pki_base::getMsg(msg);
}
QSqlError pki_crl::insertSqlData()
{
XSqlQuery q;
unsigned name_hash = getSubject().hashNum();
SQL_PREPARE(q, "SELECT x509super.item FROM x509super "
"JOIN certs ON certs.item = x509super.item "
"WHERE x509super.subj_hash=? AND certs.ca=1");
q.bindValue(0, name_hash);
q.exec();
if (q.lastError().isValid())
return q.lastError();
while (q.next()) {
pki_x509 *x = static_cast<pki_x509*>(
db_base::lookupPki(q.value(0).toULongLong()));
if (!x) {
qDebug("CA certificate with id %d not found",
q.value(0).toInt());
continue;
}
verify(x);
}
SQL_PREPARE(q, "INSERT INTO crls (item, hash, num, iss_hash, issuer, crl) "
"VALUES (?, ?, ?, ?, ?, ?)");
q.bindValue(0, sqlItemId);
q.bindValue(1, hash());
q.bindValue(2, numRev());
q.bindValue(3, name_hash);
q.bindValue(4, issuer ? issuer->getSqlItemId() : QVariant());
q.bindValue(5, i2d().toBase64());
q.exec();
return q.lastError();
}
QSqlError pki_crl::restoreSql(QVariant sqlId)
{
XSqlQuery q;
QSqlError e;
e = pki_base::restoreSql(sqlId);
if (e.isValid())
return e;
SQL_PREPARE(q, "SELECT crl, issuer FROM crls WHERE item=?");
q.bindValue(0, sqlId);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
if (!q.first())
return sqlItemNotFound(sqlId);
QByteArray ba = QByteArray::fromBase64(q.value(0).toByteArray());
d2i(ba);
setIssuer(static_cast<pki_x509*>(
db_base::lookupPki(q.value(1).toULongLong())));
return e;
}
QSqlError pki_crl::deleteSqlData()
{
XSqlQuery q;
QSqlError e;
SQL_PREPARE(q, "DELETE FROM crls WHERE item=?");
q.bindValue(0, sqlItemId);
q.exec();
return q.lastError();
}
void pki_crl::fload(const QString fname)
{
FILE *fp = fopen_read(fname);
@ -151,13 +223,6 @@ void pki_crl::fromData(const unsigned char *p, db_header_t *head)
}
}
QByteArray pki_crl::toData()
{
QByteArray ba = i2d();
pki_openssl_error();
return ba;
}
void pki_crl::addRev(const x509rev &xrev, bool withReason)
{
X509_CRL_add0_revoked(crl, xrev.get(withReason));
@ -265,14 +330,25 @@ x509name pki_crl::getSubject() const
return x509name(X509_CRL_get_issuer(crl));
}
bool pki_crl::verify(pki_key *key)
bool pki_crl::verify(pki_x509 *issuer)
{
bool ret=false;
if (key) {
ret = (X509_CRL_verify(crl, key->getPubKey()) == 1);
pki_ign_openssl_error();
if (getSubject() != issuer->getSubject())
return false;
pki_key *key = issuer->getPubKey();
if (!key)
return false;
int ret = X509_CRL_verify(crl, key->getPubKey());
pki_ign_openssl_error();
if (ret != 1) {
delete key;
return false;
}
return ret;
delete key;
pki_x509 *curr = getIssuer();
if (curr && curr->getNotAfter() > issuer->getNotAfter())
return true;
setIssuer(issuer);
return true;
}
void pki_crl::setCrlNumber(a1int num)
@ -350,13 +426,3 @@ QVariant pki_crl::getIcon(dbheader *hd)
{
return hd->id == HD_internal_name ? QVariant(*icon) : QVariant();
}
void pki_crl::oldFromData(unsigned char *p, int size)
{
QByteArray ba((const char *)p, size);
d2i(ba);
if (ba.count() > 0) {
my_error(tr("Wrong Size %1").arg(ba.count()));
}
}

View File

@ -26,8 +26,8 @@ class pki_crl: public pki_x509name
extList extensions() const;
public:
pki_crl(const QString name = "");
/* destructor */
~pki_crl();
const char *getClassName() const;
void fromPEM_BIO(BIO *bio, QString name);
void fload(const QString fname);
QString getSigAlg();
@ -54,9 +54,7 @@ class pki_crl: public pki_x509name
a1time getNextUpdate();
a1time getLastUpdate();
void fromData(const unsigned char *p, db_header_t *head);
void oldFromData(unsigned char *p, int size);
QByteArray toData();
bool verify(pki_key *pkey);
bool verify(pki_x509 *issuer);
int numRev();
x509revList getRevList();
QString printV3ext();
@ -72,6 +70,9 @@ class pki_crl: public pki_x509name
a1int getCrlNumber();
BIO *pem(BIO *, int);
bool visible();
QSqlError insertSqlData();
QSqlError deleteSqlData();
QSqlError restoreSql(QVariant sqlId);
};
#endif

View File

@ -33,18 +33,13 @@ QPixmap *pki_evp::icon[2]= { NULL, NULL };
void pki_evp::init()
{
class_name = "pki_evp";
ownPass = ptCommon;
dataVersion=2;
pkiType=asym_key;
pkiType = asym_key;
}
QString pki_evp::removeTypeFromIntName(QString n)
const char *pki_evp::getClassName() const
{
if (n.right(1) != ")" )
return n;
n.truncate(n.length() - 6);
return n;
return "pki_evp";
}
void pki_evp::setOwnPass(enum passType x)
@ -71,7 +66,26 @@ void pki_evp::setOwnPass(enum passType x)
ownPass = oldOwnPass;
throw(err);
}
EVP_PKEY_free(pk_back);
if (!sqlUpdatePrivateKey()) {
EVP_PKEY_free(pk);
key = pk_back;
ownPass = oldOwnPass;
}
}
bool pki_evp::sqlUpdatePrivateKey()
{
XSqlQuery q;
SQL_PREPARE(q, "UPDATE private_keys SET private=?, ownPass=? "
"WHERE item=?");
q.bindValue(0, encKey.toBase64());
q.bindValue(1, ownPass);
q.bindValue(2, sqlItemId);
q.exec();
encKey.fill(0);
encKey.clear();
return !q.lastError().isValid() && q.numRowsAffected() == 1;
}
void pki_evp::generate(int bits, int type, QProgressBar *progress, int curve_nid)
@ -141,7 +155,7 @@ void pki_evp::generate(int bits, int type, QProgressBar *progress, int curve_nid
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
BN_GENCB_free(bar);
#endif
isPub = false;
pki_openssl_error();
encryptKey();
}
@ -152,7 +166,7 @@ pki_evp::pki_evp(const pki_evp *pk)
init();
pki_openssl_error();
ownPass = pk->ownPass;
encKey = pk->encKey;
isPub = pk->isPub;
}
pki_evp::pki_evp(const QString name, int type)
@ -163,16 +177,6 @@ pki_evp::pki_evp(const QString name, int type)
pki_openssl_error();
}
pki_evp::pki_evp(EVP_PKEY *pkey)
:pki_key()
{
init();
if (key) {
EVP_PKEY_free(key);
}
key = pkey;
}
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
static bool EVP_PKEY_isPrivKey(EVP_PKEY *key)
{
@ -217,6 +221,23 @@ static bool EVP_PKEY_isPrivKey(EVP_PKEY *key)
}
#endif
pki_evp::pki_evp(EVP_PKEY *pkey)
:pki_key()
{
init();
if (key) {
EVP_PKEY_free(key);
}
key = pkey;
isPub = true;
if (EVP_PKEY_isPrivKey(key)) {
isPub = false;
ownPass = ptPrivate;
encryptKey();
pki_openssl_error();
}
}
void pki_evp::openssl_pw_error(QString fname)
{
switch (ERR_peek_error() & 0xff000fff) {
@ -225,7 +246,7 @@ void pki_evp::openssl_pw_error(QString fname)
case ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BAD_DECRYPT):
pki_ign_openssl_error();
throw errorEx(tr("Failed to decrypt the key (bad password) ")+
fname, class_name, E_PASSWD);
fname, getClassName(), E_PASSWD);
}
}
@ -397,15 +418,34 @@ void pki_evp::fromData(const unsigned char *p, db_header_t *head)
throw errorEx(tr("Ignoring unsupported private key"));
encKey = ba;
isPub = encKey.size() == 0;
if (isPub)
return;
/* Convert old encryption scheme to the new one */
EVP_PKEY *pk = decryptKey(1);
EVP_PKEY_free(key);
key = pk;
encryptKey();
pki_openssl_error();
}
EVP_PKEY *pki_evp::decryptKey() const
static void passToKey(Passwd &pass, unsigned char *iv,
const EVP_CIPHER *cipher, unsigned char *ckey, int old)
{
/* generate the key */
EVP_BytesToKey(cipher, old ? EVP_sha1() : EVP_sha256(), iv,
pass.constUchar(), pass.size(), old ? 1 : 8000, ckey, NULL);
}
EVP_PKEY *pki_evp::decryptKey(int oldkey) const
{
unsigned char *p;
const unsigned char *p1;
int outl, decsize;
unsigned char iv[EVP_MAX_IV_LENGTH];
unsigned char ckey[EVP_MAX_KEY_LENGTH];
QByteArray myencKey;
EVP_PKEY *tmpkey;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
@ -432,35 +472,36 @@ EVP_PKEY *pki_evp::decryptKey() const
pass_info pi(XCA_TITLE, tr("Please enter the password to decrypt the private key: '%1'").arg(getIntName()));
ret = PwDialog::execute(&pi, &ownPassBuf, false);
if (ret != 1)
throw errorEx(tr("Password input aborted"), class_name);
throw errorEx(tr("Password input aborted"),
getClassName());
} else if (ownPass == ptBogus) { // BOGUS pass
ownPassBuf = "Bogus";
} else {
ownPassBuf = passwd;
while (md5passwd(ownPassBuf) != passHash &&
while (sha512passwT(ownPassBuf, passHash) != passHash &&
sha512passwd(ownPassBuf, passHash) != passHash)
{
pass_info p(XCA_TITLE, tr("Please enter the database password for decrypting the key '%1'").arg(getIntName()));
ret = PwDialog::execute(&p, &ownPassBuf, false);
if (ret != 1)
throw errorEx(tr("Password input aborted"), class_name);
throw errorEx(tr("Password input aborted"),
getClassName());
}
}
p = (unsigned char *)OPENSSL_malloc(encKey.count());
if (encKey.count() == 0)
myencKey = getEncKey();
else
myencKey = encKey;
if (myencKey.count() == 0)
return NULL;
p = (unsigned char *)OPENSSL_malloc(myencKey.count());
check_oom(p);
pki_openssl_error();
p1 = p;
memset(iv, 0, EVP_MAX_IV_LENGTH);
memcpy(iv, encKey.constData(), 8); /* recover the iv */
/* generate the key */
EVP_BytesToKey(cipher, EVP_sha1(), iv,
ownPassBuf.constUchar(),
ownPassBuf.size(), 1, ckey, NULL);
/* we use sha1 as message digest,
* because an md5 version of the password is
* stored in the database...
*/
memcpy(iv, myencKey.constData(), 8); /* recover the iv */
passToKey(ownPassBuf, iv, cipher, ckey, oldkey);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
ctx = EVP_CIPHER_CTX_new();
#else
@ -469,15 +510,16 @@ EVP_PKEY *pki_evp::decryptKey() const
EVP_CIPHER_CTX_init(ctx);
EVP_DecryptInit(ctx, cipher, ckey, iv);
EVP_DecryptUpdate(ctx, p , &outl,
(const unsigned char*)encKey.constData() +8, encKey.count() -8);
(const unsigned char*)myencKey.constData() +8,
myencKey.count() -8);
decsize = outl;
EVP_DecryptFinal(ctx, p + decsize , &outl);
decsize += outl;
//printf("Decrypt decsize=%d, encKey_len=%d\n", decsize, encKey.count() -8);
//printf("Decrypt decsize=%d, encKey_len=%d\n", decsize, myencKey.count() -8);
pki_openssl_error();
tmpkey = d2i_PrivateKey(getKeyType(), NULL, &p1, decsize);
pki_openssl_error();
OPENSSL_cleanse(p, myencKey.count());
OPENSSL_free(p);
EVP_CIPHER_CTX_cleanup(ctx);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
@ -488,20 +530,10 @@ EVP_PKEY *pki_evp::decryptKey() const
RSA *rsa = EVP_PKEY_get0_RSA(tmpkey);
RSA_blinding_on(rsa, NULL);
}
myencKey.fill(0);
return tmpkey;
}
QByteArray pki_evp::toData()
{
QByteArray ba;
ba += db::intToData(getKeyType());
ba += db::intToData(ownPass);
ba += i2d();
ba += encKey;
return ba;
}
EVP_PKEY *pki_evp::priv2pub(EVP_PKEY* key)
{
int keylen;
@ -542,7 +574,7 @@ void pki_evp::encryptKey(const char *password)
arg(getIntName()));
ret = PwDialog::execute(&p, &ownPassBuf, true);
if (ret != 1)
throw errorEx("Password input aborted", class_name);
throw errorEx("Password input aborted", getClassName());
} else if (ownPass == ptBogus) { // BOGUS password
ownPassBuf = "Bogus";
} else {
@ -554,12 +586,13 @@ void pki_evp::encryptKey(const char *password)
int ret = 0;
ownPassBuf = passwd;
pass_info p(XCA_TITLE, tr("Please enter the database password for encrypting the key"));
while (md5passwd(ownPassBuf) != passHash &&
sha512passwd(ownPassBuf, passHash) != passHash )
while (sha512passwT(ownPassBuf, passHash) != passHash &&
sha512passwd(ownPassBuf, passHash) != passHash)
{
ret = PwDialog::execute(&p, &ownPassBuf, false);
if (ret != 1)
throw errorEx("Password input aborted", class_name);
throw errorEx("Password input aborted",
getClassName());
}
}
}
@ -567,9 +600,7 @@ void pki_evp::encryptKey(const char *password)
/* Prepare Encryption */
memset(iv, 0, EVP_MAX_IV_LENGTH);
Entropy::get(iv, 8); /* Generate a salt */
EVP_BytesToKey(cipher, EVP_sha1(), iv,
ownPassBuf.constUchar(),
ownPassBuf.size(), 1, ckey, NULL);
passToKey(ownPassBuf, iv, cipher, ckey, 0);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
ctx = EVP_CIPHER_CTX_new();
#else
@ -578,9 +609,10 @@ void pki_evp::encryptKey(const char *password)
EVP_CIPHER_CTX_init (ctx);
pki_openssl_error();
/* reserve space for unencrypted and encrypted key */
/* reserve space for encrypted key */
keylen = i2d_PrivateKey(key, NULL);
encKey.resize(keylen + EVP_MAX_KEY_LENGTH + 8);
/* allocate space for unencrypted key */
punenc1 = punenc = (unsigned char *)OPENSSL_malloc(keylen);
check_oom(punenc);
keylen = i2d_PrivateKey(key, &punenc1);
@ -606,7 +638,7 @@ void pki_evp::encryptKey(const char *password)
EVP_CIPHER_CTX_free(ctx);
#endif
/* wipe out the memory */
memset(punenc, 0, keylen);
OPENSSL_cleanse(punenc, keylen);
OPENSSL_free(punenc);
pki_openssl_error();
@ -616,9 +648,6 @@ void pki_evp::encryptKey(const char *password)
key = pkey1;
pki_openssl_error();
//CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF);
//printf("Encrypt: encKey_len=%d\n", encKey_len);
return;
}
@ -632,13 +661,83 @@ void pki_evp::set_evp_key(EVP_PKEY *pkey)
void pki_evp::bogusEncryptKey()
{
ownPass = ptBogus;
isPub = false;
encryptKey();
}
pki_evp::~pki_evp()
{
encKey.fill(0);
}
QSqlError pki_evp::insertSqlData()
{
XSqlQuery q;
QSqlError e = pki_key::insertSqlData();
if (e.isValid())
return e;
if (isPubKey())
return QSqlError();
SQL_PREPARE(q, "INSERT INTO private_keys (item, ownPass, private) "
"VALUES (?, ?, ?)");
q.bindValue(0, sqlItemId);
q.bindValue(1, ownPass);
q.bindValue(2, encKey.toBase64());
q.exec();
encKey.fill(0);
encKey.clear();
return q.lastError();
}
QSqlError pki_evp::restoreSql(QVariant sqlId)
{
XSqlQuery q;
QSqlError e;
e = pki_key::restoreSql(sqlId);
if (e.isValid())
return e;
SQL_PREPARE(q, "SELECT ownPass FROM private_keys WHERE item=?");
q.bindValue(0, sqlId);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
if (!q.first())
return QSqlError();
/* This is a private key */
ownPass = q.value(0).toInt();
isPub = false;
return e;
}
QByteArray pki_evp::getEncKey() const
{
XSqlQuery q;
QSqlError e;
QByteArray ba;
SQL_PREPARE(q, "SELECT private FROM private_keys WHERE item=?");
q.bindValue(0, sqlItemId);
q.exec();
e = q.lastError();
if (e.isValid() || !q.first())
return QByteArray();
return QByteArray::fromBase64(q.value(0).toByteArray());
}
QSqlError pki_evp::deleteSqlData()
{
XSqlQuery q;
QSqlError e = pki_key::deleteSqlData();
if (e.isValid())
return e;
SQL_PREPARE(q, "DELETE FROM private_keys WHERE item=?");
q.bindValue(0, sqlItemId);
q.exec();
return q.lastError();
}
void pki_evp::writePKCS8(const QString fname, const EVP_CIPHER *enc,
pem_password_cb *cb, bool pem)
@ -729,14 +828,6 @@ void pki_evp::writeKey(const QString fname, const EVP_CIPHER *enc,
pki_openssl_error();
}
bool pki_evp::isPubKey() const
{
if (encKey.count() == 0) {
return true;
}
return false;
}
int pki_evp::verify()
{
bool veri = false;
@ -812,7 +903,8 @@ QString pki_evp::md5passwd(QByteArray pass)
return str;
}
QString pki_evp::sha512passwd(QByteArray pass, QString salt)
QString pki_evp::_sha512passwd(QByteArray pass, QString salt,
int size, int repeat)
{
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_MD_CTX mdctxbuf;
@ -823,10 +915,10 @@ QString pki_evp::sha512passwd(QByteArray pass, QString salt)
int j;
unsigned char m[EVP_MAX_MD_SIZE];
if (salt.length() <5)
if (salt.length() < size) {
abort();
str = salt.left(5);
}
str = salt.left(size);
pass = str.toLatin1() + pass;
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
@ -834,15 +926,16 @@ QString pki_evp::sha512passwd(QByteArray pass, QString salt)
#else
mdctx = &mdctxbuf;
#endif
while (repeat--) {
EVP_DigestInit(mdctx, EVP_sha512());
EVP_DigestUpdate(mdctx, pass.constData(), pass.size());
EVP_DigestFinal(mdctx, m, (unsigned*)&n);
pass = QByteArray((char*)m, n);
EVP_DigestInit(mdctx, EVP_sha512());
EVP_DigestUpdate(mdctx, pass.constData(), pass.size());
EVP_DigestFinal(mdctx, m, (unsigned*)&n);
}
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
EVP_MD_CTX_free(mdctx);
#endif
for (j=0; j<n; j++) {
char zs[4];
sprintf(zs, "%02X",m[j]);
@ -851,90 +944,12 @@ QString pki_evp::sha512passwd(QByteArray pass, QString salt)
return str;
}
void pki_evp::veryOldFromData(unsigned char *p, int size )
QString pki_evp::sha512passwd(QByteArray pass, QString salt)
{
unsigned char *sik, *pdec, *pdec1, *sik1;
int outl, decsize;
unsigned char iv[EVP_MAX_IV_LENGTH];
unsigned char ckey[EVP_MAX_KEY_LENGTH];
memset(iv, 0, EVP_MAX_IV_LENGTH);
RSA *rsakey;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_CIPHER_CTX ctxbuf;
#endif
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *cipher = EVP_des_ede3_cbc();
sik = (unsigned char *)OPENSSL_malloc(size);
check_oom(sik);
pki_openssl_error();
pdec = (unsigned char *)OPENSSL_malloc(size);
if (pdec == NULL ) {
OPENSSL_free(sik);
check_oom(pdec);
}
pdec1=pdec;
sik1=sik;
memcpy(iv, p, 8); /* recover the iv */
/* generate the key */
EVP_BytesToKey(cipher, EVP_sha1(), iv, oldpasswd.constUchar(),
oldpasswd.size(), 1, ckey, NULL);
/* we use sha1 as message digest,
* because an md5 version of the password is
* stored in the database...
*/
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
ctx = EVP_CIPHER_CTX_new();
#else
ctx = &ctxbuf;
#endif
EVP_CIPHER_CTX_init(ctx);
EVP_DecryptInit(ctx, cipher, ckey, iv);
EVP_DecryptUpdate(ctx, pdec , &outl, p + 8, size - 8);
decsize = outl;
EVP_DecryptFinal(ctx, pdec + decsize, &outl);
decsize += outl;
pki_openssl_error();
memcpy(sik, pdec, decsize);
if (getKeyType() == EVP_PKEY_RSA) {
rsakey=d2i_RSAPrivateKey(NULL,(const unsigned char **)&pdec, decsize);
if (pki_ign_openssl_error()) {
rsakey = d2i_RSA_PUBKEY(NULL, (const unsigned char **)&sik, decsize);
}
pki_openssl_error();
if (rsakey) EVP_PKEY_assign_RSA(key, rsakey);
}
OPENSSL_free(sik1);
OPENSSL_free(pdec1);
EVP_CIPHER_CTX_cleanup(ctx);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
EVP_CIPHER_CTX_free(ctx);
#endif
pki_openssl_error();
encryptKey();
return _sha512passwd(pass, salt, 5, 1);
}
void pki_evp::oldFromData(unsigned char *p, int size )
QString pki_evp::sha512passwT(QByteArray pass, QString salt)
{
int version, type;
QByteArray ba;
version = intFromData(ba);
if (version != 1) { // backward compatibility
veryOldFromData(p, size);
return;
}
if (key)
EVP_PKEY_free(key);
key = NULL;
type = intFromData(ba);
ownPass = intFromData(ba);
d2i_old(ba, type);
pki_openssl_error();
encKey = ba;
return _sha512passwd(pass, salt, 17, 8000);
}

View File

@ -20,10 +20,12 @@
class pki_evp: public pki_key
{
Q_OBJECT
protected:
QByteArray encKey;
void init();
void veryOldFromData(unsigned char *p, int size);
QByteArray getEncKey() const;
static QString _sha512passwd(QByteArray pass, QString salt,
int size, int repeat);
protected:
void openssl_pw_error(QString fname);
public:
static QPixmap *icon[2];
@ -32,16 +34,18 @@ class pki_evp: public pki_key
static Passwd oldpasswd;
static QString md5passwd(QByteArray pass);
static QString sha512passwd(QByteArray pass, QString salt);
static QString sha512passwT(QByteArray pass, QString salt);
void generate(int bits, int type, QProgressBar *progress);
void generate(int bits, int type, QProgressBar *progress,
int curve_nid);
void setOwnPass(enum passType);
const char *getClassName() const;
pki_evp(const QString name = "", int type = EVP_PKEY_RSA);
pki_evp(EVP_PKEY *pkey);
void set_evp_key(EVP_PKEY *pkey);
void encryptKey(const char *password = NULL);
void bogusEncryptKey();
EVP_PKEY *decryptKey() const;
EVP_PKEY *decryptKey(int oldkey=0) const;
pki_evp(const pki_evp *pk);
/* destructor */
virtual ~pki_evp();
@ -52,16 +56,17 @@ class pki_evp: public pki_key
void fload(const QString fname);
void writeDefault(const QString fname);
void fromData(const unsigned char *p, db_header_t *head);
void oldFromData(unsigned char *p, int size);
QByteArray toData();
void writeKey(const QString fname, const EVP_CIPHER *enc,
pem_password_cb *cb, bool pem);
void writePKCS8(const QString fname, const EVP_CIPHER *enc,
pem_password_cb *cb, bool pem);
bool isPubKey() const;
int verify();
const EVP_MD *getDefaultMD();
QVariant getIcon(dbheader *hd);
bool sqlUpdatePrivateKey();
QSqlError insertSqlData();
QSqlError deleteSqlData();
QSqlError restoreSql(QVariant sqlId);
};
#endif

View File

@ -24,19 +24,25 @@ pki_key::pki_key(const QString name)
:pki_base(name)
{
key = EVP_PKEY_new();
ucount = 0;
class_name = "pki_key";
key_size = 0;
isPub = true;
}
const char *pki_key::getClassName() const
{
return "pki_key";
}
pki_key::pki_key(const pki_key *pk)
:pki_base(pk->desc)
{
ucount = pk->ucount;
key = EVP_PKEY_new();
if (pk->key) {
QByteArray ba = i2d_bytearray(I2D_VOID(i2d_PUBKEY), pk->key);
d2i(ba);
} else {
key = EVP_PKEY_new();
}
key_size = pk->key_size;
}
pki_key::~pki_key()
@ -45,6 +51,19 @@ pki_key::~pki_key()
EVP_PKEY_free(key);
}
EVP_PKEY *pki_key::decryptKey(int oldkey) const
{
(void)oldkey;
qDebug("VIRTUAL pki_key::decryptKey() should NEVER be called");
return NULL;
}
const EVP_MD *pki_key::getDefaultMD()
{
qDebug("VIRTUAL pki_key::getDefaultMD() should NEVER be called");
return NULL;
}
void pki_key::d2i(QByteArray &ba)
{
EVP_PKEY *k = (EVP_PKEY*)d2i_bytearray(D2I_VOID(d2i_PUBKEY), ba);
@ -127,7 +146,7 @@ BIO *pki_key::pem(BIO *b, int format)
return b;
}
QString pki_key::length()
QString pki_key::length() const
{
bool dsa_unset = false;
@ -197,24 +216,13 @@ QString pki_key::getMsg(msg_type msg)
return pki_base::getMsg(msg);
}
QString pki_key::getIntNameWithType()
QString pki_key::comboText() const
{
return QString("%1 (%2:%3%4)").arg(getIntName()).arg(getTypeString()).
arg(length()).arg(isPubKey() ?
QString(" ") + tr("Public key") : QString(""));
}
QString pki_key::removeTypeFromIntName(QString n)
{
int i;
if (n.right(1) != ")" )
return n;
i = n.lastIndexOf(" (");
if (i > 0)
n.truncate(i);
return n;
}
bool pki_key::isToken()
{
return false;
@ -225,20 +233,19 @@ bool pki_key::isPrivKey() const
return !isPubKey();
}
int pki_key::incUcount()
{
ucount++;
return ucount;
}
int pki_key::decUcount()
{
ucount--;
return ucount;
}
int pki_key::getUcount()
{
return ucount;
XSqlQuery q;
int size = -1;
SQL_PREPARE(q, "SELECT COUNT(*) FROM x509super WHERE key=?");
q.bindValue(0, sqlItemId);
q.exec();
if (q.first())
size = q.value(0).toInt();
else
qDebug("Failed to get key count for %s", CCHAR(getIntName()));
MainWindow::dbSqlError(q.lastError());
return size;
}
int pki_key::getKeyType() const
@ -395,8 +402,7 @@ QString pki_key::BN2QString(const BIGNUM *bn) const
return "--";
QString x="";
char zs[10];
int j;
int size = BN_num_bytes(bn);
int j, size = BN_num_bytes(bn);
unsigned char *buf = (unsigned char *)OPENSSL_malloc(size);
check_oom(buf);
BN_bn2bin(bn, buf);
@ -438,6 +444,92 @@ QVariant pki_key::column_data(dbheader *hd)
return pki_base::column_data(hd);
}
QSqlError pki_key::insertSqlData()
{
unsigned myhash = hash();
XSqlQuery q;
QList<pki_x509super*> list;
SQL_PREPARE(q, "SELECT item FROM x509super WHERE key_hash=? AND key IS NULL");
q.bindValue(0, myhash);
q.exec();
if (q.lastError().isValid())
return q.lastError();
while (q.next()) {
pki_x509super *x = static_cast<pki_x509super*>(
db_base::lookupPki(q.value(0).toULongLong()));
if (!x) {
qDebug("X509 Super class with id %d not found",
q.value(0).toInt());
continue;
}
if (x->compareRefKey(this)) {
x->setRefKey(this);
list << x;
}
}
q.finish();
SQL_PREPARE(q, "UPDATE x509super SET key=? WHERE item=?");
q.bindValue(0, sqlItemId);
foreach(pki_x509super* x, list) {
q.bindValue(1, x->getSqlItemId());
q.exec();
if (q.lastError().isValid())
return q.lastError();
}
q.finish();
SQL_PREPARE(q, "INSERT INTO public_keys (item, type, hash, len, public) "
"VALUES (?, ?, ?, ?, ?)");
q.bindValue(0, sqlItemId);
q.bindValue(1, getTypeString());
q.bindValue(2, myhash);
q.bindValue(3, EVP_PKEY_bits(key));
q.bindValue(4, i2d().toBase64());
q.exec();
return q.lastError();
}
QSqlError pki_key::restoreSql(QVariant sqlId)
{
XSqlQuery q;
QSqlError e;
e = pki_base::restoreSql(sqlId);
if (e.isValid())
return e;
SQL_PREPARE(q, "SELECT public, len FROM public_keys WHERE item=?");
q.bindValue(0, sqlId);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
if (!q.first())
return sqlItemNotFound(sqlId);
QByteArray ba = QByteArray::fromBase64(q.value(0).toByteArray());
d2i(ba);
key_size = q.value(1).toInt();
return e;
}
QSqlError pki_key::deleteSqlData()
{
XSqlQuery q;
QSqlError e;
SQL_PREPARE(q, "DELETE FROM public_keys WHERE item=?");
q.bindValue(0, sqlItemId);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
SQL_PREPARE(q, "UPDATE x509super SET key=NULL WHERE key=?");
q.bindValue(0, sqlItemId);
q.exec();
return q.lastError();
}
BIGNUM *pki_key::ssh_key_data2bn(QByteArray *ba, bool skip)
{
const unsigned char *d = (const unsigned char *)ba->constData();

View File

@ -22,7 +22,8 @@ class pki_key: public pki_base
{
Q_OBJECT
protected:
int ownPass;
int ownPass, key_size;
bool isPub;
EVP_PKEY *key;
QString BN2QString(const BIGNUM *bn) const;
QString BNoneLine(BIGNUM *bn) const;
@ -37,39 +38,22 @@ class pki_key: public pki_base
pki_key(const QString name = "");
pki_key(const pki_key *pk);
virtual ~pki_key();
const char *getClassName() const;
static builtin_curves builtinCurves;
enum passType { ptCommon, ptPrivate, ptBogus, ptPin };
virtual EVP_PKEY *decryptKey() const
{
return NULL;
}
virtual QString length() const
{
return QString();
}
virtual bool isPubKey() const
{
return true;
}
virtual const EVP_MD *getDefaultMD()
{
return NULL;
}
QString length() const;
QString comboText() const;
virtual EVP_PKEY *decryptKey(int oldkey=0) const;
virtual const EVP_MD *getDefaultMD();
virtual bool isToken();
virtual QString getTypeString(void) const;
virtual QString getIntNameWithType(void);
virtual QList<int> possibleHashNids();
virtual QString getMsg(msg_type msg);
virtual QString length();
void writePublic(const QString fname, bool pem);
bool compare(pki_base *ref);
int getKeyType() const;
static QString removeTypeFromIntName(QString n);
bool isPrivKey() const;
int incUcount();
int decUcount();
int getUcount();
int getOwnPass(void)
{
@ -79,6 +63,10 @@ class pki_key: public pki_base
{
return key;
}
bool isPubKey() const
{
return isPub;
}
BIO *pem(BIO *, int);
QVariant column_data(dbheader *hd);
QString modulus();
@ -92,6 +80,9 @@ class pki_key: public pki_base
QByteArray i2d();
EVP_PKEY *load_ssh2_key(FILE *fp);
void writeSSH2public(QString fname);
QSqlError insertSqlData();
QSqlError deleteSqlData();
QSqlError restoreSql(QVariant sqlId);
};
#endif

View File

@ -24,7 +24,6 @@ pki_multi::pki_multi(const QString name)
:pki_base(name)
{
multi.clear();
class_name="pki_multi";
}
pki_multi::~pki_multi()
@ -34,6 +33,11 @@ pki_multi::~pki_multi()
delete pki;
}
const char *pki_multi::getClassName() const
{
return "pki_multi";
}
pki_base *pki_multi::pull()
{
if (multi.isEmpty())

View File

@ -31,6 +31,7 @@ class pki_multi: public pki_base
{
return multi.count();
}
const char *getClassName() const;
};

View File

@ -19,13 +19,17 @@
pki_pkcs12::pki_pkcs12(const QString d, pki_x509 *acert, pki_evp *akey)
:pki_base(d)
{
class_name="pki_pkcs12";
key = new pki_evp(akey);
cert = new pki_x509(acert);
certstack = sk_X509_new_null();
openssl_error();
}
const char *pki_pkcs12::getClassName() const
{
return "pki_pkcs12";
}
pki_pkcs12::pki_pkcs12(const QString fname)
:pki_base(fname)
{
@ -34,7 +38,6 @@ pki_pkcs12::pki_pkcs12(const QString fname)
EVP_PKEY *mykey = NULL;
X509 *mycert = NULL;
key=NULL; cert=NULL;
class_name="pki_pkcs12";
certstack = sk_X509_new_null();
pass_info p(XCA_TITLE, tr("Please enter the password to decrypt the PKCS#12 file:\n%1").arg(compressFilename(fname)));
fp = fopen_read(fname);

View File

@ -34,6 +34,7 @@ class pki_pkcs12: public pki_base
pki_pkcs12(const QString fname);
~pki_pkcs12();
const char *getClassName() const;
void addCaCert(pki_x509 *acert);
pki_key *getKey();
pki_x509 *getCert();

View File

@ -17,9 +17,12 @@ pki_pkcs7::pki_pkcs7(const QString name)
p7 = PKCS7_new();
PKCS7_set_type(p7, NID_pkcs7_signed);
PKCS7_content_new(p7, NID_pkcs7_data);
class_name = "pki_pkcs7";
}
const char *pki_pkcs7::getClassName() const
{
return "pki_pkcs7";
}
pki_pkcs7::~pki_pkcs7()
{
@ -56,7 +59,8 @@ void pki_pkcs7::signBio(pki_x509 *crt, BIO *bio)
STACK_OF(X509) *certstack;
if (!crt) return;
privkey = crt->getRefKey();
if (!privkey) throw errorEx("No private key for signing found", class_name);
if (!privkey) throw errorEx("No private key for signing found",
getClassName());
certstack = sk_X509_new_null();
pki_x509 *signer = crt->getSigner();

View File

@ -21,8 +21,8 @@ class pki_pkcs7: public pki_base
void encryptBio(pki_x509 *crt, BIO * bio);
public:
pki_pkcs7(const QString name = "");
/* destructor */
virtual ~pki_pkcs7();
const char *getClassName() const;
void signFile(pki_x509 *crt, QString filename);
void signCert(pki_x509 *crt, pki_x509 *contCert);

View File

@ -34,15 +34,18 @@ bool pki_scard::only_token_hashes = false;
void pki_scard::init(void)
{
class_name = "pki_scard";
ownPass = ptPin;
dataVersion = 2;
pkiType = smartCard;
card_serial = card_manufacturer = card_label = "";
card_model = slot_label = "";
}
const char *pki_scard::getClassName() const
{
return "pki_scard";
}
pki_scard::pki_scard(const QString name)
:pki_key(name)
{
@ -67,6 +70,56 @@ QString pki_scard::getMsg(msg_type msg)
return pki_base::getMsg(msg);
}
QSqlError pki_scard::insertSqlData()
{
XSqlQuery q;
QSqlError e = pki_key::insertSqlData();
if (e.isValid())
return e;
SQL_PREPARE(q, "INSERT INTO tokens (item, card_manufacturer, card_serial, "
"card_model, card_label, slot_label, "
"object_id) "
"VALUES (?, ?, ?, ?, ?, ?, ?)");
q.bindValue(0, sqlItemId);
q.bindValue(1, card_manufacturer);
q.bindValue(2, card_serial);
q.bindValue(3, card_model);
q.bindValue(4, card_label);
q.bindValue(5, slot_label);
q.bindValue(6, object_id);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
SQL_PREPARE(q, "INSERT INTO token_mechanism (item, mechanism) "
"VALUES (?, ?)");
q.bindValue(0, sqlItemId);
foreach(CK_MECHANISM_TYPE m, mech_list) {
q.bindValue(1, QVariant((uint)m));
q.exec();
}
return q.lastError();
}
QSqlError pki_scard::deleteSqlData()
{
XSqlQuery q;
QSqlError e = pki_key::deleteSqlData();
if (e.isValid())
return e;
SQL_PREPARE(q, "DELETE FROM tokens WHERE item=?");
q.bindValue(0, sqlItemId);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
SQL_PREPARE(q, "DELETE FROM token_mechanism WHERE item=?");
q.bindValue(0, sqlItemId);
q.exec();
return q.lastError();
}
EVP_PKEY *pki_scard::load_pubkey(pkcs11 &p11, CK_OBJECT_HANDLE object) const
{
unsigned long keytype;
@ -690,24 +743,6 @@ pki_scard::~pki_scard()
{
}
QByteArray pki_scard::toData()
{
QByteArray ba;
ba += db::stringToData(card_serial);
ba += db::stringToData(card_manufacturer);
ba += db::stringToData(card_label);
ba += db::stringToData(slot_label);
ba += db::stringToData(card_model);
ba += db::stringToData(object_id);
ba += db::intToData(mech_list.count());
for (int i=0; i<mech_list.count(); i++)
ba += db::intToData(mech_list[i]);
ba += i2d();
return ba;
}
void pki_scard::fromData(const unsigned char *p, db_header_t *head )
{
int version, size;
@ -744,20 +779,16 @@ void pki_scard::fromData(const unsigned char *p, db_header_t *head )
}
}
bool pki_scard::isPubKey() const
{
return false;
}
QString pki_scard::getTypeString(void) const
{
return tr("Token %1").arg(pki_key::getTypeString());
}
EVP_PKEY *pki_scard::decryptKey() const
EVP_PKEY *pki_scard::decryptKey(int oldkey) const
{
slotid slot_id;
QString pin, key_id;
(void)oldkey;
if (!prepare_card(&slot_id))
throw errorEx(tr("Failed to find the key on the token"));

View File

@ -31,13 +31,12 @@ class pki_scard: public pki_key
public:
pki_scard(const QString name);
virtual ~pki_scard();
const char *getClassName() const;
static QPixmap *icon[1];
static bool only_token_hashes;
void load_token(pkcs11 &p11, CK_OBJECT_HANDLE object);
bool prepare_card(slotid *slot, bool verifyPubkey=true) const;
void fromData(const unsigned char *p, db_header_t *head);
QByteArray toData();
bool isPubKey() const;
QString getTypeString(void) const;
QString getManufacturer() const
{
@ -64,7 +63,7 @@ class pki_scard: public pki_key
{
return card_label;
}
EVP_PKEY *decryptKey() const;
EVP_PKEY *decryptKey(int oldkey=0) const;
QString scardLogin(pkcs11 &p11, bool so, bool force=false)const;
void changePin();
void initPin();
@ -90,6 +89,8 @@ class pki_scard: public pki_key
int renameOnToken(slotid slot, QString name);
QString getMsg(msg_type msg);
bool visible();
QSqlError insertSqlData();
QSqlError deleteSqlData();
};
#endif

View File

@ -1,6 +1,6 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2001 - 2012 Christian Hohnstaedt.
* Copyright (C) 2001 - 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
@ -11,80 +11,120 @@
#include "exception.h"
#include "widgets/MainWindow.h"
#include <QDir>
#include <QBuffer>
#include <QDataStream>
QPixmap *pki_temp::icon= NULL;
#define TEMPLATE_DS_VERSION (QDataStream::Qt_4_2)
QList<QString> pki_temp::tmpl_keys = QList<QString>()
<< "subAltName"
<< "issAltName"
<< "crlDist"
<< "authInfAcc"
<< "nsCertType"
<< "nsComment"
<< "nsBaseUrl"
<< "nsRevocationUrl"
<< "nsCARevocationUrl"
<< "nsRenewalUrl"
<< "nsCaPolicyUrl"
<< "nsSslServerName"
<< "ca"
<< "bcCritical"
<< "ekuCritical"
<< "kuCritical"
<< "subKey"
<< "authKey"
<< "basicPath"
<< "validN"
<< "validM"
<< "validMidn"
<< "keyUse"
<< "eKeyUse"
<< "adv_ext"
<< "noWellDefinedExpDate";
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;
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;
xname = pk->xname;
settings = pk->settings;
}
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;
foreach(QString key, tmpl_keys) {
settings[key] = QString();
}
settings["nsComment"] = "xca certificate";
settings["validN"] = "365";
}
const char *pki_temp::getClassName() const
{
return "pki_temp";
}
QString pki_temp::comboText() const
{
return pre_defined ? QString("[default] ") + pki_base::comboText() :
pki_base::comboText();
}
QSqlError pki_temp::insertSqlData()
{
XSqlQuery q;
QSqlError e = pki_x509name::insertSqlData();
if (e.isValid())
return e;
SQL_PREPARE(q, "INSERT INTO templates (item, version, template) "
"VALUES (?, ?, ?)");
q.bindValue(0, sqlItemId);
q.bindValue(1, TMPL_VERSION);
q.bindValue(2, toData().toBase64());
q.exec();
return q.lastError();
}
QSqlError pki_temp::restoreSql(QVariant sqlId)
{
XSqlQuery q;
QSqlError e;
e = pki_x509name::restoreSql(sqlId);
if (e.isValid())
return e;
SQL_PREPARE(q, "SELECT version, template FROM templates WHERE item=?");
q.bindValue(0, sqlId);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
if (!q.first())
return sqlItemNotFound(sqlId);
int version = q.value(0).toInt();
QByteArray ba = QByteArray::fromBase64(q.value(1).toByteArray());
fromData(ba, version);
return e;
}
QSqlError pki_temp::deleteSqlData()
{
XSqlQuery q;
QSqlError e = pki_x509name::deleteSqlData();
if (e.isValid())
return e;
SQL_PREPARE(q, "DELETE FROM templates WHERE item=?");
q.bindValue(0, sqlItemId);
q.exec();
return q.lastError();
}
QString pki_temp::getMsg(msg_type msg)
@ -129,12 +169,20 @@ static int bitsToInt(extList &el, int nid, bool *crit)
return ret;
}
void pki_temp::fromExtList(extList *el, int nid, const char *item)
{
QString target;
el->genConf(nid, &target, &adv_ext);
settings[item] = target;
}
extList pki_temp::fromCert(pki_x509super *cert_or_req)
{
x509name n;
extList el = cert_or_req->getV3ext();
adv_ext.clear();
nsComment = "";
settings["nsComment"] = "";
n = cert_or_req->getSubject();
foreach(QString sn, MainWindow::explicit_dn) {
@ -149,50 +197,51 @@ extList pki_temp::fromCert(pki_x509super *cert_or_req)
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);
fromExtList(&el, NID_subject_alt_name, "subAltName");
fromExtList(&el, NID_issuer_alt_name, "issAltName");
fromExtList(&el, NID_crl_distribution_points, "crlDist");
fromExtList(&el, NID_info_access, "authInfAcc");
fromExtList(&el, NID_netscape_comment, "nsComment");
fromExtList(&el, NID_netscape_base_url, "nsBaseUrl");
fromExtList(&el, NID_netscape_revocation_url, "nsRevocationUrl");
fromExtList(&el, NID_netscape_ca_revocation_url, "nsCARevocationUrl");
fromExtList(&el, NID_netscape_renewal_url, "nsRenewalUrl");
fromExtList(&el, NID_netscape_ca_policy_url, "nsCaPolicyUrl");
fromExtList(&el, 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);
settings["bcCritical"] = "1";
settings["ca"] = sl.contains("CA:TRUE") ? 1 : 2;
settings["basicPath"]=sl.filter("pathlen:").join("") .mid(8,-1);
} else {
bcCrit = false;
ca = 0;
settings["bcCritical"] = "";
settings["ca"] = "";
settings["basicPath"] = "";
}
authKey = el.delByNid(NID_authority_key_identifier);
subKey = el.delByNid(NID_subject_key_identifier);
settings["authKey"] = el.delByNid(NID_authority_key_identifier);
settings["subKey"] = el.delByNid(NID_subject_key_identifier);
nsCertType = bitsToInt(el, NID_netscape_cert_type, NULL);
int nsCT = bitsToInt(el, NID_netscape_cert_type, NULL);
/* bit 4 is unused. Move higher bits down. */
nsCertType = (nsCertType & 0xf) | ((nsCertType & 0xf0) >> 1);
settings["nsCertType"] = (nsCT & 0xf) | ((nsCT & 0xf0) >> 1);
keyUse = bitsToInt(el, NID_key_usage, &keyUseCrit);
bool keyUseCritical;
settings["keyUse"] = QString::number(
bitsToInt(el, NID_key_usage, &keyUseCritical));
settings["keyUseCritical"] = keyUseCritical ? "1" : "0";
fromExtList(&el, NID_ext_key_usage, "eKeyUse");
el.genConf(NID_ext_key_usage, &eKeyUse);
if (eKeyUse.startsWith("critical,")) {
eKeyUseCrit = true;
eKeyUse = eKeyUse.mid(9, -1);
}
el.genGenericConf(&adv_ext);
settings["adv_ext"] = adv_ext;
if (cert_or_req->getType() == x509) {
pki_x509 *cert = (pki_x509*)cert_or_req;
if (cert->getNotAfter().isUndefined()) {
noWellDefined = true;
settings["noWellDefinedExpDate"] = "1";
} else {
a1time notBefore = cert->getNotBefore();
a1time notAfter = cert->getNotAfter();
@ -200,20 +249,20 @@ extList pki_temp::fromCert(pki_x509super *cert_or_req)
if (notBefore.toPlain().endsWith("000000Z") &&
notAfter.toPlain().endsWith("235959Z"))
{
validMidn = true;
settings["validMidn"] = "1";
}
int diff = notBefore.daysTo(notAfter);
validM = 0;
settings["validM"] = "0";
if (diff > 60) {
validM = 1;
settings["validM"] = "1";
diff /= 30;
if (diff > 24) {
validM = 2;
settings["validM"] = "2";
diff /= 12;
}
}
validN = diff;
settings["validN"] = QString::number(diff);
}
}
return el;
@ -241,52 +290,53 @@ static QString old_eKeyUse2QString(int old)
return sl.join(", ");
}
void pki_temp::fromData(const unsigned char *p, int size, int version)
void pki_temp::old_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);
/* destination = */ db::stringFromData(ba);
settings["bcCritical"] = QString::number(db::boolFromData(ba));
settings["keyUseCritical"] = QString::number(db::boolFromData(ba));
settings["eKyUseCritical"] = QString::number(db::boolFromData(ba));
settings["subKey"] = QString::number(db::boolFromData(ba));
settings["authKey"] = QString::number(db::boolFromData(ba));
settings["ca"] = QString::number(db::intFromData(ba));
if (version > 5) {
pathLen = db::stringFromData(ba);
settings["basicPath"] = db::stringFromData(ba);
} else {
pathLen = QString::number(db::intFromData(ba));
if (pathLen == "0")
pathLen = "";
settings["basicPath"] = QString::number(db::intFromData(ba));
if (settings["basicPath"] == "0")
settings["basicPath"] = "";
}
validN = db::intFromData(ba);
validM = db::intFromData(ba);
keyUse = db::intFromData(ba);
settings["validN"] = QString::number(db::intFromData(ba));
settings["validM"] = QString::number(db::intFromData(ba));
settings["keyUse"] = QString::number(db::intFromData(ba));
if (version > 4) {
eKeyUse = db::stringFromData(ba);
settings["eKeyUse"] = db::stringFromData(ba);
} else {
int old = db::intFromData(ba);
eKeyUse = old_eKeyUse2QString(old);
settings["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);
settings["nsCertType"] = QString::number(db::intFromData(ba));
settings["subAltName"] = db::stringFromData(ba);
settings["issAltName"] = db::stringFromData(ba);
settings["crlDist"] = db::stringFromData(ba);
settings["nsComment"] = db::stringFromData(ba);
settings["nsBaseUrl"] = db::stringFromData(ba);
settings["nsRevocationUrl"] = db::stringFromData(ba);
settings["nsCARevocationUrl"] = db::stringFromData(ba);
settings["nsRenewalUrl"] = db::stringFromData(ba);
settings["nsCaPolicyUrl"] = db::stringFromData(ba);
settings["nsSslServerName"] = db::stringFromData(ba);
xname.d2i(ba);
authInfAcc = db::stringFromData(ba);
certPol = db::stringFromData(ba);
validMidn = db::boolFromData(ba);
settings["authInfAcc"] = db::stringFromData(ba);
/* certPol = */ db::stringFromData(ba);
settings["validMidn"] = QString::number(db::boolFromData(ba));
if (version>2)
adv_ext = db::stringFromData(ba);
settings["adv_ext"] = db::stringFromData(ba);
if (version>3)
noWellDefined = db::boolFromData(ba);
settings["noWellDefinedExpDate"] =
QString::number(db::boolFromData(ba));
if (ba.count() > 0) {
my_error(tr("Wrong Size %1").arg(ba.count()));
@ -297,45 +347,49 @@ 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);
QBuffer buf(&ba);
buf.open(QIODevice::WriteOnly | QIODevice::Append);
QDataStream out(&buf);
out.setVersion(TEMPLATE_DS_VERSION);
out << settings;
buf.close();
return ba;
}
void pki_temp::fromData(QByteArray &ba, int version)
{
int size = ba.size();
xname.d2i(ba);
QBuffer buf(&ba);
buf.open(QIODevice::ReadOnly);
QDataStream in(&buf);
in.setVersion(TEMPLATE_DS_VERSION);
in >> settings;
buf.close();
fprintf(stderr, "Settings: %d, ba-size:%d size:%d\n",
settings.size(), ba.size(), size);
(void)version;
//if (version < 11) ....
}
void pki_temp::fromData(const unsigned char *p, int size, int version)
{
if (version < 10) {
old_fromData(p, size, version);
} else {
QByteArray ba((const char*)p, size);
fromData(ba, version);
}
}
QByteArray pki_temp::toExportData()
{
QByteArray data, header;
data = toData();
header = db::intToData(data.count());
header += db::intToData(dataVersion);
header += db::intToData(TMPL_VERSION);
header += data;
return header;
}
@ -377,34 +431,14 @@ BIO *pki_temp::pem(BIO *b, int format)
void pki_temp::fromExportData(QByteArray data)
{
int size, version;
const int hsize = sizeof(uint32_t);
bool oldimport = false;
if (data.size() < hsize) {
if (data.size() < (int)sizeof(uint32_t))
my_error(tr("Template file content error (too small)"));
}
QByteArray header = data.mid(0, hsize);
size = db::intFromData(header);
if (size > 65535 || size <0) {
/* oldimport templates are prepended by its size in
* host endianess. Recover the size */
size = intFromData(data);
if (size > 65535 || size <0) {
my_error(tr("Template file content error (bad size)"));
}
oldimport = true;
}
if (oldimport) {
oldFromData((const unsigned char*)data.constData(),
data.size());
} else {
size = db::intFromData(data);
version = db::intFromData(data);
fromData((const unsigned char*)data.constData(),
data.size(), version);
}
size = db::intFromData(data);
version = db::intFromData(data);
fromData((const unsigned char*)data.constData(),
data.size(), version);
}
void pki_temp::try_fload(QString fname, const char *mode)
@ -471,7 +505,8 @@ void pki_temp::fromPEM_BIO(BIO *bio, QString name)
PEM_read_bio(bio, &nm, &header, &data, &len);
if (ign_openssl_error())
throw errorEx(tr("Not a PEM encoded XCA Template"), class_name);
throw errorEx(tr("Not a PEM encoded XCA Template"),
getClassName());
if (!strcmp(nm, PEM_STRING_XCA_TEMPLATE)) {
ba = QByteArray::fromRawData((char*)data, len);
@ -489,7 +524,6 @@ void pki_temp::fromPEM_BIO(BIO *bio, QString name)
pki_temp::~pki_temp()
{
}
bool pki_temp::compare(pki_base *)
@ -499,86 +533,7 @@ bool pki_temp::compare(pki_base *)
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(const 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));
}
pki_openssl_error();
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);
pki_openssl_error();
}
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()));
}
pki_openssl_error();
}

View File

@ -11,52 +11,84 @@
#include "pki_base.h"
#include "x509name.h"
#include "asn1time.h"
#include "pki_x509.h"
#include "pki_x509super.h"
#define D5 "-----"
#define PEM_STRING_XCA_TEMPLATE "XCA TEMPLATE"
#define TMPL_VERSION 10
#define CHECK_TMPL_KEY if (!tmpl_keys.contains(key)) { qDebug("Unknown template key: %s(%s)", __func__, CCHAR(key)); }
class pki_temp: public pki_x509name
{
Q_OBJECT
protected:
static QList<QString> tmpl_keys;
int dataSize();
void try_fload(QString fname, const char *mode);
bool pre_defined;
x509name xname;
QMap<QString, QString> settings;
QString adv_ext;
void fromExtList(extList *el, int nid, const char *item);
public:
static QPixmap *icon;
x509name xname;
QString subAltName, issAltName, crlDist, authInfAcc, certPol;
QString nsComment, nsBaseUrl, nsRevocationUrl,
nsCARevocationUrl, nsRenewalUrl, nsCaPolicyUrl,
nsSslServerName, destination, adv_ext, eKeyUse, pathLen;
bool bcCrit, keyUseCrit, eKeyUseCrit, subKey, authKey,
validMidn, noWellDefined;
int nsCertType, keyUse, ca;
int validN, validM;
// methods
extList fromCert(pki_x509super *cert_or_req);
const char *getClassName() const;
QString getSetting(QString key)
{
CHECK_TMPL_KEY
return settings[key];
}
int getSettingInt(QString key)
{
CHECK_TMPL_KEY
return settings[key].toInt();
}
void setSetting(QString key, QString value)
{
CHECK_TMPL_KEY
settings[key] = value;
}
void setSetting(QString key, int value)
{
CHECK_TMPL_KEY
settings[key] = QString::number(value);
}
pki_temp(const pki_temp *pk);
pki_temp(const QString d = QString());
void fload(const QString fname);
void writeDefault(const QString fname);
~pki_temp();
void fromData(const unsigned char *p, int size, int version);
void old_fromData(const unsigned char *p, int size, int version);
void fromData(const unsigned char *p, db_header_t *head );
void oldFromData(const unsigned char *p, int size);
void fromData(QByteArray &ba, int version);
void setAsPreDefined()
{
pre_defined = true;
}
QString comboText() const;
QByteArray toData();
bool compare(pki_base *ref);
void writeTemp(QString fname);
QVariant column_data(dbheader *hd);
QVariant getIcon(dbheader *hd);
virtual QString getMsg(msg_type msg);
QString getMsg(msg_type msg);
x509name getSubject() const;
void setSubject(x509name n)
{
xname = n;
}
BIO *pem(BIO *b, int format);
QByteArray toExportData();
void fromPEM_BIO(BIO *, QString);
void fromExportData(QByteArray data);
extList fromCert(pki_x509super *cert_or_req);
QSqlError insertSqlData();
QSqlError deleteSqlData();
QSqlError restoreSql(QVariant sqlId);
};
#endif

View File

@ -9,6 +9,7 @@
#include "pki_x509.h"
#include "pki_evp.h"
#include "pki_scard.h"
#include "db_base.h"
#include "func.h"
#include "base.h"
#include "exception.h"
@ -33,6 +34,11 @@ pki_x509::pki_x509(X509 *c)
pki_openssl_error();
}
const char *pki_x509::getClassName() const
{
return "pki_x509";
}
pki_x509::pki_x509(const pki_x509 *crt)
:pki_x509super(crt->desc)
{
@ -41,13 +47,11 @@ pki_x509::pki_x509(const pki_x509 *crt)
pki_openssl_error();
psigner = crt->psigner;
setRefKey(crt->getRefKey());
trust = crt->trust;
efftrust = crt->efftrust;
caSerial = crt->caSerial;
caTemplate = crt->caTemplate;
revocation = crt->revocation;
crlDays = crt->crlDays;
crlExpiry = crt->crlExpiry;
crlExpire = crt->crlExpire;
pki_openssl_error();
}
@ -73,12 +77,137 @@ QString pki_x509::getMsg(msg_type msg)
case msg_import: return tr("Successfully imported the certificate '%1'");
case msg_delete: return tr("Delete the certificate '%1'?");
case msg_create: return tr("Successfully created the certificate '%1'");
/* %1: Number of certs; %2: list of cert ames */
/* %1: Number of certs; %2: list of cert names */
case msg_delete_multi: return tr("Delete the %1 certificates: %2?");
}
return pki_base::getMsg(msg);
}
QSqlError pki_x509::insertSqlData()
{
XSqlQuery q;
a1time now;
pki_x509 *signer = findIssuer();
QSqlError e = pki_x509super::insertSqlData();
if (e.isValid())
return e;
SQL_PREPARE(q, "INSERT INTO certs (item, hash, iss_hash, serial, issuer, "
"ca, crlExpire, crlNo, cert) "
"VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?)");
q.bindValue(0, sqlItemId);
q.bindValue(1, hash());
q.bindValue(2, (uint)getIssuerName().hashNum());
q.bindValue(3, getSerial().toHex());
q.bindValue(4, signer ? signer->getSqlItemId() : QVariant());
q.bindValue(5, (int)isCA());
q.bindValue(6, now.toPlain());
q.bindValue(7, i2d().toBase64());
q.exec();
return q.lastError();
}
QSqlError pki_x509::restoreSql(QVariant sqlId)
{
XSqlQuery q;
QSqlError e;
e = pki_x509super::restoreSql(sqlId);
if (e.isValid())
return e;
SQL_PREPARE(q, "SELECT cert, issuer, crlNo, crlExpire, serial FROM certs "
"WHERE item=?");
q.bindValue(0, sqlId);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
if (!q.first())
return sqlItemNotFound(sqlId);
QByteArray ba = QByteArray::fromBase64(q.value(0).toByteArray());
d2i(ba);
signerSqlId = q.value(1);
crlNumber.set(q.value(2).toUInt());
crlExpire.fromPlain(q.value(3).toString());
revList = x509revList::fromSql(sqlId);
QVariant serial = q.value(4);
SQL_PREPARE(q, "SELECT serial, date, invaldate, crlNo, reasonBit "
"FROM revocations WHERE caId=? AND serial=?");
q.bindValue(0, signerSqlId);
q.bindValue(1, serial);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
if (q.first())
revocation = x509rev(q.record());
return q.lastError();
}
QSqlError pki_x509::deleteSqlData()
{
XSqlQuery q;
QSqlError e = pki_x509super::deleteSqlData();
if (e.isValid())
return e;
SQL_PREPARE(q, "DELETE FROM certs WHERE item=?");
q.bindValue(0, sqlItemId);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
SQL_PREPARE(q, "UPDATE crls SET issuer=NULL WHERE issuer=?");
q.bindValue(0, sqlItemId);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
SQL_PREPARE(q, "UPDATE certs SET issuer=NULL WHERE issuer=?");
q.bindValue(0, sqlItemId);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
SQL_PREPARE(q, "DELETE FROM revocations WHERE caId=?");
q.bindValue(0, sqlItemId);
q.exec();
return q.lastError();
}
pki_x509 *pki_x509::findIssuer()
{
XSqlQuery q;
pki_x509 *issuer;
unsigned hash;
if ((issuer = getSigner()) != NULL)
return issuer;
// first check for self-signed
if (verify(this))
return this;
hash = getIssuerName().hashNum();
/* Select X509 CA certificates with subject-hash == hash */
SQL_PREPARE(q, "SELECT x509super.item from x509super "
"JOIN certs ON certs.item = x509super.item "
"WHERE certs.ca=1 AND x509super.subj_hash=?");
q.bindValue(0, hash);
q.exec();
while (q.next()) {
issuer = static_cast<pki_x509*>(
db_base::lookupPki(q.value(0).toULongLong()));
if (!issuer) {
qDebug("Certificate with id %d not found",
q.value(0).toInt());
}
if (verify(issuer)) {
return issuer;
}
}
return NULL;
}
void pki_x509::fromPEM_BIO(BIO *bio, QString name)
{
X509 *_cert;
@ -89,8 +218,6 @@ void pki_x509::fromPEM_BIO(BIO *bio, QString name)
autoIntName();
if (getIntName().isEmpty())
setIntName(rmslashdot(name));
trust = 1;
efftrust = 1;
}
void pki_x509::fload(const QString fname)
@ -118,8 +245,6 @@ void pki_x509::fload(const QString fname)
autoIntName();
if (getIntName().isEmpty())
setIntName(rmslashdot(fname));
trust = 1;
efftrust = 1;
}
pki_x509::~pki_x509()
@ -133,15 +258,11 @@ pki_x509::~pki_x509()
void pki_x509::init()
{
psigner = NULL;
trust = 0;
efftrust = 0;
caSerial = 1;
caTemplate = "";
caTemplate = NULL;
crlDays = 30;
crlExpiry.setUndefined();
class_name = "pki_x509";
crlExpire.setUndefined();
cert = NULL;
dataVersion = 4;
pkiType = x509;
randomSerial = false;
}
@ -287,7 +408,7 @@ void pki_x509::store_token(bool alwaysSelect)
pk11_attr_bool(CKA_TOKEN, true) <<
pk11_attr_bool(CKA_PRIVATE, false) <<
pk11_attr_data(CKA_SUBJECT, getSubject().i2d()) <<
pk11_attr_data(CKA_ISSUER, getIssuer().i2d()) <<
pk11_attr_data(CKA_ISSUER, getIssuerName().i2d()) <<
pk11_attr_data(CKA_SERIAL_NUMBER, getSerial().i2d()) <<
pk11_attr_data(CKA_LABEL, desc.toUtf8()) <<
(card ? card->getIdAttr() : p11.findUniqueID(CKO_CERTIFICATE));
@ -404,7 +525,7 @@ x509name pki_x509::getSubject() const
return x;
}
x509name pki_x509::getIssuer() const
x509name pki_x509::getIssuerName() const
{
x509name x(X509_get_issuer_name(cert));
pki_openssl_error();
@ -442,19 +563,26 @@ void pki_x509::delSigner(pki_base *s)
psigner = NULL;
}
bool pki_x509::canSign()
bool pki_x509::isCA() const
{
BASIC_CONSTRAINTS *bc;
bool ca;
int crit;
BASIC_CONSTRAINTS *bc = (BASIC_CONSTRAINTS *)
X509_get_ext_d2i(cert, NID_basic_constraints, &crit, NULL);
pki_openssl_error();
ca = bc && bc->ca;
if (bc)
BASIC_CONSTRAINTS_free(bc);
return ca;
}
bool pki_x509::canSign() const
{
if (!privkey || privkey->isPubKey())
return false;
if (privkey->isToken() && !pkcs11::loaded())
return false;
bc = (BASIC_CONSTRAINTS *)X509_get_ext_d2i(cert, NID_basic_constraints, &crit, NULL);
pki_openssl_error();
if (!bc || !bc->ca)
return false;
return true;
return isCA();
}
bool pki_x509::hasExtension(int nid)
@ -488,7 +616,7 @@ void pki_x509::fromData(const unsigned char *p, db_header_t *head)
d2i(ba);
pki_openssl_error();
trust = db::intFromData(ba);
/* trust = */ db::intFromData(ba);
if (version < 4) {
a1time revoked;
isRevoked = db::boolFromData(ba);
@ -501,9 +629,9 @@ void pki_x509::fromData(const unsigned char *p, db_header_t *head)
}
caSerial.setHex(db::stringFromData(ba));
pki_openssl_error();
caTemplate = db::stringFromData(ba);
QString __caTemplate = db::stringFromData(ba);
crlDays = db::intFromData(ba);
crlExpiry.d2i(ba);
crlExpire.d2i(ba);
pki_openssl_error();
if (version > 1)
randomSerial = db::boolFromData(ba);
@ -536,29 +664,6 @@ void pki_x509::fromData(const unsigned char *p, db_header_t *head)
pki_openssl_error();
}
QByteArray pki_x509::toData()
{
QByteArray ba;
ba += i2d(); // cert
ba += db::intToData(trust);
// version 4: don't store isrevoked, revoked
// the serial if this is a CA
ba += db::stringToData(caSerial.toHex());
// the name of the template to use for signing
ba += db::stringToData(caTemplate);
// version 3
ba += db::intToData(crlDays); // the CRL period
ba += crlExpiry.i2d(); // last CRL date
ba += db::boolToData(randomSerial);
ba += db::stringToData(crlNumber.toHex());
// version 4: don't store own revocation but client revocations
ba += revList.toBA();
pki_openssl_error();
return ba;
}
void pki_x509::writeDefault(const QString fname)
{
writeCert(fname + QDir::separator() + getIntName() + ".crt",
@ -662,6 +767,9 @@ bool pki_x509::verify(pki_x509 *signer)
return true;
if ((psigner != NULL) || (signer == NULL))
return false;
if (signer == this && signerSqlId == sqlItemId)
return true;
if (verify_only(signer)) {
int idx;
x509rev r;
@ -807,32 +915,6 @@ pki_x509 *pki_x509::getSigner()
return (pki_x509 *)psigner;
}
int pki_x509::getTrust()
{
if (trust > 2) trust = 2;
if (trust < 0) trust = 0;
return trust;
}
void pki_x509::setTrust(int t)
{
if (t>=0 && t<=2)
trust = t;
}
int pki_x509::getEffTrust()
{
if (efftrust > 2) efftrust = 2;
if (efftrust < 0) efftrust = 0;
return efftrust;
}
void pki_x509::setEffTrust(int t)
{
if (t>= 0 && t<= 2)
efftrust = t;
}
bool pki_x509::isRevoked()
{
return revocation.isValid();
@ -841,44 +923,6 @@ bool pki_x509::isRevoked()
void pki_x509::setRevoked(const x509rev &revok)
{
revocation = revok;
if (revok.isValid()) {
setEffTrust(0);
setTrust(0);
}
}
int pki_x509::calcEffTrust()
{
int mytrust = trust;
if (mytrust != 1) {
efftrust = mytrust;
return mytrust;
}
if (isRevoked()) {
efftrust = 0;
return 0;
}
if (getSigner() == this && trust == 1) { // inherit trust, but self signed
trust=0;
efftrust=0;
return 0;
}
//we must look at the parent certs
pki_x509 *signer = getSigner();
while (mytrust == 1 && signer && signer != this) {
mytrust = signer->getTrust();
signer = signer->getSigner();
}
if (mytrust == 1) mytrust = 0;
efftrust = mytrust;
return mytrust;
}
void pki_x509::setCrlExpiry(const a1time &time)
{
crlExpiry = time;
pki_openssl_error();
}
bool pki_x509::caAndPathLen(bool *ca, a1int *pathlen, bool *hasLen)
@ -900,9 +944,6 @@ bool pki_x509::caAndPathLen(bool *ca, a1int *pathlen, bool *hasLen)
QVariant pki_x509::column_data(dbheader *hd)
{
QString truststatus[] =
{ tr("Not trusted"), tr("Trust inherited"), tr("Always Trusted") };
switch (hd->id) {
case HD_cert_serial:
return QVariant(getSerial().toHex());
@ -910,14 +951,12 @@ QVariant pki_x509::column_data(dbheader *hd)
return QVariant(getNotBefore().toSortable());
case HD_cert_notAfter:
return QVariant(getNotAfter().toSortable());
case HD_cert_trust:
return QVariant(truststatus[getTrust()]);
case HD_cert_revocation:
return QVariant(isRevoked() ?
revocation.getDate().toSortable() : "");
case HD_cert_crl_expire:
if (canSign() && !crlExpiry.isUndefined())
return QVariant(crlExpiry.toSortable());
if (canSign() && !crlExpire.isUndefined())
return QVariant(crlExpire.toSortable());
else
return QVariant();
case HD_cert_md5fp:
@ -962,7 +1001,7 @@ QVariant pki_x509::getIcon(dbheader *hd)
if (k && k->isPrivKey()) {
pixnum += 1;
}
if (calcEffTrust() == 0){
if (isRevoked()){
pixnum += 2;
}
break;
@ -976,7 +1015,7 @@ bool pki_x509::visible()
{
if (pki_x509super::visible())
return true;
if (getIssuer().search(limitPattern))
if (getIssuerName().search(limitPattern))
return true;
if (fingerprint(EVP_md5()).contains(limitPattern))
return true;
@ -1026,8 +1065,8 @@ QVariant pki_x509::bg_color(dbheader *hd)
case HD_cert_crl_expire:
if (canSign()) {
QDateTime crlwarn, crlex;
crlex = crlExpiry;
if (!crlExpiry.isUndefined()) {
crlex = crlExpire;
if (!crlExpire.isUndefined()) {
crlwarn = crlex.addSecs(-2 *60*60*24);
if (crlex < now)
return QVariant(BG_RED);
@ -1038,72 +1077,3 @@ QVariant pki_x509::bg_color(dbheader *hd)
}
return QVariant();
}
void pki_x509::oldFromData(unsigned char *p, int size)
{
int version, sRev, sLastCrl;
QByteArray ba((char*)p, size);
X509 *cert_sik = cert;
cert = NULL;
version = intFromData(ba);
if (version >=1 && version <= 5) {
intFromData(ba); /* sCert */
d2i(ba);
trust = intFromData(ba);
sRev = intFromData(ba);
if (sRev) {
a1time r;
r.d2i(ba);
if (version != 3) {
revocation.setSerial(getSerial());
revocation.setDate(r);
}
} else {
revocation = x509rev();
}
if (version == 1) {
caTemplate="";
caSerial=1;
crlExpiry.setUndefined();
crlDays=30;
}
if (version >= 2 ) {
if (version >= 5)
caSerial.setHex(db::stringFromData(ba));
else {
int i = intFromData(ba);
if (i>=0)
caSerial = i;
else {
caSerial = getSerial();
++caSerial;
}
}
caTemplate = db::stringFromData(ba);
}
if (version >= 3 ) {
crlDays = intFromData(ba);
sLastCrl = intFromData(ba);
if (sLastCrl) {
crlExpiry.d2i(ba);
}
}
// version 4 saves a NULL as revoked
// version 3 did save a recent date :-((
}
else { // old version
d2i(ba);
trust = 1;
efftrust = 1;
}
if (cert)
X509_free(cert_sik);
else
cert = cert_sik;
if (ba.count() > 0) {
my_error(tr("Wrong Size %1").arg(ba.count()));
}
}

View File

@ -12,6 +12,7 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/pem.h>
#include "pki_temp.h"
#include "pki_key.h"
#include "pki_x509req.h"
#include "pki_x509super.h"
@ -26,14 +27,13 @@ class pki_x509 : public pki_x509super
Q_OBJECT
private:
pki_x509 *psigner;
a1time crlExpiry;
QVariant signerSqlId;
a1time crlExpire;
bool randomSerial;
int trust;
int efftrust;
a1int caSerial;
a1int crlNumber;
int crlDays;
QString caTemplate;
pki_temp *caTemplate;
X509 *cert;
void init();
x509rev revocation;
@ -51,6 +51,11 @@ class pki_x509 : public pki_x509super
pki_x509(const QString name = "");
~pki_x509();
const char *getClassName() const;
void setSigner(pki_x509 *signer)
{
psigner = signer;
}
void fload(const QString fname);
void load_token(pkcs11 &p11, CK_OBJECT_HANDLE object);
void store_token(bool alwaysSelect);
@ -64,15 +69,14 @@ class pki_x509 : public pki_x509super
a1time getNotBefore() const;
a1time getNotAfter() const;
x509name getSubject() const;
x509name getIssuer() const;
x509name getIssuerName() const;
void setSubject(const x509name &n);
void setIssuer(const x509name &n);
bool caAndPathLen(bool *ca, a1int *pathlen, bool *hasLen);
QByteArray toData();
void fromData(const unsigned char *p, db_header_t *head);
void oldFromData(unsigned char *p, int size);
bool canSign();
bool isCA() const;
bool canSign() const;
void writeCert(const QString fname, bool PEM, bool append = false);
void writeIndexEntry(FILE *fp);
void writeIndexEntry(const QString fname, bool append = false);
@ -87,20 +91,16 @@ class pki_x509 : public pki_x509super
bool checkDate();
bool addV3ext(const x509v3ext &e, bool skip_existing = false);
void sign(pki_key *signkey, const EVP_MD *digest);
pki_x509 *findIssuer();
X509 *getCert()
{
return cert;
}
int getTrust();
void setTrust(int t);
int getEffTrust();
void setEffTrust(int t);
void setRevoked(bool rev, a1time inval = a1time(),
QString reason = QString());
void setRevoked(const x509rev &revok);
bool isRevoked();
pki_x509 *getBySerial(const a1int &a) const;
int calcEffTrust();
a1int getIncCaSerial();
a1int getCaSerial()
{
@ -119,12 +119,12 @@ class pki_x509 : public pki_x509super
if (n > crlNumber)
crlNumber = n;
}
void setTemplate(QString s)
void setTemplate(pki_temp *t)
{
if (s.length() > 0)
caTemplate = s;
if (t)
caTemplate = t;
}
QString getTemplate()
pki_temp *getTemplate()
{
return caTemplate;
}
@ -150,7 +150,6 @@ class pki_x509 : public pki_x509super
return revocation;
}
pk11_attlist objectAttributes();
void setCrlExpiry(const a1time &time);
bool hasExtension(int nid);
bool cmpIssuerAndSerial(pki_x509 *refcert);
bool visible();
@ -171,6 +170,13 @@ class pki_x509 : public pki_x509super
}
void setRevocations(const x509revList &rl);
bool compareNameAndKey(pki_x509 *other);
void setCrlExpire(a1time a)
{
crlExpire = a;
}
QSqlError insertSqlData();
QSqlError deleteSqlData();
QSqlError restoreSql(QVariant sqlId);
};
#endif

View File

@ -24,20 +24,72 @@ pki_x509req::pki_x509req(const QString name)
: pki_x509super(name)
{
privkey = NULL;
class_name = "pki_x509req";
request = X509_REQ_new();
pki_openssl_error();
dataVersion=1;
pkiType=x509_req;
done = false;
}
const char *pki_x509req::getClassName() const
{
return "pki_x509req";
}
pki_x509req::~pki_x509req()
{
if (request)
X509_REQ_free(request);
}
QSqlError pki_x509req::insertSqlData()
{
XSqlQuery q;
QSqlError e = pki_x509super::insertSqlData();
if (e.isValid())
return e;
SQL_PREPARE(q, "INSERT INTO requests (item, hash, signed, request) "
"VALUES (?, ?, 0, ?)");
q.bindValue(0, sqlItemId);
q.bindValue(1, hash());
q.bindValue(2, i2d().toBase64());
q.exec();
return q.lastError();
}
QSqlError pki_x509req::restoreSql(QVariant sqlId)
{
XSqlQuery q;
QSqlError e;
e = pki_x509super::restoreSql(sqlId);
if (e.isValid())
return e;
SQL_PREPARE(q, "SELECT request, signed FROM requests WHERE item=?");
q.bindValue(0, sqlId);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
if (!q.first())
return sqlItemNotFound(sqlId);
QByteArray ba = QByteArray::fromBase64(q.value(0).toByteArray());
d2i(ba);
done = q.value(1).toBool();
return e;
}
QSqlError pki_x509req::deleteSqlData()
{
XSqlQuery q;
QSqlError e = pki_x509super::deleteSqlData();
if (e.isValid())
return e;
SQL_PREPARE(q, "DELETE FROM requests WHERE item=?");
q.bindValue(0, sqlItemId);
q.exec();
return q.lastError();
}
void pki_x509req::createReq(pki_key *key, const x509name &dn, const EVP_MD *md, extList el)
{
int bad_nids[] = { NID_subject_key_identifier, NID_authority_key_identifier,
@ -163,7 +215,15 @@ void pki_x509req::fromData(const unsigned char *p, db_header_t *head )
size = head->len - sizeof(db_header_t);
oldFromData((unsigned char *)p, size);
QByteArray ba((const char *)p, size);
privkey = NULL;
d2i(ba);
pki_openssl_error();
if (ba.count() > 0) {
my_error(tr("Wrong Size %1").arg(ba.count()));
}
}
void pki_x509req::addAttribute(int nid, QString content)
@ -194,13 +254,6 @@ void pki_x509req::setSubject(const x509name &n)
X509_REQ_set_subject_name(request, n.get());
}
QByteArray pki_x509req::toData()
{
QByteArray ba = i2d();
pki_openssl_error();
return ba;
}
void pki_x509req::writeDefault(const QString fname)
{
writeReq(fname + QDir::separator() + getIntName() + ".csr", true);
@ -325,11 +378,3 @@ bool pki_x509req::visible()
return true;
return false;
}
void pki_x509req::oldFromData(unsigned char *p, int size)
{
QByteArray ba((const char *)p, size);
privkey = NULL;
d2i(ba);
}

View File

@ -30,14 +30,13 @@ class pki_x509req : public pki_x509super
public:
extList getV3ext();
static QPixmap *icon[3];
const char *getClassName() const;
pki_x509req(QString name = "");
void fromPEM_BIO(BIO *bio, QString name);
void fload(const QString fname);
void writeDefault(const QString fname);
~pki_x509req();
void fromData(const unsigned char *p, db_header_t *head);
void oldFromData(unsigned char *p, int size);
QByteArray toData();
x509name getSubject() const;
void writeReq(const QString fname, bool pem);
X509_REQ *getReq()
@ -49,8 +48,8 @@ class pki_x509req : public pki_x509super
int verify();
pki_key *getPubKey() const;
void createReq(pki_key *key, const x509name &dn, const EVP_MD *md,
extList el);
void createReq(pki_key *key, const x509name &dn,
const EVP_MD *md, extList el);
void setSubject(const x509name &n);
/* SPKAC special functions */
QVariant column_data(dbheader *hd);
@ -68,6 +67,9 @@ class pki_x509req : public pki_x509super
QByteArray i2d();
BIO *pem(BIO *, int);
bool visible();
QSqlError insertSqlData();
QSqlError deleteSqlData();
QSqlError restoreSql(QVariant sqlId);
};
#endif

View File

@ -8,6 +8,7 @@
#include "func.h"
#include "oid.h"
#include "pki_x509super.h"
#include "db_base.h"
pki_x509super::pki_x509super(const QString name)
: pki_x509name(name)
@ -17,9 +18,70 @@ pki_x509super::pki_x509super(const QString name)
pki_x509super::~pki_x509super()
{
if (privkey)
privkey->decUcount();
}
QSqlError pki_x509super::insertSqlData()
{
XSqlQuery q;
unsigned hash = pubHash();
SQL_PREPARE(q, "SELECT item FROM public_keys WHERE hash=?");
q.bindValue(0, hash);
q.exec();
if (q.lastError().isValid())
return q.lastError();
while (q.next()) {
pki_key *x = static_cast<pki_key*>(
db_base::lookupPki(q.value(0).toULongLong()));
if (!x) {
qDebug("Public key with id %d not found",
q.value(0).toInt());
continue;
}
if (compareRefKey(x)) {
setRefKey(x);
break;
}
}
SQL_PREPARE(q, "INSERT INTO x509super (item, subj_hash, key, key_hash) "
"VALUES (?, ?, ?, ?)");
q.bindValue(0, sqlItemId);
q.bindValue(1, (uint)getSubject().hashNum());
q.bindValue(2, privkey ? privkey->getSqlItemId() : QVariant());
q.bindValue(3, hash);
q.exec();
return q.lastError();
}
QSqlError pki_x509super::restoreSql(QVariant sqlId)
{
XSqlQuery q;
QSqlError e;
e = pki_base::restoreSql(sqlId);
if (e.isValid())
return e;
SQL_PREPARE(q, "SELECT key FROM x509super WHERE item=?");
q.bindValue(0, sqlId);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
if (!q.first())
return sqlItemNotFound(sqlId);
keySqlId = q.value(0);
privkey = NULL;
return e;
}
QSqlError pki_x509super::deleteSqlData()
{
XSqlQuery q;
SQL_PREPARE(q, "DELETE FROM x509super WHERE item=?");
q.bindValue(0, sqlItemId);
q.exec();
return q.lastError();
}
pki_key *pki_x509super::getRefKey() const
@ -27,27 +89,36 @@ pki_key *pki_x509super::getRefKey() const
return privkey;
}
void pki_x509super::setRefKey(pki_key *ref)
unsigned pki_x509super::pubHash()
{
if (ref == NULL || privkey != NULL )
return;
pki_key *mk = getPubKey();
if (mk == NULL)
return;
if (ref->compare(mk)) {
// this is our key
privkey = ref;
ref->incUcount();
unsigned hash;
if (privkey) {
hash = privkey->hash();
} else {
pki_key *x = getPubKey();
hash = x->hash();
delete x;
}
delete mk;
return hash;
}
void pki_x509super::delRefKey(pki_key *ref)
bool pki_x509super::compareRefKey(pki_key *ref) const
{
if (ref != privkey || ref == NULL)
return;
ref->decUcount();
privkey = NULL;
bool x;
if (ref == NULL)
return false;
pki_key *mk = getPubKey();
if (mk == NULL)
return false;
x = ref->compare(mk);
delete mk;
return x;
}
void pki_x509super::setRefKey(pki_key *ref)
{
privkey = ref;
}
QString pki_x509super::getSigAlg()

View File

@ -31,6 +31,7 @@ class pki_x509super : public pki_x509name
{
Q_OBJECT
protected:
QVariant keySqlId;
pki_key *privkey;
virtual int sigAlg() {
return NID_undef;
@ -42,6 +43,7 @@ class pki_x509super : public pki_x509name
{
return -1;
};
unsigned pubHash();
virtual pki_key *getPubKey() const
{
return NULL;
@ -52,12 +54,20 @@ class pki_x509super : public pki_x509name
};
virtual QString getSigAlg();
virtual const EVP_MD *getDigest();
QVariant getKeySqlId()
{
return keySqlId;
}
pki_key *getRefKey() const;
bool compareRefKey(pki_key* ref) const;
void setRefKey(pki_key *ref);
void delRefKey(pki_key *ref);
QVariant column_data(dbheader *hd);
void opensslConf(QString fname);
bool visible();
QSqlError insertSqlData();
QSqlError deleteSqlData();
QSqlError restoreSql(QVariant sqlId);
};
#endif

View File

@ -142,6 +142,12 @@ QString x509name::hash() const
return QString("%1").arg(X509_NAME_hash(xn), 8, 16, QChar('0'));
}
/* 32 bit signed integer */
unsigned long x509name::hashNum() const
{
return X509_NAME_hash(xn) & 0x7fffffffL;
}
QStringList x509name::entryList(int i) const
{
QStringList sl;
@ -195,6 +201,11 @@ bool x509name::operator == (const x509name &x) const
return (X509_NAME_cmp(xn, x.xn) == 0);
}
bool x509name::operator != (const x509name &x) const
{
return (X509_NAME_cmp(xn, x.xn) != 0);
}
x509name &x509name::operator = (const x509name &x)
{
set(x.xn);

View File

@ -36,6 +36,7 @@ class x509name
int entryCount() const;
x509name &operator = (const x509name &x);
bool operator == (const x509name &x) const;
bool operator != (const x509name &x) const;
static int getNidByName(const QString &nid_name);
void addEntryByNid(int nid, const QString entry);
QString checkLength() const;
@ -45,6 +46,7 @@ class x509name
QString getMostPopular() const;
QString taggedValues() const;
QString hash() const;
unsigned long hashNum() const;
bool search(const QRegExp &pattern);
};

View File

@ -7,11 +7,13 @@
#include "x509rev.h"
#include "db.h"
#include "base.h"
#include "pki_base.h"
#include "func.h"
#include "exception.h"
#include <openssl/x509v3.h>
#include <QStringList>
#include <QVariant>
#include <QSqlQuery>
#include "openssl_compat.h"
@ -56,6 +58,16 @@ QString x509rev::getReason() const
return crl_reasons[reason_idx].lname;
}
static int reasonBit2Idx(int bit)
{
for (int i=0; crl_reasons[i].lname; i++) {
if (bit == crl_reasons[i].bitnum) {
return i;
}
}
return 0;
}
void x509rev::fromREVOKED(const X509_REVOKED *rev)
{
ASN1_ENUMERATED *reason;
@ -74,11 +86,7 @@ void x509rev::fromREVOKED(const X509_REVOKED *rev)
if (reason) {
r = ASN1_ENUMERATED_get(reason);
openssl_error();
for (int i=0; crl_reasons[i].lname; i++) {
if (r == crl_reasons[i].bitnum) {
reason_idx = i;
}
}
reason_idx = reasonBit2Idx(r);
ASN1_ENUMERATED_free(reason);
}
ivalDate.setUndefined();
@ -157,6 +165,25 @@ void x509rev::dump() const
crl_reasons[reason_idx].lname);
}
x509rev::x509rev(QSqlRecord rec)
{
serial.setHex(rec.value(0).toString());
date.fromPlain(rec.value(1).toString());
ivalDate.fromPlain(rec.value(2).toString());
crlNo = rec.value(3).toInt();
reason_idx = reasonBit2Idx(rec.value(4).toInt());
}
void x509rev::executeQuery(XSqlQuery &q)
{
// 0 is the caId
q.bindValue(1, serial.toHex());
q.bindValue(2, date.toPlain());
q.bindValue(3, ivalDate.toPlain());
q.bindValue(4, crl_reasons[reason_idx].bitnum);
q.exec();
}
void x509revList::fromBA(QByteArray &ba)
{
int i, num = db::intFromData(ba);
@ -204,3 +231,42 @@ bool x509revList::identical(const x509revList &other) const
}
return true;
}
x509revList x509revList::fromSql(QVariant caId)
{
XSqlQuery q;
x509revList list;
SQL_PREPARE(q, "SELECT serial, date, invaldate, crlNo, reasonBit "
"FROM revocations WHERE caId=?");
q.bindValue(0, caId);
q.exec();
if (q.lastError().isValid())
return list;
while (q.next()) {
x509rev r(q.record());
list.append(r);
}
return list;
}
QSqlError x509revList::sqlUpdate(QVariant caId)
{
// Transaction from outside !!
XSqlQuery q;
QSqlError e;
SQL_PREPARE(q, "DELETE FROM revocations WHERE caId=?");
q.bindValue(0, caId);
q.exec();
e = q.lastError();
if (e.isValid())
return e;
SQL_PREPARE(q, "INSERT INTO revocations "
"(caId, serial, date, invaldate, reasonBit) "
"VALUES (?,?,?,?,?)");
q.bindValue(0, caId);
for (int i=0; i<size(); i++) {
x509rev r = at(i);
r.executeQuery(q);
}
}

View File

@ -9,16 +9,20 @@
#define __X509REV_H
#include <QStringList>
#include <QSqlRecord>
#include <QSqlQuery>
#include <QSqlError>
#include <openssl/x509.h>
#include "asn1time.h"
#include "asn1int.h"
#include "pki_base.h"
class x509rev
{
private:
a1int serial;
a1time date, ivalDate;
int reason_idx;
int reason_idx, crlNo;
void set(const x509rev &x);
X509_REVOKED *toREVOKED(bool withReason=true) const;
@ -45,7 +49,8 @@ class x509rev
{
set(n);
}
x509rev(QSqlRecord rec);
void executeQuery(XSqlQuery &q);
bool isValid() const
{
return serial != a1int(0L) && !date.isUndefined();
@ -92,6 +97,10 @@ class x509rev
{
return ivalDate;
}
int getCrlNo() const
{
return crlNo;
}
X509_REVOKED *get(bool withReason=true) const
{
return toREVOKED(withReason);
@ -101,6 +110,7 @@ class x509rev
class x509revList : public QList<x509rev>
{
public:
static x509revList fromSql(QVariant caId);
bool merged;
QByteArray toBA();
void fromBA(QByteArray &ba);
@ -121,5 +131,6 @@ class x509revList : public QList<x509rev>
append(r);
}
}
QSqlError sqlUpdate(QVariant caId);
};
#endif

View File

@ -1,157 +0,0 @@
<ui version="4.0" >
<class>About</class>
<widget class="QDialog" name="About" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>561</width>
<height>392</height>
</rect>
</property>
<property name="windowTitle" >
<string/>
</property>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>8</number>
</property>
<property name="topMargin" >
<number>8</number>
</property>
<property name="rightMargin" >
<number>8</number>
</property>
<property name="bottomMargin" >
<number>8</number>
</property>
<item>
<layout class="QHBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<widget class="QLabel" name="image1" >
<property name="minimumSize" >
<size>
<width>95</width>
<height>40</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>95</width>
<height>40</height>
</size>
</property>
<property name="text" >
<string/>
</property>
<property name="scaledContents" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType" >
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="button" >
<property name="text" >
<string>Done</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType" >
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="image" >
<property name="minimumSize" >
<size>
<width>95</width>
<height>40</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>95</width>
<height>40</height>
</size>
</property>
<property name="text" >
<string/>
</property>
<property name="scaledContents" >
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTextBrowser" name="textbox" />
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>button</sender>
<signal>clicked()</signal>
<receiver>About</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<x>270</x>
<y>28</y>
</hint>
<hint type="destinationlabel" >
<x>213</x>
<y>18</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>487</width>
<height>320</height>
<height>501</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
@ -81,6 +81,49 @@
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Subject manager</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="kvView" name="subjectManager"/>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QPushButton" name="extDNadd">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="extDNdel">
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="certName">
<layout class="QVBoxLayout" name="verticalLayout">
@ -89,13 +132,6 @@
<item row="0" column="1">
<widget class="QLineEdit" name="serial"/>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="randomSerial">
<property name="text">
<string>Use random Serial numbers</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
@ -123,6 +159,20 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="randomSerial">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Use random Serial numbers</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@ -150,6 +200,17 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>kvView</class>
<extends>QTableView</extends>
<header>widgets/kvView.h</header>
<slots>
<slot>addKvRow()</slot>
<slot>deleteCurrentRow()</slot>
</slots>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
@ -159,12 +220,12 @@
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>39</x>
<y>141</y>
<x>240</x>
<y>345</y>
</hint>
<hint type="destinationlabel">
<x>271</x>
<y>111</y>
<y>306</y>
</hint>
</hints>
</connection>
@ -176,7 +237,7 @@
<hints>
<hint type="sourcelabel">
<x>341</x>
<y>291</y>
<y>472</y>
</hint>
<hint type="destinationlabel">
<x>292</x>
@ -192,7 +253,7 @@
<hints>
<hint type="sourcelabel">
<x>445</x>
<y>292</y>
<y>473</y>
</hint>
<hint type="destinationlabel">
<x>445</x>
@ -200,5 +261,37 @@
</hint>
</hints>
</connection>
<connection>
<sender>extDNadd</sender>
<signal>clicked()</signal>
<receiver>subjectManager</receiver>
<slot>addKvRow()</slot>
<hints>
<hint type="sourcelabel">
<x>407</x>
<y>113</y>
</hint>
<hint type="destinationlabel">
<x>363</x>
<y>106</y>
</hint>
</hints>
</connection>
<connection>
<sender>extDNdel</sender>
<signal>clicked()</signal>
<receiver>subjectManager</receiver>
<slot>deleteCurrentRow()</slot>
<hints>
<hint type="sourcelabel">
<x>399</x>
<y>138</y>
</hint>
<hint type="destinationlabel">
<x>362</x>
<y>139</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -6,19 +6,13 @@
<rect>
<x>0</x>
<y>0</y>
<width>450</width>
<height>450</height>
<width>535</width>
<height>498</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="headerLabel">
<property name="font">
@ -81,7 +75,7 @@
</property>
<widget class="QWidget" name="unnamed">
<attribute name="title">
<string>S&amp;tatus</string>
<string>Status</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
@ -105,62 +99,7 @@
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout">
<property name="margin">
<number>9</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="3" column="1">
<widget class="CopyLabel" name="sigAlgo"/>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="ClickLabel" name="privKey"/>
</item>
<item>
<widget class="QLabel" name="serialLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Serial</string>
</property>
</widget>
</item>
<item>
<widget class="CopyLabel" name="serialNr">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>The serial number of the certificate</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="descr">
<property name="toolTip">
<string>The internal name of the certificate in the database</string>
</property>
</widget>
</item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="TextLabel2">
<property name="text">
@ -168,26 +107,10 @@
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="ClickLabel" name="signature"/>
</item>
<item>
<widget class="ClickLabel" name="trustState"/>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QLabel" name="TextLabel1_2_2">
<property name="text">
<string>Signature algorithm</string>
<item row="0" column="1">
<widget class="QLineEdit" name="descr">
<property name="toolTip">
<string>The internal name of the certificate in the database</string>
</property>
</widget>
</item>
@ -198,6 +121,24 @@
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="ClickLabel" name="signature">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="CopyLabel" name="sigAlgo">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="TextLabel6">
<property name="text">
@ -205,6 +146,42 @@
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="ClickLabel" name="privKey">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="serialLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Serial</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="CopyLabel" name="serialNr">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>The serial number of the certificate</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -265,9 +242,6 @@
<string>Validity</string>
</property>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>8</number>
</property>
@ -315,12 +289,9 @@
</widget>
<widget class="QWidget" name="unnamed_1">
<attribute name="title">
<string>&amp;Subject</string>
<string>Subject</string>
</attribute>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>11</number>
</property>
@ -331,12 +302,9 @@
</widget>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>&amp;Issuer</string>
<string>Issuer</string>
</attribute>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>11</number>
</property>
@ -357,7 +325,7 @@
</widget>
<widget class="QWidget" name="unnamed_2">
<attribute name="title">
<string>&amp;Extensions</string>
<string>Extensions</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
@ -376,12 +344,33 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="commentTab">
<attribute name="title">
<string>Comment</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QTextEdit" name="comment">
<property name="html">
<string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="acceptRichText">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
@ -414,8 +403,8 @@
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>369</x>
<y>422</y>
<x>378</x>
<y>488</y>
</hint>
<hint type="destinationlabel">
<x>235</x>
@ -423,5 +412,21 @@
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>CertDetail</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>485</x>
<y>475</y>
</hint>
<hint type="destinationlabel">
<x>530</x>
<y>428</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -281,12 +281,33 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Comment</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTextEdit" name="comment">
<property name="html">
<string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="acceptRichText">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>

View File

@ -4,11 +4,11 @@ TOPDIR=..
BUILD=..
endif
UI_H = ui_About.h ui_CaProperties.h ui_CertDetail.h ui_CertExtend.h \
UI_H = ui_CaProperties.h ui_CertDetail.h ui_CertExtend.h \
ui_CrlDetail.h ui_ExportDialog.h ui_Help.h \
ui_ImportMulti.h ui_KeyDetail.h ui_MainWindow.h ui_NewCrl.h \
ui_NewKey.h ui_NewX509.h ui_Options.h ui_PwDialog.h ui_Revoke.h \
ui_SelectToken.h ui_TrustState.h ui_v3ext.h ui_SearchPkcs11.h \
ui_SelectToken.h ui_XcaDialog.h ui_v3ext.h ui_SearchPkcs11.h \
ui_RevocationList.h ui_OidResolver.h
include $(TOPDIR)/Rules.mak

View File

@ -1,257 +1,218 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NewCrl</class>
<widget class="QDialog" name="NewCrl">
<widget class="QWidget" name="NewCrl">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>451</width>
<height>478</height>
<width>354</width>
<height>369</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="TextLabel1">
<property name="font">
<font>
<family>Arial</family>
<pointsize>14</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text">
<string>Create CRL</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="image">
<property name="minimumSize">
<size>
<width>95</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>95</width>
<height>40</height>
</size>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="dateBox">
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMinAndMaxSize</enum>
</property>
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Last update</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Validity" name="lastUpdate">
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Next update</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Validity" name="nextUpdate">
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="widget" native="true">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Last update</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Validity" name="lastUpdate">
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Next update</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Validity" name="nextUpdate">
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QLineEdit" name="validNumber"/>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="validRange">
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QLineEdit" name="validNumber"/>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="validRange">
<item>
<property name="text">
<string>Days</string>
</property>
</item>
<item>
<property name="text">
<string>Months</string>
</property>
</item>
<item>
<property name="text">
<string>Years</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="midnightCB">
<property name="text">
<string>Days</string>
<string>Midnight</string>
</property>
</item>
<item>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Months</string>
<string>Local time</string>
</property>
</item>
<item>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="applyTime">
<property name="text">
<string>Years</string>
<string>Apply</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="midnightCB">
<property name="text">
<string>Midnight</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Local time</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="applyTime">
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Options</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="3" column="1">
<widget class="QLineEdit" name="crlNumber"/>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="setCrlNumber">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>CRL number</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="subAltName">
<property name="text">
<string>Subject alternative name</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="revocationReasons">
<property name="text">
<string>Revocation reasons</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="authKeyId">
<property name="text">
<string>Authority key identifier</string>
<string>Hash algorithm</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="hashBox" name="hashAlgo"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Hash algorithm</string>
<string>Subject alternative name</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="subAltName">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Authority key identifier</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="authKeyId">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>CRL number</string>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QCheckBox" name="setCrlNumber">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="crlNumber"/>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Revocation reasons</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="revocationReasons">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>21</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
@ -271,123 +232,8 @@
<header>widgets/hashBox.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>subAltName</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>midnightCB</sender>
<signal>stateChanged(int)</signal>
<receiver>nextUpdate</receiver>
<slot>hideTimeCheck(int)</slot>
<hints>
<hint type="sourcelabel">
<x>104</x>
<y>243</y>
</hint>
<hint type="destinationlabel">
<x>233</x>
<y>149</y>
</hint>
</hints>
</connection>
<connection>
<sender>midnightCB</sender>
<signal>stateChanged(int)</signal>
<receiver>lastUpdate</receiver>
<slot>hideTimeCheck(int)</slot>
<hints>
<hint type="sourcelabel">
<x>124</x>
<y>243</y>
</hint>
<hint type="destinationlabel">
<x>233</x>
<y>118</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>NewCrl</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>538</y>
</hint>
<hint type="destinationlabel">
<x>70</x>
<y>459</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>NewCrl</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>410</x>
<y>538</y>
</hint>
<hint type="destinationlabel">
<x>179</x>
<y>454</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkBox</sender>
<signal>stateChanged(int)</signal>
<receiver>nextUpdate</receiver>
<slot>localTime(int)</slot>
<hints>
<hint type="sourcelabel">
<x>291</x>
<y>243</y>
</hint>
<hint type="destinationlabel">
<x>418</x>
<y>160</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkBox</sender>
<signal>stateChanged(int)</signal>
<receiver>lastUpdate</receiver>
<slot>localTime(int)</slot>
<hints>
<hint type="sourcelabel">
<x>291</x>
<y>243</y>
</hint>
<hint type="destinationlabel">
<x>422</x>
<y>124</y>
</hint>
</hints>
</connection>
<connection>
<sender>midnightCB</sender>
<signal>clicked(bool)</signal>
<receiver>checkBox</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>81</x>
<y>243</y>
</hint>
<hint type="destinationlabel">
<x>291</x>
<y>243</y>
</hint>
</hints>
</connection>
<connection>
<sender>setCrlNumber</sender>
<signal>clicked(bool)</signal>
@ -395,12 +241,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>158</x>
<y>424</y>
<x>198</x>
<y>326</y>
</hint>
<hint type="destinationlabel">
<x>220</x>
<y>428</y>
<x>225</x>
<y>326</y>
</hint>
</hints>
</connection>

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>712</width>
<height>634</height>
<width>747</width>
<height>637</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
@ -68,7 +68,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>2</number>
<number>0</number>
</property>
<widget class="QWidget" name="tab_0">
<attribute name="title">
@ -97,23 +97,14 @@
<string>Signing request</string>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>9</number>
</property>
<item>
<widget class="QWidget" name="reqWidget" native="true">
<layout class="QGridLayout">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="1">
<widget class="QComboBox" name="reqList"/>
<widget class="itemCombo" name="reqList"/>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="showReqBut">
@ -152,9 +143,6 @@
<item>
<widget class="QWidget" name="attrWidget" native="true">
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>0</number>
</property>
@ -186,20 +174,8 @@
<string>Signing</string>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>9</number>
</property>
<item>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="selfSignRB">
<property name="text">
@ -224,12 +200,6 @@
</item>
<item>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="foreignSignRB">
<property name="text">
@ -238,7 +208,7 @@
</widget>
</item>
<item>
<widget class="QComboBox" name="certList">
<widget class="itemCombo" name="certList">
<property name="toolTip">
<string>All certificates in your database that can create valid signatures</string>
</property>
@ -264,12 +234,6 @@
</item>
<item>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
@ -305,7 +269,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QComboBox" name="tempList">
<widget class="itemCombo" name="tempList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -476,14 +440,8 @@
<string>Private key</string>
</property>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>9</number>
</property>
<item>
<widget class="QComboBox" name="keyList">
<widget class="itemCombo" name="keyList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -589,9 +547,6 @@
<string notr="true">Key identifier</string>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>8</number>
</property>
@ -639,9 +594,6 @@
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>0</number>
</property>
@ -689,7 +641,7 @@
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0" colspan="2">
<widget class="QLineEdit" name="validNumber"/>
<widget class="QLineEdit" name="validN"/>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="validRange">
@ -724,7 +676,7 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="midnightCB">
<widget class="QCheckBox" name="validMidn">
<property name="toolTip">
<string>Set the time to 00:00:00 and 23:59:59 respectively</string>
</property>
@ -925,26 +877,14 @@
<string>Key usage</string>
</attribute>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>8</number>
</property>
<item>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="kuBox">
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>8</number>
</property>
@ -1016,9 +956,6 @@
<item>
<widget class="QGroupBox" name="ekuBox">
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>8</number>
</property>
@ -1119,12 +1056,6 @@
</item>
<item>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="nsImg">
<property name="minimumSize">
@ -1160,12 +1091,6 @@
</item>
<item>
<layout class="QGridLayout" name="gridLayout_3">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="3" column="1">
<widget class="QLineEdit" name="nsRenewalUrl"/>
</item>
@ -1263,6 +1188,16 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Comment</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QTextEdit" name="comment"/>
</item>
</layout>
</widget>
</widget>
</item>
<item>
@ -1302,7 +1237,12 @@
<customwidget>
<class>DoubleClickLabel</class>
<extends>QLabel</extends>
<header location="global">widgets/clicklabel.h</header>
<header>widgets/clicklabel.h</header>
</customwidget>
<customwidget>
<class>itemCombo</class>
<extends>QComboBox</extends>
<header>widgets/ItemCombo.h</header>
</customwidget>
</customwidgets>
<tabstops>
@ -1333,8 +1273,8 @@
<tabstop>authKey</tabstop>
<tabstop>notBefore</tabstop>
<tabstop>notAfter</tabstop>
<tabstop>validNumber</tabstop>
<tabstop>midnightCB</tabstop>
<tabstop>validN</tabstop>
<tabstop>validMidn</tabstop>
<tabstop>checkBox</tabstop>
<tabstop>noWellDefinedExpDate</tabstop>
<tabstop>validRange</tabstop>
@ -1406,8 +1346,8 @@
<slot>deleteCurrentRow()</slot>
<hints>
<hint type="sourcelabel">
<x>622</x>
<y>284</y>
<x>713</x>
<y>199</y>
</hint>
<hint type="destinationlabel">
<x>57</x>
@ -1422,8 +1362,8 @@
<slot>addKvRow()</slot>
<hints>
<hint type="sourcelabel">
<x>622</x>
<y>252</y>
<x>713</x>
<y>167</y>
</hint>
<hint type="destinationlabel">
<x>57</x>
@ -1464,7 +1404,7 @@
</hints>
</connection>
<connection>
<sender>midnightCB</sender>
<sender>validMidn</sender>
<signal>stateChanged(int)</signal>
<receiver>notBefore</receiver>
<slot>hideTimeCheck(int)</slot>
@ -1480,7 +1420,7 @@
</hints>
</connection>
<connection>
<sender>midnightCB</sender>
<sender>validMidn</sender>
<signal>stateChanged(int)</signal>
<receiver>notAfter</receiver>
<slot>hideTimeCheck(int)</slot>
@ -1502,8 +1442,8 @@
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>557</x>
<y>584</y>
<x>566</x>
<y>627</y>
</hint>
<hint type="destinationlabel">
<x>285</x>
@ -1518,8 +1458,8 @@
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>643</x>
<y>587</y>
<x>652</x>
<y>627</y>
</hint>
<hint type="destinationlabel">
<x>405</x>
@ -1560,14 +1500,14 @@
</hints>
</connection>
<connection>
<sender>midnightCB</sender>
<sender>validMidn</sender>
<signal>clicked(bool)</signal>
<receiver>checkBox</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>350</x>
<y>333</y>
<x>431</x>
<y>348</y>
</hint>
<hint type="destinationlabel">
<x>447</x>

235
ui/TimeInput.ui Normal file
View File

@ -0,0 +1,235 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>491</width>
<height>224</height>
</rect>
</property>
<property name="windowTitle">
<string>TimeInput</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="dateBox">
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMinAndMaxSize</enum>
</property>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>last update</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Validity" name="lastUpdate">
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>next update</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Validity" name="nextUpdate">
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QLineEdit" name="validNumber"/>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="validRange">
<item>
<property name="text">
<string>Days</string>
</property>
</item>
<item>
<property name="text">
<string>Months</string>
</property>
</item>
<item>
<property name="text">
<string>Years</string>
</property>
</item>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="applyTime">
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="midnightCB">
<property name="text">
<string>Midnight</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Local time</string>
</property>
</widget>
</item>
<item row="1" column="2" colspan="2">
<widget class="QCheckBox" name="noWellDefinedExpDate">
<property name="text">
<string>No well-defined expiration</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Validity</class>
<extends>QDateTimeEdit</extends>
<header>widgets/validity.h</header>
<container>1</container>
<slots>
<slot>hideTimeCheck(int)</slot>
<slot>localTime(int)</slot>
</slots>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>midnightCB</sender>
<signal>clicked(bool)</signal>
<receiver>checkBox</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>128</x>
<y>189</y>
</hint>
<hint type="destinationlabel">
<x>256</x>
<y>189</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkBox</sender>
<signal>stateChanged(int)</signal>
<receiver>nextUpdate</receiver>
<slot>localTime(int)</slot>
<hints>
<hint type="sourcelabel">
<x>187</x>
<y>187</y>
</hint>
<hint type="destinationlabel">
<x>360</x>
<y>100</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkBox</sender>
<signal>stateChanged(int)</signal>
<receiver>lastUpdate</receiver>
<slot>localTime(int)</slot>
<hints>
<hint type="sourcelabel">
<x>256</x>
<y>189</y>
</hint>
<hint type="destinationlabel">
<x>360</x>
<y>64</y>
</hint>
</hints>
</connection>
<connection>
<sender>midnightCB</sender>
<signal>stateChanged(int)</signal>
<receiver>lastUpdate</receiver>
<slot>hideTimeCheck(int)</slot>
<hints>
<hint type="sourcelabel">
<x>131</x>
<y>189</y>
</hint>
<hint type="destinationlabel">
<x>360</x>
<y>64</y>
</hint>
</hints>
</connection>
<connection>
<sender>midnightCB</sender>
<signal>stateChanged(int)</signal>
<receiver>nextUpdate</receiver>
<slot>hideTimeCheck(int)</slot>
<hints>
<hint type="sourcelabel">
<x>146</x>
<y>189</y>
</hint>
<hint type="destinationlabel">
<x>360</x>
<y>100</y>
</hint>
</hints>
</connection>
<connection>
<sender>applyTime</sender>
<signal>clicked()</signal>
<receiver>Form</receiver>
<slot>applyTimeRange()</slot>
<hints>
<hint type="sourcelabel">
<x>310</x>
<y>195</y>
</hint>
<hint type="destinationlabel">
<x>297</x>
<y>228</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>applyTimeRange()</slot>
</slots>
</ui>

197
ui/XcaDialog.ui Normal file
View File

@ -0,0 +1,197 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>XcaDialog</class>
<widget class="QDialog" name="XcaDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>435</width>
<height>177</height>
</rect>
</property>
<property name="windowTitle">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<item>
<widget class="QLabel" name="title">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>95</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>40</height>
</size>
</property>
<property name="font">
<font>
<family>Arial</family>
<pointsize>14</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="toolTip">
<string notr="true"/>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="image">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>95</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>95</width>
<height>40</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="topSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="content">
<item>
<widget class="QLabel" name="description">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="bottomSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>XcaDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>286</x>
<y>264</y>
</hint>
<hint type="destinationlabel">
<x>83</x>
<y>245</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>XcaDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>386</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>430</x>
<y>85</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -21,7 +21,6 @@ CertDetail::CertDetail(QWidget *parent)
{
setupUi(this);
setWindowTitle(XCA_TITLE);
descr->setReadOnly(true);
showConf = false;
}
@ -47,6 +46,7 @@ void CertDetail::setX509super(pki_x509super *x)
pki_key *key= x->getRefKey();
if (key) {
privKey->setText(key->getIntName());
privKey->setClickText(key->getSqlItemId().toString());
if (key->isPrivKey()) {
privKey->setGreen();
} else {
@ -73,6 +73,11 @@ void CertDetail::setX509super(pki_x509super *x)
// Algorithm
sigAlgo->setText(x->getSigAlg());
connect(sigAlgo, SIGNAL(doubleClicked(QString)),
MainWindow::getResolver(), SLOT(searchOid(QString)));
// Comment
comment->setPlainText(x->getComment());
}
void CertDetail::setCert(pki_x509 *cert)
@ -96,25 +101,15 @@ void CertDetail::setCert(pki_x509 *cert)
signature->disableToolTip();
} else {
signature->setText(cert->getSigner()->getIntName());
privKey->setClickText(cert->getSqlItemId().toString());
signature->setGreen();
}
// check trust state
trustState->disableToolTip();
if (cert->getEffTrust() == 0) {
trustState->setText(tr("Not trusted"));
trustState->setRed();
}
else {
trustState->setText(tr("Trusted"));
trustState->setGreen();
}
// the serial
serialNr->setText(cert->getSerial().toHex());
// details of the issuer
issuer->setX509name(cert->getIssuer());
issuer->setX509name(cert->getIssuerName());
// The dates
notBefore->setText(cert->getNotBefore().toPretty());
@ -170,7 +165,6 @@ void CertDetail::setReq(pki_x509req *req)
signature->setText("PKCS#10");
}
signature->disableToolTip();
trustState->hide();
fingerprints->hide();
validity->hide();
serialLabel->hide();

View File

@ -72,8 +72,6 @@ void CertTreeView::fillContextMenu(QMenu *menu, QMenu *subExport,
SLOT(manageRevocations()));
subCa->setEnabled(cert->canSign());
}
menu->addAction(tr("Trust"), this,
SLOT(setTrust()))->setEnabled(allUnrevoked);
if (sameParent && parentCanSign) {
QString n = multi ? QString(" [%1]").arg(indexes.size()) : "";
menu->addAction(tr("Renewal") +n, this, SLOT(certRenewal()));
@ -189,11 +187,3 @@ void CertTreeView::unRevoke()
if (certs)
certs->unRevoke(getSelectedIndexes());
}
void CertTreeView::setTrust()
{
if (certs)
certs->setTrust(getSelectedIndexes());
proxy->invalidate();
}

View File

@ -44,6 +44,5 @@ class CertTreeView: public X509SuperTreeView
void caProperties();
void revoke();
void unRevoke();
void setTrust();
};
#endif

View File

@ -24,7 +24,6 @@ CrlDetail::CrlDetail(MainWindow *mainwin)
setWindowTitle(tr(XCA_TITLE));
image->setPixmap(*MainWindow::revImg);
descr->setReadOnly(true);
}
void CrlDetail::setCrl(pki_crl *crl)
@ -34,19 +33,18 @@ void CrlDetail::setCrl(pki_crl *crl)
iss = crl->getIssuer();
signCheck->disableToolTip();
signCheck->setClickText(crl->getSigAlg());
if (iss != NULL) {
issuerIntName->setText(iss->getIntName());
issuerIntName->setClickText(iss->getSqlItemId().toString());
issuerIntName->setGreen();
pki_key *key = iss->getPubKey();
if (crl->verify(key)) {
if (crl->verify(iss)) {
signCheck->setText(crl->getSigAlg());
signCheck->setGreen();
} else {
signCheck->setText(tr("Failed"));
signCheck->setRed();
}
if (key)
delete key;
} else {
issuerIntName->setText(tr("Unknown signer"));
issuerIntName->setDisabled(true);
@ -55,6 +53,9 @@ void CrlDetail::setCrl(pki_crl *crl)
signCheck->setDisabled(true);
}
connect(signCheck, SIGNAL(doubleClicked(QString)),
MainWindow::getResolver(), SLOT(searchOid(QString)));
descr->setText(crl->getIntName());
lUpdate->setText(crl->getLastUpdate().toPretty());
lUpdate->setToolTip(crl->getLastUpdate().toPrettyGMT());
@ -67,4 +68,6 @@ void CrlDetail::setCrl(pki_crl *crl)
RevocationList::setupRevocationView(certList, crl->getRevList(), iss);
v3extensions->document()->setHtml(crl->printV3ext());
comment->setPlainText(crl->getComment());
}

View File

@ -53,16 +53,16 @@ ExportDialog::ExportDialog(MainWindow *mw, QString title, QString filt,
help[exportType::PEM_selected] =
tr("Concatenated list of all selected items in one PEM text file");
help[exportType::PEM_chain] = tr("Concatenated text format of the complete certificate chain in one PEM file");
help[exportType::PEM_trusted] =
tr("Concatenated text format of all trusted certificates in one PEM file");
help[exportType::PEM_unrevoked] =
tr("Concatenated text format of all unrevoked certificates in one PEM file");
help[exportType::PEM_all] =
tr("Concatenated text format of all certificates in one PEM file");
help[exportType::DER] = tr("Binary DER encoded file");
help[exportType::PKCS7] = tr("PKCS#7 encoded single certificate");
help[exportType::PKCS7_chain] =
tr("PKCS#7 encoded complete certificate chain");
help[exportType::PKCS7_trusted] =
tr("All trusted certificates encoded in one PKCS#7 file");
help[exportType::PKCS7_unrevoked] =
tr("All unrevoked certificates encoded in one PKCS#7 file");
help[exportType::PKCS7_selected] =
tr("All selected certificates encoded in one PKCS#7 file");
help[exportType::PKCS7_all] =

View File

@ -16,8 +16,8 @@ class QPixmap;
class exportType {
public:
enum etype { Separator, PEM, PEM_chain, PEM_trusted, PEM_all,
DER, PKCS7, PKCS7_chain, PKCS7_trusted, PKCS7_all,
enum etype { Separator, PEM, PEM_chain, PEM_unrevoked, PEM_all,
DER, PKCS7, PKCS7_chain, PKCS7_unrevoked, PKCS7_all,
PKCS12, PKCS12_chain, PEM_cert_key, PEM_cert_pk8,
PEM_key, PEM_private, PEM_private_encrypt, DER_private,
DER_key, PKCS8, PKCS8_encrypt, SSH2_public,

View File

@ -33,7 +33,7 @@ ImportMulti::ImportMulti(MainWindow *parent)
setWindowTitle(XCA_TITLE);
image->setPixmap(*MainWindow::certImg);
listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
mcont = new db_token(QString(), parent);
mcont = new db_token(parent);
listView->setModel(mcont);
listView->setIconSize(pki_evp::icon[0]->size());
listView->setSelectionMode(QAbstractItemView::ExtendedSelection);

35
widgets/ItemCombo.h Normal file
View File

@ -0,0 +1,35 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#ifndef __ITEMCOMBO_H
#define __ITEMCOMBO_H
#include <QList>
#include <QComboBox>
#include "lib/pki_base.h"
class itemCombo : public QComboBox
{
public:
itemCombo(QWidget *parent) : QComboBox(parent) { }
void insertPkiItems(QList<pki_base*> items) {
foreach(pki_base *p, items) {
addItem(p->comboText(), QVariant::fromValue(p));
}
}
pki_base *currentPkiItem() {
return itemData(currentIndex()).value<pki_base*>();
}
int setCurrentPkiItem(pki_base *p) {
int idx = findData(QVariant::fromValue(p));
setCurrentIndex(idx);
return idx;
}
};
#endif

View File

@ -15,43 +15,428 @@
#include <QDebug>
#include <QStatusBar>
#include <QMessageBox>
#include <QtSql>
#include "lib/db_base.h"
#include "lib/func.h"
#include "lib/db.h"
#include "widgets/ImportMulti.h"
#include "widgets/NewKey.h"
void MainWindow::set_geometry(char *p, db_header_t *head)
QSqlError MainWindow::initSqlDB()
{
if (head->version != 1)
QStringList sl; sl
/* The "32bit hash" in public_keys, x509super, requests, certs and crls
* is used to quickly find items in the DB by reference.
* It consists of the first 4 bytes of a SHA1 hash.
* Collisions are of course possible.
*
* All binaries are stored Base64 encoded in a column of type
* "B64_BLOB" It is defined here as "VARCHAR(10000)"
*/
#define B64_BLOB "VARCHAR(10000)"
/*
* The B64(DER(something)) function means DER encode something
* and then Base64 encode that.
* So finally this is PEM without newlines, header and footer
*
* Dates are alway stored as 'CHAR(15)' in the
* ASN.1 Generalized time 'yyyyMMddHHmmssZ' format
*/
#define DB_DATE "CHAR(15)"
/*
* Configuration settings from
* the Options dialog, window size, last export directory,
* default key type and size,
* table column (position, sort order, visibility)
*/
<< "CREATE TABLE settings ("
"key CHAR(20) UNIQUE, "
"value VARCHAR(1024))"
<< "INSERT INTO settings (key, value) VALUES ('schema', '1')"
/*
* All items (keys, tokens, requests, certs, crls, templates)
* are stored here with the primary key and some common data
* The other tables containing the details reference the "id"
* as FOREIGN KEY.
*/
<< "CREATE TABLE items("
"id SERIAL PRIMARY KEY, "
"name VARCHAR(128), " /* Internal name of the item */
"type INTEGER, " /* enum pki_type */
"date "DB_DATE", " /* Time of insertion (creation/import) */
"comment VARCHAR(2048))"
/*
* Storage of public keys. Private keys and tokens also store
* their public part here.
*/
<< "CREATE TABLE public_keys ("
"item INTEGER, " /* reference to items(id) */
"type CHAR(4), " /* RSA DSA EC (as text) */
"hash INTEGER, " /* 32 bit hash */
"len INTEGER, " /* key size in bits */
"public "B64_BLOB", " /* B64(DER(public key)) */
"FOREIGN KEY (item) REFERENCES items (id))"
/*
* The private part of RSA, DSA, EC keys.
* references to "items" and "public_keys"
*/
<< "CREATE TABLE private_keys ("
"item INTEGER, " /* reference to items(id) */
"ownPass INTEGER, " /* Encrypted by DB pwd or own pwd */
"private "B64_BLOB", " /* B64(Encrypt(DER(private key))) */
"FOREIGN KEY (item) REFERENCES items (id))"
/*
* Smart cards or other PKCS#11 tokens
* references to "items" and "public_keys"
*/
<< "CREATE TABLE tokens ("
"item INTEGER, " /* reference to items(id) */
"card_manufacturer VARCHAR(64), " /* Card location data */
"card_serial VARCHAR(64), " /* as text */
"card_model VARCHAR(64), "
"card_label VARCHAR(64), "
"slot_label VARCHAR(64), "
"object_id VARCHAR(64), " /* Unique ID on the token */
"FOREIGN KEY (item) REFERENCES items (id))"
/*
* Encryption and hash mechanisms supported by a token
*/
<< "CREATE TABLE token_mechanism ("
"item INTEGER, " /* reference to items(id) */
"mechanism INTEGER, " /* PKCS#11: CK_MECHANISM_TYPE */
"FOREIGN KEY (item) REFERENCES items (id))"
/*
* An X509 Super class, consisting of a
* - Distinguishd name hash
* - Referenced key in the database
* - hash of the public key, used for lookups if there
* is no key to reference
* used by Requests and certificates and the use-counter of keys:
* "SELECT from x509super WHERE key=?"
*/
<< "CREATE TABLE x509super ("
"item INTEGER, " /* reference to items(id) */
"subj_hash INTEGER, " /* 32 bit hash of the Distinguished name */
"key INTEGER, " /* reference to the key items(id) */
"key_hash INTEGER, " /* 32 bit hash of the public key */
"FOREIGN KEY (item) REFERENCES items (id), "
"FOREIGN KEY (key) REFERENCES items (id)) "
/*
* PKCS#10 Certificate request details
* also takes information from the "x509super" table.
*/
<< "CREATE TABLE requests ("
"item INTEGER, " /* reference to items(id) */
"hash INTEGER, " /* 32 bit hash of the request */
"signed INTEGER, " /* Whether it was once signed. */
"request "B64_BLOB", " /* B64(DER(PKCS#10 request)) */
"FOREIGN KEY (item) REFERENCES items (id)) "
/*
* X509 certificate details
* also takes information from the "x509super" table.
* The content of the columns: hash, iss_hash, serial, ca
* can also be retrieved directly from the certificate, but are good
* to lurk around for faster lookup
*/
<< "CREATE TABLE certs ("
"item INTEGER, " /* reference to items(id) */
"hash INTEGER, " /* 32 bit hash of the cert */
"iss_hash INTEGER, " /* 32 bit hash of the issuer DN */
"serial VARCHAR(64), " /* Serial number of the certificate */
"issuer INTEGER, " /* The items(id) of the issuer or NULL */
"ca INTEGER, " /* CA: yes / no from BasicConstraints */
"crlExpire "DB_DATE", " /* CRL expiry date */
"crlNo INTEGER, " /* Last CRL Number expiry date */
"cert "B64_BLOB", " /* B64(DER(certificate)) */
"FOREIGN KEY (item) REFERENCES items (id), "
"FOREIGN KEY (issuer) REFERENCES items (id)) "
/*
* Storage of CRLs
*/
<< "CREATE TABLE crls ("
"item INTEGER, " /* reference to items(id) */
"hash INTEGER, " /* 32 bit hash of the CRL */
"num INTEGER, " /* Number of revoked certificates */
"iss_hash INTEGER, " /* 32 bit hash of the issuer DN */
"issuer INTEGER, " /* The items(id) of the issuer or NULL */
"crl "B64_BLOB", " /* B64(DER(revocation list)) */
"FOREIGN KEY (item) REFERENCES items (id), "
"FOREIGN KEY (issuer) REFERENCES items (id)) "
/*
* Revocations (serial, date, reason, issuer) used to create new
* CRLs. "Manage revocations"
*/
<< "CREATE TABLE revocations ("
"caId INTEGER, " /* reference to certs(item) */
"serial VARCHAR(64), " /* Serial number of the revoked certificate */
"date "DB_DATE", " /* Time of creating the revocation */
"invaldate "DB_DATE", " /* Time of invalidation */
"crlNo INTEGER, " /* Crl Number of CRL of first appearance */
"reasonBit INTEGER, " /* Bit number of the revocation reason */
"FOREIGN KEY (caId) REFERENCES items (id))"
/*
* Templates
*/
<< "CREATE TABLE templates ("
"item INTEGER, " /* reference to items(id) */
"version INTEGER, " /* Version of the template format */
"template "B64_BLOB", " /* The base64 encoded template */
"FOREIGN KEY (item) REFERENCES items (id))"
;
XSqlQuery q;
if (!db.transaction())
return db.lastError();
foreach(QString sql, sl) {
fprintf(stderr, "EXEC: '%s'\n", CCHAR(sql));
if (!q.exec(sql)) {
db.rollback();
return q.lastError();
}
}
db.commit();
return QSqlError();
}
QSqlError MainWindow::openSqlDB()
{
QStringList drivers = QSqlDatabase::drivers();
foreach( QString driver, drivers)
fprintf(stderr, "DB driver: '%s'\n", CCHAR(driver));
#define POSTGRES 1
#ifndef POSTGRES
db.setDatabaseName(dbfile);
#else
db.setDatabaseName("xca_pg");
db.setHostName("192.168.140.7");
db.setUserName("xca");
db.setPassword("xca");
#endif
if (db.driverName() == "QSQLITE") {
// chmod 0600
if (!QFile::exists(dbfile)) {
QFile f(dbfile);
f.open(QIODevice::WriteOnly);
f.setPermissions(QFile::WriteOwner | QFile::ReadOwner);
f.close();
}
}
if (!db.open())
return db.lastError();
QStringList tables = db.tables();
if (!tables.contains("items")) {
return initSqlDB();
}
return QSqlError();
}
void MainWindow::set_geometry(QString geo)
{
QStringList sl = geo.split(",");
if (sl.size() != 2)
return;
QByteArray ba = QByteArray::fromRawData(p, head->len);
int w, h, i;
w = db::intFromData(ba);
h = db::intFromData(ba);
i = db::intFromData(ba);
resize(w,h);
resize(sl[0].toInt(), sl[1].toInt());
int i = sl[2].toInt();
if (i != -1)
tabView->setCurrentIndex(i);
}
void MainWindow::dbSqlError(QSqlError err)
{
if (!err.isValid())
err = QSqlDatabase::database().lastError();
if (err.isValid()) {
fprintf(stderr, "SQL ERROR: '%s'\n", CCHAR(err.text()));
XCA_WARN(err.text());
}
}
bool MainWindow::checkForOldDbFormat()
{
// 0x ca db 19 69
static const char magic[] = { 0xca, 0xdb, 0x19, 0x69 };
char head[4];
QFile file(dbfile);
if (!file.open(QIODevice::ReadOnly))
return 0;
file.read(head, sizeof head);
file.close();
return !memcmp(head, magic, sizeof head);
}
int MainWindow::verifyOldDbPass(QString dbname)
{
// look for the password
QString passhash;
db_header_t head;
class db mydb(dbname);
mydb.first();
if (!mydb.find(setting, QString("pwhash"))) {
QString val;
char *p;
if ((p = (char *)mydb.load(&head))) {
passhash = p;
free(p);
return initPass(passhash);
}
}
return 2;
}
void MainWindow::importOldDatabase(QString dbname)
{
class db mydb(dbname);
unsigned char *p = NULL;
db_header_t head;
pki_base *pki;
db_base *cont;
QList<enum pki_type> pkitype; pkitype <<
smartCard << asym_key << tmpl << x509_req << x509 << revocation;
storeSetting("pwhash", pki_evp::passHash);
for (int i=0; i < pkitype.count(); i++) {
mydb.first();
while (mydb.find(pkitype[i], QString()) == 0) {
QString s;
p = mydb.load(&head);
if (!p) {
qWarning("Load was empty !");
goto next;
}
switch (pkitype[i]) {
case smartCard:
cont = keys;
pki = new pki_scard("");
break;
case asym_key:
cont = keys;
pki = new pki_evp();
break;
case x509_req:
cont = reqs;
pki = new pki_x509req();
break;
case x509:
cont = certs;
pki = new pki_x509();
break;
case revocation:
cont = crls;
pki = new pki_crl();
break;
case tmpl:
cont = temps;
pki = new pki_temp();
break;
default:
goto next;
}
pki->setIntName(QString::fromUtf8(head.name));
try {
pki->fromData(p, &head);
}
catch (errorEx &err) {
err.appendString(pki->getIntName());
Error(err);
delete pki;
pki = NULL;
}
fprintf(stderr, "load old: '%s'\n", CCHAR(pki->getIntName()));
free(p);
if (pki) {
cont->insertPKI(pki);
}
next:
if (mydb.next())
break;
}
}
QStringList sl; sl << "workingdir" << "pkcs11path" <<
"default_hash" << "mandatory_dn" << "explicit_dn" <<
"string_opt" << "optionflags1" << "defaultkey";
mydb.first();
while (!mydb.find(setting, QString())) {
QString val;
char *p;
if ((p = (char *)mydb.load(&head))) {
val = p;
free(p);
}
QString set = QString::fromUtf8(head.name);
if (sl.contains(set)) {
if (set == "optionflags1")
set = "optionflags";
storeSetting(set, val);
}
if (mydb.next())
break;
}
}
int MainWindow::init_database()
{
int ret = 2;
QSqlError err;
QString oldDbFile;
qDebug("Opening database: %s", QString2filename(dbfile));
keys = NULL; reqs = NULL; certs = NULL; temps = NULL; crls = NULL;
if (checkForOldDbFormat()) {
QString newname = dbfile;
if (newname.endsWith(".xdb"))
newname = newname.left(newname.length() -4);
newname += "_backup_" + QDateTime::currentDateTime()
.toString("yyyyMMdd_hhmmss") + ".xdb";
if (!XCA_OKCANCEL(tr("Found an old version of the XCA database. I will make a backup copy called: '%1' and convert the database into the new format").arg(newname))) {
dbfile = "";
return 1;
}
if (verifyOldDbPass(dbfile) != 1)
return 1;
if (!QFile::rename(dbfile, newname)) {
XCA_WARN(tr("Failed to rename the database file, because the target already exists"));
return 1;
}
oldDbFile = newname;
}
Entropy::seed_rng();
err = openSqlDB();
dbSqlError(err);
certView->setRootIsDecorated(db_x509::treeview);
try {
ret = initPass();
if (ret == 2)
return ret;
keys = new db_key(dbfile, this);
reqs = new db_x509req(dbfile, this);
certs = new db_x509(dbfile, this);
temps = new db_temp(dbfile, this);
crls = new db_crl(dbfile, this);
if (pki_evp::passwd.isEmpty()) {
ret = initPass();
if (ret == 2)
return ret;
}
keys = new db_key(this);
reqs = new db_x509req(this);
certs = new db_x509(this);
temps = new db_temp(this);
crls = new db_crl(this);
certs->updateAfterDbLoad();
}
catch (errorEx &err) {
@ -73,15 +458,6 @@ int MainWindow::init_database()
workingdir = QDir::currentPath();
setOptFlags((QString()));
connect( keys, SIGNAL(newKey(pki_key *)),
certs, SLOT(newKey(pki_key *)) );
connect( keys, SIGNAL(delKey(pki_key *)),
certs, SLOT(delKey(pki_key *)) );
connect( keys, SIGNAL(newKey(pki_key *)),
reqs, SLOT(newKey(pki_key *)) );
connect( keys, SIGNAL(delKey(pki_key *)),
reqs, SLOT(delKey(pki_key *)) );
connect( certs, SIGNAL(connNewX509(NewX509 *)), this,
SLOT(connNewX509(NewX509 *)) );
connect( reqs, SIGNAL(connNewX509(NewX509 *)), this,
@ -105,57 +481,32 @@ int MainWindow::init_database()
certView->setModel(certs);
tempView->setModel(temps);
crlView->setModel(crls);
try {
db mydb(dbfile);
while (mydb.find(setting, QString()) == 0) {
QString key;
db_header_t head;
char *p = (char *)mydb.load(&head);
if (!p) {
if (mydb.next())
break;
continue;
}
key = head.name;
if (!oldDbFile.isEmpty())
importOldDatabase(oldDbFile);
if (key == "workingdir")
workingdir = p;
else if (key == "pkcs11path")
pkcs11path = p;
else if (key == "default_hash")
hashBox::setDefault(p);
else if (key == "mandatory_dn")
mandatory_dn = p;
else if (key == "explicit_dn")
explicit_dn = p;
/* what a stupid idea.... */
else if (key == "multiple_key_use")
mydb.erase();
else if (key == "string_opt")
string_opt = p;
else if (key == "suppress")
mydb.erase();
else if (key == "optionflags1")
setOptFlags((QString(p)));
/* Different optionflags, since setOptFlags()
* does an abort() for unknown flags in
* older versions. *Another stupid idea*
* This is for backward compatibility
*/
else if (key == "optionflags")
setOptFlags_old((QString(p)));
else if (key == "defaultkey")
NewKey::setDefault((QString(p)));
else if (key == "mw_geometry")
set_geometry(p, &head);
free(p);
if (mydb.next())
break;
}
} catch (errorEx &err) {
Error(err);
return ret;
XSqlQuery query("SELECT key, value FROM settings");
while (query.next()) {
QString key = query.value(0).toString();
QString value = query.value(1).toString();
if (key == "workingdir")
workingdir = value;
else if (key == "pkcs11path")
pkcs11path = value;
else if (key == "default_hash")
hashBox::setDefault(value);
else if (key == "mandatory_dn")
mandatory_dn = value;
else if (key == "explicit_dn")
explicit_dn = value;
else if (key == "string_opt")
string_opt = value;
else if (key == "optionflags")
setOptFlags(value);
else if (key == "defaultkey")
NewKey::setDefault(value);
else if (key == "mw_geometry")
set_geometry(value);
}
ASN1_STRING_set_default_mask_asc((char*)CCHAR(string_opt));
if (explicit_dn.isEmpty())
@ -205,6 +556,9 @@ void MainWindow::dump_database()
void MainWindow::undelete()
{
#warning undelete NOT WORKING!
qDebug("undelete NOT WORKING!");
#if 0
ImportMulti *dlgi = new ImportMulti(this);
db_header_t head;
db mydb(dbfile);
@ -242,6 +596,7 @@ void MainWindow::undelete()
XCA_INFO(tr("No deleted items found"));
}
delete dlgi;
#endif
}
int MainWindow::open_default_db()
@ -290,17 +645,48 @@ void MainWindow::default_database()
}
QString MainWindow::getSetting(QString key)
{
XSqlQuery q;
SQL_PREPARE(q, "SELECT value FROM settings WHERE key=?");
q.bindValue(0, key);
q.exec();
if (q.first()) {
return q.value(0).toString();
}
dbSqlError(q.lastError());
return QString();
}
void MainWindow::storeSetting(QString key, QString value)
{
XSqlQuery q;
SQL_PREPARE(q, "UPDATE settings SET value=? WHERE key=?");
q.bindValue(0, value);
q.bindValue(1, key);
q.exec();
dbSqlError(q.lastError());
if (q.numRowsAffected() == 1)
return;
SQL_PREPARE(q, "INSERT INTO settings (key, value) VALUES (?, ?)");
q.bindValue(0, key);
q.bindValue(1, value);
q.exec();
dbSqlError(q.lastError());
}
void MainWindow::close_database()
{
QByteArray ba;
if (!dbfile.isEmpty()) {
ba += db::intToData(size().width());
ba += db::intToData(size().height());
ba += db::intToData(tabView->currentIndex());
db mydb(dbfile);
mydb.set((const unsigned char *)ba.constData(), ba.size(), 1,
setting, "mw_geometry");
}
if (!db.isOpen())
return;
qDebug("Closing database: %s", QString2filename(dbfile));
QString s = QString("%1,%2,%3")
.arg(size().width()).arg(size().height())
.arg(tabView->currentIndex());
storeSetting("mw_geometry", s);
setItemEnabled(false);
statusBar()->removeWidget(searchEdit);
dbindex->clear();
@ -322,11 +708,13 @@ void MainWindow::close_database()
if (keys)
delete(keys);
db_base::flushLookup();
reqs = NULL;
certs = NULL;
temps = NULL;
keys = NULL;
db.close();
pki_evp::passwd.cleanse();
pki_evp::passwd = QByteArray();
@ -334,19 +722,6 @@ void MainWindow::close_database()
return;
crls = NULL;
try {
int ret;
db mydb(dbfile);
ret = mydb.shrink( DBFLAG_OUTDATED | DBFLAG_DELETED );
if (ret == 1)
XCA_INFO(tr("Errors detected and repaired while deleting outdated items from the database. A backup file was created"));
if (ret == 2)
XCA_INFO(tr("Removing deleted or outdated items from the database failed."));
}
catch (errorEx &err) {
MainWindow::Error(err);
}
update_history(dbfile);
pkcs11::remove_libs();
enableTokenMenu(pkcs11::loaded());

View File

@ -14,7 +14,7 @@
#ifndef OPENSSL_NO_EC
#include <openssl/ec.h>
#endif
#include "ui_About.h"
#include "XcaDialog.h"
#include "ui_Help.h"
#include "lib/func.h"
#include "lib/entropy.h"
@ -45,8 +45,10 @@ void MainWindow::cmd_help(const char* msg)
void MainWindow::about()
{
Ui::About ui;
QDialog *about = new QDialog(this, 0);
QTextEdit *textbox = new QTextEdit(NULL);
XcaDialog *about = new XcaDialog(this, x509, textbox,
QString(), QString());
about->aboutDialog(scardImg);
QString openssl, qt, cont, version, brainpool;
#ifndef OPENSSL_NO_EC
#ifdef NID_brainpoolP160r1
@ -81,7 +83,6 @@ void MainWindow::about()
} else {
version = QString("%1<br>QT version: %2").arg(openssl).arg(qt);
}
ui.setupUi(about);
Entropy::seed_rng();
cont = QString(
"<p><h3><center><u>XCA</u></center></h3>"
@ -105,10 +106,7 @@ void MainWindow::about()
.arg(version_str(true)).arg(getPrefix())
.arg(getUserSettingsDir());
about->setWindowTitle(XCA_TITLE);
ui.image->setPixmap( *keyImg );
ui.image1->setPixmap( *certImg );
ui.textbox->setHtml(cont);
textbox->setHtml(cont);
about->exec();
delete about;
}

View File

@ -144,8 +144,6 @@ void MainWindow::init_menu()
SLOT(exportIndexHierarchy()));
acList += extra->addAction(tr("C&hange DataBase password"), this,
SLOT(changeDbPass()));
acList += extra->addAction(tr("&Import old db_dump"), this,
SLOT(import_dbdump()));
acList += extra->addAction(tr("&Undelete items"), this,
SLOT(undelete()));
extra->addAction(tr("Generate DH parameter"), this,
@ -218,44 +216,6 @@ void MainWindow::load_database()
changeDB(fname);
}
void MainWindow::import_dbdump()
{
extern int read_dump(const char *, db_base **, char *, int);
Passwd pass;
char buf[50];
db_base *dbl[] = { keys, reqs, certs, temps, crls };
if (!keys)
return;
QString file = QFileDialog::getOpenFileName(this, tr(XCA_TITLE), homedir,
tr("Database dump ( *.dump );; All files ( * )"));
if (file.isEmpty())
return;
pass_info p(tr("Import password"),
tr("Please enter the password of the old database"), this);
if (PwDialog::execute(&p, &pass) != 1)
return;
try {
read_dump(CCHAR(file), dbl, buf, sizeof(buf));
if (pki_evp::md5passwd(pass) != buf) {
xcaWarning msg(this, tr("Password verification error. Ignore keys ?"));
msg.addButton(QMessageBox::Cancel);
msg.addButton(QMessageBox::Ok)->setText(
tr("Import anyway"));
if (msg.exec() == QMessageBox::Cancel)
return;
}
pki_evp::oldpasswd = pass;
read_dump(CCHAR(file), dbl, NULL, 0);
pki_evp::oldpasswd.cleanse();
} catch (errorEx &err) {
Error(err);
}
}
void MainWindow::setOptions()
{
if (dbfile.isEmpty())
@ -284,25 +244,18 @@ void MainWindow::setOptions()
return;
}
QString alg = opt->hashAlgo->currentHashName();
db mydb(dbfile);
mydb.set((const unsigned char *)CCHAR(alg), alg.length()+1, 1,
setting, "default_hash");
storeSetting("default_hash", alg);
hashBox::setDefault(alg);
mandatory_dn = opt->getExtDnString();
explicit_dn = opt->getExpDnString();
mydb.set((const unsigned char *)CCHAR(mandatory_dn),
mandatory_dn.length()+1, 1, setting, "mandatory_dn");
storeSetting("mandatory_dn", mandatory_dn);
if (explicit_dn.isEmpty())
explicit_dn = explicit_dn_default;
if (explicit_dn != explicit_dn_default) {
mydb.set((const unsigned char *)CCHAR(explicit_dn),
explicit_dn.length()+1, 1, setting, "explicit_dn");
storeSetting("explicit_dn", explicit_dn);
} else {
mydb.first();
if (!mydb.find(setting, "explicit_dn")) {
mydb.erase();
}
XSqlQuery query("DELETE FROM settings WHERE key='explicit_dn'");
}
QString flags = getOptFlags();
pki_base::suppress_messages = opt->suppress->checkState();
@ -313,11 +266,7 @@ void MainWindow::setOptions()
if (flags != getOptFlags()) {
flags = getOptFlags();
mydb.set((const unsigned char *)(CCHAR(flags)),
flags.length()+1, 1, setting, "optionflags1");
mydb.first();
if (!mydb.find(setting, "suppress"))
mydb.erase();
storeSetting("optionflags", flags);
certView->showHideSections();
reqView->showHideSections();
}
@ -325,14 +274,12 @@ void MainWindow::setOptions()
if (opt->getStringOpt() != string_opt) {
string_opt = opt->getStringOpt();
ASN1_STRING_set_default_mask_asc((char *)CCHAR(string_opt));
mydb.set((const unsigned char *)CCHAR(string_opt),
string_opt.length()+1, 1, setting,"string_opt");
storeSetting("string_opt", string_opt);
}
QString newpath = opt->getPkcs11Provider();
if (newpath != pkcs11path) {
pkcs11path = newpath;
mydb.set((const unsigned char *) CCHAR(pkcs11path),
pkcs11path.length()+1, 1,setting, "pkcs11path");
storeSetting("pkcs11path", pkcs11path);
}
enableTokenMenu(pkcs11::loaded());
delete opt;

View File

@ -38,7 +38,7 @@
#include "lib/func.h"
#include "lib/pkcs11.h"
#include "lib/builtin_curves.h"
#include "ui_About.h"
#include "XcaDialog.h"
#include "PwDialog.h"
QPixmap *MainWindow::keyImg = NULL, *MainWindow::csrImg = NULL,
@ -113,6 +113,20 @@ MainWindow::MainWindow(QWidget *parent)
wdList << keyButtons << reqButtons << certButtons <<
tempButtons << crlButtons;
QStringList drivers = QSqlDatabase::drivers();
foreach(QString driver, drivers) {
QSqlDatabase d = QSqlDatabase::addDatabase(driver, driver +"_C");
fprintf(stderr, "DB driver: '%s' LastInsertId: %s\n",
CCHAR(driver), d.driver()->
hasFeature(QSqlDriver::LastInsertId) ? "YES":"NO" );
}
#define POSTGRES 1
#ifndef POSTGRES
db = QSqlDatabase::addDatabase("QSQLITE");
#else
db = QSqlDatabase::addDatabase("QPSQL7");
#endif
historyMenu = NULL;
init_menu();
setItemEnabled(false);
@ -359,7 +373,7 @@ void MainWindow::loadPem()
keys->load_default(l);
}
bool MainWindow::pastePem(QString text)
bool MainWindow::pastePem(QString text, bool silent)
{
bool success = false;
QByteArray pemdata = text.toLatin1();
@ -378,7 +392,8 @@ bool MainWindow::pastePem(QString text)
dlgi->execute(1);
}
catch (errorEx &err) {
Error(err);
if (!silent)
Error(err);
}
if (dlgi)
delete dlgi;
@ -389,7 +404,6 @@ bool MainWindow::pastePem(QString text)
void MainWindow::pastePem()
{
Ui::About ui;
QClipboard *cb = QApplication::clipboard();
QString text;
@ -398,25 +412,21 @@ void MainWindow::pastePem()
text = cb->text(QClipboard::Clipboard);
if (!text.isEmpty())
if (pastePem(text))
if (pastePem(text, true))
return;
QDialog *input = new QDialog(this, 0);
ui.setupUi(input);
delete ui.textbox;
QTextEdit *textbox = new QTextEdit(input);
ui.vboxLayout->addWidget(textbox);
ui.button->setText(tr("Import PEM data"));
input->setWindowTitle(XCA_TITLE);
QTextEdit *textbox = new QTextEdit();
textbox->setPlainText(text);
XcaDialog *input = new XcaDialog(this, x509, textbox,
tr("Import PEM data"), QString());
input->noSpacer();
if (input->exec()) {
text = textbox->toPlainText();
if (!text.isEmpty())
pastePem(text);
}
delete input;
}
void MainWindow::initToken()
@ -550,7 +560,6 @@ void MainWindow::manageToken()
cert = new pki_x509("");
try {
cert->load_token(p11, objects[j]);
cert->setTrust(2);
dlgi->addItem(cert);
} catch (errorEx &err) {
Error(err);
@ -602,36 +611,30 @@ void MainWindow::closeEvent(QCloseEvent *e)
QString makeSalt(void)
{
unsigned char rand[2];
char saltbuf[10];
QString s = "T";
unsigned char rand[8];
Entropy::get(rand, 2);
snprintf(saltbuf, 10, "S%02X%02X", rand[0], rand[1]);
return QString(saltbuf);
Entropy::get(rand, sizeof rand);
for (unsigned i=0; i< sizeof rand; i++)
s += QString("%1").arg(rand[i]);
return s;
}
int MainWindow::checkOldGetNewPass(Passwd &pass)
{
QString passHash;
db mydb(dbfile);
if (!mydb.find(setting, "pwhash")) {
char *cpass;
QString passHash = getSetting("pwhash");
if (!passHash.isEmpty()) {
pass_info p(tr("Current Password"),
tr("Please enter the current database password"), this);
if ((cpass = (char *)mydb.load(NULL))) {
passHash = cpass;
free(cpass);
}
/* Try empty password */
if (pki_evp::sha512passwd(pass, passHash) != passHash) {
if (pki_evp::sha512passwT(pass, passHash) != passHash) {
/* Not the empty password, check it */
if (PwDialog::execute(&p, &pass, false) != 1)
return 0;
}
if (pki_evp::sha512passwd(pass, passHash) != passHash) {
if (pki_evp::sha512passwT(pass, passHash) != passHash) {
XCA_WARN(tr("The entered password is wrong"));
return 0;
}
@ -647,106 +650,50 @@ int MainWindow::checkOldGetNewPass(Passwd &pass)
void MainWindow::changeDbPass()
{
Passwd pass;
QString tempn = dbfile + "{recrypt}";
XSqlQuery q;
if (!checkOldGetNewPass(pass))
return;
try {
if (!QFile::copy(dbfile, tempn))
throw errorEx("Could not create temporary file: " +
tempn);
QString passhash = updateDbPassword(tempn, pass);
QFile new_file(tempn);
/* closing the database erases 'dbfile' */
QString dbfile_bkup = dbfile;
close_database();
db mydb(dbfile_bkup);
if (mydb.mv(new_file))
throw errorEx(QString("Failed to rename %1 to %2").
arg(tempn).arg(dbfile_bkup));
dbfile = dbfile_bkup;
pki_evp::passHash = passhash;
pki_evp::passwd = pass;
init_database();
} catch (errorEx &ex) {
QFile::remove(tempn);
Error(ex);
}
}
QString MainWindow::updateDbPassword(QString newdb, Passwd pass)
{
db mydb(newdb);
QString salt = makeSalt();
QString passhash = pki_evp::sha512passwd(pass, salt);
mydb.set((const unsigned char *)CCHAR(passhash),
passhash.length()+1, 1, setting, "pwhash");
QString passhash = pki_evp::sha512passwT(pass, salt);
QList<pki_base*> key_list = keys->sqlSELECTpki(
"SELECT item FROM private_keys WHERE ownPass=0");
QList<pki_evp*> klist;
mydb.first();
while (mydb.find(asym_key, QString()) == 0) {
QString s;
pki_evp *key;
unsigned char *p;
db_header_t head;
p = mydb.load(&head);
if (!p)
throw errorEx("Failed to load item");
key = new pki_evp();
if (key->getVersion() < head.version) {
int v = key->getVersion();
free(p);
delete key;
throw errorEx(QString("Item[%1]: Version %2 "
"> known version: %3 -> ignored")
.arg(head.name).arg(head.version).arg(v)
);
}
key->setIntName(QString::fromUtf8(head.name));
try {
key->fromData(p, &head);
}
catch (errorEx &err) {
err.appendString(key->getIntName());
free(p);
delete key;
throw err;
}
free(p);
if (key && key->getOwnPass() == pki_key::ptCommon &&
!key->isPubKey())
{
if (!db.transaction()) {
errorEx e(tr("Transaction start failed"));
Error(e);
return;
}
try {
foreach(pki_base *pki, key_list) {
pki_evp *key = static_cast<pki_evp*>(pki);
EVP_PKEY *evp = key->decryptKey();
key->set_evp_key(evp);
key->encryptKey(pass.constData());
klist << key;
} else if (key)
delete key;
if (mydb.next())
break;
key->sqlUpdatePrivateKey();
}
storeSetting("pwhash", passhash);
} catch (errorEx &e) {
Error(e);
db.rollback();
return;
}
for (int i=0; i< klist.count(); i++) {
pki_evp *key = klist[i];
QByteArray ba = key->toData();
mydb.set((const unsigned char*)ba.constData(), ba.count(),
key->getVersion(), key->getType(), key->getIntName());
delete key;
}
return passhash;
db.commit();
pki_evp::passHash = passhash;
pki_evp::passwd = pass;
}
int MainWindow::initPass()
{
db mydb(dbfile);
char *pass;
QString passhash = getSetting("pwhash");
return initPass(passhash);
}
int MainWindow::initPass(QString passhash)
{
pki_evp::passHash = QString();
QString salt;
QString salt, pass;
int ret;
pass_info p(tr("New Password"), tr("Please enter a password, "
@ -754,23 +701,17 @@ int MainWindow::initPass()
"in the database file:\n%1").
arg(compressFilename(dbfile)), this);
if (!mydb.find(setting, "pwhash")) {
if ((pass = (char *)mydb.load(NULL))) {
pki_evp::passHash = pass;
free(pass);
}
}
pki_evp::passHash = passhash;
if (pki_evp::passHash.isEmpty()) {
ret = PwDialog::execute(&p, &pki_evp::passwd, true, true);
if (ret != 1)
return ret;
salt = makeSalt();
pki_evp::passHash = pki_evp::sha512passwd(pki_evp::passwd,salt);
mydb.set((const unsigned char *)CCHAR(pki_evp::passHash),
pki_evp::passHash.length()+1, 1, setting, "pwhash");
pki_evp::passHash =pki_evp::sha512passwT(pki_evp::passwd,salt);
storeSetting("pwhash", pki_evp::passHash);
} else {
ret = 0;
while (pki_evp::sha512passwd(pki_evp::passwd, pki_evp::passHash)
while (pki_evp::sha512passwT(pki_evp::passwd, pki_evp::passHash)
!= pki_evp::passHash)
{
if (ret)
@ -784,21 +725,25 @@ int MainWindow::initPass()
pki_evp::passwd = QByteArray();
return ret;
}
if (pki_evp::passHash.left(1) == "S")
if (pki_evp::passHash.startsWith("T")) {
/* Fine, current hash function used. */
continue;
}
/* Start automatic update from sha512 to sha512*8000
* if the password is correct. The old sha512 hash does
* start with 'S', while the new hash starts with T. */
/* Start automatic update from md5 to salted sha512
* if the password is correct. my md5 hash does not
* start with 'S', while my new hash does. */
if (pki_evp::md5passwd(pki_evp::passwd) ==
pki_evp::passHash )
* if the password is correct. The md5 hash does not
* start with 'S' or 'T, but with a hex-digit */
if (pki_evp::sha512passwd(pki_evp::passwd,
pki_evp::passHash) == pki_evp::passHash ||
pki_evp::md5passwd(pki_evp::passwd) ==
pki_evp::passHash)
{
salt = makeSalt();
pki_evp::passHash = pki_evp::sha512passwd(
pki_evp::passHash = pki_evp::sha512passwT(
pki_evp::passwd, salt);
mydb.set((const unsigned char *)CCHAR(
pki_evp::passHash),
pki_evp::passHash.length() +1, 1,
setting, "pwhash");
}
}
}
@ -830,22 +775,18 @@ QString MainWindow::getPath()
void MainWindow::setPath(QString str)
{
db mydb(dbfile);
workingdir = str;
mydb.set((const unsigned char *)CCHAR(str), str.length()+1, 1, setting, "workingdir");
}
void MainWindow::setDefaultKey(QString str)
{
db mydb(dbfile);
mydb.set((const unsigned char *)CCHAR(str), str.length()+1, 1, setting, "defaultkey");
storeSetting("workingdir", str);
}
void MainWindow::connNewX509(NewX509 *nx)
{
connect( nx, SIGNAL(genKey(QString)), keys, SLOT(newItem(QString)) );
connect( keys, SIGNAL(keyDone(QString)), nx, SLOT(newKeyDone(QString)) );
connect( nx, SIGNAL(showReq(QString)), reqs, SLOT(showItem(QString)));
connect(nx, SIGNAL(genKey(QString)),
keys, SLOT(newItem(QString)));
connect(keys, SIGNAL(keyDone(pki_key*)),
nx, SLOT(newKeyDone(pki_key*)));
connect(nx, SIGNAL(showReq(pki_base*)),
reqs, SLOT(showPki(pki_base*)));
}
void MainWindow::importAnything(QString file)
@ -862,22 +803,14 @@ void MainWindow::importAnything(QString file)
pki_multi *MainWindow::probeAnything(QString file, int *ret)
{
(void)ret;
pki_multi *pki = new pki_multi();
try {
if (file.endsWith(".xdb")) {
try {
int r;
db *mydb = new db(file);
mydb->verify_magic();
delete mydb;
r = changeDB(file);
delete pki;
if (ret)
*ret = r;
return NULL;
} catch (errorEx &err) {
}
#warning FIXME OPEN DATABASE
qDebug("FIXME OPEN DATABASE");
return pki;
}
pki->probeAnything(file);
} catch (errorEx &err) {

View File

@ -24,13 +24,12 @@
#include <QFileDialog>
#include <QMenuBar>
#include <QList>
#include <QtSql>
#include <QMessageBox>
#include <QMenu>
#include <QToolTip>
#include <QLocale>
#define DBFILE "xca.xdb"
class db_x509;
class pki_multi;
@ -81,12 +80,15 @@ class MainWindow: public QMainWindow, public Ui::MainWindow
QStringList history;
tipMenu *historyMenu;
void update_history_menu();
void set_geometry(char *p, db_header_t *head);
void set_geometry(QString geo);
QLineEdit *searchEdit;
QStringList urlsToOpen;
int checkOldGetNewPass(Passwd &pass);
QString updateDbPassword(QString newdb, Passwd pass);
int exportIndex(QString fname, bool hierarchy);
void checkDB();
QSqlError initSqlDB();
QSqlError openSqlDB();
QSqlDatabase db;
protected:
void init_images();
@ -115,6 +117,10 @@ class MainWindow: public QMainWindow, public Ui::MainWindow
static QString explicit_dn;
static QString explicit_dn_default;
int exitApp;
QSqlDatabase *getDb()
{
return &db;
}
QString dbfile;
QLabel *dbindex;
@ -123,6 +129,7 @@ class MainWindow: public QMainWindow, public Ui::MainWindow
void loadSettings();
void saveSettings();
int initPass();
int initPass(QString passhash);
void read_cmdline(int argc, char *argv[]);
void load_engine();
static OidResolver *getResolver()
@ -130,6 +137,10 @@ class MainWindow: public QMainWindow, public Ui::MainWindow
return resolver;
}
static void Error(errorEx &err);
static void dbSqlError(QSqlError err = QSqlError());
static void storeSetting(QString key, QString value);
static QString getSetting(QString key);
void cmd_version();
void cmd_help(const char* msg);
@ -143,10 +154,12 @@ class MainWindow: public QMainWindow, public Ui::MainWindow
void dropEvent(QDropEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
int open_default_db();
void setDefaultKey(QString def);
void load_history();
void update_history(QString file);
void initResolver();
bool checkForOldDbFormat();
int verifyOldDbPass(QString dbname);
void importOldDatabase(QString dbname);
public slots:
int init_database();
@ -158,10 +171,9 @@ class MainWindow: public QMainWindow, public Ui::MainWindow
void connNewX509(NewX509 *nx);
void about();
void help();
void import_dbdump();
void undelete();
void loadPem();
bool pastePem(QString text);
bool pastePem(QString text, bool silent=false);
void pastePem();
void changeDbPass();
void openURLs(QStringList &files);

View File

@ -18,11 +18,9 @@
#include <QMessageBox>
NewCrl::NewCrl(QWidget *parent, pki_x509 *signer)
:QDialog(parent)
:QWidget(parent)
{
setupUi(this);
setWindowTitle(XCA_TITLE);
image->setPixmap(*MainWindow::revImg);
dateBox->setTitle(signer->getIntName());
validNumber->setText(QString::number(signer->getCrlDays()));
validRange->setCurrentIndex(0);

View File

@ -13,7 +13,7 @@
class pki_key;
class NewCrl: public QDialog, public Ui::NewCrl
class NewCrl: public QWidget, public Ui::NewCrl
{
Q_OBJECT

View File

@ -9,9 +9,10 @@
#include "NewKey.h"
#include "MainWindow.h"
#include "lib/pki_evp.h"
#include "widgets/distname.h"
#include "widgets/clicklabel.h"
#include "lib/pkcs11.h"
#include "distname.h"
#include "clicklabel.h"
#include "ItemCombo.h"
#include <QLabel>
#include <QPushButton>
#include <QLineEdit>

View File

@ -16,6 +16,8 @@
#include <QPixmap>
#include <QPushButton>
#include <QValidator>
#include <QMap>
#include <QPair>
#include "MainWindow.h"
#include "v3ext.h"
#include "lib/x509name.h"
@ -69,29 +71,30 @@ NewX509::NewX509(QWidget *parent)
nsImg->setPixmap(*MainWindow::nsImg);
serialNr->setValidator(new QRegExpValidator(QRegExp("[0-9a-fA-F]*"), this));
QStringList strings;
QList<pki_base *> requests;
// are there any useable private keys ?
newKeyDone("");
newKeyDone(NULL);
// any PKCS#10 requests to be used ?
strings = MainWindow::reqs->getDesc();
if (strings.isEmpty()) {
requests = MainWindow::reqs->getAllRequests();
if (requests.isEmpty()) {
fromReqCB->setDisabled(true);
fromReqCB->setChecked(false);
}
else {
reqList->insertItems(0, strings);
reqList->insertPkiItems(requests);
}
on_fromReqCB_clicked();
// How about signing certificates ?
strings = MainWindow::certs->getSignerDesc();
if (strings.isEmpty()) {
QList<pki_base*> issuers = MainWindow::certs->getAllIssuers();
if (issuers.isEmpty()) {
foreignSignRB->setDisabled(true);
} else {
certList->insertItems(0, strings);
certList->insertPkiItems(issuers);
}
#warning "Remove WG_QA_SERIAL finally! :-)"
#ifdef WG_QA_SERIAL
selfQASignRB = new QRadioButton(signerBox);
setTabOrder(serialNr, selfQASignRB);
@ -102,14 +105,13 @@ NewX509::NewX509(QWidget *parent)
l->insertWidget(1, selfQASignRB);
#endif
// set dates to now and now + 1 year
validNumber->setText("1");
validN->setText("1");
validRange->setCurrentIndex(2);
on_applyTime_clicked();
// settings for the templates ....
strings.clear();
strings = MainWindow::temps->getDescPredefs();
tempList->insertItems(0, strings);
QList<pki_base*> templates = MainWindow::temps->getDescPredefs();
tempList->insertPkiItems(templates);
// setup Extended keyusage
foreach(int nid, eku_nid)
@ -276,6 +278,30 @@ NewX509::NewX509(QWidget *parent)
}
if (pki_x509::disable_netscape)
tabWidget->removeTab(4);
// Setup widget <-> Template mapping
#define MAP_LE(name) templateLineEdits[#name] = name;
MAP_LE(subAltName);
MAP_LE(issAltName);
MAP_LE(crlDist);
MAP_LE(nsComment);
MAP_LE(nsBaseUrl);
MAP_LE(nsRevocationUrl);
MAP_LE(nsCARevocationUrl);
MAP_LE(nsRenewalUrl);
MAP_LE(nsCaPolicyUrl);
MAP_LE(nsSslServerName);
MAP_LE(validN);
MAP_LE(basicPath);
#define MAP_CB(name) templateCheckBoxes[#name] = name;
MAP_CB(bcCritical);
MAP_CB(kuCritical);
MAP_CB(ekuCritical);
MAP_CB(subKey);
MAP_CB(authKey);
MAP_CB(validMidn);
MAP_CB(noWellDefinedExpDate);
}
void NewX509::setRequest()
@ -344,18 +370,15 @@ void NewX509::setReqAttributes(pki_x509req *req)
/* Initialize dialog for Template creation */
void NewX509::setTemp(pki_temp *temp)
{
QString text = tr("Create XCA template");
if (temp->getIntName() != "--") {
description->setText(temp->getIntName());
description->setDisabled(true);
text = tr("Edit XCA template");
}
capt->setText(text);
description->setText(temp->getIntName());
capt->setText(tr("Edit XCA template"));
tabWidget->removeTab(0);
privKeyBox->setEnabled(false);
validityBox->setEnabled(false);
setImage(MainWindow::tempImg);
pt = tmpl;
fromTemplate(temp);
comment->setPlainText(temp->getComment());
}
/* Initialize dialog for Certificate creation */
@ -381,17 +404,15 @@ void NewX509::defineTemplate(pki_temp *temp)
/* Select a Request for signing it */
void NewX509::defineRequest(pki_x509req *req)
{
if (!req)
return;
fromReqCB->setEnabled(true);
fromReqCB->setChecked(true);
QString reqname = req->getIntName();
reqList->setCurrentIndex(reqList->findText(reqname));
reqList->setCurrentPkiItem(req);
on_fromReqCB_clicked();
}
/* Preset all values from another request to create a similar one */
void NewX509::fromX509super(pki_x509super *cert_or_req, bool applyTemp)
void NewX509::fromX509super(pki_x509super *cert_or_req)
{
pki_temp *temp = new pki_temp("");
temp->fromCert(cert_or_req);
@ -402,8 +423,7 @@ void NewX509::fromX509super(pki_x509super *cert_or_req, bool applyTemp)
pki_key *key = cert_or_req->getRefKey();
if (key) {
usedKeysToo->setChecked(true);
keyList->setCurrentIndex(private_keys.indexOf(
key->getIntNameWithType()));
keyList->setCurrentPkiItem(key);
}
hashAlgo->setCurrentMD(cert_or_req->getDigest());
@ -434,17 +454,14 @@ void NewX509::fromX509super(pki_x509super *cert_or_req, bool applyTemp)
/* Preset the signing certificate */
void NewX509::defineSigner(pki_x509 *defcert, bool applyTemp)
{
int index;
// suggested from: Andrey Brindeew <abr@abr.pp.ru>
if (defcert && defcert->canSign() ) {
QString name = defcert->getIntName();
foreignSignRB->setChecked(true);
certList->setEnabled(true);
if ((index = certList->findText(name)) >= 0) {
certList->setCurrentIndex(index);
}
if (applyTemp && !defcert->getTemplate().isEmpty()) {
on_applyTemplate_clicked();
if (certList->setCurrentPkiItem(defcert) != -1) {
foreignSignRB->setChecked(true);
certList->setEnabled(true);
if (applyTemp && defcert->getTemplate()) {
on_applyTemplate_clicked();
}
}
}
}
@ -503,39 +520,33 @@ static QString lb2QString(QListWidget *lb)
void NewX509::subjectFromTemplate(pki_temp *temp)
{
if (temp)
setX509name(temp->xname);
setX509name(temp->getSubject());
}
void NewX509::extensionsFromTemplate(pki_temp *temp)
{
if (!temp)
return;
subAltName->setText(temp->subAltName);
issAltName->setText(temp->issAltName);
crlDist->setText(temp->crlDist);
setAuthInfAcc_string(temp->authInfAcc);
nsComment->setText(temp->nsComment);
nsBaseUrl->setText(temp->nsBaseUrl);
nsRevocationUrl->setText(temp->nsRevocationUrl);
nsCARevocationUrl->setText(temp->nsCARevocationUrl);
nsRenewalUrl->setText(temp->nsRenewalUrl);
nsCaPolicyUrl->setText(temp->nsCaPolicyUrl);
nsSslServerName->setText(temp->nsSslServerName);
int2lb(nsCertType, temp->nsCertType);
basicCA->setCurrentIndex(temp->ca);
bcCritical->setChecked(temp->bcCrit);
kuCritical->setChecked(temp->keyUseCrit);
ekuCritical->setChecked(temp->eKeyUseCrit);
subKey->setChecked(temp->subKey);
authKey->setChecked(temp->authKey);
int2lb(keyUsage, temp->keyUse);
QString2lb(ekeyUsage, temp->eKeyUse);
validNumber->setText(QString::number(temp->validN));
validRange->setCurrentIndex(temp->validM);
midnightCB->setChecked(temp->validMidn);
basicPath->setText(temp->pathLen);
nconf_data->document()->setPlainText(temp->adv_ext);
noWellDefinedExpDate->setChecked(temp->noWellDefined);
QMapIterator<QString, QLineEdit*> l(templateLineEdits);
while (l.hasNext()) {
l.next();
l.value()->setText(temp->getSetting(l.key()));
}
QMapIterator<QString, QCheckBox*> i(templateCheckBoxes);
while (i.hasNext()) {
i.next();
i.value()->setChecked(temp->getSettingInt(i.key()));
}
int2lb(nsCertType, temp->getSettingInt("nsCertType"));
basicCA->setCurrentIndex(temp->getSettingInt("ca"));
int2lb(keyUsage, temp->getSettingInt("keyUse"));
QString2lb(ekeyUsage, temp->getSetting("eKeyUse"));
validRange->setCurrentIndex(temp->getSettingInt("validM"));
nconf_data->document()->setPlainText(temp->getSetting("adv_ext"));
setAuthInfAcc_string(temp->getSetting("authInfAcc"));
on_applyTime_clicked();
}
@ -548,39 +559,35 @@ void NewX509::fromTemplate(pki_temp *temp)
void NewX509::toTemplate(pki_temp *temp)
{
temp->setIntName(description->text());
temp->xname = getX509name();
temp->subAltName = subAltName->text();
temp->issAltName = issAltName->text();
temp->crlDist = crlDist->text();
temp->authInfAcc = getAuthInfAcc_string();
temp->nsComment = nsComment->text();
temp->nsBaseUrl = nsBaseUrl->text();
temp->nsRevocationUrl = nsRevocationUrl->text();
temp->nsCARevocationUrl = nsCARevocationUrl->text();
temp->nsRenewalUrl = nsRenewalUrl->text();
temp->nsCaPolicyUrl = nsCaPolicyUrl->text();
temp->nsSslServerName = nsSslServerName->text();
temp->nsCertType = lb2int(nsCertType);
temp->ca = basicCA->currentIndex();
temp->bcCrit = bcCritical->isChecked();
temp->keyUseCrit = kuCritical->isChecked();
temp->eKeyUseCrit = ekuCritical->isChecked();
temp->subKey = subKey->isChecked();
temp->authKey = authKey->isChecked();
temp->keyUse = lb2int(keyUsage);
temp->eKeyUse = lb2QString(ekeyUsage);
temp->validN = validNumber->text().toInt();
temp->validM = validRange->currentIndex();
temp->pathLen = basicPath->text();
if (!temp->pathLen.isEmpty())
temp->pathLen = QString::number(temp->pathLen.toInt());
temp->validMidn = midnightCB->isChecked();
if (nconf_data->isReadOnly()) {
temp->adv_ext = v3ext_backup;
} else {
temp->adv_ext = nconf_data->toPlainText();
temp->setSubject(getX509name());
QMapIterator<QString, QLineEdit*> l(templateLineEdits);
while (l.hasNext()) {
l.next();
temp->setSetting(l.key(), l.value()->text());
}
temp->noWellDefined = noWellDefinedExpDate->isChecked();
QMapIterator<QString, QCheckBox*> i(templateCheckBoxes);
while (i.hasNext()) {
i.next();
temp->setSetting(i.key(), i.value()->isChecked());
}
temp->setSetting("authInfAcc", getAuthInfAcc_string());
temp->setSetting("nsCertType", lb2int(nsCertType));
temp->setSetting("ca", basicCA->currentIndex());
temp->setSetting("keyUse", lb2int(keyUsage));
temp->setSetting("eKeyUse", lb2QString(ekeyUsage));
temp->setSetting("validN", validN->text().toInt());
temp->setSetting("validM", validRange->currentIndex());
if (!temp->getSetting("basicPath").isEmpty())
temp->setSetting("basicPath", temp->getSettingInt("basicPath"));
if (nconf_data->isReadOnly()) {
temp->setSetting("adv_ext", v3ext_backup);
} else {
temp->setSetting("adv_ext", nconf_data->toPlainText());
}
temp->setComment(comment->toPlainText());
}
void NewX509::on_fromReqCB_clicked()
@ -649,8 +656,7 @@ void NewX509::switchHashAlgo()
void NewX509::on_showReqBut_clicked()
{
QString req = reqList->currentText();
emit showReq(req);
emit showReq(reqList->currentPkiItem());
}
void NewX509::on_genKeyBut_clicked()
@ -673,7 +679,7 @@ void NewX509::on_certList_currentIndexChanged(int)
if (!cert)
return;
QString templ = cert->getTemplate();
pki_temp *templ = cert->getTemplate();
snb = cert->getNotBefore();
sna = cert->getNotAfter();
if (snb > notBefore->getDate())
@ -681,10 +687,8 @@ void NewX509::on_certList_currentIndexChanged(int)
if (sna < notAfter->getDate())
notAfter->setDate(sna);
if (templ.isEmpty())
return;
templateChanged(templ);
if (templ)
templateChanged(templ);
}
@ -702,33 +706,46 @@ void NewX509::templateChanged(QString tempname)
void NewX509::templateChanged(pki_temp *templ)
{
QString tempname = templ->getIntName();
templateChanged(tempname);
tempList->setCurrentPkiItem(templ);
}
pki_temp *NewX509::currentTemplate()
{
if (!tempList->isEnabled())
return NULL;
QString name = tempList->currentText();
if (name.isEmpty())
return NULL;
return (pki_temp *)MainWindow::temps->getByName(name);
return static_cast<pki_temp*>(tempList->currentPkiItem());
}
void NewX509::selfComment(QString msg)
{
QString c = comment->toPlainText();
if (!c.endsWith("\n"))
c += "\n";
c += QString("(%1)\n").arg(msg);
comment->setPlainText(c);
}
void NewX509::on_applyTemplate_clicked()
{
fromTemplate(currentTemplate());
pki_temp *t = currentTemplate();
fromTemplate(t);
selfComment(tr("Template '%1' applied").arg(t->comboText()));
}
void NewX509::on_applySubject_clicked()
{
subjectFromTemplate(currentTemplate());
pki_temp *t = currentTemplate();
subjectFromTemplate(t);
selfComment(tr("Subject applied from template '%1'")
.arg(t->comboText()));
}
void NewX509::on_applyExtensions_clicked()
{
extensionsFromTemplate(currentTemplate());
pki_temp *t = currentTemplate();
extensionsFromTemplate(t);
selfComment(tr("Extensions applied from template '%1'")
.arg(t->comboText()));
}
void NewX509::on_foreignSignRB_toggled(bool)
@ -736,51 +753,42 @@ void NewX509::on_foreignSignRB_toggled(bool)
switchHashAlgo();
}
void NewX509::newKeyDone(QString name)
void NewX509::newKeyDone(pki_key *nkey)
{
QStringList keys;
private_keys = MainWindow::keys->get0KeyDesc(true);
private_keys0 = MainWindow::keys->get0KeyDesc(false);
keyList->clear();
if (usedKeysToo->isChecked())
keys = private_keys;
else
keys = private_keys0;
keyList->insertItems(0, keys);
if (name.isEmpty() && keys.count() >0)
name = keys[0];
keyList->setCurrentIndex(keys.indexOf(name));
allKeys = MainWindow::keys->getAllKeys();
unusedKeys= MainWindow::keys->getUnusedKeys();
on_usedKeysToo_toggled(true);
if (nkey) {
selfComment(tr("New key '%1' created")
.arg(nkey->comboText()));
keyList->setCurrentPkiItem(nkey);
} else {
keyList->setCurrentIndex(0);
}
}
void NewX509::on_usedKeysToo_toggled(bool)
{
QString cur = keyList->currentText();
QStringList keys;
pki_base *cur = keyList->currentPkiItem();
keyList->clear();
if (usedKeysToo->isChecked())
keys = private_keys;
else
keys = private_keys0;
keyList->insertItems(0, keys);
keyList->setCurrentIndex(keys.indexOf(cur));
keyList->insertPkiItems(usedKeysToo->isChecked() ?
allKeys : unusedKeys);
keyList->setCurrentPkiItem(cur);
}
pki_key *NewX509::getSelectedKey()
{
QString name = pki_key::removeTypeFromIntName(keyList->currentText());
return (pki_key *)MainWindow::keys->getByName(name);
return (pki_key*)keyList->currentPkiItem();
}
pki_x509 *NewX509::getSelectedSigner()
{
return (pki_x509 *)MainWindow::certs->getByName(certList->currentText());
return (pki_x509 *)certList->currentPkiItem();
}
pki_x509req *NewX509::getSelectedReq()
{
return (pki_x509req *)MainWindow::reqs->getByName(reqList->currentText());
return (pki_x509req *)reqList->currentPkiItem();
}
x509name NewX509::getX509name(int _throw)
@ -848,7 +856,7 @@ void NewX509::setX509name(const x509name &n)
void NewX509::on_applyTime_clicked()
{
notAfter->setDiff(notBefore, validNumber->text().toInt(),
notAfter->setDiff(notBefore, validN->text().toInt(),
validRange->currentIndex());
}

View File

@ -55,13 +55,17 @@ class NewX509: public QDialog, public Ui::NewX509
enum pki_type pt;
void templateChanged(QString templatename);
QString mandatoryDnRemain();
QStringList private_keys, private_keys0, tabnames;
QStringList tabnames;
QList<pki_base*> unusedKeys, allKeys;
pki_x509 *ctx_cert;
QString v3ext_backup;
kvmodel *extDNmodel;
extList getExtDuplicates();
void checkIcon(const QString &text, int nid, QLabel*img);
QString dnEntryByNid(int nid);
void selfComment(QString msg);
QMap<QString, QLineEdit*> templateLineEdits;
QMap<QString, QCheckBox*> templateCheckBoxes;
public:
QRadioButton *selfQASignRB;
@ -119,7 +123,7 @@ class NewX509: public QDialog, public Ui::NewX509
void on_fromReqCB_clicked();
void on_keyList_currentIndexChanged(const QString &);
void on_reqList_currentIndexChanged(const QString &);
void newKeyDone(QString name);
void newKeyDone(pki_key *nkey);
void on_applyTime_clicked();
void on_editSubAlt_clicked();
void on_editIssAlt_clicked();
@ -145,7 +149,7 @@ class NewX509: public QDialog, public Ui::NewX509
signals:
void genKey(QString);
void showReq(QString req);
void showReq(pki_base *req);
};
#endif

View File

@ -18,7 +18,7 @@ Options::Options(MainWindow *parent)
{
mw = parent;
setWindowTitle(tr(XCA_TITLE));
setWindowTitle(XCA_TITLE);
setupUi(this);
foreach(int nid, *MainWindow::dn_nid) {

View File

@ -39,7 +39,7 @@ int PwDialog::execute(pass_info *p, Passwd *passwd, bool write, bool abort)
dlg = new PwDialog(p, write);
if (abort)
dlg->addAbortButton();
ret = dlg->exec();
ret = dlg->exec();
*passwd = dlg->getPass();
delete dlg;
return ret;

70
widgets/XcaDialog.h Normal file
View File

@ -0,0 +1,70 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#ifndef __XCADIALOG_H
#define __XCADIALOG_H
#include <QList>
#include <QDialog>
#include "ui_XcaDialog.h"
#include "lib/db.h"
#include "MainWindow.h"
class XcaDialog : public QDialog, public Ui::XcaDialog
{
QWidget *widg;
public:
XcaDialog(QWidget *parent, enum pki_type type, QWidget *w,
QString t, QString desc) : QDialog(parent)
{
setWindowTitle(XCA_TITLE);
setupUi(this);
QPixmap *icon = NULL;
switch (type) {
case asym_key: icon = MainWindow::keyImg; break;
case x509_req: icon = MainWindow::csrImg; break;
case x509: icon = MainWindow::certImg; break;
case revocation: icon = MainWindow::revImg; break;
case tmpl: icon = MainWindow::tempImg; break;
case smartCard: icon = MainWindow::scardImg; break;
default: break;
}
if (icon)
image->setPixmap(*icon);
content->addWidget(w);
widg = w;
title->setText(t);
if (desc.isEmpty()) {
verticalLayout->removeWidget(description);
delete description;
} else {
description->setText(desc);
}
}
void noSpacer()
{
verticalLayout->removeItem(topSpacer);
verticalLayout->removeItem(bottomSpacer);
delete topSpacer;
delete bottomSpacer;
if (widg)
widg->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Expanding);
}
void aboutDialog(QPixmap *lefticon)
{
QPixmap left = *lefticon;
title->setPixmap(left.scaledToHeight(title->height()));
noSpacer();
resize(560, 400);
buttonBox->setStandardButtons(QDialogButtonBox::Ok);
buttonBox->centerButtons();
}
};
#endif

View File

@ -15,6 +15,10 @@ bool XcaProxyModel::lessThan(const QModelIndex &left,
if (!db)
return QSortFilterProxyModel::lessThan(left, right);
if (left.column() < 0 || right.column() < 0) {
qDebug("BAD COLUMN: %d %d\n", left.column(), right.column());
return true;
}
if (db->isNumericCol(left.column()) &&
db->isNumericCol(right.column()))
{

View File

@ -275,6 +275,12 @@ void XcaTreeView::doubleClick(const QModelIndex &m)
basemodel->showItem(getIndex(m));
}
void XcaTreeView::editComment(void)
{
if (basemodel)
basemodel->editComment(currentIndex());
}
void XcaTreeView::pem2clipboard(void)
{
if (basemodel)
@ -393,9 +399,10 @@ void XcaTreeView::showContextMenu(QContextMenuEvent *e,
menu->addAction(tr("Import"), this, SLOT(load()));
menu->addAction(tr("Paste PEM data"), mainwin, SLOT(pastePem()));
if (indexes.size() == 1)
if (indexes.size() == 1) {
menu->addAction(tr("Rename"), this, SLOT(editIdx()));
menu->addAction(tr("Edit comment"), this, SLOT(editComment()));
}
if (indexes.size() > 0) {
menu->addAction(tr("Delete"), this, SLOT(deleteItems()));
subExport = menu->addMenu(tr("Export"));

View File

@ -64,5 +64,6 @@ class XcaTreeView: public QTreeView
void headerDetails(void);
void columnRemove(void);
void columnsChanged(void);
void editComment(void);
};
#endif

View File

@ -101,10 +101,11 @@ HEADERS += lib/asn1int.h \
widgets/X509SuperTreeView.h \
widgets/XcaHeaderView.h \
widgets/OidResolver.h \
widgets/ItemCombo.h \
widgets/XcaDialog.h \
widgets/XcaProxyModel.h
FORMS += ui/About.ui \
ui/CaProperties.ui \
FORMS += ui/CaProperties.ui \
ui/CertDetail.ui \
ui/CertExtend.ui \
ui/CrlDetail.ui \
@ -120,10 +121,10 @@ FORMS += ui/About.ui \
ui/PwDialog.ui \
ui/Revoke.ui \
ui/SelectToken.ui \
ui/TrustState.ui \
ui/SearchPkcs11.ui \
ui/v3ext.ui \
ui/OidResolver.ui \
ui/XcaDialog.ui \
ui/RevocationList.ui
SOURCES += lib/asn1int.cpp \
@ -138,7 +139,6 @@ SOURCES += lib/asn1int.cpp \
lib/db_x509req.cpp \
lib/db_x509super.cpp \
lib/func.cpp \
lib/import.cpp \
lib/load_obj.cpp \
lib/main.cpp \
lib/oid.cpp \