DNS Projects HTTP Projects OSS Projects Testing DNS HTTP Servers Main Page



















Posted: March 30, 2009 by Datazygte, Inc - contribution by ron scheckelhoff -- rscheckelhoff- at-fourcalorieserver -dot-com

I've always been wary of canned security applications. Black box security may be no security at all. Now there are a number of toolkits available to provide an an opportunity to more closely monitor and modify security related infrastructure.


From a programmer's standpoint, these toolkits are not so much about the encryption algorithms themselves, but instead deals with the handling of the "glue code" that must surround the algorithms in order to make them do useful things. This "glue code" accomplishes a lot of legwork, doing things that line up the private keys and the certificates, negotiate the selection of ciphers, and numerous other details.

This article is intended not so much as a complete application description, but is instead given with the intention of shining some light on the general process by which a toolkit API may be utilized to accomplish security related tasks.

We use applications every day that contain embedded security measures (or lack thereof), and we are often unaware of the consequences of decisions made within the software, and by the software, that may ultimately lower or eliminate security benefits.




By relying on software that makes all of the decisions for us, we are sometimes led down the primrose path. For instance, with an SSL connection being negotiated between a client and a server, wherein each allows for a selection of security attributes and ciphers ranging from poor to good, the ultimate settlement may be upon a pick that effectively downgrades the security measures to the least effective one in order to make the connection. In some cases, this "downgrading" is not advertised in any way to the user.

By using the toolkit API to build our own security glue software, we can force the decisions to be what we want, and not some lowly common denominator.


Note that this author is himself just at this moment investigating the capabilities of the toolkit API, and so is learning by writing about it, analyzing, quantifying, and abstracting it such that the reader may learn as he learns.

I note that the online documentation about the use of these kinds of APIs at a higher level is somewhat scarce, and the online docs are relatively spartan in terms of the descriptions of what happens when, and for what reason. The descriptions of the individual API methods are generally quite excellent, in my opinion.

The code (below) shows my initial stab at a high level abstraction of the major API method players - those that always become involved in a secure transaction implemented by the toolkit. Note the code is very preliminary, includes some pseudo-code, and should not be used in any real application. It is part of the learning experience. It is "step one" of our experiment.




/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
        # Copyright (c) 2009, Datazygte, Inc
	# Contributing author(s): Ron Scheckelhoff
	#
	# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
        # conditions ar# met:
	#    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
	#    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
	#      in the documentation and/or other materials provided with the distribution.
	#    * Neither Datazygte, Inc, nor the names of its contributors may be used to endorse or promote products derived from this software
	#      without specific prior written permission.
	#    * Distribution must include this entire web page, intact: http://www.fourcalorieservers.com/servers/fourcalssl.html
	#
	# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
	# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL  THE
	# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        # (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
        # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <dzssl.h>


//
// setupSSLContext - return is NULL unless context successfully created
//
SSL_CTX* setupSSLContext()
{

        SSL_METHOD* sslmeth = NULL;
        SSL_CTX* sslctx = NULL;

        int intReturn = SSL_library_init();

        if (intReturn == 1)
        {
                sslmeth = SSLv3_method();

                if (sslmeth != NULL)
                {
                        sslctx  = SSL_CTX_new(sslmeth);
                }

        }

        return (sslctx);

}



//
// Process Connection
//
int ProcessConnection(SSL* ssl, int socNew))
{

        int intCode = 0;

        // Configure SSL Connection
        int intResult = ConfigureSSLConnection(ssl);  // pseudo

        if (intResult == SUCCESS)
        {
		 // Connect SSL
        	 intResult = SSL_connect(ssl);

	         if (intResult > 0)
       		 {
		      // Use Select, SSL_write, and SSL_read to transfer encrypted data
		      // ...
          	 }
	         else
        	 {
                	intResult = SSL_get_error(ssl, intResult);

	                switch (intResult)
        	        {
				// No, it's not silly ... stepping through this in debugger is informative
                	        case SSL_ERROR_ZERO_RETURN:
                        	    intCode = 1;
	                            break;
        	                case SSL_ERROR_WANT_READ:
                	            intCode = 2;
                        	        break;
	                        case SSL_ERROR_WANT_WRITE:
        	                    intCode = 3;
                	            break;
				default:
				    intCode = 4;

	                }
			intResult = intCode;
		}
        }

        return (intResult)

}



