#include #include #include #include #include #include #include #include #include "bsocket.h" #include "xmpp.h" #include char pemdata_cert[] = "-----BEGIN CERTIFICATE-----\n" "MIIDbjCCAtegAwIBAgIBADANBgkqhkiG9w0BAQQFADCBhzELMAkGA1UEBhMCVVMx\n" "EzARBgNVBAgTCkNhbGlmb3JuaWExDzANBgNVBAcTBklydmluZTEYMBYGA1UEChMP\n" "RXhhbXBsZSBDb21wYW55MRQwEgYDVQQDEwtleGFtcGxlLmNvbTEiMCAGCSqGSIb3\n" "DQEJARYTZXhhbXBsZUBleGFtcGxlLmNvbTAeFw0wMzA3MjQwNzMwMDBaFw0wMzA4\n" "MjMwNzMwMDBaMIGHMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEP\n" "MA0GA1UEBxMGSXJ2aW5lMRgwFgYDVQQKEw9FeGFtcGxlIENvbXBhbnkxFDASBgNV\n" "BAMTC2V4YW1wbGUuY29tMSIwIAYJKoZIhvcNAQkBFhNleGFtcGxlQGV4YW1wbGUu\n" "Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCobzCF268K2sRp473gvBTT\n" "4AgSL1kjeF8N57vxS1P8zWrWMXNs4LuH0NRZmKTajeboy0br8xw+smIy3AbaKAwW\n" "WZToesxebu3m9VeA8dqWyOaUMjoxAcgVYesgVaMpjRe7fcWdJnX1wJoVVPuIcO8m\n" "a+AAPByfTORbzpSTmXAQAwIDAQABo4HnMIHkMB0GA1UdDgQWBBTvFierzLmmYMq0\n" "cB/+5rK1bNR56zCBtAYDVR0jBIGsMIGpgBTvFierzLmmYMq0cB/+5rK1bNR566GB\n" "jaSBijCBhzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDzANBgNV\n" "BAcTBklydmluZTEYMBYGA1UEChMPRXhhbXBsZSBDb21wYW55MRQwEgYDVQQDEwtl\n" "eGFtcGxlLmNvbTEiMCAGCSqGSIb3DQEJARYTZXhhbXBsZUBleGFtcGxlLmNvbYIB\n" "ADAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4GBAGqGhXf7xNOnYNtFO7gz\n" "K6RdZGHFI5q1DAEz4hhNBC9uElh32XGX4wN7giz3zLC8v9icL/W4ff/K5NDfv3Gf\n" "gQe/+Wo9Be3H3ul6uwPPFnx4+PIOF2a5TW99H9smyxWdNjnFtcUte4al3RszcMWG\n" "x3iqsWosGtj6F+ridmKoqKLu\n" "-----END CERTIFICATE-----\n"; char pemdata_privkey[] = "-----BEGIN RSA PRIVATE KEY-----\n" "MIICXAIBAAKBgQCobzCF268K2sRp473gvBTT4AgSL1kjeF8N57vxS1P8zWrWMXNs\n" "4LuH0NRZmKTajeboy0br8xw+smIy3AbaKAwWWZToesxebu3m9VeA8dqWyOaUMjox\n" "AcgVYesgVaMpjRe7fcWdJnX1wJoVVPuIcO8ma+AAPByfTORbzpSTmXAQAwIDAQAB\n" "AoGAP83u+aYghuIcaWhmM03MLf69z/WztKYSi/fu0BcS977w67bL3MC9CVPoPRB/\n" "0nLSt/jZIuRzHKUCYfXLerSU7v0oXDTy6GPzWMh/oXIrpF0tYNbwWF7LSq2O2gGZ\n" "XtA9MSmUNNJaKzQQeXjqdVFOY8A0Pho+k2KByBiCi+ChkcECQQDRUuyX0+PKJtA2\n" "M36BOTFpy61BAv+JRlXUnHuevOfQWl6NR6YGygqCyH1sWtP1sa9S4wWys3DFH+5A\n" "DkuAqk7zAkEAzf4eUH2hp5CIMsXH+WpIzKj09oY1it2CAKjVq4rUELf8iXvmGoFl\n" "000spua4MjHNUYm7LR0QaKesKrMyGZUesQJAL8aLdYPJI+SD9Tr/jqLtIkZ4frQe\n" "eshw4pvsoyheiHF3zyshO791crAr4EVCx3sMlxB1xnmqLXPCPyCEHxO//QJBAIBY\n" "IYkjDZJ6ofGIe1UyXJNvfdkPu9J+ut4wU5jjEcgs6mK62J6RGuFxhy2iOQfFMdjo\n" "yL+OCUg7mDCun7uCxrECQAtSvnLOFMjO5qExRjFtwi+b1rcSekd3Osk/izyRFSzg\n" "Or+AL56/EKfiogNnFipgaXIbb/xj785Cob6v96XoW1I=\n" "-----END RSA PRIVATE KEY-----\n"; QCA::Cert *cert; QCA::RSAKey *privkey; using namespace XMPP; int id_num = 0; class Session : public QObject { Q_OBJECT public: Session(const QString &host, const QString &defRealm, ByteStream *bs) : QObject(0) { id = id_num++; tls = new QCA::TLS; tls->setCertificate(*cert, *privkey); cs = new ClientStream(host, defRealm, bs, tls); connect(cs, SIGNAL(connectionClosed()), SLOT(cs_connectionClosed())); connect(cs, SIGNAL(error(int)), SLOT(cs_error(int))); } ~Session() { delete cs; delete tls; printf("[%d]: deleted\n", id); } void start() { printf("[%d]: New session!\n", id); cs->accept(); } signals: void done(); private slots: void cs_connectionClosed() { printf("[%d]: Connection closed by peer\n", id); done(); } void cs_error(int) { printf("[%d]: Error\n", id); done(); } private: int id; ClientStream *cs; QCA::TLS *tls; }; class ServerTest : public QServerSocket { Q_OBJECT public: enum { Idle, Handshaking, Active, Closing }; ServerTest(const QString &_host, int _port) : QServerSocket(_port), host(_host), port(_port) { cert = new QCA::Cert; privkey = new QCA::RSAKey; cert->fromPEM(pemdata_cert); privkey->fromPEM(pemdata_privkey); list.setAutoDelete(true); } ~ServerTest() { } void start() { char buf[256]; int r = gethostname(buf, sizeof(buf)-1); if(r == -1) { printf("Error getting hostname!\n"); QTimer::singleShot(0, this, SIGNAL(quit())); return; } QString myhostname = buf; realm = myhostname; if(host.isEmpty()) host = myhostname; if(cert->isNull() || privkey->isNull()) { printf("Error loading cert and/or private key!\n"); QTimer::singleShot(0, this, SIGNAL(quit())); return; } if(!ok()) { printf("Error binding to port %d!\n", port); QTimer::singleShot(0, this, SIGNAL(quit())); return; } printf("Listening on %s:%d ...\n", host.latin1(), port); } void newConnection(int s) { BSocket *bs = new BSocket; bs->setSocket(s); Session *sess = new Session(host, realm, bs); list.append(sess); connect(sess, SIGNAL(done()), SLOT(sess_done())); sess->start(); } signals: void quit(); private slots: void sess_done() { Session *sess = (Session *)sender(); list.removeRef(sess); } private: QString host, realm; int port; QPtrList list; }; #include "server.moc" int main(int argc, char **argv) { QApplication app(argc, argv, false); QString host = argc > 1 ? QString(argv[1]) : QString(); int port = argc > 2 ? QString(argv[2]).toInt() : 5222; if(!QCA::isSupported(QCA::CAP_TLS)) { printf("TLS not supported!\n"); return 1; } if(!QCA::isSupported(QCA::CAP_SASL)) { printf("SASL not supported!\n"); return 1; } srand(time(NULL)); ServerTest *s = new ServerTest(host, port); QObject::connect(s, SIGNAL(quit()), &app, SLOT(quit())); s->start(); app.exec(); delete s; // clean up QCA::unloadAllPlugins(); return 0; }