Within OpenHPI, the usage of the OpenSSL library is increasing,
especially within plug-ins.  (I am developing another plug-in that uses
SSL, beside those already in the project.)

OpenSSL requires some library initialization before use.  Additionally,
for a multi-threaded environment, the library requires that the user
provide some thread-safe setup, implemented as a set of calls the user
must make before using the library.

It's difficult for a plug-in to do this.  By the time the plug-in is
initialized, other plug-ins may be called.  Each plug-in doesn't know if
it's the first, and therefore whether to do the initialization.  It's
possible that the SSL library initialization call can be performed
multiple times (would have to check the SSL source code to be sure), but
it's unlikely that the thread setup can be done more than once, looking
at the implementation of those calls.

Beyond initialization, there may be opportunity to reuse SSL-based code
between plug-ins.  My experience in the last three months, trying to
come up to speed on using SSL for reliable communication to managed
hardware, is that it takes a fair amount of study and the code is
tricky.  To the extent that others can use the code, it would be nice to
reuse it.

Attached is a file of OpenSSL-based code that I propose we add to the
OpenHPI infrastructure.  All of the calls would be used by a plug-in
that I hope to propose adding next week.

If we don't want to add all this to the infrastructure, some can be kept
in the plug-in.  However, I'd suggest that we at least add the
initialization code, along with it's thread-safe setup of the SSL
library.  This would be all the code up to the oh_ssl_init() function.

We could call this SSL init code from the daemon when it starts, or each
plug-in that wants to use SSL could call it.  The code itself can be
called multiple times as it's currently implemented.

Thanks for considering this.  I'd also appreciate implementation
comments from those with OpenSSL experience.

Bryan Sutula
/*
 * Copyright (C) 2007-2008, Hewlett-Packard Development Company, LLP
 *                     All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are 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 the name of the Hewlett-Packard Corporation, nor the names
 * of its contributors may be used to endorse or promote products
 * derived from this software without specific prior written permission.
 *
 * 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.
 *
 * Author(s)
 *     Shuah Khan <[EMAIL PROTECTED]>
 *     Richard White <[EMAIL PROTECTED]>
 *     Bryan Sutula <[EMAIL PROTECTED]>
 *
 *
 * This file implements SSL connection management functionality
 * such as open, close, send, and receive.  It uses OpenSSL to do
 * most of it's work.
 *
 * The following functions are supported:
 *
 * oh_ssl_init()		- Intializes the OpenSSL library
 * oh_ssl_ctx_init()		- Creates a new SSL_CTX object
 * oh_ssl_ctx_free()		- Free an SSL_CTX object
 * oh_ssl_connect()		- Create and open a new ssl conection
 * oh_ssl_disconnect()		- Close and free an SSL connection
 * oh_ssl_read()		- Read from an SSL connection
 * oh_ssl_write()		- Write to an SSL connection
 */


/* OpenSSL and other header files */
#include <sys/select.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <oh_ssl.h>


/* Data types used by this module */
struct CRYPTO_dynlock_value {
	pthread_mutex_t	mutex;
};


/* Global (static) data for this module */
static int	oh_ssl_init_done = 0;	/* Will be set true when done */
static pthread_mutex_t *mutexes = NULL;	/* Holds array of SSL mutexes */


/* Local (static) functions, used by this module */

/* SSL thread ID function */
static unsigned long id_function(void)
{
	return((unsigned long) pthread_self());
}


/* SSL mutex lock and unlock function */
static void lock_function(int mode, int type, const char * file, int line)
{
	if (mode & CRYPTO_LOCK) {
		pthread_mutex_lock(& (mutexes[type]));
	}
	else {
		pthread_mutex_unlock(& (mutexes[type]));
	}
}


/* Function to create and initialize dynlock mutexes */
static struct CRYPTO_dynlock_value *dyn_create_function(const char *file,
							int line)
{
	struct CRYPTO_dynlock_value *value;

	if ((value = (struct CRYPTO_dynlock_value *)
			malloc(sizeof(struct CRYPTO_dynlock_value)))) {
		pthread_mutex_init(& (value->mutex), NULL);
	}
	else {
		err("out of memory");
	}

	return(value);
}


