SSL/TLS
Programming
#define CA_LIST "ca_cert.pem"
#define
ClientKEYFILE
"client.pem"
#define ClientPASSWORD "cairo"
#define ServerHOST "antares.cs.odu.edu"
#define PORT
10203
#define RANDOM "random.pem"
int main (int argc, char **argv)
{
SSL_CTX *ctx;
SSL *ssl;
BIO *sbio;
int sock;/* Build our SSL context*/
ctx = initialize_ctx (ClientKEYFILE, ClientPASSWORD);ssl = SSL_new (ctx);
/* Connect the TCP socket*/
sock = tcp_connect ();sbio = BIO_new_socket (sock, BIO_NOCLOSE);
SSL_set_bio (ssl, sbio, sbio);
/* Connect the SSL socket */
SSL_connect (ssl);
check_cert_chain (ssl, ServerHOST);/* read and write */
read_write (ssl, sock);
}
struct hostent *hp;
struct sockaddr_in addr;
int sock;hp = gethostbyname (ServerHOST);
memset (&addr,0,sizeof(addr));
addr.sin_addr = *(struct in_addr*)hp->h_addr_list[0];
addr.sin_family = AF_INET;
addr.sin_port = htons(ServerPORT);sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
connect (sock, (struct sockaddr *) &addr, sizeof(addr);
return sock;
}
/*
Read from the keyboard and write
to the server
Read from the server and write
to the keyboard
*/
void read_write (ssl, sock)
SSL *ssl;
{
int r, c2sl=0;
int shutdown_wait=0;
char c2s[BUFSIZZ], s2c[BUFSIZZ];while (1) {
/* Check for input on the console*/
c2sl = read (0, c2s, BUFSIZZ);
if (c2sl == 0 ) goto end;/* If we've got data to write then try to write it*/
SSL_write (ssl, c2s, c2sl);/* Now check if there's data to read */
do {
r = SSL_read (ssl, s2c, BUFSIZZ);switch (SSL_get_error (ssl, r) ) {
case SSL_ERROR_NONE:
fwrite (s2c, 1, r, stdout);
break;
case SSL_ERROR_ZERO_RETURN:
/* End of data */
goto end;
break;
default:
berr_exit("SSL read problem");
}} while ( SSL_pending (ssl) );
}/* end of while (1) */
end:
SSL_shutdown (ssl);
SSL_free (ssl);
close (sock);
return;
}
#define CA_LIST "ca_cert.pem"
#define
ServerKEYFILE
"server.pem"
#define ServerPASSWORD "cairo"
#define ClientHOST
"vega.cs.odu.edu"
#define PORT
10203
#define DHFILE "dh1024.pem"
#define RANDOM "random.pem"
int main (argc,argv)
int argc;
char **argv;
{
int sock, s;
BIO *sbio;
SSL_CTX *ctx;
SSL *ssl;
int r;
pid_t pid;
/* Build our SSL context*/
ctx = initialize_ctx
(ServerKEYFILE, ServerPASSWORD);
load_dh_params (ctx,
DHFILE);
generate_eph_rsa_key(ctx);
while (1) {
ps = accept (sock, 0, 0);
sbio =
BIO_new_socket (ps,
BIO_NOCLOSE);
ssl =
SSL_new(ctx);
SSL_set_bio (ssl, sbio, sbio);
SSL_accept (ssl);
check_cert_chain
(ssl,
ClientHOST);
if (fork() == 0)
echo
(ssl);
}
}
int sock;
struct sockaddr_in sin;
char buf[BUFSIZZ];
int r,len,offset;
case SSL_ERROR_ZERO_RETURN:
goto end;
default:
berr_exit ("SSL read
problem");
}
/* Now keep writing until we've written everything*/
offset=0;
default:
berr_exit("SSL write problem");
}
} /*
while (1) */
end:
SSL_shutdown(ssl);
SSL_free(ssl)
SSL_CTX *initialize_ctx (keyfile, password)
char *keyfile;
char *password;
{
SSL_METHOD *meth;
SSL_CTX *ctx;/* Global system initialization*/
SSL_library_init ();
SSL_load_error_strings ();/* An error write context */
bio_err = BIO_new_fp (stderr, BIO_NOCLOSE)
/* Create our context*/
meth = SSLv3_method ();
ctx = SSL_CTX_new (meth);/* Load our keys and certificates*/
SSL_CTX_use_certificate_file ( ctx, keyfile, SSL_FILETYPE_PEM);
int verify_callback (int ok, X509_STORE_CTX
*store)
{ char data[256];
/* Check
that the common name matches the host name*/
void check_cert_chain (ssl, host)
SSL *ssl;
char *host;
{
X509 *peer;
char peer_CN[256];if ( SSL_get_verify_result (ssl) != X509_V_OK )
berr_exit ("Certificate doesn't verify");
void load_dh_params (ctx, file)
SSL_CTX *ctx;
char *file;
{
void generate_eph_rsa_key (ctx)
SSL_CTX *ctx;
{ RSA *rsa;rsa=RSA_generate_key(512,RSA_F4,NULL,NULL);
SSL_CTX_set_tmp_rsa(ctx,rsa);
RSA_free(rsa);
}
Generating the
required .pem files:
#define
DHFILE
"dh1024.pem"
#define
RANDOM
"random.pem"
#define
CA_LIST
"ca_cert.pem"
#define ServerKEYFILE
"server.pem"
#define ClientKEYFILE "client.pem"
·
To create
the dh512.pem or dh1024.pem:
·
To create
the server.pem & client.pem:
First generate a cert request, make sure to specify: "localhost" or
the actual host name,
&
host vega: use
"vega.cs.odu.edu" as
the CN name in vega_cert.pem
&
host antares: use
"antares.cs.odu.edu" as the CN name in antares_cert.pem
Sign the hosts certificates from the CA
and then do the following:
% cat vega_privatekey.pem vega_cert.pem ca_cert.pem > vega.pem
% cat antares_privatekey.pem antares_cert.pem ca_cert.pem > antares.pem
If you run the client on vega: % cp vega.pem client.pem
If you run the server on antares: % cp antares.pem server.pem