xca/widgets/KeyTreeView.cpp
Christian Hohnstädt 6ea01e80f6 Refactor item export: separate GUI and database
Collect all export formats in pki_export.

Each export format has assigned acouple of flags, indicating,
whether they are text, concatenateable, encrypted, usable for
multiple selections or only for a single item.
2021-11-13 14:49:02 +01:00

236 lines
5.0 KiB
C++

/* vi: set sw=4 ts=4:
*
* Copyright (C) 2020 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include "lib/pki_scard.h"
#include "lib/load_obj.h"
#include "KeyTreeView.h"
#include "MainWindow.h"
#include "KeyDetail.h"
#include "NewKey.h"
#include "ExportDialog.h"
#include "XcaWarning.h"
#include <QAbstractItemView>
#include <QMenu>
void KeyTreeView::fillContextMenu(QMenu *menu, QMenu *subExport,
const QModelIndex &index, QModelIndexList indexes)
{
QMenu *clipboard;
QAction *a;
bool multi = indexes.size() > 1;
QActionGroup *group = new QActionGroup(menu);
pki_key *key = db_base::fromIndex<pki_key>(index);
int exp_type = Settings["KeyFormat"];
const pki_export *x;
clipboard = menu->addMenu(tr("Clipboard format"));
foreach(x, pki_export::select(asym_key, 0)) {
if (!(x->flags & F_CLIPBOARD))
continue;
qWarning() << "CLIPBOARD" << x->id << x->desc;
a = clipboard->addAction(x->desc);
a->setData(x->id);
a->setCheckable(true);
a->setChecked(exp_type == x->id);
group->addAction(a);
}
connect(group, SIGNAL(triggered(QAction*)),
this, SLOT(clipboardFormat(QAction*)));
if (indexes.size() == 0 || !key)
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;
default:
break;
}
}
if (!pkcs11::libraries.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 if (subExport) {
subExport->addAction(tr("Security token"),
this, SLOT(toToken()));
}
}
void KeyTreeView::setOwnPass()
{
if (!basemodel)
return;
try {
keys()->setOwnPass(currentIndex(), pki_key::ptPrivate);
} catch (errorEx &err) {
XCA_ERROR(err);
}
}
void KeyTreeView::resetOwnPass()
{
if (!basemodel)
return;
try {
keys()->setOwnPass(currentIndex(), pki_key::ptCommon);
} catch (errorEx &err) {
XCA_ERROR(err);
}
}
void KeyTreeView::changePin()
{
pki_scard *scard;
QModelIndex currentIdx = currentIndex();
if (!currentIdx.isValid())
return;
scard = db_base::fromIndex<pki_scard>(currentIdx);
try {
if (!scard->isToken()) {
throw errorEx(tr("This is not a token"));
}
scard->changePin();
} catch (errorEx &err) {
XCA_ERROR(err);
}
}
void KeyTreeView::initPin()
{
pki_scard *scard;
QModelIndex currentIdx = currentIndex();
if (!currentIdx.isValid())
return;
scard = db_base::fromIndex<pki_scard>(currentIdx);
try {
if (!scard->isToken()) {
throw errorEx(tr("This is not a token"));
}
scard->initPin();
} catch (errorEx &err) {
XCA_ERROR(err);
}
}
void KeyTreeView::changeSoPin()
{
pki_scard *scard;
QModelIndex currentIdx = currentIndex();
if (!currentIdx.isValid())
return;
scard = db_base::fromIndex<pki_scard>(currentIdx);
try {
if (!scard->isToken()) {
throw errorEx(tr("This is not a token"));
}
scard->changeSoPin();
} catch (errorEx &err) {
XCA_ERROR(err);
}
}
void KeyTreeView::toToken()
{
QModelIndex currentIdx = currentIndex();
if (!currentIdx.isValid() || !basemodel)
return;
pki_key *key = db_base::fromIndex<pki_key>(currentIdx);
if (!key || !pkcs11::libraries.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());
card->pkiSource = key->pkiSource;
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) {
XCA_ERROR(err);
}
delete card;
}
void KeyTreeView::showPki(pki_base *pki)
{
pki_key *key = dynamic_cast<pki_key *>(pki);
KeyDetail::showKey(this, key);
}
void KeyTreeView::newItem() {
newItem("");
}
void KeyTreeView::newItem(const QString &name)
{
if (!basemodel)
return;
NewKey *dlg = new NewKey(this, name);
if (dlg->exec())
keys()->newKey(dlg->getKeyJob(), dlg->keyDesc->text());
delete dlg;
}
void KeyTreeView::clipboardFormat(QAction *a)
{
Settings["KeyFormat"] = a->data().toInt();
}
void KeyTreeView::load(void)
{
load_key l;
load_default(&l);
}
ExportDialog *KeyTreeView::exportDialog(const QModelIndexList &indexes)
{
if (indexes.size() == 0)
return NULL;
pki_key *key = db_base::fromIndex<pki_key>(indexes[0]);
return new ExportDialog(this,
tr("Export public key [%1]").arg(key->getTypeString()),
tr("Private Keys ( *.pem *.der *.pk8 );; "
"SSH Public Keys ( *.pub )"), indexes,
QPixmap(key->isToken() ? ":scardImg" : ":keyImg"),
pki_export::select(asym_key, basemodel->exportFlags(indexes)),
"keyexport");
}