source: qca/trunk/examples/ssltest/ssltest.cpp@ 112

Last change on this file since 112 was 24, checked in by dmik, 19 years ago

QCA: Imported original QCA 1.0 sources from Affinix

  • Property svn:keywords set to Id
File size: 5.9 KB
Line 
1#include<qapplication.h>
2#include<qdom.h>
3#include<qfile.h>
4#include<qsocket.h>
5#include<qptrlist.h>
6#include"base64.h"
7#include"qca.h"
8
9QCA::Cert readCertXml(const QDomElement &e)
10{
11 QCA::Cert cert;
12 // there should be one child data tag
13 QDomElement data = e.elementsByTagName("data").item(0).toElement();
14 if(!data.isNull())
15 cert.fromDER(Base64::stringToArray(data.text()));
16 return cert;
17}
18
19void showCertInfo(const QCA::Cert &cert)
20{
21 printf("-- Cert --\n");
22 printf(" CN: %s\n", cert.subject()["CN"].latin1());
23 printf(" Valid from: %s, until %s\n",
24 cert.notBefore().toString().latin1(),
25 cert.notAfter().toString().latin1());
26 printf(" PEM:\n%s\n", cert.toPEM().latin1());
27}
28
29QPtrList<QCA::Cert> getRootCerts(const QString &store)
30{
31 QPtrList<QCA::Cert> list;
32
33 // open the Psi rootcerts file
34 QFile f(store);
35 if(!f.open(IO_ReadOnly)) {
36 printf("unable to open %s\n", f.name().latin1());
37 return list;
38 }
39 QDomDocument doc;
40 doc.setContent(&f);
41 f.close();
42
43 QDomElement base = doc.documentElement();
44 if(base.tagName() != "store") {
45 printf("wrong format of %s\n", f.name().latin1());
46 return list;
47 }
48 QDomNodeList cl = base.elementsByTagName("certificate");
49 if(cl.count() == 0) {
50 printf("no certs found in %s\n", f.name().latin1());
51 return list;
52 }
53
54 int num = 0;
55 for(int n = 0; n < (int)cl.count(); ++n) {
56 QCA::Cert *cert = new QCA::Cert(readCertXml(cl.item(n).toElement()));
57 if(cert->isNull()) {
58 printf("error reading cert\n");
59 delete cert;
60 continue;
61 }
62
63 ++num;
64 list.append(cert);
65 }
66 printf("imported %d root certs\n", num);
67
68 return list;
69}
70
71QString resultToString(int result)
72{
73 QString s;
74 switch(result) {
75 case QCA::TLS::NoCert:
76 s = QObject::tr("No certificate presented.");
77 break;
78 case QCA::TLS::Valid:
79 break;
80 case QCA::TLS::HostMismatch:
81 s = QObject::tr("Hostname mismatch.");
82 break;
83 case QCA::TLS::Rejected:
84 s = QObject::tr("Root CA rejects the specified purpose.");
85 break;
86 case QCA::TLS::Untrusted:
87 s = QObject::tr("Not trusted for the specified purpose.");
88 break;
89 case QCA::TLS::SignatureFailed:
90 s = QObject::tr("Invalid signature.");
91 break;
92 case QCA::TLS::InvalidCA:
93 s = QObject::tr("Invalid CA certificate.");
94 break;
95 case QCA::TLS::InvalidPurpose:
96 s = QObject::tr("Invalid certificate purpose.");
97 break;
98 case QCA::TLS::SelfSigned:
99 s = QObject::tr("Certificate is self-signed.");
100 break;
101 case QCA::TLS::Revoked:
102 s = QObject::tr("Certificate has been revoked.");
103 break;
104 case QCA::TLS::PathLengthExceeded:
105 s = QObject::tr("Maximum cert chain length exceeded.");
106 break;
107 case QCA::TLS::Expired:
108 s = QObject::tr("Certificate has expired.");
109 break;
110 case QCA::TLS::Unknown:
111 default:
112 s = QObject::tr("General validation error.");
113 break;
114 }
115 return s;
116}
117
118class SecureTest : public QObject
119{
120 Q_OBJECT
121public:
122 SecureTest()
123 {
124 sock = new QSocket;
125 connect(sock, SIGNAL(connected()), SLOT(sock_connected()));
126 connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
127 connect(sock, SIGNAL(connectionClosed()), SLOT(sock_connectionClosed()));
128 connect(sock, SIGNAL(error(int)), SLOT(sock_error(int)));
129
130 ssl = new QCA::TLS;
131 connect(ssl, SIGNAL(handshaken()), SLOT(ssl_handshaken()));
132 connect(ssl, SIGNAL(readyRead()), SLOT(ssl_readyRead()));
133 connect(ssl, SIGNAL(readyReadOutgoing(int)), SLOT(ssl_readyReadOutgoing(int)));
134 connect(ssl, SIGNAL(closed()), SLOT(ssl_closed()));
135 connect(ssl, SIGNAL(error(int)), SLOT(ssl_error(int)));
136
137 rootCerts.setAutoDelete(true);
138 rootCerts = getRootCerts("/usr/local/share/psi/certs/rootcert.xml");
139 }
140
141 ~SecureTest()
142 {
143 delete ssl;
144 delete sock;
145 }
146
147 void start(const QString &_host)
148 {
149 int n = _host.find(':');
150 int port;
151 if(n != -1) {
152 host = _host.mid(0, n);
153 port = _host.mid(n+1).toInt();
154 }
155 else {
156 host = _host;
157 port = 443;
158 }
159
160 printf("Trying %s:%d...\n", host.latin1(), port);
161 sock->connectToHost(host, port);
162 }
163
164signals:
165 void quit();
166
167private slots:
168 void sock_connected()
169 {
170 printf("Connected, starting TLS handshake...\n");
171 ssl->setCertificateStore(rootCerts);
172 ssl->startClient(host);
173 }
174
175 void sock_readyRead()
176 {
177 QByteArray buf(sock->bytesAvailable());
178 int num = sock->readBlock(buf.data(), buf.size());
179 if(num < (int)buf.size())
180 buf.resize(num);
181 ssl->writeIncoming(buf);
182 }
183
184 void sock_connectionClosed()
185 {
186 printf("\nConnection closed.\n");
187 quit();
188 }
189
190 void sock_error(int)
191 {
192 printf("\nSocket error.\n");
193 quit();
194 }
195
196 void ssl_handshaken()
197 {
198 cert = ssl->peerCertificate();
199 int vr = ssl->certificateValidityResult();
200
201 printf("Successful SSL handshake.\n");
202 if(!cert.isNull())
203 showCertInfo(cert);
204 if(vr == QCA::TLS::Valid)
205 printf("Valid certificate.\n");
206 else
207 printf("Invalid certificate: %s\n", resultToString(vr).latin1());
208
209 printf("Let's try a GET request now.\n");
210 QString req = "GET / HTTP/1.0\nHost: " + host + "\n\n";
211 QCString cs = req.latin1();
212 QByteArray buf(cs.length());
213 memcpy(buf.data(), cs.data(), buf.size());
214 ssl->write(buf);
215 }
216
217 void ssl_readyRead()
218 {
219 QByteArray a = ssl->read();
220 QCString cs;
221 cs.resize(a.size()+1);
222 memcpy(cs.data(), a.data(), a.size());
223 printf("%s", cs.data());
224 }
225
226 void ssl_readyReadOutgoing(int)
227 {
228 QByteArray a = ssl->readOutgoing();
229 sock->writeBlock(a.data(), a.size());
230 }
231
232 void ssl_closed()
233 {
234 printf("SSL session closed\n");
235 }
236
237 void ssl_error(int x)
238 {
239 if(x == QCA::TLS::ErrHandshake) {
240 printf("SSL Handshake Error!\n");
241 quit();
242 }
243 else {
244 printf("SSL Error!\n");
245 quit();
246 }
247 }
248
249private:
250 QString host;
251 QSocket *sock;
252 QCA::TLS *ssl;
253 QCA::Cert cert;
254 QPtrList<QCA::Cert> rootCerts;
255};
256
257#include"ssltest.moc"
258
259int main(int argc, char **argv)
260{
261 QApplication app(argc, argv, false);
262 QString host = argc > 1 ? argv[1] : "andbit.net";
263
264 if(!QCA::isSupported(QCA::CAP_TLS)) {
265 printf("TLS not supported!\n");
266 return 1;
267 }
268
269 SecureTest *s = new SecureTest;
270 QObject::connect(s, SIGNAL(quit()), &app, SLOT(quit()));
271 s->start(host);
272 app.exec();
273 delete s;
274
275 return 0;
276}
Note: See TracBrowser for help on using the repository browser.