Another demo.
[openssl.git] / demos / easy_tls / test.c
1 /* test.c */
2 /* $Id: test.c,v 1.1 2001/09/17 19:06:59 bodo Exp $ */
3
4 #define L_PORT 9999
5 #define C_PORT 443
6
7 #include <arpa/inet.h>
8 #include <assert.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <netinet/in.h>
12 #include <netinet/tcp.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <sys/select.h>
17 #include <sys/socket.h>
18 #include <unistd.h>
19
20 #include "test.h"
21 #include "easy-tls.h"
22
23 void
24 test_process_init(int fd, int client_p, void *apparg)
25 {
26     fprintf(stderr, "test_process_init(fd = %d, client_p = %d, apparg = %p)\n", fd, client_p, apparg);
27 }
28
29 void
30 test_errflush(int child_p, char *errbuf, size_t num, void *apparg)
31 {
32     fputs(errbuf, stderr);
33 }
34
35
36 int
37 main(int argc, char *argv[])
38 {
39     int s, fd, r;
40     FILE *conn_in;
41     FILE *conn_out;
42     char buf[256];
43     SSL_CTX *ctx;
44     int client_p = 0;
45     int port;
46     int tls = 0;
47     char infobuf[TLS_INFO_SIZE + 1];
48
49     if (argc > 1 && argv[1][0] == '-') {
50         fputs("Usage: test [port]                   -- server\n"
51               "       test num.num.num.num [port]   -- client\n",
52               stderr);
53         exit(1);
54     }
55
56     if (argc > 1) {
57         if (strchr(argv[1], '.')) {
58             client_p = 1;
59         }
60     }
61     
62     fputs(client_p ? "Client\n" : "Server\n", stderr);
63     
64     {
65         struct tls_create_ctx_args a = tls_create_ctx_defaultargs();
66         a.client_p = client_p;
67         a.certificate_file = "cert.pem";
68         a.key_file = "cert.pem";
69         a.ca_file = "cacerts.pem";
70         
71         ctx = tls_create_ctx(a, NULL);
72         if (ctx == NULL)
73             exit(1);
74     }
75     
76     s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
77     if (s == -1) {
78         perror("socket");
79         exit(1);
80     }
81     
82     if (client_p) {
83         struct sockaddr_in addr;
84         size_t addr_len = sizeof addr;
85             
86         addr.sin_family = AF_INET;
87         assert(argc > 1);
88         if (argc > 2)
89             sscanf(argv[2], "%d", &port);
90         else
91             port = C_PORT;
92         addr.sin_port = htons(port);
93         addr.sin_addr.s_addr = inet_addr(argv[1]);
94             
95         r = connect(s, &addr, addr_len);
96         if (r != 0) {
97             perror("connect");
98             exit(1);
99         }
100         fd = s;
101         fprintf(stderr, "Connect (fd = %d).\n", fd);
102     } else {
103         /* server */
104         {
105             int i = 1;
106
107             r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *) &i, sizeof i);
108             if (r == -1) {
109                 perror("setsockopt");
110                 exit(1);
111             }
112         }
113         
114         {
115             struct sockaddr_in addr;
116             size_t addr_len = sizeof addr;
117             
118             if (argc > 1)
119                 sscanf(argv[1], "%d", &port);
120             else
121                 port = L_PORT;
122             addr.sin_family = AF_INET;
123             addr.sin_port = htons(port);
124             addr.sin_addr.s_addr = INADDR_ANY;
125             
126             r = bind(s, &addr, addr_len);
127             if (r != 0) {
128                 perror("bind");
129                 exit(1);
130             }
131         }
132     
133         r = listen(s, 1);
134         if (r == -1) {
135             perror("listen");
136             exit(1);
137         }
138
139         fprintf(stderr, "Listening at port %i.\n", port);
140         
141         fd = accept(s, NULL, 0);
142         if (fd == -1) {
143             perror("accept");
144             exit(1);
145         }
146         
147         fprintf(stderr, "Accept (fd = %d).\n", fd);
148     }
149
150     conn_in = fdopen(fd, "r");
151     if (conn_in == NULL) {
152         perror("fdopen");
153         exit(1);
154     }
155     conn_out = fdopen(fd, "w");
156     if (conn_out == NULL) {
157         perror("fdopen");
158         exit(1);
159     }
160
161     setvbuf(conn_in, NULL, _IOLBF, 256);
162     setvbuf(conn_out, NULL, _IOLBF, 256);
163         
164     while (fgets(buf, sizeof buf, stdin) != NULL) {
165         if (buf[0] == 'W') {
166             fprintf(conn_out, "%.*s\r\n", (int)(strlen(buf + 1) - 1), buf + 1);
167             fprintf(stderr, ">>> %.*s\n", (int)(strlen(buf + 1) - 1), buf + 1);
168         } else if (buf[0] == 'C') {
169             fprintf(stderr, "Closing.\n");
170             fclose(conn_in);
171             fclose(conn_out);
172             exit(0);
173         } else if (buf[0] == 'R') {
174             int lines = 0;
175
176             sscanf(buf + 1, "%d", &lines);
177             do {
178                 if (fgets(buf, sizeof buf, conn_in) == NULL) {
179                     if (ferror(conn_in)) {
180                         fprintf(stderr, "ERROR\n");
181                         exit(1);
182                     }
183                     fprintf(stderr, "CLOSED\n");
184                     return 0;
185                 }
186                 fprintf(stderr, "<<< %s", buf);
187             } while (--lines > 0);
188         } else if (buf[0] == 'T') {
189             int infofd;
190
191             tls++;
192             {
193                 struct tls_start_proxy_args a = tls_start_proxy_defaultargs();
194                 a.fd = fd;
195                 a.client_p = client_p;
196                 a.ctx = ctx;
197                 a.infofd = &infofd;
198                 r = tls_start_proxy(a, NULL);
199             }
200             assert(r != 1);
201             if (r != 0) {
202                 fprintf(stderr, "tls_start_proxy failed: %d\n", r);
203                 switch (r) {
204                 case -1:
205                     fputs("socketpair", stderr); break;
206                 case 2:
207                     fputs("FD_SETSIZE exceeded", stderr); break;
208                 case -3:
209                     fputs("pipe", stderr); break;
210                 case -4:
211                     fputs("fork", stderr); break;
212                 case -5:
213                     fputs("dup2", stderr); break;
214                 default:
215                     fputs("?", stderr);
216                 }
217                 if (r < 0)
218                     perror("");
219                 else
220                     fputc('\n', stderr);
221                 exit(1);
222             }
223             
224             r = read(infofd, infobuf, sizeof infobuf - 1);
225             if (r > 0) {
226                 const char *info = infobuf;
227                 const char *eol;
228                 
229                 infobuf[r] = '\0';
230                 while ((eol = strchr(info, '\n')) != NULL) {
231                     fprintf(stderr, "+++ `%.*s'\n", eol - info, info);
232                     info = eol+1;
233                 }
234                 close (infofd);
235             }
236         } else {
237             fprintf(stderr, "W...  write line to network\n"
238                     "R[n]  read line (n lines) from network\n"
239                     "C     close\n"
240                     "T     start %sTLS proxy\n", tls ? "another " : "");
241         }
242     }
243     return 0;
244 }