/* Function to lock and unlock dynlock mutexes */
static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l,
			      const char *file, int line)
{
	if (mode & CRYPTO_LOCK) {
		pthread_mutex_lock(& (l->mutex));
	}
	else {
		pthread_mutex_unlock(& (l->mutex));
	}
}


/* Function to destroy dynlock mutexes */
static void	dyn_destroy_function(struct CRYPTO_dynlock_value *l,
				     const char *file, int line)
{
	pthread_mutex_destroy(& (l->mutex));
	free(l);
}


/* thread_setup: Set up multi-thread protection used by the SSL library
 *
 * Parameters:
 *   (none)
 *
 * Return value:
 *   0 for success, -1 for failure
 */
static int	thread_setup(void)
{
	int		i;

	/* First, create and initialize the necessary mutexes */
	if (! (mutexes = (pthread_mutex_t *)malloc(CRYPTO_num_locks() *
					    sizeof(pthread_mutex_t)))) {
		err("out of memory");
		return(-1);
	}
	for (i = 0; i < CRYPTO_num_locks(); i++) {
		pthread_mutex_init(& (mutexes[i]), NULL);
	}

	/* Register our locking functions with the SSL library */
	CRYPTO_set_id_callback(id_function);
	CRYPTO_set_locking_callback(lock_function);
	CRYPTO_set_dynlock_create_callback(dyn_create_function);
	CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
	CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
	
	return(0);			/* No errors */
}


#if 0
/* thread_cleanup: Clean up multi-thread protection used by the SSL library
 *
 * 	Note that this function is not currently used because there is no
 * 	shutdown code for plugins.  It is left here in case that happens in
 * 	the future.
 *
 * Parameters:
 *   (none)
 *
 * Return value:
 *   0 for success, -1 for failure (though it currently can't fail)
 */
static int	thread_cleanup(void)
{
	int		i;

	/* Nullify the locking functions we registered with the SSL library */
	CRYPTO_set_id_callback(NULL);
	CRYPTO_set_locking_callback(NULL);
	CRYPTO_set_dynlock_create_callback(NULL);
	CRYPTO_set_dynlock_lock_callback(NULL);
	CRYPTO_set_dynlock_destroy_callback(NULL);

	/* Clean up and destroy mutexes */
	for (i = 0; i < CRYPTO_num_locks(); i++) {
		pthread_mutex_destroy(& (mutexes[i]));
	}
	free(mutexes);
	mutexes = NULL;

	return(0);			/* No errors */
}
#endif


/* oh_ssl_init: Intialize the OpenSSL library.  Note that the calls used
 *	in this routine set up global data and are only to be called once
 *	for an SSL-based program.  To enforce this while allowing multiple
 *	callers (plugins) to initialize the library, we use a static global
 *	variable to mark when we've done the initialization.
 *
 * Parameters:
 *   (none)
 *
 * Return value:
 *   0 for success, -1 for failure
 */
int		oh_ssl_init()
{
	if (! oh_ssl_init_done) {	/* Do this only once */
		oh_ssl_init_done = 1;

 		/* Load error strings to provide human-readable error
		 * messages
		 */
		SSL_load_error_strings();
		ERR_load_BIO_strings();

		/* Initialize the SSL library */
 		if (! SSL_library_init()) {
			err("SSL_library_init() failed");
			return(-1);
		}

		/* Actions to seed PRNG */
		RAND_load_file("/dev/urandom", 1024);

		/* Set up multi-thread protection functions */
		if (thread_setup() ) {
			err("SSL multi-thread protection setup call failed");
			return(-1);
		}
	}
	
	return(0);			/* Cannot currently fail */
}


/* oh_ssl_ctx_init: Create a new SSL_CTX object as a framework for TLS/SSL
 *	enabled functions.  In particular:
 * 	- Creates a new CTX object with default option values
 * 	- Sets common compatibility options
 *	- Sets the default locations for trusted CA certificates.
 *	  SSL_CTX_set_default_verify_paths() is used to add system-wide
 *	  default certificate paths to the verify CApath without having to
 *	  specify a default location.  The intent is that the distribution's
 *	  configured location will be used.
 *
 * Parameters:
 *   (none)
 *
 * Return value:
 *   pointer to SSL_CTX or NULL for failure
 */
