/**************************************************************************
*** COPYRIGHT (c) 2002 by TransNexus, Inc. ***
*** ***
*** This software is property of TransNexus, Inc. ***
*** This software is freely available under license from TransNexus. ***
*** The license terms and conditions for free use of this software by ***
*** third parties are defined in the OSP Toolkit Software License ***
*** Agreement (LICENSE.txt). Any use of this software by third ***
*** parties, which does not comply with the terms and conditions of the ***
*** OSP Toolkit Software License Agreement is prohibited without ***
*** the prior, express, written consent of TransNexus, Inc. ***
*** ***
*** Thank you for using the OSP ToolKit(TM). Please report any bugs, ***
*** suggestions or feedback to support@transnexus.com ***
*** ***
**************************************************************************/
/*
* ospssl.c - SSL common functions
*/
#include "osp/osp.h"
#include "osp/ospssl.h"
#include "osp/osphttp.h"
#include "osp/ospcomm.h"
#include "osp/ospsocket.h"
#include "osp/osputils.h"
#include "osp/ospsecurity.h"
void
OSPPSSLSessionDelete(
OSPTBOOL ospvGracefulShutdown,
OSPTSSLSESSION **ospvSSLSession)
{
OSPM_DBGENTER(("ENTER: OSPPSSLSessionDelete()\n"));
if (*ospvSSLSession != OSPC_OSNULL)
{
if (OSPPSSLSessionHasContext(*ospvSSLSession))
{
if (ospvGracefulShutdown == OSPC_TRUE)
{
OSPPSSLWrapSessionGracefulShutdown(*ospvSSLSession);
}
OSPPSSLWrapSessionContextDelete(*ospvSSLSession);
}
OSPM_FREE(*ospvSSLSession);
*ospvSSLSession = OSPC_OSNULL;
}
OSPM_DBGEXIT(("EXIT : OSPPSSLSessionDelete()\n"));
return;
}
int
OSPPSSLSessionNew(
OSPTHTTP *ospvHttp,
OSPTSEC *ospvSecurity)
{
int errorcode = OSPC_ERR_NO_ERROR,
rootcacertlen = 0;
void *rootcacert = OSPC_OSNULL;
OSPM_DBGENTER(("ENTER: OSPPSSLSessionNew()\n"));
/*
* If https is required, ensure that a SSL Session is currently
* active for this socket and that its session-id has not expired
*/
if (OSPM_COMM_SECURED_IO(ospvHttp->ServicePoint))
{
/* if no ssl context, then create a new one */
if (ospvHttp->SSLSession == OSPC_OSNULL)
{
errorcode = OSPPSSLSessionInitialize(ospvHttp, ospvSecurity);
/* do the SSL handshake */
if (errorcode == OSPC_ERR_NO_ERROR)
{
errorcode = OSPPSSLSessionNegotiate(ospvHttp);
if (errorcode == OSPC_ERR_NO_ERROR)
{
errorcode = OSPPSSLWrapGetServerRootCACert(&rootcacert,
&rootcacertlen, ospvHttp->SSLSession);
if (errorcode == OSPC_ERR_NO_ERROR)
{
/* ------------------------------------------------------
* Verify that we trust this server's Root CA Certificate
* OpenSSL Verifies this for you. Uncomment if you need this
* ------------------------------------------------------
*errorcode = OSPPSecVerifyRootAuthorityCertificate(ospvSecurity,
* rootcacert, rootcacertlen);
*/
}
if (rootcacert != OSPC_OSNULL)
{
OSPPSSLWrapFreeServerRootCACert(&rootcacert);
}
}
else
{
/* clean up any unused session ids */
if (ospvHttp->SSLSession && ospvHttp->SSLSession->SessionId)
{
OSPPSecSSLSessionIdDelete(ospvSecurity, &(ospvHttp->SSLSession->SessionId), OSPC_TRUE);
}
}
}
}
}
OSPM_DBGEXIT(("EXIT : OSPPSSLSessionNew()\n"));
return errorcode;
}
int
OSPPSSLSessionInitialize(
OSPTHTTP *ospvHttp,
OSPTSEC *ospvSecurity)
{
int errorcode = OSPC_ERR_NO_ERROR;
OSPM_DBGENTER(("ENTER: OSPPSSLSessionInitialize()\n"));
/*
* initialize the SSL Session object
*/
ospvHttp->SSLSession = OSPPSSLSessionAlloc();
if (ospvHttp->SSLSession == OSPC_OSNULL)
{
errorcode = OSPC_ERR_HTTP_SSL_NEW_FAILED;
}
else
{
/*
* initialize the SSL Session Context
*/
errorcode = OSPPSSLWrapSessionContextNew((void *)ospvHttp,
(void *)ospvSecurity);
if (errorcode != OSPC_ERR_NO_ERROR)
{
errorcode = OSPC_ERR_HTTP_SSL_CTX_NEW_FAILED;
}
}
OSPM_DBGEXIT(("EXIT : OSPPSSLSessionInitialize() (%d)\n", errorcode));
return errorcode;
}
int
OSPPSSLSessionNegotiate(
OSPTHTTP *ospvHttp)
{
int errorcode = OSPC_ERR_NO_ERROR;
OSPM_DBGENTER(("ENTER: OSPPSSLSessionNegotiate()\n"));
/*
* attach the connected socket to the SSL library
*/
errorcode = OSPPSSLWrapAttachConnection(
ospvHttp->SSLSession, ospvHttp);
if (errorcode == OSPC_ERR_NO_ERROR)
{
errorcode = OSPPSSLWrapHandshake(ospvHttp->SSLSession);
}
OSPM_DBGEXIT(("EXIT : OSPPSSLSessionNegotiate() (%d)\n", errorcode));
return errorcode;
}
int
OSPPSSLSessionRead(
OSPTHTTP *ospvHttp,
void *ospvBuffer,
unsigned int *ospvLength,
char *ospvDelimiter)
{
int errorcode = OSPC_ERR_NO_ERROR;
register unsigned bufidx = 0;
unsigned char *tmpptr = OSPC_OSNULL;
unsigned delimitsz = 0,
delimitidx = 0;
unsigned int len = 1;
OSPM_DBGENTER(("ENTER: OSPPSSLSessionRead() delim = <%s> len = <%d>\n",
ospvDelimiter ? ospvDelimiter : "", *ospvLength));
/*
* with a delimiter present, read from buffer until
* a delimiter is encountered
*/
if (ospvDelimiter != OSPC_OSNULL)
{
delimitsz = strlen(ospvDelimiter);
tmpptr = (unsigned char *)ospvBuffer;
while (delimitsz != delimitidx &&
bufidx < *ospvLength &&
errorcode == OSPC_ERR_NO_ERROR)
{
if (OSPM_COMM_SECURED_IO(ospvHttp->ServicePoint))
{
errorcode = OSPPSSLWrapGetData(
(void *)&((unsigned char *)ospvBuffer)[bufidx],
&len,
(OSPTSSLSESSION *)
ospvHttp->SSLSession);
}
else
{
errorcode = OSPPSockRead(ospvHttp,
&((unsigned char *)ospvBuffer)[bufidx],
&len);
}
if (errorcode == OSPC_ERR_NO_ERROR)
{
/*
* does the input character match the corresponding
* character in our delimiter string?
*/
if (((unsigned char *)ospvBuffer)[bufidx]
== ospvDelimiter[delimitidx])
{
/*
* yes, we have a character match.
* if delimitidx is 0, set the tmpptr to the
* beginning buffer address which may contain the
* delimiter.
*/
if (!delimitidx)
{
tmpptr = &((unsigned char *)ospvBuffer)[bufidx];
}
delimitidx++;
}
else
/*
* not a match, reset delimitidx
*/
delimitidx = 0;
bufidx++;
}
}
if (errorcode == OSPC_ERR_NO_ERROR)
{
/*
* overwrite the current length. set to the actual
* bytes received in total
*/
*ospvLength = bufidx;
/*
* terminate the delimited input buffer
*/
if (bufidx < *ospvLength)
{
((unsigned char *)ospvBuffer)[bufidx] = '\0';
}
}
}
else
{
/*
* read the whole message from the SSL internal buffer/socket
*/
len = *ospvLength;
if (OSPM_COMM_SECURED_IO(ospvHttp->ServicePoint))
{
errorcode = OSPPSSLWrapGetData(ospvBuffer, ospvLength,
(OSPTSSLSESSION *)ospvHttp->SSLSession);
}
else
{
errorcode = OSPPSockRead(ospvHttp,
&((unsigned char *)ospvBuffer)[bufidx],
&len);
}
}
/*
OSPM_DBG((OSPVDbgFlag&OSPC_DBGNET),("NETIO: OSPPSSLSessionRead() recv [%*s]\n",
len, (char *)ospvBuffer));
*/
OSPM_DBGEXIT(("EXIT : OSPPSSLSessionRead() (%d)\n", errorcode));
return errorcode;
}
int
OSPPSSLSessionWrite(
OSPTHTTP *ospvHttp,
void *ospvBuffer,
unsigned int *ospvLength)
{
int errorcode = OSPC_ERR_NO_ERROR;
OSPM_DBGENTER(("ENTER: OSPPSSLSessionWrite()\n"));
if (OSPM_COMM_SECURED_IO(ospvHttp->ServicePoint))
{
errorcode = OSPPSSLWrapSendData(ospvBuffer,
ospvLength,
(OSPTSSLSESSION *)ospvHttp->SSLSession);
}
else
{
errorcode = OSPPSockWrite(ospvHttp,
(unsigned char *)ospvBuffer, ospvLength);
}
OSPM_DBGEXIT(("EXIT : OSPPSSLSessionWrite() (%d)\n", errorcode));
return errorcode;
}
OSPTSSLSESSION *
OSPPSSLSessionAlloc()
{
OSPTSSLSESSION *sslsess = OSPC_OSNULL;
OSPM_DBGENTER(("ENTER: OSPPSSLSessionAlloc()\n"));
OSPM_MALLOC(sslsess, OSPTSSLSESSION, sizeof(OSPTSSLSESSION));
if (sslsess != OSPC_OSNULL)
{
OSPM_MEMSET(sslsess, 0, sizeof(OSPTSSLSESSION));
}
OSPM_DBGEXIT(("EXIT : OSPPSSLSessionAlloc() (%lx)\n", (unsigned long)sslsess));
return sslsess;
}
unsigned
OSPPSSLSessionHasSessionId(
OSPTSSLSESSION *ospvSSLSession)
{
unsigned hassessionid = 0;
OSPM_DBGENTER(("ENTER: OSPPSSLSessionHasSessionId()\n"));
if (ospvSSLSession != OSPC_OSNULL)
{
hassessionid = (ospvSSLSession->SessionId != OSPC_OSNULL);
}
OSPM_DBGEXIT(("EXIT : OSPPSSLSessionHasSessionId() (%d)\n", hassessionid));
return hassessionid;
}