• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeio/kssl
 

tdeio/kssl

  • tdeio
  • kssl
ksslcertificate.cc
1 /* This file is part of the KDE project
2  *
3  * Copyright (C) 2000-2003 George Staikos <staikos@kde.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB. If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 
26 
27 
28 #include <unistd.h>
29 #include <tqstring.h>
30 #include <tqstringlist.h>
31 #include <tqfile.h>
32 
33 #include "kssldefs.h"
34 #include "ksslcertificate.h"
35 #include "ksslcertchain.h"
36 #include "ksslutils.h"
37 
38 #include <kstandarddirs.h>
39 #include <kmdcodec.h>
40 #include <tdelocale.h>
41 #include <tqdatetime.h>
42 #include <tdetempfile.h>
43 
44 #include <sys/types.h>
45 
46 #ifdef HAVE_SYS_STAT_H
47 #include <sys/stat.h>
48 #endif
49 
50 // this hack provided by Malte Starostik to avoid glibc/openssl bug
51 // on some systems
52 #ifdef KSSL_HAVE_SSL
53 #define crypt _openssl_crypt
54 #include <openssl/ssl.h>
55 #include <openssl/x509.h>
56 #include <openssl/x509v3.h>
57 #include <openssl/x509_vfy.h>
58 #include <openssl/pem.h>
59 #undef crypt
60 #endif
61 
62 #include <kopenssl.h>
63 #include <tqcstring.h>
64 #include <kdebug.h>
65 #include "ksslx509v3.h"
66 
67 
68 
69 static char hv[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
70 
71 
72 class KSSLCertificatePrivate {
73 public:
74  KSSLCertificatePrivate() {
75  kossl = KOSSL::self();
76  _lastPurpose = KSSLCertificate::None;
77  }
78 
79  ~KSSLCertificatePrivate() {
80  }
81 
82  KSSLCertificate::KSSLValidation m_stateCache;
83  bool m_stateCached;
84  #ifdef KSSL_HAVE_SSL
85  X509 *m_cert;
86  #endif
87  KOSSL *kossl;
88  KSSLCertChain _chain;
89  KSSLX509V3 _extensions;
90  KSSLCertificate::KSSLPurpose _lastPurpose;
91 };
92 
93 KSSLCertificate::KSSLCertificate() {
94  d = new KSSLCertificatePrivate;
95  d->m_stateCached = false;
96  TDEGlobal::dirs()->addResourceType("kssl", TDEStandardDirs::kde_default("data") + "kssl");
97  #ifdef KSSL_HAVE_SSL
98  d->m_cert = NULL;
99  #endif
100 }
101 
102 
103 KSSLCertificate::KSSLCertificate(const KSSLCertificate& x) {
104  d = new KSSLCertificatePrivate;
105  d->m_stateCached = false;
106  TDEGlobal::dirs()->addResourceType("kssl", TDEStandardDirs::kde_default("data") + "kssl");
107  #ifdef KSSL_HAVE_SSL
108  d->m_cert = NULL;
109  setCert(KOSSL::self()->X509_dup(const_cast<KSSLCertificate&>(x).getCert()));
110  KSSLCertChain *c = x.d->_chain.replicate();
111  setChain(c->rawChain());
112  delete c;
113  #endif
114 }
115 
116 
117 
118 KSSLCertificate::~KSSLCertificate() {
119 #ifdef KSSL_HAVE_SSL
120  if (d->m_cert)
121  d->kossl->X509_free(d->m_cert);
122 #endif
123  delete d;
124 }
125 
126 
127 KSSLCertChain& KSSLCertificate::chain() {
128  return d->_chain;
129 }
130 
131 
132 KSSLCertificate *KSSLCertificate::fromX509(X509 *x5) {
133 KSSLCertificate *n = NULL;
134 #ifdef KSSL_HAVE_SSL
135  if (x5) {
136  n = new KSSLCertificate;
137  n->setCert(KOSSL::self()->X509_dup(x5));
138  }
139 #endif
140 return n;
141 }
142 
143 
144 KSSLCertificate *KSSLCertificate::fromString(TQCString cert) {
145 KSSLCertificate *n = NULL;
146 #ifdef KSSL_HAVE_SSL
147  if (cert.length() == 0)
148  return NULL;
149 
150  TQByteArray qba, qbb = cert.copy();
151  KCodecs::base64Decode(qbb, qba);
152  unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data());
153  X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size());
154  if (!x5c) {
155  return NULL;
156  }
157 
158  n = new KSSLCertificate;
159  n->setCert(x5c);
160 #endif
161 return n;
162 }
163 
164 
165 
166 TQString KSSLCertificate::getSubject() const {
167 TQString rc = "";
168 
169 #ifdef KSSL_HAVE_SSL
170  char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_subject_name(d->m_cert), 0, 0);
171  if (!t)
172  return rc;
173  rc = t;
174  d->kossl->OPENSSL_free(t);
175 #endif
176 return rc;
177 }
178 
179 
180 TQString KSSLCertificate::getSerialNumber() const {
181 TQString rc = "";
182 
183 #ifdef KSSL_HAVE_SSL
184  ASN1_INTEGER *aint = d->kossl->X509_get_serialNumber(d->m_cert);
185  if (aint) {
186  rc = ASN1_INTEGER_QString(aint);
187  // d->kossl->ASN1_INTEGER_free(aint); this makes the sig test fail
188  }
189 #endif
190 return rc;
191 }
192 
193 
194 TQString KSSLCertificate::getSignatureText() const {
195 TQString rc = "";
196 
197 #ifdef KSSL_HAVE_SSL
198 char *s;
199 int n, i;
200 
201  i = d->kossl->OBJ_obj2nid(d->m_cert->sig_alg->algorithm);
202  rc = i18n("Signature Algorithm: ");
203  rc += (i == NID_undef)?i18n("Unknown"):TQString(d->kossl->OBJ_nid2ln(i));
204 
205  rc += "\n";
206  rc += i18n("Signature Contents:");
207  n = d->m_cert->signature->length;
208  s = (char *)d->m_cert->signature->data;
209  for (i = 0; i < n; i++) {
210  if (i%20 != 0) rc += ":";
211  else rc += "\n";
212  rc.append(hv[(s[i]&0xf0)>>4]);
213  rc.append(hv[s[i]&0x0f]);
214  }
215 
216 #endif
217 
218 return rc;
219 }
220 
221 
222 void KSSLCertificate::getEmails(TQStringList &to) const {
223  to.clear();
224 #ifdef KSSL_HAVE_SSL
225  if (!d->m_cert)
226  return;
227 
228  STACK *s = d->kossl->X509_get1_email(d->m_cert);
229  if (s) {
230  for(int n=0; n < s->num; n++) {
231  to.append(d->kossl->sk_value(s,n));
232  }
233  d->kossl->X509_email_free(s);
234  }
235 #endif
236 }
237 
238 
239 TQString KSSLCertificate::getKDEKey() const {
240  return getSubject() + " (" + getMD5DigestText() + ")";
241 }
242 
243 
244 TQString KSSLCertificate::getMD5DigestFromKDEKey(const TQString &k) {
245  TQString rc;
246  int pos = k.findRev('(');
247  if (pos != -1) {
248  unsigned int len = k.length();
249  if (k.at(len-1) == ')') {
250  rc = k.mid(pos+1, len-pos-2);
251  }
252  }
253  return rc;
254 }
255 
256 
257 TQString KSSLCertificate::getMD5DigestText() const {
258 TQString rc = "";
259 
260 #ifdef KSSL_HAVE_SSL
261  unsigned int n;
262  unsigned char md[EVP_MAX_MD_SIZE];
263 
264  if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) {
265  return rc;
266  }
267 
268  for (unsigned int j = 0; j < n; j++) {
269  if (j > 0)
270  rc += ":";
271  rc.append(hv[(md[j]&0xf0)>>4]);
272  rc.append(hv[md[j]&0x0f]);
273  }
274 
275 #endif
276 
277 return rc;
278 }
279 
280 
281 
282 TQString KSSLCertificate::getMD5Digest() const {
283 TQString rc = "";
284 
285 #ifdef KSSL_HAVE_SSL
286  unsigned int n;
287  unsigned char md[EVP_MAX_MD_SIZE];
288 
289  if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) {
290  return rc;
291  }
292 
293  for (unsigned int j = 0; j < n; j++) {
294  rc.append(hv[(md[j]&0xf0)>>4]);
295  rc.append(hv[md[j]&0x0f]);
296  }
297 
298 #endif
299 
300 return rc;
301 }
302 
303 
304 
305 TQString KSSLCertificate::getKeyType() const {
306 TQString rc = "";
307 
308 #ifdef KSSL_HAVE_SSL
309  EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert);
310  if (pkey) {
311  #ifndef NO_RSA
312  if (pkey->type == EVP_PKEY_RSA)
313  rc = "RSA";
314  else
315  #endif
316  #ifndef NO_DSA
317  if (pkey->type == EVP_PKEY_DSA)
318  rc = "DSA";
319  else
320  #endif
321  rc = "Unknown";
322  d->kossl->EVP_PKEY_free(pkey);
323  }
324 #endif
325 
326 return rc;
327 }
328 
329 
330 
331 TQString KSSLCertificate::getPublicKeyText() const {
332 TQString rc = "";
333 char *x = NULL;
334 
335 #ifdef KSSL_HAVE_SSL
336  EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert);
337  if (pkey) {
338  rc = i18n("Unknown", "Unknown key algorithm");
339  #ifndef NO_RSA
340  if (pkey->type == EVP_PKEY_RSA) {
341  rc = i18n("Key type: RSA (%1 bit)") + "\n";
342 
343  x = d->kossl->BN_bn2hex(pkey->pkey.rsa->n);
344  rc += i18n("Modulus: ");
345  rc = rc.arg(strlen(x)*4);
346  for (unsigned int i = 0; i < strlen(x); i++) {
347  if (i%40 != 0 && i%2 == 0)
348  rc += ":";
349  else if (i%40 == 0)
350  rc += "\n";
351  rc += x[i];
352  }
353  rc += "\n";
354  d->kossl->OPENSSL_free(x);
355 
356  x = d->kossl->BN_bn2hex(pkey->pkey.rsa->e);
357  rc += i18n("Exponent: 0x") + x + "\n";
358  d->kossl->OPENSSL_free(x);
359  }
360  #endif
361  #ifndef NO_DSA
362  if (pkey->type == EVP_PKEY_DSA) {
363  rc = i18n("Key type: DSA (%1 bit)") + "\n";
364 
365  x = d->kossl->BN_bn2hex(pkey->pkey.dsa->p);
366  rc += i18n("Prime: ");
367  // hack - this may not be always accurate
368  rc = rc.arg(strlen(x)*4) ;
369  for (unsigned int i = 0; i < strlen(x); i++) {
370  if (i%40 != 0 && i%2 == 0)
371  rc += ":";
372  else if (i%40 == 0)
373  rc += "\n";
374  rc += x[i];
375  }
376  rc += "\n";
377  d->kossl->OPENSSL_free(x);
378 
379  x = d->kossl->BN_bn2hex(pkey->pkey.dsa->q);
380  rc += i18n("160 bit prime factor: ");
381  for (unsigned int i = 0; i < strlen(x); i++) {
382  if (i%40 != 0 && i%2 == 0)
383  rc += ":";
384  else if (i%40 == 0)
385  rc += "\n";
386  rc += x[i];
387  }
388  rc += "\n";
389  d->kossl->OPENSSL_free(x);
390 
391  x = d->kossl->BN_bn2hex(pkey->pkey.dsa->g);
392  rc += TQString("g: ");
393  for (unsigned int i = 0; i < strlen(x); i++) {
394  if (i%40 != 0 && i%2 == 0)
395  rc += ":";
396  else if (i%40 == 0)
397  rc += "\n";
398  rc += x[i];
399  }
400  rc += "\n";
401  d->kossl->OPENSSL_free(x);
402 
403  x = d->kossl->BN_bn2hex(pkey->pkey.dsa->pub_key);
404  rc += i18n("Public key: ");
405  for (unsigned int i = 0; i < strlen(x); i++) {
406  if (i%40 != 0 && i%2 == 0)
407  rc += ":";
408  else if (i%40 == 0)
409  rc += "\n";
410  rc += x[i];
411  }
412  rc += "\n";
413  d->kossl->OPENSSL_free(x);
414  }
415  #endif
416  d->kossl->EVP_PKEY_free(pkey);
417  }
418 #endif
419 
420 return rc;
421 }
422 
423 
424 
425 TQString KSSLCertificate::getIssuer() const {
426 TQString rc = "";
427 
428 #ifdef KSSL_HAVE_SSL
429  char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_issuer_name(d->m_cert), 0, 0);
430 
431  if (!t)
432  return rc;
433 
434  rc = t;
435  d->kossl->OPENSSL_free(t);
436 #endif
437 
438 return rc;
439 }
440 
441 void KSSLCertificate::setChain(void *c) {
442 #ifdef KSSL_HAVE_SSL
443  d->_chain.setChain(c);
444 #endif
445  d->m_stateCached = false;
446  d->m_stateCache = KSSLCertificate::Unknown;
447 }
448 
449 void KSSLCertificate::setCert(X509 *c) {
450 #ifdef KSSL_HAVE_SSL
451 d->m_cert = c;
452 if (c) {
453  d->_extensions.flags = 0;
454  d->kossl->X509_check_purpose(c, -1, 0); // setup the fields (!!)
455 
456 #if 0
457  kdDebug(7029) << "---------------- Certificate ------------------"
458  << endl;
459  kdDebug(7029) << getSubject() << endl;
460 #endif
461 
462  for (int j = 0; j < d->kossl->X509_PURPOSE_get_count(); j++) {
463  X509_PURPOSE *ptmp = d->kossl->X509_PURPOSE_get0(j);
464  int id = d->kossl->X509_PURPOSE_get_id(ptmp);
465  for (int ca = 0; ca < 2; ca++) {
466  int idret = d->kossl->X509_check_purpose(c, id, ca);
467  if (idret == 1 || idret == 2) { // have it
468 // kdDebug() << "PURPOSE: " << id << (ca?" CA":"") << endl;
469  if (!ca)
470  d->_extensions.flags |= (1L <<(id-1));
471  else d->_extensions.flags |= (1L <<(16+id-1));
472  } else {
473  if (!ca)
474  d->_extensions.flags &= ~(1L <<(id-1));
475  else d->_extensions.flags &= ~(1L <<(16+id-1));
476  }
477  }
478  }
479 
480 #if 0
481  kdDebug(7029) << "flags: " << TQString::number(c->ex_flags, 2)
482  << "\nkeyusage: " << TQString::number(c->ex_kusage, 2)
483  << "\nxkeyusage: " << TQString::number(c->ex_xkusage, 2)
484  << "\nnscert: " << TQString::number(c->ex_nscert, 2)
485  << endl;
486  if (c->ex_flags & EXFLAG_KUSAGE)
487  kdDebug(7029) << " --- Key Usage extensions found" << endl;
488  else kdDebug(7029) << " --- Key Usage extensions NOT found" << endl;
489 
490  if (c->ex_flags & EXFLAG_XKUSAGE)
491  kdDebug(7029) << " --- Extended key usage extensions found" << endl;
492  else kdDebug(7029) << " --- Extended key usage extensions NOT found" << endl;
493 
494  if (c->ex_flags & EXFLAG_NSCERT)
495  kdDebug(7029) << " --- NS extensions found" << endl;
496  else kdDebug(7029) << " --- NS extensions NOT found" << endl;
497 
498  if (d->_extensions.certTypeSSLCA())
499  kdDebug(7029) << "NOTE: this is an SSL CA file." << endl;
500  else kdDebug(7029) << "NOTE: this is NOT an SSL CA file." << endl;
501 
502  if (d->_extensions.certTypeEmailCA())
503  kdDebug(7029) << "NOTE: this is an EMAIL CA file." << endl;
504  else kdDebug(7029) << "NOTE: this is NOT an EMAIL CA file." << endl;
505 
506  if (d->_extensions.certTypeCodeCA())
507  kdDebug(7029) << "NOTE: this is a CODE CA file." << endl;
508  else kdDebug(7029) << "NOTE: this is NOT a CODE CA file." << endl;
509 
510  if (d->_extensions.certTypeSSLClient())
511  kdDebug(7029) << "NOTE: this is an SSL client." << endl;
512  else kdDebug(7029) << "NOTE: this is NOT an SSL client." << endl;
513 
514  if (d->_extensions.certTypeSSLServer())
515  kdDebug(7029) << "NOTE: this is an SSL server." << endl;
516  else kdDebug(7029) << "NOTE: this is NOT an SSL server." << endl;
517 
518  if (d->_extensions.certTypeNSSSLServer())
519  kdDebug(7029) << "NOTE: this is a NETSCAPE SSL server." << endl;
520  else kdDebug(7029) << "NOTE: this is NOT a NETSCAPE SSL server." << endl;
521 
522  if (d->_extensions.certTypeSMIME())
523  kdDebug(7029) << "NOTE: this is an SMIME certificate." << endl;
524  else kdDebug(7029) << "NOTE: this is NOT an SMIME certificate." << endl;
525 
526  if (d->_extensions.certTypeSMIMEEncrypt())
527  kdDebug(7029) << "NOTE: this is an SMIME encrypt cert." << endl;
528  else kdDebug(7029) << "NOTE: this is NOT an SMIME encrypt cert." << endl;
529 
530  if (d->_extensions.certTypeSMIMESign())
531  kdDebug(7029) << "NOTE: this is an SMIME sign cert." << endl;
532  else kdDebug(7029) << "NOTE: this is NOT an SMIME sign cert." << endl;
533 
534  if (d->_extensions.certTypeCRLSign())
535  kdDebug(7029) << "NOTE: this is a CRL signer." << endl;
536  else kdDebug(7029) << "NOTE: this is NOT a CRL signer." << endl;
537 
538  kdDebug(7029) << "-----------------------------------------------"
539  << endl;
540 #endif
541 }
542 #endif
543 d->m_stateCached = false;
544 d->m_stateCache = KSSLCertificate::Unknown;
545 }
546 
547 X509 *KSSLCertificate::getCert() {
548 #ifdef KSSL_HAVE_SSL
549  return d->m_cert;
550 #endif
551 return 0;
552 }
553 
554 // pull in the callback. It's common across multiple files but we want
555 // it to be hidden.
556 
557 #include "ksslcallback.c"
558 
559 
560 bool KSSLCertificate::isValid(KSSLCertificate::KSSLPurpose p) {
561  return (validate(p) == KSSLCertificate::Ok);
562 }
563 
564 
565 bool KSSLCertificate::isValid() {
566  return isValid(KSSLCertificate::SSLServer);
567 }
568 
569 
570 int KSSLCertificate::purposeToOpenSSL(KSSLCertificate::KSSLPurpose p) const {
571 int rc = 0;
572 #ifdef KSSL_HAVE_SSL
573  if (p == KSSLCertificate::SSLServer) {
574  rc = X509_PURPOSE_SSL_SERVER;
575  } else if (p == KSSLCertificate::SSLClient) {
576  rc = X509_PURPOSE_SSL_CLIENT;
577  } else if (p == KSSLCertificate::SMIMEEncrypt) {
578  rc = X509_PURPOSE_SMIME_ENCRYPT;
579  } else if (p == KSSLCertificate::SMIMESign) {
580  rc = X509_PURPOSE_SMIME_SIGN;
581  } else if (p == KSSLCertificate::Any) {
582  rc = X509_PURPOSE_ANY;
583  }
584 #endif
585 return rc;
586 }
587 
588 
589 // For backward compatibility
590 KSSLCertificate::KSSLValidation KSSLCertificate::validate() {
591  return validate(KSSLCertificate::SSLServer);
592 }
593 
594 KSSLCertificate::KSSLValidation KSSLCertificate::validate(KSSLCertificate::KSSLPurpose purpose)
595 {
596  KSSLValidationList result = validateVerbose(purpose);
597  if (result.isEmpty())
598  return KSSLCertificate::Ok;
599  else
600  return result.first();
601 }
602 
603 //
604 // See apps/verify.c in OpenSSL for the source of most of this logic.
605 //
606 
607 // CRL files? we don't do that yet
608 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose)
609 {
610  return validateVerbose(purpose, 0);
611 }
612 
613 KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose, KSSLCertificate *ca)
614 {
615  KSSLValidationList errors;
616  if (ca || (d->_lastPurpose != purpose)) {
617  d->m_stateCached = false;
618  }
619 
620  if (!d->m_stateCached)
621  d->_lastPurpose = purpose;
622 
623 #ifdef KSSL_HAVE_SSL
624  X509_STORE *certStore;
625  X509_LOOKUP *certLookup;
626  X509_STORE_CTX *certStoreCTX;
627  int rc = 0;
628 
629  if (!d->m_cert)
630  {
631  errors << KSSLCertificate::Unknown;
632  return errors;
633  }
634 
635  if (d->m_stateCached) {
636  errors << d->m_stateCache;
637  return errors;
638  }
639 
640  TQStringList qsl = TDEGlobal::dirs()->resourceDirs("kssl");
641 
642  if (qsl.isEmpty()) {
643  errors << KSSLCertificate::NoCARoot;
644  return errors;
645  }
646 
647  KSSLCertificate::KSSLValidation ksslv = Unknown;
648 
649  for (TQStringList::Iterator j = qsl.begin(); j != qsl.end(); ++j) {
650  struct stat sb;
651  TQString _j = (*j) + "ca-bundle.crt";
652  if (-1 == stat(_j.ascii(), &sb)) {
653  continue;
654  }
655 
656  certStore = d->kossl->X509_STORE_new();
657  if (!certStore) {
658  errors << KSSLCertificate::Unknown;
659  return errors;
660  }
661 
662  X509_STORE_set_verify_cb_func(certStore, X509Callback);
663 
664  certLookup = d->kossl->X509_STORE_add_lookup(certStore, d->kossl->X509_LOOKUP_file());
665  if (!certLookup) {
666  ksslv = KSSLCertificate::Unknown;
667  d->kossl->X509_STORE_free(certStore);
668  continue;
669  }
670 
671  if (!d->kossl->X509_LOOKUP_load_file(certLookup, _j.ascii(), X509_FILETYPE_PEM)) {
672  // error accessing directory and loading pems
673  kdDebug(7029) << "KSSL couldn't read CA root: "
674  << _j << endl;
675  ksslv = KSSLCertificate::ErrorReadingRoot;
676  d->kossl->X509_STORE_free(certStore);
677  continue;
678  }
679 
680  // This is the checking code
681  certStoreCTX = d->kossl->X509_STORE_CTX_new();
682 
683  // this is a bad error - could mean no free memory.
684  // This may be the wrong thing to do here
685  if (!certStoreCTX) {
686  kdDebug(7029) << "KSSL couldn't create an X509 store context." << endl;
687  d->kossl->X509_STORE_free(certStore);
688  continue;
689  }
690 
691  d->kossl->X509_STORE_CTX_init(certStoreCTX, certStore, d->m_cert, NULL);
692  if (d->_chain.isValid()) {
693  d->kossl->X509_STORE_CTX_set_chain(certStoreCTX, (STACK_OF(X509)*)d->_chain.rawChain());
694  }
695 
696  //kdDebug(7029) << "KSSL setting CRL.............." << endl;
697  // int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x);
698 
699  d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, purposeToOpenSSL(purpose));
700 
701  KSSL_X509CallBack_ca = ca ? ca->d->m_cert : 0;
702  KSSL_X509CallBack_ca_found = false;
703 
704  certStoreCTX->error = X509_V_OK;
705  rc = d->kossl->X509_verify_cert(certStoreCTX);
706  int errcode = certStoreCTX->error;
707  if (ca && !KSSL_X509CallBack_ca_found) {
708  ksslv = KSSLCertificate::Irrelevant;
709  } else {
710  ksslv = processError(errcode);
711  }
712  // For servers, we can try NS_SSL_SERVER too
713  if ( (ksslv != KSSLCertificate::Ok) &&
714  (ksslv != KSSLCertificate::Irrelevant) &&
715  purpose == KSSLCertificate::SSLServer) {
716  d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX,
717  X509_PURPOSE_NS_SSL_SERVER);
718 
719  certStoreCTX->error = X509_V_OK;
720  rc = d->kossl->X509_verify_cert(certStoreCTX);
721  errcode = certStoreCTX->error;
722  ksslv = processError(errcode);
723  }
724  d->kossl->X509_STORE_CTX_free(certStoreCTX);
725  d->kossl->X509_STORE_free(certStore);
726  // end of checking code
727  //
728 
729  //kdDebug(7029) << "KSSL Validation procedure RC: "
730  // << rc << endl;
731  //kdDebug(7029) << "KSSL Validation procedure errcode: "
732  // << errcode << endl;
733  //kdDebug(7029) << "KSSL Validation procedure RESULTS: "
734  // << ksslv << endl;
735 
736  if (ksslv != NoCARoot && ksslv != InvalidCA) {
737  d->m_stateCached = true;
738  d->m_stateCache = ksslv;
739  }
740  break;
741  }
742 
743  if (ksslv != KSSLCertificate::Ok)
744  errors << ksslv;
745 #else
746  errors << KSSLCertificate::NoSSL;
747 #endif
748  return errors;
749 }
750 
751 
752 
753 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate() {
754  return revalidate(KSSLCertificate::SSLServer);
755 }
756 
757 
758 KSSLCertificate::KSSLValidation KSSLCertificate::revalidate(KSSLCertificate::KSSLPurpose p) {
759  d->m_stateCached = false;
760  return validate(p);
761 }
762 
763 
764 KSSLCertificate::KSSLValidation KSSLCertificate::processError(int ec) {
765 KSSLCertificate::KSSLValidation rc;
766 
767 rc = KSSLCertificate::Unknown;
768 #ifdef KSSL_HAVE_SSL
769  switch (ec) {
770  case X509_V_OK: // OK
771  rc = KSSLCertificate::Ok;
772  break;
773 
774 
775  case X509_V_ERR_CERT_REJECTED:
776  rc = KSSLCertificate::Rejected;
777  break;
778 
779 
780  case X509_V_ERR_CERT_UNTRUSTED:
781  rc = KSSLCertificate::Untrusted;
782  break;
783 
784 
785  case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
786  case X509_V_ERR_CERT_SIGNATURE_FAILURE:
787  case X509_V_ERR_CRL_SIGNATURE_FAILURE:
788  case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
789  case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
790  rc = KSSLCertificate::SignatureFailed;
791  break;
792 
793  case X509_V_ERR_INVALID_CA:
794  case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
795  case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
796  case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
797  rc = KSSLCertificate::InvalidCA;
798  break;
799 
800 
801  case X509_V_ERR_INVALID_PURPOSE:
802  rc = KSSLCertificate::InvalidPurpose;
803  break;
804 
805 
806  case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
807  rc = KSSLCertificate::SelfSigned;
808  break;
809 
810  case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
811  rc = KSSLCertificate::SelfSignedChain;
812  break;
813 
814  case X509_V_ERR_CERT_REVOKED:
815  rc = KSSLCertificate::Revoked;
816  break;
817 
818  case X509_V_ERR_PATH_LENGTH_EXCEEDED:
819  rc = KSSLCertificate::PathLengthExceeded;
820  break;
821 
822  case X509_V_ERR_CERT_NOT_YET_VALID:
823  case X509_V_ERR_CERT_HAS_EXPIRED:
824  case X509_V_ERR_CRL_NOT_YET_VALID:
825  case X509_V_ERR_CRL_HAS_EXPIRED:
826  case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
827  case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
828  case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
829  case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
830  rc = KSSLCertificate::Expired;
831  kdDebug(7029) << "KSSL apparently this is expired. Not after: "
832  << getNotAfter() << endl;
833  break;
834 
835  //case 1:
836  case X509_V_ERR_APPLICATION_VERIFICATION:
837  case X509_V_ERR_OUT_OF_MEM:
838  case X509_V_ERR_UNABLE_TO_GET_CRL:
839  case X509_V_ERR_CERT_CHAIN_TOO_LONG:
840  default:
841  rc = KSSLCertificate::Unknown;
842  break;
843 }
844 
845 d->m_stateCache = rc;
846 d->m_stateCached = true;
847 #endif
848 return rc;
849 }
850 
851 
852 TQString KSSLCertificate::getNotBefore() const {
853 #ifdef KSSL_HAVE_SSL
854 return ASN1_UTCTIME_QString(X509_get_notBefore(d->m_cert));
855 #else
856 return TQString::null;
857 #endif
858 }
859 
860 
861 TQString KSSLCertificate::getNotAfter() const {
862 #ifdef KSSL_HAVE_SSL
863 return ASN1_UTCTIME_QString(X509_get_notAfter(d->m_cert));
864 #else
865 return TQString::null;
866 #endif
867 }
868 
869 
870 TQDateTime KSSLCertificate::getQDTNotBefore() const {
871 #ifdef KSSL_HAVE_SSL
872 return ASN1_UTCTIME_QDateTime(X509_get_notBefore(d->m_cert), NULL);
873 #else
874 return TQDateTime::currentDateTime();
875 #endif
876 }
877 
878 
879 TQDateTime KSSLCertificate::getQDTNotAfter() const {
880 #ifdef KSSL_HAVE_SSL
881 return ASN1_UTCTIME_QDateTime(X509_get_notAfter(d->m_cert), NULL);
882 #else
883 return TQDateTime::currentDateTime();
884 #endif
885 }
886 
887 
888 int operator==(KSSLCertificate &x, KSSLCertificate &y) {
889 #ifndef KSSL_HAVE_SSL
890  return 1;
891 #else
892  if (!KOSSL::self()->X509_cmp(x.getCert(), y.getCert())) return 1;
893  return 0;
894 #endif
895 }
896 
897 
898 KSSLCertificate *KSSLCertificate::replicate() {
899 // The new certificate doesn't have the cached value. It's probably
900 // better this way. We can't anticipate every reason for doing this.
901 KSSLCertificate *newOne = new KSSLCertificate();
902 #ifdef KSSL_HAVE_SSL
903  newOne->setCert(d->kossl->X509_dup(getCert()));
904  KSSLCertChain *c = d->_chain.replicate();
905  newOne->setChain(c->rawChain());
906  delete c;
907 #endif
908 return newOne;
909 }
910 
911 
912 TQString KSSLCertificate::toString() {
913 return KCodecs::base64Encode(toDer());
914 }
915 
916 
917 TQString KSSLCertificate::verifyText(KSSLValidation x) {
918 switch (x) {
919 case KSSLCertificate::Ok:
920  return i18n("The certificate is valid.");
921 case KSSLCertificate::PathLengthExceeded:
922 case KSSLCertificate::ErrorReadingRoot:
923 case KSSLCertificate::NoCARoot:
924  return i18n("Certificate signing authority root files could not be found so the certificate is not verified.");
925 case KSSLCertificate::SelfSignedChain:
926 case KSSLCertificate::InvalidCA:
927  return i18n("Certificate signing authority is unknown or invalid.");
928 case KSSLCertificate::SelfSigned:
929  return i18n("Certificate is self-signed and thus may not be trustworthy.");
930 case KSSLCertificate::Expired:
931  return i18n("Certificate has expired.");
932 case KSSLCertificate::Revoked:
933  return i18n("Certificate has been revoked.");
934 case KSSLCertificate::NoSSL:
935  return i18n("SSL support was not found.");
936 case KSSLCertificate::Untrusted:
937  return i18n("Signature is untrusted.");
938 case KSSLCertificate::SignatureFailed:
939  return i18n("Signature test failed.");
940 case KSSLCertificate::Rejected:
941 case KSSLCertificate::InvalidPurpose:
942  return i18n("Rejected, possibly due to an invalid purpose.");
943 case KSSLCertificate::PrivateKeyFailed:
944  return i18n("Private key test failed.");
945 case KSSLCertificate::InvalidHost:
946  return i18n("The certificate has not been issued for this host.");
947 case KSSLCertificate::Irrelevant:
948  return i18n("This certificate is not relevant.");
949 default:
950 break;
951 }
952 
953 return i18n("The certificate is invalid.");
954 }
955 
956 
957 TQByteArray KSSLCertificate::toDer() {
958 TQByteArray qba;
959 #ifdef KSSL_HAVE_SSL
960 unsigned int certlen = d->kossl->i2d_X509(getCert(), NULL);
961 unsigned char *cert = new unsigned char[certlen];
962 unsigned char *p = cert;
963  // FIXME: return code!
964  d->kossl->i2d_X509(getCert(), &p);
965 
966  // encode it into a QString
967  qba.duplicate((const char*)cert, certlen);
968  delete[] cert;
969 #endif
970 return qba;
971 }
972 
973 
974 
975 TQByteArray KSSLCertificate::toPem() {
976 TQByteArray qba;
977 TQString thecert = toString();
978 const char *header = "-----BEGIN CERTIFICATE-----\n";
979 const char *footer = "-----END CERTIFICATE-----\n";
980 
981  // We just do base64 on the ASN1
982  // 64 character lines (unpadded)
983  unsigned int xx = thecert.length() - 1;
984  for (unsigned int i = 0; i < xx/64; i++) {
985  thecert.insert(64*(i+1)+i, '\n');
986  }
987 
988  thecert.prepend(header);
989 
990  if (thecert[thecert.length()-1] != '\n')
991  thecert += "\n";
992 
993  thecert.append(footer);
994 
995  qba.duplicate(thecert.local8Bit(), thecert.length());
996 return qba;
997 }
998 
999 
1000 #define NETSCAPE_CERT_HDR "certificate"
1001 
1002 // what a piece of crap this is
1003 TQByteArray KSSLCertificate::toNetscape() {
1004 TQByteArray qba;
1005 #ifdef KSSL_HAVE_SSL
1006 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
1007  NETSCAPE_X509 nx;
1008  ASN1_OCTET_STRING hdr;
1009 #else
1010  ASN1_HEADER ah;
1011  ASN1_OCTET_STRING os;
1012 #endif
1013  KTempFile ktf;
1014 
1015 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
1016  hdr.data = (unsigned char *)NETSCAPE_CERT_HDR;
1017  hdr.length = strlen(NETSCAPE_CERT_HDR);
1018  nx.header = &hdr;
1019  nx.cert = getCert();
1020 
1021  d->kossl->ASN1_i2d_fp(ktf.fstream(),(unsigned char *)&nx);
1022 #else
1023  os.data = (unsigned char *)NETSCAPE_CERT_HDR;
1024  os.length = strlen(NETSCAPE_CERT_HDR);
1025  ah.header = &os;
1026  ah.data = (char *)getCert();
1027  ah.meth = d->kossl->X509_asn1_meth();
1028 
1029  d->kossl->ASN1_i2d_fp(ktf.fstream(),(unsigned char *)&ah);
1030 #endif
1031 
1032  ktf.close();
1033 
1034  TQFile qf(ktf.name());
1035  qf.open(IO_ReadOnly);
1036  char *buf = new char[qf.size()];
1037  qf.readBlock(buf, qf.size());
1038  qba.duplicate(buf, qf.size());
1039  qf.close();
1040  delete[] buf;
1041 
1042  ktf.unlink();
1043 
1044 #endif
1045 return qba;
1046 }
1047 
1048 
1049 
1050 TQString KSSLCertificate::toText() {
1051 TQString text;
1052 #ifdef KSSL_HAVE_SSL
1053 KTempFile ktf;
1054 
1055  d->kossl->X509_print(ktf.fstream(), getCert());
1056  ktf.close();
1057 
1058  TQFile qf(ktf.name());
1059  qf.open(IO_ReadOnly);
1060  char *buf = new char[qf.size()+1];
1061  qf.readBlock(buf, qf.size());
1062  buf[qf.size()] = 0;
1063  text = buf;
1064  delete[] buf;
1065  qf.close();
1066  ktf.unlink();
1067 #endif
1068 return text;
1069 }
1070 
1071 // KDE 4: Make it const TQString &
1072 bool KSSLCertificate::setCert(TQString& cert) {
1073 #ifdef KSSL_HAVE_SSL
1074 TQByteArray qba, qbb = cert.local8Bit().copy();
1075  KCodecs::base64Decode(qbb, qba);
1076  unsigned char *qbap = reinterpret_cast<unsigned char *>(qba.data());
1077  X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size());
1078  if (x5c) {
1079  setCert(x5c);
1080  return true;
1081  }
1082 #endif
1083 return false;
1084 }
1085 
1086 
1087 KSSLX509V3& KSSLCertificate::x509V3Extensions() {
1088 return d->_extensions;
1089 }
1090 
1091 
1092 bool KSSLCertificate::isSigner() {
1093 return d->_extensions.certTypeCA();
1094 }
1095 
1096 
1097 TQStringList KSSLCertificate::subjAltNames() const {
1098  TQStringList rc;
1099 #ifdef KSSL_HAVE_SSL
1100  STACK_OF(GENERAL_NAME) *names;
1101  names = (STACK_OF(GENERAL_NAME)*)d->kossl->X509_get_ext_d2i(d->m_cert, NID_subject_alt_name, 0, 0);
1102 
1103  if (!names) {
1104  return rc;
1105  }
1106 
1107  int cnt = d->kossl->sk_GENERAL_NAME_num(names);
1108 
1109  for (int i = 0; i < cnt; i++) {
1110  const GENERAL_NAME *val = (const GENERAL_NAME *)d->kossl->sk_value(names, i);
1111  if (val->type != GEN_DNS) {
1112  continue;
1113  }
1114 
1115  TQString s = (const char *)d->kossl->ASN1_STRING_data(val->d.ia5);
1116  if (!s.isEmpty() &&
1117  /* skip subjectAltNames with embedded NULs */
1118  s.length() == d->kossl->ASN1_STRING_length(val->d.ia5)) {
1119  rc += s;
1120  }
1121  }
1122  d->kossl->sk_free(names);
1123 #endif
1124  return rc;
1125 }
1126 
1127 
1128 TQDataStream& operator<<(TQDataStream& s, const KSSLCertificate& r) {
1129 TQStringList qsl;
1130 TQPtrList<KSSLCertificate> cl = const_cast<KSSLCertificate&>(r).chain().getChain();
1131 
1132  for (KSSLCertificate *c = cl.first(); c != 0; c = cl.next()) {
1133  qsl << c->toString();
1134  }
1135 
1136  cl.setAutoDelete(true);
1137 
1138  s << const_cast<KSSLCertificate&>(r).toString() << qsl;
1139 
1140 return s;
1141 }
1142 
1143 
1144 TQDataStream& operator>>(TQDataStream& s, KSSLCertificate& r) {
1145 TQStringList qsl;
1146 TQString cert;
1147 
1148 s >> cert >> qsl;
1149 
1150  if (r.setCert(cert) && !qsl.isEmpty())
1151  r.chain().setCertChain(qsl);
1152 
1153 return s;
1154 }
1155 
1156 
1157 
KSSLCertChain::setCertChain
void setCertChain(const TQStringList &chain)
Set the certificate chain as a list of base64 encoded X.509 certificates.
Definition: ksslcertchain.cc:194
KSSLCertificate::getSignatureText
TQString getSignatureText() const
Get the signature.
Definition: ksslcertificate.cc:194
KSSLCertificate::getQDTNotAfter
TQDateTime getQDTNotAfter() const
Get the date that the certificate is valid until.
Definition: ksslcertificate.cc:879
KSSLCertificate::getKDEKey
TQString getKDEKey() const
KDEKey is a concatenation "Subject (MD5)", mostly needed for SMIME.
Definition: ksslcertificate.cc:239
KSSLCertificate::KSSLCertificate
KSSLCertificate(const KSSLCertificate &x)
Copy constructor.
Definition: ksslcertificate.cc:103
KSSLCertificate::replicate
KSSLCertificate * replicate()
Explicitly make a copy of this certificate.
Definition: ksslcertificate.cc:898
KSSLCertificate::getPublicKeyText
TQString getPublicKeyText() const
Get the public key.
Definition: ksslcertificate.cc:331
KSSLCertificate::getIssuer
TQString getIssuer() const
Get the issuer of the certificate (X.509 map).
Definition: ksslcertificate.cc:425
KSSLCertificate::verifyText
static TQString verifyText(KSSLValidation x)
Obtain the localized message that corresponds to a validation result.
Definition: ksslcertificate.cc:917
KSSLCertificate::validate
KSSLValidation validate()
Check if this is a valid certificate.
Definition: ksslcertificate.cc:590
KSSLCertificate::x509V3Extensions
KSSLX509V3 & x509V3Extensions()
Access the X.509v3 parameters.
Definition: ksslcertificate.cc:1087
KSSLCertificate::chain
KSSLCertChain & chain()
Get a reference to the certificate chain.
Definition: ksslcertificate.cc:127
KSSLCertificate::toText
TQString toText()
Convert the certificate to OpenSSL plain text format.
Definition: ksslcertificate.cc:1050
KSSLCertChain::rawChain
void * rawChain()
Read the raw chain in OpenSSL format.
Definition: ksslcertchain.h:127
KSSLCertificate::getMD5DigestFromKDEKey
static TQString getMD5DigestFromKDEKey(const TQString &k)
Aegypten semantics force us to search by MD5Digest only.
Definition: ksslcertificate.cc:244
KSSLCertificate::setCert
bool setCert(TQString &cert)
Re-set the certificate from a base64 string.
Definition: ksslcertificate.cc:1072
KSSLCertificate::getSerialNumber
TQString getSerialNumber() const
Get the serial number of the certificate.
Definition: ksslcertificate.cc:180
KSSLCertificate::toDer
TQByteArray toDer()
Convert the certificate to DER (ASN.1) format.
Definition: ksslcertificate.cc:957
KSSLCertificate
KDE X.509 Certificate.
Definition: ksslcertificate.h:75
KSSLCertificate::toString
TQString toString()
Convert this certificate to a string.
Definition: ksslcertificate.cc:912
KSSLCertificate::revalidate
KSSLValidation revalidate()
Check if this is a valid certificate.
Definition: ksslcertificate.cc:753
KSSLCertificate::getMD5DigestText
TQString getMD5DigestText() const
Get the MD5 digest of the certificate.
Definition: ksslcertificate.cc:257
KSSLCertificate::getEmails
void getEmails(TQStringList &to) const
FIXME: document.
Definition: ksslcertificate.cc:222
KSSLCertificate::subjAltNames
TQStringList subjAltNames() const
The alternate subject name.
Definition: ksslcertificate.cc:1097
KSSLCertificate::getNotAfter
TQString getNotAfter() const
Get the date that the certificate is valid until.
Definition: ksslcertificate.cc:861
KSSLCertChain
KDE Certificate Chain Representation Class.
Definition: ksslcertchain.h:45
KSSLCertificate::toPem
TQByteArray toPem()
Convert the certificate to PEM (base64) format.
Definition: ksslcertificate.cc:975
KSSLCertificate::getQDTNotBefore
TQDateTime getQDTNotBefore() const
Get the date that the certificate becomes valid on.
Definition: ksslcertificate.cc:870
KSSLCertificate::~KSSLCertificate
~KSSLCertificate()
Destroy this X.509 certificate.
Definition: ksslcertificate.cc:118
KSSLCertificate::toNetscape
TQByteArray toNetscape()
Convert the certificate to Netscape format.
Definition: ksslcertificate.cc:1003
KSSLCertificate::KSSLValidation
KSSLValidation
A CA certificate can be validated as Irrelevant when it was not used to sign any other relevant certi...
Definition: ksslcertificate.h:113
KSSLCertificate::getMD5Digest
TQString getMD5Digest() const
Get the MD5 digest of the certificate.
Definition: ksslcertificate.cc:282
KSSLCertificate::getNotBefore
TQString getNotBefore() const
Get the date that the certificate becomes valid on.
Definition: ksslcertificate.cc:852
KSSLX509V3
KDE X509v3 Flag Class.
Definition: ksslx509v3.h:38
KSSLCertificate::isSigner
bool isSigner()
Check if this is a signer certificate.
Definition: ksslcertificate.cc:1092
KSSLCertificate::fromString
static KSSLCertificate * fromString(TQCString cert)
Create an X.509 certificate from a base64 encoded string.
Definition: ksslcertificate.cc:144
KSSLCertificate::isValid
bool isValid()
Check if this is a valid certificate.
Definition: ksslcertificate.cc:565
KSSLCertificate::fromX509
static KSSLCertificate * fromX509(X509 *x5)
Create an X.509 certificate from the internal representation.
Definition: ksslcertificate.cc:132
KSSLCertificate::getSubject
TQString getSubject() const
Get the subject of the certificate (X.509 map).
Definition: ksslcertificate.cc:166
KSSLCertificate::validateVerbose
KSSLValidationList validateVerbose(KSSLPurpose p)
Check if this is a valid certificate.
Definition: ksslcertificate.cc:608
KSSLCertificate::getKeyType
TQString getKeyType() const
Get the key type (RSA, DSA, etc).
Definition: ksslcertificate.cc:305

tdeio/kssl

Skip menu "tdeio/kssl"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

tdeio/kssl

Skip menu "tdeio/kssl"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/kssl by doxygen 1.8.11
This website is maintained by Timothy Pearson.