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