Refactor context menu

Better support multiple selections
 - Export all selected items into one PEM file
 - Batch Revoke/unrevoke/renew of many selected certificates
   of the same issuer
 - allow exporting templates as PEM

Add Feat. Reg. #83 Option to revoke old certificate when renewing

Always put all signed certificate to the newest CA.
If a CA certificate is renewed, all certificates issued by
the old CA are now shown as signed by the new one.
This commit is contained in:
Christian Hohnstaedt 2015-05-07 18:18:31 +02:00
parent 5b40ac664b
commit 75a6d117f3
53 changed files with 2344 additions and 1405 deletions

View File

@ -160,7 +160,6 @@ $(DMGSTAGE): xca$(SUFFIX) xca_db_stat$(SUFFIX)
ln -s xca.html $(DMGSTAGE)/manual/index.html
$(MACDEPLOYQT) $(DMGSTAGE)/xca.app
codesign -s "Open Source Developer, Christian Hohnstaedt" $(DMGSTAGE)/xca.app
tar zcf $(MACTARGET).tar.gz $(DMGSTAGE)
xca.dmg: $(MACTARGET).dmg

View File

@ -8,7 +8,7 @@ CPPFLAGS += -I$(TOPDIR) -I$(BUILD) -I$(BUILD)/ui
all: .build-stamp
.build-stamp: $(OBJS)
echo $(patsubst %, $(shell pwd)/%, $(OBJS)) > $@
for i in $(patsubst %, $(shell pwd)/%, $(OBJS)); do echo $$i; done > $@
@$(PRINT) " DONE [$(BASENAME)]"
SRCS=$(patsubst %.o, %.cpp, $(OBJS))

View File

@ -97,7 +97,7 @@ int db_base::handleBadEntry(unsigned char *p, db_header_t *head)
size_t l;
db_header_t h;
FILE *fp = fopen(QString2filename(s), "w");
FILE *fp = fopen(QString2filename(s), "wb");
if (!fp) {
throw errorEx(tr("Error opening file: '%1': %2").
arg(s).arg(strerror(errno)), class_name);
@ -287,47 +287,41 @@ void db_base::insertPKI(pki_base *pki)
emit columnsContentChanged();
}
void db_base::delete_ask()
QString db_base::pem2QString(QModelIndexList indexes)
{
if (!currentIdx.isValid())
return;
pki_base *pki = static_cast<pki_base*>(currentIdx.internalPointer());
if (!XCA_OKCANCEL(pki->getMsg(pki_base::msg_delete).arg(pki->getIntName())))
return;
deletePKI();
}
void db_base::pem2clipboard()
{
long l;
const char *p;
exportType::etype format;
QString msg;
format = clipboardFormat(indexes);
foreach(QModelIndex idx, indexes) {
long l;
const char *p;
BIO *bio = BIO_new(BIO_s_mem());
pki_base *pki = static_cast<pki_base*>
(idx.internalPointer());
pki->pem(bio, format);
openssl_error();
l = BIO_get_mem_data(bio, &p);
msg += QString::fromUtf8(p, l);
BIO_free(bio);
}
return msg;
}
void db_base::pem2clipboard(QModelIndexList indexes)
{
QString msg = pem2QString(indexes);
QClipboard *cb = QApplication::clipboard();
BIO *bio = BIO_new(BIO_s_mem());
if (!currentIdx.isValid())
return;
pki_base *pki = static_cast<pki_base*>(currentIdx.internalPointer());
format = clipboardFormat();
pki->pem(bio, format);
openssl_error();
l = BIO_get_mem_data(bio, &p);
msg = QString::fromUtf8(p, l);
BIO_free(bio);
if (cb->supportsSelection())
cb->setText(msg, QClipboard::Selection);
else
cb->setText(msg);
}
void db_base::deletePKI()
void db_base::deletePKI(QModelIndex idx)
{
if (!currentIdx.isValid())
return;
pki_base *pki = static_cast<pki_base*>(currentIdx.internalPointer());
pki_base *pki = static_cast<pki_base*>(idx.internalPointer());
try {
try {
pki->deleteFromToken();
@ -335,7 +329,7 @@ void db_base::deletePKI()
MainWindow::Error(err);
}
remFromCont(currentIdx);
remFromCont(idx);
db mydb(dbName);
mydb.find(pki->getType(), pki->getIntName());
@ -358,84 +352,9 @@ void db_base::updatePKI(pki_base *pki)
}
}
void db_base::deleteSelectedItems(XcaTreeView* view)
{
QModelIndexList indexes = view->getSelectedIndexes();
QModelIndex index;
QString items, msg;
int count = 0;
pki_base *pki = NULL;
if (indexes.count() == 0)
return;
foreach(index, indexes) {
pki = static_cast<pki_base*>(index.internalPointer());
items += "'" + pki->getIntName() + "' ";
count++;
}
if (count == 1)
msg = pki->getMsg(pki_base::msg_delete).arg(pki->getIntName());
else
msg = pki->getMsg(pki_base::msg_delete_multi).arg(count).
arg(items);
if (!XCA_OKCANCEL(msg))
return;
foreach(index, indexes) {
currentIdx = index;
deletePKI();
}
currentIdx = QModelIndex();
}
void db_base::showSelectedItems(XcaTreeView* view)
{
QModelIndexList indexes = view->getSelectedIndexes();
QModelIndex index;
QString items;
foreach(index, indexes) {
currentIdx = index;
showItem();
}
currentIdx = QModelIndex();
}
void db_base::storeSelectedItems(XcaTreeView* view)
{
QModelIndexList list = view->getSelectedIndexes();
if (list.size() == 0)
return;
if (!currentIdx.isValid())
currentIdx = list[0];
store(list);
}
void db_base::store(QModelIndexList list)
{
QModelIndex index;
QString items;
foreach(index, list) {
if (index.column() != 0)
continue;
try {
currentIdx = index;
store();
} catch (errorEx &err) {
MainWindow::Error(err);
}
}
currentIdx = QModelIndex();
}
void db_base::showItem(const QModelIndex &index)
{
showPki(static_cast<pki_key*>(index.internalPointer()));
showPki(static_cast<pki_base*>(index.internalPointer()));
}
void db_base::showItem(const QString name)
@ -542,6 +461,8 @@ QModelIndex db_base::index(int row, int column, const QModelIndex &parent)
QModelIndex db_base::index(pki_base *pki) const
{
if (!pki)
return QModelIndex();
return createIndex(pki->row(), 0, pki);
}
@ -688,18 +609,45 @@ void db_base::load_default(load_base &load)
delete dlgi;
}
void db_base::edit()
void db_base::store(QModelIndexList indexes)
{
if (!currentIdx.isValid())
return;
emit editItem(currentIdx);
}
int ret;
void db_base::showItem()
{
if (!currentIdx.isValid())
xcaWarning msg(mainwin, tr("How to export the %1 selected items").
arg(indexes.size()));
msg.addButton(QMessageBox::Ok)->setText(tr("All in one PEM file"));
msg.addButton(QMessageBox::Apply)->setText(tr("Each item in one file"));
msg.addButton(QMessageBox::Cancel);
ret = msg.exec();
if (ret == QMessageBox::Apply) {
foreach(QModelIndex i, indexes)
store(i);
return;
showItem(currentIdx);
} else if (ret != QMessageBox::Ok) {
return;
}
QString fn = mainwin->getPath() + QDir::separator() + "export.pem";
QString s = QFileDialog::getSaveFileName(mainwin,
tr("Save %1 items in one file as").arg(indexes.size()), fn,
tr("PEM Files( *.pem );; All files ( * )"));
if (s.isEmpty())
return;
s = QDir::convertSeparators(s);
mainwin->setPath(s.mid(0, s.lastIndexOf(QRegExp("[/\\\\]")) ));
try {
QString pem = pem2QString(indexes);
FILE *fp = fopen(QString2filename(s), "wb");
if (!fp) {
throw errorEx(tr("Error opening file: '%1': %2").
arg(s).arg(strerror(errno)), class_name);
}
fwrite(pem.toAscii(), pem.size(), 1, fp);
fclose(fp);
}
catch (errorEx &err) {
MainWindow::Error(err);
}
}
bool db_base::columnHidden(int col) const
@ -723,86 +671,3 @@ bool db_base::isNumericCol(int col) const
{
return allHeaders[col]->isNumeric();
}
void db_base::showHeaderMenu(QContextMenuEvent *e, int sect)
{
contextMenu(e, NULL, sect);
}
void db_base::contextMenu(QContextMenuEvent *e, QMenu *parent, int)
{
int shown = 0;
tipMenu *menu, *dn, *v3ext, *current, *v3ns;
QAction *a, *sep;
dbheader *hd;
menu = new tipMenu(QString(), mainwin);
dn = new tipMenu(tr("Subject entries"), mainwin);
v3ext = new tipMenu(tr("X509v3 Extensions"), mainwin);
v3ns = new tipMenu(tr("Netscape extensions"), mainwin);
menu->addAction(tr("Reset"), this, SLOT(columnResetDefaults()));
sep = menu->addSeparator();
foreach(hd, allHeaders) {
switch (hd->type) {
case dbheader::hd_x509name:
current = dn;
break;
case dbheader::hd_v3ext:
current = v3ext;
break;
case dbheader::hd_v3ext_ns:
if (pki_x509::disable_netscape)
continue;
current = v3ns;
break;
default:
current = menu;
break;
}
a = current->addAction(hd->getName());
a->setCheckable(true);
a->setChecked(hd->show);
a->setToolTip(hd->getTooltip());
hd->action = a;
}
if (!dn->isEmpty() || !v3ext->isEmpty())
menu->insertSeparator(sep);
if (!dn->isEmpty())
menu->insertMenu(sep, dn);
else
delete dn;
if (!v3ext->isEmpty()) {
if (!v3ns->isEmpty()) {
v3ext->addSeparator();
v3ext->addMenu(v3ns);
} else {
delete v3ns;
}
menu->insertMenu(sep, v3ext);
} else {
delete v3ext;
delete v3ns;
}
if (parent) {
parent->addAction(tr("Paste PEM data"), mainwin,
SLOT(pastePem()));
parent->addMenu(menu)->setText(tr("Columns"));
parent->exec(e->globalPos());
} else {
menu->exec(e->globalPos());
}
foreach(hd, allHeaders) {
if (hd->action)
hd->show = hd->action->isChecked();
shown += hd->show ? 1 : 0;
hd->action = NULL;
}
if (!shown)
allHeaders[0]->show = true;
delete menu;
if (parent)
delete parent;
emit updateHeader();
}

View File

@ -45,7 +45,8 @@ class db_base: public QAbstractItemModel
virtual dbheaderList getHeaders();
int colResizing;
int handleBadEntry(unsigned char *p, db_header_t *head);
virtual exportType::etype clipboardFormat() {
virtual exportType::etype clipboardFormat(QModelIndexList indexes)
{
return exportType::Separator;
}
@ -69,9 +70,6 @@ class db_base: public QAbstractItemModel
QPixmap *loadImg(const char *name);
void writeAll(void);
void dump(QString dirname);
virtual void showContextMenu(QContextMenuEvent * ,
const QModelIndex &) {};
QModelIndex index(int row, int column, const QModelIndex &parent)const;
QModelIndex index(pki_base *pki)const;
QModelIndex parent(const QModelIndex &index) const;
@ -82,18 +80,13 @@ class db_base: public QAbstractItemModel
int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
void deleteSelectedItems(XcaTreeView* view);
void showSelectedItems(XcaTreeView *view);
void storeSelectedItems(XcaTreeView *view);
void deleteSelectedItems(QModelIndexList indexes);
void load_default(load_base &load);
void insertChild(pki_base *parent, pki_base *child);
void createSuccess(pki_base *pki);
void showHeaderMenu(QContextMenuEvent *e, int sect);
bool columnHidden(int col) const;
bool isNumericCol(int col) const;
void saveHeaderState();
void contextMenu(QContextMenuEvent *e,
QMenu *parent = NULL, int sect = -1);
void initHeaderView(QHeaderView *hv);
void setVisualIndex(int i, int visualIndex);
bool fixedHeaderSize(int sect);
@ -105,31 +98,31 @@ class db_base: public QAbstractItemModel
{
colResizing--;
}
virtual void store(QModelIndexList list);
virtual void store(QModelIndexList indexes);
virtual void store(QModelIndex index) { };
dbheaderList getAllHeaders() {
return allHeaders;
}
void pem2clipboard(QModelIndexList indexes);
QString pem2QString(QModelIndexList indexes);
void deletePKI(QModelIndex idx);
public slots:
void deletePKI();
void delete_ask();
void edit();
virtual void newItem() { }
virtual void load() { }
void columnResetDefaults();
virtual void showItem();
virtual void store()
{
store(QModelIndexList());
};
virtual void showPki(pki_base *) {};
virtual void showItem(const QModelIndex &index);
virtual void showItem(const QString keyname);
void sectionResized(int i, int, int newSize);
void sortIndicatorChanged(int logicalIndex, Qt::SortOrder order);
void pem2clipboard();
void sortIndicatorChanged(int, Qt::SortOrder);
signals:
void connNewX509(NewX509 *dlg);
void resetHeader();
void updateHeader();
void columnsContentChanged();
void editItem(const QModelIndex &);
};
#endif

View File

@ -78,20 +78,27 @@ void db_crl::inToCont(pki_base *pki)
{
pki_crl *crl = (pki_crl *)pki;
if (crl->getIssuer() == NULL) {
pki_x509 *iss = NULL, *last = NULL;
pki_x509 *iss = NULL, *last = NULL, *newest = NULL;
x509name issname = crl->getSubject();
while ((iss = mainwin->certs->getBySubject(issname, last)) != NULL) {
pki_key *key = iss->getPubKey();
if (key) {
if (crl->verify(key)) {
delete key;
break;
}
if (!key)
continue;
if (!crl->verify(key)) {
delete key;
continue;
}
delete key;
last = iss;
if (!newest) {
newest = iss;
} else {
if (newest->getNotAfter() < iss->getNotAfter())
newest = iss;
}
}
crl->setIssuer(iss);
crl->setIssuer(newest);
}
db_base::inToCont(pki);
}
@ -128,14 +135,13 @@ void db_crl::showPki(pki_base *pki)
}
}
void db_crl::store()
void db_crl::store(QModelIndex index)
{
QList<exportType> types;
if (!currentIdx.isValid())
if (!index.isValid())
return;
pki_crl *crl = static_cast<pki_crl*>(currentIdx.internalPointer());
pki_crl *crl = static_cast<pki_crl*>(index.internalPointer());
if (!crl)
return;
@ -160,6 +166,40 @@ void db_crl::store()
delete dlg;
}
void db_crl::updateRevocations(pki_x509 *cert)
{
x509name issname = cert->getSubject();
x509revList revlist;
pki_crl *latest = NULL;
FOR_ALL_pki(crl, pki_crl) {
if (!(issname == crl->getSubject()))
continue;
pki_key *key = cert->getPubKey();
if (!key)
continue;
if (!crl->verify(key)) {
delete key;
continue;
}
delete key;
pki_x509 *old = crl->getIssuer();
if (!old) {
crl->setIssuer(cert);
} else if (old != cert) {
if (old->getNotAfter() < cert->getNotAfter())
crl->setIssuer(cert);
}
if (!latest || (latest->getCrlNumber() < crl->getCrlNumber()))
latest = crl;
}
if (latest) {
revlist = latest->getRevList();
cert->mergeRevList(revlist);
cert->setCrlNumber(latest->getCrlNumber());
}
}
void db_crl::newItem(pki_x509 *cert)
{
if (!cert)
@ -214,23 +254,3 @@ void db_crl::newItem(pki_x509 *cert)
delete dlg;
return;
}
void db_crl::showContextMenu(QContextMenuEvent *e, const QModelIndex &index)
{
QMenu *menu = new QMenu(mainwin);
currentIdx = index;
QMenu *subExport;
menu->addAction(tr("Import"), this, SLOT(load()));
if (index != QModelIndex()) {
menu->addAction(tr("Rename"), this, SLOT(edit()));
subExport = menu->addMenu(tr("Export"));
subExport->addAction(tr("Clipboard"), this,
SLOT(pem2clipboard()));
subExport->addAction(tr("File"), this, SLOT(store()));
menu->addAction(tr("Delete"), this, SLOT(delete_ask()));
}
contextMenu(e, menu);
currentIdx = QModelIndex();
return;
}

View File

