Database hardening

- Delete invalid items (on demand)
- Be more tolerant against database errors
- Gracefully handle and repair corrupt databases
- Add "db_dump(.exe)" binary to all installations
This commit is contained in:
Christian Hohnstaedt 2014-11-15 23:45:43 +01:00
parent 848a78f352
commit aaf9339eab
11 changed files with 365 additions and 192 deletions

View File

@ -31,6 +31,7 @@ DMGSTAGE=$(BUILD)/xca-$(VERSION)
MACTARGET=$(DMGSTAGE)-$(DARWIN)
APPDIR=$(DMGSTAGE)/xca.app/Contents
all: db_dump$(SUFFIX)
ifeq ($(SUFFIX), .exe)
all: setup$(SUFFIX)
else
@ -74,9 +75,10 @@ headers: do.ui
$(MAKE) -C $* -f $(TOPDIR)/$*/Makefile \
VPATH=$(TOPDIR)/$*
db_dump: lib/.build-stamp
db_dump$(SUFFIX): lib/.build-stamp
$(MAKE) -C lib -f $(TOPDIR)/lib/Makefile \
VPATH=$(TOPDIR)/lib db_dump
VPATH=$(TOPDIR)/lib $@
cp lib/$@ $@
$(INSTTARGET): install.%: %/.build-stamp
mkdir -p $*
@ -119,24 +121,20 @@ snapshot:
git archive --format=tar --prefix=xca-$${HASH}/ HEAD | \
gzip -9 > xca-$${HASH}.tar.gz
install: xca$(SUFFIX) $(INSTTARGET)
install: xca$(SUFFIX) db_dump$(SUFFIX) $(INSTTARGET)
install -m 755 -d $(destdir)$(bindir)
install -m 755 xca $(destdir)$(bindir)
install -m 755 db_dump $(destdir)$(bindir)
$(STRIP) $(destdir)$(bindir)/xca
$(MACDEPLOYQT):
macdeployqt/macdeployqt:
$(MAKE) -C macdeployqt
setup.exe: xca$(SUFFIX) do.doc do.lang
setup.exe: xca$(SUFFIX) db_dump$(SUFFIX) do.doc do.lang
setup.exe: misc/xca.nsi
$(STRIP) xca$(SUFFIX)
$(MAKENSIS) -DINSTALLDIR=$(INSTALL_DIR) -DQTDIR=$(QTDIR) \
-DVERSION=$(VERSION) -DBDIR=$(BDIR) -DTOPDIR=$(TOPDIR)\
-NOCD -V2 $<
$(DMGSTAGE): xca$(SUFFIX) $(MACDEPLOYQT)
$(DMGSTAGE): xca$(SUFFIX) db_dump$(SUFFIX)
rm -rf $(DMGSTAGE)
mkdir -p $(DMGSTAGE)/xca.app/Contents/MacOS
mkdir -p $(DMGSTAGE)/xca.app/Contents/Resources
@ -144,7 +142,9 @@ $(DMGSTAGE): xca$(SUFFIX) $(MACDEPLOYQT)
ln -s /Applications $(DMGSTAGE)
install -m 644 $(TOPDIR)/COPYRIGHT $(DMGSTAGE)/COPYRIGHT.txt
install -m 755 xca $(DMGSTAGE)/xca.app/Contents/MacOS
install -m 755 db_dump $(DMGSTAGE)/xca.app/Contents/MacOS
$(STRIP) $(DMGSTAGE)/xca.app/Contents/MacOS/xca
$(STRIP) $(DMGSTAGE)/xca.app/Contents/MacOS/db_dump
$(MAKE) $(APPTARGET)
cp -r $(DMGSTAGE)/xca.app/Contents/Resources/*.html $(DMGSTAGE)/manual
ln -s xca.html $(DMGSTAGE)/manual/index.html

View File

@ -1,4 +1,13 @@
* Database hardening
- Delete invalid items (on demand)
- Be more tolerant against database errors
- Gracefully handle and repair corrupt databases
- add "db_dump(.exe)" binary to all installations
* Translation updates
* Optionally allow hash algos not supported by the token
* Select whether to translate established x509 terms
* Finish Token EC and DSA support - generate, import, export, sign
* SF Feat. Req. #57 More options for Distinguished Name
* Switch to autoconf for the configure script
* SF Feature Req. #76 Export private keys to clipboard
* EC Keys: show Curve name in table

View File

@ -17,6 +17,6 @@ OBJS=$(patsubst %, %.o, $(NAMES)) $(patsubst %, moc_%.o, $(MOCNAMES))
include $(TOPDIR)/Rules.mak
sinclude .depend
db_dump: db_dump.o db.o db.h
echo "'$(CPPFLAGS)'"
db_dump$(SUFFIX): db_dump.o db.o db.h
@$(PRINT) " LINK $@"
$(CC) $(CPPFLAGS) $(LDFLAGS) $(CFLAGS) db_dump.o db.o $(LIBS) -g -o $@

View File

@ -10,6 +10,8 @@
#include "func.h"
#include "exception.h"
#include <QtCore/QStringList>
#include <QtCore/QDebug>
#include <QtCore/QDateTime>
#ifdef WIN32
#include <windows.h>
#else
@ -24,6 +26,8 @@
#include <errno.h>
#endif
#define XNUM(n) CCHAR(QString::number((n), 16))
db::db(QString filename, QFlags<QFile::Permission> perm)
{
name = filename;
@ -80,9 +84,6 @@ bool db::verify_magic(void)
{
if (!eof())
if (ntohl(head.magic) != XCA_MAGIC) {
throw errorEx(QString("database error '") +
file.fileName() +"'",
"at: " + QString::number(head_offset));
return false;
}
return true;
@ -90,7 +91,7 @@ bool db::verify_magic(void)
bool db::eof()
{
return (head_offset == OFF_EOF);
return head_offset == file.size();
}
int db::find(enum pki_type type, QString name)
@ -121,7 +122,7 @@ void db::first(int flag)
if (ret < 0 )
fileIOerr("read");
if (ret==0) {
head_offset = OFF_EOF;
head_offset = file.size();
return;
}
if (!verify_magic())
@ -132,44 +133,90 @@ void db::first(int flag)
int db::next(int flag)
{
int ret;
qint64 ret;
qint64 garbage = -1;
int result = 1;
if (eof())
return 1;
head_offset += ntohl(head.len);
file.seek(head_offset);
ret = file.read((char*)&head, sizeof(db_header_t) );
if (ret==0) {
//printf("Next: EOF at %lu\n", head_offset);
head_offset = OFF_EOF;
if (head_offset >= file.size()) {
head_offset = file.size();
return 1;
}
if (ret < 0) {
fileIOerr("read");
return -1;
while (1) {
file.seek(head_offset);
ret = file.read((char*)&head, sizeof head);
if (ret==0) {
head_offset = file.size();
break;
}
if (ret < 0) {
fileIOerr("read");
return -1;
}
if (ret != sizeof head) {
qWarning("next(): Short read: 0x%s of 0x%s @ 0x%s",
XNUM(ret), XNUM(sizeof head),
XNUM(head_offset));
if (garbage != -1) {
ret += head_offset - garbage;
head_offset = garbage;
}
qWarning("next(): Truncating 0x%s garbage bytes @ 0x%s",
XNUM(ret), XNUM(head_offset));
if (backup())
file.resize(head_offset);
head_offset = file.size();
return -1;
}
qint64 hlen = ntohl(head.len);
if (!verify_magic()) {
if (garbage == -1)
garbage = head_offset;
head_offset += 1;
continue;
} else {
if (garbage != -1) {
qWarning("next(): 0x%s bytes garbage skipped at 0x%s",
XNUM(head_offset - garbage),
XNUM(garbage));
}
garbage = -1;
if (file.size() < head_offset + hlen) {
qWarning("next(): Short item (%s of %s) at 0x%s",
XNUM(ntohl(head.len)),
XNUM(file.size() - head_offset),
XNUM(head_offset));
garbage = head_offset;
/* invalidate the header */
qWarning("Invalidate short item @ 0x%s\n",
XNUM(head_offset));
file.seek(head_offset);
char inval = 0xcb; // 0xca +1
file.write(&inval, 1);
head_offset += 4;
continue;
}
}
if (!(ntohs(head.flags) & flag)) {
result = 0;
break;
} else {
head_offset += hlen;
}
}
if (ret != sizeof(db_header_t)) {
printf("Length broken: %d instead of %ld\n", ret,
(long)sizeof(db_header_t) );
//ftruncate(fd, head_offset);
head_offset = OFF_EOF;
return -1;
if (garbage != -1) {
qWarning("next(): 0x%s bytes garbage skipped at 0x%s",
XNUM(head_offset - garbage), XNUM(garbage));
}
if (!verify_magic()){
printf("Garbage found at %lu\n", (unsigned long)head_offset);
head_offset+=4;
return next(flag);
}
if (ntohs(head.flags) & flag)
return next(flag);
return 0;
return result;
}
void db::rename(enum pki_type type, QString name, QString n)
{
int ret;
qint64 ret;
first();
if (find(type, n) == 0) {
@ -186,7 +233,7 @@ void db::rename(enum pki_type type, QString name, QString n)
if (ret < 0) {
fileIOerr("write");
}
if (ret != sizeof(head)) {
if (ret != sizeof head) {
throw errorEx(QObject::tr("DB: Write error %1 - %2"
).arg(ret).arg(sizeof(head)));
}
@ -225,12 +272,12 @@ QString db::uniq_name(QString s, QList<enum pki_type> types)
int db::add(const unsigned char *p, int len, int ver, enum pki_type type,
QString name)
{
db_header_t db;
db_header_t head;
init_header(&db, ver, len, type, name);
init_header(&head, ver, len, type, name);
file.seek(file.size());
if (file.write((char*)&db, sizeof(db)) != sizeof(db)) {
if (file.write((char*)&head, sizeof head) != sizeof head) {
fileIOerr("write");
return -1;
}
@ -244,27 +291,21 @@ int db::add(const unsigned char *p, int len, int ver, enum pki_type type,
int db::set(const unsigned char *p, int len, int ver, enum pki_type type,
QString name)
{
int ret;
qint64 ret;
first();
ret = find(type, name);
if (ret == 1) {
if (ret != 0) {
return add(p, len, ver, type, name);
}
if (ret == 0) {
//printf("offs = %x, len=%d, head.len=%d name = %s flags=%x\n",
// head_offset, len, ntohl(head.len), head.name,
// ntohs(head.flags));
} else {
file.seek(head_offset);
if (len != (int)(ntohl(head.len) - sizeof(db_header_t))) {
//printf("## Found and len unequal %d, %d\n",
// len, ntohl(head.len) - sizeof(db_header_t));
int flags;
flags = head.flags;
head.flags |= htons(DBFLAG_DELETED | DBFLAG_OUTDATED);
if (file.write((char*)&head, sizeof(db_header_t)) !=
sizeof(db_header_t))
if (file.write((char*)&head, sizeof head) !=
sizeof head)
{
fileIOerr("write");
return -1;
@ -272,16 +313,14 @@ int db::set(const unsigned char *p, int len, int ver, enum pki_type type,
if (add(p, len, ver, type, name) < 0) {
file.seek(head_offset);
head.flags = flags;
ret = file.write((char*)&head, sizeof(db_header_t));
if (ret != sizeof(db_header_t))
ret = file.write((char*)&head, sizeof head);
if (ret != sizeof head)
fileIOerr("write");
}
return 0;
}
//printf("## Overwriting entry at %u\n", head_offset);
head.version = htons(ver);
if (file.write((char*)&head, sizeof(db_header_t)) !=
sizeof(db_header_t)) {
if (file.write((char*)&head, sizeof head) != sizeof head) {
fileIOerr("write");
return -1;
}
@ -297,7 +336,7 @@ int db::set(const unsigned char *p, int len, int ver, enum pki_type type,
unsigned char *db::load(db_header_t *u_header)
{
uint32_t size;
unsigned ret;
qint64 ret;
unsigned char *data;
if (eof())
@ -306,13 +345,14 @@ unsigned char *db::load(db_header_t *u_header)
data = (unsigned char *)malloc(size);
file.seek(head_offset + sizeof(db_header_t));
ret = file.read((char*)data, size);
if (ret == size) {
if (ret == (qint64)size) {
if (u_header)
convert_header(u_header);
return data;
} else {
free(data);
fileIOerr("read");
if (ret < 0)
fileIOerr("read");
return NULL;
}
}
@ -342,10 +382,11 @@ int db::erase(void)
int db::shrink(int flags)
{
int ret;
qint64 ret, garbage = -1;
uint32_t offs;
char buf[BUFSIZ];
QFile new_file;
int result = 0;
new_file.setFileName(name + "{new}");
if (!new_file.open(QIODevice::ReadWrite)) {
@ -354,29 +395,57 @@ int db::shrink(int flags)
}
file.reset();
while ((ret = file.read((char*)&head, sizeof(head))) > 0) {
if (!verify_magic())
return 1;
head_offset = ntohl(head.len) - sizeof(head);
if ((ntohs(head.flags) & flags)) {
//printf("Skip Entry\n");
/* FF to the next entry */
offs = file.seek(head_offset + file.pos());
//printf("Seeking to %d\n", offs);
if (head_offset == -1)
break;
while ((ret = file.read((char*)&head, sizeof head)) > 0) {
if (ret < sizeof head) {
qWarning("shrink(): Short read: 0x%s instead of 0x%s",
XNUM(ret), XNUM(sizeof head));
result = 1;
break;
}
if (!verify_magic()) {
file.seek(file.pos() - sizeof(head) +1);
if (garbage == -1)
garbage = file.pos() -1;
result = 1;
continue;
}
if (garbage != -1)
qWarning("shrink(): 0x%s garbage found at %s",
XNUM(file.pos() - sizeof head - garbage),
XNUM(garbage));
garbage = -1;
head_offset = ntohl(head.len) - sizeof(head);
if ((ntohs(head.flags) & flags)) {
/* FF to the next entry */
if (!file.seek(head_offset + file.pos())) {
result = 1;
break;
}
continue;
}
if (head_offset + file.pos() > file.size()) {
file.seek(file.pos() - sizeof(head) +4);
if (garbage == -1)
garbage = file.pos() -4;
continue;
}
ret = new_file.write((char*)&head, sizeof(head));
if (ret != sizeof(head))
if (ret != sizeof(head)) {
result = 2;
break;
}
offs = head_offset;
while (offs) {
ret = file.read((char*)buf, (offs > BUFSIZ) ? BUFSIZ : offs);
if (ret<=0)
if (ret <= 0) {
result = 3;
break;
if (new_file.write(buf, ret) != ret)
}
if (new_file.write(buf, ret) != ret) {
result = 4;
break;
}
offs -= ret;
}
if (offs)
@ -384,12 +453,71 @@ int db::shrink(int flags)
}
new_file.close();
if (ret) {
unlink(QString2filename(new_file.fileName()));
return 1;
}
file.close();
return mv(new_file);
QString backup, orig;
switch (result) {
case 0:
/* everything is fine */
result = mv(new_file);
break;
case 1:
/* Some repaireable errors in the database occured.
* Keep the original as backup */
backup = backup_name();
QFile::remove(backup);
orig = file.fileName();
if (file.rename(backup)) {
new_file.rename(orig);
} else {
QFile::remove(new_file.fileName());
result = 2;
}
break;
case 2:
case 3:
case 4:
QFile::remove(new_file.fileName());
result = 2;
break;
}
return result;
}
QString db::backup_name()
{
return file.fileName() + "_backup_" +
QDateTime::currentDateTime()
.toString("yyyyMMdd_hhmmss") + ".xdb";
}
bool db::backup()
{
QFile this_file, new_file;
QString backup = backup_name();
qint64 ret, wret;
char buf[BUFSIZ];
this_file.setFileName(file.fileName());
if (!this_file.open(QIODevice::ReadOnly)) {
return false;
}
new_file.setFileName(backup);
if (!new_file.open(QIODevice::ReadWrite)) {
this_file.close();
return false;
}
while (1) {
ret = this_file.read(buf, sizeof buf);
if (ret <= 0)
break;
wret = new_file.write(buf, ret);
if (wret != ret)
break;
}
this_file.close();
new_file.close();
return ret == 0;
}
int db::mv(QFile &new_file)
@ -406,7 +534,7 @@ int db::mv(QFile &new_file)
} else {
QFile::rename(tempn, name);
QFile::remove(new_file.fileName());
return 1;
return 2;
}
}
return 0;
@ -416,7 +544,7 @@ int db::mv(QFile &new_file)
check_oom(newfile);
int ret = ::rename(newfile, QString2filename(name)) == -1;
free(newfile);
return ret;
return ret == 0 ? 0 : 2;
#endif
}

View File

@ -18,7 +18,6 @@
#define XCA_MAGIC 0xcadb1969
#define NAMELEN 80
#define FNAMLEN 256
#define OFF_EOF ((off_t)-1)
#define DBFLAG_DELETED 0x1
#define DBFLAG_OUTDATED 0x2
@ -57,10 +56,12 @@ class db
QString name);
void convert_header(db_header_t *h);
void fileIOerr(QString s);
QString backup_name();
bool backup();
public:
bool verify_magic(void);
off_t head_offset;
qint64 head_offset;
db(QString, QFlags<QFile::Permission> perm = QFile::ReadOwner | QFile::WriteOwner);
~db();
bool eof();

View File

@ -5,6 +5,11 @@
* All rights reserved.
*/
#ifdef WIN32
#include <windows.h>
#else
#include <netinet/in.h>
#endif
#include "db_base.h"
#include "func.h"
@ -13,6 +18,7 @@
#include <QtGui/QListView>
#include <QtGui/QClipboard>
#include <QtCore/QDir>
#include <QtCore/QDebug>
#include "widgets/MainWindow.h"
#include "widgets/ImportMulti.h"
@ -64,6 +70,55 @@ void db_base::remFromCont(QModelIndex &idx)
emit columnsContentChanged();
}
int db_base::handleBadEntry(unsigned char *p, db_header_t *head)
{
QString name = QString::fromUtf8(head->name);
QString txt = tr("Bad database item\nName: %1\nType: %2\nSize: %3\n%4")
.arg(name).arg(class_name)
.arg(head->len - sizeof(db_header_t))
.arg(tr("Do you want to delete the item from the database? The bad item may be extracted into a separate file."));
xcaWarning msg(mainwin, txt);
msg.addButton(QMessageBox::Ok)->setText(tr("Delete"));
msg.addButton(QMessageBox::Apply)->setText(tr("Delete and extract"));
msg.addButton(QMessageBox::Cancel)->setText(tr("Continue"));
switch (msg.exec()) {
case QMessageBox::Ok:
return 1;
case QMessageBox::Cancel:
default:
return 0;
case QMessageBox::Apply:
break;
}
QString s = QFileDialog::getSaveFileName(mainwin, QString(), name,
QString(), NULL, QFileDialog::DontConfirmOverwrite);
size_t l;
db_header_t h;
FILE *fp = fopen(QString2filename(s), "w");
if (!fp) {
throw errorEx(tr("Error opening file: '%1': %2").
arg(s).arg(strerror(errno)), class_name);
}
h.magic = ntohl(head->magic);
h.len = ntohl(head->len);
h.headver = ntohs(head->headver);
h.type = ntohs(head->type);
h.version = ntohs(head->version);
h.flags = ntohs(head->flags);
memcpy(h.name, head->name, NAMELEN);
l = fwrite(&h, sizeof h, 1, fp);
l += fwrite(p, head->len - sizeof h, 1, fp);
fclose(fp);
return (l == 2);
}
void db_base::loadContainer()
{
db mydb(dbName);
@ -77,13 +132,13 @@ void db_base::loadContainer()
QString s;
p = mydb.load(&head);
if (!p) {
printf("Load was empty !\n");
qWarning("Load was empty !");
goto next;
}
pki = newPKI(&head);
if (pki->getVersion() < head.version) {
printf("Item[%s]: Version %d "
"> known version: %d -> ignored\n",
qWarning("Item[%s]: Version %d "
"> known version: %d -> ignored",
head.name, head.version,
pki->getVersion()
);
@ -101,6 +156,13 @@ void db_base::loadContainer()
mainwin->Error(err);
delete pki;
pki = NULL;
try {
if (handleBadEntry(p, &head)) {
mydb.erase();
}
} catch (errorEx &err) {
mainwin->Error(err);
}
}
free(p);
if (pki) {

View File

@ -42,6 +42,8 @@ class db_base: public QAbstractItemModel
QString class_name;
dbheaderList allHeaders;
int colResizing;
int handleBadEntry(unsigned char *p, db_header_t *head);
public:
pki_base *rootItem;
db_base(QString db, MainWindow *mw);

View File

@ -8,7 +8,7 @@
#include "db.h"
#include "exception.h"
#include <stdlib.h>
#include <qbytearray.h>
#include <QtCore/QByteArray>
QByteArray filename2bytearray(const QString &fname)
{
@ -53,17 +53,25 @@ int main(int argc, char *argv[])
unsigned char *p;
db_header_t h;
int i=0;
char type[] = "NKRCLTSUXX";
const char *type[] = {
"(none)", "Software Key", "Request", "Certificate",
"Revocation", "Template", "Setting", "Token key"
};
try {
mydb.first(0);
printf("Index Type Ver Offset Flags Len Name\n");
while (!mydb.eof()) {
p = mydb.load(&h);
free(p);
printf("%3d: %c V%d O:%6zd, F:%x L:%5d %s\n",
i++, type[h.type], h.version, mydb.head_offset,
if (h.type > smartCard)
h.type = 0;
printf("%5d %-12s%5d%7zx%6x%6x %s\n",
i++, type[h.type], h.version,
(size_t)mydb.head_offset,
h.flags, h.len, h.name);
mydb.next(0);
if (mydb.next(0))
break;
}
} catch (errorEx &ex) {
printf("Exception: '%s'\n", ex.getCString());

View File

@ -60,6 +60,7 @@ Section "xca (required)" SecMain
SetOutPath $INSTDIR
; Put files there
File "xca.exe"
File "db_dump.exe"
File "${TOPDIR}/misc\dn.txt"
File "${TOPDIR}/misc\eku.txt"
File "${TOPDIR}/misc\oids.txt"

View File

@ -11,6 +11,7 @@
#include "lib/pki_evp.h"
#include "lib/pki_scard.h"
#include <QtCore/QDir>
#include <QtCore/QDebug>
#include <QtGui/QStatusBar>
#include <QtGui/QMessageBox>
#include "lib/db_base.h"
@ -18,10 +19,24 @@
#include "widgets/ImportMulti.h"
#include "widgets/NewKey.h"
void MainWindow::set_geometry(char *p, db_header_t *head)
{
if (head->version != 1)
return;
QByteArray ba = QByteArray::fromRawData(p, head->len);
int w, h, i;
w = db::intFromData(ba);
h = db::intFromData(ba);
i = db::intFromData(ba);
resize(w,h);
if (i != -1)
tabView->setCurrentIndex(i);
}
int MainWindow::init_database()
{
int ret = 2;
fprintf(stderr, "Opening database: %s\n", QString2filename(dbfile));
qDebug("Opening database: %s", QString2filename(dbfile));
keys = NULL; reqs = NULL; certs = NULL; temps = NULL; crls = NULL;
certView->setRootIsDecorated(db_x509::treeview);
@ -44,10 +59,6 @@ int MainWindow::init_database()
mandatory_dn = "";
explicit_dn = explicit_dn_default;
pki_base::suppress_messages = false;
pki_x509::dont_colorize_expiries = false;
translate_dn = false;
pki_scard::only_token_hashes = false;
string_opt = QString("MASK:0x2002");
ASN1_STRING_set_default_mask_asc((char*)CCHAR(string_opt));
@ -55,6 +66,7 @@ int MainWindow::init_database()
pkcs11path = getDefaultPkcs11Lib();
workingdir = QDir::currentPath();
setOptFlags((QString()));
try {
pkcs11_lib p(pkcs11path);
} catch (errorEx &e) {
@ -93,115 +105,59 @@ int MainWindow::init_database()
certView->setModel(certs);
tempView->setModel(temps);
crlView->setModel(crls);
try {
db mydb(dbfile);
char *p;
if (!mydb.find(setting, "workingdir")) {
if ((p = (char *)mydb.load(NULL))) {
while (mydb.find(setting, QString()) == 0) {
QString key;
db_header_t head;
char *p = (char *)mydb.load(&head);
if (!p) {
if (mydb.next())
break;
continue;
}
key = head.name;
if (key == "workingdir")
workingdir = p;
free(p);
}
}
mydb.first();
if (!mydb.find(setting, "pkcs11path")) {
if ((p = (char *)mydb.load(NULL))) {
else if (key == "pkcs11path")
pkcs11path = p;
free(p);
}
}
mydb.first();
if (!mydb.find(setting, "default_hash")) {
if ((p = (char *)mydb.load(NULL))) {
else if (key == "default_hash")
hashBox::setDefault(p);
free(p);
}
}
mydb.first();
if (!mydb.find(setting, "mandatory_dn")) {
if ((p = (char *)mydb.load(NULL))) {
else if (key == "mandatory_dn")
mandatory_dn = p;
free(p);
}
}
mydb.first();
if (!mydb.find(setting, "explicit_dn")) {
if ((p = (char *)mydb.load(NULL))) {
else if (key == "explicit_dn")
explicit_dn = p;
free(p);
}
}
// what a stupid idea....
mydb.first();
if (!mydb.find(setting, "multiple_key_use")) {
mydb.erase();
}
mydb.first();
if (!mydb.find(setting, "string_opt")) {
if ((p = (char *)mydb.load(NULL))) {
/* what a stupid idea.... */
else if (key == "multiple_key_use")
mydb.erase();
else if (key == "string_opt")
string_opt = p;
free(p);
}
}
mydb.first();
if (!mydb.find(setting, "suppress")) {
if ((p = (char *)mydb.load(NULL))) {
QString x = p;
free(p);
if (x == "1")
pki_base::suppress_messages = 1;
}
}
mydb.first();
if (!mydb.find(setting, "optionflags1")) {
if ((p = (char *)mydb.load(NULL))) {
else if (key == "suppress")
mydb.erase();
else if (key == "optionflags1")
setOptFlags((QString(p)));
free(p);
}
} else {
/* Different optionflags, since setOptFlags()
* does an abort() for unknown flags in
* older versions. *Another stupid idea*
* This is for backward compatibility
*/
mydb.first();
if (!mydb.find(setting, "optionflags")) {
if ((p = (char *)mydb.load(NULL))) {
setOptFlags_old((QString(p)));
free(p);
}
}
}
mydb.first();
if (!mydb.find(setting, "defaultkey")) {
if ((p = (char *)mydb.load(NULL))) {
else if (key == "optionflags")
setOptFlags_old((QString(p)));
else if (key == "defaultkey")
NewKey::setDefault((QString(p)));
free(p);
}
}
ASN1_STRING_set_default_mask_asc((char*)CCHAR(string_opt));
mydb.first();
if (!mydb.find(setting, "mw_geometry")) {
db_header_t h;
if ((p = (char *)mydb.load(&h))) {
if (h.version == 1) {
QByteArray ba;
ba = QByteArray::fromRawData(p, h.len);
int w, h, i;
w = db::intFromData(ba);
h = db::intFromData(ba);
i = db::intFromData(ba);
resize(w,h);
if (i != -1)
tabView->setCurrentIndex(i);
}
free(p);
}
else if (key == "mw_geometry")
set_geometry(p, &head);
free(p);
if (mydb.next())
break;
}
} catch (errorEx &err) {
Error(err);
return ret;
}
ASN1_STRING_set_default_mask_asc((char*)CCHAR(string_opt));
if (explicit_dn.isEmpty())
explicit_dn = explicit_dn_default;
setWindowTitle(tr(XCA_TITLE));
@ -367,8 +323,13 @@ void MainWindow::close_database()
try {
int ret;
db mydb(dbfile);
mydb.shrink( DBFLAG_OUTDATED | DBFLAG_DELETED );
ret = mydb.shrink( DBFLAG_OUTDATED | DBFLAG_DELETED );
if (ret == 1)
XCA_INFO(tr("Errors detected and repaired while deleting outdated items from the database. A backup file was created"));
if (ret == 2)
XCA_INFO(tr("Removing deleted or outdated items from the database failed."));
}
catch (errorEx &err) {
MainWindow::Error(err);

View File

@ -76,6 +76,7 @@ class MainWindow: public QMainWindow, public Ui::MainWindow
QStringList history;
tipMenu *historyMenu;
void update_history_menu();
void set_geometry(char *p, db_header_t *head);
protected:
void init_images();