SSL_CTX		*oh_ssl_ctx_init()
{
	SSL_CTX		*ctx;

	ctx = SSL_CTX_new(SSLv23_client_method());
	if (ctx == NULL) {
		err("SSL_CTX_new() failed");
		return(NULL);
	}

	SSL_CTX_set_options(ctx, SSL_OP_TLS_ROLLBACK_BUG | SSL_OP_ALL);

	if(! SSL_CTX_set_default_verify_paths(ctx)) {
		err("SSL_CTX_set_default_verify_paths() failed");
		return(NULL);
	}

	return(ctx);
}


/* oh_ssl_ctx_free: Free an SSL_CTX object
 *
 * Parameters:
 *   ctx:	pointer to SSL_CTX as returned by oh_ssl_ctx_init()
 *
 * Return value:
 *   0 for success, -1 for failure
 */
int		oh_ssl_ctx_free(SSL_CTX *ctx)
{
	if (ctx == NULL) {
		err("unexpected NULL ctx pointer");
		return(-1);
	}

	SSL_CTX_free(ctx);
	
	return(0);
}


/* oh_ssl_connect: Create and open a new ssl conection to the specified host,
 *	returning a pointer to the connection's BIO structure.
 *
 * Parameters:
 *   hostname:	Name of target host.  Format:
 *		    "hostname:port" or "IPaddress:port"
 *   ctx:	pointer to SSL_CTX as returned by oh_ssl_ctx_init()
 *   timeout:	maximum number of seconds to wait for a connection to
 *		hostname, or zero to wait forever
 * Return value:
 *   pointer to BIO, or NULL for failure
 */
BIO		*oh_ssl_connect(char *hostname, SSL_CTX *ctx, long timeout)
{
	BIO		*bio;
	SSL		*ssl;
	fd_set		readfds;
	fd_set		writefds;
	struct timeval	tv;
	int		fd;
	int		err;

	if (hostname == NULL) {
		err("NULL hostname in oh_ssl_connect()");
		return(NULL);
	}
	if (ctx == NULL) {
		err("NULL ctx in oh_ssl_connect()");
		return(NULL);
	}
	if (timeout < 0) {
		err("inappropriate timeout in oh_ssl_connect()");
		return(NULL);
	}

	/* Start with a new SSL BIO */
	bio = BIO_new_ssl_connect(ctx);
	if (bio == NULL) {
		err("BIO_new_ssl_connect() failed");
		return(NULL);
	}

	/* Set up connection parameters for this BIO */
	BIO_set_conn_hostname(bio, hostname);
	BIO_set_nbio(bio, 1);		/* Set underlying socket to
					 * non-blocking mode
					 */

	/* Set up SSL session parameters */
	BIO_get_ssl(bio, &ssl);
	if(ssl == NULL) {
		err("BIO_get_ssl() failed");
		BIO_free_all(bio);
		return(NULL);
	}
	SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);

	/* Ready to open the connection.  Note that this call will probably
	 * take a while, so we need to retry it, watching for a timeout.
	 */
	while (1) {
		if (BIO_do_connect(bio) == 1) {
			break;		/* Connection established */
		}
		if (! BIO_should_retry(bio)) { /* Hard error? */
			err("BIO_do_connect() failed");
			err("SSL error: %s",
			    ERR_reason_error_string(ERR_get_error()));
			BIO_free_all(bio);
			return(NULL);
		}

		/* Wait until there's a change in the socket's status or until
		 * the timeout period.
		 *
		 * Get underlying file descriptor, needed for the select call.
		 */
		fd = BIO_get_fd(bio, NULL);
		if (fd == -1) {
			err("BIO isn't initialized in oh_ssl_connect()");
			BIO_free_all(bio);
			return(NULL);
		}

		FD_ZERO(&readfds);
		FD_ZERO(&writefds);
		if (BIO_should_read(bio)) {
			FD_SET(fd, &readfds);
		}
		else if (BIO_should_write(bio)) {
			FD_SET(fd, &writefds);
		}
		else {			/* This is BIO_should_io_special().
					 * Not sure what "special" needs to
					 * wait for, but both read and write
					 * seems to work without unnecessary
					 * retries.
					 */
			FD_SET(fd, &readfds);
			FD_SET(fd, &writefds);
		}
		if (timeout) {
			tv.tv_sec = timeout;
			tv.tv_usec = 0;
			err = select(fd + 1, &readfds, &writefds, NULL, &tv);
		}
		else {			/* No timeout */
			err = select(fd + 1, &readfds, &writefds, NULL, NULL);
		}

		/* Evaluate select() return code */
		if (err < 0) {
			err("error during select()");
			BIO_free_all(bio);
			return(NULL);
		}
		if (err == 0) {
			err("connection timeout to %s", hostname);
			BIO_free_all(bio);
			return(NULL);	/* Timeout */
		}
	}

	/* TODO: Do I need to set the client or server mode here?  I don't
	 * think so.
	 */

	return(bio);
}


