]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/regressions/ssl-45-tls12.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / regressions / ssl-45-tls12.c
1 /*
2 * Copyright (c) 2011-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 #include <Security/SecPolicy.h>
41 #include <Security/SecTrust.h>
42 #include <Security/SecIdentity.h>
43 #include <Security/SecIdentityPriv.h>
44 #include <Security/SecCertificatePriv.h>
45 #include <Security/SecKeyPriv.h>
46 #include <Security/SecItem.h>
47 #include <Security/SecRandom.h>
48
49 #include <string.h>
50 #include <sys/types.h>
51 #include <sys/socket.h>
52 #include <errno.h>
53 #include <stdlib.h>
54 #include <mach/mach_time.h>
55
56 #include "ssl_regressions.h"
57
58 struct s_server {
59 char *host;
60 int port;
61 SSLProtocol maxprot;
62 };
63
64 typedef struct {
65 struct s_server *server;
66 uint32_t session_id;
67 bool is_session_resume;
68 SSLContextRef st;
69 bool client_side_auth;
70 bool dh_anonymous;
71 int comm;
72 CFArrayRef certs;
73 } ssl_test_handle;
74
75
76
77 #if 0
78 static void hexdump(const uint8_t *bytes, size_t len) {
79 size_t ix;
80 printf("socket write(%p, %lu)\n", bytes, len);
81 for (ix = 0; ix < len; ++ix) {
82 if (!(ix % 16))
83 printf("\n");
84 printf("%02X ", bytes[ix]);
85 }
86 printf("\n");
87 }
88 #else
89 #define hexdump(bytes, len)
90 #endif
91
92 static int SocketConnect(const char *hostName, int port)
93 {
94 struct sockaddr_in addr;
95 struct in_addr host;
96 int sock;
97 int err;
98 struct hostent *ent;
99
100 if (hostName[0] >= '0' && hostName[0] <= '9')
101 {
102 host.s_addr = inet_addr(hostName);
103 }
104 else {
105 unsigned dex;
106 #define GETHOST_RETRIES 5
107 /* seeing a lot of soft failures here that I really don't want to track down */
108 for(dex=0; dex<GETHOST_RETRIES; dex++) {
109 if(dex != 0) {
110 printf("\n...retrying gethostbyname(%s)", hostName);
111 }
112 ent = gethostbyname(hostName);
113 if(ent != NULL) {
114 break;
115 }
116 }
117 if(ent == NULL) {
118 printf("\n***gethostbyname(%s) returned: %s\n", hostName, hstrerror(h_errno));
119 return -1;
120 }
121 memcpy(&host, ent->h_addr, sizeof(struct in_addr));
122 }
123
124
125 sock = socket(AF_INET, SOCK_STREAM, 0);
126 addr.sin_addr = host;
127 addr.sin_port = htons((u_short)port);
128
129 addr.sin_family = AF_INET;
130 err = connect(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in));
131
132 if(err!=0)
133 {
134 perror("connect failed");
135 return err;
136 }
137
138 return sock;
139 }
140
141
142 static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
143 {
144 size_t len = *length;
145 uint8_t *ptr = (uint8_t *)data;
146
147 do {
148 ssize_t ret;
149 do {
150 hexdump(ptr, len);
151 ret = write((int)conn, ptr, len);
152 if (ret < 0)
153 perror("send");
154 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
155 if (ret > 0) {
156 len -= ret;
157 ptr += ret;
158 }
159 else
160 return -36;
161 } while (len > 0);
162
163 *length = *length - len;
164 return errSecSuccess;
165 }
166
167 static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length)
168 {
169 size_t len = *length;
170 uint8_t *ptr = (uint8_t *)data;
171
172 do {
173 ssize_t ret;
174 do {
175 ret = read((int)conn, ptr, len);
176 if (ret < 0)
177 perror("send");
178 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
179 if (ret > 0) {
180 len -= ret;
181 ptr += ret;
182 }
183 else
184 return -36;
185 } while (len > 0);
186
187 *length = *length - len;
188 return errSecSuccess;
189 }
190
191 static SSLContextRef make_ssl_ref(int sock, SSLProtocol maxprot, const char *peerName)
192 {
193 SSLContextRef ctx = NULL;
194
195 require_noerr(SSLNewContext(false, &ctx), out);
196 require_noerr(SSLSetIOFuncs(ctx,
197 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
198 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out);
199
200 require_noerr(SSLSetSessionOption(ctx,
201 kSSLSessionOptionBreakOnServerAuth, true), out);
202
203 require_noerr(SSLSetProtocolVersionMax(ctx, maxprot), out);
204
205 require_noerr(SSLSetPeerDomainName(ctx, peerName, strlen(peerName)), out);
206 /* Tell SecureTransport to not check certs itself: it will break out of the
207 handshake to let us take care of it instead. */
208 require_noerr(SSLSetEnableCertVerify(ctx, false), out);
209
210 return ctx;
211 out:
212 if (ctx)
213 SSLDisposeContext(ctx);
214 return NULL;
215 }
216
217 static OSStatus securetransport(ssl_test_handle * ssl)
218 {
219 OSStatus ortn;
220 SSLContextRef ctx = ssl->st;
221 SecTrustRef trust = NULL;
222 bool got_server_auth = false, got_client_cert_req = false;
223
224 //uint64_t start = mach_absolute_time();
225 do {
226 ortn = SSLHandshake(ctx);
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 require((trust_result == kSecTrustResultUnspecified), out);
240
241 }
242 } while (ortn == errSSLWouldBlock
243 || ortn == errSSLServerAuthCompleted);
244 require_noerr_action_quiet(ortn, out,
245 fprintf(stderr, "Fell out of SSLHandshake with error: %d\n", (int)ortn));
246
247 require_string(got_server_auth, out, "never got server auth");
248
249 //uint64_t elapsed = mach_absolute_time() - start;
250 //fprintf(stderr, "setr elapsed: %lld\n", elapsed);
251
252 /*
253 SSLProtocol proto = kSSLProtocolUnknown;
254 require_noerr_quiet(SSLGetNegotiatedProtocolVersion(ctx, &proto), out); */
255
256 SSLCipherSuite cipherSuite;
257 require_noerr_quiet(ortn = SSLGetNegotiatedCipher(ctx, &cipherSuite), out);
258 //fprintf(stderr, "st negotiated %02x\n", cipherSuite);
259
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(struct s_server *server)
273 {
274 int comm;
275
276 comm=SocketConnect(server->host, server->port);
277 if(comm<0) {
278 fail("connect failed with err=%d - %s:%d", comm, server->host, server->port);
279 return NULL;
280 }
281
282 ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle));
283 if (handle) {
284 handle->comm = comm;
285 handle->st = make_ssl_ref(comm, server->maxprot, server->host);
286 handle->server = server;
287 }
288 return handle;
289 }
290
291 static void
292 ssl_test_handle_destroy(ssl_test_handle *handle)
293 {
294 close(handle->comm);
295 free(handle);
296 }
297
298
299 struct s_server servers[] = {
300 #if !TARGET_OS_IPHONE //This test run on AppleWifi on iPhone, so we can't connect to internal servers.
301 {"nod.apple.com", 636, kTLSProtocol12 }, // This one has only the server eku, not the client one.
302 #endif
303 {"gsa.apple.com", 443, kTLSProtocol12 }, // This one has only the server eku, not the client one.
304 /* Good tls 1.2 servers */
305 {"sslanalyzer.comodoca.com", 443, kTLSProtocol12 }, // This one has a stapled OCSP response with SCTs.
306 {"encrypted.google.com", 443, kTLSProtocol12 },
307 {"www.amazon.com",443, kTLSProtocol12 },
308 //{"www.mikestoolbox.org",443, kTLSProtocol12 },
309 /* servers with issues */
310 {"vpp.visa.co.uk", 443, kTLSProtocol12 }, // Doesnt like SSL 3.0 in initial record layer version
311 {"imap.softbank.jp",993, kTLSProtocol12 }, // softbank imap server, there are multiple servers behind this, one of them is not able to handle downgrading to TLS 1.2 properly (126.240.66.17).
312 {"mobile.charter.net",993, kTLSProtocol12 }, // Support 1.2 but fail to negotiate properly
313 {"mybill.vodafone.com.au", 443, kTLSProtocol1 }, /* 2056 bit server key */
314 };
315
316 #define NSERVERS (int)(sizeof(servers)/sizeof(servers[0]))
317 #define NLOOPS 1
318
319 static void
320 tests(void)
321 {
322 int p;
323 OSStatus r;
324
325 for(p=0; p<NSERVERS;p++) {
326 for(int loops=0; loops<NLOOPS; loops++) {
327 ssl_test_handle *client;
328
329 SKIP: {
330 skip("failed to create transport", 1,
331 client = ssl_test_handle_create(&servers[p]));
332
333 r=securetransport(client);
334 ok(!r, "handshake failed with err=%ld - %s:%d (try %d)", (long)r, servers[p].host, servers[p].port, loops);
335
336 ssl_test_handle_destroy(client);
337 }
338 }
339 }
340 }
341
342 int ssl_45_tls12(int argc, char *const *argv)
343 {
344 plan_tests(NSERVERS*NLOOPS);
345
346 tests();
347
348 return 0;
349 }