File indexing completed on 2024-06-02 04:07:04
0001 /* 0002 * stream.cpp - handles a client stream 0003 * Copyright (C) 2003 Justin Karneges 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 * either version 2 0009 of the License, or (at your option) any later version.1 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Lesser General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Lesser General Public 0017 * License along with this library; if not, write to the Free Software 0018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 0019 * 0020 */ 0021 0022 /* 0023 Notes: 0024 - For Non-SASL auth (JEP-0078), username and resource fields are required. 0025 0026 TODO: 0027 - sasl needParams is totally jacked? PLAIN requires authzid, etc 0028 - server error handling 0029 - reply with protocol errors if the client send something wrong 0030 - don't necessarily disconnect on protocol error. prepare for more. 0031 - server function 0032 - deal with stream 'to' attribute dynamically 0033 - flag tls/sasl/binding support dynamically (have the ability to specify extra stream:features) 0034 - inform the caller about the user authentication information 0035 - sasl security settings 0036 - resource-binding interaction 0037 - timeouts 0038 - allow exchanges of non-standard stanzas 0039 - send </stream:stream> even if we close prematurely? 0040 - ensure ClientStream and child classes are fully deletable after signals 0041 - xml:lang in root (<stream>) element 0042 - sasl external 0043 - sasl anonymous 0044 */ 0045 0046 #include "xmpp.h" 0047 0048 #include <QTextStream> 0049 #include <QPointer> 0050 #include <QTimer> 0051 #include <QList> 0052 #include <QByteArray> 0053 #include <stdlib.h> 0054 #include "bytestream.h" 0055 #include <QtCrypto> 0056 #include <QUrl> 0057 #include "simplesasl.h" 0058 #include "securestream.h" 0059 #include "protocol.h" 0060 0061 #ifdef XMPP_TEST 0062 #include "td.h" 0063 #endif 0064 0065 //#define XMPP_DEBUG 0066 0067 using namespace XMPP; 0068 0069 static Debug *debug_ptr = 0; 0070 void XMPP::setDebug(Debug *p) 0071 { 0072 debug_ptr = p; 0073 } 0074 0075 static QByteArray randomArray(int size) 0076 { 0077 QByteArray a; 0078 a.resize(size); 0079 for(int n = 0; n < size; ++n) 0080 a[n] = (char)(256.0*rand()/(RAND_MAX+1.0)); 0081 return a; 0082 } 0083 0084 static QString genId() 0085 { 0086 // need SHA1 here 0087 //if(!QCA::isSupported(QCA::CAP_SHA1)) 0088 // QCA::insertProvider(createProviderHash()); 0089 0090 return QCA::Hash("sha1").hashToString(randomArray(128)); 0091 } 0092 0093 //---------------------------------------------------------------------------- 0094 // Stream 0095 //---------------------------------------------------------------------------- 0096 static XmlProtocol *foo = 0; 0097 Stream::Stream(QObject *parent) 0098 :QObject(parent) 0099 { 0100 } 0101 0102 Stream::~Stream() 0103 { 0104 } 0105 0106 Stanza Stream::createStanza(Stanza::Kind k, const Jid &to, const QString &type, const QString &id) 0107 { 0108 return Stanza(this, k, to, type, id); 0109 } 0110 0111 Stanza Stream::createStanza(const QDomElement &e) 0112 { 0113 return Stanza(this, e); 0114 } 0115 0116 QString Stream::xmlToString(const QDomElement &e, bool clip) 0117 { 0118 if(!foo) 0119 foo = new CoreProtocol; 0120 return foo->elementToString(e, clip); 0121 } 0122 0123 //---------------------------------------------------------------------------- 0124 // ClientStream 0125 //---------------------------------------------------------------------------- 0126 enum { 0127 Idle, 0128 Connecting, 0129 WaitVersion, 0130 WaitTLS, 0131 NeedParams, 0132 Active, 0133 Closing 0134 }; 0135 0136 enum { 0137 Client, 0138 Server 0139 }; 0140 0141 class ClientStream::Private 0142 { 0143 public: 0144 Private() 0145 { 0146 conn = 0; 0147 bs = 0; 0148 ss = 0; 0149 tlsHandler = 0; 0150 tls = 0; 0151 sasl = 0; 0152 0153 oldOnly = false; 0154 allowPlain = NoAllowPlain; 0155 mutualAuth = false; 0156 haveLocalAddr = false; 0157 minimumSSF = 0; 0158 maximumSSF = 0; 0159 doBinding = true; 0160 lang = ""; 0161 0162 in_rrsig = false; 0163 0164 reset(); 0165 } 0166 0167 void reset() 0168 { 0169 state = Idle; 0170 notify = 0; 0171 newStanzas = false; 0172 sasl_ssf = 0; 0173 tls_warned = false; 0174 using_tls = false; 0175 } 0176 0177 Jid jid; 0178 QString server; 0179 bool oldOnly; 0180 bool mutualAuth; 0181 AllowPlainType allowPlain; 0182 bool haveLocalAddr; 0183 QHostAddress localAddr; 0184 quint16 localPort; 0185 QString connectHost; 0186 int minimumSSF, maximumSSF; 0187 QString sasl_mech; 0188 bool doBinding; 0189 0190 bool in_rrsig; 0191 0192 Connector *conn; 0193 ByteStream *bs; 0194 TLSHandler *tlsHandler; 0195 QCA::TLS *tls; 0196 QCA::SASL *sasl; 0197 SecureStream *ss; 0198 CoreProtocol client; 0199 CoreProtocol srv; 0200 QString lang; 0201 0202 QString defRealm; 0203 0204 int mode; 0205 int state; 0206 int notify; 0207 bool newStanzas; 0208 int sasl_ssf; 0209 bool tls_warned, using_tls; 0210 bool doAuth; 0211 bool doCompress; 0212 0213 QStringList sasl_mechlist; 0214 0215 int errCond; 0216 QString errText; 0217 QDomElement errAppSpec; 0218 0219 QList<Stanza*> in; 0220 0221 QTimer noopTimer; 0222 int noop_time; 0223 }; 0224 0225 ClientStream::ClientStream(Connector *conn, TLSHandler *tlsHandler, QObject *parent) 0226 :Stream(parent) 0227 { 0228 d = new Private; 0229 d->mode = Client; 0230 d->conn = conn; 0231 connect(d->conn, &Connector::connected, this, &ClientStream::cr_connected); 0232 connect(d->conn, &Connector::error, this, &ClientStream::cr_error); 0233 0234 d->noop_time = 0; 0235 connect(&d->noopTimer, &QTimer::timeout, this, &ClientStream::doNoop); 0236 0237 d->tlsHandler = tlsHandler; 0238 } 0239 0240 ClientStream::ClientStream(const QString &host, const QString &defRealm, ByteStream *bs, QCA::TLS *tls, QObject *parent) 0241 :Stream(parent) 0242 { 0243 d = new Private; 0244 d->mode = Server; 0245 d->bs = bs; 0246 connect(d->bs, &ByteStream::connectionClosed, this, &ClientStream::bs_connectionClosed); 0247 connect(d->bs, &ByteStream::delayedCloseFinished, this, &ClientStream::bs_delayedCloseFinished); 0248 connect(d->bs, &ByteStream::error, this, &ClientStream::bs_error); 0249 0250 QByteArray spare = d->bs->read(); 0251 0252 d->ss = new SecureStream(d->bs); 0253 connect(d->ss, &ByteStream::readyRead, this, &ClientStream::ss_readyRead); 0254 connect(d->ss, &ByteStream::bytesWritten, this, &ClientStream::ss_bytesWritten); 0255 connect(d->ss, &SecureStream::tlsHandshaken, this, &ClientStream::ss_tlsHandshaken); 0256 connect(d->ss, &SecureStream::tlsClosed, this, &ClientStream::ss_tlsClosed); 0257 connect(d->ss, &ByteStream::error, this, &ClientStream::ss_error); 0258 0259 d->server = host; 0260 d->defRealm = defRealm; 0261 0262 d->tls = tls; 0263 0264 d->srv.startClientIn(genId()); 0265 //d->srv.startServerIn(genId()); 0266 //d->state = Connecting; 0267 //d->jid = Jid(); 0268 //d->server = QString(); 0269 } 0270 0271 ClientStream::~ClientStream() 0272 { 0273 reset(); 0274 delete d; 0275 } 0276 0277 void ClientStream::reset(bool all) 0278 { 0279 d->reset(); 0280 d->noopTimer.stop(); 0281 0282 // delete securestream 0283 delete d->ss; 0284 d->ss = 0; 0285 0286 // reset sasl 0287 delete d->sasl; 0288 d->sasl = 0; 0289 0290 // client 0291 if(d->mode == Client) { 0292 // reset tls 0293 // FIXME: Temporarily disabled 0294 //if(d->tlsHandler) 0295 // d->tlsHandler->reset(); 0296 0297 // reset connector 0298 if(d->bs) { 0299 d->bs->close(); 0300 d->bs = 0; 0301 } 0302 d->conn->done(); 0303 0304 // reset state machine 0305 d->client.reset(); 0306 } 0307 // server 0308 else { 0309 if(d->tls) 0310 d->tls->reset(); 0311 0312 if(d->bs) { 0313 d->bs->close(); 0314 d->bs = 0; 0315 } 0316 0317 d->srv.reset(); 0318 } 0319 0320 if(all) { 0321 while (!d->in.isEmpty()) { 0322 delete d->in.takeFirst(); 0323 } 0324 } 0325 } 0326 0327 Jid ClientStream::jid() const 0328 { 0329 return d->jid; 0330 } 0331 0332 void ClientStream::connectToServer(const Jid &jid, bool auth) 0333 { 0334 reset(true); 0335 d->state = Connecting; 0336 d->jid = jid; 0337 d->doAuth = auth; 0338 d->server = d->jid.domain(); 0339 0340 d->conn->connectToServer(d->server); 0341 } 0342 0343 void ClientStream::continueAfterWarning() 0344 { 0345 if(d->state == WaitVersion) { 0346 // if we don't have TLS yet, then we're never going to get it 0347 if(!d->tls_warned && !d->using_tls) { 0348 d->tls_warned = true; 0349 d->state = WaitTLS; 0350 warning(WarnNoTLS); 0351 return; 0352 } 0353 d->state = Connecting; 0354 processNext(); 0355 } 0356 else if(d->state == WaitTLS) { 0357 d->state = Connecting; 0358 processNext(); 0359 } 0360 } 0361 0362 void ClientStream::accept() 0363 { 0364 d->srv.host = d->server; 0365 processNext(); 0366 } 0367 0368 bool ClientStream::isActive() const 0369 { 0370 return (d->state != Idle) ? true: false; 0371 } 0372 0373 bool ClientStream::isAuthenticated() const 0374 { 0375 return (d->state == Active) ? true: false; 0376 } 0377 0378 void ClientStream::setUsername(const QString &s) 0379 { 0380 if(d->sasl) 0381 d->sasl->setUsername(s); 0382 } 0383 0384 void ClientStream::setPassword(const QString &s) 0385 { 0386 if(d->client.old) { 0387 d->client.setPassword(s); 0388 } 0389 else { 0390 if(d->sasl) 0391 d->sasl->setPassword(QCA::SecureArray(s.toUtf8())); 0392 } 0393 } 0394 0395 void ClientStream::setRealm(const QString &s) 0396 { 0397 if(d->sasl) 0398 d->sasl->setRealm(s); 0399 } 0400 0401 void ClientStream::setAuthzid(const QString &s) 0402 { 0403 if(d->sasl) 0404 d->sasl->setAuthzid(s); 0405 } 0406 0407 void ClientStream::continueAfterParams() 0408 { 0409 if(d->state == NeedParams) { 0410 d->state = Connecting; 0411 if(d->client.old) { 0412 processNext(); 0413 } 0414 else { 0415 if(d->sasl) 0416 d->sasl->continueAfterParams(); 0417 } 0418 } 0419 } 0420 0421 void ClientStream::setResourceBinding(bool b) 0422 { 0423 d->doBinding = b; 0424 } 0425 0426 void ClientStream::setLang(const QString& lang) 0427 { 0428 d->lang = lang; 0429 } 0430 0431 void ClientStream::setNoopTime(int mills) 0432 { 0433 d->noop_time = mills; 0434 0435 if(d->state != Active) 0436 return; 0437 0438 if(d->noop_time == 0) { 0439 d->noopTimer.stop(); 0440 return; 0441 } 0442 d->noopTimer.start(d->noop_time); 0443 } 0444 0445 QString ClientStream::saslMechanism() const 0446 { 0447 return d->client.saslMech(); 0448 } 0449 0450 int ClientStream::saslSSF() const 0451 { 0452 return d->sasl_ssf; 0453 } 0454 0455 void ClientStream::setSASLMechanism(const QString &s) 0456 { 0457 d->sasl_mech = s; 0458 } 0459 0460 void ClientStream::setLocalAddr(const QHostAddress &addr, quint16 port) 0461 { 0462 d->haveLocalAddr = true; 0463 d->localAddr = addr; 0464 d->localPort = port; 0465 } 0466 0467 void ClientStream::setCompress(bool compress) 0468 { 0469 d->doCompress = compress; 0470 } 0471 0472 int ClientStream::errorCondition() const 0473 { 0474 return d->errCond; 0475 } 0476 0477 QString ClientStream::errorText() const 0478 { 0479 return d->errText; 0480 } 0481 0482 QDomElement ClientStream::errorAppSpec() const 0483 { 0484 return d->errAppSpec; 0485 } 0486 0487 bool ClientStream::old() const 0488 { 0489 return d->client.old; 0490 } 0491 0492 void ClientStream::close() 0493 { 0494 if(d->state == Active) { 0495 d->state = Closing; 0496 d->client.shutdown(); 0497 processNext(); 0498 } 0499 else if(d->state != Idle && d->state != Closing) { 0500 reset(); 0501 } 0502 } 0503 0504 QDomDocument & ClientStream::doc() const 0505 { 0506 return d->client.doc; 0507 } 0508 0509 QString ClientStream::baseNS() const 0510 { 0511 return NS_CLIENT; 0512 } 0513 0514 void ClientStream::setAllowPlain(AllowPlainType a) 0515 { 0516 d->allowPlain = a; 0517 } 0518 0519 void ClientStream::setRequireMutualAuth(bool b) 0520 { 0521 d->mutualAuth = b; 0522 } 0523 0524 void ClientStream::setSSFRange(int low, int high) 0525 { 0526 d->minimumSSF = low; 0527 d->maximumSSF = high; 0528 } 0529 0530 void ClientStream::setOldOnly(bool b) 0531 { 0532 d->oldOnly = b; 0533 } 0534 0535 bool ClientStream::stanzaAvailable() const 0536 { 0537 return (!d->in.isEmpty()); 0538 } 0539 0540 Stanza ClientStream::read() 0541 { 0542 if(d->in.isEmpty()) 0543 return Stanza(); 0544 else { 0545 Stanza *sp = d->in.takeFirst(); 0546 Stanza s = *sp; 0547 delete sp; 0548 return s; 0549 } 0550 } 0551 0552 void ClientStream::write(const Stanza &s) 0553 { 0554 if(d->state == Active) { 0555 d->client.sendStanza(s.element()); 0556 processNext(); 0557 } 0558 } 0559 0560 void ClientStream::cr_connected() 0561 { 0562 d->connectHost = d->conn->host(); 0563 d->bs = d->conn->stream(); 0564 connect(d->bs, &ByteStream::connectionClosed, this, &ClientStream::bs_connectionClosed); 0565 connect(d->bs, &ByteStream::delayedCloseFinished, this, &ClientStream::bs_delayedCloseFinished); 0566 0567 QByteArray spare = d->bs->read(); 0568 0569 d->ss = new SecureStream(d->bs); 0570 connect(d->ss, &ByteStream::readyRead, this, &ClientStream::ss_readyRead); 0571 connect(d->ss, &ByteStream::bytesWritten, this, &ClientStream::ss_bytesWritten); 0572 connect(d->ss, &SecureStream::tlsHandshaken, this, &ClientStream::ss_tlsHandshaken); 0573 connect(d->ss, &SecureStream::tlsClosed, this, &ClientStream::ss_tlsClosed); 0574 connect(d->ss, &ByteStream::error, this, &ClientStream::ss_error); 0575 0576 //d->client.startDialbackOut("andbit.net", "im.pyxa.org"); 0577 //d->client.startServerOut(d->server); 0578 0579 d->client.startClientOut(d->jid, d->oldOnly, d->conn->useSSL(), d->doAuth, d->doCompress); 0580 d->client.setAllowTLS(d->tlsHandler ? true: false); 0581 d->client.setAllowBind(d->doBinding); 0582 d->client.setAllowPlain(d->allowPlain == AllowPlain || (d->allowPlain == AllowPlainOverTLS && d->conn->useSSL())); 0583 d->client.setLang(d->lang); 0584 0585 /*d->client.jid = d->jid; 0586 d->client.server = d->server; 0587 d->client.allowPlain = d->allowPlain; 0588 d->client.oldOnly = d->oldOnly; 0589 d->client.sasl_mech = d->sasl_mech; 0590 d->client.doTLS = d->tlsHandler ? true: false; 0591 d->client.doBinding = d->doBinding;*/ 0592 0593 QPointer<QObject> self = this; 0594 connected(); 0595 if(!self) 0596 return; 0597 0598 // immediate SSL? 0599 if(d->conn->useSSL()) { 0600 d->using_tls = true; 0601 d->ss->startTLSClient(d->tlsHandler, d->server, spare); 0602 } 0603 else { 0604 d->client.addIncomingData(spare); 0605 processNext(); 0606 } 0607 } 0608 0609 void ClientStream::cr_error() 0610 { 0611 reset(); 0612 error(ErrConnection); 0613 } 0614 0615 void ClientStream::bs_connectionClosed() 0616 { 0617 reset(); 0618 connectionClosed(); 0619 } 0620 0621 void ClientStream::bs_delayedCloseFinished() 0622 { 0623 // we don't care about this (we track all important data ourself) 0624 } 0625 0626 void ClientStream::bs_error(int) 0627 { 0628 // TODO 0629 } 0630 0631 void ClientStream::ss_readyRead() 0632 { 0633 QByteArray a = d->ss->read(); 0634 0635 #ifdef XMPP_DEBUG 0636 fprintf(stderr, "ClientStream: recv: %d [%s]\n", a.size(), a.data()); 0637 #endif 0638 0639 if(d->mode == Client) 0640 d->client.addIncomingData(a); 0641 else 0642 d->srv.addIncomingData(a); 0643 if(d->notify & CoreProtocol::NRecv) { 0644 #ifdef XMPP_DEBUG 0645 printf("We needed data, so let's process it\n"); 0646 #endif 0647 processNext(); 0648 } 0649 } 0650 0651 void ClientStream::ss_bytesWritten(int bytes) 0652 { 0653 if(d->mode == Client) 0654 d->client.outgoingDataWritten(bytes); 0655 else 0656 d->srv.outgoingDataWritten(bytes); 0657 0658 if(d->notify & CoreProtocol::NSend) { 0659 #ifdef XMPP_DEBUG 0660 printf("We were waiting for data to be written, so let's process\n"); 0661 #endif 0662 processNext(); 0663 } 0664 } 0665 0666 void ClientStream::ss_tlsHandshaken() 0667 { 0668 QPointer<QObject> self = this; 0669 securityLayerActivated(LayerTLS); 0670 if(!self) 0671 return; 0672 d->client.setAllowPlain(d->allowPlain == AllowPlain || d->allowPlain == AllowPlainOverTLS); 0673 processNext(); 0674 } 0675 0676 void ClientStream::ss_tlsClosed() 0677 { 0678 reset(); 0679 connectionClosed(); 0680 } 0681 0682 void ClientStream::ss_error(int x) 0683 { 0684 if(x == SecureStream::ErrTLS) { 0685 reset(); 0686 d->errCond = TLSFail; 0687 error(ErrTLS); 0688 } 0689 else { 0690 reset(); 0691 error(ErrSecurityLayer); 0692 } 0693 } 0694 0695 void ClientStream::sasl_clientFirstStep(bool, const QByteArray& ba) 0696 { 0697 d->client.setSASLFirst(d->sasl->mechanism(), ba); 0698 //d->client.sasl_mech = mech; 0699 //d->client.sasl_firstStep = stepData ? true : false; 0700 //d->client.sasl_step = stepData ? *stepData : QByteArray(); 0701 0702 processNext(); 0703 } 0704 0705 void ClientStream::sasl_nextStep(const QByteArray &stepData) 0706 { 0707 if(d->mode == Client) 0708 d->client.setSASLNext(stepData); 0709 //d->client.sasl_step = stepData; 0710 else 0711 d->srv.setSASLNext(stepData); 0712 //d->srv.sasl_step = stepData; 0713 0714 processNext(); 0715 } 0716 0717 void ClientStream::sasl_needParams(const QCA::SASL::Params& p) 0718 { 0719 #ifdef XMPP_DEBUG 0720 printf("need params: %d,%d,%d,%d\n", p.user, p.authzid, p.pass, p.realm); 0721 #endif 0722 /*if(p.authzid && !p.user) { 0723 d->sasl->setAuthzid(d->jid.bare()); 0724 //d->sasl->setAuthzid("infiniti.homelesshackers.org"); 0725 }*/ 0726 if(p.needUsername() || p.needPassword() || p.canSendRealm()) { 0727 d->state = NeedParams; 0728 needAuthParams(p.needUsername(), p.needPassword(), p.canSendRealm()); 0729 } 0730 else 0731 d->sasl->continueAfterParams(); 0732 } 0733 0734 void ClientStream::sasl_authCheck(const QString &user, const QString &) 0735 { 0736 //#ifdef XMPP_DEBUG 0737 // printf("authcheck: [%s], [%s]\n", user.latin1(), authzid.latin1()); 0738 //#endif 0739 QString u = user; 0740 int n = u.indexOf('@'); 0741 if(n != -1) 0742 u.truncate(n); 0743 d->srv.user = u; 0744 d->sasl->continueAfterAuthCheck(); 0745 } 0746 0747 void ClientStream::sasl_authenticated() 0748 { 0749 #ifdef XMPP_DEBUG 0750 printf("sasl authed!!\n"); 0751 #endif 0752 d->sasl_ssf = d->sasl->ssf(); 0753 0754 if(d->mode == Server) { 0755 d->srv.setSASLAuthed(); 0756 processNext(); 0757 } 0758 } 0759 0760 void ClientStream::sasl_error() 0761 { 0762 #ifdef XMPP_DEBUG 0763 printf("sasl error: %d\n", d->sasl->authCondition()); 0764 #endif 0765 // has to be auth error 0766 int x = convertedSASLCond(); 0767 reset(); 0768 d->errCond = x; 0769 error(ErrAuth); 0770 } 0771 0772 void ClientStream::srvProcessNext() 0773 { 0774 while(1) { 0775 printf("Processing step...\n"); 0776 if(!d->srv.processStep()) { 0777 int need = d->srv.need; 0778 if(need == CoreProtocol::NNotify) { 0779 d->notify = d->srv.notify; 0780 if(d->notify & CoreProtocol::NSend) 0781 printf("More data needs to be written to process next step\n"); 0782 if(d->notify & CoreProtocol::NRecv) 0783 printf("More data is needed to process next step\n"); 0784 } 0785 else if(need == CoreProtocol::NSASLMechs) { 0786 if(!d->sasl) { 0787 d->sasl = new QCA::SASL; 0788 connect(d->sasl, &QCA::SASL::authCheck, this, &ClientStream::sasl_authCheck); 0789 connect(d->sasl, &QCA::SASL::nextStep, this, &ClientStream::sasl_nextStep); 0790 connect(d->sasl, &QCA::SASL::authenticated, this, &ClientStream::sasl_authenticated); 0791 connect(d->sasl, &QCA::SecureLayer::error, this, &ClientStream::sasl_error); 0792 0793 //d->sasl->setAllowAnonymous(false); 0794 //d->sasl->setRequirePassCredentials(true); 0795 //d->sasl->setExternalAuthID("localhost"); 0796 QCA::SASL::AuthFlags auth_flags = (QCA::SASL::AuthFlags) 0; 0797 d->sasl->setConstraints(auth_flags,0,256); 0798 0799 QStringList list; 0800 // TODO: d->server is probably wrong here 0801 d->sasl->startServer("xmpp", d->server, d->defRealm, QCA::SASL::AllowServerSendLast); 0802 d->sasl_mechlist = list; 0803 } 0804 d->srv.setSASLMechList(d->sasl_mechlist); 0805 continue; 0806 } 0807 else if(need == CoreProtocol::NStartTLS) { 0808 printf("Need StartTLS\n"); 0809 //if(!d->tls->startServer()) { 0810 d->tls->startServer(); 0811 QByteArray a = d->srv.spare; 0812 d->ss->startTLSServer(d->tls, a); 0813 } 0814 else if(need == CoreProtocol::NSASLFirst) { 0815 printf("Need SASL First Step\n"); 0816 QByteArray a = d->srv.saslStep(); 0817 d->sasl->putServerFirstStep(d->srv.saslMech(), a); 0818 } 0819 else if(need == CoreProtocol::NSASLNext) { 0820 printf("Need SASL Next Step\n"); 0821 QByteArray a = d->srv.saslStep(); 0822 printf("[%s]\n", a.data()); 0823 d->sasl->putStep(a); 0824 } 0825 else if(need == CoreProtocol::NSASLLayer) { 0826 } 0827 0828 // now we can announce stanzas 0829 //if(!d->in.isEmpty()) 0830 // readyRead(); 0831 return; 0832 } 0833 0834 d->notify = 0; 0835 0836 int event = d->srv.event; 0837 printf("event: %d\n", event); 0838 switch(event) { 0839 case CoreProtocol::EError: { 0840 printf("Error! Code=%d\n", d->srv.errorCode); 0841 reset(); 0842 error(ErrProtocol); 0843 //handleError(); 0844 return; 0845 } 0846 case CoreProtocol::ESend: { 0847 QByteArray a = d->srv.takeOutgoingData(); 0848 printf("Need Send: {%s}\n", a.data()); 0849 d->ss->write(a); 0850 break; 0851 } 0852 case CoreProtocol::ERecvOpen: { 0853 printf("Break (RecvOpen)\n"); 0854 0855 // calculate key 0856 QByteArray str = QCA::Hash("sha1").hashToString("secret").toUtf8(); 0857 str = QCA::Hash("sha1").hashToString(str + "im.pyxa.org").toUtf8(); 0858 str = QCA::Hash("sha1").hashToString(str + d->srv.id.toUtf8()).toUtf8(); 0859 d->srv.setDialbackKey(str); 0860 0861 //d->srv.setDialbackKey("3c5d721ea2fcc45b163a11420e4e358f87e3142a"); 0862 0863 if(d->srv.to != d->server) { 0864 // host-gone, host-unknown, see-other-host 0865 d->srv.shutdownWithError(CoreProtocol::HostUnknown); 0866 } 0867 else 0868 d->srv.setFrom(d->server); 0869 break; 0870 } 0871 case CoreProtocol::ESASLSuccess: { 0872 printf("Break SASL Success\n"); 0873 disconnect(d->sasl, &QCA::SecureLayer::error, this, &ClientStream::sasl_error); 0874 QByteArray a = d->srv.spare; 0875 d->ss->setLayerSASL(d->sasl, a); 0876 break; 0877 } 0878 case CoreProtocol::EPeerClosed: { 0879 // TODO: this isn' an error 0880 printf("peer closed\n"); 0881 reset(); 0882 error(ErrProtocol); 0883 return; 0884 } 0885 } 0886 } 0887 } 0888 0889 void ClientStream::doReadyRead() 0890 { 0891 //QGuardedPtr<QObject> self = this; 0892 readyRead(); 0893 //if(!self) 0894 // return; 0895 //d->in_rrsig = false; 0896 } 0897 0898 void ClientStream::processNext() 0899 { 0900 if(d->mode == Server) { 0901 srvProcessNext(); 0902 return; 0903 } 0904 0905 QPointer<QObject> self = this; 0906 0907 while(1) { 0908 #ifdef XMPP_DEBUG 0909 printf("Processing step...\n"); 0910 #endif 0911 bool ok = d->client.processStep(); 0912 // deal with send/received items 0913 for(QList<XmlProtocol::TransferItem>::ConstIterator it = d->client.transferItemList.constBegin(); it != d->client.transferItemList.constEnd(); ++it) { 0914 const XmlProtocol::TransferItem &i = *it; 0915 if(i.isExternal) 0916 continue; 0917 QString str; 0918 if(i.isString) { 0919 // skip whitespace pings 0920 if(i.str.trimmed().isEmpty()) 0921 continue; 0922 str = i.str; 0923 } 0924 else 0925 str = d->client.elementToString(i.elem); 0926 if(i.isSent) 0927 outgoingXml(str); 0928 else 0929 incomingXml(str); 0930 } 0931 0932 if(!ok) { 0933 bool cont = handleNeed(); 0934 0935 // now we can announce stanzas 0936 //if(!d->in_rrsig && !d->in.isEmpty()) { 0937 if(!d->in.isEmpty()) { 0938 //d->in_rrsig = true; 0939 QTimer::singleShot(0, this, &ClientStream::doReadyRead); 0940 } 0941 0942 if(cont) 0943 continue; 0944 return; 0945 } 0946 0947 int event = d->client.event; 0948 d->notify = 0; 0949 switch(event) { 0950 case CoreProtocol::EError: { 0951 #ifdef XMPP_DEBUG 0952 printf("Error! Code=%d\n", d->client.errorCode); 0953 #endif 0954 handleError(); 0955 return; 0956 } 0957 case CoreProtocol::ESend: { 0958 QByteArray a = d->client.takeOutgoingData(); 0959 #ifdef XMPP_DEBUG 0960 printf("Need Send: {%s}\n", a.data()); 0961 #endif 0962 d->ss->write(a); 0963 break; 0964 } 0965 case CoreProtocol::ERecvOpen: { 0966 #ifdef XMPP_DEBUG 0967 printf("Break (RecvOpen)\n"); 0968 #endif 0969 0970 #ifdef XMPP_TEST 0971 QString s = QString("handshake success (lang=[%1]").arg(d->client.lang); 0972 if(!d->client.from.isEmpty()) 0973 s += QString(", from=[%1]").arg(d->client.from); 0974 s += ')'; 0975 TD::msg(s); 0976 #endif 0977 0978 if(d->client.old) { 0979 d->state = WaitVersion; 0980 warning(WarnOldVersion); 0981 return; 0982 } 0983 break; 0984 } 0985 case CoreProtocol::EFeatures: { 0986 #ifdef XMPP_DEBUG 0987 printf("Break (Features)\n"); 0988 #endif 0989 if(!d->tls_warned && !d->using_tls && !d->client.features.tls_supported) { 0990 d->tls_warned = true; 0991 d->state = WaitTLS; 0992 warning(WarnNoTLS); 0993 return; 0994 } 0995 break; 0996 } 0997 case CoreProtocol::ESASLSuccess: { 0998 #ifdef XMPP_DEBUG 0999 printf("Break SASL Success\n"); 1000 #endif 1001 break; 1002 } 1003 case CoreProtocol::EReady: { 1004 #ifdef XMPP_DEBUG 1005 printf("Done!\n"); 1006 #endif 1007 // grab the JID, in case it changed 1008 d->jid = d->client.jid(); 1009 d->state = Active; 1010 setNoopTime(d->noop_time); 1011 authenticated(); 1012 if(!self) 1013 return; 1014 break; 1015 } 1016 case CoreProtocol::EPeerClosed: { 1017 #ifdef XMPP_DEBUG 1018 printf("DocumentClosed\n"); 1019 #endif 1020 reset(); 1021 connectionClosed(); 1022 return; 1023 } 1024 case CoreProtocol::EStanzaReady: { 1025 #ifdef XMPP_DEBUG 1026 printf("StanzaReady\n"); 1027 #endif 1028 // store the stanza for now, announce after processing all events 1029 Stanza s = createStanza(d->client.recvStanza()); 1030 if(s.isNull()) 1031 break; 1032 d->in.append(new Stanza(s)); 1033 break; 1034 } 1035 case CoreProtocol::EStanzaSent: { 1036 #ifdef XMPP_DEBUG 1037 printf("StanzasSent\n"); 1038 #endif 1039 stanzaWritten(); 1040 if(!self) 1041 return; 1042 break; 1043 } 1044 case CoreProtocol::EClosed: { 1045 #ifdef XMPP_DEBUG 1046 printf("Closed\n"); 1047 #endif 1048 reset(); 1049 delayedCloseFinished(); 1050 return; 1051 } 1052 } 1053 } 1054 } 1055 1056 bool ClientStream::handleNeed() 1057 { 1058 int need = d->client.need; 1059 if(need == CoreProtocol::NNotify) { 1060 d->notify = d->client.notify; 1061 #ifdef XMPP_DEBUG 1062 if(d->notify & CoreProtocol::NSend) 1063 printf("More data needs to be written to process next step\n"); 1064 if(d->notify & CoreProtocol::NRecv) 1065 printf("More data is needed to process next step\n"); 1066 #endif 1067 return false; 1068 } 1069 1070 d->notify = 0; 1071 switch(need) { 1072 case CoreProtocol::NStartTLS: { 1073 #ifdef XMPP_DEBUG 1074 printf("Need StartTLS\n"); 1075 #endif 1076 d->using_tls = true; 1077 d->ss->startTLSClient(d->tlsHandler, d->server, d->client.spare); 1078 return false; 1079 } 1080 case CoreProtocol::NCompress: { 1081 #ifdef XMPP_DEBUG 1082 printf("Need compress\n"); 1083 #endif 1084 d->ss->setLayerCompress(d->client.spare); 1085 return true; 1086 } 1087 case CoreProtocol::NSASLFirst: { 1088 #ifdef XMPP_DEBUG 1089 printf("Need SASL First Step\n"); 1090 #endif 1091 1092 // ensure simplesasl provider is installed 1093 bool found = false; 1094 foreach(QCA::Provider *p, QCA::providers()) { 1095 if(p->name() == "simplesasl") { 1096 found = true; 1097 break; 1098 } 1099 } 1100 if(!found) { 1101 // install with low-priority 1102 QCA::insertProvider(createProviderSimpleSASL()); 1103 QCA::setProviderPriority("simplesasl", 10); 1104 } 1105 1106 d->sasl = new QCA::SASL(); 1107 connect(d->sasl, &QCA::SASL::clientStarted, this, &ClientStream::sasl_clientFirstStep); 1108 connect(d->sasl, &QCA::SASL::nextStep, this, &ClientStream::sasl_nextStep); 1109 connect(d->sasl, &QCA::SASL::needParams, this, &ClientStream::sasl_needParams); 1110 connect(d->sasl, &QCA::SASL::authenticated, this, &ClientStream::sasl_authenticated); 1111 connect(d->sasl, &QCA::SecureLayer::error, this, &ClientStream::sasl_error); 1112 1113 if(d->haveLocalAddr) 1114 d->sasl->setLocalAddress(d->localAddr.toString(), d->localPort); 1115 if(d->conn->havePeerAddress()) 1116 d->sasl->setRemoteAddress(d->conn->peerAddress().toString(), d->conn->peerPort()); 1117 1118 //d->sasl_mech = "ANONYMOUS"; 1119 //d->sasl->setRequirePassCredentials(true); 1120 //d->sasl->setExternalAuthID("localhost"); 1121 //d->sasl->setExternalSSF(64); 1122 //d->sasl_mech = "EXTERNAL"; 1123 1124 QCA::SASL::AuthFlags auth_flags = (QCA::SASL::AuthFlags) 0; 1125 if (d->allowPlain == AllowPlain || (d->allowPlain == AllowPlainOverTLS && d->using_tls)) 1126 auth_flags = (QCA::SASL::AuthFlags) (auth_flags | QCA::SASL::AllowPlain); 1127 if (d->mutualAuth) 1128 auth_flags = (QCA::SASL::AuthFlags) (auth_flags | QCA::SASL::RequireMutualAuth); 1129 d->sasl->setConstraints(auth_flags,d->minimumSSF,d->maximumSSF); 1130 1131 QStringList ml; 1132 if(!d->sasl_mech.isEmpty()) 1133 ml += d->sasl_mech; 1134 else 1135 ml = d->client.features.sasl_mechs; 1136 1137 #ifdef IRIS_SASLCONNECTHOST 1138 d->sasl->startClient("xmpp", QUrl::toAce(d->connectHost), ml, QCA::SASL::AllowClientSendFirst); 1139 #else 1140 d->sasl->startClient("xmpp", QUrl::toAce(d->server), ml, QCA::SASL::AllowClientSendFirst); 1141 #endif 1142 return false; 1143 } 1144 case CoreProtocol::NSASLNext: { 1145 #ifdef XMPP_DEBUG 1146 printf("Need SASL Next Step\n"); 1147 #endif 1148 QByteArray a = d->client.saslStep(); 1149 d->sasl->putStep(a); 1150 return false; 1151 } 1152 case CoreProtocol::NSASLLayer: { 1153 // SecureStream will handle the errors from this point 1154 disconnect(d->sasl, &QCA::SecureLayer::error, this, &ClientStream::sasl_error); 1155 d->ss->setLayerSASL(d->sasl, d->client.spare); 1156 if(d->sasl_ssf > 0) { 1157 QPointer<QObject> self = this; 1158 securityLayerActivated(LayerSASL); 1159 if(!self) 1160 return false; 1161 } 1162 break; 1163 } 1164 case CoreProtocol::NPassword: { 1165 #ifdef XMPP_DEBUG 1166 printf("Need Password\n"); 1167 #endif 1168 d->state = NeedParams; 1169 needAuthParams(false, true, false); 1170 return false; 1171 } 1172 } 1173 1174 return true; 1175 } 1176 1177 int ClientStream::convertedSASLCond() const 1178 { 1179 int x = d->sasl->authCondition(); 1180 if(x == QCA::SASL::NoMechanism) 1181 return NoMech; 1182 else if(x == QCA::SASL::BadProtocol) 1183 return BadProto; 1184 else if(x == QCA::SASL::BadServer) 1185 return BadServ; 1186 else if(x == QCA::SASL::TooWeak) 1187 return MechTooWeak; 1188 else 1189 return GenericAuthError; 1190 return 0; 1191 } 1192 1193 void ClientStream::doNoop() 1194 { 1195 if(d->state == Active) { 1196 #ifdef XMPP_DEBUG 1197 printf("doPing\n"); 1198 #endif 1199 d->client.sendWhitespace(); 1200 processNext(); 1201 } 1202 } 1203 1204 void ClientStream::writeDirect(const QString &s) 1205 { 1206 if(d->state == Active) { 1207 #ifdef XMPP_DEBUG 1208 printf("writeDirect\n"); 1209 #endif 1210 d->client.sendDirect(s); 1211 processNext(); 1212 } 1213 } 1214 1215 void ClientStream::handleError() 1216 { 1217 int c = d->client.errorCode; 1218 if(c == CoreProtocol::ErrParse) { 1219 reset(); 1220 error(ErrParse); 1221 } 1222 else if(c == CoreProtocol::ErrProtocol) { 1223 reset(); 1224 error(ErrProtocol); 1225 } 1226 else if(c == CoreProtocol::ErrStream) { 1227 int x = d->client.errCond; 1228 QString text = d->client.errText; 1229 QDomElement appSpec = d->client.errAppSpec; 1230 1231 int connErr = -1; 1232 int strErr = -1; 1233 1234 switch(x) { 1235 case CoreProtocol::BadFormat: { break; } // should NOT happen (we send the right format) 1236 case CoreProtocol::BadNamespacePrefix: { break; } // should NOT happen (we send prefixes) 1237 case CoreProtocol::Conflict: { strErr = Conflict; break; } 1238 case CoreProtocol::ConnectionTimeout: { strErr = ConnectionTimeout; break; } 1239 case CoreProtocol::HostGone: { connErr = HostGone; break; } 1240 case CoreProtocol::HostUnknown: { connErr = HostUnknown; break; } 1241 case CoreProtocol::ImproperAddressing: { break; } // should NOT happen (we aren't a server) 1242 case CoreProtocol::InternalServerError: { strErr = InternalServerError; break; } 1243 case CoreProtocol::InvalidFrom: { strErr = InvalidFrom; break; } 1244 case CoreProtocol::InvalidId: { break; } // should NOT happen (clients don't specify id) 1245 case CoreProtocol::InvalidNamespace: { break; } // should NOT happen (we set the right ns) 1246 case CoreProtocol::InvalidXml: { strErr = InvalidXml; break; } // shouldn't happen either, but just in case ... 1247 case CoreProtocol::StreamNotAuthorized: { break; } // should NOT happen (we're not stupid) 1248 case CoreProtocol::PolicyViolation: { strErr = PolicyViolation; break; } 1249 case CoreProtocol::RemoteConnectionFailed: { connErr = RemoteConnectionFailed; break; } 1250 case CoreProtocol::ResourceConstraint: { strErr = ResourceConstraint; break; } 1251 case CoreProtocol::RestrictedXml: { strErr = InvalidXml; break; } // group with this one 1252 case CoreProtocol::SeeOtherHost: { connErr = SeeOtherHost; break; } 1253 case CoreProtocol::SystemShutdown: { strErr = SystemShutdown; break; } 1254 case CoreProtocol::UndefinedCondition: { break; } // leave as null error 1255 case CoreProtocol::UnsupportedEncoding: { break; } // should NOT happen (we send good encoding) 1256 case CoreProtocol::UnsupportedStanzaType: { break; } // should NOT happen (we're not stupid) 1257 case CoreProtocol::UnsupportedVersion: { connErr = UnsupportedVersion; break; } 1258 case CoreProtocol::XmlNotWellFormed: { strErr = InvalidXml; break; } // group with this one 1259 default: { break; } 1260 } 1261 1262 reset(); 1263 1264 d->errText = text; 1265 d->errAppSpec = appSpec; 1266 if(connErr != -1) { 1267 d->errCond = connErr; 1268 error(ErrNeg); 1269 } 1270 else { 1271 if(strErr != -1) 1272 d->errCond = strErr; 1273 else 1274 d->errCond = GenericStreamError; 1275 error(ErrStream); 1276 } 1277 } 1278 else if(c == CoreProtocol::ErrStartTLS) { 1279 reset(); 1280 d->errCond = TLSStart; 1281 error(ErrTLS); 1282 } 1283 else if(c == CoreProtocol::ErrAuth) { 1284 int x = d->client.errCond; 1285 int r = GenericAuthError; 1286 if(d->client.old) { 1287 if(x == 401) // not authorized 1288 r = NotAuthorized; 1289 else if(x == 409) // conflict 1290 r = GenericAuthError; 1291 else if(x == 406) // not acceptable (this should NOT happen) 1292 r = GenericAuthError; 1293 } 1294 else { 1295 switch(x) { 1296 case CoreProtocol::Aborted: { r = GenericAuthError; break; } // should NOT happen (we never send <abort/>) 1297 case CoreProtocol::IncorrectEncoding: { r = GenericAuthError; break; } // should NOT happen 1298 case CoreProtocol::InvalidAuthzid: { r = InvalidAuthzid; break; } 1299 case CoreProtocol::InvalidMech: { r = InvalidMech; break; } 1300 case CoreProtocol::MechTooWeak: { r = MechTooWeak; break; } 1301 case CoreProtocol::NotAuthorized: { r = NotAuthorized; break; } 1302 case CoreProtocol::TemporaryAuthFailure: { r = TemporaryAuthFailure; break; } 1303 } 1304 } 1305 reset(); 1306 d->errCond = r; 1307 error(ErrAuth); 1308 } 1309 else if(c == CoreProtocol::ErrPlain) { 1310 reset(); 1311 d->errCond = NoMech; 1312 error(ErrAuth); 1313 } 1314 else if(c == CoreProtocol::ErrBind) { 1315 int r = -1; 1316 if(d->client.errCond == CoreProtocol::BindBadRequest) { 1317 // should NOT happen 1318 } 1319 else if(d->client.errCond == CoreProtocol::BindNotAllowed) { 1320 r = BindNotAllowed; 1321 } 1322 else if(d->client.errCond == CoreProtocol::BindConflict) { 1323 r = BindConflict; 1324 } 1325 1326 if(r != -1) { 1327 reset(); 1328 d->errCond = r; 1329 error(ErrBind); 1330 } 1331 else { 1332 reset(); 1333 error(ErrProtocol); 1334 } 1335 } 1336 } 1337 1338 QStringList ClientStream::hosts() const 1339 { 1340 return d->client.hosts; 1341 } 1342 1343 1344 //---------------------------------------------------------------------------- 1345 // Debug 1346 //---------------------------------------------------------------------------- 1347 Debug::~Debug() 1348 { 1349 } 1350 1351 #ifdef XMPP_TEST 1352 TD::TD() 1353 { 1354 } 1355 1356 TD::~TD() 1357 { 1358 } 1359 1360 void TD::msg(const QString &s) 1361 { 1362 if(debug_ptr) 1363 debug_ptr->msg(s); 1364 } 1365 1366 void TD::outgoingTag(const QString &s) 1367 { 1368 if(debug_ptr) 1369 debug_ptr->outgoingTag(s); 1370 } 1371 1372 void TD::incomingTag(const QString &s) 1373 { 1374 if(debug_ptr) 1375 debug_ptr->incomingTag(s); 1376 } 1377 1378 void TD::outgoingXml(const QDomElement &e) 1379 { 1380 if(debug_ptr) 1381 debug_ptr->outgoingXml(e); 1382 } 1383 1384 void TD::incomingXml(const QDomElement &e) 1385 { 1386 if(debug_ptr) 1387 debug_ptr->incomingXml(e); 1388 } 1389 #endif