]>
Commit | Line | Data |
---|---|---|
d10b1398 JM |
1 | /* |
2 | * Testing tool for TLSv1 client routines using HTTPS | |
3 | * Copyright (c) 2011, Jouni Malinen <j@w1.fi> | |
4 | * | |
0f3d578e JM |
5 | * This software may be distributed under the terms of the BSD license. |
6 | * See README for more details. | |
d10b1398 JM |
7 | */ |
8 | ||
9 | #include "includes.h" | |
10 | #include <netdb.h> | |
11 | ||
12 | #include "common.h" | |
13 | #include "crypto/tls.h" | |
14 | ||
d10b1398 JM |
15 | |
16 | static void https_tls_event_cb(void *ctx, enum tls_event ev, | |
17 | union tls_event_data *data) | |
18 | { | |
19 | wpa_printf(MSG_DEBUG, "HTTPS: TLS event %d", ev); | |
20 | } | |
21 | ||
22 | ||
23 | static struct wpabuf * https_recv(int s) | |
24 | { | |
25 | struct wpabuf *in; | |
26 | int len, ret; | |
27 | fd_set rfds; | |
28 | struct timeval tv; | |
29 | ||
30 | in = wpabuf_alloc(20000); | |
31 | if (in == NULL) | |
32 | return NULL; | |
33 | ||
34 | FD_ZERO(&rfds); | |
35 | FD_SET(s, &rfds); | |
36 | tv.tv_sec = 5; | |
37 | tv.tv_usec = 0; | |
38 | ||
39 | wpa_printf(MSG_DEBUG, "Waiting for more data"); | |
40 | ret = select(s + 1, &rfds, NULL, NULL, &tv); | |
41 | if (ret < 0) { | |
42 | wpa_printf(MSG_ERROR, "select: %s", strerror(errno)); | |
43 | wpabuf_free(in); | |
44 | return NULL; | |
45 | } | |
46 | if (ret == 0) { | |
47 | /* timeout */ | |
48 | wpa_printf(MSG_INFO, "Timeout on waiting for data"); | |
49 | wpabuf_free(in); | |
50 | return NULL; | |
51 | } | |
52 | ||
53 | len = recv(s, wpabuf_put(in, 0), wpabuf_tailroom(in), 0); | |
54 | if (len < 0) { | |
55 | wpa_printf(MSG_ERROR, "recv: %s", strerror(errno)); | |
56 | wpabuf_free(in); | |
57 | return NULL; | |
58 | } | |
59 | if (len == 0) { | |
60 | wpa_printf(MSG_DEBUG, "No more data available"); | |
61 | wpabuf_free(in); | |
62 | return NULL; | |
63 | } | |
64 | wpa_printf(MSG_DEBUG, "Received %d bytes", len); | |
65 | wpabuf_put(in, len); | |
66 | ||
67 | return in; | |
68 | } | |
69 | ||
70 | ||
71 | static int https_client(int s, const char *path) | |
72 | { | |
73 | struct tls_config conf; | |
74 | void *tls; | |
75 | struct tls_connection *conn; | |
76 | struct wpabuf *in, *out, *appl; | |
77 | int res = -1; | |
78 | int need_more_data; | |
79 | ||
80 | os_memset(&conf, 0, sizeof(conf)); | |
81 | conf.event_cb = https_tls_event_cb; | |
82 | tls = tls_init(&conf); | |
83 | if (tls == NULL) | |
84 | return -1; | |
85 | ||
86 | conn = tls_connection_init(tls); | |
87 | if (conn == NULL) { | |
88 | tls_deinit(tls); | |
89 | return -1; | |
90 | } | |
91 | ||
92 | in = NULL; | |
93 | ||
94 | for (;;) { | |
95 | appl = NULL; | |
96 | out = tls_connection_handshake2(tls, conn, in, &appl, | |
97 | &need_more_data); | |
98 | wpabuf_free(in); | |
99 | in = NULL; | |
100 | if (out == NULL) { | |
101 | if (need_more_data) | |
102 | goto read_more; | |
103 | goto done; | |
104 | } | |
105 | if (tls_connection_get_failed(tls, conn)) { | |
106 | wpa_printf(MSG_ERROR, "TLS handshake failed"); | |
107 | goto done; | |
108 | } | |
109 | if (tls_connection_established(tls, conn)) | |
110 | break; | |
111 | wpa_printf(MSG_DEBUG, "Sending %d bytes", | |
112 | (int) wpabuf_len(out)); | |
113 | if (send(s, wpabuf_head(out), wpabuf_len(out), 0) < 0) { | |
114 | wpa_printf(MSG_ERROR, "send: %s", strerror(errno)); | |
115 | goto done; | |
116 | } | |
117 | wpabuf_free(out); | |
118 | out = NULL; | |
119 | ||
120 | read_more: | |
121 | in = https_recv(s); | |
122 | if (in == NULL) | |
123 | goto done; | |
124 | } | |
b32a8d1d JM |
125 | wpabuf_free(out); |
126 | out = NULL; | |
d10b1398 JM |
127 | |
128 | wpa_printf(MSG_INFO, "TLS connection established"); | |
129 | if (appl) | |
130 | wpa_hexdump_buf(MSG_DEBUG, "Received application data", appl); | |
131 | ||
132 | in = wpabuf_alloc(100 + os_strlen(path)); | |
133 | if (in == NULL) | |
134 | goto done; | |
135 | wpabuf_put_str(in, "GET "); | |
136 | wpabuf_put_str(in, path); | |
137 | wpabuf_put_str(in, " HTTP/1.0\r\n\r\n"); | |
138 | out = tls_connection_encrypt(tls, conn, in); | |
139 | wpabuf_free(in); | |
140 | in = NULL; | |
141 | if (out == NULL) | |
142 | goto done; | |
143 | ||
144 | wpa_printf(MSG_INFO, "Sending HTTP request: %d bytes", | |
145 | (int) wpabuf_len(out)); | |
146 | if (send(s, wpabuf_head(out), wpabuf_len(out), 0) < 0) { | |
147 | wpa_printf(MSG_ERROR, "send: %s", strerror(errno)); | |
148 | goto done; | |
149 | } | |
b32a8d1d JM |
150 | wpabuf_free(out); |
151 | out = NULL; | |
d10b1398 JM |
152 | |
153 | wpa_printf(MSG_INFO, "Reading HTTP response"); | |
154 | for (;;) { | |
155 | int need_more_data; | |
156 | in = https_recv(s); | |
157 | if (in == NULL) | |
158 | goto done; | |
159 | out = tls_connection_decrypt2(tls, conn, in, &need_more_data); | |
160 | if (need_more_data) | |
161 | wpa_printf(MSG_DEBUG, "HTTP: Need more data"); | |
162 | wpabuf_free(in); | |
163 | in = NULL; | |
164 | if (out == NULL) | |
165 | goto done; | |
166 | wpa_hexdump_ascii(MSG_INFO, "Response", wpabuf_head(out), | |
167 | wpabuf_len(out)); | |
168 | wpabuf_free(out); | |
169 | out = NULL; | |
170 | } | |
171 | ||
172 | res = 0; | |
173 | done: | |
174 | wpabuf_free(out); | |
175 | wpabuf_free(in); | |
176 | wpabuf_free(appl); | |
177 | tls_connection_deinit(tls, conn); | |
178 | tls_deinit(tls); | |
179 | ||
180 | return res; | |
181 | } | |
182 | ||
183 | ||
184 | int main(int argc, char *argv[]) | |
185 | { | |
186 | struct addrinfo hints, *result, *rp; | |
187 | int res, s; | |
188 | ||
189 | wpa_debug_level = 0; | |
190 | wpa_debug_show_keys = 1; | |
191 | ||
192 | if (argc < 4) { | |
193 | wpa_printf(MSG_INFO, "usage: test-https server port path"); | |
194 | return -1; | |
195 | } | |
196 | ||
197 | os_memset(&hints, 0, sizeof(hints)); | |
198 | hints.ai_family = AF_UNSPEC; | |
199 | hints.ai_socktype = SOCK_STREAM; | |
200 | res = getaddrinfo(argv[1], argv[2], &hints, &result); | |
201 | if (res) { | |
202 | wpa_printf(MSG_ERROR, "getaddrinfo: %s", gai_strerror(res)); | |
203 | return -1; | |
204 | } | |
205 | ||
206 | for (rp = result; rp; rp = rp->ai_next) { | |
207 | s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); | |
208 | if (s < 0) | |
209 | continue; | |
210 | if (connect(s, rp->ai_addr, rp->ai_addrlen) == 0) | |
211 | break; | |
212 | close(s); | |
213 | } | |
214 | freeaddrinfo(result); | |
215 | ||
216 | if (rp == NULL) { | |
217 | wpa_printf(MSG_ERROR, "Could not connect"); | |
218 | return -1; | |
219 | } | |
220 | ||
221 | https_client(s, argv[3]); | |
222 | close(s); | |
223 | ||
224 | return 0; | |
225 | } |