SSLeay

SSLeay is a freely available implementation of the Netscape 3.0 SSL protocol. It is the cryptographic engine that drives the Apache-SSL server.

The SSLeay system installs in the directory /usr/local/ssl. It contains the following subdirectories:

CA

The certification authority directory, used if you wish to run your own CA.

bin

Contains the executable programs, which make up the SSLeay package.

certs

Holds the actual X.509 server public key certificates, used by SSL servers on your system.

include

The C language #include files needed for compiling other programs that use the SSLeay library packages.

lib

The actual C language libraries, which are linked with other programs that use SSLeay.

private

Holds the private key certificates used by the SSL servers on your system.

SSLeay can be freely used outside the United States. Within the United States, its use is governed by the patents on public key cryptography.

SSLeay Examples

Michael Grant has created several small programs that demonstrate how to use SSLeay to create a secure SSL server and client. The programs run under Solaris 2.5. They are included here with his permission.

SSLeay Client

Here is the program:

/*
  client.c

  To compile:
  
  cc -g -c -I/usr/local/SSLeay-0.6.4/include client.c
  cc -g client.o -L/usr/local/SSLeay-0.6.4/lib -lssl -lcrypto -lsocket -lnsl -o client

  This program implements a simple client which connects to the server by a TCP/IP connection, and then starts SSL on the connection.  It sends some data, then waits for some data (which it prints) and then disconnects.

  There are two arguments:
  	hostname to connect to
	port number (which the server will tell you when it starts).

  You will need to supply a certificate for a CA.  This is used in CAfile below.

  */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "buffer.h"
#include "crypto.h"
#include "../e_os.h"
#include "x509.h"
#include "ssl.h"
#include "err.h"

int MS_CALLBACK verify_callback(int ok, X509 *xs, X509 *xi, int depth, int error, char *arg);

#define CAfile "demoCA/cacert.pem"
#define CApath NULL

