File indexing completed on 2023-09-24 04:05:18
0001 /* This file is part of the KDE project 0002 * 0003 * Copyright (C) 2001 George Staikos <staikos@kde.org> 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Library General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Library General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this library; see the file COPYING.LIB. If not, write to 0017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "ksslcertchain.h" 0022 0023 #include <ksslconfig.h> 0024 0025 #include "ksslcertificate.h" 0026 0027 // this hack provided by Malte Starostik to avoid glibc/openssl bug 0028 // on some systems 0029 #if KSSL_HAVE_SSL 0030 #define crypt _openssl_crypt 0031 #include <openssl/ssl.h> 0032 #include <openssl/x509.h> 0033 #include <openssl/x509v3.h> 0034 #include <openssl/x509_vfy.h> 0035 #include <openssl/pem.h> 0036 #include <openssl/stack.h> 0037 #include <openssl/safestack.h> 0038 #undef crypt 0039 #endif 0040 0041 #include <kopenssl.h> 0042 #include <QStringList> 0043 0044 class KSSLCertChainPrivate 0045 { 0046 public: 0047 KSSLCertChainPrivate() 0048 { 0049 kossl = KOSSL::self(); 0050 } 0051 0052 ~KSSLCertChainPrivate() 0053 { 0054 } 0055 0056 KOSSL *kossl; 0057 }; 0058 0059 KSSLCertChain::KSSLCertChain() 0060 : d(new KSSLCertChainPrivate) 0061 { 0062 _chain = nullptr; 0063 } 0064 0065 KSSLCertChain::~KSSLCertChain() 0066 { 0067 #if KSSL_HAVE_SSL 0068 if (_chain) { 0069 STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; 0070 0071 for (;;) { 0072 X509 *x5 = reinterpret_cast<X509*>(d->kossl->OPENSSL_sk_pop(reinterpret_cast<STACK *>(x))); 0073 if (!x5) { 0074 break; 0075 } 0076 d->kossl->X509_free(x5); 0077 } 0078 d->kossl->OPENSSL_sk_free(reinterpret_cast<STACK *>(x)); 0079 } 0080 #endif 0081 delete d; 0082 } 0083 0084 bool KSSLCertChain::isValid() 0085 { 0086 return (_chain && depth() > 0); 0087 } 0088 0089 KSSLCertChain *KSSLCertChain::replicate() 0090 { 0091 KSSLCertChain *x = new KSSLCertChain; 0092 QList<KSSLCertificate *> ch = getChain(); 0093 x->setChain(ch); // this will do a deep copy for us 0094 qDeleteAll(ch); 0095 return x; 0096 } 0097 0098 int KSSLCertChain::depth() 0099 { 0100 #if KSSL_HAVE_SSL 0101 return d->kossl->OPENSSL_sk_num(static_cast<STACK *>(_chain)); 0102 #endif 0103 return 0; 0104 } 0105 0106 void *KSSLCertChain::rawChain() 0107 { 0108 return _chain; 0109 } 0110 0111 QList<KSSLCertificate *> KSSLCertChain::getChain() const 0112 { 0113 QList<KSSLCertificate *> cl; 0114 if (!_chain) { 0115 return cl; 0116 } 0117 #if KSSL_HAVE_SSL 0118 STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; 0119 0120 for (int i = 0; i < d->kossl->OPENSSL_sk_num(reinterpret_cast<STACK *>(x)); i++) { 0121 X509 *x5 = reinterpret_cast<X509*>(d->kossl->OPENSSL_sk_value(reinterpret_cast<STACK *>(x), i)); 0122 if (!x5) { 0123 continue; 0124 } 0125 KSSLCertificate *nc = new KSSLCertificate; 0126 nc->setCert(d->kossl->X509_dup(x5)); 0127 cl.append(nc); 0128 } 0129 0130 #endif 0131 return cl; 0132 } 0133 0134 void KSSLCertChain::setChain(const QList<KSSLCertificate *> &chain) 0135 { 0136 #if KSSL_HAVE_SSL 0137 if (_chain) { 0138 STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; 0139 0140 for (;;) { 0141 X509 *x5 = reinterpret_cast<X509*>(d->kossl->OPENSSL_sk_pop(reinterpret_cast<STACK*>(x))); 0142 if (!x5) { 0143 break; 0144 } 0145 d->kossl->X509_free(x5); 0146 } 0147 d->kossl->OPENSSL_sk_free(reinterpret_cast<STACK*>(x)); 0148 _chain = nullptr; 0149 } 0150 0151 if (chain.isEmpty()) { 0152 return; 0153 } 0154 _chain = (void *)d->kossl->OPENSSL_sk_new(nullptr); 0155 foreach (KSSLCertificate *x, chain) { 0156 d->kossl->OPENSSL_sk_push(static_cast<STACK*>(_chain), d->kossl->X509_dup(x->getCert())); 0157 } 0158 0159 #endif 0160 } 0161 0162 void KSSLCertChain::setChain(void *stack_of_x509) 0163 { 0164 #if KSSL_HAVE_SSL 0165 if (_chain) { 0166 STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; 0167 0168 for (;;) { 0169 X509 *x5 = reinterpret_cast<X509 *>(d->kossl->OPENSSL_sk_pop(reinterpret_cast<STACK *>(x))); 0170 if (!x5) { 0171 break; 0172 } 0173 d->kossl->X509_free(x5); 0174 } 0175 d->kossl->OPENSSL_sk_free(reinterpret_cast<STACK *>(x)); 0176 _chain = nullptr; 0177 } 0178 0179 if (!stack_of_x509) { 0180 return; 0181 } 0182 0183 _chain = (void *)d->kossl->OPENSSL_sk_new(nullptr); 0184 STACK_OF(X509) *x = (STACK_OF(X509) *)stack_of_x509; 0185 0186 for (int i = 0; i < d->kossl->OPENSSL_sk_num(reinterpret_cast<STACK *>(x)); i++) { 0187 X509 *x5 = reinterpret_cast<X509*>(d->kossl->OPENSSL_sk_value(reinterpret_cast<STACK *>(x), i)); 0188 if (!x5) { 0189 continue; 0190 } 0191 d->kossl->OPENSSL_sk_push(reinterpret_cast<STACK *>(_chain), d->kossl->X509_dup(x5)); 0192 } 0193 0194 #else 0195 _chain = NULL; 0196 #endif 0197 } 0198 0199 void KSSLCertChain::setCertChain(const QStringList &chain) 0200 { 0201 QList<KSSLCertificate *> cl; 0202 for (QStringList::ConstIterator s = chain.begin(); s != chain.end(); ++s) { 0203 KSSLCertificate *c = KSSLCertificate::fromString((*s).toLocal8Bit()); 0204 if (c) { 0205 cl.append(c); 0206 } 0207 } 0208 setChain(cl); 0209 }