]>
git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/clAppUtils/sslServe.cpp
2 * sslServe.cpp : perform one server side sesssion
4 #include <Security/SecureTransport.h>
5 #include <Security/Security.h>
6 #include <clAppUtils/sslAppUtils.h>
7 #include <clAppUtils/ioSock.h>
8 #include <clAppUtils/sslThreading.h>
9 #include <clAppUtils/ringBufferIo.h>
10 #include <security_cdsa_utils/cuFileIo.h>
11 #include <utilLib/common.h>
12 #include <security_cdsa_utils/cuPrintCert.h>
14 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
20 #include <sys/param.h>
22 #define BIND_RETRIES 50
24 #define SERVER_MESSAGE "HTTP/1.0 200 OK\015\012\015\012" \
25 "<HTML><HEAD><TITLE>SecureTransport Test Server</TITLE></HEAD>" \
26 "<BODY><H2>Secure connection established.</H2>" \
27 "Message from the 'sslServe' test library.\015\012</BODY>" \
30 #define READBUF_LEN 256
33 * When true, delay setting the serverReady semaphore until we've finished
34 * setting up our SSLContext. This is a workaround for known thread-unsafety
35 * related to module attach and detach and context create/destroy:
37 * <rdar://problem/6618834> Crash in KCCursorImpl::next
38 * <rdar://problem/6621552> module/context handles not thread safe
40 #define SERVER_READY_DELAY 1
43 * params->lock is held for us by runSession() - we use it as a semapahore by
44 * unlocking it when we've created a port to listen on.
45 * This is generally run from a thread via sslRunSession() and
46 * sslServerThread() in sslAppUtils.cpp.
49 SslAppTestParams
*params
)
51 otSocket listenSock
= 0;
52 otSocket acceptSock
= 0;
54 OSStatus ortn
= noErr
;
55 SSLContextRef ctx
= NULL
;
56 SecKeychainRef serverKc
= nil
;
57 CFArrayRef serverCerts
= nil
;
58 RingBuffers ringBufs
= {params
->clientToServerRing
, params
->serverToClientRing
};
60 sslThrDebug("Server", "starting");
61 params
->negVersion
= kSSLProtocolUnknown
;
62 params
->negCipher
= SSL_NULL_WITH_NULL_NULL
;
63 params
->ortn
= noHardwareErr
;
65 if(params
->serverToClientRing
== NULL
) {
66 /* set up a socket on which to listen */
67 for(unsigned retry
=0; retry
<BIND_RETRIES
; retry
++) {
68 ortn
= ListenForClients(params
->port
, params
->nonBlocking
,
74 /* port already in use - try another */
76 if(params
->verbose
|| THREADING_DEBUG
) {
77 printf("...retrying ListenForClients at port %d\n",
90 #if !SERVER_READY_DELAY
91 /* let main thread know a socket is ready */
92 if(pthread_mutex_lock(¶ms
->pthreadMutex
)) {
93 printf("***Error acquiring server lock; aborting.\n");
96 params
->serverReady
= true;
97 if(pthread_cond_broadcast(¶ms
->pthreadCond
)) {
98 printf("***Error waking main thread; aborting.\n");
101 if(pthread_mutex_unlock(¶ms
->pthreadMutex
)) {
102 printf("***Error acquiring server lock; aborting.\n");
107 printf("ListenForClients returned %d; aborting\n", (int)ortn
);
111 if(params
->serverToClientRing
== NULL
) {
112 /* wait for a connection */
113 if(params
->verbose
) {
114 printf("Waiting for client connection...");
117 ortn
= AcceptClientConnection(listenSock
, &acceptSock
, &peerId
);
119 printf("AcceptClientConnection returned %d; aborting\n", (int)ortn
);
123 #endif /* SERVER_READY_DELAY */
126 * Set up a SecureTransport session.
128 ortn
= SSLNewContext(true, &ctx
);
130 printSslErrStr("SSLNewContext", ortn
);
134 #if !SERVER_READY_DELAY
135 if(params
->serverToClientRing
) {
137 ortn
= SSLSetIOFuncs(ctx
, ringReadFunc
, ringWriteFunc
);
139 printSslErrStr("SSLSetIOFuncs", ortn
);
142 ortn
= SSLSetConnection(ctx
, (SSLConnectionRef
)&ringBufs
);
144 printSslErrStr("SSLSetConnection", ortn
);
149 /* normal socket I/O */
150 ortn
= SSLSetIOFuncs(ctx
, SocketRead
, SocketWrite
);
152 printSslErrStr("SSLSetIOFuncs", ortn
);
155 ortn
= SSLSetConnection(ctx
, (SSLConnectionRef
)acceptSock
);
157 printSslErrStr("SSLSetConnection", ortn
);
161 #endif /* SERVER_READY_DELAY */
163 if(params
->anchorFile
) {
164 ortn
= sslAddTrustedRoot(ctx
, params
->anchorFile
,
165 params
->replaceAnchors
);
170 if(params
->myCertKcName
!= NULL
) {
171 /* if not, better be trying anonymous diff-hellman... :-) */
172 serverCerts
= getSslCerts(params
->myCertKcName
, CSSM_FALSE
, CSSM_FALSE
, NULL
,
174 if(serverCerts
== nil
) {
177 if(params
->password
) {
178 ortn
= SecKeychainUnlock(serverKc
, strlen(params
->password
),
179 (void *)params
->password
, true);
181 printf("SecKeychainUnlock returned %d\n", (int)ortn
);
185 if(params
->idIsTrustedRoot
) {
186 /* assume this is a root we want to implicitly trust */
187 ortn
= addIdentityAsTrustedRoot(ctx
, serverCerts
);
192 ortn
= SSLSetCertificate(ctx
, serverCerts
);
194 printSslErrStr("SSLSetCertificate", ortn
);
199 if(params
->disableCertVerify
) {
200 ortn
= SSLSetEnableCertVerify(ctx
, false);
202 printSslErrStr("SSLSetEnableCertVerify", ortn
);
206 if(!params
->noProtSpec
) {
207 ortn
= sslSetProtocols(ctx
, params
->acceptedProts
, params
->tryVersion
);
212 if(params
->resumeEnable
) {
213 ortn
= SSLSetPeerID(ctx
, &peerId
, sizeof(PeerSpec
));
215 printSslErrStr("SSLSetPeerID", ortn
);
219 if(params
->ciphers
!= NULL
) {
220 ortn
= sslSetEnabledCiphers(ctx
, params
->ciphers
);
225 if(params
->authenticate
!= kNeverAuthenticate
) {
226 ortn
= SSLSetClientSideAuthenticate(ctx
, params
->authenticate
);
228 printSslErrStr("SSLSetClientSideAuthenticate", ortn
);
232 if(params
->dhParams
) {
233 ortn
= SSLSetDiffieHellmanParams(ctx
, params
->dhParams
,
234 params
->dhParamsLen
);
236 printSslErrStr("SSLSetDiffieHellmanParams", ortn
);
241 #if SERVER_READY_DELAY
242 /* let main thread know server is fully functional */
243 if(pthread_mutex_lock(¶ms
->pthreadMutex
)) {
244 printf("***Error acquiring server lock; aborting.\n");
245 ortn
= internalComponentErr
;
248 params
->serverReady
= true;
249 if(pthread_cond_broadcast(¶ms
->pthreadCond
)) {
250 printf("***Error waking main thread; aborting.\n");
251 ortn
= internalComponentErr
;
254 if(pthread_mutex_unlock(¶ms
->pthreadMutex
)) {
255 printf("***Error acquiring server lock; aborting.\n");
256 ortn
= internalComponentErr
;
260 if(params
->serverToClientRing
== NULL
) {
261 /* wait for a connection */
262 if(params
->verbose
) {
263 printf("Waiting for client connection...");
266 ortn
= AcceptClientConnection(listenSock
, &acceptSock
, &peerId
);
268 printf("AcceptClientConnection returned %d; aborting\n", (int)ortn
);
273 /* Last part of SSLContext setup, now that we're connected to the client */
274 if(params
->serverToClientRing
) {
276 ortn
= SSLSetIOFuncs(ctx
, ringReadFunc
, ringWriteFunc
);
278 printSslErrStr("SSLSetIOFuncs", ortn
);
281 ortn
= SSLSetConnection(ctx
, (SSLConnectionRef
)&ringBufs
);
283 printSslErrStr("SSLSetConnection", ortn
);
288 /* normal socket I/O */
289 ortn
= SSLSetIOFuncs(ctx
, SocketRead
, SocketWrite
);
291 printSslErrStr("SSLSetIOFuncs", ortn
);
294 ortn
= SSLSetConnection(ctx
, (SSLConnectionRef
)acceptSock
);
296 printSslErrStr("SSLSetConnection", ortn
);
301 #endif /* SERVER_READY_DELAY */
303 /* Perform SSL/TLS handshake */
305 ortn
= SSLHandshake(ctx
);
306 if((ortn
== errSSLWouldBlock
) && !params
->silent
) {
307 /* keep UI responsive */
310 } while (ortn
== errSSLWouldBlock
);
312 SSLGetClientCertificateState(ctx
, ¶ms
->certState
);
313 SSLGetNegotiatedCipher(ctx
, ¶ms
->negCipher
);
314 SSLGetNegotiatedProtocolVersion(ctx
, ¶ms
->negVersion
);
316 if(params
->verbose
) {
323 /* wait for one complete line */
324 char readBuf
[READBUF_LEN
];
326 while(ortn
== noErr
) {
327 length
= READBUF_LEN
;
328 ortn
= SSLRead(ctx
, readBuf
, length
, &length
);
329 if (ortn
== errSSLWouldBlock
) {
339 /* poor person's line completion scan */
340 for(unsigned i
=0; i
<length
; i
++) {
341 if((readBuf
[i
] == '\n') || (readBuf
[i
] == '\r')) {
348 /* send out canned response */
349 ortn
= SSLWrite(ctx
, SERVER_MESSAGE
, strlen(SERVER_MESSAGE
), &length
);
351 printSslErrStr("SSLWrite", ortn
);
356 * always do close, even on error - to flush outgoing write queue
359 OSStatus cerr
= SSLClose(ctx
);
364 while(!params
->clientDone
&& !params
->serverAbort
&& (ortn
== params
->expectRtn
)) {
368 endpointShutdown(acceptSock
);
370 ringBuffersClose(&ringBufs
); /* tolerates NULLs */
372 endpointShutdown(listenSock
);
375 SSLDisposeContext(ctx
);
378 sslThrDebug("Server", "done");