@ -27,15 +27,15 @@ class db_crl: public db_x509name
void revokeCerts(pki_crl *crl);
void inToCont(pki_base *pki);
pki_base *insert(pki_base *item);
void showContextMenu(QContextMenuEvent *e, const QModelIndex &index);
void removeSigner(pki_base *signer);
public slots:
void store();
void store(QModelIndex index);
void load();
void showPki(pki_base *pki);
void newItem(pki_x509 *cert);
signals:
void updateCertView();
void updateRevocations(pki_x509 *cert);
public slots:
void newItem(pki_x509 *cert);
};
#endif

View File

@ -82,7 +82,7 @@ QStringList db_key::get0KeyDesc(bool all)
void db_key::remFromCont(QModelIndex &idx)
{
db_base::remFromCont(idx);
pki_base *pki = static_cast<pki_base*>(currentIdx.internalPointer());
pki_base *pki = static_cast<pki_base*>(idx.internalPointer());
emit delKey((pki_key *)pki);
}
@ -109,9 +109,7 @@ pki_base* db_key::insert(pki_base *item)
XCA_INFO(
tr("The database already contains the public part of the imported key as\n'%1\nand will be completed by the new, private part of the key").arg(oldkey->getIntName()));
lkey->setIntName(oldkey->getIntName());
currentIdx = index(oldkey->row(), 0, QModelIndex());
deletePKI();
currentIdx = QModelIndex();
deletePKI(index(oldkey->row(), 0, QModelIndex()));
}
}
insertPKI(lkey);
@ -187,35 +185,6 @@ void db_key::load(void)
load_default(l);
}
void db_key::toToken()
{
pki_key *key = static_cast<pki_scard*>(currentIdx.internalPointer());
if (!key || !pkcs11::loaded() || key->isToken())
return;
pki_scard *card = NULL;
try {
pkcs11 p11;
slotid slot;
if (!p11.selectToken(&slot, mainwin))
return;
card = new pki_scard(key->getIntName());
card->store_token(slot, key->decryptKey());
QString msg = tr("Shall the original key '%1' be replaced by the key on the token?\nThis will delete the key '%1' and make it unexportable").
arg(key->getIntName());
if (XCA_YESNO(msg)) {
deletePKI();
insertPKI(card);
card = NULL;
}
} catch (errorEx &err) {
mainwin->Error(err);
}
if (card)
delete card;
}
void db_key::showPki(pki_base *pki)
{
pki_evp *key = (pki_evp *)pki;
@ -226,77 +195,35 @@ void db_key::showPki(pki_base *pki)
delete dlg;
}
}
void db_key::showContextMenu(QContextMenuEvent *e, const QModelIndex &index)
exportType::etype db_key::clipboardFormat(QModelIndexList indexes)
{
QMenu *menu = new QMenu(mainwin);
QMenu *subExport;
currentIdx = index;
pki_key *key = static_cast<pki_key*>(currentIdx.internalPointer());
menu->addAction(tr("New Key"), this, SLOT(newItem()));
menu->addAction(tr("Import"), this, SLOT(load()));
if (index != QModelIndex()) {
menu->addAction(tr("Rename"), this, SLOT(edit()));
menu->addAction(tr("Show Details"), this, SLOT(showItem()));
menu->addAction(tr("Delete"), this, SLOT(delete_ask()));
subExport = menu->addMenu(tr("Export"));
subExport->addAction(tr("Clipboard"), this,
SLOT(pem2clipboard()));
subExport->addAction(tr("File"), this, SLOT(store()));
if (key->isPrivKey() && !key->isToken()) {
switch (key->getOwnPass()) {
case pki_key::ptCommon:
menu->addAction(tr("Change password"), this,
SLOT(setOwnPass()));
break;
case pki_key::ptPrivate:
menu->addAction(tr("Reset password"), this,
SLOT(resetOwnPass()));
break;
}
}
if (key->isToken() && pkcs11::loaded()) {
menu->addAction(tr("Change PIN"), this,
SLOT(changePin()));
menu->addAction(tr("Init PIN with SO PIN (PUK)"), this,
SLOT(initPin()));
menu->addAction(tr("Change SO PIN (PUK)"), this,
SLOT(changeSoPin()));
}
if (!key->isToken() && pkcs11::loaded()) {
menu->addAction(tr("Store on Security token"),
this, SLOT(toToken()));
}
}
contextMenu(e, menu);
currentIdx = QModelIndex();
return;
}
exportType::etype db_key::clipboardFormat()
{
QString title = tr("Export public key [%1]");
QList<exportType> types;
bool allPriv = true;
bool allRSADSA = true;
pki_key *key =static_cast<pki_evp*>(currentIdx.internalPointer());
foreach(QModelIndex idx, indexes) {
pki_key *key = static_cast<pki_key*>
(idx.internalPointer());
if (key->isPubKey() || key->isToken())
allPriv = false;
if (key->getKeyType() != EVP_PKEY_RSA &&
key->getKeyType() != EVP_PKEY_DSA)
allRSADSA = false;
}
if (!allPriv && !allRSADSA)
return exportType::PEM_key;
types << exportType(exportType::PEM_key, "pem", tr("PEM public"));
if (key->getKeyType() == EVP_PKEY_RSA ||
key->getKeyType() == EVP_PKEY_DSA)
if (allRSADSA)
types << exportType(exportType::SSH2_public,
"pub", tr("SSH2 public"));
if (!key->isPubKey() && !key->isToken()) {
if (allPriv)
types << exportType(exportType::PEM_private, "pem",
tr("PEM private"));
title = tr("Export private key [%1]");
}
ExportDialog *dlg = new ExportDialog(mainwin,
title.arg(key->getTypeString()), QString(), key,
key->isToken() ? MainWindow::scardImg : MainWindow::keyImg,
types);
tr("Export keys to CLipboard"), QString(), NULL,
MainWindow::keyImg, types);
dlg->filename->setText(tr("Clipboard"));
dlg->filename->setEnabled(false);
@ -308,16 +235,16 @@ exportType::etype db_key::clipboardFormat()
return dlg->type();
}
void db_key::store()
void db_key::store(QModelIndex index)
{
const EVP_CIPHER *enc = NULL;
QString title = tr("Export public key [%1]");
QList<exportType> types;
if (!currentIdx.isValid())
if (!index.isValid())
return;
pki_key *key =static_cast<pki_evp*>(currentIdx.internalPointer());
pki_key *key =static_cast<pki_evp*>(index.internalPointer());
pki_evp *privkey = (pki_evp *)key;
types <<
@ -395,84 +322,15 @@ void db_key::store()
delete dlg;
}
void db_key::setOwnPass()
{
try {
__setOwnPass(pki_key::ptPrivate);
}
catch (errorEx &err) {
mainwin->Error(err);
}
}
void db_key::resetOwnPass()
{
try {
__setOwnPass(pki_key::ptCommon);
}
catch (errorEx &err) {
mainwin->Error(err);
}
}
void db_key::__setOwnPass(enum pki_key::passType x)
void db_key::setOwnPass(QModelIndex idx, enum pki_key::passType x)
{
pki_evp *targetKey;
if (!currentIdx.isValid())
return;
targetKey = static_cast<pki_evp*>(currentIdx.internalPointer());
if (!idx.isValid())
return;
targetKey = static_cast<pki_evp*>(idx.internalPointer());
if (targetKey->isToken()) {
throw errorEx(tr("Tried to change password of a token"));
}
targetKey->setOwnPass(x);
updatePKI(targetKey);
}
void db_key::changePin()
{
pki_scard *scard;
if (!currentIdx.isValid())
return;
scard = static_cast<pki_scard*>(currentIdx.internalPointer());
try {
if (!scard->isToken()) {
throw errorEx(tr("Tried to change PIN of a key"));
}
scard->changePin();
} catch (errorEx &err) {
mainwin->Error(err);
}
}
void db_key::initPin()
{
pki_scard *scard;
if (!currentIdx.isValid())
return;
scard = static_cast<pki_scard*>(currentIdx.internalPointer());
try {
if (!scard->isToken()) {
throw errorEx(tr("Tried to init PIN of a key"));
}
scard->initPin();
} catch (errorEx &err) {
mainwin->Error(err);
}
}
void db_key::changeSoPin()
{
pki_scard *scard;
if (!currentIdx.isValid())
return;
scard = static_cast<pki_scard*>(currentIdx.internalPointer());
try {
if (!scard->isToken()) {
throw errorEx(tr("Tried to change SO PIN of a key"));
}
scard->changeSoPin();
} catch (errorEx &err) {
mainwin->Error(err);
}
}

View File

@ -20,11 +20,10 @@ class QContextMenuEvent;
class db_key: public db_base
{
Q_OBJECT
protected:
virtual dbheaderList getHeaders();
exportType::etype clipboardFormat();
private:
void __setOwnPass(enum pki_key::passType);
exportType::etype clipboardFormat(QModelIndexList indexes);
public:
db_key(QString db, MainWindow *mw);
QStringList getPrivateDesc();
@ -34,20 +33,14 @@ class db_key: public db_base
void remFromCont(QModelIndex &idx);
pki_base* insert(pki_base *item);
void writeAll();
void showContextMenu(QContextMenuEvent * e, const QModelIndex &index);
void setOwnPass(QModelIndex idx, enum pki_key::passType);
public slots:
void newItem();
void newItem(QString name);
void load();
void store();
void store(QModelIndex index);
void showPki(pki_base *pki);
void setOwnPass();
void resetOwnPass();
void changePin();
void initPin();
void changeSoPin();
void toToken();
signals:
void delKey(pki_key *delkey);

View File

@ -145,36 +145,9 @@ void db_temp::newItem()
}
delete temp;
}
void db_temp::changeTemp()
{
if (!currentIdx.isValid())
return;
pki_temp *temp = static_cast<pki_temp*>(currentIdx.internalPointer());
alterTemp(temp);
}
void db_temp::duplicateTemp()
{
if (!currentIdx.isValid())
return;
pki_temp *temp = static_cast<pki_temp*>(currentIdx.internalPointer());
pki_temp *newtemp = new pki_temp(temp);
newtemp->setIntName(newtemp->getIntName() + " " + tr("copy"));
insertPKI(newtemp);
}
bool db_temp::alterTemp(pki_temp *temp)
{
if (!runTempDlg(temp))
return false;
updatePKI(temp);
return true;
}
void db_temp::showPki(pki_base *pki)
{
alterTemp((pki_temp *)pki);
alterTemp(static_cast<pki_temp *>(pki));
}
void db_temp::load()
@ -183,11 +156,12 @@ void db_temp::load()
load_default(l);
}
void db_temp::store()
void db_temp::store(QModelIndex index)
{
if (!currentIdx.isValid())
if (!index.isValid())
return;
pki_temp *temp = static_cast<pki_temp*>(currentIdx.internalPointer());
pki_temp *temp = static_cast<pki_temp*>(index.internalPointer());
QString fn = mainwin->getPath() + QDir::separator() +
temp->getUnderlinedName() + ".xca";
@ -206,48 +180,10 @@ void db_temp::store()
}
}
void db_temp::certFromTemp()
bool db_temp::alterTemp(pki_temp *temp)
{
if (!currentIdx.isValid())
return;
pki_temp *temp = static_cast<pki_temp*>(currentIdx.internalPointer());
emit newCert(temp);
}
void db_temp::reqFromTemp()
{
if (!currentIdx.isValid())
return;
pki_temp *temp = static_cast<pki_temp*>(currentIdx.internalPointer());
emit newReq(temp);
}
void db_temp::alterTemp()
{
if (!currentIdx.isValid())
return;
pki_temp *temp = static_cast<pki_temp*>(currentIdx.internalPointer());
alterTemp(temp);
}
void db_temp::showContextMenu(QContextMenuEvent *e, const QModelIndex &index)
{
QMenu *menu = new QMenu(mainwin);
currentIdx = index;
menu->addAction(tr("New Template"), this, SLOT(newItem()));
menu->addAction(tr("Import"), this, SLOT(load()));
if (index != QModelIndex()) {
menu->addAction(tr("Rename"), this, SLOT(edit()));
menu->addAction(tr("Export"), this, SLOT(store()));
menu->addAction(tr("Change"), this, SLOT(alterTemp()));
menu->addAction(tr("Delete"), this, SLOT(delete_ask()));
menu->addAction(tr("Duplicate"), this, SLOT(duplicateTemp()));
menu->addAction(tr("Create certificate"), this,
SLOT(certFromTemp()));
menu->addAction(tr("Create request"), this, SLOT(reqFromTemp()));
}
contextMenu(e, menu);
currentIdx = QModelIndex();
return;
if (!runTempDlg(temp))
return false;
updatePKI(temp);
return true;
}

View File

@ -15,8 +15,6 @@
#include <QtCore/QObject>
#include <QtGui/QPixmap>
class Mainwin;
class db_temp: public db_x509name
{
Q_OBJECT
@ -31,23 +29,12 @@ class db_temp: public db_x509name
pki_base *newPKI(db_header_t *head = NULL);
bool runTempDlg(pki_temp *temp);
bool alterTemp(pki_temp *temp);
void showContextMenu(QContextMenuEvent *e, const QModelIndex &index);
void fillContextMenu(QMenu *menu, const QModelIndex &index);
pki_base *getByName(QString desc);
QStringList getDescPredefs();
public slots:
void newItem();
void changeTemp();
void showPki(pki_base *pki);
void load();
void store();
void certFromTemp();
void reqFromTemp();
void alterTemp();
void duplicateTemp();
signals:
void newReq(pki_temp *);
void newCert(pki_temp *);
void store(QModelIndex index);
};
#endif

View File

