]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+sni.m
Security-58286.200.222.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / regressions / SecureTransportTests / STLegacyTests+sni.m
1 #include <stdbool.h>
2 #include <pthread.h>
3 #include <fcntl.h>
4 #include <sys/mman.h>
5 #include <unistd.h>
6
7 #include <CoreFoundation/CoreFoundation.h>
8
9 #include <AssertMacros.h>
10 #include <Security/SecureTransportPriv.h> /* SSLSetOption */
11 #include <Security/SecureTransport.h>
12 #include <Security/SecPolicy.h>
13 #include <Security/SecTrust.h>
14 #include <Security/SecIdentity.h>
15 #include <Security/SecIdentityPriv.h>
16 #include <Security/SecCertificatePriv.h>
17 #include <Security/SecKeyPriv.h>
18 #include <Security/SecItem.h>
19 #include <Security/SecRandom.h>
20
21 #include <string.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <errno.h>
25 #include <stdlib.h>
26 #include <mach/mach_time.h>
27
28 #if TARGET_OS_IPHONE
29 #include <Security/SecRSAKey.h>
30 #endif
31
32 #include "ssl-utils.h"
33 #import "STLegacyTests.h"
34
35 @implementation STLegacyTests (sni)
36
37 typedef struct {
38 SSLContextRef handle;
39 uint32_t session_id;
40 bool is_server;
41 int comm;
42 } ssl_test_handle;
43
44
45 #pragma mark -
46 #pragma mark SecureTransport support
47
48 #if 0
49 static void hexdump(const uint8_t *bytes, size_t len) {
50 size_t ix;
51 printf("socket write(%p, %lu)\n", bytes, len);
52 for (ix = 0; ix < len; ++ix) {
53 if (!(ix % 16))
54 printf("\n");
55 printf("%02X ", bytes[ix]);
56 }
57 printf("\n");
58 }
59 #else
60 #define hexdump(bytes, len)
61 #endif
62
63
64 static OSStatus SocketWrite(SSLConnectionRef h, const void *data, size_t *length)
65 {
66 size_t len = *length;
67 uint8_t *ptr = (uint8_t *)data;
68
69 do {
70 ssize_t ret;
71 do {
72 hexdump(ptr, len);
73 ret = write((int)h, ptr, len);
74 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
75 if (ret > 0) {
76 len -= ret;
77 ptr += ret;
78 }
79 else
80 return -36;
81 } while (len > 0);
82
83 *length = *length - len;
84 return errSecSuccess;
85 }
86
87 static OSStatus SocketRead(SSLConnectionRef h, void *data, size_t *length)
88 {
89 size_t len = *length;
90 uint8_t *ptr = (uint8_t *)data;
91
92 do {
93 ssize_t ret;
94 do {
95 ret = read((int)h, ptr, len);
96 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
97 if (ret > 0) {
98 len -= ret;
99 ptr += ret;
100 } else {
101 printf("read error(%d): ret=%zd, errno=%d\n", (int)h, ret, errno);
102 return -errno;
103 }
104 } while (len > 0);
105
106 *length = *length - len;
107 return errSecSuccess;
108 }
109
110 static char peername[] = "localhost";
111
112 static void *securetransport_server_thread(void *arg)
113 {
114 OSStatus ortn;
115 ssl_test_handle * ssl = (ssl_test_handle *)arg;
116 SSLContextRef ctx = ssl->handle;
117 CFArrayRef server_certs = server_chain();
118
119 do {
120 ortn = SSLHandshake(ctx);
121 } while (ortn == errSSLWouldBlock);
122
123 ok(ortn==errSSLClientHelloReceived, "Unexpected Handshake exit code");
124
125 if (ortn == errSSLClientHelloReceived) {
126 char *sni = NULL;
127 size_t length = 0;
128 SSLCopyRequestedPeerNameLength(ctx, &length);
129 if (length > 0) {
130 sni = malloc(length);
131 SSLCopyRequestedPeerName(ctx, sni, &length);
132 }
133
134 SSLProtocol version = 0;
135 require_noerr(SSLGetProtocolVersionMax(ctx, &version), out);
136 if (version == kSSLProtocol3) {
137 ok(sni==NULL, "Unexpected SNI");
138 } else {
139 ok(sni!=NULL &&
140 length == sizeof(peername) &&
141 (memcmp(sni, peername, sizeof(peername))==0),
142 "SNI does not match");
143 }
144 require_noerr(SSLSetCertificate(ctx, server_certs), out);
145 free(sni);
146 }
147
148 out:
149 SSLClose(ctx);
150 SSLDisposeContext(ctx);
151 close(ssl->comm);
152 CFReleaseSafe(server_certs);
153
154 pthread_exit((void *)(intptr_t)ortn);
155 return NULL;
156 }
157
158 static void *securetransport_client_thread(void *arg)
159 {
160 OSStatus ortn;
161 ssl_test_handle * ssl = (ssl_test_handle *)arg;
162 SSLContextRef ctx = ssl->handle;
163
164 do {
165 ortn = SSLHandshake(ctx);
166 } while (ortn == errSSLWouldBlock || ortn != errSSLClosedGraceful);
167
168 SSLClose(ctx);
169 SSLDisposeContext(ctx);
170 close(ssl->comm);
171
172 pthread_exit((void *)(intptr_t)ortn);
173 return NULL;
174 }
175
176 static SSLCipherSuite ciphers[] = {
177 TLS_RSA_WITH_AES_128_CBC_SHA,
178 };
179
180 static ssl_test_handle *
181 ssl_test_handle_create(uint32_t session_id, bool server, int comm)
182 {
183 ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle));
184 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, server?kSSLServerSide:kSSLClientSide, kSSLStreamType);
185
186 require(handle, out);
187 require(ctx, out);
188
189 require_noerr(SSLSetIOFuncs(ctx,
190 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
191 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out);
192
193 if (server)
194 require_noerr(SSLSetSessionOption(ctx,
195 kSSLSessionOptionBreakOnClientHello, true), out);
196 else
197 require_noerr(SSLSetSessionOption(ctx,
198 kSSLSessionOptionBreakOnServerAuth, true), out);
199
200 /* Tell SecureTransport to not check certs itself: it will break out of the
201 handshake to let us take care of it instead. */
202 require_noerr(SSLSetEnableCertVerify(ctx, false), out);
203
204 handle->handle = ctx;
205 handle->is_server = server;
206 handle->session_id = session_id;
207 handle->comm = comm;
208
209 return handle;
210
211 out:
212 if (handle) free(handle);
213 if (ctx) CFRelease(ctx);
214 return NULL;
215 }
216
217 static SSLProtocol versions[] = {
218 kSSLProtocol3,
219 kTLSProtocol1,
220 kTLSProtocol11,
221 kTLSProtocol12,
222 };
223 static int nversions = sizeof(versions)/sizeof(versions[0]);
224
225 -(void)testSNI
226 {
227 int j;
228 pthread_t client_thread, server_thread;
229
230 for(j=0; j<nversions; j++)
231 {
232 int sp[2];
233 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno);
234
235 ssl_test_handle *server, *client;
236
237 uint32_t session_id = (j+1) << 16 | 1 << 8;
238 server = ssl_test_handle_create(session_id, true /*server*/, sp[0]);
239 client = ssl_test_handle_create(session_id, false/*client*/, sp[1]);
240
241 require_noerr(SSLSetPeerID(server->handle, &session_id, sizeof(session_id)), out);
242 require_noerr(SSLSetPeerID(client->handle, &session_id, sizeof(session_id)), out);
243
244 /* set fixed cipher on client and server */
245 require_noerr(SSLSetEnabledCiphers(client->handle, &ciphers[0], 1), out);
246 require_noerr(SSLSetEnabledCiphers(server->handle, &ciphers[0], 1), out);
247
248 require_noerr(SSLSetProtocolVersionMax(client->handle, versions[j]), out);
249 require_noerr(SSLSetPeerDomainName(client->handle, peername, sizeof(peername)), out);
250
251 require_noerr(SSLSetProtocolVersionMax(server->handle, versions[j]), out);
252
253 pthread_create(&client_thread, NULL, securetransport_client_thread, client);
254 pthread_create(&server_thread, NULL, securetransport_server_thread, server);
255
256 intptr_t server_err, client_err;
257 pthread_join(client_thread, (void*)&client_err);
258 pthread_join(server_thread, (void*)&server_err);
259
260 out:
261 free(client);
262 free(server);
263
264 }
265 }
266
267 @end