2013-04-06 18 views
6

libcurl ha timeout options come questi:Come impostare timeout di connessione e timeout il funzionamento in OpenSSL

CURLOPT_CONNECTTIMEOUT - maximum time in seconds that you allow the connection to the server to take. 
CURLOPT_TIMEOUT - maximum time in seconds that you allow the libcurl transfer operation to take. 

mi piacerebbe implementare un meccanismo di timeout simile in OpenSSL.

Quali modifiche sarebbero necessarie nel codice seguente in modo che venga applicato un valore di timeout a BIO_do_connect(), BIO_write() e BIO_read()?

Mi collego a un server e invio/ricezione di dati al/dal server tramite BIO_write()/BIO_read() fornito da OpenSSL. Il mio codice è basato sul seguente codice di esempio disponibile da here.

int main() 
{ 
    BIO * bio; 
    SSL * ssl; 
    SSL_CTX * ctx; 

    int p; 

    char * request = "GET/HTTP/1.1\x0D\x0AHost: www.verisign.com\x0D\x0A\x43onnection: Close\x0D\x0A\x0D\x0A"; 
    char r[1024]; 

    /* Set up the library */ 

    ERR_load_BIO_strings(); 
    SSL_load_error_strings(); 
    OpenSSL_add_all_algorithms(); 

    /* Set up the SSL context */ 

    ctx = SSL_CTX_new(SSLv23_client_method()); 

    /* Load the trust store */ 

    if(! SSL_CTX_load_verify_locations(ctx, "TrustStore.pem", NULL)) 
    { 
     fprintf(stderr, "Error loading trust store\n"); 
     ERR_print_errors_fp(stderr); 
     SSL_CTX_free(ctx); 
     return 0; 
    } 

    /* Setup the connection */ 

    bio = BIO_new_ssl_connect(ctx); 

    /* Set the SSL_MODE_AUTO_RETRY flag */ 

    BIO_get_ssl(bio, & ssl); 
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 

    /* Create and setup the connection */ 

    BIO_set_conn_hostname(bio, "www.verisign.com:https"); 

    if(BIO_do_connect(bio) <= 0) 
    { 
     fprintf(stderr, "Error attempting to connect\n"); 
     ERR_print_errors_fp(stderr); 
     BIO_free_all(bio); 
     SSL_CTX_free(ctx); 
     return 0; 
    } 

    /* Check the certificate */ 

    if(SSL_get_verify_result(ssl) != X509_V_OK) 
    { 
     fprintf(stderr, "Certificate verification error: %i\n", SSL_get_verify_result(ssl)); 
     BIO_free_all(bio); 
     SSL_CTX_free(ctx); 
     return 0; 
    } 

    /* Send the request */ 

    BIO_write(bio, request, strlen(request)); 

    /* Read in the response */ 

    for(;;) 
    { 
     p = BIO_read(bio, r, 1023); 
     if(p <= 0) break; 
     r[p] = 0; 
     printf("%s", r); 
    } 

    /* Close the connection and free the context */ 

    BIO_free_all(bio); 
    SSL_CTX_free(ctx); 
    return 0; 
} 

Sono cross-compiling per ARM su Ubuntu (Eclipse con CodeSourcery Lite).

+0

correlati: [openssl ssl_connect blocca per sempre - come impostare il timeout?] (Http://stackoverflow.com/questions/11835203/openssl-ssl-connect-blocks-forever-how-to-set-timeout) – jfs

risposta

5

ho finito per fare qualcosa di simile a quanto segue (pseudocodice):

int nRet; 
int fdSocket; 
fd_set connectionfds; 
struct timeval timeout; 

BIO_set_nbio(pBio, 1); 

nRet = BIO_do_connect(pBio); 

if ((nRet <= 0) && !BIO_should_retry(pBio)) 
    // failed to establish connection. 

if (BIO_get_fd(pBio, &fdSocket) < 0) 
    // failed to get fd. 

if (nRet <= 0) 
{ 
    FD_ZERO(&connectionfds); 
    FD_SET(fdSocket, &connectionfds); 

    timeout.tv_usec = 0; 
    timeout.tv_sec = 10; 

    nRet = select(fdSocket + 1, NULL, &connectionfds, NULL, &timeout); 
    if (nRet == 0) 
     // timeout has occurred. 
} 

È possibile utilizzare lo stesso approccio per BIO_read() troppo.

È possibile trovare utile this link.

+0

Fai attenzione quando usi questo comando con 'BIO_read'. La [documentazione] (https://www.openssl.org/docs/manmaster/crypto/BIO_read.html) afferma che 'BIO_read' può comportare più chiamate a' read', potenzialmente bloccando oltre il timeout specificato. –

+0

Puoi pubblicare il tuo codice attuale o un link ad esso? – am3

-1

Date un'occhiata a SSL_CTX_set_timeout() funzione, che fa simile alla variabile di libcurl CURLOPT_TIMEOUT:

Da http://www.openssl.org/docs/ssl/SSL_CTX_set_timeout.html:

SSL_CTX_set_timeout() imposta il timeout per le sessioni di nuova creazione per CTX a t. Il valore di timeout t deve essere espresso in secondi.

Nel tuo caso si potrebbe aggiungere la seguente riga dopo aver creato oggetto CTX:

SSL_CTX_set_timeout (ctx, 60); 

Speranza che aiuta!

+0

@ Wizzard, non sono sicuro che sia quello che stavo cercando. Grazie comunque per la tua risposta. – jpen

+1

Credo che 'SSL_CTX_set_timeout' e' SSL_SESSION_set_timeout' sono il timeout per la memorizzazione e la ripresa della sessione; e non un timeout per 'select'. – jww

2

Per il collegamento, @jpen ha fornito la risposta migliore. È necessario contrassegnare il BIO come non bloccante e utilizzare select per determinare se è connesso e/o scaduto.

Le letture sono un po 'diverse. Poiché OpenSSL può eseguire il buffering dei dati decrittografati (a seconda della suite di crittografia TLS utilizzata), select potrebbe timeout quando si tenta di leggere, anche se i dati sono effettivamente disponibili. Il modo corretto per gestire i timeout di lettura consiste nel controllare prima SSL_pending o BIO_pending. Se la funzione in sospeso restituisce zero, utilizzare select per impostare un timeout. Se la funzione in sospeso restituisce maggiore di zero, chiamare semplicemente SSL_read o BIO_read o qualsiasi altra funzione di lettura.