mirror of
https://github.com/QuasarApp/qca.git
synced 2025-05-12 10:49:32 +00:00
find . \( -name "*.cpp" -or -name "*.h" -or -name "*.c" -or -name "*.cc" \) -exec clang-format -i {} \; If you reached this file doing a git blame, please see README.clang-format (added 2 commits in the future of this one)
775 lines
26 KiB
C++
775 lines
26 KiB
C++
/*
|
|
Copyright (C) 2007 Justin Karneges <justin@affinix.com>
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include "pkcs11configdlg.h"
|
|
|
|
#include "ui_pkcs11config.h"
|
|
#include <QFileDialog>
|
|
#include <QMessageBox>
|
|
#include <QtCore>
|
|
#include <QtCrypto>
|
|
#include <QtGui>
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Pkcs11ProviderConfig
|
|
//----------------------------------------------------------------------------
|
|
class Pkcs11ProviderConfig
|
|
{
|
|
public:
|
|
bool allow_protected_authentication;
|
|
bool cert_private;
|
|
bool enabled;
|
|
QString library;
|
|
QString name;
|
|
int private_mask;
|
|
QString slotevent_method;
|
|
int slotevent_timeout;
|
|
|
|
Pkcs11ProviderConfig()
|
|
: allow_protected_authentication(true)
|
|
, cert_private(false)
|
|
, enabled(false)
|
|
, private_mask(0)
|
|
, slotevent_method("auto")
|
|
, slotevent_timeout(0)
|
|
{
|
|
}
|
|
|
|
QVariantMap toVariantMap() const
|
|
{
|
|
QVariantMap out;
|
|
out["allow_protected_authentication"] = allow_protected_authentication;
|
|
out["cert_private"] = cert_private;
|
|
out["enabled"] = enabled;
|
|
out["library"] = library;
|
|
out["name"] = name;
|
|
out["private_mask"] = private_mask;
|
|
out["slotevent_method"] = slotevent_method;
|
|
out["slotevent_timeout"] = slotevent_timeout;
|
|
return out;
|
|
}
|
|
|
|
bool fromVariantMap(const QVariantMap &in)
|
|
{
|
|
allow_protected_authentication = in["allow_protected_authentication"].toBool();
|
|
cert_private = in["cert_private"].toBool();
|
|
enabled = in["enabled"].toBool();
|
|
library = in["library"].toString();
|
|
name = in["name"].toString();
|
|
private_mask = in["private_mask"].toInt();
|
|
slotevent_method = in["slotevent_method"].toString();
|
|
slotevent_timeout = in["slotevent_timeout"].toInt();
|
|
return true;
|
|
}
|
|
};
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Pkcs11Config
|
|
//----------------------------------------------------------------------------
|
|
class Pkcs11Config
|
|
{
|
|
public:
|
|
bool allow_load_rootca;
|
|
bool allow_protected_authentication;
|
|
int log_level;
|
|
int pin_cache;
|
|
QList<Pkcs11ProviderConfig> providers;
|
|
|
|
QVariantMap orig_config;
|
|
|
|
Pkcs11Config()
|
|
: allow_load_rootca(false)
|
|
, allow_protected_authentication(true)
|
|
, log_level(0)
|
|
, pin_cache(-1)
|
|
{
|
|
}
|
|
|
|
QVariantMap toVariantMap() const
|
|
{
|
|
QVariantMap out = orig_config;
|
|
|
|
// form type
|
|
out["formtype"] = "http://affinix.com/qca/forms/qca-pkcs11#1.0";
|
|
|
|
// base settings
|
|
out["allow_load_rootca"] = allow_load_rootca;
|
|
out["allow_protected_authentication"] = allow_protected_authentication;
|
|
out["log_level"] = log_level;
|
|
out["pin_cache"] = pin_cache;
|
|
|
|
// provider settings (always write at least 10 providers)
|
|
for (int n = 0; n < 10 || n < providers.count(); ++n) {
|
|
QString prefix = QString().sprintf("provider_%02d_", n);
|
|
|
|
Pkcs11ProviderConfig provider;
|
|
if (n < providers.count())
|
|
provider = providers[n];
|
|
|
|
QVariantMap subconfig = provider.toVariantMap();
|
|
QMapIterator<QString, QVariant> it(subconfig);
|
|
while (it.hasNext()) {
|
|
it.next();
|
|
out.insert(prefix + it.key(), it.value());
|
|
}
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
bool fromVariantMap(const QVariantMap &in)
|
|
{
|
|
if (in["formtype"] != "http://affinix.com/qca/forms/qca-pkcs11#1.0")
|
|
return false;
|
|
|
|
allow_load_rootca = in["allow_load_rootca"].toBool();
|
|
allow_protected_authentication = in["allow_protected_authentication"].toBool();
|
|
log_level = in["log_level"].toInt();
|
|
pin_cache = in["pin_cache"].toInt();
|
|
|
|
for (int n = 0;; ++n) {
|
|
QString prefix = QString().sprintf("provider_%02d_", n);
|
|
|
|
// collect all key/values with this prefix into a
|
|
// a separate container, leaving out the prefix
|
|
// from the keys.
|
|
QVariantMap subconfig;
|
|
QMapIterator<QString, QVariant> it(in);
|
|
while (it.hasNext()) {
|
|
it.next();
|
|
if (it.key().startsWith(prefix))
|
|
subconfig.insert(it.key().mid(prefix.length()), it.value());
|
|
}
|
|
|
|
// if there are no config items with this prefix, we're done
|
|
if (subconfig.isEmpty())
|
|
break;
|
|
|
|
Pkcs11ProviderConfig provider;
|
|
if (!provider.fromVariantMap(subconfig))
|
|
return false;
|
|
|
|
// skip unnamed entries
|
|
if (provider.name.isEmpty())
|
|
continue;
|
|
|
|
// skip duplicate entries
|
|
bool have_name_already = false;
|
|
foreach (const Pkcs11ProviderConfig &i, providers) {
|
|
if (i.name == provider.name) {
|
|
have_name_already = true;
|
|
break;
|
|
}
|
|
}
|
|
if (have_name_already)
|
|
continue;
|
|
|
|
providers += provider;
|
|
}
|
|
|
|
orig_config = in;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
//----------------------------------------------------------------------------
|
|
// ModuleListModel
|
|
//----------------------------------------------------------------------------
|
|
class ModuleListModel : public QAbstractListModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
QList<Pkcs11ProviderConfig> list;
|
|
|
|
ModuleListModel(QObject *parent = 0)
|
|
: QAbstractListModel(parent)
|
|
{
|
|
}
|
|
|
|
int rowCount(const QModelIndex &parent = QModelIndex()) const
|
|
{
|
|
Q_UNUSED(parent);
|
|
return list.count();
|
|
}
|
|
|
|
QVariant data(const QModelIndex &index, int role) const
|
|
{
|
|
if (!index.isValid())
|
|
return QVariant();
|
|
|
|
if (index.row() >= list.count())
|
|
return QVariant();
|
|
|
|
if (role == Qt::DisplayRole)
|
|
return list[index.row()].name;
|
|
else if (role == Qt::EditRole)
|
|
return list[index.row()].name;
|
|
else
|
|
return QVariant();
|
|
}
|
|
|
|
Qt::ItemFlags flags(const QModelIndex &index) const
|
|
{
|
|
if (!index.isValid())
|
|
return Qt::ItemIsEnabled;
|
|
|
|
return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
|
|
}
|
|
|
|
bool setData(const QModelIndex &index, const QVariant &value, int role)
|
|
{
|
|
if (index.isValid() && role == Qt::EditRole) {
|
|
QString str = value.toString();
|
|
|
|
if (str.isEmpty()) {
|
|
emit editFailed(index, tr("Module name cannot be blank."));
|
|
return false;
|
|
}
|
|
|
|
bool have_name_already = false;
|
|
int at = index.row();
|
|
for (int n = 0; n < list.count(); ++n) {
|
|
const Pkcs11ProviderConfig &i = list[n];
|
|
|
|
// skip self
|
|
if (n == at)
|
|
continue;
|
|
|
|
if (i.name == str) {
|
|
have_name_already = true;
|
|
break;
|
|
}
|
|
}
|
|
if (have_name_already) {
|
|
emit editFailed(index, tr("There is already a module with this name."));
|
|
return false;
|
|
}
|
|
|
|
list[index.row()].name = str;
|
|
emit dataChanged(index, index);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void addItems(const QList<Pkcs11ProviderConfig> &items)
|
|
{
|
|
if (items.isEmpty())
|
|
return;
|
|
|
|
beginInsertRows(QModelIndex(), list.size(), list.size() + items.count() - 1);
|
|
list += items;
|
|
endInsertRows();
|
|
}
|
|
|
|
void addItem(const Pkcs11ProviderConfig &i)
|
|
{
|
|
beginInsertRows(QModelIndex(), list.size(), list.size());
|
|
list += i;
|
|
endInsertRows();
|
|
}
|
|
|
|
void removeItem(int at)
|
|
{
|
|
beginRemoveRows(QModelIndex(), at, at);
|
|
list.removeAt(at);
|
|
endRemoveRows();
|
|
}
|
|
|
|
Q_SIGNALS:
|
|
void editFailed(const QModelIndex &index, const QString &reasonString);
|
|
};
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Pkcs11ConfigDlg
|
|
//----------------------------------------------------------------------------
|
|
static QCA::Provider *get_pkcs11_provider(QVariantMap *_config = 0)
|
|
{
|
|
QCA::ProviderList providers = QCA::providers();
|
|
providers += QCA::defaultProvider();
|
|
|
|
QCA::Provider *provider = 0;
|
|
QVariantMap config;
|
|
foreach (QCA::Provider *p, providers) {
|
|
config = QCA::getProviderConfig(p->name());
|
|
if (!config.isEmpty() && config["formtype"] == "http://affinix.com/qca/forms/qca-pkcs11#1.0") {
|
|
provider = p;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (provider && _config)
|
|
*_config = config;
|
|
|
|
return provider;
|
|
}
|
|
|
|
class Pkcs11ConfigDlg::Private : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
Pkcs11ConfigDlg *q;
|
|
Ui_Pkcs11Config ui;
|
|
QString providerName;
|
|
ModuleListModel *model;
|
|
Pkcs11Config config;
|
|
bool dirty;
|
|
|
|
// for safe dialog closing behavior during QListView editing
|
|
bool allow_close;
|
|
bool done;
|
|
|
|
// for ignoring modifications that we cause when populating fields
|
|
bool ignore_dataChanged;
|
|
|
|
Private(Pkcs11ConfigDlg *_q, const QString &_providerName, const QVariantMap &configmap)
|
|
: QObject(_q)
|
|
, q(_q)
|
|
, providerName(_providerName)
|
|
, dirty(false)
|
|
, allow_close(true)
|
|
, done(false)
|
|
, ignore_dataChanged(true)
|
|
{
|
|
ui.setupUi(q);
|
|
q->resize(q->minimumSize());
|
|
|
|
model = new ModuleListModel(this);
|
|
qRegisterMetaType<QModelIndex>("QModelIndex");
|
|
// do this queued for two reasons:
|
|
// 1) if we throw an error dialog, it will occur after the
|
|
// row text has reverted, and the call stack completed
|
|
// (the latter may not be required, but it helps me
|
|
// sleep).
|
|
// 2) if the user accepts/rejects the dialog while editing,
|
|
// it is easy to ensure that the signal is not processed
|
|
// (if it gets delivered at all).
|
|
connect(model,
|
|
SIGNAL(editFailed(const QModelIndex &, const QString &)),
|
|
SLOT(model_editFailed(const QModelIndex &, const QString &)),
|
|
Qt::QueuedConnection);
|
|
|
|
// set up widgets
|
|
ui.rb_pincache_nolimit->setChecked(true);
|
|
ui.sb_pincache_time->setEnabled(false);
|
|
ui.sb_pincache_time->setValue(300);
|
|
ui.lv_modules->setModel(model);
|
|
ui.lv_modules->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked |
|
|
QAbstractItemView::EditKeyPressed);
|
|
ui.pb_remove->setEnabled(false);
|
|
ui.tb_details->setEnabled(false);
|
|
ui.gb_poll->setEnabled(false);
|
|
ui.rb_polldefault->setChecked(true);
|
|
ui.sb_pollcustom->setEnabled(false);
|
|
ui.sb_pollcustom->setValue(5);
|
|
ui.ck_modeauto->setChecked(true);
|
|
|
|
// disable this by default, enable on dataChanged
|
|
ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
|
|
|
// general
|
|
connect(ui.ck_allowroot, SIGNAL(toggled(bool)), SLOT(dataChanged()));
|
|
connect(ui.ck_allowprotected, SIGNAL(toggled(bool)), SLOT(dataChanged()));
|
|
connect(ui.sb_loglevel, SIGNAL(valueChanged(int)), SLOT(dataChanged()));
|
|
connect(ui.gb_pincache, SIGNAL(toggled(bool)), SLOT(dataChanged()));
|
|
connect(ui.rb_pincache_nolimit, SIGNAL(toggled(bool)), SLOT(dataChanged()));
|
|
connect(ui.rb_pincache_time, SIGNAL(toggled(bool)), ui.sb_pincache_time, SLOT(setEnabled(bool)));
|
|
connect(ui.rb_pincache_time, SIGNAL(toggled(bool)), SLOT(dataChanged()));
|
|
connect(ui.sb_pincache_time, SIGNAL(valueChanged(int)), SLOT(dataChanged()));
|
|
|
|
// modules
|
|
connect(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), SLOT(dataChanged()));
|
|
connect(ui.lv_modules->selectionModel(),
|
|
SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
|
|
SLOT(module_selectionChanged(const QItemSelection &, const QItemSelection &)));
|
|
connect(ui.pb_add, SIGNAL(clicked()), SLOT(module_add()));
|
|
connect(ui.pb_remove, SIGNAL(clicked()), SLOT(module_remove()));
|
|
connect(ui.le_library, SIGNAL(textChanged(const QString &)), SLOT(dataChanged()));
|
|
connect(ui.pb_browse, SIGNAL(clicked()), SLOT(library_browse()));
|
|
connect(ui.cb_slotmethod, SIGNAL(currentIndexChanged(int)), SLOT(slotmethod_currentIndexChanged(int)));
|
|
connect(ui.rb_polldefault, SIGNAL(toggled(bool)), SLOT(dataChanged()));
|
|
connect(ui.rb_pollcustom, SIGNAL(toggled(bool)), ui.sb_pollcustom, SLOT(setEnabled(bool)));
|
|
connect(ui.rb_pollcustom, SIGNAL(toggled(bool)), SLOT(dataChanged()));
|
|
connect(ui.sb_pollcustom, SIGNAL(valueChanged(int)), SLOT(dataChanged()));
|
|
connect(ui.ck_modallowprotected, SIGNAL(toggled(bool)), SLOT(dataChanged()));
|
|
connect(ui.ck_certprivate, SIGNAL(toggled(bool)), SLOT(dataChanged()));
|
|
connect(ui.ck_modeauto, SIGNAL(toggled(bool)), SLOT(modeauto_toggled(bool)));
|
|
connect(ui.ck_modesign, SIGNAL(toggled(bool)), SLOT(modenonauto_toggled(bool)));
|
|
connect(ui.ck_modesignrecover, SIGNAL(toggled(bool)), SLOT(modenonauto_toggled(bool)));
|
|
connect(ui.ck_modedecrypt, SIGNAL(toggled(bool)), SLOT(modenonauto_toggled(bool)));
|
|
connect(ui.ck_modeunwrap, SIGNAL(toggled(bool)), SLOT(modenonauto_toggled(bool)));
|
|
|
|
// is this a valid config?
|
|
if (!providerName.isEmpty() && config.fromVariantMap(configmap)) {
|
|
// if so, load everything up
|
|
ui.ck_allowroot->setChecked(config.allow_load_rootca);
|
|
ui.ck_allowprotected->setChecked(config.allow_protected_authentication);
|
|
ui.sb_loglevel->setValue(config.log_level);
|
|
if (config.pin_cache != 0) {
|
|
ui.gb_pincache->setChecked(true);
|
|
if (config.pin_cache <= -1)
|
|
ui.rb_pincache_nolimit->setChecked(true);
|
|
else {
|
|
ui.rb_pincache_time->setChecked(true);
|
|
ui.sb_pincache_time->setValue(config.pin_cache);
|
|
}
|
|
}
|
|
|
|
model->addItems(config.providers);
|
|
if (!model->list.isEmpty()) {
|
|
QModelIndex index = model->index(0);
|
|
ui.lv_modules->setCurrentIndex(index);
|
|
ui.lv_modules->selectionModel()->select(
|
|
index, QItemSelectionModel::Clear | QItemSelectionModel::Select | QItemSelectionModel::Current);
|
|
}
|
|
ui.buttonBox->setFocus();
|
|
ui.buttonBox->button(QDialogButtonBox::Cancel)->setFocus();
|
|
} else {
|
|
// otherwise, disable everything
|
|
ui.gb_general->setEnabled(false);
|
|
ui.gb_modules->setEnabled(false);
|
|
ui.buttonBox->setFocus();
|
|
ui.buttonBox->button(QDialogButtonBox::Cancel)->setFocus();
|
|
}
|
|
|
|
ignore_dataChanged = false;
|
|
}
|
|
|
|
void save_module(int at)
|
|
{
|
|
// save all options (except the name, which is handled by the model)
|
|
Pkcs11ProviderConfig &i = model->list[at];
|
|
|
|
i.library = ui.le_library->text();
|
|
i.enabled = true;
|
|
|
|
int x = ui.cb_slotmethod->currentIndex();
|
|
if (x == 0)
|
|
i.slotevent_method = "auto";
|
|
else if (x == 1)
|
|
i.slotevent_method = "trigger";
|
|
else // 2
|
|
i.slotevent_method = "poll";
|
|
if (x == 2) {
|
|
if (ui.rb_polldefault->isChecked())
|
|
i.slotevent_timeout = 0;
|
|
else
|
|
i.slotevent_timeout = ui.sb_pollcustom->value();
|
|
} else
|
|
i.slotevent_timeout = 0;
|
|
|
|
i.allow_protected_authentication = ui.ck_modallowprotected->isChecked();
|
|
i.cert_private = ui.ck_certprivate->isChecked();
|
|
|
|
i.private_mask = 0;
|
|
if (ui.ck_modesign->isChecked())
|
|
i.private_mask |= 1;
|
|
if (ui.ck_modesignrecover->isChecked())
|
|
i.private_mask |= 2;
|
|
if (ui.ck_modedecrypt->isChecked())
|
|
i.private_mask |= 4;
|
|
if (ui.ck_modeunwrap->isChecked())
|
|
i.private_mask |= 8;
|
|
}
|
|
|
|
void save()
|
|
{
|
|
// save currently selected module, which may not be saved yet
|
|
QItemSelection selection = ui.lv_modules->selectionModel()->selection();
|
|
if (!selection.indexes().isEmpty()) {
|
|
QModelIndex index = selection.indexes().first();
|
|
save_module(index.row());
|
|
}
|
|
|
|
config.allow_load_rootca = ui.ck_allowroot->isChecked();
|
|
config.allow_protected_authentication = ui.ck_allowprotected->isChecked();
|
|
config.log_level = ui.sb_loglevel->value();
|
|
if (ui.gb_pincache->isChecked()) {
|
|
if (ui.rb_pincache_nolimit->isChecked())
|
|
config.pin_cache = -1;
|
|
else
|
|
config.pin_cache = ui.sb_pincache_time->value();
|
|
} else
|
|
config.pin_cache = 0;
|
|
|
|
config.providers = model->list;
|
|
|
|
QVariantMap configmap = config.toVariantMap();
|
|
QCA::setProviderConfig(providerName, configmap);
|
|
QCA::saveProviderConfig(providerName);
|
|
}
|
|
|
|
private Q_SLOTS:
|
|
void model_editFailed(const QModelIndex &index, const QString &reasonString)
|
|
{
|
|
// if the dialog has already been dismissed, then don't
|
|
// bother with handling the editing failure
|
|
if (done)
|
|
return;
|
|
|
|
// show error dialog, and don't allow dimissing the dialog
|
|
// during. we need this, because the dismiss request
|
|
// can be queued, and end up being invoked during the
|
|
// QMessageBox nested eventloop.
|
|
allow_close = false;
|
|
QMessageBox::information(q, tr("Module Configuration"), reasonString);
|
|
allow_close = true;
|
|
|
|
// return to edit mode for the item
|
|
ui.lv_modules->setFocus();
|
|
ui.lv_modules->setCurrentIndex(index);
|
|
ui.lv_modules->selectionModel()->select(
|
|
index, QItemSelectionModel::Clear | QItemSelectionModel::Select | QItemSelectionModel::Current);
|
|
ui.lv_modules->edit(index);
|
|
}
|
|
|
|
void dataChanged()
|
|
{
|
|
if (ignore_dataChanged)
|
|
return;
|
|
|
|
if (dirty)
|
|
return;
|
|
|
|
dirty = true;
|
|
ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
|
|
}
|
|
|
|
void module_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
|
|
{
|
|
if (!deselected.indexes().isEmpty()) {
|
|
QModelIndex index = deselected.indexes().first();
|
|
save_module(index.row());
|
|
}
|
|
|
|
ignore_dataChanged = true;
|
|
|
|
if (!selected.indexes().isEmpty()) {
|
|
if (deselected.indexes().isEmpty()) {
|
|
ui.pb_remove->setEnabled(true);
|
|
ui.tb_details->setEnabled(true);
|
|
}
|
|
|
|
QModelIndex index = selected.indexes().first();
|
|
const Pkcs11ProviderConfig &i = model->list[index.row()];
|
|
|
|
ui.le_library->setText(i.library);
|
|
|
|
if (i.slotevent_method == "trigger")
|
|
ui.cb_slotmethod->setCurrentIndex(1);
|
|
else if (i.slotevent_method == "poll") {
|
|
ui.cb_slotmethod->setCurrentIndex(2);
|
|
if (i.slotevent_timeout <= 0)
|
|
ui.rb_polldefault->setChecked(true);
|
|
else {
|
|
ui.rb_pollcustom->setChecked(true);
|
|
ui.sb_pollcustom->setValue(i.slotevent_timeout);
|
|
}
|
|
} else // auto
|
|
ui.cb_slotmethod->setCurrentIndex(0);
|
|
if (i.slotevent_method != "poll") {
|
|
ui.rb_polldefault->setChecked(true);
|
|
ui.sb_pollcustom->setValue(5);
|
|
}
|
|
|
|
ui.ck_modallowprotected->setChecked(i.allow_protected_authentication);
|
|
ui.ck_certprivate->setChecked(i.cert_private);
|
|
|
|
if (i.private_mask == 0)
|
|
ui.ck_modeauto->setChecked(true);
|
|
else {
|
|
ui.ck_modesign->setChecked(i.private_mask & 1);
|
|
ui.ck_modesignrecover->setChecked(i.private_mask & 2);
|
|
ui.ck_modedecrypt->setChecked(i.private_mask & 4);
|
|
ui.ck_modeunwrap->setChecked(i.private_mask & 8);
|
|
}
|
|
} else if (selected.indexes().isEmpty() && !deselected.indexes().isEmpty()) {
|
|
// restore defaults for all details widgets
|
|
ui.le_library->setText(QString());
|
|
ui.cb_slotmethod->setCurrentIndex(0);
|
|
ui.rb_polldefault->setChecked(true);
|
|
ui.sb_pollcustom->setValue(5);
|
|
ui.ck_modallowprotected->setChecked(false);
|
|
ui.ck_certprivate->setChecked(false);
|
|
ui.ck_modeauto->setChecked(true);
|
|
|
|
// flip to first page, disable
|
|
ui.tb_details->setCurrentIndex(0);
|
|
ui.pb_remove->setEnabled(false);
|
|
ui.tb_details->setEnabled(false);
|
|
}
|
|
|
|
ignore_dataChanged = false;
|
|
}
|
|
|
|
void module_add()
|
|
{
|
|
// find unused default name
|
|
QString name;
|
|
for (int n = 1;; ++n) {
|
|
if (n == 1)
|
|
name = tr("New Module");
|
|
else
|
|
name = tr("New Module (%1)").arg(n);
|
|
|
|
bool have_name_already = false;
|
|
for (int n = 0; n < model->list.count(); ++n) {
|
|
const Pkcs11ProviderConfig &i = model->list[n];
|
|
if (i.name == name) {
|
|
have_name_already = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!have_name_already)
|
|
break;
|
|
}
|
|
|
|
Pkcs11ProviderConfig i;
|
|
i.name = name;
|
|
i.enabled = true;
|
|
model->addItem(i);
|
|
|
|
dataChanged();
|
|
|
|
QModelIndex index = model->index(model->list.count() - 1);
|
|
|
|
// flip to first page
|
|
ui.tb_details->setCurrentIndex(0);
|
|
|
|
// edit this item
|
|
ui.lv_modules->setFocus();
|
|
ui.lv_modules->setCurrentIndex(index);
|
|
ui.lv_modules->selectionModel()->select(
|
|
index, QItemSelectionModel::Clear | QItemSelectionModel::Select | QItemSelectionModel::Current);
|
|
ui.lv_modules->edit(index);
|
|
}
|
|
|
|
void module_remove()
|
|
{
|
|
QItemSelection selection = ui.lv_modules->selectionModel()->selection();
|
|
if (selection.indexes().isEmpty())
|
|
return;
|
|
QModelIndex index = selection.indexes().first();
|
|
model->removeItem(index.row());
|
|
|
|
dataChanged();
|
|
}
|
|
|
|
void library_browse()
|
|
{
|
|
QString fileName =
|
|
QFileDialog::getOpenFileName(q, tr("Select PKCS#11 Module"), QString(), tr("PKCS#11 Modules (*.*)"));
|
|
if (fileName.isEmpty())
|
|
return;
|
|
|
|
ui.le_library->setText(fileName);
|
|
}
|
|
|
|
void slotmethod_currentIndexChanged(int index)
|
|
{
|
|
if (index == 2) // Polling
|
|
ui.gb_poll->setEnabled(true);
|
|
else
|
|
ui.gb_poll->setEnabled(false);
|
|
|
|
dataChanged();
|
|
}
|
|
|
|
void modeauto_toggled(bool checked)
|
|
{
|
|
if (checked) {
|
|
if (ui.ck_modesign->isChecked())
|
|
ui.ck_modesign->setChecked(false);
|
|
if (ui.ck_modesignrecover->isChecked())
|
|
ui.ck_modesignrecover->setChecked(false);
|
|
if (ui.ck_modedecrypt->isChecked())
|
|
ui.ck_modedecrypt->setChecked(false);
|
|
if (ui.ck_modeunwrap->isChecked())
|
|
ui.ck_modeunwrap->setChecked(false);
|
|
} else {
|
|
if (!ui.ck_modesign->isChecked() && !ui.ck_modesignrecover->isChecked() &&
|
|
!ui.ck_modedecrypt->isChecked() && !ui.ck_modeunwrap->isChecked()) {
|
|
ui.ck_modesign->setChecked(true);
|
|
ui.ck_modesignrecover->setChecked(true);
|
|
ui.ck_modedecrypt->setChecked(true);
|
|
ui.ck_modeunwrap->setChecked(true);
|
|
}
|
|
}
|
|
|
|
dataChanged();
|
|
}
|
|
|
|
void modenonauto_toggled(bool checked)
|
|
{
|
|
if (checked) {
|
|
if (ui.ck_modeauto->isChecked())
|
|
ui.ck_modeauto->setChecked(false);
|
|
} else {
|
|
if (!ui.ck_modesign->isChecked() && !ui.ck_modesignrecover->isChecked() &&
|
|
!ui.ck_modedecrypt->isChecked() && !ui.ck_modeunwrap->isChecked()) {
|
|
ui.ck_modeauto->setChecked(true);
|
|
}
|
|
}
|
|
|
|
dataChanged();
|
|
}
|
|
};
|
|
|
|
Pkcs11ConfigDlg::Pkcs11ConfigDlg(QWidget *parent)
|
|
: QDialog(parent)
|
|
{
|
|
QVariantMap config;
|
|
QCA::Provider *p = get_pkcs11_provider(&config);
|
|
if (p)
|
|
d = new Private(this, p->name(), config);
|
|
else
|
|
d = new Private(this, QString(), QVariantMap());
|
|
}
|
|
|
|
Pkcs11ConfigDlg::Pkcs11ConfigDlg(const QString &providerName, const QVariantMap &config, QWidget *parent)
|
|
: QDialog(parent)
|
|
{
|
|
d = new Private(this, providerName, config);
|
|
}
|
|
|
|
Pkcs11ConfigDlg::~Pkcs11ConfigDlg()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
void Pkcs11ConfigDlg::done(int r)
|
|
{
|
|
if (!d->allow_close)
|
|
return;
|
|
|
|
d->done = true;
|
|
if (r == Accepted)
|
|
d->save();
|
|
QDialog::done(r);
|
|
}
|
|
|
|
bool Pkcs11ConfigDlg::isSupported()
|
|
{
|
|
return (get_pkcs11_provider() ? true : false);
|
|
}
|
|
|
|
#include "pkcs11configdlg.moc"
|