2 * sslEAP - test EAP-FAST style PAC-based session resumption.
4 * This only works with a debug Security.framework since server side
5 * PAC support is not present in deployment builds.
7 * Written by Doug Mitchell.
9 #include <Security/SecureTransport.h>
10 #include <Security/SecureTransportPriv.h>
11 #include <clAppUtils/sslAppUtils.h>
12 #include <security_cdsa_utils/cuFileIo.h>
13 #include <utilLib/common.h>
14 #include <clAppUtils/ringBufferIo.h>
15 #include "ringBufferThreads.h" /* like the ones in clAppUtils, tailored for EAP/PAC */
17 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
23 #include <sys/param.h>
24 #include <CoreFoundation/CoreFoundation.h>
25 #include <security_utilities/devrandom.h>
27 #define DEFAULT_XFER 1024 /* total xfer size in bytes */
29 /* we might make these user-tweakable */
30 #define DEFAULT_NUM_BUFS 16
31 #define DEFAULT_BUF_SIZE 2048 /* in the ring buffers */
32 #define DEFAULT_CHUNK 1024 /* bytes to write per SSLWrite() */
33 #define SESSION_TICKET_SIZE 512
35 static void usage(char **argv
)
37 printf("Usage: %s [option ...]\n", argv
[0]);
39 printf(" -x transferSize -- default=%d; 0=forever\n", DEFAULT_XFER
);
40 printf(" -k keychainName -- not needed if PAC will be done\n");
41 printf(" -n -- *NO* PAC\n");
42 printf(" -h hostName -- force a SSLSetPeerDomainName on client side\n");
43 printf(" -p (pause on error)\n");
47 int main(int argc
, char **argv
)
49 RingBuffer serverToClientRing
;
50 RingBuffer clientToServerRing
;
51 unsigned numBufs
= DEFAULT_NUM_BUFS
;
52 unsigned bufSize
= DEFAULT_BUF_SIZE
;
53 unsigned chunkSize
= DEFAULT_CHUNK
;
54 unsigned char clientBuf
[DEFAULT_CHUNK
];
55 unsigned char serverBuf
[DEFAULT_CHUNK
];
56 RingBufferArgs clientArgs
;
57 RingBufferArgs serverArgs
;
58 bool abortFlag
= false;
59 pthread_t client_thread
= NULL
;
62 unsigned char sessionTicket
[SESSION_TICKET_SIZE
];
64 CFArrayRef idArray
= NULL
; /* for SSLSetCertificate */
65 CFArrayRef anchorArray
= NULL
; /* trusted roots */
66 char *hostName
= NULL
;
68 /* user-spec'd variables */
70 unsigned xferSize
= DEFAULT_XFER
;
71 bool pauseOnError
= false;
72 bool runForever
= false;
79 while ((arg
= getopt(argc
, argv
, "x:c:k:h:np")) != -1) {
83 unsigned xsize
= atoi(optarg
);
86 /* and leave xferSize alone */
100 /* mainly to test EAP session ticket and ServerName simultaneously */
114 /* set up ring buffers */
115 ringBufSetup(&serverToClientRing
, "serveToClient", numBufs
, bufSize
);
116 ringBufSetup(&clientToServerRing
, "clientToServe", numBufs
, bufSize
);
118 /* get optional server SecIdentity */
120 SecKeychainRef kcRef
= NULL
;
121 SecCertificateRef anchorCert
= NULL
;
122 SecIdentityRef idRef
= NULL
;
123 idArray
= getSslCerts(kcName
,
124 CSSM_FALSE
, /* encryptOnly */
125 CSSM_FALSE
, /* completeCertChain */
126 NULL
, /* anchorFile */
128 if(idArray
== NULL
) {
129 printf("***Can't get signing cert from %s\n", kcName
);
132 idRef
= (SecIdentityRef
)CFArrayGetValueAtIndex(idArray
, 0);
133 ortn
= SecIdentityCopyCertificate(idRef
, &anchorCert
);
135 cssmPerror("SecIdentityCopyCertificate", ortn
);
138 anchorArray
= CFArrayCreate(NULL
, (const void **)&anchorCert
,
139 1, &kCFTypeArrayCallBacks
);
141 CFRelease(anchorCert
);
144 /* set up server side */
145 memset(&serverArgs
, 0, sizeof(serverArgs
));
146 serverArgs
.xferSize
= xferSize
;
147 serverArgs
.xferBuf
= serverBuf
;
148 serverArgs
.chunkSize
= chunkSize
;
149 serverArgs
.ringWrite
= &serverToClientRing
;
150 serverArgs
.ringRead
= &clientToServerRing
;
151 serverArgs
.goFlag
= &clientArgs
.iAmReady
;
152 serverArgs
.abortFlag
= &abortFlag
;
153 serverArgs
.pauseOnError
= pauseOnError
;
154 appGetRandomBytes(serverArgs
.sharedSecret
, SHARED_SECRET_SIZE
);
156 serverArgs
.setMasterSecret
= true;
158 serverArgs
.idArray
= idArray
;
159 serverArgs
.trustedRoots
= anchorArray
;
161 /* set up client side */
162 memset(&clientArgs
, 0, sizeof(clientArgs
));
163 clientArgs
.xferSize
= xferSize
;
164 clientArgs
.xferBuf
= clientBuf
;
165 clientArgs
.chunkSize
= chunkSize
;
166 clientArgs
.ringWrite
= &clientToServerRing
;
167 clientArgs
.ringRead
= &serverToClientRing
;
168 clientArgs
.goFlag
= &serverArgs
.iAmReady
;
169 clientArgs
.abortFlag
= &abortFlag
;
170 clientArgs
.pauseOnError
= pauseOnError
;
171 memmove(clientArgs
.sharedSecret
, serverArgs
.sharedSecret
, SHARED_SECRET_SIZE
);
172 clientArgs
.hostName
= hostName
;
174 /* for now set up an easily recognizable ticket */
175 for(unsigned dex
=0; dex
<SESSION_TICKET_SIZE
; dex
++) {
176 sessionTicket
[dex
] = dex
;
178 clientArgs
.sessionTicket
= sessionTicket
;
179 clientArgs
.sessionTicketLen
= SESSION_TICKET_SIZE
;
180 /* client always tries setting the master secret in this test */
181 clientArgs
.setMasterSecret
= true;
182 clientArgs
.trustedRoots
= anchorArray
;
184 /* fire up client thread */
185 result
= pthread_create(&client_thread
, NULL
,
186 rbClientThread
, &clientArgs
);
188 printf("***pthread_create returned %d, aborting\n", result
);
193 * And the server pseudo thread. This returns when all data has been transferred.
195 ortn
= rbServerThread(&serverArgs
);
198 printf("***Test aborted.\n");
204 printf("SSL Protocol Version : %s\n",
205 sslGetProtocolVersionString(serverArgs
.negotiatedProt
));
206 printf("SSL Cipher : %s\n",
207 sslGetCipherSuiteString(serverArgs
.negotiatedCipher
));
210 if(clientArgs
.sessionWasResumed
) {
211 printf("***skipPAC true, but client reported sessionWasResumed\n");
214 if(serverArgs
.sessionWasResumed
) {
215 printf("***skipPAC true, but server reported sessionWasResumed\n");
219 printf("...PAC session attempted by client; refused by server;\n");
220 printf(" Normal session proceeded correctly.\n");
224 if(!clientArgs
.sessionWasResumed
) {
225 printf("***client reported !sessionWasResumed\n");
228 if(!serverArgs
.sessionWasResumed
) {
229 printf("***server reported !sessionWasResumed\n");
232 if(memcmp(clientBuf
, serverBuf
, DEFAULT_CHUNK
)) {
233 printf("***Data miscompare***\n");
237 printf("...PAC session resumed correctly.\n");
240 /* FIXME other stuff? */