Add PKCS#11 library searching facility

Also fix dir-separator on W32
This commit is contained in:
Christian Hohnstaedt 2011-07-19 14:34:49 +02:00 committed by Christian Hohnstaedt
parent e7260c9288
commit 323923f00c
12 changed files with 496 additions and 39 deletions

View File

@ -585,19 +585,18 @@ bool db_base::setData(const QModelIndex &index, const QVariant &value, int role)
void db_base::load_default(load_base &load)
{
QString s;
QStringList slist = QFileDialog::getOpenFileNames(mainwin, load.caption,
mainwin->getPath(), load.filter);
if (!slist.count())
return;
QString fn = QDir::convertSeparators(slist[0]);
mainwin->setPath(fn.mid(0, fn.lastIndexOf(QRegExp("[/\\\\]")) ));
QString fn = slist[0];
mainwin->setPath(fn.mid(0, fn.lastIndexOf("/")));
ImportMulti *dlgi = new ImportMulti(mainwin);
for (QStringList::Iterator it = slist.begin(); it != slist.end(); ++it) {
QString s = *it;
s = QDir::convertSeparators(s);
foreach(s, slist) {
pki_base *item = NULL;
try {
item = load.loadItem(s);

View File

@ -54,6 +54,19 @@ QString getDefaultPkcs11Lib()
#endif
}
QStringList getLibExtensions()
{
QStringList l;
#if defined(_WIN32) || defined(USE_CYGWIN)
l << QString("*.dll") << QString("*.DLL");
#elif defined(Q_WS_MAC)
l << QString("*.dylib") << QString("*.so");
#else
l << QString("*.so");
#endif
return l;
}
/* returns e.g. /usr/local/share/xca for unix systems
* or HKEY_LOCAL_MACHINE->Software->xca for WIN32
* (e.g. c:\Program Files\xca )
@ -209,28 +222,21 @@ QString filename2QString(const char *fname)
#endif
}
QString compressFilename(QString filename)
QString compressFilename(QString filename, int maxlen)
{
/* quick and dirty demo for compacting filename */
/* there are i compactable path components, but keep the filename */
int i = filename.count(QDir::separator()) - 1;
if (filename.length() < maxlen)
return filename;
/* we want to keep the first component,
* so don't count the starting slash */
if(filename.startsWith(QDir::separator()))
i--;
int len, lastslash = filename.lastIndexOf("/");
QString base = filename.mid(lastslash);
len = base.length();
len = maxlen - len -3;
if (len < 0)
return QString("...") + base.right(maxlen -3);
filename = filename.left(len);
lastslash = filename.lastIndexOf("/");
#define MAX_DISPLAY_LEN 50
// start most-right
int from, to = filename.lastIndexOf(QDir::separator());
for (; i > 0 && filename.length() > MAX_DISPLAY_LEN; i--) {
from = filename.lastIndexOf(QDir::separator(), to - 1);
filename.replace(from + 1 , to-from - 1, "...");
to = from;
}
return filename;
return filename.left(lastslash+1) + "..." + base;
}

View File

@ -23,10 +23,11 @@ QString getDocDir();
QString getUserSettingsDir();
QString getDefaultPkcs11Lib();
QString getFullFilename(const QString &filename, const QString &selectedFilter);
QStringList getLibExtensions();
QByteArray filename2bytearray(const QString &fname);
QString filename2QString(const char *fname);
QString compressFilename(QString filename);
QString compressFilename(QString filename, int maxlen = 50);
QString asn1ToQString(const ASN1_STRING *str, bool quote = false);
ASN1_STRING *QStringToAsn1(QString s, int nid);

View File

@ -105,13 +105,7 @@ QString pki_base::rmslashdot(const QString &s)
{
QByteArray a = s.toAscii();
int r = a.lastIndexOf('.');
#ifdef WIN32
int l = a.lastIndexOf('\\');
#else
int l = a.lastIndexOf('/');
#endif
//printf("r=%d, l=%d, s='%s', mid='%s'\n",r,l,(const char*)a,
// CCHAR(s.mid(l+1,r-l-1)));
return s.mid(l+1,r-l-1);
}

View File

@ -8,7 +8,7 @@ UI_H = ui_About.h ui_CaProperties.h ui_CertDetail.h ui_CertExtend.h \
ui_CrlDetail.h ui_ExportDialog.h ui_ExportKey.h ui_Help.h \
ui_ImportMulti.h ui_KeyDetail.h ui_MainWindow.h ui_NewCrl.h \
ui_NewKey.h ui_NewX509.h ui_Options.h ui_PwDialog.h ui_Revoke.h \
ui_SelectToken.h ui_TrustState.h ui_v3ext.h
ui_SelectToken.h ui_TrustState.h ui_v3ext.h ui_SearchPkcs11.h
include $(TOPDIR)/Rules.mak

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>494</width>
<height>495</height>
<height>529</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
@ -172,6 +172,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="searchPkcs11">
<property name="text">
<string>Search</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
@ -179,8 +186,8 @@
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
<width>77</width>
<height>17</height>
</size>
</property>
</spacer>

152
ui/SearchPkcs11.ui Normal file
View File

@ -0,0 +1,152 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SearchPkcs11</class>
<widget class="QDialog" name="SearchPkcs11">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>480</width>
<height>378</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="frame_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="TextLabel14">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Directory</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="filename"/>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="fileBut">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="subdirs">
<property name="text">
<string>include sub directorys</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="search">
<property name="text">
<string>Search</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="currFile">
<property name="text">
<string notr="true"/>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="liblist">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Open</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>clicked(QAbstractButton*)</signal>
<receiver>SearchPkcs11</receiver>
<slot>buttonPress(QAbstractButton*)</slot>
<hints>
<hint type="sourcelabel">
<x>229</x>
<y>362</y>
</hint>
<hint type="destinationlabel">
<x>368</x>
<y>104</y>
</hint>
</hints>
</connection>
<connection>
<sender>liblist</sender>
<signal>itemDoubleClicked(QListWidgetItem*)</signal>
<receiver>SearchPkcs11</receiver>
<slot>loadItem(QListWidgetItem*)</slot>
<hints>
<hint type="sourcelabel">
<x>339</x>
<y>279</y>
</hint>
<hint type="destinationlabel">
<x>368</x>
<y>225</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>buttonPress(QAbstractButton*)</slot>
<slot>loadItem(QListWidgetItem*)</slot>
</slots>
</ui>

View File

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

View File

@ -7,9 +7,11 @@
#include "lib/func.h"
#include "Options.h"
#include "SearchPkcs11.h"
#include "lib/pki_scard.h"
#include <openssl/objects.h>
#include <QtGui/QMessageBox>
#include <QtGui/QToolTip>
Options::Options(MainWindow *parent)
:QDialog(parent)
@ -40,6 +42,13 @@ Options::Options(MainWindow *parent)
<< tr("UTF8 strings only (RFC2459)")
<< tr("All strings");
mbstring->addItems(s);
searchP11 = NULL;
}
Options::~Options()
{
if (searchP11)
delete searchP11;
}
void Options::on_extDNadd_clicked()
@ -78,12 +87,21 @@ QString Options::getStringOpt()
void Options::on_addButton_clicked(void)
{
load_pkcs11 l;
pkcs11_lib *lib;
QString fname, status;
QString fname;
fname = QFileDialog::getOpenFileName(this, l.caption,
getLibDir(), l.filter);
addLib(fname);
}
void Options::addLib(QString fname)
{
pkcs11_lib *lib;
QString status;
fname = QFileInfo(fname).canonicalFilePath();
if (fname.isEmpty() || pkcs11::get_lib(fname))
return;
try {
@ -94,11 +112,15 @@ void Options::on_addButton_clicked(void)
lib = NULL;
status = ex.getString();
}
status = status.trimmed();
QListWidgetItem *item = new QListWidgetItem(fname);
item->setToolTip(status);
if (lib)
item->setIcon(*MainWindow::doneIco);
pkcs11List->addItem(item);
if (searchP11)
QToolTip::showText(searchP11->mapToGlobal(
QPoint(0,0)), status);
}
void Options::on_removeButton_clicked(void)
@ -113,6 +135,16 @@ void Options::on_removeButton_clicked(void)
}
}
void Options::on_searchPkcs11_clicked(void)
{
if (!searchP11) {
searchP11 = new SearchPkcs11(this, QString());
connect(searchP11, SIGNAL(addLib(QString)),
this, SLOT(addLib(QString)));
}
searchP11->show();
}
void Options::setupPkcs11Provider(QString list)
{
pkcs11_lib_list libs = pkcs11::get_libs();

View File

@ -11,16 +11,19 @@
#include "ui_Options.h"
#include <QtGui/QDialog>
#include "lib/base.h"
#include "widgets/MainWindow.h"
#include "SearchPkcs11.h"
#include "MainWindow.h"
class Options: public QDialog, public Ui::Options
{
Q_OBJECT
private:
SearchPkcs11 *searchP11;
QStringList string_opts;
MainWindow *mw;
public:
Options(MainWindow *parent);
~Options();
void setupPkcs11Provider(QString list);
void setStringOpt(const QString string_opt);
QString getDnString();
@ -32,6 +35,8 @@ class Options: public QDialog, public Ui::Options
void on_extDNdel_clicked();
void on_addButton_clicked(void);
void on_removeButton_clicked(void);
void on_searchPkcs11_clicked(void);
void addLib(QString);
};
#endif

192
widgets/SearchPkcs11.cpp Normal file
View File

@ -0,0 +1,192 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2010 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include "SearchPkcs11.h"
#include "lib/base.h"
#include "lib/func.h"
#include "lib/pkcs11_lib.h"
#include <QtGui/QComboBox>
#include <QtGui/QLineEdit>
#include <QtGui/QFileDialog>
#include <QtGui/QPushButton>
#include <QtGui/QMessageBox>
#include <QtCore/QStringList>
#include <QtCore/QFile>
SearchPkcs11::SearchPkcs11(QWidget *parent, QString fname)
:QDialog(parent)
{
setupUi(this);
filename->setText(fname);
setWindowTitle(XCA_TITLE);
filename->setText(getLibDir());
searching = NULL;
}
SearchPkcs11::~SearchPkcs11()
{
if (searching)
search->click();
}
void SearchPkcs11::on_fileBut_clicked()
{
QString s = QFileDialog::getExistingDirectory(this, QString(XCA_TITLE),
filename->text());
if (!s.isEmpty()) {
QDir::convertSeparators(s);
filename->setText(s);
}
}
void SearchPkcs11::on_search_clicked()
{
if (searching) {
return;
}
searching = new searchThread(filename->text(),
getLibExtensions(),
subdirs->isChecked());
liblist->clear();
connect(searching, SIGNAL(updateLibs(QString)),
this, SLOT(updateLibs(QString)));
connect(searching, SIGNAL(updateCurrFile(QString)),
this, SLOT(updateCurrFile(QString)));
connect(searching, SIGNAL(finished()),
this, SLOT(finishSearch()));
connect(search, SIGNAL(clicked()),
searching, SLOT(cancelSearch()));
search->setText("Cancel");
searching->start();
}
void SearchPkcs11::finishSearch()
{
search->setText("Start");
currFile->setText(tr("The following files are possible PKCS#11 libraries"));
if (!searching)
return;
searching->wait(1000);
delete searching;
searching = NULL;
}
void SearchPkcs11::buttonPress(QAbstractButton *but)
{
QList<QListWidgetItem *> libitems;
QListWidgetItem *lib;
switch (buttonBox->standardButton(but)) {
case QDialogButtonBox::Ok:
accept();
break;
default:
case QDialogButtonBox::Cancel:
reject();
break;
case QDialogButtonBox::Open:
libitems = liblist->selectedItems();
foreach(lib, libitems)
loadItem(lib);
break;
}
}
void SearchPkcs11::loadItem(QListWidgetItem *lib)
{
emit addLib(lib->text());
delete lib;
}
void SearchPkcs11::updateCurrFile(QString f)
{
int len = f.length();
QString reduced = f;
QFontMetrics fm(currFile->font());
currFile->setToolTip(f);
while ((currFile->width() < (fm.width(reduced) -10)) && (len > 0)) {
len -= 10;
reduced = compressFilename(f, len);
}
currFile->setText(reduced);
currFile->update();
}
void SearchPkcs11::updateLibs(QString f)
{
liblist->addItem(new QListWidgetItem(f));
liblist->update();
}
searchThread::searchThread(QString _dir, QStringList _ext, bool _recursive)
{
dirname = _dir;
ext = _ext;
recursive = _recursive;
keepOnRunning = true;
}
void searchThread::cancelSearch()
{
keepOnRunning = false;
}
bool searchThread::checkLib(QString file)
{
qint64 siz;
int r = -1;
QFile qf(file);
siz = qf.size();
if (qf.open(QIODevice::ReadOnly)) {
uchar *p = qf.map(0, siz);
r = QByteArray::fromRawData((char*)p, siz)
.indexOf("C_GetFunctionList");
qf.unmap(p);
qf.close();
}
return r != -1;
}
void searchThread::search(QString mydir)
{
QDir dir = QDir(mydir);
QStringList files = dir.entryList(
QStringList(ext),
QDir::Files | QDir::Readable);
while (!files.isEmpty() && keepOnRunning) {
QString file = files.takeFirst();
if (file.isEmpty())
continue;
file = mydir + QDir::separator() + file;
emit updateCurrFile(file);
if (checkLib(file))
emit updateLibs(file);
}
if (recursive && keepOnRunning) {
QString d;
QStringList dirs = dir.entryList(QStringList(),
QDir::AllDirs | QDir::NoDotAndDotDot);
foreach(d, dirs) {
if (!keepOnRunning)
break;
QString s = mydir +QDir::separator() +d;
emit updateCurrFile(s);
search(s);
}
}
}

68
widgets/SearchPkcs11.h Normal file
View File

@ -0,0 +1,68 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2010 Christian Hohnstaedt.
*
* All rights reserved.
*/
#ifndef __SEARCHPKCS11DIALOG_H
#define __SEARCHPKCS11DIALOG_H
#include <QtCore/QThread>
#include "ui_SearchPkcs11.h"
class SearchPkcs11;
class searchThread: public QThread
{
Q_OBJECT
protected:
QString dirname;
QStringList ext;
bool recursive;
bool keepOnRunning;
bool checkLib(QString file);
public:
searchThread(QString _dir, QStringList _ext, bool _recursive);
void search(QString mydir);
void run()
{
search(dirname);
}
public slots:
void cancelSearch();
signals:
void updateCurrFile(QString f);
void updateLibs(QString f);
};
class SearchPkcs11: public QDialog, public Ui::SearchPkcs11
{
Q_OBJECT
protected:
void searchDir(QString dirname, bool subdirs);
searchThread *searching;
public:
SearchPkcs11(QWidget *parent, QString fname);
~SearchPkcs11();
public slots:
void on_search_clicked();
void on_fileBut_clicked();
void buttonPress(QAbstractButton *but);
void loadItem(QListWidgetItem *lib);
void updateLibs(QString f);
void updateCurrFile(QString f);
void finishSearch();
signals:
void addLib(QString);
};
#endif