KIO
ksslkeygen.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 * 00003 * Copyright (C) 2001 George Staikos <staikos@kde.org> 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Library General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Library General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Library General Public License 00016 * along with this library; see the file COPYING.LIB. If not, write to 00017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 * Boston, MA 02110-1301, USA. 00019 */ 00020 00021 00022 #include "ksslkeygen.h" 00023 #include "ksslkeygen_p.h" 00024 #include "ui_keygenwizard.h" 00025 00026 #include <kdebug.h> 00027 #include <klocale.h> 00028 #include <kmessagebox.h> 00029 #include <kopenssl.h> 00030 #include <kprogressdialog.h> 00031 #include <kstandarddirs.h> 00032 #include <ktemporaryfile.h> 00033 #include <kwallet.h> 00034 00035 #include <assert.h> 00036 00037 KSSLKeyGenWizardPage2::KSSLKeyGenWizardPage2(QWidget* parent) 00038 : QWizardPage(parent) 00039 { 00040 ui2 = new Ui_KGWizardPage2; 00041 ui2->setupUi(this); 00042 connect(ui2->_password1, SIGNAL(textChanged(const QString&)), this, SLOT(slotPassChanged())); 00043 connect(ui2->_password2, SIGNAL(textChanged(const QString&)), this, SLOT(slotPassChanged())); 00044 } 00045 00046 bool KSSLKeyGenWizardPage2::isComplete() const 00047 { 00048 return ui2->_password1->text() == ui2->_password2->text() && ui2->_password1->text().length() >= 4; 00049 } 00050 00051 void KSSLKeyGenWizardPage2::slotPassChanged() 00052 { 00053 emit completeChanged(); // well maybe it hasn't changed, but it might have; QWizard calls isComplete() to find out 00054 } 00055 00056 QString KSSLKeyGenWizardPage2::password() const 00057 { 00058 Q_ASSERT(isComplete()); 00059 return ui2->_password1->text(); 00060 } 00061 00063 00064 class KSSLKeyGenPrivate 00065 { 00066 public: 00067 KSSLKeyGenPrivate() 00068 : idx(-1) 00069 { 00070 } 00071 int idx; 00072 Ui_KGWizardPage1 *ui1; 00073 KSSLKeyGenWizardPage2* page2; 00074 }; 00075 00076 KSSLKeyGen::KSSLKeyGen(QWidget *parent) 00077 : QWizard(parent), d(new KSSLKeyGenPrivate) 00078 { 00079 #ifdef KSSL_HAVE_SSL 00080 00081 QWizardPage* page1 = new QWizardPage(this); 00082 page1->setTitle(i18n("KDE Certificate Request")); 00083 d->ui1 = new Ui_KGWizardPage1; 00084 d->ui1->setupUi(page1); 00085 addPage(page1); 00086 //setHelpEnabled(page1, false); 00087 00088 d->page2 = new KSSLKeyGenWizardPage2(this); 00089 d->page2->setTitle(i18n("KDE Certificate Request - Password")); 00090 addPage(d->page2); 00091 #else 00092 // tell him he doesn't have SSL 00093 #endif 00094 } 00095 00096 00097 KSSLKeyGen::~KSSLKeyGen() { 00098 delete d->ui1; 00099 delete d; 00100 } 00101 00102 bool KSSLKeyGen::validateCurrentPage() { 00103 if (currentPage() != d->page2) 00104 return true; 00105 00106 assert(d->idx >= 0 && d->idx <= 3); // for now 00107 00108 // Generate the CSR 00109 int bits; 00110 switch (d->idx) { 00111 case 0: 00112 bits = 2048; 00113 break; 00114 case 1: 00115 bits = 1024; 00116 break; 00117 case 2: 00118 bits = 768; 00119 break; 00120 case 3: 00121 bits = 512; 00122 break; 00123 default: 00124 KMessageBox::sorry(this, i18n("Unsupported key size."), i18n("KDE SSL Information")); 00125 return false; 00126 } 00127 00128 KProgressDialog *kpd = new KProgressDialog(this); 00129 kpd->setObjectName("progress dialog"); 00130 kpd->setWindowTitle(i18n("KDE")); 00131 kpd->setLabelText(i18n("Please wait while the encryption keys are generated...")); 00132 kpd->progressBar()->setValue(0); 00133 kpd->show(); 00134 // FIXME - progress dialog won't show this way 00135 00136 int rc = generateCSR("This CSR" /*FIXME */, d->page2->password(), bits, 0x10001 /* This is the traditional exponent used */); 00137 if (rc != 0) // error 00138 return false; 00139 00140 kpd->progressBar()->setValue(100); 00141 00142 #if 0 // TODO: implement 00143 if (rc == 0 && KWallet::Wallet::isEnabled()) { 00144 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"))); 00145 if (rc == KMessageBox::Yes) { 00146 KWallet::Wallet *w = KWallet::Wallet::openWallet(KWallet::Wallet::LocalWallet(), winId()); 00147 if (w) { 00148 // FIXME: store passphrase in wallet 00149 delete w; 00150 } 00151 } 00152 } 00153 #endif 00154 00155 kpd->deleteLater(); 00156 return true; 00157 } 00158 00159 00160 int KSSLKeyGen::generateCSR(const QString& name, const QString& pass, int bits, int e) { 00161 #ifdef KSSL_HAVE_SSL 00162 KOSSL *kossl = KOSSL::self(); 00163 int rc; 00164 00165 X509_REQ *req = kossl->X509_REQ_new(); 00166 if (!req) { 00167 return -2; 00168 } 00169 00170 EVP_PKEY *pkey = kossl->EVP_PKEY_new(); 00171 if (!pkey) { 00172 kossl->X509_REQ_free(req); 00173 return -4; 00174 } 00175 00176 RSA *rsakey = kossl->RSA_generate_key(bits, e, NULL, NULL); 00177 if (!rsakey) { 00178 kossl->X509_REQ_free(req); 00179 kossl->EVP_PKEY_free(pkey); 00180 return -3; 00181 } 00182 00183 rc = kossl->EVP_PKEY_assign(pkey, EVP_PKEY_RSA, (char *)rsakey); 00184 00185 rc = kossl->X509_REQ_set_pubkey(req, pkey); 00186 00187 // Set the subject 00188 X509_NAME *n = kossl->X509_NAME_new(); 00189 00190 kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_countryName, MBSTRING_UTF8, (unsigned char*)name.toLocal8Bit().data(), -1, -1, 0); 00191 kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_organizationName, MBSTRING_UTF8, (unsigned char*)name.toLocal8Bit().data(), -1, -1, 0); 00192 kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_organizationalUnitName, MBSTRING_UTF8, (unsigned char*)name.toLocal8Bit().data(), -1, -1, 0); 00193 kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_localityName, MBSTRING_UTF8, (unsigned char*)name.toLocal8Bit().data(), -1, -1, 0); 00194 kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_stateOrProvinceName, MBSTRING_UTF8, (unsigned char*)name.toLocal8Bit().data(), -1, -1, 0); 00195 kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_commonName, MBSTRING_UTF8, (unsigned char*)name.toLocal8Bit().data(), -1, -1, 0); 00196 kossl->X509_NAME_add_entry_by_txt(n, (char*)LN_pkcs9_emailAddress, MBSTRING_UTF8, (unsigned char*)name.toLocal8Bit().data(), -1, -1, 0); 00197 00198 rc = kossl->X509_REQ_set_subject_name(req, n); 00199 00200 00201 rc = kossl->X509_REQ_sign(req, pkey, kossl->EVP_md5()); 00202 00203 // We write it to the database and then the caller can obtain it 00204 // back from there. Yes it's inefficient, but it doesn't happen 00205 // often and this way things are uniform. 00206 00207 KGlobal::dirs()->addResourceType("kssl", "data", "kssl"); 00208 00209 QString path = KGlobal::dirs()->saveLocation("kssl"); 00210 KTemporaryFile csrFile; 00211 csrFile.setAutoRemove(false); 00212 csrFile.setPrefix(path + "csr_"); 00213 csrFile.setSuffix(".der"); 00214 00215 if (!csrFile.open()) { 00216 kossl->X509_REQ_free(req); 00217 kossl->EVP_PKEY_free(pkey); 00218 return -5; 00219 } 00220 00221 KTemporaryFile p8File; 00222 p8File.setAutoRemove(false); 00223 p8File.setPrefix(path + "pkey_"); 00224 p8File.setSuffix(".p8"); 00225 00226 if (!p8File.open()) { 00227 kossl->X509_REQ_free(req); 00228 kossl->EVP_PKEY_free(pkey); 00229 return -5; 00230 } 00231 00232 FILE *csr_fs = fopen(QFile::encodeName(csrFile.fileName()), "r+"); 00233 FILE *p8_fs = fopen(QFile::encodeName(p8File.fileName()), "r+"); 00234 00235 kossl->i2d_X509_REQ_fp(csr_fs, req); 00236 00237 kossl->i2d_PKCS8PrivateKey_fp(p8_fs, pkey, 00238 kossl->EVP_bf_cbc(), pass.toLocal8Bit().data(), 00239 pass.length(), 0L, 0L); 00240 00241 // FIXME Write kconfig entry to store the filenames under the md5 hash 00242 00243 kossl->X509_REQ_free(req); 00244 kossl->EVP_PKEY_free(pkey); 00245 00246 fclose(csr_fs); 00247 fclose(p8_fs); 00248 00249 return 0; 00250 #else 00251 return -1; 00252 #endif 00253 } 00254 00255 00256 QStringList KSSLKeyGen::supportedKeySizes() { 00257 QStringList x; 00258 00259 #ifdef KSSL_HAVE_SSL 00260 x << i18n("2048 (High Grade)") 00261 << i18n("1024 (Medium Grade)") 00262 << i18n("768 (Low Grade)") 00263 << i18n("512 (Low Grade)"); 00264 #else 00265 x << i18n("No SSL support."); 00266 #endif 00267 00268 return x; 00269 } 00270 00271 void KSSLKeyGen::setKeySize(int idx) 00272 { 00273 d->idx = idx; 00274 } 00275 00276 #include "ksslkeygen.moc" 00277 00278 #include "ksslkeygen_p.moc"
KDE 4.7 API Reference