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