/* oh_ssl_disconnect: Close the SSL connection and free the memory
 * 	associated with it.
 *
 * Parameters:
 *   bio:	pointer to a BIO as returned by oh_ssl_connect()
 *   shutdown:	Selects a uni-directional or bi-directional SSL shutdown.
 *   		See the SSL_shutdown() man page.
 *
 * Return value:
 *   0 for success, -1 for failure
 */
int		oh_ssl_disconnect(BIO *bio, enum OH_SSL_SHUTDOWN_TYPE shutdown)
{
	SSL		*ssl;
	int		ret;

	if(bio == NULL) {
		err("NULL bio in oh_ssl_disconnect()");
		return(-1);
	}

	/* Shut down the SSL connection.  This may involve a handshake with
	 * the server.
	 */
	BIO_get_ssl(bio, &ssl);
	if (ssl == NULL) {
		err("BIO_get_ssl() failed");
		return(-1);
	}
	ret = SSL_shutdown(ssl);
	if (ret == -1) {
		err("SSL_shutdown() failed");
		/* Continuing on to free BIO memory */
	}
	else if ((ret == 0) && (shutdown == OH_SSL_BI)) {
		/* Still need stage 2 shutdown (see SSL_shutdown() man page) */
		ret = SSL_shutdown(ssl);
		if (ret == -1) {
			err("SSL_shutdown() failed");
			/* Continuing on to free BIO memory */
		}
		else if (ret == 0) {
			err("stage 2 of SSL_shutdown() failed");
			/* Continuing on to free BIO memory */
		}
	}

	/* Free the connection */
	BIO_free_all(bio);

	return(0);
}


/* oh_ssl_read: Read from an existing SSL connection.  The data and number
 * 	of bytes read are returned.
 *
 *	Note that oh_ssl_read() and oh_ssl_write() have some subtle differences
 *	in behavior.  While oh_ssl_write() will try to write all the bytes,
 *	oh_ssl_read() will return as soon as it has read some data.
 *
 * Parameters:
 *   bio:	pointer to a BIO as returned by oh_ssl_connect()
 *   buf:	buffer for the data which is read from the connection
 *   size:	maximum number of bytes to be read into buf
 *   timeout:	maximum number of seconds to wait for input to be available,
 *		or zero to wait forever
 *
 * Return value:
 *   >0:	number of bytes read
 *    0:	nothing more to read; remote host closed the connection
 *   -1:	SSL or other error
 *   -2:	Timeout
 */
