Showing posts with label C. Show all posts
Showing posts with label C. Show all posts
Wednesday, April 16, 2008
Proxy HTTP request
Today I was working with HTTP protocol, I had to connect to web server over proxy using C and Sockets.
For this task you have to connect with the proxy and it'll redirect your request to your requested web server, if you are authenticated.
My Proxy uses Basic Authorization then I had to send the login information (userid and password) in base64 format. For this task I used OpenSSL one more time.
Once you are authenticated, and you have send a GET request correctly formated, proxy will send response to you.
Bellow I write a necesary code to do this connection. I hope it'll be usefull for you.
// Proxy.c : HTTP/HTTPS Request example
//
#include <stdio.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#ifdef WIN32
#include <winsock.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include "applink.c"
// OpenSSL functions
void OpenSSL_add_all_algorithms();
void ERR_load_crypto_strings();
void ENGINE_load_builtin_engines();
// my functions
char *base64(const unsigned char *input, int length);
BOOL sendGet(const char* host, const char* dir, const char* proxy,
unsigned short proxyPort, const char* uid, const char* pwd);
char* GetIpAddress(char* host);
long getLen(char* cadena, long *bytes);
#define MAXLEN 10000
int main (int argc, char* argv[])
{
char ret[2500]="";
boolean r=FALSE;
// OpenSSL Init
_fmode=_O_BINARY;
CRYPTO_malloc_init();
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
ENGINE_load_builtin_engines();
vERR_load_crypto_strings();
// HTTPS connection example
r= sendGet("www.ingdirect.es:443", "CONNECT www.ingdirect.es:443 ", "myproxy.es", 8080, "uid", "pwd");
// Ejemplo HTTP
r= sendGet("www.elmundo.es", "GET /", "myproxy.es", 8080, "uid", "pwd");
return 0;
}
/*
*
* Sends a HTTP request
*
*/
BOOL sendGet(const char* host, const char* dir, const char* proxy,
unsigned short proxyPort, const char* uid, const char* pwd)
{
int iProtocolPort = 0;
char szBuffer[MAXLEN] = "";
SOCKET sd;
struct sockaddr_in sa;
char proxySrv[16]="";
char login[200]="";
boolean loop=TRUE;
int ret=0;
FILE *file=NULL;
int len=0;
long bytes=0;
#ifdef WIN32
int err=0;
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup(wVersionRequested, &wsaData );
if ( err != 0 )
{
return FALSE;
}
#endif
// Translate hostname to ip address
strcpy(proxySrv, GetIpAddress((char*)proxy));
// creating Socket
sd = socket(PF_INET, SOCK_STREAM, 0);
if (sd == INVALID_SOCKET)
{
// Can't open the socket
return FALSE;
}
memset (&sa, '\0', sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr (proxySrv); /* Proxy Ip */
sa.sin_port = htons(proxyPort); /* Proxy Port */
// Connecting to Proxy
if(connect(sd, (struct sockaddr*) &sa, sizeof(sa)))
{
// Error connecting proxy!
return FALSE;
}
// Init Request
sprintf(szBuffer,"%s HTTP/1.1\r\nHost:%s\r\n", dir,host);
// setting login information
strcat(szBuffer,"Proxy-authorization:Basic ");
strcpy(login,uid);
strcat(login, ":");
strcat(login,pwd);
strcpy(login, base64(login, strlen(login)));
strcat(szBuffer,login);
strcat(szBuffer, "\r\n\r\n");
// Sending request
send(sd,szBuffer,strlen(szBuffer),0);
// Proxy response
bytes=recv(sd, szBuffer, sizeof(szBuffer), 0);
file=fopen("c:\\index.html","w");
len=getLen(szBuffer, &bytes);
fprintf(file, "%s", szBuffer);
fflush(file);
if(bytes>0 && strncmp(szBuffer+strlen(szBuffer)-4,"\r\n\r\n",4)!=0 && (len>0 && len>bytes)){
// Writing proxy response
do{
ret=recv(sd, szBuffer, sizeof(szBuffer), 0);
bytes+=ret;
if(ret<0 || strncmp(szBuffer+strlen(szBuffer)-4,"\r\n\r\n",4)==0 || (len>0 && len<bytes)){
loop=FALSE;
}
fprintf(file, "%s",szBuffer);
fflush(file);
}while(loop);
}
fclose(file);
// closing connection
#ifdef WIN32
closesocket (sd);
// free resources
WSACleanup();
#else
close(sd);
#endif
return TRUE;
}
/*
*
* Returns a Base64 string
*
*/
char *base64(const unsigned char *input, int length)
{
BIO *bmem, *b64;
BUF_MEM *bptr;
char *buff="";
b64 = BIO_new(BIO_f_base64());
bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
BIO_write(b64, input, length);
BIO_flush(b64);
BIO_get_mem_ptr(b64, &bptr);
buff = (char *)malloc(bptr->length);
memcpy(buff, bptr->data, bptr->length-1);
buff[bptr->length-1] = 0;
BIO_free_all(b64);
return buff;
}
/*
*
* Translate hostname to ip address
*
*/
char* GetIpAddress(char *hostname)
{
struct sockaddr_in SocketAddress;
struct hostent *pHost = 0;
char aszIPAddresses[16];
int iCnt=0;
pHost = gethostbyname(hostname);
if(!pHost)
return "";
// Recupero la primera ip del Servidor
memcpy(&SocketAddress.sin_addr, pHost->h_addr_list[0], pHost->h_length);
strcpy(aszIPAddresses, inet_ntoa(SocketAddress.sin_addr));
// Retorno la ip
return aszIPAddresses;
}
/*
*
* Returns length data from Content-Length header
*
*/
long getLen(char* cadena, long *bytes){
int t=0;
char len[10];
while(t<MAXLEN){
if(strncmp(cadena+t,"Content-Length:",15)==0){
int f=t+16;
while(cadena[f]!='\r')
f++;
memcpy(len, cadena+t+16,f-(t+16));
while(strncmp(cadena+f,"\r\n\r\n",4)!=0)
f++;
*bytes=*bytes-f;
return atol(len);
}
t++;
}
return -1;
}
Monday, March 31, 2008
Socket eMail Example
Hi Friends, today We need to send a simple alert mail from our application and I have wanted to send this email from C using sockets.
It isn't difficult, you need to open a socket connection to the server using the port of email service and exchange some messages to send the alert message.
All messages you have to send, should be terminated by "\r\n" and after each message you have to call to recv function to get the response from the server.
The first message to send to the Server is the HELO %s\r\n message, replacing %s with the server ip address.
After this message you have to send the EHLO\r\n message, this message will be responsed by the Server with all operations permited by the server.
If you need to send some login information to your email server, you'll need to send the auth\r\n message and after this, you'll have to send the user uid\r\n and pwd\r\n in base64 format.
To do this, I've used Openssl again.
At this point you have to send the information about the from address, to address, subject and body.
For ending the comunication with the server you need to send a blank line and after this blank line send a quit\r\n message.
Bellow I paste the code I've used to do this, I hope it'll be useful for you
// Mail.c : email function example
//
#include <stdio.h>
#include <memory.h>
#include <errno.h>
#includee <sys/types.h>
#ifdef WIN32
#include <winsock.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include <openssl/bio.h>
#include <openssl/evp.h>
#include "applink.c"
BIO_METHOD * BIO_f_base64(void);
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
char *base64(const unsigned char *input, int length);
int main (int argc, char* argv[])
{
char ret[2500]="";
// Init OpenSSL
_fmode=_O_BINARY;
CRYPTO_malloc_init();
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
ENGINE_load_builtin_engines();
ERR_load_crypto_strings();
return SendMail("uid@server.es","uidTo@server.es", "MailServerIp", "Subject", "UID","PWD", "Message");
}
/*
*
* Send Text Mail from user requested to the target user, using the server and the specified credentials.
*
*/
BOOL SendMail(const char* _From, const char* _To, const char* host,
const char* _Subject, const char* uid, const char* pwd, const char* _MessageFormat, ...)
{
int iProtocolPort = 0;
char szBuffer[4096] = "";
SOCKET sd;
struct sockaddr_in sa;
LPSERVENT lpServEntry;
va_list message_parts;
char message[65536];
int err=0;
char _SMTP[16]="";
#ifdef WIN32
WORD wVersionRequested;
WSADATA wsaData;
#endif
#ifdef WIN32
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup(wVersionRequested, &wsaData );
if ( err != 0 )
{
exit(1);
}
#endif
// traslating namehost to ip address
strcpy(_SMTP, GetIpAddress((char*)host));
// creating the Socket
sd = socket(PF_INET, SOCK_STREAM, 0);
if (sd == INVALID_SOCKET)
{
// Cannot open mail server socket!
return FALSE;
}
// Getting the mail port
lpServEntry = getservbyname("mail", 0);
// if we havent't a port, we use the default port to SMTP
if (!lpServEntry)
iProtocolPort = htons(IPPORT_SMTP);
else
iProtocolPort = lpServEntry->s_port;
memset (&sa, '\0', sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr (_SMTP); /* Server IP*/
sa.sin_port = (iProtocolPort); /* Server Port*/
// Connecting to the Server
if(connect(sd, (struct sockaddr*) &sa, sizeof(sa)))
{
// Error connecting to the Server!
return FALSE;
}
// Initial response from the Server
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Init dialog
sprintf(szBuffer, "HELO %s\r\n", _SMTP);
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
sprintf(szBuffer,"ehlo\r\n");
send(sd,szBuffer,strlen(szBuffer),0);
recv(sd,szBuffer,sizeof(szBuffer),0);
// Sending login
strcpy(szBuffer, "auth login\r\n");
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Send userid
sprintf(szBuffer,"%s\r\n", base64(uid, strlen(uid)));
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Send Pwd
sprintf(szBuffer,"%s\r\n", base64(pwd, strlen(pwd)));
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// send From
sprintf(szBuffer, "MAIL FROM:<%s>\r\n", _From);
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Send To
// repeat for each target address
sprintf(szBuffer, "RCPT TO:<%s>\r\n", _To);
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Send Data
sprintf(szBuffer, "DATA\r\n");
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Preparing the string to send
va_start(message_parts, _MessageFormat);
vsprintf(message, _MessageFormat, message_parts);
va_end(message_parts);
// Setting Subject and Body
sprintf(szBuffer,"Subject: %s\r\n\r\n%s\r\n.\r\n",_Subject, message);
// Send a blank line to end the transmision
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Sending end command
sprintf(szBuffer, "quit\r\n");
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// closing the connection
#ifdef WIN32
closesocket (sd);
#else
close(sd);
#endif
return TRUE;
}
char *base64(const unsigned char *input, int length)
{
BIO *bmem, *b64;
BUF_MEM *bptr;
char *buff="";
b64 = BIO_new(BIO_f_base64());
bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
BIO_write(b64, input, length);
BIO_flush(b64);
BIO_get_mem_ptr(b64, &bptr);
buff = (char *)malloc(bptr->length);
memcpy(buff, bptr->data, bptr->length-1);
buff[bptr->length-1] = 0;
BIO_free_all(b64);
return buff;
}
/*
*
* Return Ip from hostname
*
*/
char* GetIpAddress(char *hostname)
{
struct sockaddr_in SocketAddress;
struct hostent *pHost = 0;
char aszIPAddresses[16];
int iCnt=0;
pHost = gethostbyname(hostname);
if(!pHost)
return "";
// get first server ip
memcpy(&SocketAddress.sin_addr, pHost->h_addr_list[0], pHost->h_length);
strcpy(aszIPAddresses, inet_ntoa(SocketAddress.sin_addr));
// returning ip
return aszIPAddresses;
}
It isn't difficult, you need to open a socket connection to the server using the port of email service and exchange some messages to send the alert message.
All messages you have to send, should be terminated by "\r\n" and after each message you have to call to recv function to get the response from the server.
The first message to send to the Server is the HELO %s\r\n message, replacing %s with the server ip address.
After this message you have to send the EHLO\r\n message, this message will be responsed by the Server with all operations permited by the server.
If you need to send some login information to your email server, you'll need to send the auth\r\n message and after this, you'll have to send the user uid\r\n and pwd\r\n in base64 format.
To do this, I've used Openssl again.
At this point you have to send the information about the from address, to address, subject and body.
For ending the comunication with the server you need to send a blank line and after this blank line send a quit\r\n message.
Bellow I paste the code I've used to do this, I hope it'll be useful for you
// Mail.c : email function example
//
#include <stdio.h>
#include <memory.h>
#include <errno.h>
#includee <sys/types.h>
#ifdef WIN32
#include <winsock.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include <openssl/bio.h>
#include <openssl/evp.h>
#include "applink.c"
BIO_METHOD * BIO_f_base64(void);
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
char *base64(const unsigned char *input, int length);
int main (int argc, char* argv[])
{
char ret[2500]="";
// Init OpenSSL
_fmode=_O_BINARY;
CRYPTO_malloc_init();
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
ENGINE_load_builtin_engines();
ERR_load_crypto_strings();
return SendMail("uid@server.es","uidTo@server.es", "MailServerIp", "Subject", "UID","PWD", "Message");
}
/*
*
* Send Text Mail from user requested to the target user, using the server and the specified credentials.
*
*/
BOOL SendMail(const char* _From, const char* _To, const char* host,
const char* _Subject, const char* uid, const char* pwd, const char* _MessageFormat, ...)
{
int iProtocolPort = 0;
char szBuffer[4096] = "";
SOCKET sd;
struct sockaddr_in sa;
LPSERVENT lpServEntry;
va_list message_parts;
char message[65536];
int err=0;
char _SMTP[16]="";
#ifdef WIN32
WORD wVersionRequested;
WSADATA wsaData;
#endif
#ifdef WIN32
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup(wVersionRequested, &wsaData );
if ( err != 0 )
{
exit(1);
}
#endif
// traslating namehost to ip address
strcpy(_SMTP, GetIpAddress((char*)host));
// creating the Socket
sd = socket(PF_INET, SOCK_STREAM, 0);
if (sd == INVALID_SOCKET)
{
// Cannot open mail server socket!
return FALSE;
}
// Getting the mail port
lpServEntry = getservbyname("mail", 0);
// if we havent't a port, we use the default port to SMTP
if (!lpServEntry)
iProtocolPort = htons(IPPORT_SMTP);
else
iProtocolPort = lpServEntry->s_port;
memset (&sa, '\0', sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr (_SMTP); /* Server IP*/
sa.sin_port = (iProtocolPort); /* Server Port*/
// Connecting to the Server
if(connect(sd, (struct sockaddr*) &sa, sizeof(sa)))
{
// Error connecting to the Server!
return FALSE;
}
// Initial response from the Server
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Init dialog
sprintf(szBuffer, "HELO %s\r\n", _SMTP);
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
sprintf(szBuffer,"ehlo\r\n");
send(sd,szBuffer,strlen(szBuffer),0);
recv(sd,szBuffer,sizeof(szBuffer),0);
// Sending login
strcpy(szBuffer, "auth login\r\n");
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Send userid
sprintf(szBuffer,"%s\r\n", base64(uid, strlen(uid)));
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Send Pwd
sprintf(szBuffer,"%s\r\n", base64(pwd, strlen(pwd)));
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// send From
sprintf(szBuffer, "MAIL FROM:<%s>\r\n", _From);
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Send To
// repeat for each target address
sprintf(szBuffer, "RCPT TO:<%s>\r\n", _To);
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Send Data
sprintf(szBuffer, "DATA\r\n");
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Preparing the string to send
va_start(message_parts, _MessageFormat);
vsprintf(message, _MessageFormat, message_parts);
va_end(message_parts);
// Setting Subject and Body
sprintf(szBuffer,"Subject: %s\r\n\r\n%s\r\n.\r\n",_Subject, message);
// Send a blank line to end the transmision
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// Sending end command
sprintf(szBuffer, "quit\r\n");
send(sd, szBuffer, strlen(szBuffer), 0);
recv(sd, szBuffer, sizeof(szBuffer), 0);
// closing the connection
#ifdef WIN32
closesocket (sd);
#else
close(sd);
#endif
return TRUE;
}
char *base64(const unsigned char *input, int length)
{
BIO *bmem, *b64;
BUF_MEM *bptr;
char *buff="";
b64 = BIO_new(BIO_f_base64());
bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
BIO_write(b64, input, length);
BIO_flush(b64);
BIO_get_mem_ptr(b64, &bptr);
buff = (char *)malloc(bptr->length);
memcpy(buff, bptr->data, bptr->length-1);
buff[bptr->length-1] = 0;
BIO_free_all(b64);
return buff;
}
/*
*
* Return Ip from hostname
*
*/
char* GetIpAddress(char *hostname)
{
struct sockaddr_in SocketAddress;
struct hostent *pHost = 0;
char aszIPAddresses[16];
int iCnt=0;
pHost = gethostbyname(hostname);
if(!pHost)
return "";
// get first server ip
memcpy(&SocketAddress.sin_addr, pHost->h_addr_list[0], pHost->h_length);
strcpy(aszIPAddresses, inet_ntoa(SocketAddress.sin_addr));
// returning ip
return aszIPAddresses;
}
Friday, January 25, 2008
SSL OpenSSL with Visual C++
Today I have another solution to work with SSL from Visual C++ using OpenSSL.
Well, the OpenSSL compilation was described before, so I can’t described here again. Click here if you want to know more about OpenSSL compilation
To work with SSL is easy with OpenSSL, really is a layer to add to our Windows Socket Projects.
The steps you’ll have to do are:
1. Add the OpenSSL libs (libeay32.lib, ssleay32.lib) to your project in Link options. Well, and touch some different options in this sheet, download the projects to see more about this point.
2. Add the OpenSSL header files to your main cpp.
3. And the OpenSSL SSL commands.
Here is the sample server code:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <winsock.h>
#include <openssl/rsa.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
/* certificates root path */
#define HOME "./"
/* certificate and private key */
#define CERTF HOME "micert.pem"
#define KEYF HOME "mikey.key"
/* checking fuctions */
#define CHK_NULL(x) if ((x)==NULL) exit (1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }
int err;
void main ()
{
int err;
int listen_sd;
int sd;
struct sockaddr_in sa_serv;
struct sockaddr_in sa_cli;
int client_len;
SSL_CTX* ctx;
SSL* ssl;
X509* client_cert;
char* str;
char buf [4096];
SSL_METHOD *meth;
WORD wVersionRequested;
WSADATA wsaData;
/* SSL init. Keep the Key and the certificate in the context. */
SSL_load_error_strings();
SSLeay_add_ssl_algorithms();
meth = SSLv23_server_method();
ctx = SSL_CTX_new (meth);
if (!ctx) {
ERR_print_errors_fp(stderr);
exit(2);
}
if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
exit(3);
}
if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
exit(4);
}
if (!SSL_CTX_check_private_key(ctx)) {
fprintf(stderr,"The private Key don’t match with the certificate\n");
exit(5);
}
/*****************************************************/
/* */
/* Socket Initialitation */
/* */
/*****************************************************/
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup(wVersionRequested, &wsaData );
if ( err != 0 )
{
printf("///Error in WSAStartup//%d\n",err);
exit(err);
}
listen_sd = socket (AF_INET, SOCK_STREAM, 0);
printf("socket() return 0x%X (%d)\n", listen_sd, listen_sd);
CHK_ERR(listen_sd, "socket");
memset (&sa_serv, '\0', sizeof(sa_serv));
sa_serv.sin_family = AF_INET;
sa_serv.sin_addr.s_addr = INADDR_ANY;
sa_serv.sin_port = htons (9000); /* Server listen Port */
err = bind(listen_sd, (struct sockaddr*) &sa_serv,
sizeof (sa_serv));
CHK_ERR(err, "bind");
/*****************************************************/
/* */
/* setting listening */
/* */
/*****************************************************/
printf("listening\n");
err = listen (listen_sd, 5); CHK_ERR(err, "listen");
client_len = sizeof(sa_cli);
sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len);
CHK_ERR(sd, "accept");
closesocket (listen_sd);
printf ("Connection from %lx, port %x\n",
sa_cli.sin_addr.s_addr, sa_cli.sin_port);
/*****************************************************/
/* */
/* preparing SSL with the recived socket */
/* */
/*****************************************************/
ssl = SSL_new (ctx); CHK_NULL(ssl);
SSL_set_fd (ssl, sd);
err = SSL_accept (ssl); CHK_SSL(err);
/* Showing cipher - optional */
printf ("SSL connection using %s\n", SSL_get_cipher (ssl));
/* Get Client cert, if exist - optional */
client_cert = SSL_get_peer_certificate (ssl);
if (client_cert != NULL) {
printf ("Client Certificate:\n");
str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);
CHK_NULL(str);
printf ("\t subject: %s\n", str);
OPENSSL_free (str);
str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0);
CHK_NULL(str);
printf ("\t issuer: %s\n", str);
OPENSSL_free (str);
/* Here we could check all we want about client certificate. */
X509_free (client_cert);
} else
printf ("The Client hasn’t certificate.\n");
/* Exchanging messages */
err = SSL_read (ssl, buf, sizeof(buf) - 1); CHK_SSL(err);
buf[err] = '\0';
printf ("Read %d characters:'%s'\n", err, buf);
err = SSL_write (ssl, "I’m listening.", strlen("I’m listening.")); CHK_SSL(err);
/* Freeing resources */
closesocket (sd);
SSL_free (ssl);
SSL_CTX_free (ctx);
}
Bellow is the SSL Client Code.
#include <stdio.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <winsock.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define CHK_NULL(x) if ((x)==NULL) exit (1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }
void main ()
{
int err=0;
int sd;
struct sockaddr_in sa;
SSL_CTX* ctx;
SSL* ssl;
X509* scert;
char* txt;
char buff [4096];
SSL_METHOD *meth;
WORD wVersionRequested;
WSADATA wsaData;
SSLeay_add_ssl_algorithms();
meth = SSLv2_client_method();
SSL_load_error_strings();
ctx = SSL_CTX_new (meth); CHK_NULL(ctx);
CHK_SSL(err);
/*****************************************************/
/* */
/* Socket Init and connecting. */
/* */
/*****************************************************/
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup(wVersionRequested, &wsaData );
if ( err != 0 )
{
printf("///Error in WSAStartup //%d\n",err);
exit(1);
}
sd = socket (AF_INET, SOCK_STREAM, 0);
CHK_ERR(sd, "socket");
memset (&sa, '\0', sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr ("127.0.0.1"); /* Server Ip */
sa.sin_port = htons (9000); /* Server port */
err = connect(sd, (struct sockaddr*) &sa,
sizeof(sa)); CHK_ERR(err, "connection");
/*****************************************************/
/* */
/* Starting SSL connection */
/* */
/*****************************************************/
ssl = SSL_new (ctx); CHK_NULL(ssl);
SSL_set_fd (ssl, sd);
err = SSL_connect (ssl); CHK_SSL(err);
/* Get the cipher - optional */
printf ("SSL connection using %s\n", SSL_get_cipher (ssl));
/* Get Server certificate - optional */
scert = SSL_get_peer_certificate (ssl); CHK_NULL(scert);
printf ("Server Certificate:\n");
txt = X509_NAME_oneline (X509_get_subject_name (scert),0,0);
CHK_NULL(txt);
printf ("\t Subject: %s\n", txt);
OPENSSL_free (txt);
txt = X509_NAME_oneline (X509_get_issuer_name (scert),0,0);
CHK_NULL(txt);
printf ("\t Issuer: %s\n", txt);
OPENSSL_free (txt);
/* Here we can check what we wanted about the Server certificate */
X509_free (scert);
/*****************************************************/
/* */
/* Exchanging messages */
/* */
/*****************************************************/
err = SSL_write (ssl, "Is someone there?", strlen("Is someone there?")); CHK_SSL(err);
err = SSL_read (ssl, buff, sizeof(buff) - 1); CHK_SSL(err);
buff[err] = '\0';
printf ("Read %d characters:'%s'\n", err, buff);
SSL_shutdown (ssl); /* sending the SSL/TLS end*/
/* Freeing resources */
closesocket (sd);
SSL_free (ssl);
SSL_CTX_free (ctx);
}
If you want to download the client and Server projects, click here. Source Files
Well, the OpenSSL compilation was described before, so I can’t described here again. Click here if you want to know more about OpenSSL compilation
To work with SSL is easy with OpenSSL, really is a layer to add to our Windows Socket Projects.
The steps you’ll have to do are:
1. Add the OpenSSL libs (libeay32.lib, ssleay32.lib) to your project in Link options. Well, and touch some different options in this sheet, download the projects to see more about this point.
2. Add the OpenSSL header files to your main cpp.
3. And the OpenSSL SSL commands.
Here is the sample server code:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <winsock.h>
#include <openssl/rsa.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
/* certificates root path */
#define HOME "./"
/* certificate and private key */
#define CERTF HOME "micert.pem"
#define KEYF HOME "mikey.key"
/* checking fuctions */
#define CHK_NULL(x) if ((x)==NULL) exit (1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }
int err;
void main ()
{
int err;
int listen_sd;
int sd;
struct sockaddr_in sa_serv;
struct sockaddr_in sa_cli;
int client_len;
SSL_CTX* ctx;
SSL* ssl;
X509* client_cert;
char* str;
char buf [4096];
SSL_METHOD *meth;
WORD wVersionRequested;
WSADATA wsaData;
/* SSL init. Keep the Key and the certificate in the context. */
SSL_load_error_strings();
SSLeay_add_ssl_algorithms();
meth = SSLv23_server_method();
ctx = SSL_CTX_new (meth);
if (!ctx) {
ERR_print_errors_fp(stderr);
exit(2);
}
if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
exit(3);
}
if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
exit(4);
}
if (!SSL_CTX_check_private_key(ctx)) {
fprintf(stderr,"The private Key don’t match with the certificate\n");
exit(5);
}
/*****************************************************/
/* */
/* Socket Initialitation */
/* */
/*****************************************************/
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup(wVersionRequested, &wsaData );
if ( err != 0 )
{
printf("///Error in WSAStartup//%d\n",err);
exit(err);
}
listen_sd = socket (AF_INET, SOCK_STREAM, 0);
printf("socket() return 0x%X (%d)\n", listen_sd, listen_sd);
CHK_ERR(listen_sd, "socket");
memset (&sa_serv, '\0', sizeof(sa_serv));
sa_serv.sin_family = AF_INET;
sa_serv.sin_addr.s_addr = INADDR_ANY;
sa_serv.sin_port = htons (9000); /* Server listen Port */
err = bind(listen_sd, (struct sockaddr*) &sa_serv,
sizeof (sa_serv));
CHK_ERR(err, "bind");
/*****************************************************/
/* */
/* setting listening */
/* */
/*****************************************************/
printf("listening\n");
err = listen (listen_sd, 5); CHK_ERR(err, "listen");
client_len = sizeof(sa_cli);
sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len);
CHK_ERR(sd, "accept");
closesocket (listen_sd);
printf ("Connection from %lx, port %x\n",
sa_cli.sin_addr.s_addr, sa_cli.sin_port);
/*****************************************************/
/* */
/* preparing SSL with the recived socket */
/* */
/*****************************************************/
ssl = SSL_new (ctx); CHK_NULL(ssl);
SSL_set_fd (ssl, sd);
err = SSL_accept (ssl); CHK_SSL(err);
/* Showing cipher - optional */
printf ("SSL connection using %s\n", SSL_get_cipher (ssl));
/* Get Client cert, if exist - optional */
client_cert = SSL_get_peer_certificate (ssl);
if (client_cert != NULL) {
printf ("Client Certificate:\n");
str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);
CHK_NULL(str);
printf ("\t subject: %s\n", str);
OPENSSL_free (str);
str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0);
CHK_NULL(str);
printf ("\t issuer: %s\n", str);
OPENSSL_free (str);
/* Here we could check all we want about client certificate. */
X509_free (client_cert);
} else
printf ("The Client hasn’t certificate.\n");
/* Exchanging messages */
err = SSL_read (ssl, buf, sizeof(buf) - 1); CHK_SSL(err);
buf[err] = '\0';
printf ("Read %d characters:'%s'\n", err, buf);
err = SSL_write (ssl, "I’m listening.", strlen("I’m listening.")); CHK_SSL(err);
/* Freeing resources */
closesocket (sd);
SSL_free (ssl);
SSL_CTX_free (ctx);
}
Bellow is the SSL Client Code.
#include <stdio.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <winsock.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define CHK_NULL(x) if ((x)==NULL) exit (1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }
void main ()
{
int err=0;
int sd;
struct sockaddr_in sa;
SSL_CTX* ctx;
SSL* ssl;
X509* scert;
char* txt;
char buff [4096];
SSL_METHOD *meth;
WORD wVersionRequested;
WSADATA wsaData;
SSLeay_add_ssl_algorithms();
meth = SSLv2_client_method();
SSL_load_error_strings();
ctx = SSL_CTX_new (meth); CHK_NULL(ctx);
CHK_SSL(err);
/*****************************************************/
/* */
/* Socket Init and connecting. */
/* */
/*****************************************************/
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup(wVersionRequested, &wsaData );
if ( err != 0 )
{
printf("///Error in WSAStartup //%d\n",err);
exit(1);
}
sd = socket (AF_INET, SOCK_STREAM, 0);
CHK_ERR(sd, "socket");
memset (&sa, '\0', sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr ("127.0.0.1"); /* Server Ip */
sa.sin_port = htons (9000); /* Server port */
err = connect(sd, (struct sockaddr*) &sa,
sizeof(sa)); CHK_ERR(err, "connection");
/*****************************************************/
/* */
/* Starting SSL connection */
/* */
/*****************************************************/
ssl = SSL_new (ctx); CHK_NULL(ssl);
SSL_set_fd (ssl, sd);
err = SSL_connect (ssl); CHK_SSL(err);
/* Get the cipher - optional */
printf ("SSL connection using %s\n", SSL_get_cipher (ssl));
/* Get Server certificate - optional */
scert = SSL_get_peer_certificate (ssl); CHK_NULL(scert);
printf ("Server Certificate:\n");
txt = X509_NAME_oneline (X509_get_subject_name (scert),0,0);
CHK_NULL(txt);
printf ("\t Subject: %s\n", txt);
OPENSSL_free (txt);
txt = X509_NAME_oneline (X509_get_issuer_name (scert),0,0);
CHK_NULL(txt);
printf ("\t Issuer: %s\n", txt);
OPENSSL_free (txt);
/* Here we can check what we wanted about the Server certificate */
X509_free (scert);
/*****************************************************/
/* */
/* Exchanging messages */
/* */
/*****************************************************/
err = SSL_write (ssl, "Is someone there?", strlen("Is someone there?")); CHK_SSL(err);
err = SSL_read (ssl, buff, sizeof(buff) - 1); CHK_SSL(err);
buff[err] = '\0';
printf ("Read %d characters:'%s'\n", err, buff);
SSL_shutdown (ssl); /* sending the SSL/TLS end*/
/* Freeing resources */
closesocket (sd);
SSL_free (ssl);
SSL_CTX_free (ctx);
}
If you want to download the client and Server projects, click here. Source Files
Thursday, January 24, 2008
CSoap and Visual Studio
First of all, I’m sorry for my English, but I want to improve it and this is a good way.
Well, this is my first solution.
Many times I have had to connect a c program to a Web Service, in Windows with MFC is too easy. I have a dll, which connects the c program with whatever Web Service only updating some xml files.
But, when you need to connect a c program running in other OS, you'll need to try other solutions.
The best, for me, it's CSoap.
However when I had to develop that connection I only had Windows Systems and well, I tried to connect CSoap in a Visual Studio Project.
It wasn't easy for me to find examples about CSOAP for Visual C++, and that is why I put that solution here.
Here is the original link to my source files https://sourceforge.net/tracker/download.php?group_id=74977&atid=542567&file_id=250457&aid=1816455
Well, this is my first solution.
Many times I have had to connect a c program to a Web Service, in Windows with MFC is too easy. I have a dll, which connects the c program with whatever Web Service only updating some xml files.
But, when you need to connect a c program running in other OS, you'll need to try other solutions.
The best, for me, it's CSoap.
However when I had to develop that connection I only had Windows Systems and well, I tried to connect CSoap in a Visual Studio Project.
It wasn't easy for me to find examples about CSOAP for Visual C++, and that is why I put that solution here.
Here is the original link to my source files https://sourceforge.net/tracker/download.php?group_id=74977&atid=542567&file_id=250457&aid=1816455
Subscribe to:
Posts (Atom)