1ebfedea0SLionel Sambuc /* ====================================================================
2ebfedea0SLionel Sambuc * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
3ebfedea0SLionel Sambuc *
4ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without
5ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions
6ebfedea0SLionel Sambuc * are met:
7ebfedea0SLionel Sambuc *
8ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
9ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer.
10ebfedea0SLionel Sambuc *
11ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
12ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in
13ebfedea0SLionel Sambuc * the documentation and/or other materials provided with the
14ebfedea0SLionel Sambuc * distribution.
15ebfedea0SLionel Sambuc *
16ebfedea0SLionel Sambuc * 3. All advertising materials mentioning features or use of this
17ebfedea0SLionel Sambuc * software must display the following acknowledgment:
18ebfedea0SLionel Sambuc * "This product includes software developed by the OpenSSL Project
19ebfedea0SLionel Sambuc * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20ebfedea0SLionel Sambuc *
21ebfedea0SLionel Sambuc * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22ebfedea0SLionel Sambuc * endorse or promote products derived from this software without
23ebfedea0SLionel Sambuc * prior written permission. For written permission, please contact
24ebfedea0SLionel Sambuc * openssl-core@openssl.org.
25ebfedea0SLionel Sambuc *
26ebfedea0SLionel Sambuc * 5. Products derived from this software may not be called "OpenSSL"
27ebfedea0SLionel Sambuc * nor may "OpenSSL" appear in their names without prior written
28ebfedea0SLionel Sambuc * permission of the OpenSSL Project.
29ebfedea0SLionel Sambuc *
30ebfedea0SLionel Sambuc * 6. Redistributions of any form whatsoever must retain the following
31ebfedea0SLionel Sambuc * acknowledgment:
32ebfedea0SLionel Sambuc * "This product includes software developed by the OpenSSL Project
33ebfedea0SLionel Sambuc * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34ebfedea0SLionel Sambuc *
35ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36ebfedea0SLionel Sambuc * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37ebfedea0SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38ebfedea0SLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
39ebfedea0SLionel Sambuc * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40ebfedea0SLionel Sambuc * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41ebfedea0SLionel Sambuc * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42ebfedea0SLionel Sambuc * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43ebfedea0SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44ebfedea0SLionel Sambuc * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45ebfedea0SLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46ebfedea0SLionel Sambuc * OF THE POSSIBILITY OF SUCH DAMAGE.
47ebfedea0SLionel Sambuc * ====================================================================
48ebfedea0SLionel Sambuc *
49ebfedea0SLionel Sambuc * This product includes cryptographic software written by Eric Young
50ebfedea0SLionel Sambuc * (eay@cryptsoft.com). This product includes software written by Tim
51ebfedea0SLionel Sambuc * Hudson (tjh@cryptsoft.com).
52ebfedea0SLionel Sambuc *
53ebfedea0SLionel Sambuc */
54ebfedea0SLionel Sambuc
55ebfedea0SLionel Sambuc /*
56ebfedea0SLionel Sambuc * Nuron, a leader in hardware encryption technology, generously
57ebfedea0SLionel Sambuc * sponsored the development of this demo by Ben Laurie.
58ebfedea0SLionel Sambuc *
59ebfedea0SLionel Sambuc * See http://www.nuron.com/.
60ebfedea0SLionel Sambuc */
61ebfedea0SLionel Sambuc
62ebfedea0SLionel Sambuc /*
63ebfedea0SLionel Sambuc * the aim of this demo is to provide a fully working state-machine
64ebfedea0SLionel Sambuc * style SSL implementation, i.e. one where the main loop acquires
65ebfedea0SLionel Sambuc * some data, then converts it from or to SSL by feeding it into the
66ebfedea0SLionel Sambuc * SSL state machine. It then does any I/O required by the state machine
67ebfedea0SLionel Sambuc * and loops.
68ebfedea0SLionel Sambuc *
69ebfedea0SLionel Sambuc * In order to keep things as simple as possible, this implementation
70ebfedea0SLionel Sambuc * listens on a TCP socket, which it expects to get an SSL connection
71ebfedea0SLionel Sambuc * on (for example, from s_client) and from then on writes decrypted
72ebfedea0SLionel Sambuc * data to stdout and encrypts anything arriving on stdin. Verbose
73ebfedea0SLionel Sambuc * commentary is written to stderr.
74ebfedea0SLionel Sambuc *
75ebfedea0SLionel Sambuc * This implementation acts as a server, but it can also be done for a client. */
76ebfedea0SLionel Sambuc
77ebfedea0SLionel Sambuc #include <openssl/ssl.h>
78ebfedea0SLionel Sambuc #include <assert.h>
79ebfedea0SLionel Sambuc #include <unistd.h>
80ebfedea0SLionel Sambuc #include <string.h>
81ebfedea0SLionel Sambuc #include <openssl/err.h>
82ebfedea0SLionel Sambuc #include <sys/types.h>
83ebfedea0SLionel Sambuc #include <sys/socket.h>
84ebfedea0SLionel Sambuc #include <netinet/in.h>
85ebfedea0SLionel Sambuc
86*0a6a1f1dSLionel Sambuc /*
87*0a6a1f1dSLionel Sambuc * die_unless is intended to work like assert, except that it happens always,
88*0a6a1f1dSLionel Sambuc * even if NDEBUG is defined. Use assert as a stopgap.
89*0a6a1f1dSLionel Sambuc */
90ebfedea0SLionel Sambuc
91ebfedea0SLionel Sambuc #define die_unless(x) assert(x)
92ebfedea0SLionel Sambuc
93*0a6a1f1dSLionel Sambuc typedef struct {
94ebfedea0SLionel Sambuc SSL_CTX *pCtx;
95ebfedea0SLionel Sambuc BIO *pbioRead;
96ebfedea0SLionel Sambuc BIO *pbioWrite;
97ebfedea0SLionel Sambuc SSL *pSSL;
98ebfedea0SLionel Sambuc } SSLStateMachine;
99ebfedea0SLionel Sambuc
SSLStateMachine_print_error(SSLStateMachine * pMachine,const char * szErr)100*0a6a1f1dSLionel Sambuc void SSLStateMachine_print_error(SSLStateMachine * pMachine,
101*0a6a1f1dSLionel Sambuc const char *szErr)
102ebfedea0SLionel Sambuc {
103ebfedea0SLionel Sambuc unsigned long l;
104ebfedea0SLionel Sambuc
105ebfedea0SLionel Sambuc fprintf(stderr, "%s\n", szErr);
106*0a6a1f1dSLionel Sambuc while ((l = ERR_get_error())) {
107ebfedea0SLionel Sambuc char buf[1024];
108ebfedea0SLionel Sambuc
109ebfedea0SLionel Sambuc ERR_error_string_n(l, buf, sizeof buf);
110ebfedea0SLionel Sambuc fprintf(stderr, "Error %lx: %s\n", l, buf);
111ebfedea0SLionel Sambuc }
112ebfedea0SLionel Sambuc }
113ebfedea0SLionel Sambuc
SSLStateMachine_new(const char * szCertificateFile,const char * szKeyFile)114ebfedea0SLionel Sambuc SSLStateMachine *SSLStateMachine_new(const char *szCertificateFile,
115ebfedea0SLionel Sambuc const char *szKeyFile)
116ebfedea0SLionel Sambuc {
117ebfedea0SLionel Sambuc SSLStateMachine *pMachine = malloc(sizeof *pMachine);
118ebfedea0SLionel Sambuc int n;
119ebfedea0SLionel Sambuc
120ebfedea0SLionel Sambuc die_unless(pMachine);
121ebfedea0SLionel Sambuc
122ebfedea0SLionel Sambuc pMachine->pCtx = SSL_CTX_new(SSLv23_server_method());
123ebfedea0SLionel Sambuc die_unless(pMachine->pCtx);
124ebfedea0SLionel Sambuc
125ebfedea0SLionel Sambuc n = SSL_CTX_use_certificate_file(pMachine->pCtx, szCertificateFile,
126ebfedea0SLionel Sambuc SSL_FILETYPE_PEM);
127ebfedea0SLionel Sambuc die_unless(n > 0);
128ebfedea0SLionel Sambuc
129*0a6a1f1dSLionel Sambuc n = SSL_CTX_use_PrivateKey_file(pMachine->pCtx, szKeyFile,
130*0a6a1f1dSLionel Sambuc SSL_FILETYPE_PEM);
131ebfedea0SLionel Sambuc die_unless(n > 0);
132ebfedea0SLionel Sambuc
133ebfedea0SLionel Sambuc pMachine->pSSL = SSL_new(pMachine->pCtx);
134ebfedea0SLionel Sambuc die_unless(pMachine->pSSL);
135ebfedea0SLionel Sambuc
136ebfedea0SLionel Sambuc pMachine->pbioRead = BIO_new(BIO_s_mem());
137ebfedea0SLionel Sambuc
138ebfedea0SLionel Sambuc pMachine->pbioWrite = BIO_new(BIO_s_mem());
139ebfedea0SLionel Sambuc
140ebfedea0SLionel Sambuc SSL_set_bio(pMachine->pSSL, pMachine->pbioRead, pMachine->pbioWrite);
141ebfedea0SLionel Sambuc
142ebfedea0SLionel Sambuc SSL_set_accept_state(pMachine->pSSL);
143ebfedea0SLionel Sambuc
144ebfedea0SLionel Sambuc return pMachine;
145ebfedea0SLionel Sambuc }
146ebfedea0SLionel Sambuc
SSLStateMachine_read_inject(SSLStateMachine * pMachine,const unsigned char * aucBuf,int nBuf)147ebfedea0SLionel Sambuc void SSLStateMachine_read_inject(SSLStateMachine * pMachine,
148ebfedea0SLionel Sambuc const unsigned char *aucBuf, int nBuf)
149ebfedea0SLionel Sambuc {
150ebfedea0SLionel Sambuc int n = BIO_write(pMachine->pbioRead, aucBuf, nBuf);
151*0a6a1f1dSLionel Sambuc /*
152*0a6a1f1dSLionel Sambuc * If it turns out this assert fails, then buffer the data here and just
153*0a6a1f1dSLionel Sambuc * feed it in in churn instead. Seems to me that it should be guaranteed
154*0a6a1f1dSLionel Sambuc * to succeed, though.
155ebfedea0SLionel Sambuc */
156ebfedea0SLionel Sambuc assert(n == nBuf);
157ebfedea0SLionel Sambuc fprintf(stderr, "%d bytes of encrypted data fed to state machine\n", n);
158ebfedea0SLionel Sambuc }
159ebfedea0SLionel Sambuc
SSLStateMachine_read_extract(SSLStateMachine * pMachine,unsigned char * aucBuf,int nBuf)160ebfedea0SLionel Sambuc int SSLStateMachine_read_extract(SSLStateMachine * pMachine,
161ebfedea0SLionel Sambuc unsigned char *aucBuf, int nBuf)
162ebfedea0SLionel Sambuc {
163ebfedea0SLionel Sambuc int n;
164ebfedea0SLionel Sambuc
165*0a6a1f1dSLionel Sambuc if (!SSL_is_init_finished(pMachine->pSSL)) {
166ebfedea0SLionel Sambuc fprintf(stderr, "Doing SSL_accept\n");
167ebfedea0SLionel Sambuc n = SSL_accept(pMachine->pSSL);
168ebfedea0SLionel Sambuc if (n == 0)
169ebfedea0SLionel Sambuc fprintf(stderr, "SSL_accept returned zero\n");
170*0a6a1f1dSLionel Sambuc if (n < 0) {
171ebfedea0SLionel Sambuc int err;
172ebfedea0SLionel Sambuc
173*0a6a1f1dSLionel Sambuc if ((err =
174*0a6a1f1dSLionel Sambuc SSL_get_error(pMachine->pSSL, n)) == SSL_ERROR_WANT_READ) {
175ebfedea0SLionel Sambuc fprintf(stderr, "SSL_accept wants more data\n");
176ebfedea0SLionel Sambuc return 0;
177ebfedea0SLionel Sambuc }
178ebfedea0SLionel Sambuc
179ebfedea0SLionel Sambuc SSLStateMachine_print_error(pMachine, "SSL_accept error");
180ebfedea0SLionel Sambuc exit(7);
181ebfedea0SLionel Sambuc }
182ebfedea0SLionel Sambuc return 0;
183ebfedea0SLionel Sambuc }
184ebfedea0SLionel Sambuc
185ebfedea0SLionel Sambuc n = SSL_read(pMachine->pSSL, aucBuf, nBuf);
186*0a6a1f1dSLionel Sambuc if (n < 0) {
187ebfedea0SLionel Sambuc int err = SSL_get_error(pMachine->pSSL, n);
188ebfedea0SLionel Sambuc
189*0a6a1f1dSLionel Sambuc if (err == SSL_ERROR_WANT_READ) {
190ebfedea0SLionel Sambuc fprintf(stderr, "SSL_read wants more data\n");
191ebfedea0SLionel Sambuc return 0;
192ebfedea0SLionel Sambuc }
193ebfedea0SLionel Sambuc
194ebfedea0SLionel Sambuc SSLStateMachine_print_error(pMachine, "SSL_read error");
195ebfedea0SLionel Sambuc exit(8);
196ebfedea0SLionel Sambuc }
197ebfedea0SLionel Sambuc
198*0a6a1f1dSLionel Sambuc fprintf(stderr, "%d bytes of decrypted data read from state machine\n",
199*0a6a1f1dSLionel Sambuc n);
200ebfedea0SLionel Sambuc return n;
201ebfedea0SLionel Sambuc }
202ebfedea0SLionel Sambuc
SSLStateMachine_write_can_extract(SSLStateMachine * pMachine)203ebfedea0SLionel Sambuc int SSLStateMachine_write_can_extract(SSLStateMachine * pMachine)
204ebfedea0SLionel Sambuc {
205ebfedea0SLionel Sambuc int n = BIO_pending(pMachine->pbioWrite);
206ebfedea0SLionel Sambuc if (n)
207ebfedea0SLionel Sambuc fprintf(stderr, "There is encrypted data available to write\n");
208ebfedea0SLionel Sambuc else
209ebfedea0SLionel Sambuc fprintf(stderr, "There is no encrypted data available to write\n");
210ebfedea0SLionel Sambuc
211ebfedea0SLionel Sambuc return n;
212ebfedea0SLionel Sambuc }
213ebfedea0SLionel Sambuc
SSLStateMachine_write_extract(SSLStateMachine * pMachine,unsigned char * aucBuf,int nBuf)214ebfedea0SLionel Sambuc int SSLStateMachine_write_extract(SSLStateMachine * pMachine,
215ebfedea0SLionel Sambuc unsigned char *aucBuf, int nBuf)
216ebfedea0SLionel Sambuc {
217ebfedea0SLionel Sambuc int n;
218ebfedea0SLionel Sambuc
219ebfedea0SLionel Sambuc n = BIO_read(pMachine->pbioWrite, aucBuf, nBuf);
220*0a6a1f1dSLionel Sambuc fprintf(stderr, "%d bytes of encrypted data read from state machine\n",
221*0a6a1f1dSLionel Sambuc n);
222ebfedea0SLionel Sambuc return n;
223ebfedea0SLionel Sambuc }
224ebfedea0SLionel Sambuc
SSLStateMachine_write_inject(SSLStateMachine * pMachine,const unsigned char * aucBuf,int nBuf)225ebfedea0SLionel Sambuc void SSLStateMachine_write_inject(SSLStateMachine * pMachine,
226ebfedea0SLionel Sambuc const unsigned char *aucBuf, int nBuf)
227ebfedea0SLionel Sambuc {
228ebfedea0SLionel Sambuc int n = SSL_write(pMachine->pSSL, aucBuf, nBuf);
229*0a6a1f1dSLionel Sambuc /*
230*0a6a1f1dSLionel Sambuc * If it turns out this assert fails, then buffer the data here and just
231*0a6a1f1dSLionel Sambuc * feed it in in churn instead. Seems to me that it should be guaranteed
232*0a6a1f1dSLionel Sambuc * to succeed, though.
233ebfedea0SLionel Sambuc */
234ebfedea0SLionel Sambuc assert(n == nBuf);
235ebfedea0SLionel Sambuc fprintf(stderr, "%d bytes of unencrypted data fed to state machine\n", n);
236ebfedea0SLionel Sambuc }
237ebfedea0SLionel Sambuc
OpenSocket(int nPort)238ebfedea0SLionel Sambuc int OpenSocket(int nPort)
239ebfedea0SLionel Sambuc {
240ebfedea0SLionel Sambuc int nSocket;
241ebfedea0SLionel Sambuc struct sockaddr_in saServer;
242ebfedea0SLionel Sambuc struct sockaddr_in saClient;
243ebfedea0SLionel Sambuc int one = 1;
244ebfedea0SLionel Sambuc int nSize;
245ebfedea0SLionel Sambuc int nFD;
246ebfedea0SLionel Sambuc int nLen;
247ebfedea0SLionel Sambuc
248ebfedea0SLionel Sambuc nSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
249*0a6a1f1dSLionel Sambuc if (nSocket < 0) {
250ebfedea0SLionel Sambuc perror("socket");
251ebfedea0SLionel Sambuc exit(1);
252ebfedea0SLionel Sambuc }
253ebfedea0SLionel Sambuc
254*0a6a1f1dSLionel Sambuc if (setsockopt
255*0a6a1f1dSLionel Sambuc (nSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof one) < 0) {
256ebfedea0SLionel Sambuc perror("setsockopt");
257ebfedea0SLionel Sambuc exit(2);
258ebfedea0SLionel Sambuc }
259ebfedea0SLionel Sambuc
260ebfedea0SLionel Sambuc memset(&saServer, 0, sizeof saServer);
261ebfedea0SLionel Sambuc saServer.sin_family = AF_INET;
262ebfedea0SLionel Sambuc saServer.sin_port = htons(nPort);
263ebfedea0SLionel Sambuc nSize = sizeof saServer;
264*0a6a1f1dSLionel Sambuc if (bind(nSocket, (struct sockaddr *)&saServer, nSize) < 0) {
265ebfedea0SLionel Sambuc perror("bind");
266ebfedea0SLionel Sambuc exit(3);
267ebfedea0SLionel Sambuc }
268ebfedea0SLionel Sambuc
269*0a6a1f1dSLionel Sambuc if (listen(nSocket, 512) < 0) {
270ebfedea0SLionel Sambuc perror("listen");
271ebfedea0SLionel Sambuc exit(4);
272ebfedea0SLionel Sambuc }
273ebfedea0SLionel Sambuc
274ebfedea0SLionel Sambuc nLen = sizeof saClient;
275ebfedea0SLionel Sambuc nFD = accept(nSocket, (struct sockaddr *)&saClient, &nLen);
276*0a6a1f1dSLionel Sambuc if (nFD < 0) {
277ebfedea0SLionel Sambuc perror("accept");
278ebfedea0SLionel Sambuc exit(5);
279ebfedea0SLionel Sambuc }
280ebfedea0SLionel Sambuc
281ebfedea0SLionel Sambuc fprintf(stderr, "Incoming accepted on port %d\n", nPort);
282ebfedea0SLionel Sambuc
283ebfedea0SLionel Sambuc return nFD;
284ebfedea0SLionel Sambuc }
285ebfedea0SLionel Sambuc
main(int argc,char ** argv)286ebfedea0SLionel Sambuc int main(int argc, char **argv)
287ebfedea0SLionel Sambuc {
288ebfedea0SLionel Sambuc SSLStateMachine *pMachine;
289ebfedea0SLionel Sambuc int nPort;
290ebfedea0SLionel Sambuc int nFD;
291ebfedea0SLionel Sambuc const char *szCertificateFile;
292ebfedea0SLionel Sambuc const char *szKeyFile;
293ebfedea0SLionel Sambuc char rbuf[1];
294ebfedea0SLionel Sambuc int nrbuf = 0;
295ebfedea0SLionel Sambuc
296*0a6a1f1dSLionel Sambuc if (argc != 4) {
297ebfedea0SLionel Sambuc fprintf(stderr, "%s <port> <certificate file> <key file>\n", argv[0]);
298ebfedea0SLionel Sambuc exit(6);
299ebfedea0SLionel Sambuc }
300ebfedea0SLionel Sambuc
301ebfedea0SLionel Sambuc nPort = atoi(argv[1]);
302ebfedea0SLionel Sambuc szCertificateFile = argv[2];
303ebfedea0SLionel Sambuc szKeyFile = argv[3];
304ebfedea0SLionel Sambuc
305ebfedea0SLionel Sambuc SSL_library_init();
306ebfedea0SLionel Sambuc OpenSSL_add_ssl_algorithms();
307ebfedea0SLionel Sambuc SSL_load_error_strings();
308ebfedea0SLionel Sambuc ERR_load_crypto_strings();
309ebfedea0SLionel Sambuc
310ebfedea0SLionel Sambuc nFD = OpenSocket(nPort);
311ebfedea0SLionel Sambuc
312ebfedea0SLionel Sambuc pMachine = SSLStateMachine_new(szCertificateFile, szKeyFile);
313ebfedea0SLionel Sambuc
314*0a6a1f1dSLionel Sambuc for (;;) {
315ebfedea0SLionel Sambuc fd_set rfds, wfds;
316ebfedea0SLionel Sambuc unsigned char buf[1024];
317ebfedea0SLionel Sambuc int n;
318ebfedea0SLionel Sambuc
319ebfedea0SLionel Sambuc FD_ZERO(&rfds);
320ebfedea0SLionel Sambuc FD_ZERO(&wfds);
321ebfedea0SLionel Sambuc
322ebfedea0SLionel Sambuc /* Select socket for input */
323ebfedea0SLionel Sambuc FD_SET(nFD, &rfds);
324ebfedea0SLionel Sambuc
325ebfedea0SLionel Sambuc /* check whether there's decrypted data */
326ebfedea0SLionel Sambuc if (!nrbuf)
327ebfedea0SLionel Sambuc nrbuf = SSLStateMachine_read_extract(pMachine, rbuf, 1);
328ebfedea0SLionel Sambuc
329ebfedea0SLionel Sambuc /* if there's decrypted data, check whether we can write it */
330ebfedea0SLionel Sambuc if (nrbuf)
331ebfedea0SLionel Sambuc FD_SET(1, &wfds);
332ebfedea0SLionel Sambuc
333ebfedea0SLionel Sambuc /* Select socket for output */
334ebfedea0SLionel Sambuc if (SSLStateMachine_write_can_extract(pMachine))
335ebfedea0SLionel Sambuc FD_SET(nFD, &wfds);
336ebfedea0SLionel Sambuc
337ebfedea0SLionel Sambuc /* Select stdin for input */
338ebfedea0SLionel Sambuc FD_SET(0, &rfds);
339ebfedea0SLionel Sambuc
340ebfedea0SLionel Sambuc /* Wait for something to do something */
341ebfedea0SLionel Sambuc n = select(nFD + 1, &rfds, &wfds, NULL, NULL);
342ebfedea0SLionel Sambuc assert(n > 0);
343ebfedea0SLionel Sambuc
344ebfedea0SLionel Sambuc /* Socket is ready for input */
345*0a6a1f1dSLionel Sambuc if (FD_ISSET(nFD, &rfds)) {
346ebfedea0SLionel Sambuc n = read(nFD, buf, sizeof buf);
347*0a6a1f1dSLionel Sambuc if (n == 0) {
348ebfedea0SLionel Sambuc fprintf(stderr, "Got EOF on socket\n");
349ebfedea0SLionel Sambuc exit(0);
350ebfedea0SLionel Sambuc }
351ebfedea0SLionel Sambuc assert(n > 0);
352ebfedea0SLionel Sambuc
353ebfedea0SLionel Sambuc SSLStateMachine_read_inject(pMachine, buf, n);
354ebfedea0SLionel Sambuc }
355ebfedea0SLionel Sambuc
356ebfedea0SLionel Sambuc /* stdout is ready for output (and hence we have some to send it) */
357*0a6a1f1dSLionel Sambuc if (FD_ISSET(1, &wfds)) {
358ebfedea0SLionel Sambuc assert(nrbuf == 1);
359ebfedea0SLionel Sambuc buf[0] = rbuf[0];
360ebfedea0SLionel Sambuc nrbuf = 0;
361ebfedea0SLionel Sambuc
362*0a6a1f1dSLionel Sambuc n = SSLStateMachine_read_extract(pMachine, buf + 1,
363*0a6a1f1dSLionel Sambuc sizeof buf - 1);
364*0a6a1f1dSLionel Sambuc if (n < 0) {
365ebfedea0SLionel Sambuc SSLStateMachine_print_error(pMachine, "read extract failed");
366ebfedea0SLionel Sambuc break;
367ebfedea0SLionel Sambuc }
368ebfedea0SLionel Sambuc assert(n >= 0);
369ebfedea0SLionel Sambuc ++n;
370*0a6a1f1dSLionel Sambuc if (n > 0) { /* FIXME: has to be true now */
371ebfedea0SLionel Sambuc int w;
372ebfedea0SLionel Sambuc
373ebfedea0SLionel Sambuc w = write(1, buf, n);
374ebfedea0SLionel Sambuc /* FIXME: we should push back any unwritten data */
375ebfedea0SLionel Sambuc assert(w == n);
376ebfedea0SLionel Sambuc }
377ebfedea0SLionel Sambuc }
378ebfedea0SLionel Sambuc
379*0a6a1f1dSLionel Sambuc /*
380*0a6a1f1dSLionel Sambuc * Socket is ready for output (and therefore we have output to send)
381*0a6a1f1dSLionel Sambuc */
382*0a6a1f1dSLionel Sambuc if (FD_ISSET(nFD, &wfds)) {
383ebfedea0SLionel Sambuc int w;
384ebfedea0SLionel Sambuc
385ebfedea0SLionel Sambuc n = SSLStateMachine_write_extract(pMachine, buf, sizeof buf);
386ebfedea0SLionel Sambuc assert(n > 0);
387ebfedea0SLionel Sambuc
388ebfedea0SLionel Sambuc w = write(nFD, buf, n);
389ebfedea0SLionel Sambuc /* FIXME: we should push back any unwritten data */
390ebfedea0SLionel Sambuc assert(w == n);
391ebfedea0SLionel Sambuc }
392ebfedea0SLionel Sambuc
393ebfedea0SLionel Sambuc /* Stdin is ready for input */
394*0a6a1f1dSLionel Sambuc if (FD_ISSET(0, &rfds)) {
395ebfedea0SLionel Sambuc n = read(0, buf, sizeof buf);
396*0a6a1f1dSLionel Sambuc if (n == 0) {
397ebfedea0SLionel Sambuc fprintf(stderr, "Got EOF on stdin\n");
398ebfedea0SLionel Sambuc exit(0);
399ebfedea0SLionel Sambuc }
400ebfedea0SLionel Sambuc assert(n > 0);
401ebfedea0SLionel Sambuc
402ebfedea0SLionel Sambuc SSLStateMachine_write_inject(pMachine, buf, n);
403ebfedea0SLionel Sambuc }
404ebfedea0SLionel Sambuc }
405ebfedea0SLionel Sambuc /* not reached */
406ebfedea0SLionel Sambuc return 0;
407ebfedea0SLionel Sambuc }
408