2 * Copyright (c) 2011,2013-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
30 #include <sys/types.h>
31 #include <netinet/in.h>
32 #include <sys/socket.h>
34 #include <arpa/inet.h>
35 #include <CoreFoundation/CoreFoundation.h>
37 #include <AssertMacros.h>
38 #include <Security/SecureTransportPriv.h> /* SSLSetOption */
39 #include <Security/SecureTransport.h>
42 #include <sys/types.h>
43 #include <sys/socket.h>
46 #include <mach/mach_time.h>
49 #include "ssl_regressions.h"
54 bool is_session_resume
;
57 bool client_side_auth
;
66 static void hexdump(const uint8_t *bytes
, size_t len
) {
68 printf("socket write(%p, %lu)\n", bytes
, len
);
69 for (ix
= 0; ix
< len
; ++ix
) {
72 printf("%02X ", bytes
[ix
]);
77 #define hexdump(bytes, len)
80 static int SocketConnect(const char *hostName
, int port
)
82 struct sockaddr_in addr
;
88 if (hostName
[0] >= '0' && hostName
[0] <= '9')
90 host
.s_addr
= inet_addr(hostName
);
94 #define GETHOST_RETRIES 5
95 /* seeing a lot of soft failures here that I really don't want to track down */
96 for(dex
=0; dex
<GETHOST_RETRIES
; dex
++) {
98 printf("\n...retrying gethostbyname(%s)", hostName
);
100 ent
= gethostbyname(hostName
);
106 printf("\n***gethostbyname(%s) returned: %s\n", hostName
, hstrerror(h_errno
));
109 memcpy(&host
, ent
->h_addr
, sizeof(struct in_addr
));
113 sock
= socket(AF_INET
, SOCK_STREAM
, 0);
114 addr
.sin_addr
= host
;
115 addr
.sin_port
= htons((u_short
)port
);
117 addr
.sin_family
= AF_INET
;
118 err
= connect(sock
, (struct sockaddr
*) &addr
, sizeof(struct sockaddr_in
));
122 perror("connect failed");
126 /* make non blocking */
127 fcntl(sock
, F_SETFL
, O_NONBLOCK
);
134 static OSStatus
SocketWrite(SSLConnectionRef conn
, const void *data
, size_t *length
)
136 size_t len
= *length
;
137 uint8_t *ptr
= (uint8_t *)data
;
143 ret
= write((int)conn
, ptr
, len
);
146 } while ((ret
< 0) && (errno
== EAGAIN
|| errno
== EINTR
));
155 *length
= *length
- len
;
156 return errSecSuccess
;
161 SSLConnectionRef connection
,
165 int fd
= (int)connection
;
168 len
= read(fd
, data
, *dataLength
);
174 //printf("SocketRead: EAGAIN\n");
176 /* nonblocking, no data */
177 return errSSLWouldBlock
;
179 perror("SocketRead");
184 if(len
<(ssize_t
)*dataLength
) {
186 return errSSLWouldBlock
;
189 return errSecSuccess
;
192 static SSLContextRef
make_ssl_ref(int sock
, SSLProtocol maxprot
, Boolean false_start
)
194 SSLContextRef ctx
= NULL
;
196 require_noerr(SSLNewContext(false, &ctx
), out
);
197 require_noerr(SSLSetIOFuncs(ctx
,
198 (SSLReadFunc
)SocketRead
, (SSLWriteFunc
)SocketWrite
), out
);
199 require_noerr(SSLSetConnection(ctx
, (SSLConnectionRef
)(intptr_t)sock
), out
);
201 require_noerr(SSLSetSessionOption(ctx
,
202 kSSLSessionOptionBreakOnServerAuth
, true), out
);
204 require_noerr(SSLSetSessionOption(ctx
,
205 kSSLSessionOptionFalseStart
, false_start
), out
);
207 require_noerr(SSLSetProtocolVersionMax(ctx
, maxprot
), out
);
212 SSLDisposeContext(ctx
);
216 const char request
[]="GET / HTTP/1.1\n\n";
219 static OSStatus
securetransport(ssl_test_handle
* ssl
)
222 SSLContextRef ctx
= ssl
->st
;
223 SecTrustRef trust
= NULL
;
224 bool got_server_auth
= false, got_client_cert_req
= false;
226 ortn
= SSLHandshake(ctx
);
227 //fprintf(stderr, "Fell out of SSLHandshake with error: %ld\n", (long)ortn);
229 size_t sent
, received
;
230 const char *r
=request
;
231 size_t l
=sizeof(request
);
235 ortn
= SSLWrite(ctx
, r
, l
, &sent
);
237 if(ortn
== errSSLWouldBlock
) {
242 if (ortn
== errSSLServerAuthCompleted
)
244 require_string(!got_server_auth
, out
, "second server auth");
245 require_string(!got_client_cert_req
, out
, "got client cert req before server auth");
246 got_server_auth
= true;
247 require_string(!trust
, out
, "Got errSSLServerAuthCompleted twice?");
248 /* verify peer cert chain */
249 require_noerr(SSLCopyPeerTrust(ctx
, &trust
), out
);
250 SecTrustResultType trust_result
= 0;
251 /* this won't verify without setting up a trusted anchor */
252 require_noerr(SecTrustEvaluate(trust
, &trust_result
), out
);
254 } while(ortn
== errSSLWouldBlock
|| ortn
== errSSLServerAuthCompleted
);
256 //fprintf(stderr, "\nHTTP Request Sent\n");
258 require_noerr_action_quiet(ortn
, out
, printf("SSLWrite failed with err %ld\n", (long)ortn
));
260 require_string(got_server_auth
, out
, "never got server auth");
263 ortn
= SSLRead(ctx
, reply
, sizeof(reply
)-1, &received
);
264 //fprintf(stderr, "r"); usleep(1000);
265 } while(ortn
== errSSLWouldBlock
);
267 //fprintf(stderr, "\n");
269 require_noerr_action_quiet(ortn
, out
, printf("SSLRead failed with err %ld\n", (long)ortn
));
273 //fprintf(stderr, "HTTP reply:\n");
274 //fprintf(stderr, "%s\n",reply);
278 SSLDisposeContext(ctx
);
279 if (trust
) CFRelease(trust
);
284 static ssl_test_handle
*
285 ssl_test_handle_create(int comm
, SSLProtocol maxprot
, Boolean false_start
)
287 ssl_test_handle
*handle
= calloc(1, sizeof(ssl_test_handle
));
290 handle
->st
= make_ssl_ref(comm
, maxprot
, false_start
);
301 /* Good tls 1.2 servers */
302 {"encrypted.google.com", 443, kTLSProtocol12
},
303 {"www.amazon.com",443, kTLSProtocol12
},
304 //{"www.mikestoolbox.org",443, kTLSProtocol12 },
307 #define NSERVERS (int)(sizeof(servers)/sizeof(servers[0]))
316 for(p
=0; p
<NSERVERS
;p
++) {
317 for(int loops
=0; loops
<NLOOPS
; loops
++) {
318 for(fs
=0;fs
<2; fs
++) {
320 ssl_test_handle
*client
;
325 s
=SocketConnect(servers
[p
].host
, servers
[p
].port
);
327 fail("connect failed with err=%d - %s:%d (try %d)", s
, servers
[p
].host
, servers
[p
].port
, loops
);
331 client
= ssl_test_handle_create(s
, servers
[p
].maxprot
, fs
);
333 r
=securetransport(client
);
334 ok(!r
, "handshake failed with err=%ld - %s:%d (try %d), false start=%d", (long)r
, servers
[p
].host
, servers
[p
].port
, loops
, fs
);
341 int ssl_47_falsestart(int argc
, char *const *argv
)
343 plan_tests(NSERVERS
*NLOOPS
*2);