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>
24 #include <sys/types.h>
25 #include <sys/socket.h>
28 #include <mach/mach_time.h>
31 #include <Security/SecRSAKey.h>
34 #include "ssl_regressions.h"
35 #include "ssl-utils.h"
38 SSL Client Auth tests:
40 Test both the client and server side.
42 Server side test goals:
43 Verify Server behavior in the following cases:
45 - when using kTryAuthenticate vs kAlwaysAuthenticate
46 - with or without breakOnClientAuth.
47 - AnonDH and PSK ciphersuites.
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).
55 - handshake pass or fail
56 - SSLGetClientCertificateState returns expected results
58 Client side test goals:
60 - with or without breakOnCertRequest.
63 - No client cert requested, vs client cert requested vs client cert required.
65 - handshake pass or fail
66 - SSLGetClientCertificateState returns expected results
71 static OSStatus
SocketWrite(SSLConnectionRef conn
, const void *data
, size_t *length
)
74 uint8_t *ptr
= (uint8_t *)data
;
79 ret
= write((int)conn
, ptr
, len
);
80 } while ((ret
< 0) && (errno
== EAGAIN
|| errno
== EINTR
));
89 *length
= *length
- len
;
93 static OSStatus
SocketRead(SSLConnectionRef conn
, void *data
, size_t *length
)
96 uint8_t *ptr
= (uint8_t *)data
;
101 ret
= read((int)conn
, ptr
, len
);
102 } while ((ret
< 0) && (errno
== EINPROGRESS
|| errno
== EAGAIN
|| errno
== EINTR
));
107 printf("read error(%d): ret=%zd, errno=%d\n", (int)conn
, ret
, errno
);
112 *length
= *length
- len
;
113 return errSecSuccess
;
121 int auth
; //expected client auth behavior of the server (0=no request, 1=optional , 2=required)
124 static ssl_client_handle
*
125 ssl_client_handle_create(bool break_on_req
, int comm
, CFArrayRef certs
, CFArrayRef trustedCA
, int auth
)
127 ssl_client_handle
*handle
= calloc(1, sizeof(ssl_client_handle
));
128 SSLContextRef ctx
= SSLCreateContext(kCFAllocatorDefault
, kSSLClientSide
, kSSLStreamType
);
130 require(handle
, out
);
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
);
140 require_noerr(SSLSetTrustedRoots(ctx
, trustedCA
, true), out
);
143 /* Setting client certificate in advance */
144 if (!break_on_req
&& certs
) {
145 require_noerr(SSLSetCertificate(ctx
, certs
), out
);
149 require_noerr(SSLSetSessionOption(ctx
,
150 kSSLSessionOptionBreakOnCertRequested
, true), out
);
153 handle
->break_on_req
= break_on_req
;
155 handle
->certs
= certs
;
171 ssl_client_handle_destroy(ssl_client_handle
*handle
)
174 SSLClose(handle
->st
);
175 CFRelease(handle
->st
);
180 static void *securetransport_ssl_client_thread(void *arg
)
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
;
188 pthread_setname_np("client thread");
190 require_noerr(ortn
=SSLGetSessionState(ctx
,&ssl_state
), out
);
191 require_action(ssl_state
==kSSLIdle
, out
, ortn
= -1);
194 ortn
= SSLHandshake(ctx
);
195 require_noerr(SSLGetSessionState(ctx
,&ssl_state
), out
);
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;
203 SSLClientCertificateState clientState
;
204 SSLGetClientCertificateState(ctx
, &clientState
);
205 require_string(clientState
==kSSLClientCertRequested
, out
, "Wrong client cert state after cert request");
207 require_string(ssl
->break_on_req
, out
, "errSSLClientCertRequested in run not testing that");
209 require_noerr(SSLSetCertificate(ctx
, ssl
->certs
), out
);
212 } else if (ortn
== errSSLWouldBlock
) {
213 require_string(ssl_state
==kSSLHandshake
, out
, "Wrong client handshake state after errSSLWouldBlock");
215 } while (ortn
== errSSLWouldBlock
|| ortn
== errSSLClientCertRequested
);
217 require_string((got_client_cert_req
|| !ssl
->auth
|| !ssl
->break_on_req
), out
, "didn't get client cert req as expected");
223 pthread_exit((void *)(intptr_t)ortn
);
231 SSLAuthenticate client_auth
;
235 static ssl_server_handle
*
236 ssl_server_handle_create(SSLAuthenticate client_auth
, int comm
, CFArrayRef certs
, CFArrayRef trustedCA
)
238 ssl_server_handle
*handle
= calloc(1, sizeof(ssl_server_handle
));
239 SSLContextRef ctx
= SSLCreateContext(kCFAllocatorDefault
, kSSLServerSide
, kSSLStreamType
);
241 require(handle
, out
);
244 require_noerr(SSLSetIOFuncs(ctx
,
245 (SSLReadFunc
)SocketRead
, (SSLWriteFunc
)SocketWrite
), out
);
246 require_noerr(SSLSetConnection(ctx
, (SSLConnectionRef
)(intptr_t)comm
), out
);
248 require_noerr(SSLSetCertificate(ctx
, certs
), out
);
250 require_noerr(SSLSetTrustedRoots(ctx
, trustedCA
, true), out
);
252 SSLAuthenticate auth
;
253 require_noerr(SSLSetClientSideAuthenticate(ctx
, client_auth
), out
);
254 require_noerr(SSLGetClientSideAuthenticate(ctx
, &auth
), out
);
255 require(auth
==client_auth
, out
);
257 handle
->client_auth
= client_auth
;
259 handle
->certs
= certs
;
274 ssl_server_handle_destroy(ssl_server_handle
*handle
)
277 SSLClose(handle
->st
);
278 CFRelease(handle
->st
);
283 static void *securetransport_ssl_server_thread(void *arg
)
286 ssl_server_handle
* ssl
= (ssl_server_handle
*)arg
;
287 SSLContextRef ctx
= ssl
->st
;
288 SSLSessionState ssl_state
;
290 pthread_setname_np("server thread");
292 require_noerr(ortn
=SSLGetSessionState(ctx
,&ssl_state
), out
);
293 require_action(ssl_state
==kSSLIdle
, out
, ortn
= -1);
296 ortn
= SSLHandshake(ctx
);
297 require_noerr(SSLGetSessionState(ctx
,&ssl_state
), out
);
299 if (ortn
== errSSLWouldBlock
) {
300 require_action(ssl_state
==kSSLHandshake
, out
, ortn
= -1);
302 } while (ortn
== errSSLWouldBlock
);
304 require_noerr_quiet(ortn
, out
);
306 require_action(ssl_state
==kSSLConnected
, out
, ortn
= -1);
311 pthread_exit((void *)(intptr_t)ortn
);
320 pthread_t client_thread
, server_thread
;
321 CFArrayRef server_certs
= server_chain();
322 CFArrayRef trusted_ca
= trusted_roots();
324 ok(server_certs
, "got server certs");
325 ok(trusted_ca
, "got trusted roots");
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 */
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);
338 bool break_on_req
= (j
!=0);
339 SSLAuthenticate auth
= (k
== 0) ? kNeverAuthenticate
340 : (k
== 1) ? kTryAuthenticate
341 : kAlwaysAuthenticate
;
343 CFArrayRef client_certs
= (i
== 0) ? NULL
344 : (i
== 1) ? trusted_client_chain()
345 : untrusted_client_chain();
347 ssl_client_handle
*client
;
348 client
= ssl_client_handle_create(break_on_req
, sp
[0], client_certs
, trusted_ca
, auth
);
350 ssl_server_handle
*server
;
351 server
= ssl_server_handle_create(auth
, sp
[1], server_certs
, trusted_ca
);
353 pthread_create(&client_thread
, NULL
, securetransport_ssl_client_thread
, client
);
354 pthread_create(&server_thread
, NULL
, securetransport_ssl_server_thread
, server
);
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;
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.
365 expected_client_err
= errSSLPeerCertUnknown
;
366 expected_server_err
= errSSLXCertChainInvalid
;
372 expected_client_cauth_state
= kSSLClientCertRequested
;
373 expected_server_cauth_state
= kSSLClientCertRequested
;
375 expected_client_cauth_state
= kSSLClientCertSent
;
376 expected_server_cauth_state
= kSSLClientCertSent
;
380 pthread_join(client_thread
, (void*)&client_err
);
381 pthread_join(server_thread
, (void*)&server_err
);
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
);
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
);
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
);
394 ssl_server_handle_destroy(server
);
395 ssl_client_handle_destroy(client
);
397 CFReleaseSafe(client_certs
);
402 CFReleaseSafe(server_certs
);
403 CFReleaseSafe(trusted_ca
);
406 int ssl_53_clientauth(int argc
, char *const *argv
)
409 plan_tests(3 * 3 * 2 * 6 + 2 /*cert*/);