@ -39,7 +39,6 @@ db_x509::db_x509(QString DBfile, MainWindow *mw)
void db_x509::updateAfterCrlLoad(pki_x509 *pki)
{
if (pki->revList.merged) {
fprintf(stderr, "Update '%s'\n", CCHAR(pki->getIntName()));
updatePKI(pki);
pki->revList.merged = false;
}
@ -115,7 +114,7 @@ QStringList db_x509::getSignerDesc()
void db_x509::remFromCont(QModelIndex &idx)
{
int row;
pki_base *pki = static_cast<pki_base*>(currentIdx.internalPointer());
pki_base *pki = static_cast<pki_base*>(idx.internalPointer());
pki_base *parent_pki = pki->getParent();
row = pki->row();
pki_x509 *child;
@ -155,8 +154,6 @@ void db_x509::changeView()
return;
temproot = new pki_base();
mainwin->certView->hide();
mainwin->certView->setModel(NULL);
beginRemoveRows(QModelIndex(), 0, rows -1);
pki_base *pki = rootItem;
pki_base *parent;
@ -181,8 +178,6 @@ void db_x509::changeView()
inToCont(pki);
}
delete temproot;
mainwin->certView->setModel(this);
mainwin->certView->show();
}
void db_x509::calcEffTrust()
@ -191,6 +186,23 @@ void db_x509::calcEffTrust()
pki->calcEffTrust();
}
static bool recursiveSigning(pki_x509 *cert, pki_x509 *client)
{
/* recursive signing check */
for (pki_x509 *s = cert->getSigner(); s; s = s->getSigner()) {
if (s == s->getSigner()) {
return false;
}
if (s == client) {
printf("Recursive signing: '%s' <-> '%s'\n",
CCHAR(s->getIntName()),
CCHAR(cert->getIntName()));
return true;
}
}
return false;
}
void db_x509::inToCont(pki_base *pki)
{
pki_x509 *cert = (pki_x509*)pki;
@ -198,47 +210,68 @@ void db_x509::inToCont(pki_base *pki)
cert->delSigner(cert->getSigner());
findSigner(cert);
pki_base *root = cert->getSigner();
if (!treeview || root == cert)
if (!treeview || root == cert || root == NULL)
root = rootItem;
fprintf(stderr, "INSERT '%s' below '%s'\n",
CCHAR(cert->getIntName()),
CCHAR(root->getIntName()));
insertChild(root, pki);
/* search for dangling certificates, which signer this is */
insertChild(root, cert);
QList<pki_x509 *> childs;
/* Search for another certificate (name and key)
* and use its childs if we are newer */
FOR_ALL_pki(client, pki_x509) {
if (client->getSigner() == NULL) {
if (client->verify(cert) && treeview ) {
int row = client->row();
pki_x509 *s;
/* recursive signing check */
for (s = cert; s; s = s->getSigner()) {
if (s == s->getSigner()) {
s = NULL;
break;
}
if (s == client) {
printf("Recursive signing: '%s' <-> '%s'\n",
CCHAR(client->getIntName()),
CCHAR(cert->getIntName()));
break;
}
}
if (s)
continue;
beginRemoveRows(QModelIndex(), row, row);
rootItem->takeChild(client);
endRemoveRows();
insertChild(pki, client);
client = (pki_x509*)rootItem;
}
if (client == cert)
continue;
if (!client->compareNameAndKey(cert))
continue;
if (cert->getNotAfter() < client->getNotAfter())
continue;
fprintf(stderr, "Other CA '%s' is older then us '%s'\n",
CCHAR(client->getIntName()),
CCHAR(cert->getIntName()));
foreach(pki_base *_child, client->childItems) {
pki_x509 *child = static_cast<pki_x509*>(_child);
child->delSigner(client);
childs << child;
}
}
/* Search rootItem childs, whether they are ours */
foreach(pki_base *_child, rootItem->childItems) {
pki_x509 *child = static_cast<pki_x509*>(_child);
if (child == cert || child->getSigner() == child)
continue;
if (child->verify_only(cert))
childs << child;
}
/* move collected childs to us */
foreach(pki_x509 *child, childs) {
int row;
if (recursiveSigning(cert, child))
continue;
if (!child->verify(cert))
continue;
fprintf(stderr, "MOVE Child '%s' from '%s' to '%s'\n",
CCHAR(child->getIntName()),
CCHAR(child->getParent()->getIntName()),
CCHAR(cert->getIntName()));
row = child->row();
beginRemoveRows(index(child), row, row);
child->getParent()->takeChild(child);
endRemoveRows();
if (treeview)
insertChild(cert, child);
else
insertChild(rootItem, child);
}
findKey(cert);
pki_key *pub = cert->getPubKey();
if (pub) {
QList<pki_x509super *> reqs = mainwin->reqs->findByPubKey(pub);
delete pub;
foreach (pki_x509super *r, reqs) {
foreach(pki_x509super *r, reqs) {
((pki_x509req*)r)->setDone();
}
}
@ -348,6 +381,9 @@ 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;
}
@ -358,18 +394,6 @@ void db_x509::load(void)
load_default(c);
}
void db_x509::loadPKCS12()
{
load_pkcs12 l;
load_default(l);
}
void db_x509::loadPKCS7()
{
load_pkcs7 l;
load_default(l);
}
pki_x509 *db_x509::get1SelectedCert()
{
QModelIndexList indexes = mainwin->certView->getSelectedIndexes();
@ -584,110 +608,29 @@ void db_x509::showPki(pki_base *pki)
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) ),
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::showContextMenu(QContextMenuEvent *e, const QModelIndex &index)
{
QMenu *menu = new QMenu(mainwin);
QMenu *subExport, *subCa, *transform;
QAction *action;
QList<QAction*> scardItems;
bool parentCanSign, canSign, hasScard;
currentIdx = index;
pki_key *privkey;
pki_x509 *cert = static_cast<pki_x509*>(index.internalPointer());
pki_x509 *parent;
menu->addAction(tr("New Certificate"), this, SLOT(newItem()));
menu->addAction(tr("Import"), this, SLOT(load()));
menu->addAction(tr("Import PKCS#12"), this, SLOT(loadPKCS12()));
menu->addAction(tr("Import from PKCS#7"), this, SLOT(loadPKCS7()));
if (index != QModelIndex()) {
privkey = cert->getRefKey();
parent = cert->getSigner();
parentCanSign = parent && parent->canSign() && (parent != cert);
canSign = cert->canSign();
menu->addAction(tr("Rename"), this, SLOT(edit()));
menu->addAction(tr("Show Details"), this, SLOT(showItem()));
subExport = menu->addMenu(tr("Export"));
subExport->addAction(tr("Clipboard"), this,
SLOT(pem2clipboard()));
subExport->addAction(tr("File"), this, SLOT(store()));
scardItems += subExport->addAction(tr("Security token"),
this, SLOT(toToken()));
scardItems += subExport->addAction(tr("Other token"),
this, SLOT(toOtherToken()));
subExport->addAction(tr("OpenSSL config"),
this, SLOT(toOpenssl()));
transform = menu->addMenu(tr("Transform"));
transform->addAction(tr("Public Key"),
this, SLOT(extractPubkey()))->
setEnabled(!privkey);
transform->addAction(tr("Request"),
this, SLOT(toRequest()))->
setEnabled(privkey && privkey->isPrivKey());
transform->addAction(tr("Similar Certificate"),
this, SLOT(toCertificate()));
transform->addAction(tr("Template"), this, SLOT(toTemplate()));
menu->addAction(tr("Delete"), this, SLOT(delete_ask()));
scardItems += menu->addAction(
tr("Delete from Security token"),
this, SLOT(deleteFromToken()));
menu->addAction(tr("Trust"), this,SLOT(setTrust()))->
setEnabled(!cert->isRevoked());
menu->addSeparator();
subCa = menu->addMenu(tr("CA"));
subCa->addAction(tr("Properties"), this, SLOT(caProperties()));
subCa->addAction(tr("Generate CRL"), this, SLOT(genCrl()));
subCa->addAction(tr("Manage revocations"),
this, SLOT(manageRevocations()));
subCa->setEnabled(canSign);
menu->addSeparator();
menu->addAction(tr("Renewal"), this, SLOT(extendCert()))->
setEnabled(parentCanSign);
if (cert->isRevoked()) {
menu->addAction(tr("Unrevoke"),
this, SLOT(unRevoke()))->
setEnabled(parentCanSign);
} else {
menu->addAction(tr("Revoke"), this, SLOT(revoke()))->
setEnabled(parentCanSign);
}
hasScard = pkcs11::loaded();
foreach(action, scardItems)
action->setEnabled(hasScard);
}
contextMenu(e, menu);
currentIdx = QModelIndex();
return;
}
void db_x509::store(QModelIndexList list)
{
QStringList filt;
bool append, chain;
QList<exportType> types, usual;
if (!currentIdx.isValid())
if (list.size() == 0)
return;
pki_x509 *crt = static_cast<pki_x509*>(currentIdx.internalPointer());
pki_x509 *crt = static_cast<pki_x509*>(list[0].internalPointer());
pki_x509 *oldcrt = NULL;
if (!crt)
return;
pki_key *privkey = crt->getRefKey();
pki_evp *pkey;
chain = crt->getSigner() && crt->getSigner() != crt;
@ -905,33 +848,9 @@ void db_x509::writePKCS7(pki_x509 *cert, QString s, exportType::etype type,
}
void db_x509::setMultiTrust(QAbstractItemView* view)
void db_x509::manageRevocations(QModelIndex idx)
{
QItemSelectionModel *selectionModel = view->selectionModel();
QModelIndexList indexes = selectionModel->selectedIndexes();
QString items;
foreach(currentIdx, indexes) {
setTrust();
}
currentIdx = QModelIndex();
}
void db_x509::deleteFromToken()
{
if (!currentIdx.isValid())
return;
pki_x509 *pki = static_cast<pki_x509*>(currentIdx.internalPointer());
try {
pki->deleteFromToken();
} catch (errorEx &err) {
mainwin->Error(err);
}
}
void db_x509::manageRevocations()
{
pki_x509 *cert = static_cast<pki_x509*>(currentIdx.internalPointer());
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
if (!cert)
return;
RevocationList *dlg = new RevocationList(mainwin);
@ -941,51 +860,71 @@ void db_x509::manageRevocations()
if (dlg->exec()) {
cert->setRevocations(dlg->getRevList());
updatePKI(cert);
emit columnsContentChanged();
}
}
void db_x509::setTrust()
void db_x509::setTrust(QModelIndexList indexes)
{
int state, newstate = 0;
int newstate = -1;
Ui::TrustState ui;
pki_x509 *cert = static_cast<pki_x509*>(currentIdx.internalPointer());
if (!cert)
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);
state = cert->getTrust();
if (cert->getSigner() == cert) {
if (state == 1)
state = 0;
ui.trust1->setDisabled(true);
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 (state == 0 ) ui.trust0->setChecked(true);
if (state == 1 ) ui.trust1->setChecked(true);
if (state == 2 ) ui.trust2->setChecked(true);
if (dlg->exec()) {
if (ui.trust0->isChecked()) newstate = 0;
if (ui.trust1->isChecked()) newstate = 1;
if (ui.trust2->isChecked()) newstate = 2;
if (newstate!=state) {
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);
}
}
delete dlg;
}
void db_x509::extendCert()
void db_x509::certRenewal(QModelIndexList indexes)
{
pki_x509 *oldcert = NULL, *signer = NULL, *newcert =NULL;
pki_key *signkey = NULL;
a1time time;
a1int serial;
CertExtend *dlg = NULL;
x509rev r;
bool doRevoke = false;
if (indexes.size() == 0)
return;
QModelIndex idx = indexes[0];
try {
oldcert = static_cast<pki_x509*>(currentIdx.internalPointer());
oldcert = static_cast<pki_x509*>(idx.internalPointer());
if (!oldcert ||
!(signer = oldcert->getSigner()) ||
!(signkey = signer->getRefKey()) ||
@ -997,27 +936,37 @@ void db_x509::extendCert()
delete dlg;
return;
}
newcert = new pki_x509(oldcert);
serial = getUniqueSerial(signer);
if (dlg->revoke->isChecked()) {
Revocation *revoke = new Revocation(mainwin, indexes);
doRevoke = revoke->exec();
r = revoke->getRevocation();
delete revoke;
}
foreach(idx, indexes) {
oldcert = static_cast<pki_x509*>
(idx.internalPointer());
newcert = new pki_x509(oldcert);
serial = getUniqueSerial(signer);
newcert->setRevoked(x509rev());
// change date and serial
newcert->setSerial(serial);
newcert->setNotBefore(dlg->notBefore->getDate());
a1time a;
if (dlg->noWellDefinedExpDate->isChecked())
a.setUndefined();
else
a = dlg->notAfter->getDate();
// change date and serial
newcert->setSerial(serial);
newcert->setNotBefore(dlg->notBefore->getDate());
a1time a;
if (dlg->noWellDefinedExpDate->isChecked())
a.setUndefined();
else
a = dlg->notAfter->getDate();
newcert->setNotAfter(a);
newcert->setNotAfter(a);
// and finally sign the cert
newcert->sign(signkey, oldcert->getDigest());
newcert = (pki_x509 *)insert(newcert);
createSuccess(newcert);
if (dlg->revoke->isChecked())
revoke();
// and finally sign the cert
newcert->sign(signkey, oldcert->getDigest());
newcert = (pki_x509 *)insert(newcert);
createSuccess(newcert);
}
if (doRevoke)
do_revoke(indexes, r);
}
catch (errorEx &err) {
MainWindow::Error(err);
@ -1026,66 +975,98 @@ void db_x509::extendCert()
}
if (dlg)
delete dlg;
emit columnsContentChanged();
}
void db_x509::revoke()
void db_x509::revoke(QModelIndexList indexes)
{
pki_x509 *cert = static_cast<pki_x509*>(currentIdx.internalPointer());
if (!cert)
if (indexes.size() == 0)
return;
Revocation *revoke = new Revocation(mainwin, cert);
Revocation *revoke = new Revocation(mainwin, indexes);
if (revoke->exec()) {
const x509rev r = revoke->getRevocation();
cert->setRevoked(r);
pki_x509 *iss = cert->getSigner();
if (iss) {
x509revList rl(r);
iss->mergeRevList(rl);
updatePKI(iss);
do_revoke(indexes, revoke->getRevocation());
}
emit columnsContentChanged();
}
void db_x509::do_revoke(QModelIndexList indexes, const x509rev &r)
{
pki_x509 *parent = NULL, *cert, *iss;
x509revList revlist;
foreach(QModelIndex idx, indexes) {
cert = static_cast<pki_x509*>(idx.internalPointer());
iss = cert->getSigner();
if (parent == NULL) {
parent = iss;
} else if (parent != iss) {
parent = NULL;
break;
}
}
if (!parent) {
qWarning("%s(%d): Certs have different/no signer\n",
__func__, __LINE__);
}
foreach(QModelIndex idx, indexes) {
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
x509rev rev(r);
rev.setSerial(cert->getSerial());
cert->setRevoked(rev);
revlist << rev;
}
parent->mergeRevList(revlist);
updatePKI(parent);
}
void db_x509::unRevoke()
void db_x509::unRevoke(QModelIndexList indexes)
{
pki_x509 *cert = static_cast<pki_x509*>(currentIdx.internalPointer());
pki_x509 *sig;
int idx;
x509rev rev;
pki_x509 *parent = NULL;
foreach(QModelIndex idx, indexes) {
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
if (!cert)
return;
pki_x509 *iss = cert->getSigner();
if (parent == NULL) {
parent = iss;
} else if (parent != iss) {
parent = NULL;
break;
}
}
if (!parent) {
qWarning("%s(%d): Certs have different/no signer\n",
__func__, __LINE__);
}
foreach(QModelIndex idx, indexes) {
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
int idx;
x509rev rev;
if (!cert)
return;
sig = cert->getSigner();
if (!sig)
return;
cert->setRevoked(x509rev());
rev.setSerial(cert->getSerial());
idx = sig->revList.indexOf(rev);
if (idx != -1)
sig->revList.takeAt(idx);
updatePKI(sig);
cert->setRevoked(x509rev());
rev.setSerial(cert->getSerial());
idx = parent->revList.indexOf(rev);
if (idx != -1)
parent->revList.takeAt(idx);
}
updatePKI(parent);
emit columnsContentChanged();
}
void db_x509::genCrl()
void db_x509::toCertificate(QModelIndex index)
{
pki_x509 *cert = static_cast<pki_x509*>(currentIdx.internalPointer());
mainwin->crls->newItem(cert);
}
void db_x509::toCertificate()
{
pki_x509 *cert = static_cast<pki_x509*>(currentIdx.internalPointer());
pki_x509 *cert = static_cast<pki_x509*>(index.internalPointer());
if (!cert)
return;
if (!cert->getRefKey() && cert->getSigner() != cert)
extractPubkey();
extractPubkey(index);
newCert(cert);
}
void db_x509::toRequest()
void db_x509::toRequest(QModelIndex idx)
{
pki_x509 *cert = static_cast<pki_x509*>(currentIdx.internalPointer());
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
if (!cert)
return;
@ -1102,9 +1083,9 @@ void db_x509::toRequest()
}
}
void db_x509::myToToken(bool alwaysSelect)
void db_x509::toToken(QModelIndex idx, bool alwaysSelect)
{
pki_x509 *cert = static_cast<pki_x509*>(currentIdx.internalPointer());
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
if (!cert)
return;
try {
@ -1114,23 +1095,15 @@ void db_x509::myToToken(bool alwaysSelect)
}
}
void db_x509::toToken()
{
myToToken(false);
}
void db_x509::toOtherToken()
{
myToToken(true);
}
void db_x509::caProperties()
void db_x509::caProperties(QModelIndex idx)
{
Ui::CaProperties ui;
int i;
pki_x509 *cert = static_cast<pki_x509*>(currentIdx.internalPointer());
pki_x509 *cert = static_cast<pki_x509*>(idx.internalPointer());
if (!cert)
return;
QDialog *dlg = new QDialog(mainwin);
ui.setupUi(dlg);
ui.serial->setText(cert->getCaSerial().toHex());

View File

@ -54,34 +54,29 @@ class db_x509: public db_x509super
void writePKCS12(pki_x509 *cert, QString s, bool chain);
void writePKCS7(pki_x509 *cert, QString s,
exportType::etype type, QModelIndexList list);
void showContextMenu(QContextMenuEvent *e, const QModelIndex &index);
void fillContextMenu(QMenu *menu, const QModelIndex &index);
void inToCont(pki_base *pki);
void changeView();
a1int getUniqueSerial(pki_x509 *signer);
void myToToken(bool alwaysSelect);
void toToken(QModelIndex idx, bool alwaysSelect);
void toRequest(QModelIndex idx);
void store(QModelIndexList list);
void showPki(pki_base *pki);
void load();
void caProperties(QModelIndex idx);
void toCertificate(QModelIndex index);
void manageRevocations(QModelIndex idx);
void certRenewal(QModelIndexList indexes);
void revoke(QModelIndexList indexes);
void do_revoke(QModelIndexList indexes, const x509rev &r);
void unRevoke(QModelIndexList indexes);
void setTrust(QModelIndexList indexes);
public slots:
void load(void);
void newItem(void);
void showPki(pki_base *pki);
void setMultiTrust(QAbstractItemView* view);
void setTrust();
void deleteFromToken();
void extendCert();
void revoke();
void unRevoke();
void genCrl();
void caProperties();
void toRequest();
void toCertificate();
void toToken();
void toOtherToken();
void newItem();
void newCert(pki_temp *);
void newCert(pki_x509req *);
void loadPKCS12();
void loadPKCS7();
void manageRevocations();
};
#endif