main(int argc, char **argv)
{
	int sock;		/* The TCP/IP socket */
	struct sockaddr_in server;
	struct hostent *hp;
	char buf[1024];
	
	SSL_CTX *c_ctx=NULL;	/* The Client's context */
	SSL *c_ssl=NULL;	/* The Client's SSL connection */
	int rval;
	
	if (argc<2)
	{
		printf("usage: client hostname port#
");
		exit(1);
	}

	SSL_load_error_strings();

	/* Create a new context.  This holds information pertinent to the
	 * client's SSL side of the connection.
	 */
	c_ctx=SSL_CTX_new();

	if (c_ctx == NULL)
	{
		printf("SSL_CTX_new() failed
");
	}

	/* Tell SSL where the Certificate Authority files are located */
	if ((!SSL_load_verify_locations(c_ctx,CAfile,CApath)) ||
	    (!SSL_set_default_verify_paths(c_ctx)))
	{
		fprintf(stderr,"SSL_load_verify_locations
");
		ERR_print_errors_fp(stderr);
		exit(1);
	}

	/* Tell SSL to request the server's certificate when we connect. */
	SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER, verify_callback);

	/* Now we can create a basic TCP/IP connection */
	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		perror("socket");
		exit(1);
	}

	server.sin_family = AF_INET;

	if ((hp = gethostbyname(argv[1])) == NULL)
	{
		perror(argv[1]);
		exit(1);
	}

	memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);

	server.sin_port = htons(atoi(argv[2]));

	if (connect(sock, (struct sockaddr *)&server, sizeof(server)) 
			== -1)
	{
		perror("connect");
		exit(1);
	}

	/* We now have a basic TCP/IP connection up.  Now we start SSL
	 * on this connection.
	 */

	/* Creates a new SSL connection.  This holds information pertinent
	 * to this connection.
	 */
	if ((c_ssl=SSL_new(c_ctx)) == NULL)
	{
		printf("SSL_new() failed
");
		exit(1);
	}

	/* Tell SSL that this connection is to use the socket we just
	 * created above. 
	 */
	SSL_set_fd(c_ssl, sock);

	/* Finally, start the SSL connection */
	if (SSL_connect(c_ssl) < 1)
	{
		fprintf(stderr, "SSL_connect:");
		ERR_print_errors_fp(stderr);
		exit(1);
	}

	/* Lets find out who the peer *really* is.  We look though the
	 * server's certificate to see who he says he is.
	 */
	{
		X509 *peer_x509;
		char *s = NULL;

		peer_x509 = SSL_get_peer_certificate(c_ssl);

		if (peer_x509==0)
		{
			fprintf(stderr, "SSL_get_peer_cert:");
			ERR_print_errors_fp(stderr);
			exit(1);
		}

		s=(char *)X509_NAME_oneline(X509_get_subject_name(peer_x509));

		if (s==NULL)
		{
			fprintf(stderr, "X509_NAME_oneline:");
			ERR_print_errors_fp(stderr);
			exit(1);
		}

		printf("Server's subject name is '%s'
', s);stderr
	}

	/* Send some data to the server */
	printf("sending data
");
	SSL_write(c_ssl,"hello from client",18);

	memset(buf, 0, sizeof(buf));
	
	printf("waiting for data
");

	/* Now we receive some data from the server and print it out */
	rval=SSL_read(c_ssl,buf,1024);
	printf("-->%s
", buf);

	/* Close the SSL connection */
	SSL_free(c_ssl);

	/* Close the TCP/IP socket */
	close(sock);

	exit(0);
}

	
int MS_CALLBACK verify_callback(int ok, X509 *xs, X509 *xi, int depth, int error, char *arg)
{
	char *s;
	
	s=(char *)X509_NAME_oneline(X509_get_subject_name(xs));
	if (s != NULL)
	{
		if (ok)
			fprintf(stderr,"depth=%d %s
",depth,s);
		else
		{
			fprintf(stderr,"depth=%d error=%d ok=%d %s
",
					depth,error,ok,s);
			ERR_print_errors_fp(stderr);
		}
		Free(s);
	}
	
	return(ok);
}

SSLeay Server

Here’s what the output from server looks like:

sun% ./server
server ready waiting on port 43205
starting connection using RC4-MD5 cipher
-->hello from client
ending connection

And here is the source code:

/*
  server.c

  To compile:

  cc -c -I/usr/local/SSLeay-0.6.4/include server.c
  cc server.o -L/usr/local/SSLeay-0.6.4/lib -lssl -lcrypto 
  -lsocket -lnsl -o server

  This program implements a simple server which accepts TCP/IP connections, 
starts SSL on the connection, waits for some data (which it prints), sends 
some data back to the client, then waits for more data.  When the connection 
is closed by the client, it continues to wait for a new connection.

  There are no arguments.  When the server starts, it will tell you what 
port it is waiting on.  This information is used to start the client.

  You will need to supply a certificate for a CA, the server's certificate, 
and the server's private key.  These are used in CAfile, SERVER_CERT, and 
SERVER_KEY respectively below.

  */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "buffer.h"
#include "crypto.h"
#include "../e_os.h"
#include "x509.h"
#include "ssl.h"
#include "err.h"

#define CAfile "demoCA/cacert.pem"
#define CApath NULL
#define SERVER_CERT "./server_cert.pem"
#define SERVER_KEY "./server_key.pem"

main()
{
	int sock;		/* The TCP/IP socket */
	int length;
	struct sockaddr_in server;
	int fd;
	char buf[1024];
	int rval;
	SSL_CTX *s_ctx=NULL;	/* The Server's context */
	SSL *s_ssl=NULL;	/* The Server's SSL connection */
	
	SSL_load_error_strings();

	/* Create a new context.  This holds information pertinent to the
	 * client's SSL side of the connection.
	 */
	s_ctx=SSL_CTX_new();

	if (s_ctx == NULL)
	{
		printf("SSL_CTX_new() failed
");
	}

	/* Tell SSL where the server's public certificate is */
	if (SSL_CTX_use_certificate_file(s_ctx,SERVER_CERT,
			SSL_FILETYPE_PEM) == 0)
	{
		fprintf(stderr, "SSL_CTX_use_certificate_file:");
		ERR_print_errors_fp(stderr);
		exit(1);
	}

	/* Tell SSL where the server's private key is */
	if (SSL_CTX_use_RSAPrivateKey_file(s_ctx,SERVER_KEY,
			SSL_FILETYPE_PEM) == 0)
	{
		fprintf(stderr, "SSL_CTX_use_RSAPrivateKey_file:");
		ERR_print_errors_fp(stderr);
		exit(1);
	}

	/* Tell SSL where the Certificate Authority files are located */
	if ((!SSL_load_verify_locations(s_ctx,CAfile,CApath)) ||
	    (!SSL_set_default_verify_paths(s_ctx)))
	{
		fprintf(stderr,"SSL_load_verify_locations
");
		ERR_print_errors_fp(stderr);
		exit(1);
	}

	/* Now we create a socket and wait for a basic TCP/IP connection */
	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		perror("socket");
		exit(1);
	}

	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY;
	server.sin_port = 0;
	
	if (bind(sock, (struct sockaddr *)&server, sizeof(server)) == -1)
	{
		perror("bind");
		exit(1);
	}

	length = sizeof(server);

	if (getsockname(sock, (struct sockaddr *)&server, &length) == -1)
	{
		perror("getsockname");
		exit(1);
	}
	
	printf("server ready waiting on port %d
", ntohs(server.sin_port));
	
	/* We now are ready to wait for a basic TCP/IP connection up.
	 */

	listen(sock, 5);

	while (1)	/* Do this for each incoming TCP/IP connection */
	{
		/* Accept the new TCP/IP connection */
		if ((fd = accept(sock, NULL, NULL)) == -1)
		{
			perror("accept");
			exit(1);
		}

		/* Creates a new SSL connection.  This holds information
		 * pertinent to this
		 * connection.
		 */
		if ((s_ssl=SSL_new(s_ctx)) == NULL)
		{
			printf("SSL_new() failed
");
			exit(1);
		}

		/* Tell SSL that this connection is to use the socket we 
		 * just created above. 
		 */
		SSL_set_fd(s_ssl, fd);

		/* Finally, start the SSL connection */
		if (SSL_accept(s_ssl)<1)
		{
			fprintf(stderr, "SSL_accept failed
");
			ERR_print_errors_fp(stderr);

			SSL_free(s_ssl);
			close (fd);
			continue;
		}
		
		printf("starting connection using %s cipher
", 
				SSL_get_cipher(s_ssl));
		
		do	/* Do this until the client disconnects: */
		{
			/* Receive data from the client and print it out */
			rval = SSL_read(s_ssl,buf,1024);
			if (rval < 0)
			{
				fprintf(stderr, "SSL_read: %s
", 
							ERR_reason_error_string
(ERR_get_error()));
			}

			if (rval==0)
			{
				printf("ending connection
");
			}				
			else
			{
				/* If everything is OK, print out data received */
				printf("-->%s
", buf);

				/* Now send some data back to the client */
				SSL_write(s_ssl,"hello from server",18);
			}

		} while (rval>0);
		
		/* Close the SSL connection */
		SSL_free(s_ssl);

		/* Close the TCP/IP socket */
		close (fd);

	}
}

SSLeay CA

Michael Grant has also put together a very simplified CA to create and sign the certificates needed for the demo client and server programs. The ca.conf file is included below.

Here is the program’s operation. First we create a configuration file and a directory to hold the certificates:

                     % mkdir demoCA
                     % cp ca.conf demoCA
                     % cd demoCA
                     % mkdir new_certs
                     % touch index.txt
                     % echo 01 > serial

Now we create the private key and x509 certificate for the CA. The -x509 option makes this a self-signed certificate (issuer and subject are the same).

                     
% ssleay req -config ca.conf -x509 -new -keyout cakey.pem -out
cacert.pem Generating a 1024 bit private key
...............................+++++
....................+++++
unable to write 'random state'
writing new private key to 'cakey.pem'
-----
You are about to be asked to enter information that will be incorperated into 
your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:US
Organization Name (eg, company) [MegaWidget]:MegaWidget
Organizational Unit Name (eg, section) [Eng]:Eng
Common Name (eg, YOUR name) [Michael Grant]:CA 
% ls
ca.conf         cakey.pem       new_certs/
cacert.pem      index.txt       serial

Now we generate a request for a certificate and a private key for the server. This request could be emailed to the CA.

                     % ssleay req -config ca.conf -new -keyout server_key.pem -out
server_req.pem Generating a 1024 bit private key
.+++++
...........................+++++
unable to write 'random state'
writing new private key to 'server_key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:US
Organization Name (eg, company) [MegaWidget]:MegaWidget
Organizational Unit Name (eg, section) [Eng]:Eng
Common Name (eg, YOUR name) [Michael Grant]:Michael Grant Server 

When the certificate request is received, the CA signs it:

% ssleay ca -config ca.conf -keyfile cakey.pem -cert cacert.pem -in
server_req.pem -out server_cert.pem Check that the request matches the
signature Signature ok
The Subjects Distinguished Name is as follows
countryName           :PRINTABLE:'US'
organizationName      :PRINTABLE:'MegaWidget'
organizationalUnitName:PRINTABLE:'Eng'
commonName            :PRINTABLE:'Michael Grant Server'
Certificate is to be certified until Jan 24 09:02:06 1998 GMT (365 days)
Sign the certificate? [y/n]:y 
1 out of 1 certificate requests certified, commit? [y/n]y 
Write out database with 1 new entries
Data Base Updated
[unix% 559] ls
ca.conf         index.txt       serial          server_key.pem
cacert.pem      index.txt.old   serial.old      server_req.pem
cakey.pem       new_certs/      server_cert.pem

Now let’s look at the contents of the CA’s self certifying certificate. Notice that the Issuer (the signer) and the subject (the owner of the key) are the same:

% ssleay x509 -text -noout -in cacert.pem
Certificate:
    Data:
        Version: 0 (0x0)
        Serial Number: 0 (0x0)
        Signature Algorithm: md5withRSAEncryption
        Issuer: C=US, O=MegaWidget, OU=Eng, CN=CA
        Validity
            Not Before: Jan 24 08:59:30 1997 GMT
            Not After : Feb 23 08:59:30 1997 GMT
        Subject: C=US, O=MegaWidget, OU=Eng, CN=CA
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Modulus:
                    00:d5:c1:40:2d:67:95:c4:99:97:29:39:49:f1:72:
                    bd:6f:9b:d8:7d:ae:a2:93:ce:f1:d4:e7:ab:df:d4:
                    50:eb:c6:3a:d0:cf:ce:ff:f0:40:47:b5:8f:58:83:
                    0c:9b:4a:02:66:1d:f4:dd:67:a0:a1:17:01:ad:d3:
                    da:f3:3d:08:6b:ad:8d:a7:63:42:f5:5d:3b:b9:99:
                    2a:9e:88:b6:70:cd:ca:c1:79:5e:93:a0:05:da:24:
                    15:1a:57:91:b3:5e:03:03:64:b2:3d:98:5b:ba:43:
                    0e:62:62:29:30:bb:67:4f:99:44:4e:f7:15:3e:70:
                    c1:97:c0:b2:93:ed:cd:a9:dd
                Exponent: 65537 (0x10001)
    Signature Algorithm: md5withRSAEncryption
        4b:17:78:78:82:5e:7a:aa:00:33:98:6b:ae:4f:e0:36:81:b5:
        88:30:a9:6b:60:75:df:3d:23:74:27:cf:87:35:be:2d:b5:50:
        64:d9:1b:11:07:e8:19:ff:04:54:11:ce:cd:aa:b4:32:25:97:
        21:bb:ac:fa:86:14:2b:e1:85:69:17:4e:64:93:f6:dc:3e:61:
        46:5d:1c:4b:ac:2c:c4:1e:07:fe:0c:52:e7:ff:a5:a6:cd:9a:
        a3:52:fe:d8:2a:68:a7:ee:bd:2d:8a:20:91:1d:22:ae:a6:4d:
        c0:3e:74:04:c9:73:d2:60:56:85:16:c4:af:85:c4:40:66:b9:
        b5:8a

This shows the server’s CA certified certificate. Notice that the issuer is the CA (the signer) and the subject (the owner) is the server:

% ssleay x509 -text -noout -in server_cert.pem
Certificate:
    Data:
        Version: 0 (0x0)
        Serial Number: 1 (0x1)
        Signature Algorithm: md5withRSAEncryption
        Issuer: C=US, O=MegaWidget, OU=Eng, CN=CA
        Validity
            Not Before: Jan 24 09:02:06 1997 GMT
            Not After : Jan 24 09:02:06 1998 GMT
        Subject: C=US, O=MegaWidget, OU=Eng, CN=Michael Grant Server
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Modulus:
                    00:e0:78:86:09:00:93:3d:a0:c8:c9:71:ef:b4:2e:
                    3a:ce:84:47:ed:e0:c2:8d:aa:ef:53:f8:35:5e:69:
                    de:5c:b7:88:d1:e1:01:9b:6e:0e:ba:7c:f3:e7:3d:
                    76:6d:fd:1c:75:28:bd:13:a0:fd:a8:7a:bd:82:36:
                    dd:fb:8a:9f:80:2f:0f:4f:b2:94:06:82:52:44:7b:
                    1f:c4:d7:a2:9d:61:e2:59:b8:e0:13:73:af:7b:02:
                    71:6c:23:23:47:5f:f9:46:3c:d0:49:ee:c7:42:ac:
                    f0:7a:9b:d1:8f:19:d3:c6:f0:89:71:6c:3c:a0:c7:
                    77:a4:a9:b3:c3:6b:7c:f7:7b
                Exponent: 65537 (0x10001)
    Signature Algorithm: md5withRSAEncryption
        cc:ec:71:9d:1a:c3:eb:b1:c6:ba:1b:79:f4:46:e8:b7:cd:5b:
        bf:bd:47:da:6a:1b:31:59:e1:a5:f6:9d:a3:c0:10:93:f0:b2:
        5b:cc:2d:f7:b3:dd:e0:43:df:5a:2a:c8:97:b6:06:b7:ea:af:
        7d:1f:a2:f7:13:57:96:ed:70:1a:85:03:7e:b0:3b:ee:f5:d5:
        fd:f8:fb:ab:6f:82:86:6a:b7:c8:f1:84:82:00:37:cc:1a:22:
        29:42:7a:f0:6c:34:05:24:e5:ec:95:98:ba:4d:c5:1b:ba:55:
        16:d5:b2:1c:b6:d0:19:28:ed:97:8b:26:52:13:c9:bb:66:3f:
        ff:1c

Now we will move the certificate into the parent directory, which contains the client and server programs:

% mv server_*.pem ..
% cd ..

Running the server

The server program must be run before the client is started. It prints the number of the port that it is running on:

% ./server
server ready waiting on port 43436
starting connection using RC4-MD5 cipher
-->hello from client
ending connection

Running the client

The client program should be run in another window. Its argument is the hostname and port where the server is running:

% ./client localhost 43436
depth=0 /C=US/O=MegaWidget/OU=Eng/CN=Michael Grant Server
depth=1 /C=US/O=MegaWidget/OU=Eng/CN=CA
Server's subject name is '/C=US/O=MegaWidget/OU=Eng/CN=Michael Grant Server'
sending data
waiting for data
-->hello from server

There are two certificates, one for a CA (that’s the depth=1) and one for the server (that’s depth=0).

SSLeay ca.conf file

This is the configuration file needed for the example:

#
# SSLeay example configuration file.
# This is mostly being used for generation of certificate requests.
#

RANDFILE		= $ENV::HOME/.sslrand

####################################################################
[ ca ]
default_ca	= CA_default		# The default ca section

####################################################################
[ CA_default ]

dir		= .			# Where everything is kept
certs		= $dir/certs		# Where the issued certs are kept
crl_dir		= $dir/crl		# Where the issued crl are kept
database	= $dir/index.txt	# database index file.
new_certs_dir	= $dir/new_certs	# default place for new certs.

certificate	= $dir/cacert.pem 	# The CA certificate
serial		= $dir/serial 		# The current serial number
crl		= $dir/crl.pem 		# The current CRL
private_key	= $dir/ca_key.pem	# The private key
RANDFILE	= $dir/.rand	 	# private random number file

default_days	= 365			# how long to certify for
default_crl_days= 30			# how long before next CRL
default_md	= md5			# which md to use.

# A few difference way of specifying how similar the request should
# look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy		= policy_match

# For the CA policy
[ policy_match ]
countryName		=		match
stateOrProvinceName	= 		optional
organizationName	= 		match
organizationalUnitName	=               optional
commonName		= 		supplied
emailAddress		= 		optional

# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName		= 		optional
stateOrProvinceName	= 		optional
localityName		= 		optional
organizationName	= 		optional
organizationalUnitName	=               optional
organizationalUnitName	=               optional
commonName		= 		supplied
emailAddress		= 		optional

####################################################################
[ req ]
default_bits		=		1024
#default_keyfile 	= 		newkey.pem
distinguished_name	= 		req_distinguished_name
encrypt_rsa_key		= 		no

[ req_distinguished_name ]
countryName			= 	Country Name (2 letter code)
countryName_default		= 	US
countryName_value		= 	US

organizationName		= 	Organization Name (eg, company)
organizationName_default	= MegaWidget
organizationName_value		= MegaWidget

organizationalUnitName		= Organizational Unit Name (eg, section)
organizationalUnitName_default	= Eng
organizationalUnitName_value	= Eng

commonName			= 	Common Name (eg, YOUR name)
commonName_default		= 	Michael Grant
#commonName_value		= 	Michael Grant
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.111.1