]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/regressions/ssl-53-clientauth.c
Security-59306.61.1.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / regressions / ssl-53-clientauth.c
1
2 #include <stdbool.h>
3 #include <pthread.h>
4 #include <fcntl.h>
5 #include <sys/mman.h>
6 #include <unistd.h>
7
8 #include <CoreFoundation/CoreFoundation.h>
9
10 #include <AssertMacros.h>
11 #include <Security/SecureTransportPriv.h> /* SSLSetOption */
12 #include <Security/SecureTransport.h>
13 #include <Security/SecPolicy.h>
14 #include <Security/SecTrust.h>
15 #include <Security/SecIdentity.h>
16 #include <Security/SecIdentityPriv.h>
17 #include <Security/SecCertificatePriv.h>
18 #include <Security/SecKeyPriv.h>
19 #include <Security/SecItem.h>
20 #include <Security/SecRandom.h>
21
22 #include <utilities/array_size.h>
23 #include <utilities/SecCFRelease.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <mach/mach_time.h>
30
31 #if TARGET_OS_IPHONE
32 #include <Security/SecRSAKey.h>
33 #endif
34
35 #include "ssl_regressions.h"
36 #include "ssl-utils.h"
37
38 /*
39 SSL Client Auth tests:
40
41 Test both the client and server side.
42
43 Server side test goals:
44 Verify Server behavior in the following cases:
45 Server configuration:
46 - when using kTryAuthenticate vs kAlwaysAuthenticate
47 - with or without breakOnClientAuth.
48 - AnonDH and PSK ciphersuites.
49 Client configuration:
50 - Client sends back no cert vs a cert.
51 - Client sends back an unsupported cert.
52 - Client sends back a malformed cert.
53 - Client cert is trusted vs untrusted.
54 - Client does not have private key (ie: Certificate Verify message should fail).
55 Behavior to verify:
56 - handshake pass or fail
57 - SSLGetClientCertificateState returns expected results
58
59 Client side test goals:
60 Client configuration:
61 - with or without breakOnCertRequest.
62 - no cert, vs cert.
63 Server config:
64 - No client cert requested, vs client cert requested vs client cert required.
65 Behavior to verify:
66 - handshake pass or fail
67 - SSLGetClientCertificateState returns expected results
68
69 */
70
71
72 static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
73 {
74 size_t len = *length;
75 uint8_t *ptr = (uint8_t *)data;
76
77 do {
78 ssize_t ret;
79 do {
80 ret = write((int)conn, ptr, len);
81 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
82 if (ret > 0) {
83 len -= ret;
84 ptr += ret;
85 }
86 else
87 return -36;
88 } while (len > 0);
89
90 *length = *length - len;
91 return errSecSuccess;
92 }
93
94 static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length)
95 {
96 size_t len = *length;
97 uint8_t *ptr = (uint8_t *)data;
98
99 do {
100 ssize_t ret;
101 do {
102 ret = read((int)conn, ptr, len);
103 } while ((ret < 0) && (errno == EINPROGRESS || errno == EAGAIN || errno == EINTR));
104 if (ret > 0) {
105 len -= ret;
106 ptr += ret;
107 } else {
108 printf("read error(%d): ret=%zd, errno=%d\n", (int)conn, ret, errno);
109 return -errno;
110 }
111 } while (len > 0);
112
113 *length = *length - len;
114 return errSecSuccess;
115 }
116
117 typedef struct {
118 SSLContextRef st;
119 int comm;
120 bool break_on_req;
121 CFArrayRef certs;
122 int auth; //expected client auth behavior of the server (0=no request, 1=optional , 2=required)
123 } ssl_client_handle;
124
125 static ssl_client_handle *
126 ssl_client_handle_create(bool break_on_req, int comm, CFArrayRef certs, CFArrayRef trustedCA, int auth)
127 {
128 ssl_client_handle *handle = calloc(1, sizeof(ssl_client_handle));
129 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType);
130
131 require(handle, out);
132 require(ctx, out);
133
134 require_noerr(SSLSetIOFuncs(ctx,
135 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
136 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out);
137 static const char *peer_domain_name = "localhost";
138 require_noerr(SSLSetPeerDomainName(ctx, peer_domain_name,
139 strlen(peer_domain_name)), out);
140
141 require_noerr(SSLSetTrustedRoots(ctx, trustedCA, true), out);
142
143
144 /* Setting client certificate in advance */
145 if (!break_on_req && certs) {
146 require_noerr(SSLSetCertificate(ctx, certs), out);
147 }
148
149 if (break_on_req) {
150 require_noerr(SSLSetSessionOption(ctx,
151 kSSLSessionOptionBreakOnCertRequested, true), out);
152 }
153
154 handle->break_on_req = break_on_req;
155 handle->comm = comm;
156 handle->certs = certs;
157 handle->st = ctx;
158 handle->auth = auth;
159
160 return handle;
161
162 out:
163 if (ctx)
164 CFRelease(ctx);
165 if (handle)
166 free(handle);
167
168 return NULL;
169 }
170
171 static void
172 ssl_client_handle_destroy(ssl_client_handle *handle)
173 {
174 if(handle) {
175 SSLClose(handle->st);
176 CFRelease(handle->st);
177 free(handle);
178 }
179 }
180
181 static void *securetransport_ssl_client_thread(void *arg)
182 {
183 OSStatus ortn;
184 ssl_client_handle * ssl = (ssl_client_handle *)arg;
185 SSLContextRef ctx = ssl->st;
186 bool got_client_cert_req = false;
187 SSLSessionState ssl_state;
188
189 pthread_setname_np("client thread");
190
191 require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out);
192 require_action(ssl_state==kSSLIdle, out, ortn = -1);
193
194 do {
195 ortn = SSLHandshake(ctx);
196 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
197
198 if (ortn == errSSLClientCertRequested) {
199 require_string(ssl->auth, out, "cert req not expected");
200 require_string(ssl_state==kSSLHandshake, out, "wrong client handshake state after errSSLClientCertRequested");
201 require_string(!got_client_cert_req, out, "second client cert req");
202 got_client_cert_req = true;
203
204 SSLClientCertificateState clientState;
205 SSLGetClientCertificateState(ctx, &clientState);
206 require_string(clientState==kSSLClientCertRequested, out, "Wrong client cert state after cert request");
207
208 require_string(ssl->break_on_req, out, "errSSLClientCertRequested in run not testing that");
209 if(ssl->certs) {
210 require_noerr(SSLSetCertificate(ctx, ssl->certs), out);
211 }
212
213 } else if (ortn == errSSLWouldBlock) {
214 require_string(ssl_state==kSSLHandshake, out, "Wrong client handshake state after errSSLWouldBlock");
215 }
216 } while (ortn == errSSLWouldBlock || ortn == errSSLClientCertRequested);
217
218 require_string((got_client_cert_req || !ssl->auth || !ssl->break_on_req), out, "didn't get client cert req as expected");
219
220
221 out:
222 SSLClose(ssl->st);
223 close(ssl->comm);
224 pthread_exit((void *)(intptr_t)ortn);
225 return NULL;
226 }
227
228
229 typedef struct {
230 SSLContextRef st;
231 int comm;
232 SSLAuthenticate client_auth;
233 CFArrayRef certs;
234 } ssl_server_handle;
235
236 static ssl_server_handle *
237 ssl_server_handle_create(SSLAuthenticate client_auth, int comm, CFArrayRef certs, CFArrayRef trustedCA)
238 {
239 ssl_server_handle *handle = calloc(1, sizeof(ssl_server_handle));
240 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType);
241
242 require(handle, out);
243 require(ctx, out);
244
245 require_noerr(SSLSetIOFuncs(ctx,
246 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
247 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out);
248
249 require_noerr(SSLSetCertificate(ctx, certs), out);
250
251 require_noerr(SSLSetTrustedRoots(ctx, trustedCA, true), out);
252
253 SSLAuthenticate auth;
254 require_noerr(SSLSetClientSideAuthenticate(ctx, client_auth), out);
255 require_noerr(SSLGetClientSideAuthenticate(ctx, &auth), out);
256 require(auth==client_auth, out);
257
258 handle->client_auth = client_auth;
259 handle->comm = comm;
260 handle->certs = certs;
261 handle->st = ctx;
262
263 return handle;
264
265 out:
266 if (ctx)
267 CFRelease(ctx);
268 if (handle)
269 free(handle);
270
271 return NULL;
272 }
273
274 static void
275 ssl_server_handle_destroy(ssl_server_handle *handle)
276 {
277 if(handle) {
278 SSLClose(handle->st);
279 CFRelease(handle->st);
280 free(handle);
281 }
282 }
283
284 static void *securetransport_ssl_server_thread(void *arg)
285 {
286 OSStatus ortn;
287 ssl_server_handle * ssl = (ssl_server_handle *)arg;
288 SSLContextRef ctx = ssl->st;
289 SSLSessionState ssl_state;
290
291 pthread_setname_np("server thread");
292
293 require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out);
294 require_action(ssl_state==kSSLIdle, out, ortn = -1);
295
296 do {
297 ortn = SSLHandshake(ctx);
298 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
299
300 if (ortn == errSSLWouldBlock) {
301 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
302 }
303 } while (ortn == errSSLWouldBlock);
304
305 require_noerr_quiet(ortn, out);
306
307 require_action(ssl_state==kSSLConnected, out, ortn = -1);
308
309 out:
310 SSLClose(ssl->st);
311 close(ssl->comm);
312 pthread_exit((void *)(intptr_t)ortn);
313 return NULL;
314 }
315
316
317
318 static void
319 tests(void)
320 {
321 pthread_t client_thread, server_thread;
322 CFArrayRef server_certs = server_chain();
323 CFArrayRef trusted_ca = trusted_roots();
324
325 ok(server_certs, "got server certs");
326 ok(trusted_ca, "got trusted roots");
327
328 int i, j, k;
329
330 for (i=0; i<3; i++) {/* client side cert: 0 = no cert, 1 = trusted cert, 2 = untrusted cert. */
331 for (j=0; j<2; j++) { /* break on cert request */
332 for (k=0; k<3; k++) { /* server behvior: 0 = no cert request, 1 = optional cert, 2 = required cert */
333
334 int sp[2];
335 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno);
336 fcntl(sp[0], F_SETNOSIGPIPE, 1);
337 fcntl(sp[1], F_SETNOSIGPIPE, 1);
338
339 bool break_on_req = (j!=0);
340 SSLAuthenticate auth = (k == 0) ? kNeverAuthenticate
341 : (k == 1) ? kTryAuthenticate
342 : kAlwaysAuthenticate;
343
344 CFArrayRef client_certs = (i == 0) ? NULL
345 : (i == 1) ? trusted_client_chain()
346 : untrusted_client_chain();
347
348 ssl_client_handle *client;
349 client = ssl_client_handle_create(break_on_req, sp[0], client_certs, trusted_ca, auth);
350
351 ssl_server_handle *server;
352 server = ssl_server_handle_create(auth, sp[1], server_certs, trusted_ca);
353
354 pthread_create(&client_thread, NULL, securetransport_ssl_client_thread, client);
355 pthread_create(&server_thread, NULL, securetransport_ssl_server_thread, server);
356
357 intptr_t server_err, client_err;
358 int expected_server_err = 0, expected_client_err = 0;
359 SSLClientCertificateState client_cauth_state, server_cauth_state;
360 SSLClientCertificateState expected_client_cauth_state = 0, expected_server_cauth_state = 0;
361
362
363 if(((k == 2) && (i != 1)) // Server requires good cert, but client not sending good cert,
364 || ((k == 1) && (i == 2)) // Or server request optionally, and client sending bad cert.
365 ) {
366 expected_client_err = errSSLPeerCertUnknown;
367 expected_server_err = errSSLXCertChainInvalid;
368 }
369
370
371 if(k != 0) {
372 if(i == 0) {
373 expected_client_cauth_state = kSSLClientCertRequested;
374 expected_server_cauth_state = kSSLClientCertRequested;
375 } else {
376 expected_client_cauth_state = kSSLClientCertSent;
377 expected_server_cauth_state = kSSLClientCertSent;
378 }
379 }
380
381 pthread_join(client_thread, (void*)&client_err);
382 pthread_join(server_thread, (void*)&server_err);
383
384
385 ok_status(SSLGetClientCertificateState(client->st, &client_cauth_state), "SSLGetClientCertificateState (client %d:%d:%d)", i, j, k);
386 ok_status(SSLGetClientCertificateState(client->st, &server_cauth_state), "SSLGetClientCertificateState (server %d:%d:%d)", i, j, k);
387
388 ok(client_err==expected_client_err, "unexpected error %d!=%d (client %d:%d:%d)", (int)client_err, expected_client_err, i, j, k);
389 ok(server_err==expected_server_err, "unexpected error %d!=%d (server %d:%d:%d)", (int)server_err, expected_server_err, i, j, k);
390
391 ok(client_cauth_state==expected_client_cauth_state, "unexpected client auth state %d!=%d (client %d:%d:%d)", client_cauth_state, expected_client_cauth_state, i, j, k);
392 ok(server_cauth_state==expected_server_cauth_state, "unexpected client auth state %d!=%d (server %d:%d:%d)", server_cauth_state, expected_server_cauth_state, i, j, k);
393
394
395 ssl_server_handle_destroy(server);
396 ssl_client_handle_destroy(client);
397
398 CFReleaseSafe(client_certs);
399 }
400 }
401 }
402
403 CFReleaseSafe(server_certs);
404 CFReleaseSafe(trusted_ca);
405 }
406
407 int ssl_53_clientauth(int argc, char *const *argv)
408 {
409
410 plan_tests(3 * 3 * 2 * 6 + 2 /*cert*/);
411
412
413 tests();
414
415 return 0;
416 }