View File

@ -55,6 +55,11 @@ pki_base *db_x509req::insert(pki_base *item)
return req;
}
void db_x509req::newItem()
{
newItem(NULL, NULL);
}
void db_x509req::newItem(pki_temp *temp, pki_x509req *orig)
{
pki_x509req *req = NULL;
@ -67,7 +72,7 @@ void db_x509req::newItem(pki_temp *temp, pki_x509req *orig)
dlg->fromX509super(orig);
}
dlg->setRequest();
if (! dlg->exec()){
if (!dlg->exec()){
delete dlg;
return;
}
@ -90,10 +95,9 @@ void db_x509req::newItem(pki_temp *temp, pki_x509req *orig)
}
}
void db_x509req::toRequest(void)
void db_x509req::toRequest(QModelIndex index)
{
pki_x509req *req = static_cast<pki_x509req*>
(currentIdx.internalPointer());
pki_x509req *req = static_cast<pki_x509req*>(index.internalPointer());
if (!req)
return;
newItem(NULL, req);
@ -136,16 +140,14 @@ void db_x509req::showPki(pki_base *pki)
}
}
void db_x509req::store()
void db_x509req::store(QModelIndex index)
{
QList<exportType> types;
if (!currentIdx.isValid())
return;
pki_x509req *req = static_cast<pki_x509req*>(currentIdx.internalPointer());
pki_x509req *req = static_cast<pki_x509req*>(index.internalPointer());
if (!req)
return;
types << exportType(exportType::PEM, "pem", "PEM") <<
exportType(exportType::DER, "der", "DER");
@ -167,51 +169,8 @@ void db_x509req::store()
delete dlg;
}
void db_x509req::signReq()
void db_x509req::signReq(QModelIndex index)
{
if (!currentIdx.isValid())
return;
pki_x509req *req = static_cast<pki_x509req*>(currentIdx.internalPointer());
pki_x509req *req = static_cast<pki_x509req*>(index.internalPointer());
emit newCert(req);
}
void db_x509req::showContextMenu(QContextMenuEvent *e, const QModelIndex &index)
{
QMenu *menu = new QMenu(mainwin);
QMenu *subExport, *transform;
currentIdx = index;
pki_x509req *req = static_cast<pki_x509req*>(index.internalPointer());
menu->addAction(tr("New Request"), this, SLOT(newItem()));
menu->addAction(tr("Import"), this, SLOT(load()));
if (index != QModelIndex()) {
menu->addAction(tr("Rename"), this, SLOT(edit()));
menu->addAction(tr("Show Details"), this, SLOT(showItem()));
menu->addAction(tr("Sign"), this, SLOT(signReq()));
subExport = menu->addMenu(tr("Export"));
subExport->addAction(tr("Clipboard"), this,
SLOT(pem2clipboard()));
subExport->addAction(tr("File"), this, SLOT(store()));
subExport->addAction(tr("OpenSSL config"), this,
SLOT(toOpenssl()));
subExport->setEnabled(!req->isSpki());
transform = menu->addMenu(tr("Transform"));
transform->addAction(tr("Template"), this,
SLOT(toTemplate()))->
setEnabled(!req->isSpki());
transform->addAction(tr("Public Key"), this,
SLOT(extractPubkey()))->
setEnabled(!req->getRefKey());
transform->addAction(tr("Similar Request"),
this, SLOT(toRequest()));
menu->addAction(tr("Delete"), this, SLOT(delete_ask()));
}
contextMenu(e, menu);
currentIdx = QModelIndex();
return;
}

View File

@ -24,16 +24,18 @@ class db_x509req: public db_x509super
db_x509req(QString DBfile, MainWindow *mw);
pki_base* insert(pki_base *item);
pki_base *newPKI(db_header_t *head = NULL);
void showContextMenu(QContextMenuEvent *e, const QModelIndex &index);
void fillContextMenu(QMenu *menu, const QModelIndex &index);
void inToCont(pki_base *pki);
void store(QModelIndex index);
void signReq(QModelIndex index);
void toRequest(QModelIndex index);
void load();
void showPki(pki_base *pki);
public slots:
void newItem(pki_temp *temp = NULL, pki_x509req *orig = NULL);
void load();
void store();
void showPki(pki_base *pki);
void signReq();
void toRequest(void);
void newItem(pki_temp *temp, pki_x509req *orig = NULL);
void newItem();
signals:
void newCert(pki_x509req *req);
};

View File

