8 #include <CoreFoundation/CoreFoundation.h>
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>
22 #include <utilities/array_size.h>
23 #include <utilities/SecCFRelease.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
29 #include <mach/mach_time.h>
32 #include <Security/SecRSAKey.h>
35 #include "ssl_regressions.h"
36 #include "ssl-utils.h"
39 SSL Client Auth tests:
41 Test both the client and server side.
43 Server side test goals:
44 Verify Server behavior in the following cases:
46 - when using kTryAuthenticate vs kAlwaysAuthenticate
47 - with or without breakOnClientAuth.
48 - AnonDH and PSK ciphersuites.
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).
56 - handshake pass or fail
57 - SSLGetClientCertificateState returns expected results
59 Client side test goals:
61 - with or without breakOnCertRequest.
64 - No client cert requested, vs client cert requested vs client cert required.
66 - handshake pass or fail
67 - SSLGetClientCertificateState returns expected results
72 static OSStatus
SocketWrite(SSLConnectionRef conn
, const void *data
, size_t *length
)
75 uint8_t *ptr
= (uint8_t *)data
;
80 ret
= write((int)conn
, ptr
, len
);
81 } while ((ret
< 0) && (errno
== EAGAIN
|| errno
== EINTR
));
90 *length
= *length
- len
;
94 static OSStatus
SocketRead(SSLConnectionRef conn
, void *data
, size_t *length
)
97 uint8_t *ptr
= (uint8_t *)data
;
102 ret
= read((int)conn
, ptr
, len
);
103 } while ((ret
< 0) && (errno
== EINPROGRESS
|| errno
== EAGAIN
|| errno
== EINTR
));
108 printf("read error(%d): ret=%zd, errno=%d\n", (int)conn
, ret
, errno
);
113 *length
= *length
- len
;
114 return errSecSuccess
;
122 int auth
; //expected client auth behavior of the server (0=no request, 1=optional , 2=required)
125 static ssl_client_handle
*
126 ssl_client_handle_create(bool break_on_req
, int comm
, CFArrayRef certs
, CFArrayRef trustedCA
, int auth
)
128 ssl_client_handle
*handle
= calloc(1, sizeof(ssl_client_handle
));
129 SSLContextRef ctx
= SSLCreateContext(kCFAllocatorDefault
, kSSLClientSide
, kSSLStreamType
);
131 require(handle
, out
);
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
);
141 require_noerr(SSLSetTrustedRoots(ctx
, trustedCA
, true), out
);
144 /* Setting client certificate in advance */
145 if (!break_on_req
&& certs
) {
146 require_noerr(SSLSetCertificate(ctx
, certs
), out
);
150 require_noerr(SSLSetSessionOption(ctx
,
151 kSSLSessionOptionBreakOnCertRequested
, true), out
);
154 handle
->break_on_req
= break_on_req
;
156 handle
->certs
= certs
;
172 ssl_client_handle_destroy(ssl_client_handle
*handle
)
175 SSLClose(handle
->st
);
176 CFRelease(handle
->st
);
181 static void *securetransport_ssl_client_thread(void *arg
)
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
;
189 pthread_setname_np("client thread");
191 require_noerr(ortn
=SSLGetSessionState(ctx
,&ssl_state
), out
);
192 require_action(ssl_state
==kSSLIdle
, out
, ortn
= -1);
195 ortn
= SSLHandshake(ctx
);
196 require_noerr(SSLGetSessionState(ctx
,&ssl_state
), out
);
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;
204 SSLClientCertificateState clientState
;
205 SSLGetClientCertificateState(ctx
, &clientState
);
206 require_string(clientState
==kSSLClientCertRequested
, out
, "Wrong client cert state after cert request");
208 require_string(ssl
->break_on_req
, out
, "errSSLClientCertRequested in run not testing that");
210 require_noerr(SSLSetCertificate(ctx
, ssl
->certs
), out
);
213 } else if (ortn
== errSSLWouldBlock
) {
214 require_string(ssl_state
==kSSLHandshake
, out
, "Wrong client handshake state after errSSLWouldBlock");
216 } while (ortn
== errSSLWouldBlock
|| ortn
== errSSLClientCertRequested
);
218 require_string((got_client_cert_req
|| !ssl
->auth
|| !ssl
->break_on_req
), out
, "didn't get client cert req as expected");
224 pthread_exit((void *)(intptr_t)ortn
);
232 SSLAuthenticate client_auth
;
236 static ssl_server_handle
*
237 ssl_server_handle_create(SSLAuthenticate client_auth
, int comm
, CFArrayRef certs
, CFArrayRef trustedCA
)
239 ssl_server_handle
*handle
= calloc(1, sizeof(ssl_server_handle
));
240 SSLContextRef ctx
= SSLCreateContext(kCFAllocatorDefault
, kSSLServerSide
, kSSLStreamType
);
242 require(handle
, out
);
245 require_noerr(SSLSetIOFuncs(ctx
,
246 (SSLReadFunc
)SocketRead
, (SSLWriteFunc
)SocketWrite
), out
);
247 require_noerr(SSLSetConnection(ctx
, (SSLConnectionRef
)(intptr_t)comm
), out
);
249 require_noerr(SSLSetCertificate(ctx
, certs
), out
);
251 require_noerr(SSLSetTrustedRoots(ctx
, trustedCA
, true), out
);
253 SSLAuthenticate auth
;
254 require_noerr(SSLSetClientSideAuthenticate(ctx
, client_auth
), out
);
255 require_noerr(SSLGetClientSideAuthenticate(ctx
, &auth
), out
);
256 require(auth
==client_auth
, out
);
258 handle
->client_auth
= client_auth
;
260 handle
->certs
= certs
;
275 ssl_server_handle_destroy(ssl_server_handle
*handle
)
278 SSLClose(handle
->st
);
279 CFRelease(handle
->st
);
284 static void *securetransport_ssl_server_thread(void *arg
)
287 ssl_server_handle
* ssl
= (ssl_server_handle
*)arg
;
288 SSLContextRef ctx
= ssl
->st
;
289 SSLSessionState ssl_state
;
291 pthread_setname_np("server thread");
293 require_noerr(ortn
=SSLGetSessionState(ctx
,&ssl_state
), out
);
294 require_action(ssl_state
==kSSLIdle
, out
, ortn
= -1);
297 ortn
= SSLHandshake(ctx
);
298 require_noerr(SSLGetSessionState(ctx
,&ssl_state
), out
);
300 if (ortn
== errSSLWouldBlock
) {
301 require_action(ssl_state
==kSSLHandshake
, out
, ortn
= -1);
303 } while (ortn
== errSSLWouldBlock
);
305 require_noerr_quiet(ortn
, out
);
307 require_action(ssl_state
==kSSLConnected
, out
, ortn
= -1);
312 pthread_exit((void *)(intptr_t)ortn
);
321 pthread_t client_thread
, server_thread
;
322 CFArrayRef server_certs
= server_chain();
323 CFArrayRef trusted_ca
= trusted_roots();
325 ok(server_certs
, "got server certs");
326 ok(trusted_ca
, "got trusted roots");
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 */
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);
339 bool break_on_req
= (j
!=0);
340 SSLAuthenticate auth
= (k
== 0) ? kNeverAuthenticate
341 : (k
== 1) ? kTryAuthenticate
342 : kAlwaysAuthenticate
;
344 CFArrayRef client_certs
= (i
== 0) ? NULL
345 : (i
== 1) ? trusted_client_chain()
346 : untrusted_client_chain();
348 ssl_client_handle
*client
;
349 client
= ssl_client_handle_create(break_on_req
, sp
[0], client_certs
, trusted_ca
, auth
);
351 ssl_server_handle
*server
;
352 server
= ssl_server_handle_create(auth
, sp
[1], server_certs
, trusted_ca
);
354 pthread_create(&client_thread
, NULL
, securetransport_ssl_client_thread
, client
);
355 pthread_create(&server_thread
, NULL
, securetransport_ssl_server_thread
, server
);
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;
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.
366 expected_client_err
= errSSLPeerCertUnknown
;
367 expected_server_err
= errSSLXCertChainInvalid
;
373 expected_client_cauth_state
= kSSLClientCertRequested
;
374 expected_server_cauth_state
= kSSLClientCertRequested
;
376 expected_client_cauth_state
= kSSLClientCertSent
;
377 expected_server_cauth_state
= kSSLClientCertSent
;
381 pthread_join(client_thread
, (void*)&client_err
);
382 pthread_join(server_thread
, (void*)&server_err
);
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
);
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
);
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
);
395 ssl_server_handle_destroy(server
);
396 ssl_client_handle_destroy(client
);
398 CFReleaseSafe(client_certs
);
403 CFReleaseSafe(server_certs
);
404 CFReleaseSafe(trusted_ca
);
407 int ssl_53_clientauth(int argc
, char *const *argv
)
410 plan_tests(3 * 3 * 2 * 6 + 2 /*cert*/);