1 /*
2 * Testing tool for TLSv1 server routines using HTTPS
3 * Copyright (c) 2011-2019, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "crypto/tls.h"
13
14
https_tls_event_cb(void * ctx,enum tls_event ev,union tls_event_data * data)15 static void https_tls_event_cb(void *ctx, enum tls_event ev,
16 union tls_event_data *data)
17 {
18 wpa_printf(MSG_DEBUG, "HTTPS: TLS event %d", ev);
19 }
20
21
https_recv(int s,int timeout_ms)22 static struct wpabuf * https_recv(int s, int timeout_ms)
23 {
24 struct wpabuf *in;
25 int len, ret;
26 fd_set rfds;
27 struct timeval tv;
28
29 in = wpabuf_alloc(20000);
30 if (in == NULL)
31 return NULL;
32
33 FD_ZERO(&rfds);
34 FD_SET(s, &rfds);
35 tv.tv_sec = timeout_ms / 1000;
36 tv.tv_usec = timeout_ms % 1000;
37
38 wpa_printf(MSG_DEBUG, "Waiting for more data");
39 ret = select(s + 1, &rfds, NULL, NULL, &tv);
40 if (ret < 0) {
41 wpa_printf(MSG_ERROR, "select: %s", strerror(errno));
42 wpabuf_free(in);
43 return NULL;
44 }
45 if (ret == 0) {
46 /* timeout */
47 wpa_printf(MSG_INFO, "Timeout on waiting for data");
48 wpabuf_free(in);
49 return NULL;
50 }
51
52 len = recv(s, wpabuf_put(in, 0), wpabuf_tailroom(in), 0);
53 if (len < 0) {
54 wpa_printf(MSG_ERROR, "recv: %s", strerror(errno));
55 wpabuf_free(in);
56 return NULL;
57 }
58 if (len == 0) {
59 wpa_printf(MSG_DEBUG, "No more data available");
60 wpabuf_free(in);
61 return NULL;
62 }
63 wpa_printf(MSG_DEBUG, "Received %d bytes", len);
64 wpabuf_put(in, len);
65
66 return in;
67 }
68
69
https_tls_log_cb(void * ctx,const char * msg)70 static void https_tls_log_cb(void *ctx, const char *msg)
71 {
72 wpa_printf(MSG_DEBUG, "TLS: %s", msg);
73 }
74
75
https_server(int s)76 static int https_server(int s)
77 {
78 struct tls_config conf;
79 void *tls;
80 struct tls_connection_params params;
81 struct tls_connection *conn;
82 struct wpabuf *in, *out, *appl;
83 int res = -1;
84
85 os_memset(&conf, 0, sizeof(conf));
86 conf.event_cb = https_tls_event_cb;
87 tls = tls_init(&conf);
88 if (!tls)
89 return -1;
90
91 os_memset(¶ms, 0, sizeof(params));
92 params.ca_cert = "hwsim/auth_serv/ca.pem";
93 params.client_cert = "hwsim/auth_serv/server.pem";
94 params.private_key = "hwsim/auth_serv/server.key";
95 params.dh_file = "hwsim/auth_serv/dh.conf";
96
97 if (tls_global_set_params(tls, ¶ms)) {
98 wpa_printf(MSG_ERROR, "Failed to set TLS parameters");
99 tls_deinit(tls);
100 return -1;
101 }
102
103 conn = tls_connection_init(tls);
104 if (!conn) {
105 tls_deinit(tls);
106 return -1;
107 }
108
109 tls_connection_set_log_cb(conn, https_tls_log_cb, NULL);
110
111 for (;;) {
112 in = https_recv(s, 5000);
113 if (!in)
114 goto done;
115
116 appl = NULL;
117 out = tls_connection_server_handshake(tls, conn, in, &appl);
118 wpabuf_free(in);
119 in = NULL;
120 if (!out) {
121 if (!tls_connection_get_failed(tls, conn) &&
122 !tls_connection_established(tls, conn))
123 continue;
124 goto done;
125 }
126 wpa_printf(MSG_DEBUG, "Sending %d bytes",
127 (int) wpabuf_len(out));
128 if (send(s, wpabuf_head(out), wpabuf_len(out), 0) < 0) {
129 wpa_printf(MSG_ERROR, "send: %s", strerror(errno));
130 goto done;
131 }
132 wpabuf_free(out);
133 out = NULL;
134 if (tls_connection_get_failed(tls, conn)) {
135 wpa_printf(MSG_ERROR, "TLS handshake failed");
136 goto done;
137 }
138 if (tls_connection_established(tls, conn))
139 break;
140 }
141 wpabuf_free(out);
142 out = NULL;
143
144 wpa_printf(MSG_INFO, "TLS connection established");
145 if (appl)
146 wpa_hexdump_buf(MSG_DEBUG, "Received application data", appl);
147
148 wpa_printf(MSG_INFO, "Reading HTTP request");
149 for (;;) {
150 int need_more_data;
151
152 in = https_recv(s, 5000);
153 if (!in)
154 goto done;
155 out = tls_connection_decrypt2(tls, conn, in, &need_more_data);
156 wpabuf_free(in);
157 in = NULL;
158 if (need_more_data) {
159 wpa_printf(MSG_DEBUG, "HTTP: Need more data");
160 continue;
161 }
162 if (!out)
163 goto done;
164 wpa_hexdump_ascii(MSG_INFO, "Request",
165 wpabuf_head(out), wpabuf_len(out));
166 wpabuf_free(out);
167 out = NULL;
168 break;
169 }
170
171 in = wpabuf_alloc(1000);
172 if (!in)
173 goto done;
174 wpabuf_put_str(in, "HTTP/1.1 200 OK\r\n"
175 "Server: test-https_server\r\n"
176 "\r\n"
177 "<HTML><BODY>HELLO</BODY></HTML>\n");
178 wpa_hexdump_ascii(MSG_DEBUG, "Response",
179 wpabuf_head(in), wpabuf_len(in));
180 out = tls_connection_encrypt(tls, conn, in);
181 wpabuf_free(in);
182 in = NULL;
183 wpa_hexdump_buf(MSG_DEBUG, "Encrypted response", out);
184 if (!out)
185 goto done;
186
187 wpa_printf(MSG_INFO, "Sending HTTP response: %d bytes",
188 (int) wpabuf_len(out));
189 if (send(s, wpabuf_head(out), wpabuf_len(out), 0) < 0) {
190 wpa_printf(MSG_ERROR, "send: %s", strerror(errno));
191 goto done;
192 }
193 wpabuf_free(out);
194 out = NULL;
195
196 res = 0;
197 done:
198 wpabuf_free(out);
199 wpabuf_free(in);
200 wpabuf_free(appl);
201 tls_connection_deinit(tls, conn);
202 tls_deinit(tls);
203 close(s);
204
205 return res;
206 }
207
208
main(int argc,char * argv[])209 int main(int argc, char *argv[])
210 {
211 struct sockaddr_in sin;
212 int port, s, conn;
213 int on = 1;
214
215 wpa_debug_level = 0;
216 wpa_debug_show_keys = 1;
217
218 if (argc < 2) {
219 wpa_printf(MSG_INFO, "usage: test-https_server port");
220 return -1;
221 }
222
223 port = atoi(argv[1]);
224
225 s = socket(AF_INET, SOCK_STREAM, 0);
226 if (s < 0) {
227 perror("socket");
228 return -1;
229 }
230
231 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
232 wpa_printf(MSG_DEBUG,
233 "HTTP: setsockopt(SO_REUSEADDR) failed: %s",
234 strerror(errno));
235 /* try to continue anyway */
236 }
237
238 os_memset(&sin, 0, sizeof(sin));
239 sin.sin_family = AF_INET;
240 sin.sin_port = htons(port);
241 if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
242 perror("bind");
243 close(s);
244 return -1;
245 }
246
247 if (listen(s, 10) < 0) {
248 perror("listen");
249 close(s);
250 return -1;
251 }
252
253 for (;;) {
254 struct sockaddr_in addr;
255 socklen_t addr_len = sizeof(addr);
256
257 conn = accept(s, (struct sockaddr *) &addr, &addr_len);
258 if (conn < 0) {
259 perror("accept");
260 break;
261 }
262
263 wpa_printf(MSG_DEBUG, "-------------------------------------");
264 wpa_printf(MSG_DEBUG, "Connection from %s:%d",
265 inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
266
267 https_server(conn);
268 wpa_printf(MSG_DEBUG, "Done with the connection");
269 wpa_printf(MSG_DEBUG, "-------------------------------------");
270 }
271
272 close(s);
273
274 return 0;
275 }
276