summaryrefslogtreecommitdiffstats
path: root/examples/ssltest/ssltest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/ssltest/ssltest.cpp')
-rw-r--r--examples/ssltest/ssltest.cpp276
1 files changed, 276 insertions, 0 deletions
diff --git a/examples/ssltest/ssltest.cpp b/examples/ssltest/ssltest.cpp
new file mode 100644
index 0000000..f26f293
--- /dev/null
+++ b/examples/ssltest/ssltest.cpp
@@ -0,0 +1,276 @@
+#include<tqapplication.h>
+#include<tqdom.h>
+#include<tqfile.h>
+#include<tqsocket.h>
+#include<tqptrlist.h>
+#include"base64.h"
+#include"qca.h"
+
+TQCA::Cert readCertXml(const TQDomElement &e)
+{
+ TQCA::Cert cert;
+ // there should be one child data tag
+ TQDomElement data = e.elementsByTagName("data").item(0).toElement();
+ if(!data.isNull())
+ cert.fromDER(Base64::stringToArray(data.text()));
+ return cert;
+}
+
+void showCertInfo(const TQCA::Cert &cert)
+{
+ printf("-- Cert --\n");
+ printf(" CN: %s\n", cert.subject()["CN"].latin1());
+ printf(" Valid from: %s, until %s\n",
+ cert.notBefore().toString().latin1(),
+ cert.notAfter().toString().latin1());
+ printf(" PEM:\n%s\n", cert.toPEM().latin1());
+}
+
+TQPtrList<TQCA::Cert> getRootCerts(const TQString &store)
+{
+ TQPtrList<TQCA::Cert> list;
+
+ // open the Psi rootcerts file
+ TQFile f(store);
+ if(!f.open(IO_ReadOnly)) {
+ printf("unable to open %s\n", f.name().latin1());
+ return list;
+ }
+ TQDomDocument doc;
+ doc.setContent(&f);
+ f.close();
+
+ TQDomElement base = doc.documentElement();
+ if(base.tagName() != "store") {
+ printf("wrong format of %s\n", f.name().latin1());
+ return list;
+ }
+ TQDomNodeList cl = base.elementsByTagName("certificate");
+ if(cl.count() == 0) {
+ printf("no certs found in %s\n", f.name().latin1());
+ return list;
+ }
+
+ int num = 0;
+ for(int n = 0; n < (int)cl.count(); ++n) {
+ TQCA::Cert *cert = new TQCA::Cert(readCertXml(cl.item(n).toElement()));
+ if(cert->isNull()) {
+ printf("error reading cert\n");
+ delete cert;
+ continue;
+ }
+
+ ++num;
+ list.append(cert);
+ }
+ printf("imported %d root certs\n", num);
+
+ return list;
+}
+
+TQString resultToString(int result)
+{
+ TQString s;
+ switch(result) {
+ case TQCA::TLS::NoCert:
+ s = TQObject::tr("No certificate presented.");
+ break;
+ case TQCA::TLS::Valid:
+ break;
+ case TQCA::TLS::HostMismatch:
+ s = TQObject::tr("Hostname mismatch.");
+ break;
+ case TQCA::TLS::Rejected:
+ s = TQObject::tr("Root CA rejects the specified purpose.");
+ break;
+ case TQCA::TLS::Untrusted:
+ s = TQObject::tr("Not trusted for the specified purpose.");
+ break;
+ case TQCA::TLS::SignatureFailed:
+ s = TQObject::tr("Invalid signature.");
+ break;
+ case TQCA::TLS::InvalidCA:
+ s = TQObject::tr("Invalid CA certificate.");
+ break;
+ case TQCA::TLS::InvalidPurpose:
+ s = TQObject::tr("Invalid certificate purpose.");
+ break;
+ case TQCA::TLS::SelfSigned:
+ s = TQObject::tr("Certificate is self-signed.");
+ break;
+ case TQCA::TLS::Revoked:
+ s = TQObject::tr("Certificate has been revoked.");
+ break;
+ case TQCA::TLS::PathLengthExceeded:
+ s = TQObject::tr("Maximum cert chain length exceeded.");
+ break;
+ case TQCA::TLS::Expired:
+ s = TQObject::tr("Certificate has expired.");
+ break;
+ case TQCA::TLS::Unknown:
+ default:
+ s = TQObject::tr("General validation error.");
+ break;
+ }
+ return s;
+}
+
+class SecureTest : public TQObject
+{
+ Q_OBJECT
+public:
+ SecureTest()
+ {
+ sock = new TQSocket;
+ connect(sock, SIGNAL(connected()), SLOT(sock_connected()));
+ connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
+ connect(sock, SIGNAL(connectionClosed()), SLOT(sock_connectionClosed()));
+ connect(sock, SIGNAL(error(int)), SLOT(sock_error(int)));
+
+ ssl = new TQCA::TLS;
+ connect(ssl, SIGNAL(handshaken()), SLOT(ssl_handshaken()));
+ connect(ssl, SIGNAL(readyRead()), SLOT(ssl_readyRead()));
+ connect(ssl, SIGNAL(readyReadOutgoing(int)), SLOT(ssl_readyReadOutgoing(int)));
+ connect(ssl, SIGNAL(closed()), SLOT(ssl_closed()));
+ connect(ssl, SIGNAL(error(int)), SLOT(ssl_error(int)));
+
+ rootCerts.setAutoDelete(true);
+ rootCerts = getRootCerts("/usr/local/share/psi/certs/rootcert.xml");
+ }
+
+ ~SecureTest()
+ {
+ delete ssl;
+ delete sock;
+ }
+
+ void start(const TQString &_host)
+ {
+ int n = _host.find(':');
+ int port;
+ if(n != -1) {
+ host = _host.mid(0, n);
+ port = _host.mid(n+1).toInt();
+ }
+ else {
+ host = _host;
+ port = 443;
+ }
+
+ printf("Trying %s:%d...\n", host.latin1(), port);
+ sock->connectToHost(host, port);
+ }
+
+signals:
+ void quit();
+
+private slots:
+ void sock_connected()
+ {
+ printf("Connected, starting TLS handshake...\n");
+ ssl->setCertificateStore(rootCerts);
+ ssl->startClient(host);
+ }
+
+ void sock_readyRead()
+ {
+ TQByteArray buf(sock->bytesAvailable());
+ int num = sock->readBlock(buf.data(), buf.size());
+ if(num < (int)buf.size())
+ buf.resize(num);
+ ssl->writeIncoming(buf);
+ }
+
+ void sock_connectionClosed()
+ {
+ printf("\nConnection closed.\n");
+ quit();
+ }
+
+ void sock_error(int)
+ {
+ printf("\nSocket error.\n");
+ quit();
+ }
+
+ void ssl_handshaken()
+ {
+ cert = ssl->peerCertificate();
+ int vr = ssl->certificateValidityResult();
+
+ printf("Successful SSL handshake.\n");
+ if(!cert.isNull())
+ showCertInfo(cert);
+ if(vr == TQCA::TLS::Valid)
+ printf("Valid certificate.\n");
+ else
+ printf("Invalid certificate: %s\n", resultToString(vr).latin1());
+
+ printf("Let's try a GET request now.\n");
+ TQString req = "GET / HTTP/1.0\nHost: " + host + "\n\n";
+ TQCString cs = req.latin1();
+ TQByteArray buf(cs.length());
+ memcpy(buf.data(), cs.data(), buf.size());
+ ssl->write(buf);
+ }
+
+ void ssl_readyRead()
+ {
+ TQByteArray a = ssl->read();
+ TQCString cs;
+ cs.resize(a.size()+1);
+ memcpy(cs.data(), a.data(), a.size());
+ printf("%s", cs.data());
+ }
+
+ void ssl_readyReadOutgoing(int)
+ {
+ TQByteArray a = ssl->readOutgoing();
+ sock->writeBlock(a.data(), a.size());
+ }
+
+ void ssl_closed()
+ {
+ printf("SSL session closed\n");
+ }
+
+ void ssl_error(int x)
+ {
+ if(x == TQCA::TLS::ErrHandshake) {
+ printf("SSL Handshake Error!\n");
+ quit();
+ }
+ else {
+ printf("SSL Error!\n");
+ quit();
+ }
+ }
+
+private:
+ TQString host;
+ TQSocket *sock;
+ TQCA::TLS *ssl;
+ TQCA::Cert cert;
+ TQPtrList<TQCA::Cert> rootCerts;
+};
+
+#include"ssltest.moc"
+
+int main(int argc, char **argv)
+{
+ TQApplication app(argc, argv, false);
+ TQString host = argc > 1 ? argv[1] : "andbit.net";
+
+ if(!TQCA::isSupported(TQCA::CAP_TLS)) {
+ printf("TLS not supported!\n");
+ return 1;
+ }
+
+ SecureTest *s = new SecureTest;
+ TQObject::connect(s, SIGNAL(quit()), &app, SLOT(quit()));
+ s->start(host);
+ app.exec();
+ delete s;
+
+ return 0;
+}