]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_ssl/regressions/ssl-47-falsestart.c
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / regressions / ssl-47-falsestart.c
CommitLineData
d8f41ccd
A
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
427c49bc
A
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#include "ssl_regressions.h"
50
51
52typedef struct {
53 uint32_t session_id;
54 bool is_session_resume;
55 SSLContextRef st;
56 bool is_server;
57 bool client_side_auth;
58 bool dh_anonymous;
59 int comm;
60 CFArrayRef certs;
61} ssl_test_handle;
62
63
64
65#if 0
66static void hexdump(const uint8_t *bytes, size_t len) {
67 size_t ix;
68 printf("socket write(%p, %lu)\n", bytes, len);
69 for (ix = 0; ix < len; ++ix) {
70 if (!(ix % 16))
71 printf("\n");
72 printf("%02X ", bytes[ix]);
73 }
74 printf("\n");
75}
76#else
77#define hexdump(bytes, len)
78#endif
79
80static int SocketConnect(const char *hostName, int port)
81{
82 struct sockaddr_in addr;
83 struct in_addr host;
fa7225c8 84 int sock;
427c49bc
A
85 int err;
86 struct hostent *ent;
87
fa7225c8 88 if (hostName[0] >= '0' && hostName[0] <= '9') {
427c49bc 89 host.s_addr = inet_addr(hostName);
fa7225c8
A
90 } else {
91 ent = gethostbyname(hostName);
427c49bc 92 if(ent == NULL) {
fa7225c8
A
93 printf("\n***gethostbyname(%s) returned: %s\n", hostName, hstrerror(h_errno));
94 return -2;
427c49bc
A
95 }
96 memcpy(&host, ent->h_addr, sizeof(struct in_addr));
97 }
98
427c49bc
A
99 sock = socket(AF_INET, SOCK_STREAM, 0);
100 addr.sin_addr = host;
101 addr.sin_port = htons((u_short)port);
102
103 addr.sin_family = AF_INET;
104 err = connect(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in));
105
106 if(err!=0)
107 {
108 perror("connect failed");
fa7225c8 109 return -1;
427c49bc
A
110 }
111
112 /* make non blocking */
113 fcntl(sock, F_SETFL, O_NONBLOCK);
114
427c49bc
A
115 return sock;
116}
117
427c49bc
A
118static 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
143static
144OSStatus 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
176static 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;
194out:
195 if (ctx)
196 SSLDisposeContext(ctx);
197 return NULL;
198}
199
200const char request[]="GET / HTTP/1.1\n\n";
201char reply[2048];
202
203static 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);
fa7225c8
A
211
212 require_action_quiet(ortn==errSSLWouldBlock, out, printf("SSLHandshake failed with err %ld\n", (long)ortn));
213
427c49bc
A
214 size_t sent, received;
215 const char *r=request;
216 size_t l=sizeof(request);
217
218 do {
219
220 ortn = SSLWrite(ctx, r, l, &sent);
221
222 if(ortn == errSSLWouldBlock) {
223 r+=sent;
224 l-=sent;
225 }
226
227 if (ortn == errSSLServerAuthCompleted)
228 {
229 require_string(!got_server_auth, out, "second server auth");
230 require_string(!got_client_cert_req, out, "got client cert req before server auth");
231 got_server_auth = true;
232 require_string(!trust, out, "Got errSSLServerAuthCompleted twice?");
233 /* verify peer cert chain */
234 require_noerr(SSLCopyPeerTrust(ctx, &trust), out);
235 SecTrustResultType trust_result = 0;
236 /* this won't verify without setting up a trusted anchor */
237 require_noerr(SecTrustEvaluate(trust, &trust_result), out);
238 }
427c49bc
A
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
261out:
262 SSLClose(ctx);
263 SSLDisposeContext(ctx);
264 if (trust) CFRelease(trust);
265
266 return ortn;
267}
268
427c49bc
A
269static ssl_test_handle *
270ssl_test_handle_create(int comm, SSLProtocol maxprot, Boolean false_start)
271{
272 ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle));
273 if (handle) {
274 handle->comm = comm;
275 handle->st = make_ssl_ref(comm, maxprot, false_start);
276 }
277 return handle;
278}
279
280static
281struct s_server {
282 char *host;
283 int port;
284 SSLProtocol maxprot;
285} servers[] = {
286 /* Good tls 1.2 servers */
287 {"encrypted.google.com", 443, kTLSProtocol12 },
288 {"www.amazon.com",443, kTLSProtocol12 },
d8f41ccd 289 //{"www.mikestoolbox.org",443, kTLSProtocol12 },
427c49bc
A
290};
291
292#define NSERVERS (int)(sizeof(servers)/sizeof(servers[0]))
293#define NLOOPS 1
fa7225c8 294#define CONNECT_TRIES 3
427c49bc
A
295
296static void
297tests(void)
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;
427c49bc 307 OSStatus r;
fa7225c8
A
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 }
427c49bc 313
427c49bc
A
314 if(s<0) {
315 fail("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 ok(!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);
d8f41ccd 325 free(client);
427c49bc
A
326 } } }
327}
328
329int ssl_47_falsestart(int argc, char *const *argv)
330{
331 plan_tests(NSERVERS*NLOOPS*2);
332
333 tests();
334
335 return 0;
336}