xref: /minix3/crypto/external/bsd/openssl/dist/demos/state_machine/state_machine.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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