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