Shows how to set up a listening socket for a SSL connection using WinSock and LibC on NetWare.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <nks/thread.h>
#include <novsock2.h>
#include <screen.h>
#define BUFFER_SIZE 256
#define WS_VER MAKEWORD(2,2)
SOCKET SSL_Bind(char *pczPort);
int SendHTTPResponse(SOCKET);
SOCKET gServerSocketHnd;
SOCKET gClientHnd;
void sigHnd(int signal)
{
closesocket(gServerSocketHnd);
gServerSocketHnd = INVALID_SOCKET;
if(INVALID_SOCKET != gClientHnd)
{
closesocket(gClientHnd);
gClientHnd = INVALID_SOCKET;
}
WSACleanup();
}
int main(void)
{
int rcode;
WORD wVersionRequested = WS_VER;
WSADATA wsaData;
char czBuffer[BUFFER_SIZE];
struct sockaddr_in saClient;
int iClientSize = sizeof(saClient);
gClientHnd = INVALID_SOCKET;
gServerSocketHnd = INVALID_SOCKET;
signal(SIGTERM, sigHnd);
memset((char *)&saClient, 0, iClientSize);
memset(czBuffer, 0, sizeof(czBuffer));
rcode = WSAStartup(wVersionRequested, &wsaData);
if(rcode){
printf("Error: %d with WSAStartup\r\n", WSAGetLastError());
goto ERR;
}
if(wsaData.wVersion != wVersionRequested){
printf("Error: invalid winsock version loaded\r\n");
goto ERR;
}
gServerSocketHnd = SSL_Bind("9000");
if(INVALID_SOCKET == gServerSocketHnd){
printf("Error: %d with SSL_Bind\r\n", WSAGetLastError());
goto ERR;
}
while(1){
gClientHnd = accept(gServerSocketHnd,
(struct sockaddr *)&saClient,
&iClientSize);
if(INVALID_SOCKET == gClientHnd){
printf("Error: %d with accept\r\n", WSAGetLastError());
goto ERR;
}
printf("Accepted client: %s:%d\r\n",
inet_ntoa(saClient.sin_addr),
ntohs(saClient.sin_port));
memset(czBuffer, 0, sizeof(czBuffer));
rcode = recv(gClientHnd, czBuffer, sizeof(czBuffer), 0);
if(SOCKET_ERROR == rcode){
printf("Error: %d with recv\r\n", WSAGetLastError());
goto ERR;
}
printf("recv returned %d\r\n", rcode);
printf("RCV: %s\r\n", czBuffer);
if(0 == strncmp("GET", czBuffer, 3))
{
rcode = SendHTTPResponse(gClientHnd);
}
else
{
rcode = send(gClientHnd, czBuffer, strlen(czBuffer), 0);
}
if(SOCKET_ERROR == rcode)
{
printf("Error: %d with send\r\n", WSAGetLastError());
// goto ERR;
}
else
{
printf("SND: %d Bytes\r\n", rcode);
}
//NXThreadYield();
printf("Closing connection\r\n\r\n");
shutdown(gClientHnd, SD_BOTH);
closesocket(gClientHnd);
gClientHnd = INVALID_SOCKET;
}
ERR:
if(INVALID_SOCKET != gClientHnd)
closesocket(gClientHnd);
if(INVALID_SOCKET != gServerSocketHnd)
closesocket(gServerSocketHnd);
WSACleanup();
pressanykey();
return 0;
}
/*
** function: SSL_Bind
** usage: binds to a port using ssl information.
*/
SOCKET SSL_Bind(char *pczPort)
{
SOCKET socketHnd = INVALID_SOCKET;
int rcode;
struct sockaddr_in saListenAddr;
WSAPROTOCOL_INFO sProtocolInfo;
struct tlsserveropts sWS2Opts;
struct nwtlsopts sNWTLSOpts;
unicode *SASKey = L"SSL CertificateDNS"; //nds name for server key
//zero out structures
memset((char *)&saListenAddr, 0, sizeof(struct sockaddr_in));
memset((char *)&sProtocolInfo, 0, sizeof(WSAPROTOCOL_INFO));
memset((char *)&sWS2Opts, 0, sizeof(struct tlsserveropts));
memset((char *)&sNWTLSOpts, 0, sizeof(struct nwtlsopts));
//setup the WSAPROTOCOL_INFO structure
sProtocolInfo.iAddressFamily = AF_INET;
sProtocolInfo.iSocketType = SOCK_STREAM;
sProtocolInfo.iProtocol = IPPROTO_TCP;
sProtocolInfo.iSecurityScheme = SECURITY_PROTOCOL_SSL;
//create a socket
socketHnd = WSASocket(AF_INET,
SOCK_STREAM,
IPPROTO_TCP,
&sProtocolInfo,
NULL,
NULL);
if(INVALID_SOCKET == socketHnd){
goto ERR;
}
//setup the tlsserveropts struct
sWS2Opts.wallet = SASKey;
sWS2Opts.walletlen = unilen(SASKey);
sWS2Opts.sidtimeout = 0;
sWS2Opts.sidentries = 0;
sWS2Opts.siddir = NULL;
sWS2Opts.options = &sNWTLSOpts;
//setup the nwtlsopts structure
sNWTLSOpts.walletProvider = WAL_PROV_KMO;
sNWTLSOpts.keysList = NULL;
sNWTLSOpts.numElementsInKeyList = 0;
sNWTLSOpts.reservedforfutureuse = NULL;
sNWTLSOpts.reservedforfutureCRL = NULL;
sNWTLSOpts.reservedforfutureCRLLen = NULL;
sNWTLSOpts.reserved1 = NULL;
sNWTLSOpts.reserved2 = NULL;
sNWTLSOpts.reserved3 = NULL;
rcode = WSAIoctl(socketHnd,
SO_TLS_SET_SERVER,
&sWS2Opts,
sizeof(struct tlsserveropts),
NULL,
0,
NULL,
NULL,
NULL);
if(SOCKET_ERROR == rcode){
printf("Error: %d with WSAIoctl(SO_TLS_SET_SERVER)\r\n", WSAGetLastError());
goto ERR;
}
saListenAddr.sin_family = AF_INET;
saListenAddr.sin_port = htons(atoi(pczPort));
saListenAddr.sin_addr.s_addr = INADDR_ANY;
rcode = bind(socketHnd,
(struct sockaddr *)&saListenAddr,
sizeof(struct sockaddr_in));
if(SOCKET_ERROR == rcode){
printf("Error: %d with bind\r\n", WSAGetLastError());
goto ERR;
}
rcode = listen(socketHnd, 0);
if(SOCKET_ERROR == rcode){
printf("Error: %d with listen\r\n", WSAGetLastError());
goto ERR;
}
ERR:
if(rcode){
closesocket(socketHnd);
socketHnd = INVALID_SOCKET;
}
return socketHnd;
}
int SendHTTPResponse(SOCKET socketHnd)
{
char czBuffer[1024];
memset(czBuffer, 0, sizeof(czBuffer));
strcpy(czBuffer, "HTTP/1.0 200 OK\r\n");
strcat(czBuffer, "Connection: close\r\n");
strcat(czBuffer, "Content-Type: text/html\r\n\r\n");
strcat(czBuffer, "<HTML>\r\n");
strcat(czBuffer, "\t<HEAD>\r\n");
strcat(czBuffer, "\t\t<TITLE>SSL/TLS Basic Server Example</TITLE>\r\n");
strcat(czBuffer, "\t</HEAD>\r\n");
strcat(czBuffer, "\t<BODY>\r\n");
strcat(czBuffer, "\t\t<H1>Look Basic Worked!!</H1>\r\n");
strcat(czBuffer, "\t</BODY>\r\n");
strcat(czBuffer, "</HTML>\r\n\r\n");
return send(socketHnd, czBuffer, strlen(czBuffer) + 1, 0);
}
int __init_environment
(
void *reserved
)
{
#pragma unused(reserved)
/*
** The caller isn't a C++ application which would have had to link mwcrtl.lib
** in order to get real C++ initilization. This is just a do-nothing dummy to
** satisfy a missing symbol in the case where the calling C-only application
** failed to link Metrowerks' library which it can do (as long as it isn't
** C++).
*/
return 0;
}
int __deinit_environment
(
void *reserved
)
{
#pragma unused(reserved)
/*
** Similarly, this function satisfies a symbol missing because the calling
** application didn't link mwcrtl.lib.
*/
return 0;
}
© 2008 Novell, Inc. All Rights Reserved.