mirror of
https://github.com/chris2511/xca.git
synced 2026-09-14 11:06:19 +05:00
- Only once set notBefore to "now" when creating Cert-renewal or NewCert dialog. - Apply-time button now always uses the current value from notBefore and adds the time-span without resetting notBefore - Checking "midnight" now immediately modifies the dates. Unchecking "midnight" now recovers the old value - The seconds are always set to 00, since they can't be set via the DateTime dialog anyway - CRL generation now too allows to use midnight and time ranges and uses GENERALIZED time if the date is out of range for UTCTIME (same logic as for certificates)
328 lines
7.4 KiB
C++
328 lines
7.4 KiB
C++
/* vi: set sw=4 ts=4:
|
|
*
|
|
* Copyright (C) 2001 - 2010 Christian Hohnstaedt.
|
|
*
|
|
* All rights reserved.
|
|
*/
|
|
|
|
|
|
#include "func.h"
|
|
#include "exception.h"
|
|
#include "lib/asn1time.h"
|
|
#include "widgets/validity.h"
|
|
#include <openssl/objects.h>
|
|
#include <openssl/asn1.h>
|
|
#include <openssl/err.h>
|
|
|
|
#if defined(Q_WS_MAC)
|
|
#include <QtGui/QDesktopServices>
|
|
#endif
|
|
#include <QtCore/QDir>
|
|
#include <QtCore/QFile>
|
|
#include <QtCore/QStringList>
|
|
#include <QtGui/QLabel>
|
|
#include <QtGui/QLineEdit>
|
|
#include <QtGui/QComboBox>
|
|
#include <QtGui/QMessageBox>
|
|
#include <QtGui/QApplication>
|
|
#include <QtGui/QPushButton>
|
|
#include <QtGui/QProgressBar>
|
|
|
|
#ifdef WIN32
|
|
#include <windows.h>
|
|
#include <shlobj.h>
|
|
#else
|
|
/* for htons() */
|
|
#include <netinet/in.h>
|
|
#endif
|
|
|
|
QPixmap *loadImg(const char *name )
|
|
{
|
|
return new QPixmap(QString(":") + name);
|
|
}
|
|
|
|
/* returns e.g. /usr/local/share/xca for unix systems
|
|
* or HKEY_LOCAL_MACHINE->Software->xca for WIN32
|
|
* (e.g. c:\Program Files\xca )
|
|
*/
|
|
|
|
QString getPrefix()
|
|
{
|
|
#ifdef WIN32
|
|
static char inst_dir[100] = "";
|
|
char *p;
|
|
ULONG dwLength = 100;
|
|
LONG lRc;
|
|
HKEY hKey;
|
|
|
|
if (inst_dir[0] != '\0') {
|
|
/* if we already once discovered the directory just return it */
|
|
return QString(inst_dir);
|
|
}
|
|
// fallback: directory of xca.exe
|
|
GetModuleFileName(0, inst_dir, dwLength - 1);
|
|
p = strrchr(inst_dir, '\\');
|
|
if (p) {
|
|
*p = '\0';
|
|
return QString(inst_dir);
|
|
}
|
|
p = inst_dir;
|
|
*p = '\0';
|
|
lRc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\xca", 0, KEY_READ, &hKey);
|
|
if (lRc != ERROR_SUCCESS) {
|
|
QMessageBox::warning(NULL,XCA_TITLE,
|
|
"Registry Key: 'HKEY_LOCAL_MACHINE->Software->xca' not found");
|
|
return QString(inst_dir);
|
|
}
|
|
lRc = RegQueryValueEx(hKey, "Install_Dir", NULL, NULL,
|
|
(unsigned char *)inst_dir, &dwLength);
|
|
if (lRc != ERROR_SUCCESS){
|
|
QMessageBox::warning(NULL, XCA_TITLE, "Registry Key: "
|
|
"'HKEY_LOCAL_MACHINE->Software->xca->Install_Dir' not found");
|
|
}
|
|
lRc = RegCloseKey(hKey);
|
|
return QString(inst_dir);
|
|
|
|
#elif defined(Q_WS_MAC)
|
|
// since this is platform-specific anyway,
|
|
// this is a more robust way to get the bundle directory
|
|
QDir bundleDir(qApp->applicationDirPath());
|
|
bundleDir.cdUp();
|
|
return bundleDir.canonicalPath() + "/Resources";
|
|
#else
|
|
return QString(PREFIX) + "/share/xca";
|
|
#endif
|
|
|
|
}
|
|
|
|
QString getHomeDir()
|
|
{
|
|
QString hd;
|
|
#ifdef WIN32
|
|
LPITEMIDLIST pidl = NULL;
|
|
TCHAR buf[255] = "";
|
|
if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_PERSONAL, &pidl))) {
|
|
SHGetPathFromIDList(pidl, buf);
|
|
}
|
|
hd = buf;
|
|
#else
|
|
hd = QDir::homePath();
|
|
#endif
|
|
return hd;
|
|
}
|
|
|
|
QString getDocDir()
|
|
{
|
|
#if defined(WIN32) || defined (Q_WS_MAC)
|
|
return getPrefix();
|
|
#else
|
|
return QString(DOCDIR);
|
|
#endif
|
|
}
|
|
|
|
// The intent of this function is to return the proper location for
|
|
// user-controlled settings on the current platform
|
|
// i.e. PROFILE\Application Data\xca on windows, HOME/.xca on UNIX,
|
|
// ~/Library/Preferences/xca on Mac OS X
|
|
QString getUserSettingsDir()
|
|
{
|
|
QString rv;
|
|
#ifdef WIN32
|
|
/* not called on WIN32 platforms */
|
|
QMessageBox::warning(NULL, XCA_TITLE, "No not to be called");
|
|
#elif defined(Q_WS_MAC)
|
|
rv = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
|
|
rv.insert(rv.count() - QCoreApplication::applicationName().count(),
|
|
QCoreApplication::organizationName() + "/");
|
|
#else
|
|
rv = QDir::homePath();
|
|
rv += QDir::separator();
|
|
rv += ".xca";
|
|
#endif
|
|
return rv;
|
|
}
|
|
|
|
// Qt's open and save dialogs result in some undesirable quirks.
|
|
// This function makes sure that a filename has the user-selected extension.
|
|
QString getFullFilename(const QString & filename, const QString & selectedFilter)
|
|
{
|
|
QString rv = filename.trimmed(), ext;
|
|
QRegExp rx(".* \\( ?\\*(.[a-z]{1,3}) ?\\)");
|
|
rx.indexIn(selectedFilter);
|
|
ext = rx.cap(1);
|
|
if (!ext.isEmpty() && !rv.endsWith(ext)) {
|
|
rv += ext;
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
QByteArray filename2bytearray(const QString &fname)
|
|
{
|
|
#ifdef WIN32
|
|
return fname.toLocal8Bit();
|
|
#else
|
|
return fname.toUtf8();
|
|
#endif
|
|
}
|
|
|
|
QString filename2QString(const char *fname)
|
|
{
|
|
#ifdef WIN32
|
|
return QString::fromLocal8Bit(fname);
|
|
#else
|
|
return QString::fromUtf8(fname);
|
|
#endif
|
|
}
|
|
|
|
QString asn1ToQString(const ASN1_STRING *str)
|
|
{
|
|
QString qs;
|
|
unsigned short *bmp;
|
|
int i;
|
|
|
|
if (!str)
|
|
return qs;
|
|
|
|
switch (str->type) {
|
|
case V_ASN1_BMPSTRING:
|
|
bmp = (unsigned short*)str->data;
|
|
for (i = 0; i < str->length/2; i++) {
|
|
unsigned short s = ntohs(bmp[i]);
|
|
qs += QString::fromUtf16(&s, 1);
|
|
}
|
|
break;
|
|
case V_ASN1_UTF8STRING:
|
|
qs = QString::fromUtf8((const char*)str->data, str->length);
|
|
break;
|
|
case V_ASN1_T61STRING:
|
|
qs = QString::fromLocal8Bit((const char*)str->data, str->length);
|
|
break;
|
|
default:
|
|
qs = QString::fromLatin1((const char*)str->data, str->length);
|
|
}
|
|
#if 0
|
|
printf("Convert %s (%d %d) string to '%s' len %d:", ASN1_tag2str(str->type), str->type, V_ASN1_UTF8STRING, CCHAR(qs), str->length);
|
|
for (int i=0; i< str->length; i++)
|
|
printf(" %02x", str->data[i]);
|
|
printf("\n");
|
|
#endif
|
|
return qs;
|
|
}
|
|
|
|
/* returns an encoded ASN1 string from QString for a special nid*/
|
|
ASN1_STRING *QStringToAsn1(const QString s, int nid)
|
|
{
|
|
QByteArray ba = s.toUtf8();
|
|
const unsigned char *utf8 = (const unsigned char *)ba.constData();
|
|
return ASN1_STRING_set_by_NID(NULL, utf8, -1, MBSTRING_UTF8, nid);
|
|
}
|
|
|
|
const char *OBJ_ln2sn(const char *ln)
|
|
{
|
|
return OBJ_nid2sn(OBJ_ln2nid(ln));
|
|
}
|
|
|
|
const char *OBJ_sn2ln(const char *sn)
|
|
{
|
|
return OBJ_nid2ln(OBJ_sn2nid(sn));
|
|
}
|
|
|
|
QString changeFilenameSuffix(QString fn, const QStringList &suffixlist,
|
|
int selected)
|
|
{
|
|
if (selected <0 || selected >= suffixlist.size())
|
|
return fn;
|
|
|
|
foreach(QString suffix, suffixlist) {
|
|
if (fn.endsWith(QString(".") +suffix)) {
|
|
return fn.left(fn.length() -suffix.length()) +
|
|
suffixlist[selected];
|
|
}
|
|
}
|
|
return fn;
|
|
}
|
|
|
|
bool mayWriteFile(const QString &fname)
|
|
{
|
|
if (QFile::exists(fname)) {
|
|
QMessageBox msg(QMessageBox::Warning, XCA_TITLE,
|
|
QObject::tr("The file: '%1' already exists!").
|
|
arg(fname));
|
|
msg.addButton(QMessageBox::Ok)->setText(
|
|
QObject::tr("Overwrite"));
|
|
msg.addButton(QMessageBox::Cancel)->setText(
|
|
QObject::tr("Do not overwrite"));
|
|
if (msg.exec() != QMessageBox::Ok)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
QByteArray i2d_bytearray(int(*i2d)(const void*, unsigned char **),
|
|
const void *data)
|
|
{
|
|
QByteArray ba;
|
|
|
|
ba.resize(i2d(data, NULL));
|
|
unsigned char *p = (unsigned char*)ba.data();
|
|
i2d(data, &p);
|
|
openssl_error();
|
|
return ba;
|
|
}
|
|
|
|
void *d2i_bytearray(void *(*d2i)(void *, unsigned char **, long),
|
|
QByteArray &ba)
|
|
{
|
|
unsigned char *p, *p1;
|
|
void *ret;
|
|
p = p1 = (unsigned char *)ba.constData();
|
|
ret = d2i(NULL, &p1, ba.count());
|
|
ba = ba.mid(p1-p);
|
|
openssl_error();
|
|
return ret;
|
|
}
|
|
|
|
void _openssl_error(const QString txt, const char *file, int line)
|
|
{
|
|
QString error;
|
|
|
|
while (int i = ERR_get_error() ) {
|
|
error += QString(ERR_error_string(i, NULL)) + "\n";
|
|
fprintf(stderr, CCHAR(QString("OpenSSL error (%1:%2) : %3\n").
|
|
arg(file).arg(line).arg(ERR_error_string(i, NULL))));
|
|
}
|
|
if (!error.isEmpty()) {
|
|
if (!txt.isEmpty())
|
|
error = txt + "\n" + error + "\n" +
|
|
QString("(%1:%2").arg(file).arg(line);
|
|
throw errorEx(error);
|
|
}
|
|
}
|
|
|
|
bool _ign_openssl_error(const char *file, int line)
|
|
{
|
|
// ignore openssl errors
|
|
QString errtxt;
|
|
while (int i = ERR_get_error() ) {
|
|
errtxt = ERR_error_string(i, NULL);
|
|
fprintf(stderr, CCHAR(QString("IGNORED (%1:%2) : %3\n").
|
|
arg(file).arg(line).arg(errtxt)));
|
|
}
|
|
return !errtxt.isEmpty();
|
|
}
|
|
|
|
void inc_progress_bar(int, int, void *p)
|
|
{
|
|
QProgressBar *bar = (QProgressBar *)p;
|
|
int value = bar->value();
|
|
|
|
if (value == bar->maximum()) {
|
|
bar->reset();
|
|
} else {
|
|
bar->setValue(value +1);
|
|
}
|
|
}
|
|
|