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;
}
Subscribe to:
Posts (Atom)