Commit 9fea5457 authored by powelld's avatar powelld
Browse files

Adding Demonstrator v 0.1

parent bfd3cd81
-----BEGIN CERTIFICATE-----
MIIDhTCCAm2gAwIBAgIJALSFyHa6alS0MA0GCSqGSIb3DQEBCwUAMFkxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xNDEyMjgyMjEz
MzBaFw0xNTAxMjcyMjEzMzBaMFkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21l
LVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNV
BAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMFf
P79u/Y0g+pUMxXuzUuF7L3Fo8pIyNigeaFNSIE9L86QOfJZEjuZE2tIdAbYzIAzE
JEOGRremcqA3kLQaT6H6qi9YacChJEVDQDnCf9tDzxFKrLDiFPnFLhGDrdXaxZJV
oSipmyz6iCCJV2FpHVcqofTWcmQJ5RavFJ78DA/B62B+Iy+q5n1DrIquZYMSqWpp
Em50dY+wz0uAHDjkCtudyN3aqIZEqaR/NoMXzbK7aaJoUhD1Mj4aHs/ei+JFx4iU
f3DW4zXJj9XfUa8G1DqcBl+qLqCuGUOnyW+GLutrk9axkUZCIpQNNfRvPQVxtCeF
tuh9ZuwpTJXdUZUnZ8MCAwEAAaNQME4wHQYDVR0OBBYEFLIcln/y41ddl1EBHY9S
J5efVl9BMB8GA1UdIwQYMBaAFLIcln/y41ddl1EBHY9SJ5efVl9BMAwGA1UdEwQF
MAMBAf8wDQYJKoZIhvcNAQELBQADggEBADLIVXyUjIgg41HsuAzZXDQkGVXmhmmH
OeWmGzntfW98Ct73N7NrOa+3R7ZVuwUdwRQZQPb7MtshYlrILN/rpB25iWXAtzfS
1mLPqhbJtlauIFtEmV+/rGfgPrmKcAgAD3Zm0gvv9soSNwSp9jba29S6NNEkTz7S
4/u0rr9vt4J74N6ggtpgmVPnku5RWg9XhIAB2CXAOa7rgDb0+1HDz8LTFCc0bCcH
Dw9smQ5kkvWWFPi2Txk8xb9xXFMuuD8kSfxRhjOraSPx99B174l96xof0Yrcx3r8
aPv3qkfiVPU3gmgTYSerXgNGX1rNVWQs/b1RoSmnl6GdOCSKA3xSAUQ=
-----END CERTIFICATE-----
#include <pthread.h>
#include <assert.h>
#include <getopt.h>
#include "common.h"
#include <signal.h>
#include <unistd.h>
const char *USAGE="client [-v | -V logfile ] [ -k keylog ] [-c context_list] [-s server] [-m middlebox_list | -M middlebox_list_file]\n"
"\tcontext list must be comma-separated list of context names, defaults to \"header,body\"\n"
"\tserver must be url including port, default 127.0.0.1:" xstr(DEFAULT_SERVER_PORT) "\n"
"\tmiddlebox list must semi-colon delimited urls including port,"
"\tmiddlebox list_file must be a file with middlebox urls on separate lines,"
"\t\tdefault \"127.0.0.1:" xstr(DEFAULT_MBOX_PORT) "\n"
"Input to send to the server is taken from stdin in lines of the form context:command\n";
const char *ARG_TYPES="v:V:k:c:s:m:M";
typedef struct ClientConfigST {
FILE *vlog;
FILE *fIn;
FILE *fOut;
SSL *pSSL;
int numContexts;
const char *contextDescs[50];
int numMiddleboxes;
const char *MiddleboxURLs[50];
const char *serverURL;
char myKeyFile[1024];
char myPassword[1024];
char caFile[1024];
} ClientConfig;
static int
client_ParseArgs(int iArgC, char *papsArgV[], ClientConfig *ptCConf);
void
client_SetDefaults(ClientConfig *ptC)
{
memset(ptC,0,sizeof(*ptC));
ptC->fIn=stdin;
ptC->fOut=stdout;
strcpy(ptC->caFile,"ca.pem");
strcpy(ptC->myKeyFile,"client.pem");
strcpy(ptC->myPassword,"password");
ptC->serverURL="127.0.0.1:" xstr(DEFAULT_SERVER_PORT);
ptC->numMiddleboxes=1;
ptC->MiddleboxURLs[0]="127.0.0.1:" xstr(DEFAULT_MBOX_PORT);
}
extern char *optarg;
//the next two are available but currently ununsed,
//commented out to prevent compiler complaining
//extern int optind;
//extern int optopt;
static int
client_ParseArgs(int iArgC, char *papsArgV[], ClientConfig *ptCConf)
{
int iStatus=0;
char carg=0;
while( iStatus==0 && (carg=getopt(iArgC,papsArgV,ARG_TYPES)) != -1) {
switch(carg) {
case 'v':
case 'V':
if(ptCConf->vlog!=NULL) {
COMMON_LogErrorAndExit(iStatus=INVALID_COMMAND_LINE_ARGS,stderr,"verbose logging specified multiple times\n%s",USAGE);
}
if(carg=='v') {
ptCConf->vlog=stdout;
} else { /*carg=='V'*/
ptCConf->vlog=fopen(optarg,"w");
if(ptCConf->vlog==NULL) {
COMMON_LogErrorAndExit(iStatus=FILE_NOT_WRITABLE,stderr,"Unable to open log file %s",optarg);
}
}
break;
case 's':
/*todo*/
assert(0);
break;
case 'k':
/*todo*/
assert(0);
break;
case 'c':
/*todo*/
assert(0);
break;
case 'm':
/*todo*/
assert(0);
break;
case 'M':
/*todo*/
assert(0);
break;
default:
COMMON_LogErrorAndExit(iStatus=INVALID_COMMAND_LINE_ARGS,stderr,"Unrecognised command line option -%c",carg);
break; /*never reached - keeps compiler happy*/
}
}
return iStatus;
}
ERROR_STATUS
client_CreateContext(SSL_CTX **pptSSLctx,const ClientConfig *ptConf)
{
ERROR_STATUS iStatus;
iStatus=COMMON_InitializeSSLCtx(pptSSLctx,
ptConf->myKeyFile, ptConf->myPassword,
ptConf->caFile,
ID_CLIENT);
return iStatus;
}
ERROR_STATUS
client_Connect(SSL_CTX *ptSSLctx, ClientConfig *ptConf)
{
ERROR_STATUS iStatus=SUCCESS;
int i,j,p;
BIO *ptSBio;
/*step 0 - create SSL structure*/
/*the SSL_CTX already has out keys set up*/
ptConf->pSSL=SSL_new(ptSSLctx);
/*todo - check for NULL return*/
assert(ptConf->pSSL!=NULL);
/*step 1 - create the contexts*/
iStatus=COMMON_InitMulticontextSet(ptConf->pSSL);
assert(iStatus==SUCCESS);
if(ptConf->numContexts==0) {
iStatus=COMMON_AppendContext(ptConf->pSSL,"default");
} else {
/*Iterate through the context descriptions and create each one*/
for(i=0;i!=ptConf->numContexts && iStatus==SUCCESS;i++) {
iStatus=COMMON_AppendContext(ptConf->pSSL,ptConf->contextDescs[i]);
}
}
if(iStatus!=SUCCESS) {
/*TODO*/
assert(0);
}
/*step 2 - create the middlebox list*/
iStatus=COMMON_InitProxySet(ptConf->pSSL);
assert(iStatus==SUCCESS);
/*step 2.0? - do we need to insert client as middlebox 0? - TODO confirm*/
/*step 2.1 - iterate through middlebox list */
for(i=0;i!=ptConf->numMiddleboxes;i++) {
iStatus=COMMON_AppendProxy(ptConf->pSSL,ptConf->MiddleboxURLs[i]);
}
/*step 2.2 - add server url*/
iStatus=COMMON_AppendClientServer(ptConf->pSSL,ptConf->serverURL,1);
/*step 3 - set the middlebox access permissions*/
/*for demonstration purposed, we will set by the following rule:
* Middleboxes with an even port number get read-only access
* Middleboxes with an odd port number get write access
* This is for demonstration only - there is no sensible
* reason why this rule would ever be real-world implemented!
*/
for(j=0;j!=ptConf->numContexts;j++) {
/*grant client if included*/
/*grant server*/
iStatus=COMMON_SetProxyAccessPermissionByID(ptConf->pSSL,ptConf->pSSL->slices[j]->slice_id, ptConf->numMiddleboxes-1,
1,1);
for(i=0;i!=ptConf->numMiddleboxes-1;i++) { /*change to i=1 if client included*/
char *sMBoxUrl=ptConf->pSSL->proxies[i]->address;
char *sPort=strchr(sMBoxUrl,':');
assert(sPort);
sPort++;
int iPort=atoi(sPort);
iStatus=COMMON_SetProxyAccessPermissionByID(ptConf->pSSL,ptConf->pSSL->slices[j]->slice_id, i,
1,iPort%2);
}
}
/*step 4? - do we need to create a socket to first middlebox?*/
// TCP Connect
char* sAddress = (char*)malloc(strlen(ptConf->pSSL->proxies[0]->address) + 1); // Large enough for string+\0
memcpy(sAddress, ptConf->pSSL->proxies[0]->address, strlen(ptConf->pSSL->proxies[0]->address) + 1);
char *sHost = strtok(sAddress, ":");
int iPort = atoi(strtok(NULL, ":"));
int iSock;
COMMON_TcpConnect(&iSock, sHost, iPort);
// Connect TCP socket to SSL socket
ptSBio = BIO_new_socket(iSock, BIO_NOCLOSE);
SSL_set_bio(ptConf->pSSL, ptSBio, ptSBio);
/*step 5 - call the connect method*/
/*SPP connect calls this method but also adds some checks,
* in particular it checks that there is at least one context (fine)
* but also checks that there is at least one proxy (which seems
* unnecassary but the server is included so there must be one)
*/
if (SSL_connect(ptConf->pSSL) <= 0) {
iStatus=NETWORK_CONNECT_FAIL;
}
return SUCCESS;
}
int giSignal=0;
int giDone=0;
static pthread_t gtParent_thread;
static pthread_t gtSending_thread;
static pthread_t gtReceiving_thread;
static void
client_sighandler(int sig) {
if(giSignal==0) giSignal=sig;
giDone=1;
/*note: pthread_kill is a signal sending method - not a
* "Die now" method. Unfortunate naming
*/
pthread_kill(gtSending_thread,sig);
pthread_kill(gtReceiving_thread,sig);
}
struct iobuffer {
int iUsed;
union {
unsigned char aucBuffer[1024];
char stext[1024];
};
char z;/*force null termination of string*/
};
static void *
client_sendThread(void *pvArg)
{
int iNewLine=0;
int iCurrentSlice=0;
ERROR_STATUS iStatus=SUCCESS;
int iBytesRead;
int iBytesToSend;
int iBytesSent;
struct iobuffer tInBuff;
const ClientConfig *ptCConf=(const ClientConfig *)pvArg;
char *sCurrent,*sEnd,sChunk;
char sContext[MAX_CONTEXT_LEN];
int iFIn=fileno(ptCConf->fIn);
memset(&tInBuff,0,sizeof(tInBuff));
while(!giDone && iStatus==SUCCESS) {
/*wait until we have data to read*/
/*we should always have an empty buffer at this point*/
tInBuff.iUsed=0;
memset(tInBuff.aucBuffer,0,sizeof(tInBuff.aucBuffer));
iStatus=COMMON_ReadWaitFD(iFIn);
/*Read as much data as possible*/
iBytesRead=read(iFIn,tInBuff.aucBuffer,sizeof(tInBuff.aucBuffer));
assert(iBytesRead>0); /*should be as we waited for it*/
iBytesToSend=iBytesRead;
iNewLine=(tInBuff.aucBuffer[0]=='\n');
while(iStatus==SUCCESS && iBytesToSend>0) {
if(iNewLine) {
/*we hit a new line - advance to next context*/
iCurrentSlice=(iCurrentSlice+1)%ptCConf->pSSL->slices_len;
ptCConf->pSSL->write_slice=SPP_get_slice_by_id(ptCConf->pSSL,ptCConf->pSSL->slices[iCurrentSlice]->slice_id);
tInBuff.iUsed++;
iBytesToSend--;
iNewLine=(tInBuff.aucBuffer[tInBuff.iUsed]=='\n'); /*should only happen on \n\n*/
/*note - line above may overflow if \n happens to be last byte read
* this is guaranteed safe due to the additional null terminator char
* and the next iteration of the top loop will reset correctly*/
} else if((sEnd=strchr(tInBuff.stext+tInBuff.iUsed,'\n'))==NULL) {
/*entire buffer to output in this context*/
iBytesSent=SSL_write(ptCConf->pSSL,tInBuff.stext+tInBuff.iUsed,iBytesToSend);
/*todo - handle error sending*/
assert(iBytesSent>0);
tInBuff.iUsed+=iBytesSent;
iBytesToSend-=iBytesSent;
} else {
/*send entire buffer up to and including new line*/
/*advance buffer up to new line only - context change on next iteration
* of this loop*/
iBytesSent=SSL_write(ptCConf->pSSL,tInBuff.stext+tInBuff.iUsed,sEnd-(tInBuff.stext+tInBuff.iUsed)+1);
/*todo - handle error sending*/
tInBuff.iUsed=sEnd-tInBuff.stext;
iBytesToSend-=sEnd-(tInBuff.stext+tInBuff.iUsed);
iNewLine=1;
assert(iBytesSent==(sEnd-(tInBuff.stext+tInBuff.iUsed))+1);
}
}
}
/*signal to the parent so all other threads are woken*/
pthread_kill(gtParent_thread,SIGINT);
pthread_exit(NULL);
return NULL;
}
static void *
client_receiveThread(void *pvArg)
{
ERROR_STATUS iStatus=SUCCESS;
struct iobuffer tInBuff;
int iBytesRead=1;
const ClientConfig *ptCConf=(const ClientConfig *)pvArg;
BIO *sock_bio=ptCConf->pSSL->rbio;
int rfd;
SPP_SLICE *pSlice;
SPP_CTX *pCtx;
BIO_get_fd(sock_bio,&rfd);
memset(&tInBuff,0,sizeof(tInBuff));
while(iBytesRead>0 && iStatus==SUCCESS) {
/*wait until we have data to read*/
iStatus=COMMON_ReadWaitFD(rfd);
iBytesRead = SSL_read(ptCConf->pSSL,tInBuff.aucBuffer,sizeof(tInBuff.aucBuffer));
pSlice = ptCConf->pSSL->read_slice;
pCtx = ptCConf->pSSL->spp_read_ctx;
ptCConf->pSSL->read_slice = NULL;
ptCConf->pSSL->spp_read_ctx = NULL;
if(iBytesRead>0) {
/*print out what we got and from where*/
fprintf(ptCConf->fOut,"<%s(%d)>:%s",pSlice->purpose,pSlice->slice_id,tInBuff.stext);
} else {
fprintf(ptCConf->fOut,"zero bytes read - closing");
}
}
/*signal to the parent so all other threads are woken*/
pthread_kill(gtParent_thread,SIGINT);
pthread_exit(NULL);
return NULL;
}
ERROR_STATUS
client_RunClient(const ClientConfig *ptConf)
{
void *pvUnused;
ERROR_STATUS iStatus=SUCCESS;
/*set an interrupt signal handler to kill the process*/
signal(SIGINT,client_sighandler);
signal(SIGTERM,client_sighandler);
gtParent_thread=pthread_self();
/*create the send and recioeve threads*/
pthread_create(&gtReceiving_thread, NULL, client_receiveThread, (void *)ptConf);
pthread_create(&gtSending_thread, NULL, client_sendThread, (void *)ptConf);
/*wait for both to finish*/
pthread_join(gtReceiving_thread,&pvUnused);
pthread_join(gtSending_thread,&pvUnused);
return SUCCESS;
}
int
main(const int iArgC, char *papsArgV[])
{
ClientConfig tConfig;
SSL_CTX *ptSSLctx=NULL;
int iStatus;
client_SetDefaults(&tConfig);
iStatus=client_ParseArgs(iArgC,papsArgV, &tConfig);
COMMON_CheckLogErrorAndExit(iStatus,stderr,"%s\n",USAGE);
iStatus=client_CreateContext(&ptSSLctx,&tConfig);
iStatus=client_Connect(ptSSLctx,&tConfig);
iStatus=client_RunClient(&tConfig);
return iStatus;
}
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDHH/fTFwKTMHDaFXw6LvyDMhHcXwbN3dfI+RGMbBqrQmb7M0+M
vDsx5pVo/d0k4HzKnVuLe9mRUmxRWKrC6yk6R+ginrbvdPGEsP97bJxZdaxa4HvZ
eVVs7I20gYbY9oHCw9fdMluaPgLKn+QTQz+Bu+xXeXVxnkZikbXRI4l0UQIDAQAB
AoGALVj1amhKGNUmTjQoZ2O98+7aLHKjrQyBkO5P9cfExw3HQBvuWOGhJXsauZ9e
1oAdS1NMvtZEtRitPFVSBjPh3lGPcJcYrWWQ6Sc4wldAMLZEOM3e8IhQKFDMtJz0
bdw4YubZxbIZKY1/9u27HpMZ3ZXGIVziqSZ3mWyPEbDUbKUCQQD6ghyUVd+CMwlM
U6mJmjGlS6TfykgD5eUHdpbif724jrYzpj0yp8SAAegmsfeH8RIpd3jmV41d1lcT
UV5uYTujAkEAy318TB6sh1ApkupmQU2pQWnVt0kewZA/NCDZ6MPsa//cHuhbi7P6
ZxmyZn+u+0KfiVYYeyMjv3BFDfeGn5PPewJAKE6hLJj4oql1mItpnxNpY5BdUgjp
N39ZL688Leuh6j1EQeFAvZLTAknMQdWm33/BjVyE3oM94thnIFuaVyZcAwJAYmly
xqGDEQHcyVehUm3LsH4NxNGRFU28s2o72M2ANo8MFsqLE5pcPKZ52AZiStPishm4
Rz0sWbZjPyj5q41hpwJALbwQYxv9GVVY3hywyzK3t/6ToGmC/jvXYqu5pR+5Khs6
rCD+hZMKQU1AYA4l6n5CMhRYmYk+XdkdjZKUylgcmg==
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIICojCCAYoCAQIwDQYJKoZIhvcNAQELBQAwWTELMAkGA1UEBhMCQVUxEzARBgNV
BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTE0MTIyODIyMTM1N1oXDTE1MDEyNzIy
MTM1N1owWTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNV
BAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHH/fTFwKTMHDaFXw6LvyDMhHc
XwbN3dfI+RGMbBqrQmb7M0+MvDsx5pVo/d0k4HzKnVuLe9mRUmxRWKrC6yk6R+gi
nrbvdPGEsP97bJxZdaxa4HvZeVVs7I20gYbY9oHCw9fdMluaPgLKn+QTQz+Bu+xX
eXVxnkZikbXRI4l0UQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBaCxFScRowAmHv
d3DF8BugvtWZFq+GS4/BWgH1pAIj6ED6HrFnxZKrs8t67zUI888An1nmxAFNPPST
6ys1VEW2z4xzZEh2EK/ZPiwkz9rWl9jjilypvIAeG4jnhk5OaaqE0X6J/Lx5rxWk
iQmEslthAz4aysUD9kmivr0Cyzz41ZaJR8oMdRnXx88Qeq4Y3dStIIDjPCRfwaYu
nA4G5P4fj1LY4vcjL5Y/Vw2bkn9gh4t0lx5LuCOh5RRyFYpygW2gyc7qSYI5v5dh
/rsDfRapHgbL5bvfO+qkky2lKfmvy0e0QV0CzStq6CALaa8EbMz8cPiyEfcqmgVg
45HRLZut
-----END CERTIFICATE-----
#include "common.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <sys/select.h>
#include <errno.h>
#define MAXSTRLEN (1024)
static void
common_Log(FILE *pLog, const char *csFmtStr, va_list va_args);
static void
common_DoExit(int iExitCode);
static void
common_SigpipeHandle(int x);
/*function to wait for a specific FILE to be ready for reading*/
ERROR_STATUS
COMMON_ReadWaitFile(FILE *phF)
{
int iFDNum=fileno(phF);
return COMMON_ReadWaitFD(iFDNum);
}
/*function to wait for a specific File Descriptor (file, socket, pipe) to be ready for reading*/
ERROR_STATUS
COMMON_ReadWaitFD(int iFD)
{
int iStatus;
fd_set fds_r,fds_w,fds_ex;
FD_ZERO(&fds_r);
FD_ZERO(&fds_w);
FD_ZERO(&fds_ex);
FD_SET(iFD,&fds_r);
iStatus=select(iFD+1,&fds_r,&fds_w,&fds_ex,NULL);
if(iStatus>0) {
/*more one file ready (i.e. should only be one)*/
iStatus=SUCCESS;
} else {
/*something gone wrond or we are interrupted*/
iStatus=ERROR_INTERRUPT;
}
return iStatus;
}
// Function to read a proxy list from file and populate array of proxies
// Each proxy should be a separate line containing the url only
// e.g.:
//127.0.0.1:8423
//127.0.0.1:8424
//127.0.0.1:4433
ERROR_STATUS
COMMON_ReadProxyListFile(SSL *ptSSL,
const char *sFilename){
FILE *phF; // pointer to file
unsigned int uiCount = 0; // simple counters
char acLine [128]; // maximum size of line to read from
SPP_PROXY *patNewProxiesList=NULL;
if(ptSSL==NULL || sFilename==NULL) {
return INVALID_POINTER;
}
// Open file for reading
phF = fopen(sFilename,"r");
// Check for errors while opening file
if( phF == NULL ){
return FILE_NOT_READABLE;
}
uiCount=0;
// Read file line-by-line
while ( fgets ( acLine, sizeof(acLine), phF ) != NULL ) {
// Remove trailing newline (NOTE: strtoK is not thread safe)
strtok(acLine, "\n");
if(strlen(acLine)<=2) continue; //ignore blank lines
COMMON_AppendProxy(ptSSL,acLine);
/*TODO - log the proxy creation properly*/
COMMON_Log(stdout,"Proxy(%2u): %s\n",uiCount,acLine);
}
// Close file
fclose(phF);
return SUCCESS;
}
ERROR_STATUS
COMMON_InitProxySet(SSL *ptSSL)
{
while(ptSSL->proxies_len>0) {
ptSSL->proxies_len--;
OPENSSL_free(ptSSL->proxies[ptSSL->proxies_len]);
}
ptSSL->proxies_len=0;
memset(ptSSL->proxies,0,sizeof(ptSSL->proxies));
return SUCCESS;
}
ERROR_STATUS
COMMON_InitMulticontextSet(SSL *ptSSL)
{
while(ptSSL->slices_len>0) {
ptSSL->slices_len--;
OPENSSL_free(ptSSL->slices[ptSSL->slices_len]);
}
ptSSL->slices_len=0;
memset(ptSSL->slices,0,sizeof(ptSSL->slices));
return SUCCESS;
}
ERROR_STATUS
COMMON_AppendProxy(SSL *ptSSL,
const char *psProxyURL)
{
char *psProxyUrlCpy=NULL;
if(ptSSL->proxies_len>=(sizeof(ptSSL->proxies)/sizeof(ptSSL->proxies[0])))
return ARRAY_OVERFLOW;
/*SPP_generate_proxy will generate something with the string provide
* but there is no guarantee that it will be sensible if
* invalid data is passed in*/
psProxyUrlCpy=strdup(psProxyURL);
ptSSL->proxies[ptSSL->proxies_len] = SPP_generate_proxy(ptSSL, psProxyUrlCpy);
(ptSSL->proxies_len)++;
return SUCCESS;
}
ERROR_STATUS
COMMON_AppendClientServer(SSL *ptSSL,
const char *psURL, int isServer)
{
char *psUrlCpy=NULL;
if(ptSSL->proxies_len>=(sizeof(ptSSL->proxies)/sizeof(ptSSL->proxies[0])))
return ARRAY_OVERFLOW;
/*SPP_generate_proxy will generate something with the string provide
* but there is no guarantee that it will be sensible if
* invalid data is passed in*/
psUrlCpy=strdup(psURL);
/* TODO - SPP_generate_proxy probably won't assign the correct ID's
* to denote server and client
*/
if(isServer) {
ptSSL->proxies[ptSSL->proxies_len] = SPP_generate_proxy(ptSSL, psUrlCpy);
(ptSSL->proxies_len)++;
} else { /*isClient*/
memmove(&ptSSL->proxies[1],&ptSSL->proxies[0],ptSSL->proxies_len * sizeof(*ptSSL->proxies));
ptSSL->proxies[0] = SPP_generate_proxy(ptSSL, psUrlCpy);
}
return SUCCESS;
}
ERROR_STATUS
COMMON_AppendContext(SSL *ptSSL,
const char *psContextDesc)
{
char *psContextDescCpy=NULL;