]> git.saurik.com Git - apple/security.git/blob - libsecurity_ssl/regressions/ssl-47-falsestart.c
Security-55471.14.tar.gz
[apple/security.git] / libsecurity_ssl / regressions / ssl-47-falsestart.c
1 //
2 // ssl-46-falsestart.c
3 // regressions
4 //
5 // Created by Fabrice Gautier on 6/7/11.
6 // Copyright 2011 Apple, Inc. All rights reserved.
7 //
8
9 #include <stdbool.h>
10 #include <pthread.h>
11 #include <fcntl.h>
12 #include <sys/mman.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <netinet/in.h>
16 #include <sys/socket.h>
17 #include <netdb.h>
18 #include <arpa/inet.h>
19 #include <CoreFoundation/CoreFoundation.h>
20
21 #include <AssertMacros.h>
22 #include <Security/SecureTransportPriv.h> /* SSLSetOption */
23 #include <Security/SecureTransport.h>
24
25 #include <string.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <errno.h>
29 #include <stdlib.h>
30 #include <mach/mach_time.h>
31
32
33 #include "ssl_regressions.h"
34
35
36 typedef struct {
37 uint32_t session_id;
38 bool is_session_resume;
39 SSLContextRef st;
40 bool is_server;
41 bool client_side_auth;
42 bool dh_anonymous;
43 int comm;
44 CFArrayRef certs;
45 } ssl_test_handle;
46
47
48
49 #if 0
50 static void hexdump(const uint8_t *bytes, size_t len) {
51 size_t ix;
52 printf("socket write(%p, %lu)\n", bytes, len);
53 for (ix = 0; ix < len; ++ix) {
54 if (!(ix % 16))
55 printf("\n");
56 printf("%02X ", bytes[ix]);
57 }
58 printf("\n");
59 }
60 #else
61 #define hexdump(bytes, len)
62 #endif
63
64 static int SocketConnect(const char *hostName, int port)
65 {
66 struct sockaddr_in addr;
67 struct in_addr host;
68 int sock;
69 int err;
70 struct hostent *ent;
71
72 if (hostName[0] >= '0' && hostName[0] <= '9')
73 {
74 host.s_addr = inet_addr(hostName);
75 }
76 else {
77 unsigned dex;
78 #define GETHOST_RETRIES 5
79 /* seeing a lot of soft failures here that I really don't want to track down */
80 for(dex=0; dex<GETHOST_RETRIES; dex++) {
81 if(dex != 0) {
82 printf("\n...retrying gethostbyname(%s)", hostName);
83 }
84 ent = gethostbyname(hostName);
85 if(ent != NULL) {
86 break;
87 }
88 }
89 if(ent == NULL) {
90 printf("\n***gethostbyname(%s) returned: %s\n", hostName, hstrerror(h_errno));
91 return -1;
92 }
93 memcpy(&host, ent->h_addr, sizeof(struct in_addr));
94 }
95
96
97 sock = socket(AF_INET, SOCK_STREAM, 0);
98 addr.sin_addr = host;
99 addr.sin_port = htons((u_short)port);
100
101 addr.sin_family = AF_INET;
102 err = connect(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in));
103
104 if(err!=0)
105 {
106 perror("connect failed");
107 return err;
108 }
109
110 /* make non blocking */
111 fcntl(sock, F_SETFL, O_NONBLOCK);
112
113
114 return sock;
115 }
116
117
118 static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
119 {
120 size_t len = *length;
121 uint8_t *ptr = (uint8_t *)data;
122
123 do {
124 ssize_t ret;
125 do {
126 hexdump(ptr, len);
127 ret = write((int)conn, ptr, len);
128 if (ret < 0)
129 perror("send");
130 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
131 if (ret > 0) {
132 len -= ret;
133 ptr += ret;
134 }
135 else
136 return -36;
137 } while (len > 0);
138
139 *length = *length - len;
140 return errSecSuccess;
141 }
142
143 static
144 OSStatus SocketRead(
145 SSLConnectionRef connection,
146 void *data,
147 size_t *dataLength)
148 {
149 int fd = (int)connection;
150 ssize_t len;
151
152 len = read(fd, data, *dataLength);
153
154 if(len<0) {
155 int theErr = errno;
156 switch(theErr) {
157 case EAGAIN:
158 //printf("SocketRead: EAGAIN\n");
159 *dataLength=0;
160 /* nonblocking, no data */
161 return errSSLWouldBlock;
162 default:
163 perror("SocketRead");
164 return -36;
165 }
166 }
167
168 if(len<(ssize_t)*dataLength) {
169 *dataLength=len;
170 return errSSLWouldBlock;
171 }
172
173 return errSecSuccess;
174 }
175
176 static SSLContextRef make_ssl_ref(int sock, SSLProtocol maxprot, Boolean false_start)
177 {
178 SSLContextRef ctx = NULL;
179
180 require_noerr(SSLNewContext(false, &ctx), out);
181 require_noerr(SSLSetIOFuncs(ctx,
182 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
183 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out);
184
185 require_noerr(SSLSetSessionOption(ctx,
186 kSSLSessionOptionBreakOnServerAuth, true), out);
187
188 require_noerr(SSLSetSessionOption(ctx,
189 kSSLSessionOptionFalseStart, false_start), out);
190
191 require_noerr(SSLSetProtocolVersionMax(ctx, maxprot), out);
192
193 return ctx;
194 out:
195 if (ctx)
196 SSLDisposeContext(ctx);
197 return NULL;
198 }
199
200 const char request[]="GET / HTTP/1.1\n\n";
201 char reply[2048];
202
203 static OSStatus securetransport(ssl_test_handle * ssl)
204 {
205 OSStatus ortn;
206 SSLContextRef ctx = ssl->st;
207 SecTrustRef trust = NULL;
208 bool got_server_auth = false, got_client_cert_req = false;
209
210 ortn = SSLHandshake(ctx);
211 //fprintf(stderr, "Fell out of SSLHandshake with error: %ld\n", (long)ortn);
212
213 size_t sent, received;
214 const char *r=request;
215 size_t l=sizeof(request);
216
217 do {
218
219 ortn = SSLWrite(ctx, r, l, &sent);
220
221 if(ortn == errSSLWouldBlock) {
222 r+=sent;
223 l-=sent;
224 }
225
226 if (ortn == errSSLServerAuthCompleted)
227 {
228 require_string(!got_server_auth, out, "second server auth");
229 require_string(!got_client_cert_req, out, "got client cert req before server auth");
230 got_server_auth = true;
231 require_string(!trust, out, "Got errSSLServerAuthCompleted twice?");
232 /* verify peer cert chain */
233 require_noerr(SSLCopyPeerTrust(ctx, &trust), out);
234 SecTrustResultType trust_result = 0;
235 /* this won't verify without setting up a trusted anchor */
236 require_noerr(SecTrustEvaluate(trust, &trust_result), out);
237 }
238
239 } while(ortn == errSSLWouldBlock || ortn == errSSLServerAuthCompleted);
240
241 //fprintf(stderr, "\nHTTP Request Sent\n");
242
243 require_noerr_action_quiet(ortn, out, printf("SSLWrite failed with err %ld\n", (long)ortn));
244
245 require_string(got_server_auth, out, "never got server auth");
246
247 do {
248 ortn = SSLRead(ctx, reply, sizeof(reply)-1, &received);
249 //fprintf(stderr, "r"); usleep(1000);
250 } while(ortn == errSSLWouldBlock);
251
252 //fprintf(stderr, "\n");
253
254 require_noerr_action_quiet(ortn, out, printf("SSLRead failed with err %ld\n", (long)ortn));
255
256 reply[received]=0;
257
258 //fprintf(stderr, "HTTP reply:\n");
259 //fprintf(stderr, "%s\n",reply);
260
261 out:
262 SSLClose(ctx);
263 SSLDisposeContext(ctx);
264 if (trust) CFRelease(trust);
265
266 return ortn;
267 }
268
269
270
271 static ssl_test_handle *
272 ssl_test_handle_create(int comm, SSLProtocol maxprot, Boolean false_start)
273 {
274 ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle));
275 if (handle) {
276 handle->comm = comm;
277 handle->st = make_ssl_ref(comm, maxprot, false_start);
278 }
279 return handle;
280 }
281
282 static
283 struct s_server {
284 char *host;
285 int port;
286 SSLProtocol maxprot;
287 } servers[] = {
288 /* Good tls 1.2 servers */
289 {"encrypted.google.com", 443, kTLSProtocol12 },
290 {"www.amazon.com",443, kTLSProtocol12 },
291 {"www.mikestoolbox.org",443, kTLSProtocol12 },
292 };
293
294 #define NSERVERS (int)(sizeof(servers)/sizeof(servers[0]))
295 #define NLOOPS 1
296
297 static void
298 tests(void)
299 {
300 int p;
301 int fs;
302
303 for(p=0; p<NSERVERS;p++) {
304 for(int loops=0; loops<NLOOPS; loops++) {
305 for(fs=0;fs<2; fs++) {
306
307 ssl_test_handle *client;
308
309 int s;
310 OSStatus r;
311
312 s=SocketConnect(servers[p].host, servers[p].port);
313 if(s<0) {
314 fail("connect failed with err=%d - %s:%d (try %d)", s, servers[p].host, servers[p].port, loops);
315 break;
316 }
317
318 client = ssl_test_handle_create(s, servers[p].maxprot, fs);
319
320 r=securetransport(client);
321 ok(!r, "handshake failed with err=%ld - %s:%d (try %d), false start=%d", (long)r, servers[p].host, servers[p].port, loops, fs);
322
323 close(s);
324 } } }
325 }
326
327 int ssl_47_falsestart(int argc, char *const *argv)
328 {
329 plan_tests(NSERVERS*NLOOPS*2);
330
331 tests();
332
333 return 0;
334 }