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