Showing posts with label HTTPS. Show all posts
Showing posts with label HTTPS. 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;

}

Wednesday, March 5, 2008

SSL HTTP POST

Hi, friends

I'm developing a module to connect C programs with WebServices and newly I've used OpenSSL. Actually it hasn't very difficult, although I had some problem. It's very important to set properly the method to use. I'm connecting with a JBoss HTTPs WebService and I had to set this one:


meth = TLSv1_client_method();
ctx = SSL_CTX_new (meth);

I copy bellow the main function I had used, to send the HTTP POST message, I hope it'll be usefull for you:

int sendPOST(void* sd, SSL* ssl, ;char* server, char* port, char* post, char* action, char* csoap, char *response){

int ret=0;
char msg[5000]="";
char buff[5000]="";
int err=0;
int len=0;
char header[200]="";

    // Setting HTTP Headers
    sprintf(msg,"POST %s HTTP/1.1\r\n", post);
    sprintf(header,"Host: %s:%s\r\n", server, port);
    len=strlen(msg) ;
    memcpy(msg + len , header, strlen(header));
    len+=strlen(header);
    strcpy(header,"Content-Type: application/x-www-form-urlencoded; charset=utf-8\r\n");
    memcpy(msg + len, header, strlen(header));
    len+=strlen(header);
    sprintf(header,"Content-Length: %d\r\n", strlen(datos));
    memcpy(msg + len, header, strlen(header));
    len+=strlen(header);
    sprintf(header,"SOAPAction: %s\r\n\r\n",action);
    memcpy(msg + len, header, strlen(header));
    len+=strlen(header);
    // Adding csoap
    memcpy(msg + len, datos, strlen(datos));

    if(sd!=NULL){
        // No SSL Connections

        err=send((int)sd, msg, len + strlen(datos),0);
        if (err == SOCKET_ERROR) {
            printf("send() failed with error: %d\n", WSAGetLastError());
            closesocket((int)sd);
            WSACleanup();
            exit(1);
        }

        do {
            err = recv((int)sd, buff, sizeof(buff) - 1, 0);
            if ( err > 0 )
                printf("Bytes received: %d\n", err);
            else if ( err == 0 )
                printf("Connection closed\n");
            else
                printf("recv failed with error: %d\n", WSAGetLastError());

        } while( err > 0 );


    }else{
        // SSL Connections
        err = SSL_write (ssl, msg, len + strlen(datos)); CHK_SSL(err);

        err = SSL_read (ssl, buff, sizeof(buff) - 1);
        CHK_SSL(err);
        buff[err] = '\0';

        SSL_shutdown (ssl);
    }

    strcpy(respuesta, buff);

    return ret;

}