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 58typedef struct { 59 uint32_t session_id; 60 bool is_session_resume; 61 SSLContextRef st; 62 bool is_server; 63 bool client_side_auth; 64 bool dh_anonymous; 65 int comm; 66 CFArrayRef certs; 67} ssl_test_handle; 68 69 70 71#if 0 72static void hexdump(const uint8_t *bytes, size_t len) { 73 size_t ix; 74 printf("socket write(%p, %lu)\n", bytes, len); 75 for (ix = 0; ix < len; ++ix) { 76 if (!(ix % 16)) 77 printf("\n"); 78 printf("%02X ", bytes[ix]); 79 } 80 printf("\n"); 81} 82#else 83#define hexdump(bytes, len) 84#endif 85 86static int SocketConnect(const char *hostName, int port) 87{ 88 struct sockaddr_in addr; 89 struct in_addr host; 90 int sock; 91 int err; 92 struct hostent *ent; 93 94 if (hostName[0] >= '0' && hostName[0] <= '9') 95 { 96 host.s_addr = inet_addr(hostName); 97 } 98 else { 99 unsigned dex; 100#define GETHOST_RETRIES 5 101 /* seeing a lot of soft failures here that I really don't want to track down */ 102 for(dex=0; dex<GETHOST_RETRIES; dex++) { 103 if(dex != 0) { 104 printf("\n...retrying gethostbyname(%s)", hostName); 105 } 106 ent = gethostbyname(hostName); 107 if(ent != NULL) { 108 break; 109 } 110 } 111 if(ent == NULL) { 112 printf("\n***gethostbyname(%s) returned: %s\n", hostName, hstrerror(h_errno)); 113 return -1; 114 } 115 memcpy(&host, ent->h_addr, sizeof(struct in_addr)); 116 } 117 118 119 sock = socket(AF_INET, SOCK_STREAM, 0); 120 addr.sin_addr = host; 121 addr.sin_port = htons((u_short)port); 122 123 addr.sin_family = AF_INET; 124 err = connect(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)); 125 126 if(err!=0) 127 { 128 perror("connect failed"); 129 return err; 130 } 131 132 return sock; 133} 134 135 136static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length) 137{ 138 size_t len = *length; 139 uint8_t *ptr = (uint8_t *)data; 140 141 do { 142 ssize_t ret; 143 do { 144 hexdump(ptr, len); 145 ret = write((int)conn, ptr, len); 146 if (ret < 0) 147 perror("send"); 148 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR)); 149 if (ret > 0) { 150 len -= ret; 151 ptr += ret; 152 } 153 else 154 return -36; 155 } while (len > 0); 156 157 *length = *length - len; 158 return errSecSuccess; 159} 160 161static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length) 162{ 163 size_t len = *length; 164 uint8_t *ptr = (uint8_t *)data; 165 166 do { 167 ssize_t ret; 168 do { 169 ret = read((int)conn, ptr, len); 170 if (ret < 0) 171 perror("send"); 172 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR)); 173 if (ret > 0) { 174 len -= ret; 175 ptr += ret; 176 } 177 else 178 return -36; 179 } while (len > 0); 180 181 *length = *length - len; 182 return errSecSuccess; 183} 184 185static SSLContextRef make_ssl_ref(int sock, SSLProtocol maxprot) 186{ 187 SSLContextRef ctx = NULL; 188 189 require_noerr(SSLNewContext(false, &ctx), out); 190 require_noerr(SSLSetIOFuncs(ctx, 191 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out); 192 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out); 193 194 require_noerr(SSLSetSessionOption(ctx, 195 kSSLSessionOptionBreakOnServerAuth, true), out); 196 197 require_noerr(SSLSetProtocolVersionMax(ctx, maxprot), out); 198 /* Tell SecureTransport to not check certs itself: it will break out of the 199 handshake to let us take care of it instead. */ 200 require_noerr(SSLSetEnableCertVerify(ctx, false), out); 201 202 return ctx; 203out: 204 if (ctx) 205 SSLDisposeContext(ctx); 206 return NULL; 207} 208 209static OSStatus securetransport(ssl_test_handle * ssl) 210{ 211 OSStatus ortn; 212 SSLContextRef ctx = ssl->st; 213 SecTrustRef trust = NULL; 214 bool got_server_auth = false, got_client_cert_req = false; 215 216 //uint64_t start = mach_absolute_time(); 217 do { 218 ortn = SSLHandshake(ctx); 219 220 if (ortn == errSSLServerAuthCompleted) 221 { 222 require_string(!got_server_auth, out, "second server auth"); 223 require_string(!got_client_cert_req, out, "got client cert req before server auth"); 224 got_server_auth = true; 225 require_string(!trust, out, "Got errSSLServerAuthCompleted twice?"); 226 /* verify peer cert chain */ 227 require_noerr(SSLCopyPeerTrust(ctx, &trust), out); 228 SecTrustResultType trust_result = 0; 229 /* this won't verify without setting up a trusted anchor */ 230 require_noerr(SecTrustEvaluate(trust, &trust_result), out); 231 232 } } while (ortn == errSSLWouldBlock 233 || ortn == errSSLServerAuthCompleted); 234 require_noerr_action_quiet(ortn, out, 235 fprintf(stderr, "Fell out of SSLHandshake with error: %d\n", (int)ortn)); 236 237 require_string(got_server_auth, out, "never got server auth"); 238 239 //uint64_t elapsed = mach_absolute_time() - start; 240 //fprintf(stderr, "setr elapsed: %lld\n", elapsed); 241 242 /* 243 SSLProtocol proto = kSSLProtocolUnknown; 244 require_noerr_quiet(SSLGetNegotiatedProtocolVersion(ctx, &proto), out); */ 245 246 SSLCipherSuite cipherSuite; 247 require_noerr_quiet(ortn = SSLGetNegotiatedCipher(ctx, &cipherSuite), out); 248 //fprintf(stderr, "st negotiated %02x\n", cipherSuite); 249 250 251out: 252 SSLClose(ctx); 253 SSLDisposeContext(ctx); 254 if (trust) CFRelease(trust); 255 256 return ortn; 257} 258 259 260 261static ssl_test_handle * 262ssl_test_handle_create(int comm, SSLProtocol maxprot) 263{ 264 ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle)); 265 if (handle) { 266 handle->comm = comm; 267 handle->st = make_ssl_ref(comm, maxprot); 268 } 269 return handle; 270} 271 272struct s_server { 273 char *host; 274 int port; 275 SSLProtocol maxprot; 276} servers[] = { 277 /* Good tls 1.2 servers */ 278 {"encrypted.google.com", 443, kTLSProtocol12 }, 279 {"www.amazon.com",443, kTLSProtocol12 }, 280 //{"www.mikestoolbox.org",443, kTLSProtocol12 }, 281 /* servers with issues */ 282 {"vpp.visa.co.uk", 443, kTLSProtocol12 }, // Doesnt like SSL 3.0 in initial record layer version 283 {"imap.softbank.jp",993, kTLSProtocol1 }, // 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). 284 {"mobile.charter.net",993, kTLSProtocol1 }, // Support 1.2 but fail to negotiate properly 285 {"mybill.vodafone.com.au", 443, kTLSProtocol1 }, /* 2056 bit server key */ 286}; 287 288#define NSERVERS (int)(sizeof(servers)/sizeof(servers[0])) 289#define NLOOPS 1 290 291static void 292tests(void) 293{ 294 int p; 295 296 for(p=0; p<NSERVERS;p++) { 297 for(int loops=0; loops<NLOOPS; loops++) { 298 299 ssl_test_handle *client; 300 301 int s; 302 OSStatus r; 303 304 s=SocketConnect(servers[p].host, servers[p].port); 305 if(s<0) { 306 fail("connect failed with err=%d - %s:%d (try %d)", s, servers[p].host, servers[p].port, loops); 307 break; 308 } 309 310 client = ssl_test_handle_create(s, servers[p].maxprot); 311 312 r=securetransport(client); 313 ok(!r, "handshake failed with err=%ld - %s:%d (try %d)", (long)r, servers[p].host, servers[p].port, loops); 314 315 free(client); 316 close(s); 317 } } 318} 319 320int ssl_45_tls12(int argc, char *const *argv) 321{ 322 plan_tests(NSERVERS*NLOOPS); 323 324 tests(); 325 326 return 0; 327} 328