//
// main function is obviously designed to run one and only  one connection,
// which keeps it sweet and simple.  
//
int main()
{
        int socNew = 0;
        int intResult = FAILURE;
	int intShutdown = 0;
        struct sockaddr_in addr;

        BIO* bioNew = NULL;
        SSL* ssl = NULL;
        SSL_CTX* sslctx1 = NULL;

        sslctx1 = setupSSLContext();

        if (sslctx1 != NULL)
        {

                memset(&addr,0,sizeof(addr));

                addr.sin_family = AF_INET;
                addr.sin_port = htons(443);
                addr.sin_addr.s_addr = inet_addr("127.0.0.1");

                socNew = socket(AF_INET, SOCK_STREAM, 0);

                if (socNew > 0)
                {
                        intResult = connect(socNew, (struct sockaddr*) &addr, sizeof(addr));

                        if (intResult >= 0)
                        {
                                ssl = SSL_new(sslctx1);

                                if (ssl != NULL)
                                {
                                        bioNew = BIO_new_socket(socNew, BIO_NOCLOSE);

                                        if (bioNew != NULL)
                                        {
                                                SSL_set_bio(ssl, bioNew, bioNew);

                                                intResult = ProcessConnection(ssl, socNew);
                                                intShutdown = SSL_shutdown(ssl);
                                        }
					else
					    intResult = FAILURE_BIO;

					SSL_free(ssl);  // also frees bioNew;

                                }
				else
				    intResult = FAILURE_SSL;
                        }
                        close(socNew);
                }
		else
		     intResult = FAILURE_SOCK;
               
                SSL_CTX_free(sslctx1);  
        }
	else
	    intResult = FAILURE_CONTEXT;


        // Since this is part of our "experiment", terse error ok

	if (intResult != SUCCESS)
		printf("Problem! Error code: %d \n", intResult);

	printf("Shutdown status: %d \n", intShutdown);   
}

         
 


What Have we Written?

SSL
Continued post: 04/02/2009



So, what's going on? The API really is a blend of SSL related functions and a number of wrappers for the Berkley sockets that it works around. This makes the API pleasantly familiar for those with sockets experience.

When referencing the code (above), one will note that the standard Berkley socket was set up in advance of anything else, other than the context. In fact, the actual TCP/IP connection was made in advance of any manipulations by the SSL API. Subsequent manipulations by the SSL wrappers thusly allow the encrypted traffic to ride on that initial socket connection.

Later in the code, we will use wrappers for the regular socket equivalents, to read and write encrypted data over the basic TCP/IP connection. Thus, there must be some way to tell the toolkit about our regular connection, so that the toolkit libraries can use that connection to send (and receive) our communications (after it's wrappers encrypt and/or decrypt those comunications.

That "method", or "way" to tell the toolkit libraries about our regular connection is via the BIO_new_socket() and SSL_set_bio() API calls.

In the snippet (below), it is readily apparent that the library API call BIO_new_socket receives the socket descriptor for our regular socket.

bioNew = BIO_new_socket(socNew, BIO_NOCLOSE);

Just as apparent is the association to the ssl object:

SSL_set_bio(ssl, bioNew, bioNew);

To be continued ...







Note that the toolkit used in this review is an open source project which is under a BSD-like license type, is not affiliated with this site or it's owners, and does not endorse this site in any way. All things related to this third party toolkit may be found at:
http://www.openssl.org





Contact for this site (fourcalorieservers.com) : Ron Scheckelhoff -- Email suggestions to: rscheckelhoff@fourcalorieservers.com ( )




Valid HTML 4.01 Transitional