File indexing completed on 2024-12-01 07:27:47
0001 /* 0002 * Copyright (C) 2003-2007 Justin Karneges <justin@affinix.com> 0003 * Copyright (C) 2004,2005 Brad Hards <bradh@frogmouth.net> 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Lesser General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2.1 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 * Lesser General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Lesser General Public 0016 * License along with this library; if not, write to the Free Software 0017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 0018 * 02110-1301 USA 0019 * 0020 */ 0021 0022 #include "qca_securelayer.h" 0023 0024 #include "qca_safeobj.h" 0025 #include "qca_safetimer.h" 0026 #include "qcaprovider.h" 0027 0028 #include <QMetaMethod> 0029 #include <QPointer> 0030 0031 namespace QCA { 0032 0033 Provider::Context *getContext(const QString &type, const QString &provider); 0034 0035 enum ResetMode 0036 { 0037 ResetSession = 0, 0038 ResetSessionAndData = 1, 0039 ResetAll = 2 0040 }; 0041 0042 //---------------------------------------------------------------------------- 0043 // LayerTracker 0044 //---------------------------------------------------------------------------- 0045 class LayerTracker 0046 { 0047 private: 0048 struct Item 0049 { 0050 int plain; 0051 qint64 encoded; 0052 }; 0053 0054 int p; 0055 QList<Item> list; 0056 0057 public: 0058 LayerTracker() 0059 { 0060 p = 0; 0061 } 0062 0063 void reset() 0064 { 0065 p = 0; 0066 list.clear(); 0067 } 0068 0069 void addPlain(int plain) 0070 { 0071 p += plain; 0072 } 0073 0074 void specifyEncoded(int encoded, int plain) 0075 { 0076 // can't specify more bytes than we have 0077 if (plain > p) 0078 plain = p; 0079 p -= plain; 0080 Item i; 0081 i.plain = plain; 0082 i.encoded = encoded; 0083 list += i; 0084 } 0085 0086 int finished(qint64 encoded) 0087 { 0088 int plain = 0; 0089 for (QList<Item>::Iterator it = list.begin(); it != list.end();) { 0090 Item &i = *it; 0091 0092 // not enough? 0093 if (encoded < i.encoded) { 0094 i.encoded -= encoded; 0095 break; 0096 } 0097 0098 encoded -= i.encoded; 0099 plain += i.plain; 0100 it = list.erase(it); 0101 } 0102 return plain; 0103 } 0104 }; 0105 0106 //---------------------------------------------------------------------------- 0107 // SecureLayer 0108 //---------------------------------------------------------------------------- 0109 SecureLayer::SecureLayer(QObject *parent) 0110 : QObject(parent) 0111 { 0112 } 0113 0114 bool SecureLayer::isClosable() const 0115 { 0116 return false; 0117 } 0118 0119 void SecureLayer::close() 0120 { 0121 } 0122 0123 QByteArray SecureLayer::readUnprocessed() 0124 { 0125 return QByteArray(); 0126 } 0127 0128 //---------------------------------------------------------------------------- 0129 // TLSSession 0130 //---------------------------------------------------------------------------- 0131 TLSSession::TLSSession() 0132 { 0133 } 0134 0135 TLSSession::TLSSession(const TLSSession &from) 0136 : Algorithm(from) 0137 { 0138 } 0139 0140 TLSSession::~TLSSession() 0141 { 0142 } 0143 0144 TLSSession &TLSSession::operator=(const TLSSession &from) 0145 { 0146 Algorithm::operator=(from); 0147 return *this; 0148 } 0149 0150 bool TLSSession::isNull() const 0151 { 0152 return (!context() ? true : false); 0153 } 0154 0155 //---------------------------------------------------------------------------- 0156 // TLS 0157 //---------------------------------------------------------------------------- 0158 class TLS::Private : public QObject 0159 { 0160 Q_OBJECT 0161 public: 0162 enum 0163 { 0164 OpStart, 0165 OpUpdate 0166 }; 0167 0168 enum State 0169 { 0170 Inactive, 0171 Initializing, 0172 Handshaking, 0173 Connected, 0174 Closing 0175 }; 0176 0177 class Action 0178 { 0179 public: 0180 enum Type 0181 { 0182 ReadyRead, 0183 ReadyReadOutgoing, 0184 Handshaken, 0185 Close, 0186 CheckPeerCertificate, 0187 CertificateRequested, 0188 HostNameReceived 0189 }; 0190 0191 int type; 0192 0193 Action(int _type) 0194 : type(_type) 0195 { 0196 } 0197 }; 0198 0199 TLS *q; 0200 TLSContext *c; 0201 TLS::Mode mode; 0202 0203 // signal connected flags 0204 bool connect_hostNameReceived; 0205 bool connect_certificateRequested; 0206 bool connect_peerCertificateAvailable; 0207 bool connect_handshaken; 0208 0209 // persistent settings (survives ResetSessionAndData) 0210 CertificateChain localCert; 0211 PrivateKey localKey; 0212 CertificateCollection trusted; 0213 bool con_ssfMode; 0214 int con_minSSF, con_maxSSF; 0215 QStringList con_cipherSuites; 0216 bool tryCompress; 0217 int packet_mtu; 0218 QList<CertificateInfoOrdered> issuerList; 0219 TLSSession session; 0220 0221 // session 0222 State state; 0223 bool blocked; 0224 bool server; 0225 QString host; 0226 TLSContext::SessionInfo sessionInfo; 0227 SafeTimer actionTrigger; 0228 int op; 0229 QList<Action> actionQueue; 0230 bool need_update; 0231 bool maybe_input; 0232 bool emitted_hostNameReceived; 0233 bool emitted_certificateRequested; 0234 bool emitted_peerCertificateAvailable; 0235 0236 // data (survives ResetSession) 0237 CertificateChain peerCert; 0238 Validity peerValidity; 0239 bool hostMismatch; 0240 Error errorCode; 0241 0242 // stream i/o 0243 QByteArray in, out; 0244 QByteArray to_net, from_net; 0245 QByteArray unprocessed; 0246 int out_pending; 0247 int to_net_encoded; 0248 LayerTracker layer; 0249 0250 // datagram i/o 0251 QList<QByteArray> packet_in, packet_out; 0252 QList<QByteArray> packet_to_net, packet_from_net; 0253 int packet_out_pending; // packet count 0254 QList<int> packet_to_net_encoded; 0255 0256 Private(TLS *_q, TLS::Mode _mode) 0257 : QObject(_q) 0258 , q(_q) 0259 , mode(_mode) 0260 , actionTrigger(this) 0261 { 0262 // c is 0 during initial reset, so we don't redundantly reset it 0263 c = nullptr; 0264 connect_hostNameReceived = false; 0265 connect_certificateRequested = false; 0266 connect_peerCertificateAvailable = false; 0267 connect_handshaken = false; 0268 server = false; 0269 0270 connect(&actionTrigger, &SafeTimer::timeout, this, &Private::doNextAction); 0271 actionTrigger.setSingleShot(true); 0272 0273 reset(ResetAll); 0274 0275 c = static_cast<TLSContext *>(q->context()); 0276 0277 // parent the context to us, so that moveToThread works 0278 c->setParent(this); 0279 0280 connect(c, &TLSContext::resultsReady, this, &Private::tls_resultsReady); 0281 connect(c, &TLSContext::dtlsTimeout, this, &Private::tls_dtlsTimeout); 0282 } 0283 0284 ~Private() override 0285 { 0286 // context is owned by Algorithm, unparent so we don't double-delete 0287 c->setParent(nullptr); 0288 } 0289 0290 void reset(ResetMode mode) 0291 { 0292 if (c) 0293 c->reset(); 0294 0295 // if we reset while in client mode, then clear this list 0296 // (it should only persist when used for server mode) 0297 if (!server) 0298 issuerList.clear(); 0299 0300 state = Inactive; 0301 blocked = false; 0302 server = false; 0303 host = QString(); 0304 sessionInfo = TLSContext::SessionInfo(); 0305 actionTrigger.stop(); 0306 op = -1; 0307 actionQueue.clear(); 0308 need_update = false; 0309 maybe_input = false; 0310 emitted_hostNameReceived = false; 0311 emitted_certificateRequested = false; 0312 emitted_peerCertificateAvailable = false; 0313 0314 out.clear(); 0315 out_pending = 0; 0316 packet_out.clear(); 0317 packet_out_pending = 0; 0318 0319 if (mode >= ResetSessionAndData) { 0320 peerCert = CertificateChain(); 0321 peerValidity = ErrorValidityUnknown; 0322 hostMismatch = false; 0323 errorCode = (TLS::Error)-1; 0324 0325 in.clear(); 0326 to_net.clear(); 0327 from_net.clear(); 0328 unprocessed.clear(); 0329 to_net_encoded = 0; 0330 layer.reset(); 0331 0332 packet_in.clear(); 0333 packet_to_net.clear(); 0334 packet_from_net.clear(); 0335 packet_to_net_encoded.clear(); 0336 } 0337 0338 if (mode >= ResetAll) { 0339 localCert = CertificateChain(); 0340 localKey = PrivateKey(); 0341 trusted = CertificateCollection(); 0342 con_ssfMode = true; 0343 con_minSSF = 128; 0344 con_maxSSF = -1; 0345 con_cipherSuites = QStringList(); 0346 tryCompress = false; 0347 packet_mtu = -1; 0348 issuerList.clear(); 0349 session = TLSSession(); 0350 } 0351 } 0352 0353 void start(bool serverMode) 0354 { 0355 state = Initializing; 0356 server = serverMode; 0357 0358 c->setup(serverMode, host, tryCompress); 0359 0360 if (con_ssfMode) 0361 c->setConstraints(con_minSSF, con_maxSSF); 0362 else 0363 c->setConstraints(con_cipherSuites); 0364 0365 c->setCertificate(localCert, localKey); 0366 c->setTrustedCertificates(trusted); 0367 if (serverMode) 0368 c->setIssuerList(issuerList); 0369 if (!session.isNull()) { 0370 TLSSessionContext *sc = static_cast<TLSSessionContext *>(session.context()); 0371 c->setSessionId(*sc); 0372 } 0373 c->setMTU(packet_mtu); 0374 0375 QCA_logTextMessage(QStringLiteral("tls[%1]: c->start()").arg(q->objectName()), Logger::Information); 0376 op = OpStart; 0377 c->start(); 0378 } 0379 0380 void close() 0381 { 0382 QCA_logTextMessage(QStringLiteral("tls[%1]: close").arg(q->objectName()), Logger::Information); 0383 0384 if (state != Connected) 0385 return; 0386 0387 state = Closing; 0388 c->shutdown(); 0389 } 0390 0391 void continueAfterStep() 0392 { 0393 QCA_logTextMessage(QStringLiteral("tls[%1]: continueAfterStep").arg(q->objectName()), Logger::Information); 0394 0395 if (!blocked) 0396 return; 0397 0398 blocked = false; 0399 update(); 0400 } 0401 0402 void processNextAction() 0403 { 0404 if (actionQueue.isEmpty()) { 0405 if (need_update) { 0406 QCA_logTextMessage(QStringLiteral("tls[%1]: need_update").arg(q->objectName()), Logger::Information); 0407 update(); 0408 } 0409 return; 0410 } 0411 0412 const Action a = actionQueue.takeFirst(); 0413 0414 // set up for the next one, if necessary 0415 if (!actionQueue.isEmpty() || need_update) { 0416 if (!actionTrigger.isActive()) 0417 actionTrigger.start(); 0418 } 0419 0420 if (a.type == Action::ReadyRead) { 0421 emit q->readyRead(); 0422 } else if (a.type == Action::ReadyReadOutgoing) { 0423 emit q->readyReadOutgoing(); 0424 } else if (a.type == Action::Handshaken) { 0425 state = Connected; 0426 0427 // write any app data waiting during handshake 0428 if (!out.isEmpty()) { 0429 need_update = true; 0430 if (!actionTrigger.isActive()) 0431 actionTrigger.start(); 0432 } 0433 0434 QCA_logTextMessage(QStringLiteral("tls[%1]: handshaken").arg(q->objectName()), Logger::Information); 0435 0436 if (connect_handshaken) { 0437 blocked = true; 0438 emit q->handshaken(); 0439 } 0440 } else if (a.type == Action::Close) { 0441 unprocessed = c->unprocessed(); 0442 reset(ResetSession); 0443 emit q->closed(); 0444 } else if (a.type == Action::CheckPeerCertificate) { 0445 peerCert = c->peerCertificateChain(); 0446 if (!peerCert.isEmpty()) { 0447 peerValidity = c->peerCertificateValidity(); 0448 if (peerValidity == ValidityGood && !host.isEmpty() && !peerCert.primary().matchesHostName(host)) 0449 hostMismatch = true; 0450 } 0451 0452 if (connect_peerCertificateAvailable) { 0453 blocked = true; 0454 emitted_peerCertificateAvailable = true; 0455 emit q->peerCertificateAvailable(); 0456 } 0457 } else if (a.type == Action::CertificateRequested) { 0458 issuerList = c->issuerList(); 0459 if (connect_certificateRequested) { 0460 blocked = true; 0461 emitted_certificateRequested = true; 0462 emit q->certificateRequested(); 0463 } 0464 } else if (a.type == Action::HostNameReceived) { 0465 if (connect_hostNameReceived) { 0466 blocked = true; 0467 emitted_hostNameReceived = true; 0468 emit q->hostNameReceived(); 0469 } 0470 } 0471 } 0472 0473 void update() 0474 { 0475 QCA_logTextMessage(QStringLiteral("tls[%1]: update").arg(q->objectName()), Logger::Information); 0476 0477 if (blocked) { 0478 QCA_logTextMessage(QStringLiteral("tls[%1]: ignoring update while blocked").arg(q->objectName()), 0479 Logger::Information); 0480 return; 0481 } 0482 0483 if (!actionQueue.isEmpty()) { 0484 QCA_logTextMessage(QStringLiteral("tls[%1]: ignoring update while processing actions").arg(q->objectName()), 0485 Logger::Information); 0486 need_update = true; 0487 return; 0488 } 0489 0490 // only allow one operation at a time 0491 if (op != -1) { 0492 QCA_logTextMessage(QStringLiteral("tls[%1]: ignoring update while operation active").arg(q->objectName()), 0493 Logger::Information); 0494 need_update = true; 0495 return; 0496 } 0497 0498 need_update = false; 0499 0500 QByteArray arg_from_net, arg_from_app; 0501 0502 if (state == Handshaking) { 0503 // during handshake, only send from_net (no app data) 0504 0505 if (mode == TLS::Stream) { 0506 arg_from_net = from_net; 0507 from_net.clear(); 0508 } else { 0509 // note: there may not be a packet 0510 if (!packet_from_net.isEmpty()) 0511 arg_from_net = packet_from_net.takeFirst(); 0512 } 0513 } else { 0514 if (mode == TLS::Stream) { 0515 if (!from_net.isEmpty()) { 0516 arg_from_net = from_net; 0517 from_net.clear(); 0518 } 0519 0520 if (!out.isEmpty()) { 0521 out_pending += out.size(); 0522 arg_from_app = out; 0523 out.clear(); 0524 } 0525 } else { 0526 if (!packet_from_net.isEmpty()) 0527 arg_from_net = packet_from_net.takeFirst(); 0528 0529 if (!packet_out.isEmpty()) { 0530 arg_from_app = packet_out.takeFirst(); 0531 ++packet_out_pending; 0532 } 0533 } 0534 } 0535 0536 if (arg_from_net.isEmpty() && arg_from_app.isEmpty() && !maybe_input) { 0537 QCA_logTextMessage( 0538 QStringLiteral("tls[%1]: ignoring update: no output and no expected input").arg(q->objectName()), 0539 Logger::Information); 0540 return; 0541 } 0542 0543 // clear this flag 0544 maybe_input = false; 0545 0546 QCA_logTextMessage(QStringLiteral("tls[%1]: c->update").arg(q->objectName()), Logger::Information); 0547 op = OpUpdate; 0548 c->update(arg_from_net, arg_from_app); 0549 } 0550 0551 void start_finished() 0552 { 0553 const bool ok = c->result() == TLSContext::Success; 0554 if (!ok) { 0555 reset(ResetSession); 0556 errorCode = TLS::ErrorInit; 0557 emit q->error(); 0558 return; 0559 } 0560 0561 state = Handshaking; 0562 0563 // immediately update so we can get the first packet to send 0564 maybe_input = true; 0565 update(); 0566 } 0567 0568 void update_finished() 0569 { 0570 const TLSContext::Result r = c->result(); 0571 if (r == TLSContext::Error) { 0572 if (state == Handshaking || state == Closing) { 0573 reset(ResetSession); 0574 errorCode = ErrorHandshake; 0575 } else { 0576 reset(ResetSession); 0577 errorCode = ErrorCrypt; 0578 } 0579 0580 emit q->error(); 0581 return; 0582 } 0583 0584 const QByteArray c_to_net = c->to_net(); 0585 if (!c_to_net.isEmpty()) { 0586 QCA_logTextMessage( 0587 QStringLiteral("tls[%1]: to_net %2").arg(q->objectName(), QString::number(c_to_net.size())), 0588 Logger::Information); 0589 } 0590 0591 if (state == Closing) { 0592 if (mode == TLS::Stream) 0593 to_net += c_to_net; 0594 else 0595 packet_to_net += c_to_net; 0596 0597 if (!c_to_net.isEmpty()) 0598 actionQueue += Action(Action::ReadyReadOutgoing); 0599 0600 if (r == TLSContext::Success) 0601 actionQueue += Action(Action::Close); 0602 0603 processNextAction(); 0604 return; 0605 } else if (state == Handshaking) { 0606 if (mode == TLS::Stream) 0607 to_net += c_to_net; 0608 else 0609 packet_to_net += c_to_net; 0610 0611 if (!c_to_net.isEmpty()) 0612 actionQueue += Action(Action::ReadyReadOutgoing); 0613 0614 bool clientHello = false; 0615 bool serverHello = false; 0616 if (server) 0617 clientHello = c->clientHelloReceived(); 0618 else 0619 serverHello = c->serverHelloReceived(); 0620 0621 // client specifies a host? 0622 if (!emitted_hostNameReceived && clientHello) { 0623 host = c->hostName(); 0624 if (!host.isEmpty()) 0625 actionQueue += Action(Action::HostNameReceived); 0626 } 0627 0628 // successful handshake or server hello means there might be a peer cert 0629 if (!emitted_peerCertificateAvailable && (r == TLSContext::Success || (!server && serverHello))) 0630 actionQueue += Action(Action::CheckPeerCertificate); 0631 0632 // server requests a cert from us? 0633 if (!emitted_certificateRequested && (serverHello && c->certificateRequested())) 0634 actionQueue += Action(Action::CertificateRequested); 0635 0636 if (r == TLSContext::Success) { 0637 sessionInfo = c->sessionInfo(); 0638 if (sessionInfo.id) { 0639 TLSSessionContext *sc = static_cast<TLSSessionContext *>(sessionInfo.id->clone()); 0640 session.change(sc); 0641 } 0642 0643 actionQueue += Action(Action::Handshaken); 0644 } 0645 0646 processNextAction(); 0647 return; 0648 } else // Connected 0649 { 0650 const QByteArray c_to_app = c->to_app(); 0651 if (!c_to_app.isEmpty()) { 0652 QCA_logTextMessage( 0653 QStringLiteral("tls[%1]: to_app %2").arg(q->objectName(), QString::number(c_to_app.size())), 0654 Logger::Information); 0655 } 0656 0657 const bool eof = c->eof(); 0658 int enc = -1; 0659 if (!c_to_net.isEmpty()) 0660 enc = c->encoded(); 0661 0662 bool io_pending = false; 0663 if (mode == TLS::Stream) { 0664 if (!c_to_net.isEmpty()) 0665 out_pending -= enc; 0666 0667 if (out_pending > 0) { 0668 maybe_input = true; 0669 io_pending = true; 0670 } 0671 0672 if (!out.isEmpty()) 0673 io_pending = true; 0674 } else { 0675 if (!c_to_net.isEmpty()) 0676 --packet_out_pending; 0677 0678 if (packet_out_pending > 0) { 0679 maybe_input = true; 0680 io_pending = true; 0681 } 0682 0683 if (!packet_out.isEmpty()) 0684 io_pending = true; 0685 } 0686 0687 if (mode == TLS::Stream) { 0688 to_net += c_to_net; 0689 in += c_to_app; 0690 to_net_encoded += enc; 0691 } else { 0692 packet_to_net += c_to_net; 0693 packet_in += c_to_app; 0694 } 0695 0696 if (!c_to_net.isEmpty()) 0697 actionQueue += Action(Action::ReadyReadOutgoing); 0698 0699 if (!c_to_app.isEmpty()) 0700 actionQueue += Action(Action::ReadyRead); 0701 0702 if (eof) { 0703 close(); 0704 maybe_input = true; 0705 } 0706 0707 if (eof || io_pending) { 0708 QCA_logTextMessage(QStringLiteral("tls[%1]: eof || io_pending").arg(q->objectName()), 0709 Logger::Information); 0710 update(); 0711 } 0712 0713 processNextAction(); 0714 return; 0715 } 0716 } 0717 0718 private Q_SLOTS: 0719 void tls_resultsReady() 0720 { 0721 QCA_logTextMessage(QStringLiteral("tls[%1]: c->resultsReady()").arg(q->objectName()), Logger::Information); 0722 0723 Q_ASSERT(op != -1); 0724 0725 int last_op = op; 0726 op = -1; 0727 0728 if (last_op == OpStart) 0729 start_finished(); 0730 else // OpUpdate 0731 update_finished(); 0732 } 0733 0734 void tls_dtlsTimeout() 0735 { 0736 QCA_logTextMessage(QStringLiteral("tls[%1]: c->dtlsTimeout()").arg(q->objectName()), Logger::Information); 0737 0738 maybe_input = true; 0739 update(); 0740 } 0741 0742 void doNextAction() 0743 { 0744 processNextAction(); 0745 } 0746 }; 0747 0748 TLS::TLS(QObject *parent, const QString &provider) 0749 : SecureLayer(parent) 0750 , Algorithm(QStringLiteral("tls"), provider) 0751 { 0752 d = new Private(this, TLS::Stream); 0753 } 0754 0755 TLS::TLS(Mode mode, QObject *parent, const QString &provider) 0756 : SecureLayer(parent) 0757 , Algorithm(mode == Stream ? QStringLiteral("tls") : QStringLiteral("dtls"), provider) 0758 { 0759 d = new Private(this, mode); 0760 } 0761 0762 TLS::~TLS() 0763 { 0764 delete d; 0765 } 0766 0767 void TLS::reset() 0768 { 0769 d->reset(ResetAll); 0770 } 0771 0772 QStringList TLS::supportedCipherSuites( 0773 const Version &version) const // clazy:exclude=function-args-by-value TODO make it remove the & when we break ABI 0774 { 0775 return d->c->supportedCipherSuites(version); 0776 } 0777 0778 void TLS::setCertificate(const CertificateChain &cert, const PrivateKey &key) 0779 { 0780 d->localCert = cert; 0781 d->localKey = key; 0782 if (d->state != TLS::Private::Inactive) 0783 d->c->setCertificate(cert, key); 0784 } 0785 0786 void TLS::setCertificate(const KeyBundle &kb) 0787 { 0788 setCertificate(kb.certificateChain(), kb.privateKey()); 0789 } 0790 0791 CertificateCollection TLS::trustedCertificates() const 0792 { 0793 return d->trusted; 0794 } 0795 0796 void TLS::setTrustedCertificates(const CertificateCollection &trusted) 0797 { 0798 d->trusted = trusted; 0799 if (d->state != TLS::Private::Inactive) 0800 d->c->setTrustedCertificates(trusted); 0801 } 0802 0803 void TLS::setConstraints(SecurityLevel s) 0804 { 0805 int min = 128; 0806 switch (s) { 0807 case SL_None: 0808 min = 0; 0809 break; 0810 case SL_Integrity: 0811 min = 1; 0812 break; 0813 case SL_Export: 0814 min = 40; 0815 break; 0816 case SL_Baseline: 0817 min = 128; 0818 break; 0819 case SL_High: 0820 min = 129; 0821 break; 0822 case SL_Highest: 0823 min = qMax(129, d->c->maxSSF()); 0824 break; 0825 } 0826 0827 d->con_ssfMode = true; 0828 d->con_minSSF = min; 0829 d->con_maxSSF = -1; 0830 0831 if (d->state != TLS::Private::Inactive) 0832 d->c->setConstraints(d->con_minSSF, d->con_maxSSF); 0833 } 0834 0835 void TLS::setConstraints(int minSSF, int maxSSF) 0836 { 0837 d->con_ssfMode = true; 0838 d->con_minSSF = minSSF; 0839 d->con_maxSSF = maxSSF; 0840 0841 if (d->state != TLS::Private::Inactive) 0842 d->c->setConstraints(d->con_minSSF, d->con_maxSSF); 0843 } 0844 0845 void TLS::setConstraints(const QStringList &cipherSuiteList) 0846 { 0847 d->con_ssfMode = false; 0848 d->con_cipherSuites = cipherSuiteList; 0849 0850 if (d->state != TLS::Private::Inactive) 0851 d->c->setConstraints(d->con_cipherSuites); 0852 } 0853 0854 QList<CertificateInfoOrdered> TLS::issuerList() const 0855 { 0856 return d->issuerList; 0857 } 0858 0859 void TLS::setIssuerList(const QList<CertificateInfoOrdered> &issuers) 0860 { 0861 d->issuerList = issuers; 0862 if (d->state != TLS::Private::Inactive) 0863 d->c->setIssuerList(issuers); 0864 } 0865 0866 void TLS::setSession(const TLSSession &session) 0867 { 0868 d->session = session; 0869 } 0870 0871 bool TLS::canCompress() const 0872 { 0873 return d->c->canCompress(); 0874 } 0875 0876 bool TLS::canSetHostName() const 0877 { 0878 return d->c->canSetHostName(); 0879 } 0880 0881 bool TLS::compressionEnabled() const 0882 { 0883 return d->tryCompress; 0884 } 0885 0886 void TLS::setCompressionEnabled(bool b) 0887 { 0888 d->tryCompress = b; 0889 } 0890 0891 void TLS::startClient(const QString &host) 0892 { 0893 d->reset(ResetSessionAndData); 0894 d->host = host; 0895 d->issuerList.clear(); 0896 0897 // client mode 0898 d->start(false); 0899 } 0900 0901 void TLS::startServer() 0902 { 0903 d->reset(ResetSessionAndData); 0904 0905 // server mode 0906 d->start(true); 0907 } 0908 0909 void TLS::continueAfterStep() 0910 { 0911 d->continueAfterStep(); 0912 } 0913 0914 bool TLS::isHandshaken() const 0915 { 0916 if (d->state == TLS::Private::Connected || d->state == TLS::Private::Closing) 0917 return true; 0918 else 0919 return false; 0920 } 0921 0922 bool TLS::isCompressed() const 0923 { 0924 return d->sessionInfo.isCompressed; 0925 } 0926 0927 TLS::Version TLS::version() const 0928 { 0929 return d->sessionInfo.version; 0930 } 0931 0932 QString TLS::cipherSuite() const 0933 { 0934 return d->sessionInfo.cipherSuite; 0935 } 0936 0937 int TLS::cipherBits() const 0938 { 0939 return d->sessionInfo.cipherBits; 0940 } 0941 0942 int TLS::cipherMaxBits() const 0943 { 0944 return d->sessionInfo.cipherMaxBits; 0945 } 0946 0947 TLSSession TLS::session() const 0948 { 0949 return d->session; 0950 } 0951 0952 TLS::Error TLS::errorCode() const 0953 { 0954 return d->errorCode; 0955 } 0956 0957 TLS::IdentityResult TLS::peerIdentityResult() const 0958 { 0959 if (d->peerCert.isEmpty()) 0960 return NoCertificate; 0961 0962 if (d->peerValidity != ValidityGood) 0963 return InvalidCertificate; 0964 0965 if (d->hostMismatch) 0966 return HostMismatch; 0967 0968 return Valid; 0969 } 0970 0971 Validity TLS::peerCertificateValidity() const 0972 { 0973 return d->peerValidity; 0974 } 0975 0976 CertificateChain TLS::localCertificateChain() const 0977 { 0978 return d->localCert; 0979 } 0980 0981 PrivateKey TLS::localPrivateKey() const 0982 { 0983 return d->localKey; 0984 } 0985 0986 CertificateChain TLS::peerCertificateChain() const 0987 { 0988 return d->peerCert; 0989 } 0990 0991 bool TLS::isClosable() const 0992 { 0993 return true; 0994 } 0995 0996 int TLS::bytesAvailable() const 0997 { 0998 if (d->mode == Stream) 0999 return d->in.size(); 1000 else 1001 return 0; 1002 } 1003 1004 int TLS::bytesOutgoingAvailable() const 1005 { 1006 if (d->mode == Stream) 1007 return d->to_net.size(); 1008 else 1009 return 0; 1010 } 1011 1012 void TLS::close() 1013 { 1014 d->close(); 1015 d->update(); 1016 } 1017 1018 void TLS::write(const QByteArray &a) 1019 { 1020 if (d->mode == Stream) { 1021 d->out.append(a); 1022 d->layer.addPlain(a.size()); 1023 } else 1024 d->packet_out.append(a); 1025 QCA_logTextMessage(QStringLiteral("tls[%1]: write").arg(objectName()), Logger::Information); 1026 d->update(); 1027 } 1028 1029 QByteArray TLS::read() 1030 { 1031 if (d->mode == Stream) { 1032 const QByteArray a = d->in; 1033 d->in.clear(); 1034 return a; 1035 } else { 1036 if (!d->packet_in.isEmpty()) 1037 return d->packet_in.takeFirst(); 1038 else 1039 return QByteArray(); 1040 } 1041 } 1042 1043 void TLS::writeIncoming(const QByteArray &a) 1044 { 1045 if (d->mode == Stream) 1046 d->from_net.append(a); 1047 else 1048 d->packet_from_net.append(a); 1049 QCA_logTextMessage(QStringLiteral("tls[%1]: writeIncoming %2").arg(objectName(), QString::number(a.size())), 1050 Logger::Information); 1051 d->update(); 1052 } 1053 1054 QByteArray TLS::readOutgoing(int *plainBytes) 1055 { 1056 if (d->mode == Stream) { 1057 const QByteArray a = d->to_net; 1058 d->to_net.clear(); 1059 if (plainBytes) 1060 *plainBytes = d->to_net_encoded; 1061 d->layer.specifyEncoded(a.size(), d->to_net_encoded); 1062 d->to_net_encoded = 0; 1063 return a; 1064 } else { 1065 if (!d->packet_to_net.isEmpty()) { 1066 const QByteArray a = d->packet_to_net.takeFirst(); 1067 const int x = d->packet_to_net_encoded.takeFirst(); 1068 if (plainBytes) 1069 *plainBytes = x; 1070 return a; 1071 } else { 1072 if (plainBytes) 1073 *plainBytes = 0; 1074 return QByteArray(); 1075 } 1076 } 1077 } 1078 1079 QByteArray TLS::readUnprocessed() 1080 { 1081 if (d->mode == Stream) { 1082 const QByteArray a = d->unprocessed; 1083 d->unprocessed.clear(); 1084 return a; 1085 } else 1086 return QByteArray(); 1087 } 1088 1089 int TLS::convertBytesWritten(qint64 bytes) 1090 { 1091 return d->layer.finished(bytes); 1092 } 1093 1094 int TLS::packetsAvailable() const 1095 { 1096 return d->packet_in.count(); 1097 } 1098 1099 int TLS::packetsOutgoingAvailable() const 1100 { 1101 return d->packet_to_net.count(); 1102 } 1103 1104 int TLS::packetMTU() const 1105 { 1106 return d->packet_mtu; 1107 } 1108 1109 void TLS::setPacketMTU(int size) const 1110 { 1111 d->packet_mtu = size; 1112 if (d->state != TLS::Private::Inactive) 1113 d->c->setMTU(size); 1114 } 1115 1116 void TLS::connectNotify(const QMetaMethod &signal) 1117 { 1118 if (signal == QMetaMethod::fromSignal(&TLS::hostNameReceived)) 1119 d->connect_hostNameReceived = true; 1120 else if (signal == QMetaMethod::fromSignal(&TLS::certificateRequested)) 1121 d->connect_certificateRequested = true; 1122 else if (signal == QMetaMethod::fromSignal(&TLS::peerCertificateAvailable)) 1123 d->connect_peerCertificateAvailable = true; 1124 else if (signal == QMetaMethod::fromSignal(&TLS::handshaken)) 1125 d->connect_handshaken = true; 1126 } 1127 1128 void TLS::disconnectNotify(const QMetaMethod &signal) 1129 { 1130 if (signal == QMetaMethod::fromSignal(&TLS::hostNameReceived)) 1131 d->connect_hostNameReceived = false; 1132 else if (signal == QMetaMethod::fromSignal(&TLS::certificateRequested)) 1133 d->connect_certificateRequested = false; 1134 else if (signal == QMetaMethod::fromSignal(&TLS::peerCertificateAvailable)) 1135 d->connect_peerCertificateAvailable = false; 1136 else if (signal == QMetaMethod::fromSignal(&TLS::handshaken)) 1137 d->connect_handshaken = false; 1138 } 1139 1140 //---------------------------------------------------------------------------- 1141 // SASL::Params 1142 //---------------------------------------------------------------------------- 1143 class SASL::Params::Private 1144 { 1145 public: 1146 bool needUsername, canSendAuthzid, needPassword, canSendRealm; 1147 }; 1148 1149 SASL::Params::Params() 1150 : d(new Private) 1151 { 1152 } 1153 1154 SASL::Params::Params(bool user, bool authzid, bool pass, bool realm) 1155 : d(new Private) 1156 { 1157 d->needUsername = user; 1158 d->canSendAuthzid = authzid; 1159 d->needPassword = pass; 1160 d->canSendRealm = realm; 1161 } 1162 1163 SASL::Params::Params(const SASL::Params &from) 1164 : d(new Private(*from.d)) 1165 { 1166 } 1167 1168 SASL::Params::~Params() 1169 { 1170 delete d; 1171 } 1172 1173 SASL::Params &SASL::Params::operator=(const SASL::Params &from) 1174 { 1175 *d = *from.d; 1176 return *this; 1177 } 1178 1179 bool SASL::Params::needUsername() const 1180 { 1181 return d->needUsername; 1182 } 1183 1184 bool SASL::Params::canSendAuthzid() const 1185 { 1186 return d->canSendAuthzid; 1187 } 1188 1189 bool SASL::Params::needPassword() const 1190 { 1191 return d->needPassword; 1192 } 1193 1194 bool SASL::Params::canSendRealm() const 1195 { 1196 return d->canSendRealm; 1197 } 1198 1199 //---------------------------------------------------------------------------- 1200 // SASL 1201 //---------------------------------------------------------------------------- 1202 /* 1203 These don't map, but I don't think it matters much.. 1204 SASL_TRYAGAIN (-8) transient failure (e.g., weak key) 1205 SASL_BADMAC (-9) integrity check failed 1206 -- client only codes -- 1207 SASL_WRONGMECH (-11) mechanism doesn't support requested feature 1208 SASL_NEWSECRET (-12) new secret needed 1209 -- server only codes -- 1210 SASL_TRANS (-17) One time use of a plaintext password will 1211 enable requested mechanism for user 1212 SASL_PWLOCK (-21) password locked 1213 SASL_NOCHANGE (-22) requested change was not needed 1214 */ 1215 1216 class SASL::Private : public QObject 1217 { 1218 Q_OBJECT 1219 public: 1220 enum 1221 { 1222 OpStart, 1223 OpServerFirstStep, 1224 OpNextStep, 1225 OpTryAgain, 1226 OpUpdate 1227 }; 1228 1229 class Action 1230 { 1231 public: 1232 enum Type 1233 { 1234 ClientStarted, 1235 NextStep, 1236 Authenticated, 1237 ReadyRead, 1238 ReadyReadOutgoing 1239 }; 1240 1241 int type; 1242 QByteArray stepData; 1243 bool haveInit; 1244 1245 Action(int _type) 1246 : type(_type) 1247 { 1248 } 1249 1250 Action(int _type, const QByteArray &_stepData) 1251 : type(_type) 1252 , stepData(_stepData) 1253 { 1254 } 1255 1256 Action(int _type, bool _haveInit, const QByteArray &_stepData) 1257 : type(_type) 1258 , stepData(_stepData) 1259 , haveInit(_haveInit) 1260 { 1261 } 1262 }; 1263 1264 SASL *q; 1265 SASLContext *c; 1266 1267 // persistent settings (survives ResetSessionAndData) 1268 AuthFlags auth_flags; 1269 int ssfmin, ssfmax; 1270 QString ext_authid; 1271 int ext_ssf; 1272 bool localSet, remoteSet; 1273 SASLContext::HostPort local, remote; 1274 bool set_username, set_authzid, set_password, set_realm; 1275 QString username, authzid, realm; 1276 SecureArray password; 1277 1278 // session 1279 bool server; 1280 QStringList mechlist; 1281 QString server_realm; 1282 bool allowClientSendFirst; 1283 bool disableServerSendLast; 1284 SafeTimer actionTrigger; 1285 int op; 1286 QList<Action> actionQueue; 1287 bool need_update; 1288 bool first; 1289 bool authed; 1290 1291 // data (survives ResetSession) 1292 QString mech; // selected mech 1293 Error errorCode; 1294 1295 // stream i/o 1296 QByteArray in, out; 1297 QByteArray to_net, from_net; 1298 int out_pending; 1299 int to_net_encoded; 1300 LayerTracker layer; 1301 1302 Private(SASL *_q) 1303 : QObject(_q) 1304 , q(_q) 1305 , actionTrigger(this) 1306 { 1307 c = nullptr; 1308 set_username = false; 1309 set_authzid = false; 1310 set_password = false; 1311 set_realm = false; 1312 1313 connect(&actionTrigger, &SafeTimer::timeout, this, &Private::doNextAction); 1314 actionTrigger.setSingleShot(true); 1315 1316 reset(ResetAll); 1317 1318 c = static_cast<SASLContext *>(q->context()); 1319 1320 // parent the context to us, so that moveToThread works 1321 c->setParent(this); 1322 1323 connect(c, &SASLContext::resultsReady, this, &Private::sasl_resultsReady); 1324 } 1325 1326 ~Private() override 1327 { 1328 // context is owned by Algorithm, unparent so we don't double-delete 1329 c->setParent(nullptr); 1330 } 1331 1332 void reset(ResetMode mode) 1333 { 1334 if (c) 1335 c->reset(); 1336 1337 server = false; 1338 mechlist.clear(); 1339 server_realm = QString(); 1340 allowClientSendFirst = false; 1341 disableServerSendLast = true; 1342 actionTrigger.stop(); 1343 op = -1; 1344 actionQueue.clear(); 1345 need_update = false; 1346 first = false; 1347 authed = false; 1348 1349 out.clear(); 1350 out_pending = 0; 1351 1352 if (mode >= ResetSessionAndData) { 1353 mech = QString(); 1354 errorCode = (SASL::Error)-1; 1355 1356 in.clear(); 1357 to_net.clear(); 1358 from_net.clear(); 1359 to_net_encoded = 0; 1360 layer.reset(); 1361 } 1362 1363 if (mode >= ResetAll) { 1364 auth_flags = SASL::AuthFlagsNone; 1365 ssfmin = 0; 1366 ssfmax = 0; 1367 ext_authid = QString(); 1368 ext_ssf = 0; 1369 localSet = false; 1370 remoteSet = false; 1371 local = SASLContext::HostPort(); 1372 remote = SASLContext::HostPort(); 1373 1374 set_username = false; 1375 username = QString(); 1376 set_authzid = false; 1377 authzid = QString(); 1378 set_password = false; 1379 password = SecureArray(); 1380 set_realm = false; 1381 realm = QString(); 1382 } 1383 } 1384 1385 void setup(const QString &service, const QString &host) 1386 { 1387 c->setup(service, host, localSet ? &local : nullptr, remoteSet ? &remote : nullptr, ext_authid, ext_ssf); 1388 c->setConstraints(auth_flags, ssfmin, ssfmax); 1389 1390 QString *p_username = nullptr; 1391 QString *p_authzid = nullptr; 1392 SecureArray *p_password = nullptr; 1393 QString *p_realm = nullptr; 1394 1395 if (set_username) 1396 p_username = &username; 1397 if (set_authzid) 1398 p_authzid = &authzid; 1399 if (set_password) 1400 p_password = &password; 1401 if (set_realm) 1402 p_realm = &realm; 1403 1404 c->setClientParams(p_username, p_authzid, p_password, p_realm); 1405 } 1406 1407 void start() 1408 { 1409 op = OpStart; 1410 first = true; 1411 1412 if (server) { 1413 QCA_logTextMessage(QStringLiteral("sasl[%1]: c->startServer()").arg(q->objectName()), Logger::Information); 1414 c->startServer(server_realm, disableServerSendLast); 1415 } else { 1416 QCA_logTextMessage(QStringLiteral("sasl[%1]: c->startClient()").arg(q->objectName()), Logger::Information); 1417 c->startClient(mechlist, allowClientSendFirst); 1418 } 1419 } 1420 1421 void putServerFirstStep(const QString &mech, const QByteArray *clientInit) 1422 { 1423 if (op != -1) 1424 return; 1425 1426 QCA_logTextMessage(QStringLiteral("sasl[%1]: c->serverFirstStep()").arg(q->objectName()), Logger::Information); 1427 op = OpServerFirstStep; 1428 c->serverFirstStep(mech, clientInit); 1429 } 1430 1431 void putStep(const QByteArray &stepData) 1432 { 1433 if (op != -1) 1434 return; 1435 1436 QCA_logTextMessage(QStringLiteral("sasl[%1]: c->nextStep()").arg(q->objectName()), Logger::Information); 1437 op = OpNextStep; 1438 c->nextStep(stepData); 1439 } 1440 1441 void tryAgain() 1442 { 1443 if (op != -1) 1444 return; 1445 1446 QCA_logTextMessage(QStringLiteral("sasl[%1]: c->tryAgain()").arg(q->objectName()), Logger::Information); 1447 op = OpTryAgain; 1448 c->tryAgain(); 1449 } 1450 1451 void processNextAction() 1452 { 1453 if (actionQueue.isEmpty()) { 1454 if (need_update) 1455 update(); 1456 return; 1457 } 1458 1459 const Action a = actionQueue.takeFirst(); 1460 1461 // set up for the next one, if necessary 1462 if (!actionQueue.isEmpty() || need_update) { 1463 if (!actionTrigger.isActive()) 1464 actionTrigger.start(); 1465 } 1466 1467 if (a.type == Action::ClientStarted) { 1468 emit q->clientStarted(a.haveInit, a.stepData); 1469 } else if (a.type == Action::NextStep) { 1470 emit q->nextStep(a.stepData); 1471 } else if (a.type == Action::Authenticated) { 1472 authed = true; 1473 1474 // write any app data waiting during authentication 1475 if (!out.isEmpty()) { 1476 need_update = true; 1477 if (!actionTrigger.isActive()) 1478 actionTrigger.start(); 1479 } 1480 1481 QCA_logTextMessage(QStringLiteral("sasl[%1]: authenticated").arg(q->objectName()), Logger::Information); 1482 emit q->authenticated(); 1483 } else if (a.type == Action::ReadyRead) { 1484 emit q->readyRead(); 1485 } else if (a.type == Action::ReadyReadOutgoing) { 1486 emit q->readyReadOutgoing(); 1487 } 1488 } 1489 1490 void update() 1491 { 1492 // defer writes while authenticating 1493 if (!authed) { 1494 QCA_logTextMessage( 1495 QStringLiteral("sasl[%1]: ignoring update while not yet authenticated").arg(q->objectName()), 1496 Logger::Information); 1497 return; 1498 } 1499 1500 if (!actionQueue.isEmpty()) { 1501 QCA_logTextMessage( 1502 QStringLiteral("sasl[%1]: ignoring update while processing actions").arg(q->objectName()), 1503 Logger::Information); 1504 need_update = true; 1505 return; 1506 } 1507 1508 // only allow one operation at a time 1509 if (op != -1) { 1510 QCA_logTextMessage(QStringLiteral("sasl[%1]: ignoring update while operation active").arg(q->objectName()), 1511 Logger::Information); 1512 need_update = true; 1513 return; 1514 } 1515 1516 need_update = false; 1517 1518 QCA_logTextMessage(QStringLiteral("sasl[%1]: c->update()").arg(q->objectName()), Logger::Information); 1519 op = OpUpdate; 1520 out_pending += out.size(); 1521 c->update(from_net, out); 1522 from_net.clear(); 1523 out.clear(); 1524 } 1525 1526 private Q_SLOTS: 1527 void sasl_resultsReady() 1528 { 1529 QCA_logTextMessage(QStringLiteral("sasl[%1]: c->resultsReady()").arg(q->objectName()), Logger::Information); 1530 1531 int last_op = op; 1532 op = -1; 1533 1534 const SASLContext::Result r = c->result(); 1535 1536 if (last_op == OpStart) { 1537 if (server) { 1538 if (r != SASLContext::Success) { 1539 errorCode = SASL::ErrorInit; 1540 emit q->error(); 1541 return; 1542 } 1543 1544 emit q->serverStarted(); 1545 return; 1546 } else // client 1547 { 1548 mech = c->mech(); 1549 1550 // fall into this logic 1551 last_op = OpTryAgain; 1552 } 1553 } else if (last_op == OpServerFirstStep) { 1554 // fall into this logic 1555 last_op = OpTryAgain; 1556 } else if (last_op == OpNextStep) { 1557 // fall into this logic 1558 last_op = OpTryAgain; 1559 } 1560 1561 if (last_op == OpTryAgain) { 1562 if (server) { 1563 if (r == SASLContext::Continue) { 1564 emit q->nextStep(c->stepData()); 1565 return; 1566 } else if (r == SASLContext::AuthCheck) { 1567 emit q->authCheck(c->username(), c->authzid()); 1568 return; 1569 } else if (r == SASLContext::Success) { 1570 if (!disableServerSendLast) 1571 actionQueue += Action(Action::NextStep, c->stepData()); 1572 1573 actionQueue += Action(Action::Authenticated); 1574 1575 processNextAction(); 1576 return; 1577 } else // error 1578 { 1579 errorCode = SASL::ErrorHandshake; 1580 emit q->error(); 1581 return; 1582 } 1583 } else // client 1584 { 1585 if (first) { 1586 if (r == SASLContext::Error) { 1587 if (first) 1588 errorCode = SASL::ErrorInit; 1589 else 1590 errorCode = SASL::ErrorHandshake; 1591 emit q->error(); 1592 return; 1593 } else if (r == SASLContext::Params) { 1594 const Params np = c->clientParams(); 1595 emit q->needParams(np); 1596 return; 1597 } 1598 1599 first = false; 1600 actionQueue += Action(Action::ClientStarted, c->haveClientInit(), c->stepData()); 1601 if (r == SASLContext::Success) 1602 actionQueue += Action(Action::Authenticated); 1603 1604 processNextAction(); 1605 return; 1606 } else { 1607 if (r == SASLContext::Error) { 1608 errorCode = ErrorHandshake; 1609 emit q->error(); 1610 return; 1611 } else if (r == SASLContext::Params) { 1612 const Params np = c->clientParams(); 1613 emit q->needParams(np); 1614 return; 1615 } else if (r == SASLContext::Continue) { 1616 emit q->nextStep(c->stepData()); 1617 return; 1618 } else if (r == SASLContext::Success) { 1619 actionQueue += Action(Action::NextStep, c->stepData()); 1620 actionQueue += Action(Action::Authenticated); 1621 1622 processNextAction(); 1623 return; 1624 } 1625 } 1626 } 1627 } else if (last_op == OpUpdate) { 1628 if (r != SASLContext::Success) { 1629 errorCode = ErrorCrypt; 1630 emit q->error(); 1631 return; 1632 } 1633 1634 const QByteArray c_to_net = c->to_net(); 1635 const QByteArray c_to_app = c->to_app(); 1636 int enc = -1; 1637 if (!c_to_net.isEmpty()) 1638 enc = c->encoded(); 1639 1640 bool io_pending = false; 1641 if (!c_to_net.isEmpty()) 1642 out_pending -= enc; 1643 1644 if (out_pending > 0) 1645 io_pending = true; 1646 1647 if (!out.isEmpty()) 1648 io_pending = true; 1649 1650 to_net += c_to_net; 1651 in += c_to_app; 1652 to_net_encoded += enc; 1653 1654 if (!c_to_net.isEmpty()) 1655 actionQueue += Action(Action::ReadyReadOutgoing); 1656 1657 if (!c_to_app.isEmpty()) 1658 actionQueue += Action(Action::ReadyRead); 1659 1660 if (io_pending) 1661 update(); 1662 1663 processNextAction(); 1664 return; 1665 } 1666 } 1667 1668 void doNextAction() 1669 { 1670 processNextAction(); 1671 } 1672 }; 1673 1674 SASL::SASL(QObject *parent, const QString &provider) 1675 : SecureLayer(parent) 1676 , Algorithm(QStringLiteral("sasl"), provider) 1677 { 1678 d = new Private(this); 1679 } 1680 1681 SASL::~SASL() 1682 { 1683 delete d; 1684 } 1685 1686 void SASL::reset() 1687 { 1688 d->reset(ResetAll); 1689 } 1690 1691 SASL::Error SASL::errorCode() const 1692 { 1693 return d->errorCode; 1694 } 1695 1696 SASL::AuthCondition SASL::authCondition() const 1697 { 1698 return d->c->authCondition(); 1699 } 1700 1701 void SASL::setConstraints(AuthFlags f, SecurityLevel s) 1702 { 1703 int min = 0; 1704 if (s == SL_Integrity) 1705 min = 1; 1706 else if (s == SL_Export) 1707 min = 56; 1708 else if (s == SL_Baseline) 1709 min = 128; 1710 else if (s == SL_High) 1711 min = 192; 1712 else if (s == SL_Highest) 1713 min = 256; 1714 1715 setConstraints(f, min, 256); 1716 } 1717 1718 void SASL::setConstraints(AuthFlags f, int minSSF, int maxSSF) 1719 { 1720 d->auth_flags = f; 1721 1722 d->ssfmin = minSSF; 1723 d->ssfmax = maxSSF; 1724 } 1725 1726 void SASL::setExternalAuthId(const QString &authid) 1727 { 1728 d->ext_authid = authid; 1729 } 1730 1731 void SASL::setExternalSSF(int strength) 1732 { 1733 d->ext_ssf = strength; 1734 } 1735 1736 void SASL::setLocalAddress(const QString &addr, quint16 port) 1737 { 1738 d->localSet = true; 1739 d->local.addr = addr; 1740 d->local.port = port; 1741 } 1742 1743 void SASL::setRemoteAddress(const QString &addr, quint16 port) 1744 { 1745 d->remoteSet = true; 1746 d->remote.addr = addr; 1747 d->remote.port = port; 1748 } 1749 1750 void SASL::startClient(const QString &service, const QString &host, const QStringList &mechlist, ClientSendMode mode) 1751 { 1752 d->reset(ResetSessionAndData); 1753 d->setup(service, host); 1754 d->server = false; 1755 d->mechlist = mechlist; 1756 d->allowClientSendFirst = (mode == AllowClientSendFirst); 1757 d->start(); 1758 } 1759 1760 void SASL::startServer(const QString &service, const QString &host, const QString &realm, ServerSendMode mode) 1761 { 1762 d->reset(ResetSessionAndData); 1763 d->setup(service, host); 1764 d->server = true; 1765 d->server_realm = realm; 1766 d->disableServerSendLast = (mode == DisableServerSendLast); 1767 d->start(); 1768 } 1769 1770 void SASL::putServerFirstStep(const QString &mech) 1771 { 1772 d->putServerFirstStep(mech, nullptr); 1773 } 1774 1775 void SASL::putServerFirstStep(const QString &mech, const QByteArray &clientInit) 1776 { 1777 d->putServerFirstStep(mech, &clientInit); 1778 } 1779 1780 void SASL::putStep(const QByteArray &stepData) 1781 { 1782 d->putStep(stepData); 1783 } 1784 1785 void SASL::setUsername(const QString &user) 1786 { 1787 d->set_username = true; 1788 d->username = user; 1789 d->c->setClientParams(&user, nullptr, nullptr, nullptr); 1790 } 1791 1792 void SASL::setAuthzid(const QString &authzid) 1793 { 1794 d->set_authzid = true; 1795 d->authzid = authzid; 1796 d->c->setClientParams(nullptr, &authzid, nullptr, nullptr); 1797 } 1798 1799 void SASL::setPassword(const SecureArray &pass) 1800 { 1801 d->set_password = true; 1802 d->password = pass; 1803 d->c->setClientParams(nullptr, nullptr, &pass, nullptr); 1804 } 1805 1806 void SASL::setRealm(const QString &realm) 1807 { 1808 d->set_realm = true; 1809 d->realm = realm; 1810 d->c->setClientParams(nullptr, nullptr, nullptr, &realm); 1811 } 1812 1813 void SASL::continueAfterParams() 1814 { 1815 d->tryAgain(); 1816 } 1817 1818 void SASL::continueAfterAuthCheck() 1819 { 1820 d->tryAgain(); 1821 } 1822 1823 QString SASL::mechanism() const 1824 { 1825 return d->mech; 1826 } 1827 1828 QStringList SASL::mechanismList() const 1829 { 1830 return d->c->mechlist(); 1831 } 1832 1833 QStringList SASL::realmList() const 1834 { 1835 return d->c->realmlist(); 1836 } 1837 1838 int SASL::ssf() const 1839 { 1840 return d->c->ssf(); 1841 } 1842 1843 int SASL::bytesAvailable() const 1844 { 1845 return d->in.size(); 1846 } 1847 1848 int SASL::bytesOutgoingAvailable() const 1849 { 1850 return d->to_net.size(); 1851 } 1852 1853 void SASL::write(const QByteArray &a) 1854 { 1855 d->out.append(a); 1856 d->layer.addPlain(a.size()); 1857 d->update(); 1858 } 1859 1860 QByteArray SASL::read() 1861 { 1862 const QByteArray a = d->in; 1863 d->in.clear(); 1864 return a; 1865 } 1866 1867 void SASL::writeIncoming(const QByteArray &a) 1868 { 1869 d->from_net.append(a); 1870 d->update(); 1871 } 1872 1873 QByteArray SASL::readOutgoing(int *plainBytes) 1874 { 1875 const QByteArray a = d->to_net; 1876 d->to_net.clear(); 1877 if (plainBytes) 1878 *plainBytes = d->to_net_encoded; 1879 d->layer.specifyEncoded(a.size(), d->to_net_encoded); 1880 d->to_net_encoded = 0; 1881 return a; 1882 } 1883 1884 int SASL::convertBytesWritten(qint64 bytes) 1885 { 1886 return d->layer.finished(bytes); 1887 } 1888 1889 } 1890 1891 #include "qca_securelayer.moc"