00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#ifdef HAVE_CONFIG_H
00023
#include <config.h>
00024
#endif
00025
00026
00027
00028
#include <unistd.h>
00029
#include <qstring.h>
00030
#include <qstringlist.h>
00031
#include <qfile.h>
00032
00033
#include "kssldefs.h"
00034
#include "ksslcertificate.h"
00035
#include "ksslcertchain.h"
00036
#include "ksslutils.h"
00037
00038
#include <kstandarddirs.h>
00039
#include <kmdcodec.h>
00040
#include <klocale.h>
00041
#include <qdatetime.h>
00042
#include <ktempfile.h>
00043
00044
#include <sys/types.h>
00045
00046
#ifdef HAVE_SYS_STAT_H
00047
#include <sys/stat.h>
00048
#endif
00049
00050
00051
00052
#ifdef KSSL_HAVE_SSL
00053
#define crypt _openssl_crypt
00054
#include <openssl/ssl.h>
00055
#include <openssl/x509.h>
00056
#include <openssl/x509v3.h>
00057
#include <openssl/x509_vfy.h>
00058
#include <openssl/pem.h>
00059
#undef crypt
00060
#endif
00061
00062
#include <kopenssl.h>
00063
#include <qcstring.h>
00064
#include <kdebug.h>
00065
#include "ksslx509v3.h"
00066
00067
00068
00069
static char hv[] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F'};
00070
00071
00072
class KSSLCertificatePrivate {
00073
public:
00074 KSSLCertificatePrivate() {
00075 kossl = KOSSL::self();
00076 _lastPurpose = KSSLCertificate::None;
00077 }
00078
00079 ~KSSLCertificatePrivate() {
00080 }
00081
00082
KSSLCertificate::KSSLValidation m_stateCache;
00083
bool m_stateCached;
00084
#ifdef KSSL_HAVE_SSL
00085
X509 *m_cert;
00086
#endif
00087
KOSSL *kossl;
00088
KSSLCertChain _chain;
00089
KSSLX509V3 _extensions;
00090 KSSLCertificate::KSSLPurpose _lastPurpose;
00091 };
00092
00093
KSSLCertificate::KSSLCertificate() {
00094 d =
new KSSLCertificatePrivate;
00095 d->m_stateCached =
false;
00096
KGlobal::dirs()->
addResourceType(
"kssl", KStandardDirs::kde_default(
"data") +
"kssl");
00097
#ifdef KSSL_HAVE_SSL
00098
d->m_cert = NULL;
00099
#endif
00100
}
00101
00102
00103 KSSLCertificate::KSSLCertificate(
const KSSLCertificate& x) {
00104 d =
new KSSLCertificatePrivate;
00105 d->m_stateCached =
false;
00106
KGlobal::dirs()->
addResourceType(
"kssl", KStandardDirs::kde_default(
"data") +
"kssl");
00107
#ifdef KSSL_HAVE_SSL
00108
d->m_cert = NULL;
00109
setCert(KOSSL::self()->X509_dup(const_cast<KSSLCertificate&>(x).getCert()));
00110
KSSLCertChain *c = x.d->_chain.replicate();
00111 setChain(c->
rawChain());
00112
delete c;
00113
#endif
00114
}
00115
00116
00117
00118 KSSLCertificate::~KSSLCertificate() {
00119
#ifdef KSSL_HAVE_SSL
00120
if (d->m_cert)
00121 d->kossl->X509_free(d->m_cert);
00122
#endif
00123
delete d;
00124 }
00125
00126
00127 KSSLCertChain&
KSSLCertificate::chain() {
00128
return d->_chain;
00129 }
00130
00131
00132 KSSLCertificate *
KSSLCertificate::fromX509(X509 *x5) {
00133
KSSLCertificate *n = NULL;
00134
#ifdef KSSL_HAVE_SSL
00135
if (x5) {
00136 n =
new KSSLCertificate;
00137 n->
setCert(KOSSL::self()->X509_dup(x5));
00138 }
00139
#endif
00140
return n;
00141 }
00142
00143
00144 KSSLCertificate *
KSSLCertificate::fromString(
QCString cert) {
00145
KSSLCertificate *n = NULL;
00146
#ifdef KSSL_HAVE_SSL
00147
if (cert.
length() == 0)
00148
return NULL;
00149
00150
QByteArray qba, qbb = cert.
copy();
00151 KCodecs::base64Decode(qbb, qba);
00152
unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data());
00153 X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size());
00154
if (!x5c) {
00155
return NULL;
00156 }
00157
00158 n =
new KSSLCertificate;
00159 n->
setCert(x5c);
00160
#endif
00161
return n;
00162 }
00163
00164
00165
00166 QString KSSLCertificate::getSubject()
const {
00167
QString rc =
"";
00168
00169
#ifdef KSSL_HAVE_SSL
00170
char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_subject_name(d->m_cert), 0, 0);
00171
if (!t)
00172
return rc;
00173 rc = t;
00174 d->kossl->OPENSSL_free(t);
00175
#endif
00176
return rc;
00177 }
00178
00179
00180 QString KSSLCertificate::getSerialNumber()
const {
00181
QString rc =
"";
00182
00183
#ifdef KSSL_HAVE_SSL
00184
ASN1_INTEGER *aint = d->kossl->X509_get_serialNumber(d->m_cert);
00185
if (aint) {
00186 rc = ASN1_INTEGER_QString(aint);
00187
00188 }
00189
#endif
00190
return rc;
00191 }
00192
00193
00194 QString KSSLCertificate::getSignatureText()
const {
00195
QString rc =
"";
00196
00197
#ifdef KSSL_HAVE_SSL
00198
char *s;
00199
int n, i;
00200
00201 i = d->kossl->OBJ_obj2nid(d->m_cert->sig_alg->algorithm);
00202 rc = i18n(
"Signature Algorithm: ");
00203 rc += (i == NID_undef)?i18n(
"Unknown"):
QString(d->kossl->OBJ_nid2ln(i));
00204
00205 rc +=
"\n";
00206 rc += i18n(
"Signature Contents:");
00207 n = d->m_cert->signature->length;
00208 s = (
char *)d->m_cert->signature->data;
00209
for (i = 0; i < n; i++) {
00210
if (i%20 != 0) rc +=
":";
00211
else rc +=
"\n";
00212 rc.
append(hv[(s[i]&0xf0)>>4]);
00213 rc.
append(hv[s[i]&0x0f]);
00214 }
00215
00216
#endif
00217
00218
return rc;
00219 }
00220
00221
00222 void KSSLCertificate::getEmails(
QStringList &to)
const {
00223 to.clear();
00224
#ifdef KSSL_HAVE_SSL
00225
if (!d->m_cert)
00226
return;
00227
00228 STACK *s = d->kossl->X509_get1_email(d->m_cert);
00229
if (s) {
00230
for(
int n=0; n < s->num; n++) {
00231 to.append(d->kossl->sk_value(s,n));
00232 }
00233 d->kossl->X509_email_free(s);
00234 }
00235
#endif
00236
}
00237
00238
00239 QString KSSLCertificate::getKDEKey()
const {
00240
return getSubject() +
" (" +
getMD5DigestText() +
")";
00241 }
00242
00243
00244 QString KSSLCertificate::getMD5DigestFromKDEKey(
const QString &k) {
00245
QString rc;
00246
int pos = k.
findRev(
'(');
00247
if (pos != -1) {
00248
unsigned int len = k.
length();
00249
if (k.
at(len-1) ==
')') {
00250 rc = k.
mid(pos+1, len-pos-2);
00251 }
00252 }
00253
return rc;
00254 }
00255
00256
00257 QString KSSLCertificate::getMD5DigestText()
const {
00258
QString rc =
"";
00259
00260
#ifdef KSSL_HAVE_SSL
00261
unsigned int n;
00262
unsigned char md[EVP_MAX_MD_SIZE];
00263
00264
if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) {
00265
return rc;
00266 }
00267
00268
for (
unsigned int j = 0; j < n; j++) {
00269
if (j > 0)
00270 rc +=
":";
00271 rc.
append(hv[(md[j]&0xf0)>>4]);
00272 rc.
append(hv[md[j]&0x0f]);
00273 }
00274
00275
#endif
00276
00277
return rc;
00278 }
00279
00280
00281
00282 QString KSSLCertificate::getKeyType()
const {
00283
QString rc =
"";
00284
00285
#ifdef KSSL_HAVE_SSL
00286
EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert);
00287
if (pkey) {
00288
#ifndef NO_RSA
00289
if (pkey->type == EVP_PKEY_RSA)
00290 rc =
"RSA";
00291
else
00292
#endif
00293
#ifndef NO_DSA
00294
if (pkey->type == EVP_PKEY_DSA)
00295 rc =
"DSA";
00296
else
00297
#endif
00298
rc =
"Unknown";
00299 d->kossl->EVP_PKEY_free(pkey);
00300 }
00301
#endif
00302
00303
return rc;
00304 }
00305
00306
00307
00308 QString KSSLCertificate::getPublicKeyText()
const {
00309
QString rc =
"";
00310
char *x = NULL;
00311
00312
#ifdef KSSL_HAVE_SSL
00313
EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert);
00314
if (pkey) {
00315 rc = i18n(
"Unknown",
"Unknown key algorithm");
00316
#ifndef NO_RSA
00317
if (pkey->type == EVP_PKEY_RSA) {
00318 rc = i18n(
"Key type: RSA (%1 bit)") +
"\n";
00319
00320 x = d->kossl->BN_bn2hex(pkey->pkey.rsa->n);
00321 rc += i18n(
"Modulus: ");
00322 rc = rc.
arg(strlen(x)*4);
00323
for (
unsigned int i = 0; i < strlen(x); i++) {
00324
if (i%40 != 0 && i%2 == 0)
00325 rc +=
":";
00326
else if (i%40 == 0)
00327 rc +=
"\n";
00328 rc += x[i];
00329 }
00330 rc +=
"\n";
00331 d->kossl->OPENSSL_free(x);
00332
00333 x = d->kossl->BN_bn2hex(pkey->pkey.rsa->e);
00334 rc += i18n(
"Exponent: 0x") + x +
"\n";
00335 d->kossl->OPENSSL_free(x);
00336 }
00337
#endif
00338
#ifndef NO_DSA
00339
if (pkey->type == EVP_PKEY_DSA) {
00340 rc = i18n(
"Key type: DSA (%1 bit)") +
"\n";
00341
00342 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->p);
00343 rc += i18n(
"Prime: ");
00344
00345 rc = rc.
arg(strlen(x)*4) ;
00346
for (
unsigned int i = 0; i < strlen(x); i++) {
00347
if (i%40 != 0 && i%2 == 0)
00348 rc +=
":";
00349
else if (i%40 == 0)
00350 rc +=
"\n";
00351 rc += x[i];
00352 }
00353 rc +=
"\n";
00354 d->kossl->OPENSSL_free(x);
00355
00356 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->q);
00357 rc += i18n(
"160 bit prime factor: ");
00358
for (
unsigned int i = 0; i < strlen(x); i++) {
00359
if (i%40 != 0 && i%2 == 0)
00360 rc +=
":";
00361
else if (i%40 == 0)
00362 rc +=
"\n";
00363 rc += x[i];
00364 }
00365 rc +=
"\n";
00366 d->kossl->OPENSSL_free(x);
00367
00368 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->g);
00369 rc +=
QString(
"g: ");
00370
for (
unsigned int i = 0; i < strlen(x); i++) {
00371
if (i%40 != 0 && i%2 == 0)
00372 rc +=
":";
00373
else if (i%40 == 0)
00374 rc +=
"\n";
00375 rc += x[i];
00376 }
00377 rc +=
"\n";
00378 d->kossl->OPENSSL_free(x);
00379
00380 x = d->kossl->BN_bn2hex(pkey->pkey.dsa->pub_key);
00381 rc += i18n(
"Public key: ");
00382
for (
unsigned int i = 0; i < strlen(x); i++) {
00383
if (i%40 != 0 && i%2 == 0)
00384 rc +=
":";
00385
else if (i%40 == 0)
00386 rc +=
"\n";
00387 rc += x[i];
00388 }
00389 rc +=
"\n";
00390 d->kossl->OPENSSL_free(x);
00391 }
00392
#endif
00393
d->kossl->EVP_PKEY_free(pkey);
00394 }
00395
#endif
00396
00397
return rc;
00398 }
00399
00400
00401
00402 QString KSSLCertificate::getIssuer()
const {
00403
QString rc =
"";
00404
00405
#ifdef KSSL_HAVE_SSL
00406
char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_issuer_name(d->m_cert), 0, 0);
00407
00408
if (!t)
00409
return rc;
00410
00411 rc = t;
00412 d->kossl->OPENSSL_free(t);
00413
#endif
00414
00415
return rc;
00416 }
00417
00418
void KSSLCertificate::setChain(
void *c) {
00419
#ifdef KSSL_HAVE_SSL
00420
d->_chain.setChain(c);
00421
#endif
00422
d->m_stateCached =
false;
00423 d->m_stateCache = KSSLCertificate::Unknown;
00424 }
00425
00426
void KSSLCertificate::setCert(X509 *c) {
00427
#ifdef KSSL_HAVE_SSL
00428
d->m_cert = c;
00429
if (c) {
00430 d->_extensions.flags = 0;
00431 d->kossl->X509_check_purpose(c, -1, 0);
00432
00433
#if 0
00434
kdDebug(7029) <<
"---------------- Certificate ------------------"
00435 <<
endl;
00436
kdDebug(7029) <<
getSubject() <<
endl;
00437
#endif
00438
00439
for (
int j = 0; j < d->kossl->X509_PURPOSE_get_count(); j++) {
00440 X509_PURPOSE *ptmp = d->kossl->X509_PURPOSE_get0(j);
00441
int id = d->kossl->X509_PURPOSE_get_id(ptmp);
00442
for (
int ca = 0; ca < 2; ca++) {
00443
int idret = d->kossl->X509_check_purpose(c,
id, ca);
00444
if (idret == 1 || idret == 2) {
00445
00446
if (!ca)
00447 d->_extensions.flags |= (1L <<(
id-1));
00448
else d->_extensions.flags |= (1L <<(16+
id-1));
00449 }
else {
00450
if (!ca)
00451 d->_extensions.flags &= ~(1L <<(
id-1));
00452
else d->_extensions.flags &= ~(1L <<(16+
id-1));
00453 }
00454 }
00455 }
00456
00457
#if 0
00458
kdDebug(7029) <<
"flags: " <<
QString::number(c->ex_flags, 2)
00459 <<
"\nkeyusage: " <<
QString::number(c->ex_kusage, 2)
00460 <<
"\nxkeyusage: " <<
QString::number(c->ex_xkusage, 2)
00461 <<
"\nnscert: " <<
QString::number(c->ex_nscert, 2)
00462 <<
endl;
00463
if (c->ex_flags & EXFLAG_KUSAGE)
00464
kdDebug(7029) <<
" --- Key Usage extensions found" <<
endl;
00465
else kdDebug(7029) <<
" --- Key Usage extensions NOT found" <<
endl;
00466
00467
if (c->ex_flags & EXFLAG_XKUSAGE)
00468
kdDebug(7029) <<
" --- Extended key usage extensions found" <<
endl;
00469
else kdDebug(7029) <<
" --- Extended key usage extensions NOT found" <<
endl;
00470
00471
if (c->ex_flags & EXFLAG_NSCERT)
00472
kdDebug(7029) <<
" --- NS extensions found" <<
endl;
00473
else kdDebug(7029) <<
" --- NS extensions NOT found" <<
endl;
00474
00475
if (d->_extensions.certTypeSSLCA())
00476
kdDebug(7029) <<
"NOTE: this is an SSL CA file." <<
endl;
00477
else kdDebug(7029) <<
"NOTE: this is NOT an SSL CA file." <<
endl;
00478
00479
if (d->_extensions.certTypeEmailCA())
00480
kdDebug(7029) <<
"NOTE: this is an EMAIL CA file." <<
endl;
00481
else kdDebug(7029) <<
"NOTE: this is NOT an EMAIL CA file." <<
endl;
00482
00483
if (d->_extensions.certTypeCodeCA())
00484
kdDebug(7029) <<
"NOTE: this is a CODE CA file." <<
endl;
00485
else kdDebug(7029) <<
"NOTE: this is NOT a CODE CA file." <<
endl;
00486
00487
if (d->_extensions.certTypeSSLClient())
00488
kdDebug(7029) <<
"NOTE: this is an SSL client." <<
endl;
00489
else kdDebug(7029) <<
"NOTE: this is NOT an SSL client." <<
endl;
00490
00491
if (d->_extensions.certTypeSSLServer())
00492
kdDebug(7029) <<
"NOTE: this is an SSL server." <<
endl;
00493
else kdDebug(7029) <<
"NOTE: this is NOT an SSL server." <<
endl;
00494
00495
if (d->_extensions.certTypeNSSSLServer())
00496
kdDebug(7029) <<
"NOTE: this is a NETSCAPE SSL server." <<
endl;
00497
else kdDebug(7029) <<
"NOTE: this is NOT a NETSCAPE SSL server." <<
endl;
00498
00499
if (d->_extensions.certTypeSMIME())
00500
kdDebug(7029) <<
"NOTE: this is an SMIME certificate." <<
endl;
00501
else kdDebug(7029) <<
"NOTE: this is NOT an SMIME certificate." <<
endl;
00502
00503
if (d->_extensions.certTypeSMIMEEncrypt())
00504
kdDebug(7029) <<
"NOTE: this is an SMIME encrypt cert." <<
endl;
00505
else kdDebug(7029) <<
"NOTE: this is NOT an SMIME encrypt cert." <<
endl;
00506
00507
if (d->_extensions.certTypeSMIMESign())
00508
kdDebug(7029) <<
"NOTE: this is an SMIME sign cert." <<
endl;
00509
else kdDebug(7029) <<
"NOTE: this is NOT an SMIME sign cert." <<
endl;
00510
00511
if (d->_extensions.certTypeCRLSign())
00512
kdDebug(7029) <<
"NOTE: this is a CRL signer." <<
endl;
00513
else kdDebug(7029) <<
"NOTE: this is NOT a CRL signer." <<
endl;
00514
00515
kdDebug(7029) <<
"-----------------------------------------------"
00516 <<
endl;
00517
#endif
00518
}
00519
#endif
00520
d->m_stateCached =
false;
00521 d->m_stateCache = KSSLCertificate::Unknown;
00522 }
00523
00524 X509 *KSSLCertificate::getCert() {
00525
#ifdef KSSL_HAVE_SSL
00526
return d->m_cert;
00527
#endif
00528
return 0;
00529 }
00530
00531
00532
00533
00534
#include "ksslcallback.c"
00535
00536
00537 bool KSSLCertificate::isValid(KSSLCertificate::KSSLPurpose p) {
00538
return (
validate(p) == KSSLCertificate::Ok);
00539 }
00540
00541
00542 bool KSSLCertificate::isValid() {
00543
return isValid(KSSLCertificate::SSLServer);
00544 }
00545
00546
00547
int KSSLCertificate::purposeToOpenSSL(KSSLCertificate::KSSLPurpose p)
const {
00548
int rc = 0;
00549
#ifdef KSSL_HAVE_SSL
00550
if (p == KSSLCertificate::SSLServer) {
00551 rc = X509_PURPOSE_SSL_SERVER;
00552 }
else if (p == KSSLCertificate::SSLClient) {
00553 rc = X509_PURPOSE_SSL_CLIENT;
00554 }
else if (p == KSSLCertificate::SMIMEEncrypt) {
00555 rc = X509_PURPOSE_SMIME_ENCRYPT;
00556 }
else if (p == KSSLCertificate::SMIMESign) {
00557 rc = X509_PURPOSE_SMIME_SIGN;
00558 }
else if (p == KSSLCertificate::Any) {
00559 rc = X509_PURPOSE_ANY;
00560 }
00561
#endif
00562
return rc;
00563 }
00564
00565
00566
00567 KSSLCertificate::KSSLValidation KSSLCertificate::validate() {
00568
return validate(KSSLCertificate::SSLServer);
00569 }
00570
00571 KSSLCertificate::KSSLValidation KSSLCertificate::validate(KSSLCertificate::KSSLPurpose purpose)
00572 {
00573
KSSLValidationList result =
validateVerbose(purpose);
00574
if (result.
isEmpty())
00575
return KSSLCertificate::Ok;
00576
else
00577
return result.
first();
00578 }
00579
00580
00581
00582
00583
00584
00585 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose)
00586 {
00587
return validateVerbose(purpose, 0);
00588 }
00589
00590 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose,
KSSLCertificate *ca)
00591 {
00592
KSSLValidationList errors;
00593
if (ca || (d->_lastPurpose != purpose)) {
00594 d->m_stateCached =
false;
00595 }
00596
00597
if (!d->m_stateCached)
00598 d->_lastPurpose = purpose;
00599
00600
#ifdef KSSL_HAVE_SSL
00601
X509_STORE *certStore;
00602 X509_LOOKUP *certLookup;
00603 X509_STORE_CTX *certStoreCTX;
00604
int rc = 0;
00605
00606
if (!d->m_cert)
00607 {
00608 errors << KSSLCertificate::Unknown;
00609
return errors;
00610 }
00611
00612
if (d->m_stateCached) {
00613 errors << d->m_stateCache;
00614
return errors;
00615 }
00616
00617
QStringList qsl =
KGlobal::dirs()->
resourceDirs(
"kssl");
00618
00619
if (qsl.isEmpty()) {
00620 errors << KSSLCertificate::NoCARoot;
00621
return errors;
00622 }
00623
00624
KSSLCertificate::KSSLValidation ksslv = Unknown;
00625
00626
for (QStringList::Iterator j = qsl.begin(); j != qsl.end(); ++j) {
00627
struct stat sb;
00628
QString _j = (*j) +
"ca-bundle.crt";
00629
if (-1 == stat(_j.ascii(), &sb)) {
00630
continue;
00631 }
00632
00633 certStore = d->kossl->X509_STORE_new();
00634
if (!certStore) {
00635 errors << KSSLCertificate::Unknown;
00636
return errors;
00637 }
00638
00639 X509_STORE_set_verify_cb_func(certStore, X509Callback);
00640
00641 certLookup = d->kossl->X509_STORE_add_lookup(certStore, d->kossl->X509_LOOKUP_file());
00642
if (!certLookup) {
00643 ksslv = KSSLCertificate::Unknown;
00644 d->kossl->X509_STORE_free(certStore);
00645
continue;
00646 }
00647
00648
if (!d->kossl->X509_LOOKUP_load_file(certLookup, _j.ascii(), X509_FILETYPE_PEM)) {
00649
00650
kdDebug(7029) <<
"KSSL couldn't read CA root: "
00651 << _j <<
endl;
00652 ksslv = KSSLCertificate::ErrorReadingRoot;
00653 d->kossl->X509_STORE_free(certStore);
00654
continue;
00655 }
00656
00657
00658 certStoreCTX = d->kossl->X509_STORE_CTX_new();
00659
00660
00661
00662
if (!certStoreCTX) {
00663
kdDebug(7029) <<
"KSSL couldn't create an X509 store context." <<
endl;
00664 d->kossl->X509_STORE_free(certStore);
00665
continue;
00666 }
00667
00668 d->kossl->X509_STORE_CTX_init(certStoreCTX, certStore, d->m_cert, NULL);
00669
if (d->_chain.isValid()) {
00670 d->kossl->X509_STORE_CTX_set_chain(certStoreCTX, (STACK_OF(X509)*)d->_chain.rawChain());
00671 }
00672
00673
00674
00675
00676 d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, purposeToOpenSSL(purpose));
00677
00678 KSSL_X509CallBack_ca = ca ? ca->
d->m_cert : 0;
00679 KSSL_X509CallBack_ca_found =
false;
00680
00681 certStoreCTX->error = X509_V_OK;
00682 rc = d->kossl->X509_verify_cert(certStoreCTX);
00683
int errcode = certStoreCTX->error;
00684
if (ca && !KSSL_X509CallBack_ca_found) {
00685 ksslv = KSSLCertificate::Irrelevant;
00686 }
else {
00687 ksslv = processError(errcode);
00688 }
00689
00690
if ( (ksslv != KSSLCertificate::Ok) &&
00691 (ksslv != KSSLCertificate::Irrelevant) &&
00692 purpose == KSSLCertificate::SSLServer) {
00693 d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX,
00694 X509_PURPOSE_NS_SSL_SERVER);
00695
00696 certStoreCTX->error = X509_V_OK;
00697 rc = d->kossl->X509_verify_cert(certStoreCTX);
00698 errcode = certStoreCTX->error;
00699 ksslv = processError(errcode);
00700 }
00701 d->kossl->X509_STORE_CTX_free(certStoreCTX);
00702 d->kossl->X509_STORE_free(certStore);
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
if (ksslv != NoCARoot && ksslv != InvalidCA) {
00714 d->m_stateCached =
true;
00715 d->m_stateCache = ksslv;
00716 }
00717
break;
00718 }
00719
00720
if (ksslv != KSSLCertificate::Ok)
00721 errors << ksslv;
00722
#else
00723
errors << KSSLCertificate::NoSSL;
00724
#endif
00725
return errors;
00726 }
00727
00728
00729
00730 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate() {
00731
return revalidate(KSSLCertificate::SSLServer);
00732 }
00733
00734
00735 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate(KSSLCertificate::KSSLPurpose p) {
00736 d->m_stateCached =
false;
00737
return validate(p);
00738 }
00739
00740
00741 KSSLCertificate::KSSLValidation KSSLCertificate::processError(
int ec) {
00742 KSSLCertificate::KSSLValidation rc;
00743
00744 rc = KSSLCertificate::Unknown;
00745
#ifdef KSSL_HAVE_SSL
00746
switch (ec) {
00747
case X509_V_OK:
00748 rc = KSSLCertificate::Ok;
00749
break;
00750
00751
00752
case X509_V_ERR_CERT_REJECTED:
00753 rc = KSSLCertificate::Rejected;
00754
break;
00755
00756
00757
case X509_V_ERR_CERT_UNTRUSTED:
00758 rc = KSSLCertificate::Untrusted;
00759
break;
00760
00761
00762
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
00763
case X509_V_ERR_CERT_SIGNATURE_FAILURE:
00764
case X509_V_ERR_CRL_SIGNATURE_FAILURE:
00765
case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
00766
case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
00767 rc = KSSLCertificate::SignatureFailed;
00768
break;
00769
00770
case X509_V_ERR_INVALID_CA:
00771
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
00772
case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
00773
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
00774 rc = KSSLCertificate::InvalidCA;
00775
break;
00776
00777
00778
case X509_V_ERR_INVALID_PURPOSE:
00779 rc = KSSLCertificate::InvalidPurpose;
00780
break;
00781
00782
00783
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
00784 rc = KSSLCertificate::SelfSigned;
00785
break;
00786
00787
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
00788 rc = KSSLCertificate::SelfSignedChain;
00789
break;
00790
00791
case X509_V_ERR_CERT_REVOKED:
00792 rc = KSSLCertificate::Revoked;
00793
break;
00794
00795
case X509_V_ERR_PATH_LENGTH_EXCEEDED:
00796 rc = KSSLCertificate::PathLengthExceeded;
00797
break;
00798
00799
case X509_V_ERR_CERT_NOT_YET_VALID:
00800
case X509_V_ERR_CERT_HAS_EXPIRED:
00801
case X509_V_ERR_CRL_NOT_YET_VALID:
00802
case X509_V_ERR_CRL_HAS_EXPIRED:
00803
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
00804
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
00805
case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
00806
case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
00807 rc = KSSLCertificate::Expired;
00808
kdDebug(7029) <<
"KSSL apparently this is expired. Not after: "
00809 <<
getNotAfter() <<
endl;
00810
break;
00811
00812
00813
case X509_V_ERR_APPLICATION_VERIFICATION:
00814
case X509_V_ERR_OUT_OF_MEM:
00815
case X509_V_ERR_UNABLE_TO_GET_CRL:
00816
case X509_V_ERR_CERT_CHAIN_TOO_LONG:
00817
default:
00818 rc = KSSLCertificate::Unknown;
00819
break;
00820 }
00821
00822 d->m_stateCache = rc;
00823 d->m_stateCached =
true;
00824
#endif
00825
return rc;
00826 }
00827
00828
00829 QString KSSLCertificate::getNotBefore()
const {
00830
#ifdef KSSL_HAVE_SSL
00831
return ASN1_UTCTIME_QString(X509_get_notBefore(d->m_cert));
00832
#else
00833
return QString::null;
00834
#endif
00835
}
00836
00837
00838 QString KSSLCertificate::getNotAfter()
const {
00839
#ifdef KSSL_HAVE_SSL
00840
return ASN1_UTCTIME_QString(X509_get_notAfter(d->m_cert));
00841
#else
00842
return QString::null;
00843
#endif
00844
}
00845
00846
00847 QDateTime KSSLCertificate::getQDTNotBefore()
const {
00848
#ifdef KSSL_HAVE_SSL
00849
return ASN1_UTCTIME_QDateTime(X509_get_notBefore(d->m_cert), NULL);
00850
#else
00851
return QDateTime::currentDateTime();
00852
#endif
00853
}
00854
00855
00856 QDateTime KSSLCertificate::getQDTNotAfter()
const {
00857
#ifdef KSSL_HAVE_SSL
00858
return ASN1_UTCTIME_QDateTime(X509_get_notAfter(d->m_cert), NULL);
00859
#else
00860
return QDateTime::currentDateTime();
00861
#endif
00862
}
00863
00864
00865
int operator==(
KSSLCertificate &x,
KSSLCertificate &y) {
00866
#ifndef KSSL_HAVE_SSL
00867
return 1;
00868
#else
00869
if (!KOSSL::self()->X509_cmp(x.
getCert(), y.
getCert()))
return 1;
00870
return 0;
00871
#endif
00872
}
00873
00874
00875 KSSLCertificate *
KSSLCertificate::replicate() {
00876
00877
00878
KSSLCertificate *newOne =
new KSSLCertificate();
00879
#ifdef KSSL_HAVE_SSL
00880
newOne->
setCert(d->kossl->X509_dup(getCert()));
00881
KSSLCertChain *c = d->_chain.replicate();
00882 newOne->
setChain(c->
rawChain());
00883
delete c;
00884
#endif
00885
return newOne;
00886 }
00887
00888
00889 QString KSSLCertificate::toString() {
00890
return KCodecs::base64Encode(
toDer());
00891 }
00892
00893
00894 QString KSSLCertificate::verifyText(KSSLValidation x) {
00895
switch (x) {
00896
case KSSLCertificate::Ok:
00897
return i18n(
"The certificate is valid.");
00898
case KSSLCertificate::PathLengthExceeded:
00899
case KSSLCertificate::ErrorReadingRoot:
00900
case KSSLCertificate::NoCARoot:
00901
return i18n(
"Certificate signing authority root files could not be found so the certificate is not verified.");
00902
case KSSLCertificate::SelfSignedChain:
00903
case KSSLCertificate::InvalidCA:
00904
return i18n(
"Certificate signing authority is unknown or invalid.");
00905
case KSSLCertificate::SelfSigned:
00906
return i18n(
"Certificate is self-signed and thus may not be trustworthy.");
00907
case KSSLCertificate::Expired:
00908
return i18n(
"Certificate has expired.");
00909
case KSSLCertificate::Revoked:
00910
return i18n(
"Certificate has been revoked.");
00911
case KSSLCertificate::NoSSL:
00912
return i18n(
"SSL support was not found.");
00913
case KSSLCertificate::Untrusted:
00914
return i18n(
"Signature is untrusted.");
00915
case KSSLCertificate::SignatureFailed:
00916
return i18n(
"Signature test failed.");
00917
case KSSLCertificate::Rejected:
00918
case KSSLCertificate::InvalidPurpose:
00919
return i18n(
"Rejected, possibly due to an invalid purpose.");
00920
case KSSLCertificate::PrivateKeyFailed:
00921
return i18n(
"Private key test failed.");
00922
case KSSLCertificate::InvalidHost:
00923
return i18n(
"The certificate has not been issued for this host.");
00924
case KSSLCertificate::Irrelevant:
00925
return i18n(
"This certificate is not relevant.");
00926
default:
00927
break;
00928 }
00929
00930
return i18n(
"The certificate is invalid.");
00931 }
00932
00933
00934 QByteArray KSSLCertificate::toDer() {
00935
QByteArray qba;
00936
#ifdef KSSL_HAVE_SSL
00937
unsigned int certlen = d->kossl->i2d_X509(getCert(), NULL);
00938
00939
00940
char *cert =
new char[certlen];
00941
char *p = cert;
00942
00943 d->kossl->i2d_X509(getCert(), (
unsigned char **)&p);
00944
00945
00946 qba.duplicate(cert, certlen);
00947
delete[] cert;
00948
#endif
00949
return qba;
00950 }
00951
00952
00953
00954 QByteArray KSSLCertificate::toPem() {
00955
QByteArray qba;
00956
QString thecert =
toString();
00957
const char *header =
"-----BEGIN CERTIFICATE-----\n";
00958
const char *footer =
"-----END CERTIFICATE-----\n";
00959
00960
00961
00962
unsigned int xx = thecert.
length() - 1;
00963
for (
unsigned int i = 0; i < xx/64; i++) {
00964 thecert.
insert(64*(i+1)+i,
'\n');
00965 }
00966
00967 thecert.
prepend(header);
00968
00969
if (thecert[thecert.
length()-1] !=
'\n')
00970 thecert +=
"\n";
00971
00972 thecert.
append(footer);
00973
00974 qba.duplicate(thecert.
local8Bit(), thecert.
length());
00975
return qba;
00976 }
00977
00978
00979
#define NETSCAPE_CERT_HDR "certificate"
00980
00981
00982 QByteArray KSSLCertificate::toNetscape() {
00983
QByteArray qba;
00984
#ifdef KSSL_HAVE_SSL
00985
ASN1_HEADER ah;
00986 ASN1_OCTET_STRING os;
00987
KTempFile ktf;
00988
00989 os.data = (
unsigned char *)NETSCAPE_CERT_HDR;
00990 os.length = strlen(NETSCAPE_CERT_HDR);
00991 ah.header = &os;
00992 ah.data = (
char *)getCert();
00993 ah.meth = d->kossl->X509_asn1_meth();
00994
00995 d->kossl->ASN1_i2d_fp(ktf.
fstream(),(
unsigned char *)&ah);
00996
00997 ktf.
close();
00998
00999
QFile qf(ktf.
name());
01000 qf.
open(IO_ReadOnly);
01001
char *buf =
new char[qf.
size()];
01002 qf.readBlock(buf, qf.
size());
01003 qba.duplicate(buf, qf.
size());
01004 qf.
close();
01005
delete[] buf;
01006
01007 ktf.
unlink();
01008
01009
#endif
01010
return qba;
01011 }
01012
01013
01014
01015 QString KSSLCertificate::toText() {
01016
QString text;
01017
#ifdef KSSL_HAVE_SSL
01018
KTempFile ktf;
01019
01020 d->kossl->X509_print(ktf.
fstream(), getCert());
01021 ktf.
close();
01022
01023
QFile qf(ktf.
name());
01024 qf.
open(IO_ReadOnly);
01025
char *buf =
new char[qf.
size()+1];
01026 qf.readBlock(buf, qf.
size());
01027 buf[qf.
size()] = 0;
01028 text = buf;
01029
delete[] buf;
01030 qf.
close();
01031 ktf.
unlink();
01032
#endif
01033
return text;
01034 }
01035
01036
01037 bool KSSLCertificate::setCert(
QString& cert) {
01038
#ifdef KSSL_HAVE_SSL
01039
QByteArray qba, qbb = cert.
local8Bit().copy();
01040 KCodecs::base64Decode(qbb, qba);
01041
unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data());
01042 X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size());
01043
if (x5c) {
01044
setCert(x5c);
01045
return true;
01046 }
01047
#endif
01048
return false;
01049 }
01050
01051
01052 KSSLX509V3&
KSSLCertificate::x509V3Extensions() {
01053
return d->_extensions;
01054 }
01055
01056
01057 bool KSSLCertificate::isSigner() {
01058
return d->_extensions.certTypeCA();
01059 }
01060
01061
01062 QStringList KSSLCertificate::subjAltNames()
const {
01063
QStringList rc;
01064
#ifdef KSSL_HAVE_SSL
01065
STACK_OF(GENERAL_NAME) *names;
01066 names = (STACK_OF(GENERAL_NAME)*)d->kossl->X509_get_ext_d2i(d->m_cert, NID_subject_alt_name, 0, 0);
01067
01068
if (!names) {
01069
return rc;
01070 }
01071
01072
int cnt = d->kossl->sk_GENERAL_NAME_num(names);
01073
01074
for (
int i = 0; i < cnt; i++) {
01075
const GENERAL_NAME *val = (
const GENERAL_NAME *)d->kossl->sk_value(names, i);
01076
if (val->type != GEN_DNS) {
01077
continue;
01078 }
01079
01080
QString s = (
const char *)d->kossl->ASN1_STRING_data(val->d.ia5);
01081
if (!s.
isEmpty()) {
01082 rc += s;
01083 }
01084 }
01085 d->kossl->sk_free(names);
01086
#endif
01087
return rc;
01088 }
01089
01090
01091
QDataStream&
operator<<(
QDataStream& s,
const KSSLCertificate& r) {
01092
QStringList qsl;
01093
QPtrList<KSSLCertificate> cl = const_cast<KSSLCertificate&>(r).chain().getChain();
01094
01095
for (
KSSLCertificate *c = cl.
first(); c != 0; c = cl.
next()) {
01096 qsl << c->
toString();
01097 }
01098
01099 cl.
setAutoDelete(
true);
01100
01101 s << const_cast<KSSLCertificate&>(r).toString() << qsl;
01102
01103
return s;
01104 }
01105
01106
01107
QDataStream& operator>>(
QDataStream& s,
KSSLCertificate& r) {
01108
QStringList qsl;
01109
QString cert;
01110
01111 s >> cert >> qsl;
01112
01113
if (r.
setCert(cert) && !qsl.isEmpty())
01114 r.
chain().
setCertChain(qsl);
01115
01116
return s;
01117 }
01118
01119
01120