]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+falsestart.m
Security-59754.80.3.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 #import "STLegacyTests.h"
49
50 #pragma clang diagnostic push
51 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
52
53 @implementation STLegacyTests (falsestart)
54
55 typedef struct {
56 uint32_t session_id;
57 bool is_session_resume;
58 SSLContextRef st;
59 bool is_server;
60 bool client_side_auth;
61 bool dh_anonymous;
62 int comm;
63 CFArrayRef certs;
64 } ssl_test_handle;
65
66
67 #if SECTRANS_VERBOSE_DEBUG
68 static void hexdump(const uint8_t *bytes, size_t len) {
69 size_t ix;
70 printf("socket write(%p, %lu)\n", bytes, len);
71 for (ix = 0; ix < len; ++ix) {
72 if (!(ix % 16))
73 printf("\n");
74 printf("%02X ", bytes[ix]);
75 }
76 printf("\n");
77 }
78 #else
79 #define hexdump(bytes, len)
80 #endif
81
82 static int SocketConnect(const char *hostName, int port)
83 {
84 struct sockaddr_in addr;
85 struct in_addr host;
86 int sock;
87 int err;
88 struct hostent *ent;
89 char **h_addr_list = NULL;
90
91 if (hostName[0] >= '0' && hostName[0] <= '9') {
92 host.s_addr = inet_addr(hostName);
93 } else {
94 ent = gethostbyname(hostName);
95 if(ent == NULL) {
96 printf("\n***gethostbyname(%s) returned: %s\n", hostName, hstrerror(h_errno));
97 return -2;
98 }
99 h_addr_list = malloc(sizeof(char *));
100 memcpy(h_addr_list, ent->h_addr_list, sizeof(char *));
101 memcpy(&host, h_addr_list[0], sizeof(struct in_addr));
102 }
103
104 sock = socket(AF_INET, SOCK_STREAM, 0);
105 addr.sin_addr.s_addr = host.s_addr;
106 free(h_addr_list);
107 addr.sin_port = htons((u_short)port);
108
109 addr.sin_family = AF_INET;
110 err = connect(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in));
111
112 if(err != 0)
113 {
114 perror("connect failed");
115 return -1;
116 }
117
118 /* make non blocking */
119 fcntl(sock, F_SETFL, O_NONBLOCK);
120 return sock;
121 }
122
123 static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
124 {
125 size_t len = *length;
126 uint8_t *ptr = (uint8_t *)data;
127
128 do {
129 ssize_t ret;
130 do {
131 hexdump(ptr, len);
132 ret = write((int)conn, ptr, len);
133 if (ret < 0)
134 perror("send");
135 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
136 if (ret > 0) {
137 len -= ret;
138 ptr += ret;
139 } else {
140 return -36;
141 }
142 } while (len > 0);
143
144 *length = *length - len;
145 return errSecSuccess;
146 }
147
148 static
149 OSStatus SocketRead(
150 SSLConnectionRef connection,
151 void *data,
152 size_t *dataLength)
153 {
154 int fd = (int)connection;
155 ssize_t len;
156
157 len = read(fd, data, *dataLength);
158
159 if (len < 0) {
160 int theErr = errno;
161 switch(theErr) {
162 case EAGAIN:
163 *dataLength=0;
164 /* nonblocking, no data */
165 return errSSLWouldBlock;
166 default:
167 perror("SocketRead");
168 return -36;
169 }
170 }
171
172 if (len < (ssize_t)*dataLength) {
173 *dataLength = len;
174 return errSSLWouldBlock;
175 }
176
177 return errSecSuccess;
178 }
179
180 static SSLContextRef make_ssl_ref(int sock, SSLProtocol maxprot, Boolean false_start)
181 {
182 SSLContextRef ctx = NULL;
183
184 require_noerr(SSLNewContext(false, &ctx), out);
185 require_noerr(SSLSetIOFuncs(ctx,
186 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
187 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out);
188
189 require_noerr(SSLSetSessionOption(ctx,
190 kSSLSessionOptionBreakOnServerAuth, true), out);
191
192 require_noerr(SSLSetSessionOption(ctx,
193 kSSLSessionOptionFalseStart, false_start), out);
194
195 require_noerr(SSLSetProtocolVersionMax(ctx, maxprot), out);
196
197 return ctx;
198 out:
199 if (ctx) {
200 SSLDisposeContext(ctx);
201 }
202 return NULL;
203 }
204
205 const char request[]="GET / HTTP/1.1\n\n";
206 char reply[2048];
207
208 static OSStatus securetransport(ssl_test_handle * ssl)
209 {
210 OSStatus ortn;
211 SSLContextRef ctx = ssl->st;
212 SecTrustRef trust = NULL;
213 bool got_server_auth = false, got_client_cert_req = false;
214
215 ortn = SSLHandshake(ctx);
216
217 require_action_quiet(ortn == errSSLWouldBlock, out, printf("SSLHandshake failed with err %ld\n", (long)ortn));
218
219 size_t sent, received;
220 const char *r = request;
221 size_t l = sizeof(request);
222
223 do {
224
225 ortn = SSLWrite(ctx, r, l, &sent);
226
227 if (ortn == errSSLWouldBlock) {
228 r += sent;
229 l -= sent;
230 }
231
232 if (ortn == errSSLServerAuthCompleted) {
233 require_string(!got_server_auth, out, "second server auth");
234 require_string(!got_client_cert_req, out, "got client cert req before server auth");
235 got_server_auth = true;
236 require_string(!trust, out, "Got errSSLServerAuthCompleted twice?");
237 /* verify peer cert chain */
238 require_noerr(SSLCopyPeerTrust(ctx, &trust), out);
239 SecTrustResultType trust_result = 0;
240 /* this won't verify without setting up a trusted anchor */
241 require_noerr(SecTrustEvaluate(trust, &trust_result), out);
242 }
243 } while (ortn == errSSLWouldBlock || ortn == errSSLServerAuthCompleted);
244
245 require_noerr_action_quiet(ortn, out, printf("SSLWrite failed with err %ld\n", (long)ortn));
246
247 require_string(got_server_auth, out, "never got server auth");
248
249 do {
250 ortn = SSLRead(ctx, reply, sizeof(reply)-1, &received);
251 } while (ortn == errSSLWouldBlock);
252
253 require_noerr_action_quiet(ortn, out, printf("SSLRead failed with err %ld\n", (long)ortn));
254
255 reply[received] = 0;
256
257 out:
258 SSLClose(ctx);
259 SSLDisposeContext(ctx);
260 if (trust) CFRelease(trust);
261
262 return ortn;
263 }
264
265 static ssl_test_handle *
266 ssl_test_handle_create(int comm, SSLProtocol maxprot, Boolean false_start)
267 {
268 ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle));
269 if (handle) {
270 handle->comm = comm;
271 handle->st = make_ssl_ref(comm, maxprot, false_start);
272 }
273 return handle;
274 }
275
276 static
277 struct s_server {
278 char *host;
279 int port;
280 SSLProtocol maxprot;
281 } servers[] = {
282 /* Good tls 1.2 servers */
283 {"encrypted.google.com", 443, kTLSProtocol12 },
284 {"www.amazon.com",443, kTLSProtocol12 },
285 };
286
287 #define NSERVERS (int)(sizeof(servers)/sizeof(servers[0]))
288 #define NLOOPS 1
289 #define CONNECT_TRIES 3
290
291 -(void)testFalseStart
292 {
293 int p;
294 int fs;
295
296 for (p = 0; p < NSERVERS; p++) {
297 for (int loops = 0; loops < NLOOPS; loops++) {
298 for (fs = 0;fs < 2; fs++) {
299
300 ssl_test_handle *client;
301 OSStatus r;
302 int s = -1;
303
304 for (int try = 0; s < 0 && try < CONNECT_TRIES; try++) {
305 s = SocketConnect(servers[p].host, servers[p].port);
306 }
307 if (s < 0) {
308 break;
309 }
310 client = ssl_test_handle_create(s, servers[p].maxprot, fs);
311
312 r = securetransport(client);
313 XCTAssert(!r, "handshake failed with err=%ld - %s:%d (try %d), false start=%d", (long)r, servers[p].host, servers[p].port, loops, fs);
314
315 close(s);
316 free(client);
317 }
318 }
319 }
320 }
321
322 @end
323
324 #pragma clang diagnostic pop