int		oh_ssl_read(BIO *bio, char *buf, int size, long timeout)
{
	SSL		*ssl;
	int		bytes = 0;
	fd_set		readfds;
	fd_set		writefds;
	struct		timeval tv;
	int		read_wait;
	int		done;
	int		err;
	int		fd;

	if (bio == NULL) {
		err("NULL bio in oh_ssl_read()");
		return(-1);
	}
	if (buf == NULL) {
		err("NULL buf in oh_ssl_read()");
		return(-1);
	}
	if (size <= 0) {
		err("inappropriate size in oh_ssl_read()");
		return(-1);
	}
	if (timeout < 0) {
		err("inappropriate timeout in oh_ssl_read()");
		return(-1);
	}

	/* Get underlying file descriptor, needed for select call */
	fd = BIO_get_fd(bio, NULL);
	if (fd == -1) {
		err("BIO doesn't seem to be initialized in oh_ssl_read()");
		return(-1);
	}

	/* We also need the SSL connection pointer */
	BIO_get_ssl(bio, &ssl);
	if (ssl == NULL) {
		err("BIO_get_ssl() failed");
		return(-1);
	}

	/* Because of SSL renegotiations, we may have to wait on a socket
	 * write even though we're trying to do a read.  The initial value
	 * of read_wait indicates that we're trying to read, but it can be
	 * set to 0 if we end up waiting for a socket write.
	 */
	read_wait = 1;
	done = 0;

	/* We have to loop on the read call, until we get something we
	 * can return to the user.
	 */
	while (! done) {
		/* First, we need to wait until something happens on the
		 * underlying socket.  We are either waiting for a read
		 * or a write (but not both).
		 */
		FD_ZERO(&readfds);
		FD_ZERO(&writefds);
		if (read_wait) {
			FD_SET(fd, &readfds);
		}
		else {
			FD_SET(fd, &writefds);
		}
		if (timeout) {
			tv.tv_sec = timeout;
			tv.tv_usec = 0;
			err = select(fd + 1, &readfds, &writefds, NULL, &tv);
		}
		else {			/* No timeout */
			err = select(fd + 1, &readfds, &writefds, NULL, NULL);
		}

		/* Evaluate select() return code */
		if (err < 0) {
			err("error during select()");
			return(-1);
		}
		if (err == 0) {
			return(-2);	/* Timeout */
		}

		/* The socket has something.  Ready to try (or re-try)
		 * the read call.
		 */
		bytes = SSL_read(ssl, buf, size);
		switch (SSL_get_error(ssl, bytes)) {
			case SSL_ERROR_NONE:
				/* No error */
				if (bytes) {
					done = 1;
				}
				break;
			case SSL_ERROR_ZERO_RETURN:
				/* Connection was closed.  For this case,
				 * since it's normal for the remote host
				 * to close when it's done, we'll not signal
				 * any error, but will return zero bytes.
				 */
				return(0);
			case SSL_ERROR_WANT_READ:
				read_wait = 1;
				break;
			case SSL_ERROR_WANT_WRITE:
				read_wait = 0;
				break;
			default:
				/* Some other sort of error */
				err("error %d from SSL_read", bytes);
				return(-1);
		}
	}

	return(bytes);
}


/* oh_ssl_write: Write data to an existing SSL connection.
 *
 *	Note that oh_ssl_read() and oh_ssl_write() have some subtle differences
 *	in behavior.  While oh_ssl_read() returns as soon as it has data for
 *	the caller, oh_ssl_write() does not return until all the bytes have
 *	been written to the remote host.
 *
 * Parameters:
 *   bio:	pointer to a BIO as returned by oh_ssl_connect()
 *   buf:	buffer to write to the connection
 *   size:	number of bytes to be written
 *   timeout:	maximum number of seconds to wait for the remote host to
 *   		accept the data, or zero to wait forever
 *
 * Return value:
 *    0:	success
 *   -1:	error
 *   -2:	timeout
 *
 */
