Linux en Espanol Espontaneas - De tu ojo a la web
 
Un poco de libssl (tema #24610)
Publicar nuevo tema   Responder al tema    Foros de discusión -> Compartir Codigos
Ver tema anterior :: Ver tema siguiente  
Autor Mensaje
AnimAlf
Forista


Registrado: 18 Ago 2008
Mensajes: 750
Ubicación: tgn

MensajePublicado: Vie Dic 28, 2012 3:21 pm    Asunto: Un poco de libssl Responder citando

Aquí tenéis un code funcional, que muestra los pasos a seguir para un primer contacto. Realiza una conexión remota al puerto 443, recibe el certificado y envia y recibe información cifrada.

Se debe enlazar con libssl y libcrypto, por lo que para construirlo añadiremos -lssl -lcrypto

Código:
#include <stdio.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>

#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#define TIEMPO_DE_SESION 300
#define PUERTO_HTTPS 443

static void info_devuelta ( const SSL *s, int lugar, int ret )
{
    printf ( "\t%s\n", SSL_state_string_long ( s ) );
}

static void errorssl ( char *cadena )
{
    char msgerror [120];

    ERR_error_string ( ERR_get_error(), msgerror );
    printf ( "%s: %s", cadena, msgerror );
}


int main ( int argc, const char * argv[] )
{
    SSL * ssl;
    SSL_CTX * ctx;
    X509 * certificado_server;
    int sd, err;
    char *str, *urlremota, bufferSalida[4096],
        bufferEntrada[4096], peticionAlServer[512];
    struct hostent * host_entry;
    struct sockaddr_in direcion_socket_server;
    struct in_addr ip;
   
    /*
     * si no se indica la url la pedimos
     */
    if(argc != 2)
    {
        urlremota = ( char * ) malloc ( 255 );
        printf( "https://" );
        scanf ( "%s", urlremota );
    } else urlremota = ( char * ) argv[1];
   
    /*
     * iniciamos la librería SSL
     */
    SSLeay_add_ssl_algorithms ();
    SSL_load_error_strings ();
    ctx = SSL_CTX_new ( SSLv3_client_method () );

    SSL_CTX_set_session_cache_mode ( ctx, SSL_SESS_CACHE_BOTH );
    SSL_CTX_set_timeout ( ctx, TIEMPO_DE_SESION );
    SSL_CTX_set_info_callback ( ctx, info_devuelta );   

    printf ( "Entorno SSL iniciado\n\n" );

    /*
     * adquirimos la dirección ip de la URL
     */

    host_entry = gethostbyname ( urlremota );
    bcopy ( host_entry->h_addr, &( ip.s_addr ), host_entry->h_length );
    printf ( "'%s' tiene la siguiente IP '%s'\n\n", urlremota, inet_ntoa ( ip ) );
   
    /*
     * abrimos la conexión TCP al puerto remoto
     */
    sd = socket ( AF_INET,SOCK_STREAM, 0 );
   
    memset ( &direcion_socket_server, '\0', sizeof ( direcion_socket_server ) );
    direcion_socket_server.sin_family = AF_INET;
    direcion_socket_server.sin_port = htons ( PUERTO_HTTPS );
    memcpy ( &( direcion_socket_server.sin_addr.s_addr ), host_entry->h_addr,
        host_entry->h_length );
   
    err = connect(sd, (const struct sockaddr * ) &direcion_socket_server,
        sizeof ( direcion_socket_server ) );
    if(err < 0)
    {
        perror ( "no se pueder connectar con el puerto remoto" );
        exit (1);
    }
   
    printf ( "Conexión TCP iniciada con '%s' a traves de puerto local %d \n\n",
        urlremota, direcion_socket_server.sin_port );
   
    /*
     *  iniciar la negociación SSL sobre la conexión TCP
     */
    if ( ! ( ssl = SSL_new (ctx) ) ) { /*punto final pila SSL */
        errorssl ( "SSL_new" );
        close ( sd );
        exit (1);
    }
    SSL_set_fd ( ssl, sd ); /* añadimos la pila SSL al socket */

    puts ( "Información retornada durante el proceso de sonexión:" );
    err = SSL_connect ( ssl ); /* Iniciamos la negociación SSL */
    if ( err <= 0 ) {
        errorssl (  "SSL_connect" );
        SSL_shutdown ( ssl );
        SSL_free ( ssl );
        SSL_CTX_free ( ctx );
        close ( sd );
        exit (1);
    }
   
    printf("\nSSL endpoint creado & negociación completeda. err = %d\n\n", err);
   
    /*
     * mostramos el metodo de cifrado para la comunicación
     */
    printf("SSL conectado con cifrado: %s\n\n", SSL_get_cipher ( ssl ) );
   
    /*
     * mostramos el certificado del server
     */
    certificado_server = SSL_get_peer_certificate ( ssl );
    printf("Certificado del server recibido:\n\n");
    str = X509_NAME_oneline ( X509_get_subject_name ( certificado_server ), 0, 0 );
    printf("\tasunto: %s\n",str);
    str = X509_NAME_oneline ( X509_get_issuer_name ( certificado_server ), 0, 0 );
    printf ( "\temisor: %s\n",str );
    printf ( "\n" );
   
    /* la verificación del certificado ocurrió aquí. */
   
    X509_free ( certificado_server );
   
    /*
     * negociación completada --- enviar petición HTTP sobre SSL
     */
    strcpy ( bufferSalida,"GET / HTTP/1.0\r\n" );
    sprintf ( peticionAlServer, "Host: %s:%d\r\n", urlremota, PUERTO_HTTPS );
    strcat ( bufferSalida, peticionAlServer );
    strcat ( bufferSalida, "Connection: close\r\n");
    strcat ( bufferSalida, "\r\n");
   
    err = SSL_write ( ssl, bufferSalida, strlen ( bufferSalida ) );
    shutdown ( sd, 1 ); /* enviamos EOF al server */
   
    printf("Enviar petición HTTP por un canal cifrado:\n\n%s\n", bufferSalida );
   
    /*
     * leermos la respuesta HTTP a traves de la pila SSL
     */
    err = SSL_read ( ssl, bufferEntrada, sizeof ( bufferEntrada ) -1 );
    bufferEntrada[err] = '\0';
    printf ( "recibidos %d bytes como respuesta HTTP:\n\n%s\n", err, bufferEntrada );
   
    /*
     * terminamos cerrando la sesión y liberando
     */
    printf ( " salida y cierre de sesion.\n\nPulsa Return para terminar" );
    getchar ();
    SSL_shutdown ( ssl );
    close ( sd );
    SSL_free ( ssl );
    SSL_CTX_free ( ctx );
   
    return 0;
}


SaludOS
_________________
En busca del TuXeR perdido
Volver arriba
Ver perfil de usuario Enviar mensaje privado Visitar sitio web del autor MSN Messenger
Mostrar mensajes de anteriores:   
Publicar nuevo tema   Responder al tema    Foros de discusión -> Compartir Codigos Todas las horas son GMT
Página 1 de 1

 
Cambiar a:  
Puede publicar nuevos temas en este foro
No puede responder a temas en este foro
No puede editar sus mensajes en este foro
No puede borrar sus mensajes en este foro
No puede votar en encuestas en este foro




La marca registrada Linux (R) se usa siguiendo la sublicensia obtenida del "Linux Mark Institute",
el LICENCIATARIO exclusivo de Linus Torvalds, propietario de la marca en EEUU y otros países
The registered trademark Linux (R) is used pursuant to a sublicense from the Linux Mark Institute,
the exclusive LICENSEE of Linus Torvalds, owner of the mark in the U.S. and other countries
Powered by phpBB © 2001, 2002 phpBB Group

Contactos