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