@ -112,10 +112,11 @@ QList<pki_x509super *> db_x509super::findByPubKey(pki_key *refkey)
return list;
}
void db_x509super::extractPubkey()
void db_x509super::extractPubkey(QModelIndex index)
{
pki_key *key;
pki_x509super *pki = static_cast<pki_x509super*>(currentIdx.internalPointer());
pki_x509super *pki = static_cast<pki_x509super*>
(index.internalPointer());
if (!pki)
return;
key = pki->getPubKey();
@ -130,9 +131,9 @@ void db_x509super::extractPubkey()
XCA_INFO(key->getMsg(pki_base::msg_import).arg(pki->getIntName()));
}
void db_x509super::toOpenssl() const
void db_x509super::toOpenssl(QModelIndex index) const
{
pki_x509super *pki = static_cast<pki_x509super*>(currentIdx.internalPointer());
pki_x509super *pki = static_cast<pki_x509super*>(index.internalPointer());
QString fn = mainwin->getPath() + QDir::separator() +
pki->getUnderlinedName() + ".conf";
QString fname = QFileDialog::getSaveFileName(mainwin,
@ -145,9 +146,9 @@ void db_x509super::toOpenssl() const
pki->opensslConf(fname);
}
void db_x509super::toTemplate()
void db_x509super::toTemplate(QModelIndex index)
{
pki_x509super *pki = static_cast<pki_x509super*>(currentIdx.internalPointer());
pki_x509super *pki = static_cast<pki_x509super*>(index.internalPointer());
if (!pki)
return;

View File

@ -34,13 +34,13 @@ class db_x509super: public db_x509name
db_x509super(QString db, 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 extractPubkey();
void toTemplate();
void toOpenssl() const;
};
#endif

View File

@ -269,10 +269,10 @@ bool pki_crl::verify(pki_key *key)
{
bool ret=false;
if (crl && crl->crl && key) {
ret = (X509_CRL_verify(crl , key->getPubKey()) == 1);
ret = (X509_CRL_verify(crl, key->getPubKey()) == 1);
pki_ign_openssl_error();
}
return ret ;
return ret;
}
void pki_crl::setCrlNumber(a1int num)
@ -284,6 +284,14 @@ void pki_crl::setCrlNumber(a1int num)
pki_openssl_error();
}
a1int pki_crl::getCrlNumber()
{
a1int num;
if (!getCrlNumber(&num))
num.set(0L);
return num;
}
bool pki_crl::getCrlNumber(a1int *num)
{
int j;

View File

@ -68,6 +68,7 @@ class pki_crl: public pki_x509name
QByteArray i2d();
void setCrlNumber(a1int num);
bool getCrlNumber(a1int *num);
a1int getCrlNumber();
BIO *pem(BIO *, int);
bool visible();
};

View File

@ -13,6 +13,7 @@
#include "pki_pkcs7.h"
#include "pki_pkcs12.h"
#include "pki_crl.h"
#include "pki_temp.h"
#include "load_obj.h"
#include "exception.h"
#include "func.h"
@ -40,12 +41,12 @@ pki_base *pki_multi::pull()
return multi.takeFirst();
}
#define D5 "-----"
#define BEGIN D5 "BEGIN "
/* General PEM loader */
static pki_base *pkiByPEM(QString text, int *skip)
{
int pos;
#define D5 "-----"
#define BEGIN D5 "BEGIN "
pos = text.indexOf(BEGIN);
if (pos <0) {
if (skip)
@ -74,6 +75,9 @@ static pki_base *pkiByPEM(QString text, int *skip)
if (text.startsWith(PEM_STRING_X509_CRL D5))
return new pki_crl();
if (text.startsWith(PEM_STRING_XCA_TEMPLATE D5))
return new pki_temp();
if (text.startsWith(PEM_STRING_EVP_PKEY D5) ||
text.startsWith(PEM_STRING_PUBLIC D5) ||
text.startsWith(PEM_STRING_RSA D5) ||
@ -155,7 +159,8 @@ void pki_multi::probeAnything(const QString fname)
load_base *lb;
QList<load_base *> lbs;
lbs << new load_cert() << new load_pkcs7() << new load_pkcs12() <<
lbs << new load_pem() <<
new load_cert() << new load_pkcs7() << new load_pkcs12() <<
new load_crl() << new load_req() << new load_key() <<
new load_temp();

View File

@ -251,7 +251,7 @@ void pki_temp::fromData(const unsigned char *p, int size, int version)
eKeyUseCrit = db::boolFromData(ba);
subKey = db::boolFromData(ba);
authKey = db::boolFromData(ba);
ca = db:: intFromData(ba);
ca = db::intFromData(ba);
if (version > 5) {
pathLen = db::stringFromData(ba);
} else {
@ -330,25 +330,113 @@ QByteArray pki_temp::toData()
return ba;
}
void pki_temp::writeDefault(const QString fname)
QByteArray pki_temp::toExportData()
{
writeTemp(fname + QDir::separator() + getIntName() + ".xca");
QByteArray data, header;
data = toData();
header = db::intToData(data.count());
header += db::intToData(dataVersion);
header += data;
return header;
}
void pki_temp::writeTemp(QString fname)
{
QByteArray data, header;
FILE *fp = fopen(QString2filename(fname),"wb");
if (fp == NULL) {
fopen_error(fname);
return;
}
data = toData();
header = db::intToData(data.count());
header += db::intToData(dataVersion);
header += data;
fwrite_ba(fp, header, fname);
fwrite_ba(fp, toExportData(), fname);
fclose(fp);
}
void pki_temp::writeDefault(const QString fname)
{
writeTemp(fname + QDir::separator() + getIntName() + ".xca");
}
BIO *pki_temp::pem(BIO *b, int format)
{
QByteArray ba = toExportData();
if (!b)
b = BIO_new(BIO_s_mem());
PEM_write_bio(b, PEM_STRING_XCA_TEMPLATE, "",
(const unsigned char*)ba.constData(), ba.size());
pki_openssl_error();
return b;
}
void pki_temp::fromExportData(QByteArray data)
{
int size, version;
const int hsize = sizeof(uint32_t);
bool oldimport = false;
if (data.size() < hsize) {
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);
}
}
void pki_temp::try_fload(QString fname, const char *mode)
{
FILE *fp = fopen(QString2filename(fname), mode);
char buf[4096];
QByteArray ba;
BIO *b;
if (fp == NULL) {
fopen_error(fname);
return;
}
b = BIO_new(BIO_s_file());
pki_openssl_error();
BIO_set_fp(b,fp,BIO_NOCLOSE);
try {
fromPEM_BIO(b, fname);
BIO_free(b);
return;
} catch (errorEx &err) {
BIO_free(b);
fseek(fp, 0, SEEK_SET);
}
while (1) {
size_t ret = fread(buf, 1, sizeof buf, fp);
ba.append(buf, ret);
if (ret < sizeof buf)
break;
}
int err = ferror(fp);
fclose(fp);
if (err) {
my_error(tr("Template file content error (too small): %1").
arg(fname));
}
fromExportData(ba);
setIntName(rmslashdot(fname));
fclose(fp);
}
@ -367,58 +455,30 @@ void pki_temp::fload(QString fname)
}
}
void pki_temp::try_fload(QString fname, const char *mode)
void pki_temp::fromPEM_BIO(BIO *bio, QString name)
{
int size, s, version;
const int hsize = 2 * sizeof(uint32_t);
char buf[hsize];
unsigned char *p;
FILE *fp = fopen(QString2filename(fname), mode);
bool oldimport = false;
QByteArray ba;
QString msg;
char *nm = NULL, *header = NULL;
unsigned char *data = NULL;
long len;
if (fp == NULL) {
fopen_error(fname);
return;
PEM_read_bio(bio, &nm, &header, &data, &len);
pki_openssl_error();
if (!strcmp(nm, PEM_STRING_XCA_TEMPLATE)) {
ba = QByteArray::fromRawData((char*)data, len);
fromExportData(ba);
setIntName(rmslashdot(name));
} else {
msg = tr("Not an XCA Template, but '%1'").arg(nm);
}
if (fread(buf, hsize, 1, fp) != 1) {
fclose(fp);
my_error(tr("Template file content error (too small): %1").
arg(fname));
}
QByteArray header(buf, hsize);
QByteArray backup = header;
size = db::intFromData(header);
version = db::intFromData(header);
if (size > 65535 || size <0) {
/* oldimport templates are prepended by its size in host endianess.
Set fp after the first int and recover the size */
fseek(fp, sizeof(int), SEEK_SET);
size = intFromData(backup);
if (size > 65535 || size <0) {
fclose(fp);
my_error(tr("Template file content error (bad size): %1 ").arg(fname));
}
oldimport = true;
}
p = (unsigned char *)OPENSSL_malloc(size);
if (p) {
if ((s=fread(p, 1, size, fp)) != size) {
OPENSSL_free(p);
fclose(fp);
my_error(tr("Template file content error (bad length) :%1").arg(fname));
}
}
if (oldimport)
oldFromData(p, size);
else
fromData(p, size, version);
OPENSSL_free(p);
setIntName(rmslashdot(fname));
fclose(fp);
OPENSSL_free(nm);
OPENSSL_free(header);
OPENSSL_free(data);
if (!msg.isEmpty())
my_error(msg);
}
pki_temp::~pki_temp()
@ -447,7 +507,7 @@ QVariant pki_temp::getIcon(dbheader *hd)
return hd->id == HD_internal_name ? QVariant(*icon) : QVariant();
}
void pki_temp::oldFromData(unsigned char *p, int size)
void pki_temp::oldFromData(const unsigned char *p, int size)
{
int version;

View File

@ -13,6 +13,9 @@
#include "asn1time.h"
#include "pki_x509.h"
#define D5 "-----"
#define PEM_STRING_XCA_TEMPLATE "XCA TEMPLATE"
class pki_temp: public pki_x509name
{
Q_OBJECT
@ -41,7 +44,7 @@ class pki_temp: public pki_x509name
~pki_temp();
void fromData(const unsigned char *p, int size, int version);
void fromData(const unsigned char *p, db_header_t *head );
void oldFromData(unsigned char *p, int size);
void oldFromData(const unsigned char *p, int size);
QByteArray toData();
bool compare(pki_base *ref);
@ -50,6 +53,10 @@ class pki_temp: public pki_x509name
QVariant getIcon(dbheader *hd);
virtual QString getMsg(msg_type msg);
x509name getSubject() const;
BIO *pem(BIO *b, int format);
QByteArray toExportData();
void fromPEM_BIO(BIO *, QString);
void fromExportData(QByteArray data);
};
#endif

View File

@ -194,17 +194,6 @@ a1int pki_x509::hashInfo(const EVP_MD *md) const
return a;
}
a1int pki_x509::getQASerial(const a1int &secret) const
{
ASN1_INTEGER *hold = cert->cert_info->serialNumber;
cert->cert_info->serialNumber = secret.get();
a1int ret = hashInfo(EVP_md5());
ASN1_INTEGER_free(cert->cert_info->serialNumber);
cert->cert_info->serialNumber = hold;
pki_openssl_error();
return ret;
}
void pki_x509::load_token(pkcs11 &p11, CK_OBJECT_HANDLE object)
{
QString desc;
@ -382,11 +371,6 @@ int pki_x509::renameOnToken(slotid slot, QString name)
return 1;
}
bool pki_x509::verifyQASerial(const a1int &secret) const
{
return getQASerial(secret) == getSerial();
}
void pki_x509::setNotBefore(const a1time &a)
{
a1time t(a);
@ -615,13 +599,9 @@ bool pki_x509::cmpIssuerAndSerial(pki_x509 *refcert)
}
bool pki_x509::verify(pki_x509 *signer)
bool pki_x509::verify_only(pki_x509 *signer)
{
if (psigner == signer)
return true;
if ((psigner != NULL )||( signer == NULL))
return false;
X509_NAME *subject = X509_get_subject_name(signer->cert);
X509_NAME *subject = X509_get_subject_name(signer->cert);
X509_NAME *issuer = X509_get_issuer_name(cert);
pki_openssl_error();
if (X509_NAME_cmp(subject, issuer)) {
@ -634,7 +614,16 @@ bool pki_x509::verify(pki_x509 *signer)
}
int i = X509_verify(cert, pub);
pki_ign_openssl_error();
if (i>0) {
return i>0;
}
bool pki_x509::verify(pki_x509 *signer)
{
if (psigner == signer)
return true;
if ((psigner != NULL) || (signer == NULL))
return false;
if (verify_only(signer)) {
int idx;
x509rev r;
r.setSerial(getSerial());
@ -675,6 +664,25 @@ pki_key *pki_x509::getPubKey() const
return key;
}
bool pki_x509::compareNameAndKey(pki_x509 *other)
{
X509_NAME *subject = X509_get_subject_name(other->cert);
X509_NAME *issuer = X509_get_issuer_name(cert);
pki_openssl_error();
if (!subject || !issuer)
return false;
if (X509_NAME_cmp(subject, issuer))
return false;
EVP_PKEY *pub1 = X509_get_pubkey(cert);
EVP_PKEY *pub2 = X509_get_pubkey(other->cert);
pki_ign_openssl_error();
if (!pub1 || !pub2)
return false;
int r = EVP_PKEY_cmp(pub1, pub2);
pki_openssl_error();
return r == 1;
}
void pki_x509::setPubKey(pki_key *key)
{
X509_set_pubkey(cert, key->getPubKey());

View File

@ -57,8 +57,6 @@ class pki_x509 : public pki_x509super
void fromPEM_BIO(BIO *bio, QString name);
void writeDefault(const QString fname);
a1int hashInfo(const EVP_MD *md) const;
a1int getQASerial(const a1int &secret) const;
bool verifyQASerial(const a1int &secret) const;
void setSerial(const a1int &serial);
a1int getSerial() const;
void setNotBefore(const a1time &a);
@ -77,6 +75,7 @@ class pki_x509 : public pki_x509super
bool canSign();
void writeCert(const QString fname, bool PEM, bool append = false);
bool verify(pki_x509 *signer);
bool verify_only(pki_x509 *signer);
pki_key *getPubKey() const;
void setPubKey(pki_key *key);
pki_x509 *getSigner();
@ -113,6 +112,11 @@ class pki_x509 : public pki_x509super
{
return ++crlNumber;
}
void setCrlNumber(a1int n)
{
if (n > crlNumber)
crlNumber = n;
}
void setTemplate(QString s)
{
if (s.length() > 0)
@ -164,6 +168,7 @@ class pki_x509 : public pki_x509super
revList.merge(l);
}
void setRevocations(const x509revList &rl);
bool compareNameAndKey(pki_x509 *other);
};
#endif

View File

@ -52,6 +52,10 @@ class pki_x509super : public pki_x509name
};
virtual QString getSigAlg();
virtual const EVP_MD *getDigest();
virtual bool isSpki() const
{
return false;
}
pki_key *getRefKey() const;
void setRefKey(pki_key *ref);
void delRefKey(pki_key *ref);

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>653</width>
<height>370</height>
<width>589</width>
<height>331</height>
</rect>
</property>
<property name="windowTitle">

View File

@ -12,30 +12,21 @@
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>9</number>
</property>
<item>
<widget class="QTabWidget" name="tabView">
<property name="currentIndex">
<number>0</number>
<number>2</number>
</property>
<widget class="QWidget" name="RSATab">
<attribute name="title">
<string>Private Keys</string>
</attribute>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>8</number>
</property>
<item>
<widget class="XcaTreeView" name="keyView"/>
<widget class="KeyTreeView" name="keyView"/>
</item>
<item>
<widget class="QFrame" name="keyButtons">
@ -133,14 +124,11 @@
<string>Certificate signing requests</string>
</attribute>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>8</number>
</property>
<item>
<widget class="XcaTreeView" name="reqView"/>
<widget class="ReqTreeView" name="reqView"/>
</item>
<item>
<widget class="QFrame" name="reqButtons">
@ -157,9 +145,6 @@
<enum>QFrame::Sunken</enum>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>8</number>
</property>
@ -237,14 +222,11 @@
<string>Certificates</string>
</attribute>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>8</number>
</property>
<item>
<widget class="XcaTreeView" name="certView"/>
<widget class="CertTreeView" name="certView"/>
</item>
<item>
<widget class="QFrame" name="certButtons">
@ -255,9 +237,6 @@
<enum>QFrame::Sunken</enum>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>11</number>
</property>
@ -356,14 +335,11 @@
<string>Templates</string>
</attribute>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>8</number>
</property>
<item>
<widget class="XcaTreeView" name="tempView">
<widget class="TempTreeView" name="tempView">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
@ -378,9 +354,6 @@
<enum>QFrame::Sunken</enum>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>11</number>
</property>
@ -458,12 +431,6 @@
<string>Revocation lists</string>
</attribute>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>9</number>
</property>
<item>
<widget class="XcaTreeView" name="crlView"/>
</item>
@ -476,12 +443,6 @@
<enum>QFrame::Sunken</enum>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>9</number>
</property>
<item>
<widget class="QPushButton" name="BNexportCrl">
<property name="text">
@ -554,8 +515,489 @@
<class>XcaTreeView</class>
<extends>QTreeView</extends>
<header>widgets/XcaTreeView.h</header>
<slots>
<slot>newItem()</slot>
<slot>load()</slot>
<slot>storeItems()</slot>
<slot>showItems()</slot>
<slot>deleteItems()</slot>
</slots>
</customwidget>
<customwidget>
<class>KeyTreeView</class>
<extends>QTreeView</extends>
<header>widgets/KeyTreeView.h</header>
</customwidget>
<customwidget>
<class>TempTreeView</class>
<extends>QTreeView</extends>
<header>widgets/TempTreeView.h</header>
</customwidget>
<customwidget>
<class>ReqTreeView</class>
<extends>QTreeView</extends>
<header>widgets/ReqTreeView.h</header>
</customwidget>
<customwidget>
<class>CertTreeView</class>
<extends>QTreeView</extends>
<header>widgets/CertTreeView.h</header>
<slots>
<slot>loadPKCS12()</slot>
<slot>loadPKCS7()</slot>
<slot>changeView()</slot>
</slots>
</customwidget>
</customwidgets>
<resources/>
<connections/>
<connections>
<connection>
<sender>BNimportKey</sender>
<signal>clicked()</signal>
<receiver>keyView</receiver>
<slot>load()</slot>
<hints>
<hint type="sourcelabel">
<x>505</x>
<y>129</y>
</hint>
<hint type="destinationlabel">
<x>382</x>
<y>135</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNnewKey</sender>
<signal>clicked()</signal>
<receiver>keyView</receiver>
<slot>newItem()</slot>
<hints>
<hint type="sourcelabel">
<x>488</x>
<y>67</y>
</hint>
<hint type="destinationlabel">
<x>392</x>
<y>67</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNexportKey</sender>
<signal>clicked()</signal>
<receiver>keyView</receiver>
<slot>storeItems()</slot>
<hints>
<hint type="sourcelabel">
<x>526</x>
<y>99</y>
</hint>
<hint type="destinationlabel">
<x>393</x>
<y>99</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNdetailsKey</sender>
<signal>clicked()</signal>
<receiver>keyView</receiver>
<slot>showItems()</slot>
<hints>
<hint type="sourcelabel">
<x>473</x>
<y>200</y>
</hint>
<hint type="destinationlabel">
<x>405</x>
<y>200</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNdeleteKey</sender>
<signal>clicked()</signal>
<receiver>keyView</receiver>
<slot>deleteItems()</slot>
<hints>
<hint type="sourcelabel">
<x>470</x>
<y>229</y>
</hint>
<hint type="destinationlabel">
<x>404</x>
<y>230</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNnewReq</sender>
<signal>clicked()</signal>
<receiver>reqView</receiver>
<slot>newItem()</slot>
<hints>
<hint type="sourcelabel">
<x>496</x>
<y>57</y>
</hint>
<hint type="destinationlabel">
<x>371</x>
<y>58</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNexportReq</sender>
<signal>clicked()</signal>
<receiver>reqView</receiver>
<slot>storeItems()</slot>
<hints>
<hint type="sourcelabel">
<x>489</x>
<y>91</y>
</hint>
<hint type="destinationlabel">
<x>400</x>
<y>95</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNimportReq</sender>
<signal>clicked()</signal>
<receiver>reqView</receiver>
<slot>load()</slot>
<hints>
<hint type="sourcelabel">
<x>500</x>
<y>123</y>
</hint>
<hint type="destinationlabel">
<x>412</x>
<y>130</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNdetailsReq</sender>
<signal>clicked()</signal>
<receiver>reqView</receiver>
<slot>showItems()</slot>
<hints>
<hint type="sourcelabel">
<x>497</x>
<y>157</y>
</hint>
<hint type="destinationlabel">
<x>419</x>
<y>166</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNdeleteReq</sender>
<signal>clicked()</signal>
<receiver>reqView</receiver>
<slot>deleteItems()</slot>
<hints>
<hint type="sourcelabel">
<x>475</x>
<y>196</y>
</hint>
<hint type="destinationlabel">
<x>399</x>
<y>196</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNnewCert</sender>
<signal>clicked()</signal>
<receiver>certView</receiver>
<slot>newItem()</slot>
<hints>
<hint type="sourcelabel">
<x>478</x>
<y>63</y>
</hint>
<hint type="destinationlabel">
<x>398</x>
<y>63</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNexportCert</sender>
<signal>clicked()</signal>
<receiver>certView</receiver>
<slot>storeItems()</slot>
<hints>
<hint type="sourcelabel">
<x>499</x>
<y>97</y>
</hint>
<hint type="destinationlabel">
<x>401</x>
<y>99</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNimportCert</sender>
<signal>clicked()</signal>
<receiver>certView</receiver>
<slot>load()</slot>
<hints>
<hint type="sourcelabel">
<x>475</x>
<y>127</y>
</hint>
<hint type="destinationlabel">
<x>401</x>
<y>128</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNdetailsCert</sender>
<signal>clicked()</signal>
<receiver>certView</receiver>
<slot>showItems()</slot>
<hints>
<hint type="sourcelabel">
<x>486</x>
<y>162</y>
</hint>
<hint type="destinationlabel">
<x>395</x>
<y>165</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNdeleteCert</sender>
<signal>clicked()</signal>
<receiver>certView</receiver>
<slot>deleteItems()</slot>
<hints>
<hint type="sourcelabel">
<x>482</x>
<y>203</y>
</hint>
<hint type="destinationlabel">
<x>357</x>
<y>207</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNnewTemp</sender>
<signal>clicked()</signal>
<receiver>tempView</receiver>
<slot>newItem()</slot>
<hints>
<hint type="sourcelabel">
<x>513</x>
<y>60</y>
</hint>
<hint type="destinationlabel">
<x>363</x>
<y>62</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNchangeTemp</sender>
<signal>clicked()</signal>
<receiver>tempView</receiver>
<slot>showItems()</slot>
<hints>
<hint type="sourcelabel">
<x>481</x>
<y>94</y>
</hint>
<hint type="destinationlabel">
<x>415</x>
<y>97</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNdeleteTemp</sender>
<signal>clicked()</signal>
<receiver>tempView</receiver>
<slot>deleteItems()</slot>
<hints>
<hint type="sourcelabel">
<x>482</x>
<y>126</y>
</hint>
<hint type="destinationlabel">
<x>428</x>
<y>126</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNimportTemp</sender>
<signal>clicked()</signal>
<receiver>tempView</receiver>
<slot>load()</slot>
<hints>
<hint type="sourcelabel">
<x>487</x>
<y>165</y>
</hint>
<hint type="destinationlabel">
<x>407</x>
<y>165</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNexportTemp</sender>
<signal>clicked()</signal>
<receiver>tempView</receiver>
<slot>storeItems()</slot>
<hints>
<hint type="sourcelabel">
<x>488</x>
<y>201</y>
</hint>
<hint type="destinationlabel">
<x>428</x>
<y>201</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNexportCrl</sender>
<signal>clicked()</signal>
<receiver>crlView</receiver>
<slot>storeItems()</slot>
<hints>
<hint type="sourcelabel">
<x>472</x>
<y>70</y>
</hint>
<hint type="destinationlabel">
<x>381</x>
<y>70</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNimportCrl</sender>
<signal>clicked()</signal>
<receiver>crlView</receiver>
<slot>load()</slot>
<hints>
<hint type="sourcelabel">
<x>496</x>
<y>99</y>
</hint>
<hint type="destinationlabel">
<x>382</x>
<y>99</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNdetailsCrl</sender>
<signal>clicked()</signal>
<receiver>crlView</receiver>
<slot>showItems()</slot>
<hints>
<hint type="sourcelabel">
<x>477</x>
<y>131</y>
</hint>
<hint type="destinationlabel">
<x>391</x>
<y>131</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNdeleteCrl</sender>
<signal>clicked()</signal>
<receiver>crlView</receiver>
<slot>deleteItems()</slot>
<hints>
<hint type="sourcelabel">
<x>471</x>
<y>173</y>
</hint>
<hint type="destinationlabel">
<x>386</x>
<y>172</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNimportPKCS12</sender>
<signal>clicked()</signal>
<receiver>certView</receiver>
<slot>loadPKCS12()</slot>
<hints>
<hint type="sourcelabel">
<x>504</x>
<y>239</y>
</hint>
<hint type="destinationlabel">
<x>420</x>
<y>234</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNimportPKCS7</sender>
<signal>clicked()</signal>
<receiver>certView</receiver>
<slot>loadPKCS7()</slot>
<hints>
<hint type="sourcelabel">
<x>544</x>
<y>265</y>
</hint>
<hint type="destinationlabel">
<x>406</x>
<y>260</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNimportPFX</sender>
<signal>clicked()</signal>
<receiver>certView</receiver>
<slot>loadPKCS12()</slot>
<hints>
<hint type="sourcelabel">
<x>483</x>
<y>170</y>
</hint>
<hint type="destinationlabel">
<x>230</x>
<y>263</y>
</hint>
</hints>
</connection>
<connection>
<sender>BNviewState</sender>
<signal>clicked()</signal>
<receiver>certView</receiver>
<slot>changeView()</slot>
<hints>
<hint type="sourcelabel">
<x>472</x>
<y>304</y>
</hint>
<hint type="destinationlabel">
<x>402</x>
<y>301</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -124,7 +124,7 @@
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Abort|QDialogButtonBox::Ok</set>
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>

View File

@ -164,8 +164,8 @@
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>236</x>
<y>185</y>
<x>242</x>
<y>277</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
@ -180,12 +180,28 @@
<slot>localTime(int)</slot>
<hints>
<hint type="sourcelabel">
<x>397</x>
<y>122</y>
<x>398</x>
<y>194</y>
</hint>
<hint type="destinationlabel">
<x>389</x>
<y>93</y>
<y>167</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Revoke</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>97</x>
<y>268</y>
</hint>
<hint type="destinationlabel">
<x>109</x>
<y>59</y>
</hint>
</hints>
</connection>

198
widgets/CertTreeView.cpp Normal file
View File

@ -0,0 +1,198 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include "lib/pki_x509.h"
#include "CertTreeView.h"
#include "MainWindow.h"
#include <QtCore/QAbstractItemModel>
#include <QtGui/QAbstractItemView>
#include <QtGui/QMenu>
void CertTreeView::fillContextMenu(QMenu *menu, QMenu *subExport,
const QModelIndex &index, QModelIndexList indexes)
{
QMenu *subCa;
bool parentCanSign, multi, hasScard, sameParent,
allRevoked, allUnrevoked;
pki_key *privkey;
X509SuperTreeView::fillContextMenu(menu, subExport, index, indexes);
menu->addAction(tr("Import PKCS#12"), this, SLOT(loadPKCS12()));
menu->addAction(tr("Import from PKCS#7"), this, SLOT(loadPKCS7()));
if (indexes.size() == 0)
return;
pki_x509 *cert = static_cast<pki_x509*>(index.internalPointer());
pki_x509 *parent;
privkey = cert->getRefKey();
parent = cert->getSigner();
parentCanSign = parent && parent->canSign() && (parent != cert);
hasScard = pkcs11::loaded();
multi = indexes.size() > 1;
allUnrevoked = allRevoked = sameParent = true;
foreach(QModelIndex i, indexes) {
pki_x509 *c = static_cast<pki_x509*>
(i.internalPointer());
if (c->getSigner() != parent)
sameParent = false;
if (c->isRevoked())
allUnrevoked = false;
else
allRevoked = false;
}
if (!multi) {
transform->addAction(tr("Request"), this, SLOT(toRequest()))->
setEnabled(privkey && privkey->isPrivKey());
subExport->addAction(tr("Security token"), this,
SLOT(toToken()))->setEnabled(hasScard);
subExport->addAction(tr("Other token"), this,
SLOT(toOtherToken()))->setEnabled(hasScard);
transform->addAction(tr("Similar Certificate"), this,
SLOT(toCertificate()));
menu->addAction(tr("Delete from Security token"), this,
SLOT(deleteFromToken()))->setEnabled(hasScard);
subCa = menu->addMenu(tr("CA"));
subCa->addAction(tr("Properties"), this, SLOT(caProperties()));
subCa->addAction(tr("Generate CRL"), this, SLOT(genCrl()));
subCa->addAction(tr("Manage revocations"), this,
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()));
if (allUnrevoked)
menu->addAction(tr("Revoke") +n, this, SLOT(revoke()));
if (allRevoked)
menu->addAction(tr("Unrevoke") +n, this,
SLOT(unRevoke()));
}
}
void CertTreeView::changeView()
{
if (!certs)
return;
db_x509 *c = certs;
hide();
setModel();
c->changeView();
setModel(c);
show();
setRootIsDecorated(db_x509::treeview);
}
void CertTreeView::toRequest()
{
if (certs)
certs->toRequest(currentIndex());
}
void CertTreeView::toToken()
{
if (certs)
certs->toToken(currentIndex(), false);
}
void CertTreeView::toOtherToken()
{
if (certs)
certs->toToken(currentIndex(), true);
}
void CertTreeView::loadPKCS12()
{
if (certs) {
load_pkcs12 l;
certs->load_default(l);
}
}
void CertTreeView::loadPKCS7()
{
if (certs) {
load_pkcs7 l;
certs->load_default(l);
}
}
void CertTreeView::genCrl()
{
pki_x509 *cert = static_cast<pki_x509*>
(currentIndex().internalPointer());
mainwin->crls->newItem(cert);
}
void CertTreeView::toCertificate()
{
if (certs)
certs->toCertificate(currentIndex());
}
void CertTreeView::deleteFromToken()
{
pki_x509 *cert = static_cast<pki_x509*>
(currentIndex().internalPointer());
try {
cert->deleteFromToken();
} catch (errorEx &err) {
mainwin->Error(err);
}
}
void CertTreeView::manageRevocations()
{
if (certs)
certs->manageRevocations(currentIndex());
}
void CertTreeView::caProperties()
{
if (certs)
certs->caProperties(currentIndex());
}
void CertTreeView::certRenewal()
{
if (certs)
certs->certRenewal(getSelectedIndexes());
}
void CertTreeView::revoke()
{
if (certs)
certs->revoke(getSelectedIndexes());
}
void CertTreeView::unRevoke()
{
if (certs)
certs->unRevoke(getSelectedIndexes());
}
void CertTreeView::setTrust()
{
if (certs)
certs->setTrust(getSelectedIndexes());
proxy->invalidate();
}

