#include <Security/SecureTransport.h>
#include <Security/SecureTransportPriv.h>
#include <clAppUtils/sslAppUtils.h>
#include <security_cdsa_utils/cuFileIo.h>
#include <utilLib/common.h>
#include <clAppUtils/ringBufferIo.h>
#include "ringBufferThreads.h"
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <sys/param.h>
#include <CoreFoundation/CoreFoundation.h>
#include <security_utilities/devrandom.h>
#define DEFAULT_XFER 1024
#define DEFAULT_NUM_BUFS 16
#define DEFAULT_BUF_SIZE 2048
#define DEFAULT_CHUNK 1024
#define SESSION_TICKET_SIZE 512
static void usage(char **argv)
{
printf("Usage: %s [option ...]\n", argv[0]);
printf("Options:\n");
printf(" -x transferSize -- default=%d; 0=forever\n", DEFAULT_XFER);
printf(" -k keychainName -- not needed if PAC will be done\n");
printf(" -n -- *NO* PAC\n");
printf(" -h hostName -- force a SSLSetPeerDomainName on client side\n");
printf(" -p (pause on error)\n");
exit(1);
}
int main(int argc, char **argv)
{
RingBuffer serverToClientRing;
RingBuffer clientToServerRing;
unsigned numBufs = DEFAULT_NUM_BUFS;
unsigned bufSize = DEFAULT_BUF_SIZE;
unsigned chunkSize = DEFAULT_CHUNK;
unsigned char clientBuf[DEFAULT_CHUNK];
unsigned char serverBuf[DEFAULT_CHUNK];
RingBufferArgs clientArgs;
RingBufferArgs serverArgs;
bool abortFlag = false;
pthread_t client_thread = NULL;
int result;
OSStatus ortn;
unsigned char sessionTicket[SESSION_TICKET_SIZE];
int ourRtn = 0;
CFArrayRef idArray = NULL;
CFArrayRef anchorArray = NULL;
char *hostName = NULL;
char *kcName = NULL;
unsigned xferSize = DEFAULT_XFER;
bool pauseOnError = false;
bool runForever = false;
bool skipPAC = false;
extern int optind;
extern char *optarg;
int arg;
optind = 1;
while ((arg = getopt(argc, argv, "x:c:k:h:np")) != -1) {
switch (arg) {
case 'x':
{
unsigned xsize = atoi(optarg);
if(xsize == 0) {
runForever = true;
}
else {
xferSize = xsize;
}
break;
}
case 'k':
kcName = optarg;
break;
case 'n':
skipPAC = true;
break;
case 'h':
hostName = optarg;
break;
case 'p':
pauseOnError = true;
break;
default:
usage(argv);
}
}
if(optind != argc) {
usage(argv);
}
ringBufSetup(&serverToClientRing, "serveToClient", numBufs, bufSize);
ringBufSetup(&clientToServerRing, "clientToServe", numBufs, bufSize);
if(kcName) {
SecKeychainRef kcRef = NULL;
SecCertificateRef anchorCert = NULL;
SecIdentityRef idRef = NULL;
idArray = getSslCerts(kcName,
CSSM_FALSE,
CSSM_FALSE,
NULL,
&kcRef);
if(idArray == NULL) {
printf("***Can't get signing cert from %s\n", kcName);
exit(1);
}
idRef = (SecIdentityRef)CFArrayGetValueAtIndex(idArray, 0);
ortn = SecIdentityCopyCertificate(idRef, &anchorCert);
if(ortn) {
cssmPerror("SecIdentityCopyCertificate", ortn);
exit(1);
}
anchorArray = CFArrayCreate(NULL, (const void **)&anchorCert,
1, &kCFTypeArrayCallBacks);
CFRelease(kcRef);
CFRelease(anchorCert);
}
memset(&serverArgs, 0, sizeof(serverArgs));
serverArgs.xferSize = xferSize;
serverArgs.xferBuf = serverBuf;
serverArgs.chunkSize = chunkSize;
serverArgs.ringWrite = &serverToClientRing;
serverArgs.ringRead = &clientToServerRing;
serverArgs.goFlag = &clientArgs.iAmReady;
serverArgs.abortFlag = &abortFlag;
serverArgs.pauseOnError = pauseOnError;
appGetRandomBytes(serverArgs.sharedSecret, SHARED_SECRET_SIZE);
if(!skipPAC) {
serverArgs.setMasterSecret = true;
}
serverArgs.idArray = idArray;
serverArgs.trustedRoots = anchorArray;
memset(&clientArgs, 0, sizeof(clientArgs));
clientArgs.xferSize = xferSize;
clientArgs.xferBuf = clientBuf;
clientArgs.chunkSize = chunkSize;
clientArgs.ringWrite = &clientToServerRing;
clientArgs.ringRead = &serverToClientRing;
clientArgs.goFlag = &serverArgs.iAmReady;
clientArgs.abortFlag = &abortFlag;
clientArgs.pauseOnError = pauseOnError;
memmove(clientArgs.sharedSecret, serverArgs.sharedSecret, SHARED_SECRET_SIZE);
clientArgs.hostName = hostName;
for(unsigned dex=0; dex<SESSION_TICKET_SIZE; dex++) {
sessionTicket[dex] = dex;
}
clientArgs.sessionTicket = sessionTicket;
clientArgs.sessionTicketLen = SESSION_TICKET_SIZE;
clientArgs.setMasterSecret = true;
clientArgs.trustedRoots = anchorArray;
result = pthread_create(&client_thread, NULL,
rbClientThread, &clientArgs);
if(result) {
printf("***pthread_create returned %d, aborting\n", result);
exit(1);
}
ortn = rbServerThread(&serverArgs);
if(abortFlag) {
printf("***Test aborted.\n");
exit(1);
}
printf("\n");
printf("SSL Protocol Version : %s\n",
sslGetProtocolVersionString(serverArgs.negotiatedProt));
printf("SSL Cipher : %s\n",
sslGetCipherSuiteString(serverArgs.negotiatedCipher));
if(skipPAC) {
if(clientArgs.sessionWasResumed) {
printf("***skipPAC true, but client reported sessionWasResumed\n");
ourRtn = -1;
}
if(serverArgs.sessionWasResumed) {
printf("***skipPAC true, but server reported sessionWasResumed\n");
ourRtn = -1;
}
if(ourRtn == 0) {
printf("...PAC session attempted by client; refused by server;\n");
printf(" Normal session proceeded correctly.\n");
}
}
else {
if(!clientArgs.sessionWasResumed) {
printf("***client reported !sessionWasResumed\n");
ourRtn = -1;
}
if(!serverArgs.sessionWasResumed) {
printf("***server reported !sessionWasResumed\n");
ourRtn = -1;
}
if(memcmp(clientBuf, serverBuf, DEFAULT_CHUNK)) {
printf("***Data miscompare***\n");
ourRtn = -1;
}
if(ourRtn == 0) {
printf("...PAC session resumed correctly.\n");
}
}
return ourRtn;
}