Hi all,
I am trying to implement renegotiation on server after a certain
amount of time using BIO_set_ssl_renegotiate_timeout() function
Renegotiation is not happening after the specified timeout.
I have written a small server program to test the renegotiation on
timeout. The server merely reads the data sent by the client, it does
not write any data. The server code is attached.
Used "s_client -connect host:port -tls1"
as the client to send data.
I am implementing non-blocking IO on the server.
Am I doing anything wrong or missing something?
The sample server code is below:
*****Server code**********
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <openssl/e_os2.h>
#include <openssl/engine.h>
#include <openssl/conf.h>
#include <openssl/crypto.h>
#include <asm/ioctls.h>
#include <sys/types.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/ssl.h>
#include <openssl/rand.h>
#define SERV_PORT 443
static unsigned char dh512_p[]={
0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75,
0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F,
0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3,
0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12,
0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C,
0x47,0x74,0xE8,0x33,
};
static unsigned char dh512_g[]={
0x02,
};
static DH *get_dh512(void)
{
DH *dh=NULL;
if ((dh=DH_new()) == NULL) return(NULL);
dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL);
dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL);
if ((dh->p == NULL) || (dh->g == NULL))
return(NULL);
return(dh);
}
static DH *load_dh_param(char *dhfile)
{
DH *ret=NULL;
BIO *bio;
if ((bio=BIO_new_file(dhfile,"r")) == NULL)
goto err;
ret=PEM_read_bio_DHparams(bio,NULL,NULL,NULL);
err:
if (bio != NULL) BIO_free(bio);
return(ret);
}
#define TEST_CERT "server.pem"
int main()
{
int sock, i, ret, err, connfd, total_bytes=0;
unsigned long Switch =1;
BIO *bio;
SSL *ssl;
SSL_CTX *ctx;
char buf[80]={0};
socklen_t cli_len;
X509_STORE *store = NULL;
int vflags = 0;
int s_server_verify=SSL_VERIFY_NONE;
char *CApath=NULL,*CAfile=NULL;
struct sockaddr_in addr, cl_addr;
if( !SSL_library_init() )
{
printf("Error in initializing SSL Library\n");
return 0;
}
SSL_load_error_strings();
sock = socket(AF_INET, SOCK_STREAM, 0);
memset (&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons( SERV_PORT );
ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
if(ret != 0)
{ printf("unable to bind to socket\n");
return 0;
}
ret = listen(sock,1);
if(ret != 0)
{
printf("unable to listen on socket\n");
return 0;
}
ctx = SSL_CTX_new(SSLv23_server_method());
if (ctx == NULL)
{
printf ("Unable to create ssl context: %s\n",
ERR_error_string(ERR_get_error(), NULL));
return 0;
}
SSL_CTX_set_options(ctx,0);
/* setting certificates and keys */
{
/*if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) ||
(!SSL_CTX_set_default_verify_paths(ctx)))
{
printf("Unable to set default cert paths: %s\n",
ERR_error_string(ERR_get_error(), NULL));
}*/
DH *dh = NULL;
dh = load_dh_param(TEST_CERT);
SSL_CTX_set_tmp_dh(ctx,dh);
DH_free(dh);
RSA *rsa;
rsa=RSA_generate_key(512,RSA_F4,NULL, NULL);
if (!SSL_CTX_set_tmp_rsa(ctx,rsa))
{
printf("Unable to set rsa values: %s\n",
ERR_error_string(ERR_get_error(), NULL));
return 0;
}
RSA_free(rsa);
if (SSL_CTX_use_certificate_file(ctx,TEST_CERT,
SSL_FILETYPE_PEM) <= 0)
{
printf("Unable to set certificate file: %s\n",
ERR_error_string(ERR_get_error(), NULL));
return(0);
}
if (SSL_CTX_use_PrivateKey_file(ctx,TEST_CERT,
SSL_FILETYPE_PEM) <= 0)
{
printf("Unable to set PrivateKey file: %s\n",
ERR_error_string(ERR_get_error(), NULL));
return(0);
}
}
for(;;)
{
total_bytes = 0;
cli_len = sizeof(cl_addr);
connfd = accept(sock, (struct sockaddr*)&cl_addr, &cli_len);
if(connfd <=0 )
continue;
bio = BIO_new_socket(connfd, BIO_CLOSE);
ssl = SSL_new(ctx);
if (ssl == NULL)
{
printf ("Unable to create ssl: %s\n",
ERR_error_string(ERR_get_error(), NULL));
return 0;
}
if ((ret = BIO_socket_ioctl(connfd,FIONBIO,&Switch)) < 0)
{
printf ("Unable to set non-blocking option on BIO\n");
return 0;
}
SSL_set_bio(ssl, bio, bio);
SSL_set_accept_state( ssl );
while ( (ret = SSL_accept(ssl)) <=0 )
{
/* printf("Error accepting ssl connection: %s\n",
ERR_error_string(ERR_get_error(), NULL));*/
}
printf("Accepted SSL Connection\n");
ret = BIO_set_ssl_renegotiate_timeout(bio, 5);
// ret = BIO_set_ssl_renegotiate_bytes(bio, 1024);
printf("setting renegotiation timeout to 5, ret = %d\n", ret);
for (; ;)
{
err = SSL_read(ssl, buf, sizeof(buf));
switch(SSL_get_error(ssl,err))
{
case SSL_ERROR_NONE:
total_bytes += err;
printf("Read: %s\n",buf);
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
break;
default:
goto shutdown;
}
}
shutdown:
if(SSL_get_shutdown(ssl) && SSL_RECEIVED_SHUTDOWN)
SSL_shutdown(ssl);
else
SSL_clear(ssl);
close(connfd);
// BIO_free(bio);
printf("total bytes read = %d\n", total_bytes);
printf("Closing connection\n");
SSL_free(ssl);
}
return 0;
}
thanks,
Lakshmi Prasanna.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <openssl/e_os2.h>
#include <openssl/engine.h>
#include <openssl/conf.h>
#include <openssl/crypto.h>
#include <asm/ioctls.h>
#include <sys/types.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/ssl.h>
#include <openssl/rand.h>
#define SERV_PORT 443
static unsigned char dh512_p[]={
0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75,
0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F,
0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3,
0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12,
0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C,
0x47,0x74,0xE8,0x33,
};
static unsigned char dh512_g[]={
0x02,
};
static DH *get_dh512(void)
{
DH *dh=NULL;
if ((dh=DH_new()) == NULL) return(NULL);
dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL);
dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL);
if ((dh->p == NULL) || (dh->g == NULL))
return(NULL);
return(dh);
}
static DH *load_dh_param(char *dhfile)
{
DH *ret=NULL;
BIO *bio;
if ((bio=BIO_new_file(dhfile,"r")) == NULL)
goto err;
ret=PEM_read_bio_DHparams(bio,NULL,NULL,NULL);
err:
if (bio != NULL) BIO_free(bio);
return(ret);
}
#define TEST_CERT "server.pem"
int main()
{
int sock, i, ret, err, connfd, total_bytes=0;
unsigned long Switch =1;
BIO *bio;
SSL *ssl;
SSL_CTX *ctx;
char buf[80]={0};
socklen_t cli_len;
X509_STORE *store = NULL;
int vflags = 0;
int s_server_verify=SSL_VERIFY_NONE;
char *CApath=NULL,*CAfile=NULL;
struct sockaddr_in addr, cl_addr;
if( !SSL_library_init() )
{
printf("Error in initializing SSL Library\n");
return 0;
}
SSL_load_error_strings();
sock = socket(AF_INET, SOCK_STREAM, 0);
memset (&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons( SERV_PORT );
ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
if(ret != 0)
{ printf("unable to bind to socket\n");
return 0;
}
ret = listen(sock,1);
if(ret != 0)
{
printf("unable to listen on socket\n");
return 0;
}
ctx = SSL_CTX_new(SSLv23_server_method());
if (ctx == NULL)
{
printf ("Unable to create ssl context: %s\n",
ERR_error_string(ERR_get_error(), NULL));
return 0;
}
SSL_CTX_set_options(ctx,0);
/* setting certificates and keys */
{
/*if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) ||
(!SSL_CTX_set_default_verify_paths(ctx)))
{
printf("Unable to set default cert paths: %s\n",
ERR_error_string(ERR_get_error(), NULL));
}*/
DH *dh = NULL;
dh = load_dh_param(TEST_CERT);
SSL_CTX_set_tmp_dh(ctx,dh);
DH_free(dh);
RSA *rsa;
rsa=RSA_generate_key(512,RSA_F4,NULL, NULL);
if (!SSL_CTX_set_tmp_rsa(ctx,rsa))
{
printf("Unable to set rsa values: %s\n",
ERR_error_string(ERR_get_error(), NULL));
return 0;
}
RSA_free(rsa);
if (SSL_CTX_use_certificate_file(ctx,TEST_CERT,
SSL_FILETYPE_PEM) <= 0)
{
printf("Unable to set certificate file: %s\n",
ERR_error_string(ERR_get_error(), NULL));
return(0);
}
if (SSL_CTX_use_PrivateKey_file(ctx,TEST_CERT,
SSL_FILETYPE_PEM) <= 0)
{
printf("Unable to set PrivateKey file: %s\n",
ERR_error_string(ERR_get_error(), NULL));
return(0);
}
}
for(;;)
{
total_bytes = 0;
cli_len = sizeof(cl_addr);
connfd = accept(sock, (struct sockaddr*)&cl_addr, &cli_len);
if(connfd <=0 )
continue;
bio = BIO_new_socket(connfd, BIO_CLOSE);
ssl = SSL_new(ctx);
if (ssl == NULL)
{
printf ("Unable to create ssl: %s\n",
ERR_error_string(ERR_get_error(), NULL));
return 0;
}
if ((ret = BIO_socket_ioctl(connfd,FIONBIO,&Switch)) < 0)
{
printf ("Unable to set non-blocking option on BIO\n");
return 0;
}
SSL_set_bio(ssl, bio, bio);
SSL_set_accept_state( ssl );
while ( (ret = SSL_accept(ssl)) <=0 )
{
/* printf("Error accepting ssl connection: %s\n",
ERR_error_string(ERR_get_error(), NULL));*/
}
printf("Accepted SSL Connection\n");
ret = BIO_set_ssl_renegotiate_timeout(bio, 5);
// ret = BIO_set_ssl_renegotiate_bytes(bio, 1024);
printf("setting renegotiation timeout to 5, ret = %d\n", ret);
for (; ;)
{
err = SSL_read(ssl, buf, sizeof(buf));
switch(SSL_get_error(ssl,err))
{
case SSL_ERROR_NONE:
total_bytes += err;
printf("Read: %s\n",buf);
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
break;
default:
goto shutdown;
}
}
shutdown:
if(SSL_get_shutdown(ssl) && SSL_RECEIVED_SHUTDOWN)
SSL_shutdown(ssl);
else
SSL_clear(ssl);
close(connfd);
// BIO_free(bio);
printf("total bytes read = %d\n", total_bytes);
printf("Closing connection\n");
SSL_free(ssl);
}
return 0;
}