49
widgets/CertTreeView.h Normal file
View File

@ -0,0 +1,49 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#ifndef __CERTTREEVIEW_H
#define __CERTTREEVIEW_H
#include "X509SuperTreeView.h"
#include "lib/db_x509.h"
class CertTreeView: public X509SuperTreeView
{
Q_OBJECT
db_x509 *certs;
public:
CertTreeView(QWidget *parent) : X509SuperTreeView(parent)
{
certs = NULL;
}
void fillContextMenu(QMenu *menu, QMenu *subExport,
const QModelIndex &index, QModelIndexList indexes);
void setModel(db_x509 *model=NULL)
{
certs = model;
X509SuperTreeView::setModel(model);
}
public slots:
void changeView();
void toRequest();
void toCertificate();
void toToken();
void toOtherToken();
void genCrl();
void loadPKCS7();
void loadPKCS12();
void deleteFromToken();
void manageRevocations();
void certRenewal();
void caProperties();
void revoke();
void unRevoke();
void setTrust();
};
#endif

View File

@ -24,13 +24,16 @@ ExportDialog::ExportDialog(MainWindow *mw, QString title, QString filt,
setupUi(this);
mainwin = mw;
setWindowTitle(XCA_TITLE);
descr->setText(pki->getIntName());
if (pki)
descr->setText(pki->getIntName());
descr->setReadOnly(true);
image->setPixmap(*img);
label->setText(title);
QString fn = mainwin->getPath() + QDir::separator() +
pki->getUnderlinedName() + "." + types[0].extension;
filename->setText(fn);
if (pki) {
QString fn = mainwin->getPath() + QDir::separator() +
pki->getUnderlinedName() + "." + types[0].extension;
filename->setText(fn);
}
filter = filt + ";;" + tr("All files ( * )");
foreach(exportType t, types) {

158
widgets/KeyTreeView.cpp Normal file
View File

@ -0,0 +1,158 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include "lib/pki_scard.h"
#include "XcaTreeView.h"
#include "MainWindow.h"
#include <QtCore/QAbstractItemModel>
#include <QtGui/QAbstractItemView>
#include <QtGui/QMenu>
void KeyTreeView::fillContextMenu(QMenu *menu, QMenu *subExport,
const QModelIndex &index, QModelIndexList indexes)
{
bool multi = indexes.size() > 1;
pki_key *key = static_cast<pki_key*>(index.internalPointer());
if (index == QModelIndex())
return;
if (!multi && key && key->isPrivKey() && !key->isToken()) {
switch (key->getOwnPass()) {
case pki_key::ptCommon:
menu->addAction(tr("Change password"), this,
SLOT(setOwnPass()));
break;
case pki_key::ptPrivate:
menu->addAction(tr("Reset password"), this,
SLOT(resetOwnPass()));
break;
}
}
if (!pkcs11::loaded() || multi)
return;
if (key->isToken()) {
menu->addAction(tr("Change PIN"), this,
SLOT(changePin()));
menu->addAction(tr("Init PIN with SO PIN (PUK)"), this,
SLOT(initPin()));
menu->addAction(tr("Change SO PIN (PUK)"), this,
SLOT(changeSoPin()));
} else {
menu->addAction(tr("Store on Security token"),
this, SLOT(toToken()));
}
}
void KeyTreeView::setOwnPass()
{
try {
keys->setOwnPass(currentIndex(), pki_key::ptPrivate);
} catch (errorEx &err) {
mainwin->Error(err);
}
}
void KeyTreeView::resetOwnPass()
{
try {
keys->setOwnPass(currentIndex(), pki_key::ptCommon);
} catch (errorEx &err) {
mainwin->Error(err);
}
}
void KeyTreeView::changePin()
{
pki_scard *scard;
QModelIndex currentIdx = currentIndex();
if (!currentIdx.isValid())
return;
scard = static_cast<pki_scard*>(currentIdx.internalPointer());
try {
if (!scard->isToken()) {
throw errorEx(tr("Tried to change PIN of a key"));
}
scard->changePin();
} catch (errorEx &err) {
mainwin->Error(err);
}
}
void KeyTreeView::initPin()
{
pki_scard *scard;
QModelIndex currentIdx = currentIndex();
if (!currentIdx.isValid())
return;
scard = static_cast<pki_scard*>(currentIdx.internalPointer());
try {
if (!scard->isToken()) {
throw errorEx(tr("Tried to init PIN of a key"));
}
scard->initPin();
} catch (errorEx &err) {
mainwin->Error(err);
}
}
void KeyTreeView::changeSoPin()
{
pki_scard *scard;
QModelIndex currentIdx = currentIndex();
if (!currentIdx.isValid())
return;
scard = static_cast<pki_scard*>(currentIdx.internalPointer());
try {
if (!scard->isToken()) {
throw errorEx(tr("Tried to change SO PIN of a key"));
}
scard->changeSoPin();
} catch (errorEx &err) {
mainwin->Error(err);
}
}
void KeyTreeView::toToken()
{
QModelIndex currentIdx = currentIndex();
if (!currentIdx.isValid())
return;
pki_key *key = static_cast<pki_scard*>(currentIdx.internalPointer());
if (!key || !pkcs11::loaded() || key->isToken())
return;
pki_scard *card = NULL;
try {
pkcs11 p11;
slotid slot;
if (!p11.selectToken(&slot, mainwin))
return;
card = new pki_scard(key->getIntName());
card->store_token(slot, key->decryptKey());
QString msg = tr("Shall the original key '%1' be replaced by the key on the token?\nThis will delete the key '%1' and make it unexportable").
arg(key->getIntName());
if (XCA_YESNO(msg)) {
keys->deletePKI(currentIdx);
keys->insertPKI(card);
card = NULL;
}
} catch (errorEx &err) {
mainwin->Error(err);
}
if (card)
delete card;
}

40
widgets/KeyTreeView.h Normal file
View File

@ -0,0 +1,40 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2006 - 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#ifndef __KEYTREEVIEW_H
#define __KEYTREEVIEW_H
#include "XcaTreeView.h"
#include "lib/db_key.h"
class KeyTreeView: public XcaTreeView
{
Q_OBJECT
db_key *keys;
public:
KeyTreeView(QWidget *parent) : XcaTreeView(parent)
{
keys = NULL;
}
void fillContextMenu(QMenu *menu, QMenu *subExport,
const QModelIndex &index, QModelIndexList indexes);
void setModel(db_key *model=NULL)
{
keys = model;
XcaTreeView::setModel(model);
}
public slots:
void resetOwnPass();
void setOwnPass();
void changePin();
void initPin();
void changeSoPin();
void toToken();
};
#endif

View File

@ -89,9 +89,9 @@ int MainWindow::init_database()
connect( reqs, SIGNAL(newCert(pki_x509req *)),
certs, SLOT(newCert(pki_x509req *)) );
connect( temps, SIGNAL(newCert(pki_temp *)),
connect( tempView, SIGNAL(newCert(pki_temp *)),
certs, SLOT(newCert(pki_temp *)) );
connect( temps, SIGNAL(newReq(pki_temp *)),
connect( tempView, SIGNAL(newReq(pki_temp *)),
reqs, SLOT(newItem(pki_temp *)) );
keyView->setIconSize(pki_evp::icon[0]->size());
@ -298,11 +298,11 @@ void MainWindow::close_database()
statusBar()->removeWidget(searchEdit);
dbindex->clear();
keyView->setModel(NULL);
reqView->setModel(NULL);
certView->setModel(NULL);
tempView->setModel(NULL);
crlView->setModel(NULL);
keyView->setModel();
reqView->setModel();
certView->setModel();
tempView->setModel();
crlView->setModel();
if (crls)
delete(crls);
@ -406,188 +406,3 @@ void MainWindow::update_history(QString fname)
file.close();
update_history_menu();
}
/* Asymetric Key buttons */
void MainWindow::on_BNnewKey_clicked(void)
{
if (keys)
keys->newItem();
}
void MainWindow::on_BNdeleteKey_clicked(void)
{
if (keys)
keys->deleteSelectedItems(keyView);
}
void MainWindow::on_BNdetailsKey_clicked(void)
{
if (keys)
keys->showSelectedItems(keyView);
}
void MainWindow::on_BNimportKey_clicked(void)
{
if (keys)
keys->load();
}
void MainWindow::on_BNexportKey_clicked(void)
{
if (keys)
keys->storeSelectedItems(keyView);
}
void MainWindow::on_keyView_doubleClicked(const QModelIndex &m)
{
if (keys)
keys->showItem(keyView->getIndex(m));
}
void MainWindow::on_reqView_doubleClicked(const QModelIndex &m)
{
if (reqs)
reqs->showItem(reqView->getIndex(m));
}
void MainWindow::on_certView_doubleClicked(const QModelIndex &m)
{
if (certs)
certs->showItem(certView->getIndex(m));
}
void MainWindow::on_tempView_doubleClicked(const QModelIndex &m)
{
if (temps)
temps->showItem(tempView->getIndex(m));
}
void MainWindow::on_crlView_doubleClicked(const QModelIndex &m)
{
if (crls)
crls->showItem(crlView->getIndex(m));
}
void MainWindow::on_BNimportPFX_clicked(void)
{
if (certs)
certs->loadPKCS12();
}
/* Certificate request buttons */
void MainWindow::on_BNnewReq_clicked(void)
{
if (reqs)
reqs->newItem();
}
void MainWindow::on_BNdeleteReq_clicked(void)
{
if (reqs)
reqs->deleteSelectedItems(reqView);
}
void MainWindow::on_BNdetailsReq_clicked(void)
{
if (reqs)
reqs->showSelectedItems(reqView);
}
void MainWindow::on_BNimportReq_clicked(void)
{
if (reqs)
reqs->load();
}
void MainWindow::on_BNexportReq_clicked(void)
{
if(reqs)
reqs->storeSelectedItems(reqView);
}
/* Certificate buttons */
void MainWindow::on_BNnewCert_clicked(void)
{
if (certs)
certs->newItem();
}
void MainWindow::on_BNdeleteCert_clicked(void)
{
if (certs)
certs->deleteSelectedItems(certView);
}
void MainWindow::on_BNdetailsCert_clicked(void)
{
if (certs)
certs->showSelectedItems(certView);
}
void MainWindow::on_BNimportCert_clicked(void)
{
if (certs)
certs->load();
}
void MainWindow::on_BNexportCert_clicked(void)
{
if(certs)
certs->storeSelectedItems(certView);
}
void MainWindow::on_BNimportPKCS12_clicked(void)
{
if(certs)
certs->loadPKCS12();
}
void MainWindow::on_BNimportPKCS7_clicked(void)
{
if(certs)
certs->loadPKCS7();
}
void MainWindow::on_BNviewState_clicked(void)
{
if(certs)
certs->changeView();
certView->setRootIsDecorated(db_x509::treeview);
}
/* Template buttons */
void MainWindow::on_BNdeleteTemp_clicked(void)
{
if (temps)
temps->deleteSelectedItems(tempView);
}
void MainWindow::on_BNchangeTemp_clicked(void)
{
if (temps)
temps->showSelectedItems(tempView);
}
void MainWindow::on_BNimportTemp_clicked(void)
{
if (temps)
temps->load();
}
void MainWindow::on_BNexportTemp_clicked(void)
{
if(temps)
temps->storeSelectedItems(tempView);
}
void MainWindow::on_BNnewTemp_clicked(void)
{
if (temps)
temps->newItem();
}
/* CRL buttons */
void MainWindow::on_BNdeleteCrl_clicked(void)
{
if (crls)
crls->deleteSelectedItems(crlView);
}
void MainWindow::on_BNimportCrl_clicked(void)
{
if (crls)
crls->load();
}
void MainWindow::on_BNexportCrl_clicked(void)
{
if (crls)
crls->storeSelectedItems(crlView);
}
void MainWindow::on_BNdetailsCrl_clicked(void)
{
if(crls)
crls->showSelectedItems(crlView);
}

View File

@ -119,24 +119,15 @@ void MainWindow::init_menu()
file->addAction(a);
import = menuBar()->addMenu(tr("I&mport"));
import->addAction(tr("Keys"), this,
SLOT(on_BNimportKey_clicked()) );
import->addAction(tr("Requests"), this,
SLOT(on_BNimportReq_clicked()) );
import->addAction(tr("Certificates"), this,
SLOT(on_BNimportCert_clicked()) );
import->addAction(tr("PKCS#12"), this,
SLOT(on_BNimportPKCS12_clicked()) );
import->addAction(tr("PKCS#7"), this,
SLOT(on_BNimportPKCS7_clicked()) );
import->addAction(tr("Template"), this,
SLOT(on_BNimportTemp_clicked()) );
import->addAction(tr("Revocation list"), this,
SLOT(on_BNimportCrl_clicked()) );
import->addAction(tr("PEM file"), this,
SLOT(loadPem()) );
import->addAction(tr("paste PEM file"), this,
SLOT(pastePem()) );
import->addAction(tr("Keys"), keyView, SLOT(load()) );
import->addAction(tr("Requests"), reqView, SLOT(load()) );
import->addAction(tr("Certificates"), certView, SLOT(load()) );
import->addAction(tr("PKCS#12"), certView, SLOT(loadPKCS12()) );
import->addAction(tr("PKCS#7"), certView, SLOT(loadPKCS7()) );
import->addAction(tr("Template"), tempView, SLOT(load()) );
import->addAction(tr("Revocation list"), crlView, SLOT(load()));
import->addAction(tr("PEM file"), this, SLOT(loadPem()) );
import->addAction(tr("paste PEM file"), this, SLOT(pastePem()));
token = menuBar()->addMenu(tr("&Token"));
token->addAction(tr("&Manage Security token"), this,

View File

@ -139,22 +139,11 @@ MainWindow::MainWindow(QWidget *parent)
searchEdit = new QLineEdit();
connect(searchEdit, SIGNAL(textChanged(const QString &)),
keyView, SLOT(setFilter(const QString&)));
connect(searchEdit, SIGNAL(textChanged(const QString &)),
reqView, SLOT(setFilter(const QString&)));
connect(searchEdit, SIGNAL(textChanged(const QString &)),
certView, SLOT(setFilter(const QString&)));
connect(searchEdit, SIGNAL(textChanged(const QString &)),
tempView, SLOT(setFilter(const QString&)));
connect(searchEdit, SIGNAL(textChanged(const QString &)),
crlView, SLOT(setFilter(const QString&)));
keyView->setModel(keys);
reqView->setModel(reqs);
certView->setModel(certs);
tempView->setModel(temps);
crlView->setModel(crls);
keyView->setMainwin(this, searchEdit);
reqView->setMainwin(this, searchEdit);
certView->setMainwin(this, searchEdit);
tempView->setMainwin(this, searchEdit);
crlView->setMainwin(this, searchEdit);
}
void MainWindow::dropEvent(QDropEvent *event)

View File

@ -168,44 +168,5 @@ class MainWindow: public QMainWindow, public Ui::MainWindow
void initPin();
void generateDHparam();
void open_database(QAction* a);
void on_keyView_doubleClicked(const QModelIndex &m);
void on_reqView_doubleClicked(const QModelIndex &m);
void on_certView_doubleClicked(const QModelIndex &m);
void on_tempView_doubleClicked(const QModelIndex &m);
void on_crlView_doubleClicked(const QModelIndex &m);
void on_BNnewKey_clicked();
void on_BNdeleteKey_clicked();
void on_BNdetailsKey_clicked();
void on_BNimportKey_clicked();
void on_BNexportKey_clicked();
void on_BNimportPFX_clicked();
void on_BNnewReq_clicked();
void on_BNdeleteReq_clicked();
void on_BNdetailsReq_clicked();
void on_BNimportReq_clicked();
void on_BNexportReq_clicked();
void on_BNnewCert_clicked();
void on_BNdeleteCert_clicked();
void on_BNdetailsCert_clicked();
void on_BNimportCert_clicked();
void on_BNexportCert_clicked();
void on_BNimportPKCS12_clicked();
void on_BNimportPKCS7_clicked();
void on_BNviewState_clicked();
void on_BNnewTemp_clicked();
void on_BNdeleteTemp_clicked();
void on_BNchangeTemp_clicked();
void on_BNimportTemp_clicked();
void on_BNexportTemp_clicked();
void on_BNdeleteCrl_clicked();
void on_BNdetailsCrl_clicked();
void on_BNimportCrl_clicked();
void on_BNexportCrl_clicked();
};
#endif

View File

@ -7,7 +7,8 @@ endif
MOC_NAMES=MainWindow KeyDetail clicklabel XcaTreeView NewX509 \
validity v3ext distname CertDetail CertExtend PwDialog \
ImportMulti CrlDetail ExportDialog hashBox Options NewKey kvView \
NewCrl SearchPkcs11 RevocationList
NewCrl SearchPkcs11 RevocationList XcaProxyModel XcaHeaderView \
KeyTreeView TempTreeView ReqTreeView X509SuperTreeView CertTreeView
NAMES=$(MOC_NAMES) NewX509_ext MW_menu MW_help MW_database
OBJS=$(patsubst %,moc_%.o,$(MOC_NAMES)) $(patsubst %,%.o,$(NAMES))

40
widgets/ReqTreeView.cpp Normal file
View File

@ -0,0 +1,40 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include "lib/pki_x509req.h"
#include "ReqTreeView.h"
#include "MainWindow.h"
#include <QtCore/QAbstractItemModel>
#include <QtGui/QAbstractItemView>
#include <QtGui/QMenu>
void ReqTreeView::fillContextMenu(QMenu *menu, QMenu *subExport,
const QModelIndex &index, QModelIndexList indexes)
{
X509SuperTreeView::fillContextMenu(menu, subExport, index, indexes);
if (indexes.size() != 1)
return;
menu->addAction(tr("Sign"), this, SLOT(signReq()));
if (transform) {
transform->addAction(tr("Similar Request"), this,
SLOT(toRequest()));
}
}
void ReqTreeView::toRequest()
{
if (reqs)
reqs->toRequest(currentIndex());
}
void ReqTreeView::signReq()
{
if (reqs)
reqs->signReq(currentIndex());
}

36
widgets/ReqTreeView.h Normal file
View File

@ -0,0 +1,36 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#ifndef __REQTREEVIEW_H
#define __REQTREEVIEW_H
#include "X509SuperTreeView.h"
#include "lib/db_x509req.h"
class ReqTreeView: public X509SuperTreeView
{
Q_OBJECT
db_x509req *reqs;
public:
ReqTreeView(QWidget *parent) : X509SuperTreeView(parent)
{
reqs = NULL;
}
void fillContextMenu(QMenu *menu, QMenu *subExport,
const QModelIndex &index, QModelIndexList indexes);
void setModel(db_x509req *model=NULL)
{
reqs = model;
X509SuperTreeView::setModel(model);
}
public slots:
void toRequest();
void signReq();
};
#endif

View File

@ -10,22 +10,50 @@
#include "lib/asn1int.h"
#include "lib/pki_x509.h"
enum revCol { Cserial, Cdate, Creason, CiDate };
enum revCol { Cnumber, Cserial, Cdate, Creason, CiDate };
class revListItem : public QTreeWidgetItem
{
public:
revListItem(QTreeWidget *w) : QTreeWidgetItem(w) { };
bool operator < (const QTreeWidgetItem &other) const
{
int col = treeWidget()->sortColumn();
switch (col) {
case Cserial: {
a1int ithis, iother;
ithis.setHex(text(Cserial));
iother.setHex(other.text(Cserial));
return ithis < iother;
}
case Cnumber:
return text(Cnumber).toLong() <
other.text(Cnumber).toLong();
default:
return QTreeWidgetItem::operator < (other);
}
}
};
static void addRevItem(QTreeWidget *certList, const x509rev &revit,
const pki_x509 *iss)
int no, const pki_x509 *iss)
{
QTreeWidgetItem *current;
revListItem *current;
pki_x509 *rev;
a1time a;
rev = iss->getBySerial(revit.getSerial());
current = new QTreeWidgetItem(certList);
current = new revListItem(certList);
if (rev != NULL) {
current->setToolTip(Cserial, rev->getIntName() );
}
current->setText(Cserial, revit.getSerial().toHex()) ;
current->setText(Cnumber, QString("%1").arg(no));
current->setText(Cserial, revit.getSerial().toHex());
current->setText(Cdate, revit.getDate().toSortable());
current->setText(Creason, revit.getReason());
current->setTextAlignment(Cnumber, Qt::AlignRight);
current->setTextAlignment(Cserial, Qt::AlignRight);
a = revit.getInvalDate();
if (!a.isUndefined())
current->setText(CiDate, a.toSortable());
@ -39,7 +67,7 @@ void RevocationList::setupRevocationView(QTreeWidget *certList,
certList->clear();
sl << tr("Serial") << tr("Revocation") << tr("Reason") <<
sl << tr("No.") << tr("Serial") << tr("Revocation") << tr("Reason") <<
tr("Invalidation");
cols = sl.size();
@ -47,9 +75,11 @@ void RevocationList::setupRevocationView(QTreeWidget *certList,
certList->setHeaderLabels(sl);
certList->setItemsExpandable(false);
certList->setRootIsDecorated(false);
certList->sortItems(Cnumber, Qt::AscendingOrder);
i=1;
foreach(x509rev revit, revList) {
addRevItem(certList, revit, iss);
addRevItem(certList, revit, i++, iss);
}
for (i=0; i<cols; i++)
certList->resizeColumnToContents(i);
@ -88,11 +118,11 @@ const x509revList &RevocationList::getRevList()
void RevocationList::on_addRev_clicked(void)
{
Revocation *revoke = new Revocation(this, NULL);
Revocation *revoke = new Revocation(this, QModelIndexList());
if (revoke->exec()) {
x509rev revit = revoke->getRevocation();
revList << revit;
addRevItem(certList, revit, issuer);
addRevItem(certList, revit, revList.size(), issuer);
}
}
@ -114,14 +144,32 @@ void RevocationList::on_delRev_clicked(void)
revList.takeAt(idx);
}
Revocation::Revocation(QWidget *w, pki_x509 *r) : QDialog(w)
Revocation::Revocation(QWidget *w, QModelIndexList indexes) : QDialog(w)
{
setupUi(this);
setWindowTitle(XCA_TITLE);
reason->addItems(x509rev::crlreasons());
invalid->setNow();
if (r) {
serial->setText(r->getSerial().toHex());
if (indexes.size() > 1) {
QList<a1int> serials;
QStringList sl;
serial->setText(QString("Batch revocation of %1 Certificates").
arg(indexes.size()));
foreach(QModelIndex idx, indexes) {
pki_x509 *cert = static_cast<pki_x509*>
(idx.internalPointer());
serials << cert->getSerial();
}
qSort(serials.begin(), serials.end());
foreach(a1int a, serials)
sl << a.toHex();
serial->setToolTip(sl.join("\n"));
serial->setEnabled(false);
} else if (indexes.size() == 1) {
pki_x509 *cert = static_cast<pki_x509*>
(indexes[0].internalPointer());
serial->setText(cert->getSerial().toHex());
serial->setEnabled(false);
}
}

View File

@ -11,6 +11,7 @@
#include "ui_RevocationList.h"
#include "ui_Revoke.h"
#include "lib/x509rev.h"
#include <QtCore/QModelIndex>
class pki_x509;
@ -42,7 +43,7 @@ class Revocation: public QDialog, public Ui::Revoke
Q_OBJECT
public:
Revocation(QWidget *w, pki_x509 *r);
Revocation(QWidget *w, QModelIndexList indexes);
x509rev getRevocation();
};
#endif

55
widgets/TempTreeView.cpp Normal file
View File

@ -0,0 +1,55 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include "lib/pki_temp.h"
#include "XcaTreeView.h"
#include "MainWindow.h"
#include <QtCore/QAbstractItemModel>
#include <QtGui/QAbstractItemView>
#include <QtGui/QMenu>
void TempTreeView::fillContextMenu(QMenu *menu, QMenu *subExport,
const QModelIndex &index, QModelIndexList indexes)
{
if (indexes.size() != 1)
return;
menu->addAction(tr("Duplicate"), this, SLOT(duplicateTemp()));
menu->addAction(tr("Create certificate"), this, SLOT(certFromTemp()));
menu->addAction(tr("Create request"), this, SLOT(reqFromTemp()));
}
void TempTreeView::duplicateTemp()
{
QModelIndex currentIdx = currentIndex();
if (!currentIdx.isValid())
return;
pki_temp *temp = static_cast<pki_temp*>(currentIdx.internalPointer());
pki_temp *newtemp = new pki_temp(temp);
newtemp->setIntName(newtemp->getIntName() + " " + tr("copy"));
temps->insertPKI(newtemp);
}
void TempTreeView::certFromTemp()
{
QModelIndex currentIdx = currentIndex();
if (!currentIdx.isValid())
return;
pki_temp *temp = static_cast<pki_temp*>(currentIdx.internalPointer());
emit newCert(temp);
}
void TempTreeView::reqFromTemp()
{
QModelIndex currentIdx = currentIndex();
if (!currentIdx.isValid())
return;
pki_temp *temp = static_cast<pki_temp*>(currentIdx.internalPointer());
emit newReq(temp);
}

40
widgets/TempTreeView.h Normal file
View File

@ -0,0 +1,40 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2006 - 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#ifndef __TEMPTREEVIEW_H
#define __TEMPTREEVIEW_H
#include "XcaTreeView.h"
#include "lib/db_temp.h"
class TempTreeView: public XcaTreeView
{
Q_OBJECT
db_temp *temps;
public:
TempTreeView(QWidget *parent) : XcaTreeView(parent)
{
temps = NULL;
}
void fillContextMenu(QMenu *menu, QMenu *subExport,
const QModelIndex &index, QModelIndexList indexes);
void setModel(db_temp *model=NULL)
{
temps = model;
XcaTreeView::setModel(model);
}
public slots:
void certFromTemp();
void reqFromTemp();
void duplicateTemp();
signals:
void newReq(pki_temp *);
void newCert(pki_temp *);
};
#endif

View File

@ -0,0 +1,56 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include "lib/pki_x509req.h"
#include "X509SuperTreeView.h"
#include "MainWindow.h"
#include <QtCore/QAbstractItemModel>
#include <QtGui/QAbstractItemView>
#include <QtGui/QMenu>
void X509SuperTreeView::fillContextMenu(QMenu *menu, QMenu *subExport,
const QModelIndex &index, QModelIndexList indexes)
{
pki_x509super *x = static_cast<pki_x509super *>
(index.internalPointer());
transform = NULL;
if (indexes.size() != 1)
return;
subExport->addAction(tr("OpenSSL config"), this, SLOT(toOpenssl()));
subExport->setEnabled(!x->isSpki());
transform = menu->addMenu(tr("Transform"));
transform->addAction(tr("Template"), this,
SLOT(toTemplate()))->setEnabled(!x->isSpki());
transform->addAction(tr("Public Key"), this,
SLOT(extractPubkey()))->setEnabled(!x->getRefKey());
}
void X509SuperTreeView::extractPubkey()
{
QModelIndex idx = currentIndex();
if (idx.isValid() && x509super)
x509super->extractPubkey(idx);
}
void X509SuperTreeView::toTemplate()
{
QModelIndex idx = currentIndex();
if (idx.isValid() && x509super)
x509super->toTemplate(idx);
}
void X509SuperTreeView::toOpenssl()
{
QModelIndex idx = currentIndex();
if (idx.isValid() && x509super)
x509super->toOpenssl(idx);
}

View File

@ -0,0 +1,38 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2006 - 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#ifndef __X509SUPERTREEVIEW_H
#define __X509SUPERTREEVIEW_H
#include "XcaTreeView.h"
#include "lib/db_x509req.h"
class X509SuperTreeView: public XcaTreeView
{
Q_OBJECT
db_x509super *x509super;
public:
QMenu *transform;
X509SuperTreeView(QWidget *parent) : XcaTreeView(parent)
{
x509super = NULL;
}
void fillContextMenu(QMenu *menu, QMenu *subExport,
const QModelIndex &index, QModelIndexList indexes);
void setModel(db_x509super *model=NULL)
{
x509super = model;
XcaTreeView::setModel(model);
}
public slots:
void extractPubkey();
void toTemplate();
void toOpenssl();
};
#endif

33
widgets/XcaHeaderView.cpp Normal file
View File

@ -0,0 +1,33 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include "XcaHeaderView.h"
#include "XcaTreeView.h"
XcaHeaderView::XcaHeaderView()
:QHeaderView(Qt::Horizontal)
{
setMovable(true);
}
void XcaHeaderView::contextMenuEvent(QContextMenuEvent *e)
{
XcaTreeView *tv = static_cast<XcaTreeView *>(parentWidget());
if (tv)
tv->headerEvent(e, logicalIndexAt(e->pos()));
}
void XcaHeaderView::resetMoves()
{
for (int i=0; i<count(); i++) {
if (i != visualIndex(i)) {
moveSection(visualIndex(i), i);
i=0;
}
}
resizeSections(QHeaderView::ResizeToContents);
}

24
widgets/XcaHeaderView.h Normal file
View File

@ -0,0 +1,24 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#ifndef __XCAHEADERVIEW_H
#define __XCAHEADERVIEW_H
#include <QtGui/QHeaderView>
class XcaHeaderView: public QHeaderView
{
Q_OBJECT
public:
XcaHeaderView();
void contextMenuEvent(QContextMenuEvent *e);
public slots:
void resetMoves();
};
#endif

62
widgets/XcaProxyModel.cpp Normal file
View File

@ -0,0 +1,62 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2006 - 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include "XcaProxyModel.h"
#include "lib/db_base.h"
bool XcaProxyModel::lessThan(const QModelIndex &left,
const QModelIndex &right) const
{
db_base *db = (db_base *)sourceModel();
if (!db)
return QSortFilterProxyModel::lessThan(left, right);
if (db->isNumericCol(left.column()) &&
db->isNumericCol(right.column()))
{
int diff;
QString l = sourceModel()->data(left).toString();
QString r = sourceModel()->data(right).toString();
diff = l.size() - r.size();
if (diff<0)
return true;
else if (diff>0)
return false;
else
return l < r;
}
return QSortFilterProxyModel::lessThan(left, right);
}
bool XcaProxyModel::filterAcceptsRow(int sourceRow,
const QModelIndex &sourceParent) const
{
QModelIndex idx = sourceModel()->index(sourceRow, 0, sourceParent);
return sourceModel()->data(idx, Qt::UserRole).toBool();
}
QVariant XcaProxyModel::data(const QModelIndex &index, int role) const
{
QModelIndex i;
QString number;
if (index.column() != 1)
return QSortFilterProxyModel::data(index, role);
/* Row number */
switch (role) {
case Qt::EditRole:
case Qt::DisplayRole:
for (i = index; i.isValid(); i = i.parent())
number += QString(" %1").arg(i.row()+1);
return QVariant(number);
default:
return QSortFilterProxyModel::data(index, role);
}
return QVariant();
}

27
widgets/XcaProxyModel.h Normal file
View File

@ -0,0 +1,27 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2006 - 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#ifndef __XCAPROXYMODEL_H
#define __XCAPROXYMODEL_H
#include <QtGui/QWidget>
#include <QtGui/QItemSelectionModel>
#include <QtGui/QSortFilterProxyModel>
class XcaProxyModel: public QSortFilterProxyModel
{
Q_OBJECT
public:
XcaProxyModel(QWidget *parent = 0)
:QSortFilterProxyModel(parent) { }
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
bool filterAcceptsRow(int sourceRow,
const QModelIndex &sourceParent) const;
QVariant data(const QModelIndex &index, int role) const;
};
#endif

View File

@ -6,12 +6,14 @@
*/
#include "XcaHeaderView.h"
#include "XcaTreeView.h"
#include "lib/db_base.h"
#include "XcaProxyModel.h"
#include "MainWindow.h"
#include <QtCore/QAbstractItemModel>
#include <QtGui/QAbstractItemView>
#include <QtGui/QHeaderView>
#include <QtGui/QContextMenuEvent>
#include <QtGui/QMenu>
#include <QtCore/QVariant>
#include <QtCore/QRegExp>
@ -19,6 +21,7 @@
XcaTreeView::XcaTreeView(QWidget *parent)
:QTreeView(parent)
{
mainwin = NULL;
setHeader(new XcaHeaderView());
setAlternatingRowColors(true);
setSelectionMode(QAbstractItemView::ExtendedSelection);
@ -34,6 +37,8 @@ XcaTreeView::XcaTreeView(QWidget *parent)
basemodel = NULL;
connect(header(), SIGNAL(sectionHandleDoubleClicked(int)),
this, SLOT(resizeColumnToContents(int)));
connect(this, SIGNAL(doubleClicked(const QModelIndex &)),
this, SLOT(doubleClick(const QModelIndex &)));
header()->setClickable(true);
}
@ -48,9 +53,7 @@ void XcaTreeView::contextMenuEvent(QContextMenuEvent * e)
if (!basemodel)
return;
index = indexAt(e->pos());
/* unselect all but the current on context menu */
setCurrentIndex(index);
basemodel->showContextMenu(e, getIndex(index));
showContextMenu(e, getIndex(index));
}
void XcaTreeView::showHideSections()
@ -69,12 +72,18 @@ void XcaTreeView::showHideSections()
columnsResize();
}
void XcaTreeView::setMainwin(MainWindow *mw, QLineEdit *filter)
{
mainwin = mw;
connect(filter, SIGNAL(textChanged(const QString &)),
this, SLOT(setFilter(const QString&)));
}
void XcaTreeView::setModel(QAbstractItemModel *model)
{
QByteArray ba;
basemodel = (db_base *)model;
proxy->setSourceModel(model);
QTreeView::setModel(proxy);
@ -83,8 +92,6 @@ void XcaTreeView::setModel(QAbstractItemModel *model)
header(), SLOT(resetMoves()));
connect(basemodel, SIGNAL(resetHeader()),
this, SLOT(columnsResize()));
connect(basemodel, SIGNAL(updateHeader()),
this, SLOT(showHideSections()));
connect(header(), SIGNAL(sectionMoved(int,int,int)),
this, SLOT(sectionMoved(int,int,int)));
connect(header(), SIGNAL(sectionResized(int,int,int)),
@ -95,8 +102,6 @@ void XcaTreeView::setModel(QAbstractItemModel *model)
this, SLOT(columnsResize()));
connect(basemodel, SIGNAL(columnsContentChanged()),
proxy, SLOT(invalidate()));
connect(basemodel, SIGNAL(editItem(const QModelIndex &)),
this, SLOT(editIdx(const QModelIndex &)));
basemodel->initHeaderView(header());
}
@ -105,7 +110,7 @@ void XcaTreeView::setModel(QAbstractItemModel *model)
void XcaTreeView::headerEvent(QContextMenuEvent *e, int col)
{
basemodel->showHeaderMenu(e, col);
contextMenu(e, NULL, col);
}
QModelIndex XcaTreeView::getIndex(const QModelIndex &index)
@ -158,90 +163,216 @@ void XcaTreeView::sectionMoved(int, int, int)
}
}
void XcaTreeView::editIdx(const QModelIndex &idx)
QModelIndex XcaTreeView::currentIndex()
{
edit(proxy->mapFromSource(idx));
QModelIndex idx = QTreeView::currentIndex();
idx = getIndex(idx);
idx = basemodel->index(idx.row(), 0, idx.parent());
if (!idx.isValid()) {
QModelIndexList l = getSelectedIndexes();
if (l.size() > 0)
idx = l[0];
}
return idx;
}
void XcaTreeView::editIdx()
{
edit(getProxyIndex(currentIndex()));
}
void XcaTreeView::setFilter(const QString &pattern)
{
pki_base::limitPattern = QRegExp(pattern,
pki_base::limitPattern = QRegExp(pattern,
Qt::CaseInsensitive, QRegExp::Wildcard);
// Only to tell the model about the changed filter
proxy->setFilterFixedString(pattern);
proxy->setFilterFixedString(pattern);
}
XcaProxyModel::XcaProxyModel(QWidget *parent)
:QSortFilterProxyModel(parent)
void XcaTreeView::deleteItems(void)
{
}
QModelIndex index;
QModelIndexList indexes = getSelectedIndexes();
QString items, msg;
int count = 0;
pki_base *pki = NULL;
bool XcaProxyModel::lessThan(const QModelIndex &left,
const QModelIndex &right) const
{
db_base *db = (db_base *)sourceModel();
if (!db)
return QSortFilterProxyModel::lessThan(left, right);
if (indexes.count() == 0 || !basemodel)
return;
if (db->isNumericCol(left.column()) &&
db->isNumericCol(right.column()))
{
int diff;
QString l = sourceModel()->data(left).toString();
QString r = sourceModel()->data(right).toString();
diff = l.size() - r.size();
if (diff<0)
return true;
else if (diff>0)
return false;
else
return l < r;
foreach(index, indexes) {
pki = static_cast<pki_base*>(index.internalPointer());
items += "'" + pki->getIntName() + "' ";
count++;
}
return QSortFilterProxyModel::lessThan(left, right);
}
bool XcaProxyModel::filterAcceptsRow(int sourceRow,
const QModelIndex &sourceParent) const
{
QModelIndex idx = sourceModel()->index(sourceRow, 0, sourceParent);
return sourceModel()->data(idx, Qt::UserRole).toBool();
}
if (count == 1)
msg = pki->getMsg(pki_base::msg_delete).arg(pki->getIntName());
else
msg = pki->getMsg(pki_base::msg_delete_multi).arg(count).
arg(items);
QVariant XcaProxyModel::data(const QModelIndex &index, int role) const
{
QModelIndex i;
QString number;
if (!XCA_OKCANCEL(msg))
return;
if (index.column() != 1)
return QSortFilterProxyModel::data(index, role);
/* Row number */
switch (role) {
case Qt::EditRole:
case Qt::DisplayRole:
for (i = index; i.isValid(); i = i.parent())
number += QString(" %1").arg(i.row()+1);
return QVariant(number);
default:
return QSortFilterProxyModel::data(index, role);
foreach(index, indexes) {
basemodel->deletePKI(index);
}
return QVariant();
}
void XcaHeaderView::contextMenuEvent(QContextMenuEvent * e)
void XcaTreeView::storeItems(void)
{
XcaTreeView *tv = (XcaTreeView *)parentWidget();
if (tv)
tv->headerEvent(e, logicalIndexAt(e->pos()));
}
void XcaHeaderView::resetMoves()
{
for (int i=0; i<count(); i++) {
if (i != visualIndex(i)) {
moveSection(visualIndex(i), i);
i=0;
QModelIndexList indexes = getSelectedIndexes();
if (basemodel) {
try {
switch (indexes.size()) {
case 0: return;
case 1: basemodel->store(indexes[0]); return;
default: basemodel->store(getSelectedIndexes());
return;
}
} catch (errorEx &err) {
MainWindow::Error(err);
}
}
resizeSections(QHeaderView::ResizeToContents);
}
void XcaTreeView::showItems(void)
{
if (basemodel) {
QModelIndexList indexes = getSelectedIndexes();
foreach(QModelIndex index, indexes)
basemodel->showItem(index);
}
}
void XcaTreeView::newItem(void)
{
if (basemodel)
basemodel->newItem();
}
void XcaTreeView::load(void)
{
if (basemodel)
basemodel->load();
}
void XcaTreeView::doubleClick(const QModelIndex &m)
{
if (basemodel)
basemodel->showItem(getIndex(m));
}
void XcaTreeView::pem2clipboard(void)
{
if (basemodel)
basemodel->pem2clipboard(getSelectedIndexes());
}
void XcaTreeView::contextMenu(QContextMenuEvent *e, QMenu *parent, int)
{
int shown = 0;
tipMenu *menu, *dn, *v3ext, *current, *v3ns;
QAction *a, *sep;
dbheader *hd;
dbheaderList allHeaders = basemodel->getAllHeaders();
menu = new tipMenu(QString(), mainwin);
dn = new tipMenu(tr("Subject entries"), mainwin);
v3ext = new tipMenu(tr("X509v3 Extensions"), mainwin);
v3ns = new tipMenu(tr("Netscape extensions"), mainwin);
menu->addAction(tr("Reset"), basemodel, SLOT(columnResetDefaults()));
sep = menu->addSeparator();
foreach(hd, allHeaders) {
switch (hd->type) {
case dbheader::hd_x509name:
current = dn;
break;
case dbheader::hd_v3ext:
current = v3ext;
break;
case dbheader::hd_v3ext_ns:
if (pki_x509::disable_netscape)
continue;
current = v3ns;
break;
default:
current = menu;
break;
}
a = current->addAction(hd->getName());
a->setCheckable(true);
a->setChecked(hd->show);
a->setToolTip(hd->getTooltip());
hd->action = a;
}
if (!dn->isEmpty() || !v3ext->isEmpty())
menu->insertSeparator(sep);
if (!dn->isEmpty())
menu->insertMenu(sep, dn);
else
delete dn;
if (!v3ext->isEmpty()) {
if (!v3ns->isEmpty()) {
v3ext->addSeparator();
v3ext->addMenu(v3ns);
} else {
delete v3ns;
}
menu->insertMenu(sep, v3ext);
} else {
delete v3ext;
delete v3ns;
}
if (parent) {
parent->addSeparator();
parent->addMenu(menu)->setText(tr("Columns"));
parent->exec(e->globalPos());
} else {
menu->exec(e->globalPos());
}
foreach(hd, allHeaders) {
if (hd->action)
hd->show = hd->action->isChecked();
shown += hd->show ? 1 : 0;
hd->action = NULL;
}
if (!shown)
allHeaders[0]->show = true;
delete menu;
if (parent)
delete parent;
showHideSections();
}
void XcaTreeView::showContextMenu(QContextMenuEvent *e,
const QModelIndex &idx)
{
QMenu *menu = new QMenu(mainwin);
QMenu *subExport = NULL;
QModelIndexList indexes = getSelectedIndexes();
QModelIndex index;
index = idx.isValid() ? idx : currentIndex();
menu->addAction(tr("New"), this, SLOT(newItem()));
menu->addAction(tr("Import"), this, SLOT(load()));
menu->addAction(tr("Paste PEM data"), mainwin, SLOT(pastePem()));
if (indexes.size() == 1)
menu->addAction(tr("Rename"), this, SLOT(editIdx()));
if (indexes.size() > 0) {
menu->addAction(tr("Delete"), this, SLOT(deleteItems()));
subExport = menu->addMenu(tr("Export"));
subExport->addAction(tr("Clipboard"), this,
SLOT(pem2clipboard()));
subExport->addAction(tr("File"), this, SLOT(storeItems()));
}
fillContextMenu(menu, subExport, index, indexes);
contextMenu(e, menu);
}

View File

@ -8,27 +8,14 @@
#ifndef __XCATREEVIEW_H
#define __XCATREEVIEW_H
#include "lib/db_base.h"
#include <QtGui/QTreeView>
#include <QtGui/QItemSelectionModel>
#include <QtGui/QSortFilterProxyModel>
#include <QtGui/QHeaderView>
#include "lib/db_base.h"
class db_base;
class XcaHeaderView: public QHeaderView
{
Q_OBJECT
public:
XcaHeaderView()
:QHeaderView(Qt::Horizontal)
{
setMovable(true);
}
void contextMenuEvent(QContextMenuEvent *e);
public slots:
void resetMoves();
};
class MainWindow;
class QLineEdit;
class XcaTreeView: public QTreeView
{
@ -36,33 +23,38 @@ class XcaTreeView: public QTreeView
protected:
db_base *basemodel;
QSortFilterProxyModel *proxy;
MainWindow *mainwin;
public:
XcaTreeView(QWidget *parent = 0);
~XcaTreeView();
virtual ~XcaTreeView();
void contextMenuEvent(QContextMenuEvent *e);
void setModel(QAbstractItemModel *model);
virtual void setModel(QAbstractItemModel *model=NULL);
void setMainwin(MainWindow *mw, QLineEdit *filter);
QModelIndex getIndex(const QModelIndex &index);
QModelIndex getProxyIndex(const QModelIndex &index);
QModelIndexList getSelectedIndexes();
void headerEvent(QContextMenuEvent *e, int col);
QModelIndex currentIndex();
void showContextMenu(QContextMenuEvent *e,
const QModelIndex &index);
virtual void fillContextMenu(QMenu *menu, QMenu *subExport,
const QModelIndex &index, QModelIndexList indexes) {}
void contextMenu(QContextMenuEvent *e,
QMenu *parent = NULL, int sect = -1);
public slots:
void showHideSections();
void sectionMoved(int idx, int oldI, int newI);
void columnsResize();
void editIdx(const QModelIndex &idx);
void editIdx();
void setFilter(const QString &pattern);
void deleteItems(void);
void storeItems(void);
void showItems(void);
void newItem(void);
void doubleClick(const QModelIndex &m);
void load(void);
void pem2clipboard(void);
};
class XcaProxyModel: public QSortFilterProxyModel
{
Q_OBJECT
public:
XcaProxyModel(QWidget *parent = 0);
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
bool filterAcceptsRow(int sourceRow,
const QModelIndex &sourceParent) const;
QVariant data(const QModelIndex &index, int role) const;
};
#endif

18
xca.pro
View File

@ -82,7 +82,14 @@ HEADERS += local.h \
widgets/validity.h \
widgets/SearchPkcs11.h \
widgets/RevocationList.h \
widgets/XcaTreeView.h
widgets/XcaTreeView.h \
widgets/CertTreeView.h \
widgets/KeyTreeView.h \
widgets/ReqTreeView.h \
widgets/TempTreeView.h \
widgets/X509SuperTreeView.h \
widgets/XcaHeaderView.h \
widgets/XcaProxyModel.h
FORMS += ui/About.ui \
ui/CaProperties.ui \
@ -168,6 +175,13 @@ SOURCES += lib/asn1int.cpp \
widgets/validity.cpp \
widgets/SearchPkcs11.cpp \
widgets/RevocationList.cpp \
widgets/XcaTreeView.cpp
widgets/XcaTreeView.cpp \
widgets/CertTreeView.cpp \
widgets/KeyTreeView.cpp \
widgets/ReqTreeView.cpp \
widgets/TempTreeView.cpp \
widgets/X509SuperTreeView.cpp \
widgets/XcaHeaderView.cpp \
widgets/XcaProxyModel.cpp
TRANSLATIONS += lang/xca_de.ts lang/xca_es.ts lang/xca_ru.ts lang/xca.ts lang/xca_tr.ts lang/xca_fr.ts lang/xca_hr.ts