int		oh_ssl_write(BIO *bio, char *buf, int size, long timeout)
{
	SSL		*ssl;
	int		bytes;
	fd_set		readfds;
	fd_set		writefds;
	struct		timeval tv;
	int		write_wait;
	int		done;
	int		err;
	int		fd;
	int		sent;

	if (bio == NULL) {
		err("NULL bio in oh_ssl_write()");
		return(-1);
	}
	if (buf == NULL) {
		err("NULL buf in oh_ssl_write()");
		return(-1);
	}
	if (size <= 0) {
		err("inappropriate size in oh_ssl_write()");
		return(-1);
	}
	if (timeout < 0) {
		err("inappropriate timeout in oh_ssl_write()");
		return(-1);
	}

	/* Get underlying file descriptor, needed for select call */
	fd = BIO_get_fd(bio, NULL);
	if (fd == -1) {
		err("BIO doesn't seem to be initialized in oh_ssl_write()");
		return(-1);
	}

	/* We also need the SSL connection pointer */
	BIO_get_ssl(bio, &ssl);
	if (ssl == NULL) {
		err("BIO_get_ssl() failed");
		return(-1);
	}

	/* Because of SSL renegotiations, we may have to wait on a socket
	 * read even though we're trying to do a write.  The initial value
	 * of write_wait indicates that we're trying to write, but it can
	 * be set to 0 if we end up waiting for a socket read.
	 */
	write_wait = 1;
	done = 0;
	sent = 0;

	/* We have to loop on the write call, until everything gets written */
	while (! done) {
		/* First, we need to wait until something happens on the
		 * underlying socket.  We are either waiting for a read
		 * or a write (but not both).
		 */
		FD_ZERO(&readfds);
		FD_ZERO(&writefds);
		if (write_wait) {
			FD_SET(fd, &writefds);
		}
		else {
			FD_SET(fd, &readfds);
		}
		if (timeout) {
			tv.tv_sec = timeout;
			tv.tv_usec = 0;
			err = select(fd + 1, &readfds, &writefds, NULL, &tv);
		}
		else {			/* No timeout */
			err = select(fd + 1, &readfds, &writefds, NULL, NULL);
		}

		/* Evaluate select() return code */
		if (err < 0) {
			err("error during select()");
			return(-1);
		}
		if (err == 0) {
			return(-2);	/* Timeout */
		}

		/* The socket is ready.  Ready to try (or re-try) the write
		 * call.
		 */
		bytes = SSL_write(ssl, buf + sent, size - sent);
		switch (SSL_get_error(ssl, bytes)) {
			case SSL_ERROR_NONE:
				/* No error */
				sent += bytes;
				if (sent == size) {
					done = 1;
				}
				break;
			case SSL_ERROR_ZERO_RETURN:
				/* Connection was closed.  Since we're trying
				 * to write, this is an error condition.
				 */
				err("remote host unexpectedly closed"
				    " the connection");
				return(-1);
			case SSL_ERROR_WANT_READ:
				write_wait = 0;
				break;
			case SSL_ERROR_WANT_WRITE:
				write_wait = 1;
				break;
			default:
				/* Some other sort of error */
				err("error %d from SSL_write", bytes);
				return(-1);
		}
	}

	return(0);
}
/*
 * Copyright (C) 2007-2008, Hewlett-Packard Development Company, LLP
 *                     All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are 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 the name of the Hewlett-Packard Corporation, nor the names
 * of its contributors may be used to endorse or promote products
 * derived from this software without specific prior written permission.
 *
 * 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.
 *
 * Author(s)
 *     Shuah Khan <[EMAIL PROTECTED]>
 *     Richard White <[EMAIL PROTECTED]>
 *     Bryan Sutula <[EMAIL PROTECTED]>
 */


#ifndef _INC_OH_SSL_H_
#define _INC_OH_SSL_H_


/* Include files */
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/x509v3.h>
#include <oh_error.h>


/* Data types used while using these routines */
enum OH_SSL_SHUTDOWN_TYPE {		/* See SSL_shutdown man page */
	OH_SSL_UNI,			/* Unidirectional SSL shutdown */
	OH_SSL_BI			/* Bidirectional SSL shutdown */
};


/*
 * This file defines prototypes for the SSL connection management functions
 * implemented in oh_ssl.c
 */
extern int oh_ssl_init(void);
extern SSL_CTX *oh_ssl_ctx_init(void);
extern int oh_ssl_ctx_free(SSL_CTX *ctx);
extern BIO *oh_ssl_connect(char *hostname, SSL_CTX *ctx, long timeout);
extern int oh_ssl_disconnect(BIO *bio, enum OH_SSL_SHUTDOWN_TYPE shutdown);
extern int oh_ssl_read(BIO *bio, char *buf, int size, long timeout);
extern int oh_ssl_write(BIO *bio, char *buf, int size, long timeout);


#endif /* _INC_HPI_SSL_H_ */
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Openhpi-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openhpi-devel

Reply via email to