00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "ksslkeygen.h"
00023 #include "ksslkeygen_p.h"
00024 #include "ui_keygenwizard.h"
00025
00026 #include <kapplication.h>
00027 #include <kdebug.h>
00028 #include <klocale.h>
00029 #include <kmessagebox.h>
00030 #include <kopenssl.h>
00031 #include <kprogressdialog.h>
00032 #include <kstandarddirs.h>
00033 #include <ktemporaryfile.h>
00034 #include <kwallet.h>
00035
00036 #include <QtGui/QLineEdit>
00037 #include <QtGui/QPushButton>
00038
00039 #include <assert.h>
00040
00041 KSSLKeyGenWizardPage2::KSSLKeyGenWizardPage2(QWidget* parent)
00042 : QWizardPage(parent)
00043 {
00044 ui2 = new Ui_KGWizardPage2;
00045 ui2->setupUi(this);
00046 connect(ui2->_password1, SIGNAL(textChanged(const QString&)), this, SLOT(slotPassChanged()));
00047 connect(ui2->_password2, SIGNAL(textChanged(const QString&)), this, SLOT(slotPassChanged()));
00048 }
00049
00050 bool KSSLKeyGenWizardPage2::isComplete() const
00051 {
00052 return ui2->_password1->text() == ui2->_password2->text() && ui2->_password1->text().length() >= 4;
00053 }
00054
00055 void KSSLKeyGenWizardPage2::slotPassChanged()
00056 {
00057 emit completeChanged();
00058 }
00059
00060 QString KSSLKeyGenWizardPage2::password() const
00061 {
00062 Q_ASSERT(isComplete());
00063 return ui2->_password1->text();
00064 }
00065
00067
00068 class KSSLKeyGenPrivate
00069 {
00070 public:
00071 KSSLKeyGenPrivate()
00072 : idx(-1)
00073 {
00074 }
00075 int idx;
00076 Ui_KGWizardPage1 *ui1;
00077 KSSLKeyGenWizardPage2* page2;
00078 };
00079
00080 KSSLKeyGen::KSSLKeyGen(QWidget *parent)
00081 : QWizard(parent), d(new KSSLKeyGenPrivate)
00082 {
00083 #ifdef KSSL_HAVE_SSL
00084
00085 QWizardPage* page1 = new QWizardPage(this);
00086 page1->setTitle(i18n("KDE Certificate Request"));
00087 d->ui1 = new Ui_KGWizardPage1;
00088 d->ui1->setupUi(page1);
00089 addPage(page1);
00090
00091
00092 d->page2 = new KSSLKeyGenWizardPage2(this);
00093 d->page2->setTitle(i18n("KDE Certificate Request - Password"));
00094 addPage(d->page2);
00095 #else
00096
00097 #endif
00098 }
00099
00100
00101 KSSLKeyGen::~KSSLKeyGen() {
00102 delete d->ui1;
00103 delete d;
00104 }
00105
00106 bool KSSLKeyGen::validateCurrentPage() {
00107 if (currentPage() != d->page2)
00108 return true;
00109
00110 assert(d->idx >= 0 && d->idx <= 3);
00111
00112
00113 int bits;
00114 switch (d->idx) {
00115 case 0:
00116 bits = 2048;
00117 break;
00118 case 1:
00119 bits = 1024;
00120 break;
00121 case 2:
00122 bits = 768;
00123 break;
00124 case 3:
00125 bits = 512;
00126 break;
00127 default:
00128 KMessageBox::sorry(this, i18n("Unsupported key size."), i18n("KDE SSL Information"));
00129 return false;
00130 }
00131
00132 KProgressDialog *kpd = new KProgressDialog(this);
00133 kpd->setObjectName("progress dialog");
00134 kpd->setWindowTitle(i18n("KDE"));
00135 kpd->setLabelText(i18n("Please wait while the encryption keys are generated..."));
00136 kpd->progressBar()->setValue(0);
00137 kpd->show();
00138
00139
00140 int rc = generateCSR("This CSR" , d->page2->password(), bits, 0x10001 );
00141 if (rc != 0)
00142 return false;
00143
00144 kpd->progressBar()->setValue(100);
00145
00146 #if 0 // TODO: implement
00147 if (rc == 0 && KWallet::Wallet::isEnabled()) {
00148 rc = KMessageBox::questionYesNo(this, i18n("Do you wish to store the passphrase in your wallet file?"), QString(), KGuiItem(i18n("Store")), KGuiItem(i18n("Do Not Store")));
00149 if (rc == KMessageBox::Yes) {
00150 KWallet::Wallet *w = KWallet::Wallet::openWallet(KWallet::Wallet::LocalWallet(), winId());
00151 if (w) {
00152
00153 delete w;
00154 }
00155 }
00156 }
00157 #endif
00158
00159 kpd->deleteLater();
00160 return true;
00161 }
00162
00163
00164 int KSSLKeyGen::generateCSR(const QString& name, const QString& pass, int bits, int e) {
00165 #ifdef KSSL_HAVE_SSL
00166 KOSSL *kossl = KOSSL::self();
00167 int rc;
00168
00169 X509_REQ *req = kossl->X509_REQ_new();
00170 if (!req) {
00171 return -2;
00172 }
00173
00174 EVP_PKEY *pkey = kossl->EVP_PKEY_new();
00175 if (!pkey) {
00176 kossl->X509_REQ_free(req);
00177 return -4;
00178 }
00179
00180 RSA *rsakey = kossl->RSA_generate_key(bits, e, NULL, NULL);
00181 if (!rsakey) {
00182 kossl->X509_REQ_free(req);
00183 kossl->EVP_PKEY_free(pkey);
00184 return -3;
00185 }
00186
00187 rc = kossl->EVP_PKEY_assign(pkey, EVP_PKEY_RSA, (char *)rsakey);
00188
00189 rc = kossl->X509_REQ_set_pubkey(req, pkey);
00190
00191
00192 X509_NAME *n = kossl->X509_NAME_new();
00193
00194 kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_countryName, MBSTRING_UTF8, (unsigned char*)name.toLocal8Bit().data(), -1, -1, 0);
00195 kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_organizationName, MBSTRING_UTF8, (unsigned char*)name.toLocal8Bit().data(), -1, -1, 0);
00196 kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_organizationalUnitName, MBSTRING_UTF8, (unsigned char*)name.toLocal8Bit().data(), -1, -1, 0);
00197 kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_localityName, MBSTRING_UTF8, (unsigned char*)name.toLocal8Bit().data(), -1, -1, 0);
00198 kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_stateOrProvinceName, MBSTRING_UTF8, (unsigned char*)name.toLocal8Bit().data(), -1, -1, 0);
00199 kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_commonName, MBSTRING_UTF8, (unsigned char*)name.toLocal8Bit().data(), -1, -1, 0);
00200 kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_pkcs9_emailAddress, MBSTRING_UTF8, (unsigned char*)name.toLocal8Bit().data(), -1, -1, 0);
00201
00202 rc = kossl->X509_REQ_set_subject_name(req, n);
00203
00204
00205 rc = kossl->X509_REQ_sign(req, pkey, kossl->EVP_md5());
00206
00207
00208
00209
00210
00211 KGlobal::dirs()->addResourceType("kssl", "data", "kssl");
00212
00213 QString path = KGlobal::dirs()->saveLocation("kssl");
00214 KTemporaryFile csrFile;
00215 csrFile.setAutoRemove(false);
00216 csrFile.setPrefix(path + "csr_");
00217 csrFile.setSuffix(".der");
00218
00219 if (!csrFile.open()) {
00220 kossl->X509_REQ_free(req);
00221 kossl->EVP_PKEY_free(pkey);
00222 return -5;
00223 }
00224
00225 KTemporaryFile p8File;
00226 p8File.setAutoRemove(false);
00227 p8File.setPrefix(path + "pkey_");
00228 p8File.setSuffix(".p8");
00229
00230 if (!p8File.open()) {
00231 kossl->X509_REQ_free(req);
00232 kossl->EVP_PKEY_free(pkey);
00233 return -5;
00234 }
00235
00236 FILE *csr_fs = fopen(QFile::encodeName(csrFile.fileName()), "r+");
00237 FILE *p8_fs = fopen(QFile::encodeName(p8File.fileName()), "r+");
00238
00239 kossl->i2d_X509_REQ_fp(csr_fs, req);
00240
00241 kossl->i2d_PKCS8PrivateKey_fp(p8_fs, pkey,
00242 kossl->EVP_bf_cbc(), pass.toLocal8Bit().data(),
00243 pass.length(), 0L, 0L);
00244
00245
00246
00247 kossl->X509_REQ_free(req);
00248 kossl->EVP_PKEY_free(pkey);
00249
00250 fclose(csr_fs);
00251 fclose(p8_fs);
00252
00253 return 0;
00254 #else
00255 return -1;
00256 #endif
00257 }
00258
00259
00260 QStringList KSSLKeyGen::supportedKeySizes() {
00261 QStringList x;
00262
00263 #ifdef KSSL_HAVE_SSL
00264 x << i18n("2048 (High Grade)")
00265 << i18n("1024 (Medium Grade)")
00266 << i18n("768 (Low Grade)")
00267 << i18n("512 (Low Grade)");
00268 #else
00269 x << i18n("No SSL support.");
00270 #endif
00271
00272 return x;
00273 }
00274
00275 void KSSLKeyGen::setKeySize(int idx)
00276 {
00277 d->idx = idx;
00278 }
00279
00280 #include "ksslkeygen.moc"
00281
00282 #include "ksslkeygen_p.moc"