source: qca/trunk/examples/sslservtest/sslservtest.cpp

Last change on this file 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: 7.0 KB
Line 
1#include<qapplication.h>
2#include<qfile.h>
3#include<qsocket.h>
4#include<qserversocket.h>
5#include<qvaluelist.h>
6#include<qtimer.h>
7#include"qca.h"
8
9char pemdata_cert[] =
10 "-----BEGIN CERTIFICATE-----\n"
11 "MIIDbjCCAtegAwIBAgIBADANBgkqhkiG9w0BAQQFADCBhzELMAkGA1UEBhMCVVMx\n"
12 "EzARBgNVBAgTCkNhbGlmb3JuaWExDzANBgNVBAcTBklydmluZTEYMBYGA1UEChMP\n"
13 "RXhhbXBsZSBDb21wYW55MRQwEgYDVQQDEwtleGFtcGxlLmNvbTEiMCAGCSqGSIb3\n"
14 "DQEJARYTZXhhbXBsZUBleGFtcGxlLmNvbTAeFw0wMzA3MjQwNzMwMDBaFw0wMzA4\n"
15 "MjMwNzMwMDBaMIGHMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEP\n"
16 "MA0GA1UEBxMGSXJ2aW5lMRgwFgYDVQQKEw9FeGFtcGxlIENvbXBhbnkxFDASBgNV\n"
17 "BAMTC2V4YW1wbGUuY29tMSIwIAYJKoZIhvcNAQkBFhNleGFtcGxlQGV4YW1wbGUu\n"
18 "Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCobzCF268K2sRp473gvBTT\n"
19 "4AgSL1kjeF8N57vxS1P8zWrWMXNs4LuH0NRZmKTajeboy0br8xw+smIy3AbaKAwW\n"
20 "WZToesxebu3m9VeA8dqWyOaUMjoxAcgVYesgVaMpjRe7fcWdJnX1wJoVVPuIcO8m\n"
21 "a+AAPByfTORbzpSTmXAQAwIDAQABo4HnMIHkMB0GA1UdDgQWBBTvFierzLmmYMq0\n"
22 "cB/+5rK1bNR56zCBtAYDVR0jBIGsMIGpgBTvFierzLmmYMq0cB/+5rK1bNR566GB\n"
23 "jaSBijCBhzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDzANBgNV\n"
24 "BAcTBklydmluZTEYMBYGA1UEChMPRXhhbXBsZSBDb21wYW55MRQwEgYDVQQDEwtl\n"
25 "eGFtcGxlLmNvbTEiMCAGCSqGSIb3DQEJARYTZXhhbXBsZUBleGFtcGxlLmNvbYIB\n"
26 "ADAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4GBAGqGhXf7xNOnYNtFO7gz\n"
27 "K6RdZGHFI5q1DAEz4hhNBC9uElh32XGX4wN7giz3zLC8v9icL/W4ff/K5NDfv3Gf\n"
28 "gQe/+Wo9Be3H3ul6uwPPFnx4+PIOF2a5TW99H9smyxWdNjnFtcUte4al3RszcMWG\n"
29 "x3iqsWosGtj6F+ridmKoqKLu\n"
30 "-----END CERTIFICATE-----\n";
31
32char pemdata_privkey[] =
33 "-----BEGIN RSA PRIVATE KEY-----\n"
34 "MIICXAIBAAKBgQCobzCF268K2sRp473gvBTT4AgSL1kjeF8N57vxS1P8zWrWMXNs\n"
35 "4LuH0NRZmKTajeboy0br8xw+smIy3AbaKAwWWZToesxebu3m9VeA8dqWyOaUMjox\n"
36 "AcgVYesgVaMpjRe7fcWdJnX1wJoVVPuIcO8ma+AAPByfTORbzpSTmXAQAwIDAQAB\n"
37 "AoGAP83u+aYghuIcaWhmM03MLf69z/WztKYSi/fu0BcS977w67bL3MC9CVPoPRB/\n"
38 "0nLSt/jZIuRzHKUCYfXLerSU7v0oXDTy6GPzWMh/oXIrpF0tYNbwWF7LSq2O2gGZ\n"
39 "XtA9MSmUNNJaKzQQeXjqdVFOY8A0Pho+k2KByBiCi+ChkcECQQDRUuyX0+PKJtA2\n"
40 "M36BOTFpy61BAv+JRlXUnHuevOfQWl6NR6YGygqCyH1sWtP1sa9S4wWys3DFH+5A\n"
41 "DkuAqk7zAkEAzf4eUH2hp5CIMsXH+WpIzKj09oY1it2CAKjVq4rUELf8iXvmGoFl\n"
42 "000spua4MjHNUYm7LR0QaKesKrMyGZUesQJAL8aLdYPJI+SD9Tr/jqLtIkZ4frQe\n"
43 "eshw4pvsoyheiHF3zyshO791crAr4EVCx3sMlxB1xnmqLXPCPyCEHxO//QJBAIBY\n"
44 "IYkjDZJ6ofGIe1UyXJNvfdkPu9J+ut4wU5jjEcgs6mK62J6RGuFxhy2iOQfFMdjo\n"
45 "yL+OCUg7mDCun7uCxrECQAtSvnLOFMjO5qExRjFtwi+b1rcSekd3Osk/izyRFSzg\n"
46 "Or+AL56/EKfiogNnFipgaXIbb/xj785Cob6v96XoW1I=\n"
47 "-----END RSA PRIVATE KEY-----\n";
48
49class LayerTracker
50{
51public:
52 struct Item
53 {
54 int plain;
55 int encoded;
56 };
57
58 LayerTracker()
59 {
60 p = 0;
61 }
62
63 void reset()
64 {
65 p = 0;
66 list.clear();
67 }
68
69 void addPlain(int plain)
70 {
71 p += plain;
72 }
73
74 void specifyEncoded(int encoded, int plain)
75 {
76 // can't specify more bytes than we have
77 if(plain > p)
78 plain = p;
79 p -= plain;
80 Item i;
81 i.plain = plain;
82 i.encoded = encoded;
83 list += i;
84 }
85
86 int finished(int encoded)
87 {
88 int plain = 0;
89 for(QValueList<Item>::Iterator it = list.begin(); it != list.end();) {
90 Item &i = *it;
91
92 // not enough?
93 if(encoded < i.encoded) {
94 i.encoded -= encoded;
95 break;
96 }
97
98 encoded -= i.encoded;
99 plain += i.plain;
100 it = list.remove(it);
101 }
102 return plain;
103 }
104
105 int p;
106 QValueList<Item> list;
107};
108
109class SecureServerTest : public QServerSocket
110{
111 Q_OBJECT
112public:
113 enum { Idle, Handshaking, Active, Closing };
114
115 SecureServerTest(int _port) : QServerSocket(_port), port(_port)
116 {
117 sock = new QSocket;
118 connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
119 connect(sock, SIGNAL(connectionClosed()), SLOT(sock_connectionClosed()));
120 connect(sock, SIGNAL(error(int)), SLOT(sock_error(int)));
121 connect(sock, SIGNAL(bytesWritten(int)), SLOT(sock_bytesWritten(int)));
122
123 ssl = new QCA::TLS;
124 connect(ssl, SIGNAL(handshaken()), SLOT(ssl_handshaken()));
125 connect(ssl, SIGNAL(readyRead()), SLOT(ssl_readyRead()));
126 connect(ssl, SIGNAL(readyReadOutgoing(int)), SLOT(ssl_readyReadOutgoing(int)));
127 connect(ssl, SIGNAL(closed()), SLOT(ssl_closed()));
128 connect(ssl, SIGNAL(error(int)), SLOT(ssl_error(int)));
129
130 cert.fromPEM(pemdata_cert);
131 privkey.fromPEM(pemdata_privkey);
132
133 mode = Idle;
134 }
135
136 ~SecureServerTest()
137 {
138 delete ssl;
139 delete sock;
140 }
141
142 void start()
143 {
144 if(cert.isNull() || privkey.isNull()) {
145 printf("Error loading cert and/or private key!\n");
146 QTimer::singleShot(0, this, SIGNAL(quit()));
147 return;
148 }
149 if(!ok()) {
150 printf("Error binding to port %d!\n", port);
151 QTimer::singleShot(0, this, SIGNAL(quit()));
152 return;
153 }
154 printf("Listening on port %d ...\n", port);
155 }
156
157 void newConnection(int s)
158 {
159 // Note: only 1 connection supported at a time in this example!
160 if(sock->isOpen()) {
161 QSocket tmp;
162 tmp.setSocket(s);
163 printf("throwing away extra connection\n");
164 return;
165 }
166 mode = Handshaking;
167 sock->setSocket(s);
168 printf("Connection received! Starting TLS handshake...\n");
169 ssl->setCertificate(cert, privkey);
170 ssl->startServer();
171 }
172
173signals:
174 void quit();
175
176private slots:
177 void sock_readyRead()
178 {
179 QByteArray buf(sock->bytesAvailable());
180 int num = sock->readBlock(buf.data(), buf.size());
181 if(num < (int)buf.size())
182 buf.resize(num);
183 ssl->writeIncoming(buf);
184 }
185
186 void sock_connectionClosed()
187 {
188 printf("Connection closed.\n");
189 }
190
191 void sock_bytesWritten(int x)
192 {
193 if(mode == Active && sent) {
194 int bytes = layer.finished(x);
195 bytesLeft -= bytes;
196
197 if(bytesLeft == 0) {
198 mode = Closing;
199 printf("SSL shutdown\n");
200 ssl->close();
201 }
202 }
203 }
204
205 void sock_error(int)
206 {
207 printf("Socket error.\n");
208 }
209
210 void ssl_handshaken()
211 {
212 printf("Successful SSL handshake. Waiting for newline.\n");
213 layer.reset();
214 bytesLeft = 0;
215 sent = false;
216 mode = Active;
217 }
218
219 void ssl_readyRead()
220 {
221 QByteArray a = ssl->read();
222 QString str =
223 "<html>\n"
224 "<head><title>Test</title></head>\n"
225 "<body>this is only a test</body>\n"
226 "</html>\n";
227 QCString cs = str.latin1();
228 QByteArray b(cs.length());
229 memcpy(b.data(), cs.data(), b.size());
230
231 printf("Sending test response...\n");
232 sent = true;
233 layer.addPlain(b.size());
234 ssl->write(b);
235 }
236
237 void ssl_readyReadOutgoing(int plainBytes)
238 {
239 QByteArray a = ssl->readOutgoing();
240 layer.specifyEncoded(a.size(), plainBytes);
241 sock->writeBlock(a.data(), a.size());
242 }
243
244 void ssl_closed()
245 {
246 printf("Closing.\n");
247 sock->close();
248 }
249
250 void ssl_error(int x)
251 {
252 if(x == QCA::TLS::ErrHandshake) {
253 printf("SSL Handshake Error! Closing.\n");
254 sock->close();
255 }
256 else {
257 printf("SSL Error! Closing.\n");
258 sock->close();
259 }
260 }
261
262private:
263 int port;
264 QSocket *sock;
265 QCA::TLS *ssl;
266 QCA::Cert cert;
267 QCA::RSAKey privkey;
268
269 bool sent;
270 int mode;
271 int bytesLeft;
272 LayerTracker layer;
273};
274
275#include"sslservtest.moc"
276
277int main(int argc, char **argv)
278{
279 QApplication app(argc, argv, false);
280 int port = argc > 1 ? QString(argv[1]).toInt() : 8000;
281
282 if(!QCA::isSupported(QCA::CAP_TLS)) {
283 printf("TLS not supported!\n");
284 return 1;
285 }
286
287 SecureServerTest *s = new SecureServerTest(port);
288 QObject::connect(s, SIGNAL(quit()), &app, SLOT(quit()));
289 s->start();
290 app.exec();
291 delete s;
292
293 return 0;
294}
Note: See TracBrowser for help on using the repository browser.