]>
git.saurik.com Git - apple/security.git/blob - sslViewer/sslServe.cpp
2 * Copyright (c) 2006-2008,2010,2013 Apple Inc. All Rights Reserved.
4 * sslServe.cpp : perform one server side sesssion
7 #include <Security/SecureTransport.h>
8 #include <Security/Security.h>
9 #include <clAppUtils/sslAppUtils.h>
10 #include <clAppUtils/ioSock.h>
11 #include <clAppUtils/sslThreading.h>
12 #include <utilLib/fileIo.h>
13 #include <utilLib/common.h>
14 #include <security_cdsa_utils/cuPrintCert.h>
16 #include <Security/SecBase.h>
23 #include <sys/param.h>
25 #define BIND_RETRIES 10
27 #define SERVER_MESSAGE "HTTP/1.0 200 OK\015\012\015\012" \
28 "<HTML><HEAD><TITLE>SecureTransport Test Server</TITLE></HEAD>" \
29 "<BODY><H2>Secure connection established.</H2>" \
30 "Message from the 'sslServe' test library.\015\012</BODY>" \
33 #define READBUF_LEN 256
35 /* relies on SSLSetProtocolVersionEnabled */
38 * params->lock is held for us by runSession() - we use it as a semapahore by
39 * unlocking it when we've created a port to listen on.
40 * This is generally run from a thread via sslRunSession() and
41 * sslServerThread() in sslAppUtils.cpp.
44 SslAppTestParams
*params
)
46 otSocket listenSock
= 0;
47 otSocket acceptSock
= 0;
50 SSLContextRef ctx
= NULL
;
51 SecKeychainRef serverKc
= nil
;
52 CFArrayRef serverCerts
= nil
;
54 sslThrDebug("Server", "starting");
55 params
->negVersion
= kSSLProtocolUnknown
;
56 params
->negCipher
= SSL_NULL_WITH_NULL_NULL
;
57 params
->ortn
= noHardwareErr
;
59 /* set up a socket on which to listen */
60 for(unsigned retry
=0; retry
<BIND_RETRIES
; retry
++) {
61 ortn
= ListenForClients(params
->port
, params
->nonBlocking
,
67 /* port already in use - try another */
69 if(params
->verbose
|| THREADING_DEBUG
) {
70 printf("...retrying ListenForClients at port %d\n",
77 if(ortn
!= errSecOpWr
) {
82 /* let main thread know a socket is ready */
83 if(pthread_mutex_lock(¶ms
->pthreadMutex
)) {
84 printf("***Error acquiring server lock; aborting.\n");
87 params
->serverReady
= true;
88 if(pthread_cond_broadcast(¶ms
->pthreadCond
)) {
89 printf("***Error waking main thread; aborting.\n");
92 if(pthread_mutex_unlock(¶ms
->pthreadMutex
)) {
93 printf("***Error acquiring server lock; aborting.\n");
98 printf("ListenForClients returned %d; aborting\n", (int)ortn
);
102 /* wait for a connection */
103 if(params
->verbose
) {
104 printf("Waiting for client connection...");
107 ortn
= AcceptClientConnection(listenSock
, &acceptSock
, &peerId
);
109 printf("AcceptClientConnection returned %d; aborting\n", (int)ortn
);
114 * Set up a SecureTransport session.
116 ortn
= SSLNewContext(true, &ctx
);
118 printSslErrStr("SSLNewContext", ortn
);
121 ortn
= SSLSetIOFuncs(ctx
, SocketRead
, SocketWrite
);
123 printSslErrStr("SSLSetIOFuncs", ortn
);
126 ortn
= SSLSetConnection(ctx
, (SSLConnectionRef
)acceptSock
);
128 printSslErrStr("SSLSetConnection", ortn
);
132 if(params
->anchorFile
) {
133 ortn
= sslAddTrustedRoot(ctx
, params
->anchorFile
,
134 params
->replaceAnchors
);
139 if(params
->myCertKcName
!= NULL
) {
140 /* if not, better be trying anonymous diff-hellman... :-) */
141 serverCerts
= getSslCerts(params
->myCertKcName
, false, false, NULL
,
143 if(serverCerts
== nil
) {
146 if(params
->password
) {
147 ortn
= SecKeychainUnlock(serverKc
, strlen(params
->password
),
148 (void *)params
->password
, true);
150 printf("SecKeychainUnlock returned %d\n", (int)ortn
);
154 if(params
->idIsTrustedRoot
) {
155 /* assume this is a root we want to implicitly trust */
156 ortn
= addIdentityAsTrustedRoot(ctx
, serverCerts
);
161 ortn
= SSLSetCertificate(ctx
, serverCerts
);
163 printSslErrStr("SSLSetCertificate", ortn
);
168 if(params
->disableCertVerify
) {
169 ortn
= SSLSetEnableCertVerify(ctx
, false);
171 printSslErrStr("SSLSetEnableCertVerify", ortn
);
175 ortn
= sslSetProtocols(ctx
, params
->acceptedProts
, params
->tryVersion
);
179 if(params
->resumeEnable
) {
180 ortn
= SSLSetPeerID(ctx
, &peerId
, sizeof(PeerSpec
));
182 printSslErrStr("SSLSetPeerID", ortn
);
186 if(params
->ciphers
!= NULL
) {
187 ortn
= sslSetEnabledCiphers(ctx
, params
->ciphers
);
192 if(params
->authenticate
!= kNeverAuthenticate
) {
193 ortn
= SSLSetClientSideAuthenticate(ctx
, params
->authenticate
);
195 printSslErrStr("SSLSetClientSideAuthenticate", ortn
);
199 if(params
->dhParams
) {
201 printf("***Diffie-Hellman not supported in this config.\n");
203 ortn
= SSLSetDiffieHellmanParams(ctx
, params
->dhParams
,
204 params
->dhParamsLen
);
206 printSslErrStr("SSLSetDiffieHellmanParams", ortn
);
212 /* Perform SSL/TLS handshake */
214 ortn
= SSLHandshake(ctx
);
215 if((ortn
== errSSLWouldBlock
) && !params
->silent
) {
216 /* keep UI responsive */
219 } while (ortn
== errSSLWouldBlock
);
221 SSLGetClientCertificateState(ctx
, ¶ms
->certState
);
222 SSLGetNegotiatedCipher(ctx
, ¶ms
->negCipher
);
223 SSLGetNegotiatedProtocolVersion(ctx
, ¶ms
->negVersion
);
225 if(params
->verbose
) {
232 /* wait for one complete line */
233 char readBuf
[READBUF_LEN
];
235 while(ortn
== errSecSuccess
) {
236 length
= READBUF_LEN
;
237 ortn
= SSLRead(ctx
, readBuf
, length
, &length
);
238 if (ortn
== errSSLWouldBlock
) {
240 ortn
= errSecSuccess
;
248 /* poor person's line completion scan */
249 for(unsigned i
=0; i
<length
; i
++) {
250 if((readBuf
[i
] == '\n') || (readBuf
[i
] == '\r')) {
257 /* send out canned response */
258 ortn
= SSLWrite(ctx
, SERVER_MESSAGE
, strlen(SERVER_MESSAGE
), &length
);
260 printSslErrStr("SSLWrite", ortn
);
265 * always do close, even on error - to flush outgoing write queue
268 OSStatus cerr
= SSLClose(ctx
);
269 if(ortn
== errSecSuccess
) {
274 while(!params
->clientDone
&& !params
->serverAbort
) {
277 endpointShutdown(acceptSock
);
280 endpointShutdown(listenSock
);
283 SSLDisposeContext(ctx
);
286 sslThrDebug("Server", "done");