1/* Tunala ("Tunneler with a New Zealand accent") 2 * 3 * Written by Geoff Thorpe, but endorsed/supported by noone. Please use this is 4 * if it's useful or informative to you, but it's only here as a scratchpad for 5 * ideas about how you might (or might not) program with OpenSSL. If you deploy 6 * this is in a mission-critical environment, and have not read, understood, 7 * audited, and modified this code to your satisfaction, and the result is that 8 * all hell breaks loose and you are looking for a new employer, then it proves 9 * nothing except perhaps that Darwinism is alive and well. Let's just say, *I* 10 * don't use this in a mission-critical environment, so it would be stupid for 11 * anyone to assume that it is solid and/or tested enough when even its author 12 * doesn't place that much trust in it. You have been warned. 13 * 14 * With thanks to Cryptographic Appliances, Inc. 15 */ 16 17#ifndef _TUNALA_H 18#define _TUNALA_H 19 20/* pull in autoconf fluff */ 21#ifndef NO_CONFIG_H 22#include "config.h" 23#else 24/* We don't have autoconf, we have to set all of these unless a tweaked Makefile 25 * tells us not to ... */ 26/* headers */ 27#ifndef NO_HAVE_SELECT 28#define HAVE_SELECT 29#endif 30#ifndef NO_HAVE_SOCKET 31#define HAVE_SOCKET 32#endif 33#ifndef NO_HAVE_UNISTD_H 34#define HAVE_UNISTD_H 35#endif 36#ifndef NO_HAVE_FCNTL_H 37#define HAVE_FCNTL_H 38#endif 39#ifndef NO_HAVE_LIMITS_H 40#define HAVE_LIMITS_H 41#endif 42/* features */ 43#ifndef NO_HAVE_STRSTR 44#define HAVE_STRSTR 45#endif 46#ifndef NO_HAVE_STRTOUL 47#define HAVE_STRTOUL 48#endif 49#endif 50 51#if !defined(HAVE_SELECT) || !defined(HAVE_SOCKET) 52#error "can't build without some network basics like select() and socket()" 53#endif 54 55#include <stdlib.h> 56#ifndef NO_SYSTEM_H 57#include <string.h> 58#ifdef HAVE_UNISTD_H 59#include <unistd.h> 60#endif 61#ifdef HAVE_FCNTL_H 62#include <fcntl.h> 63#endif 64#ifdef HAVE_LIMITS_H 65#include <limits.h> 66#endif 67#include <netdb.h> 68#include <signal.h> 69#include <sys/socket.h> 70#include <sys/types.h> 71#include <netinet/in.h> 72#endif /* !defined(NO_SYSTEM_H) */ 73 74#ifndef NO_OPENSSL 75#include <openssl/err.h> 76#include <openssl/engine.h> 77#include <openssl/ssl.h> 78#endif /* !defined(NO_OPENSSL) */ 79 80#ifndef OPENSSL_NO_BUFFER 81/* This is the generic "buffer" type that is used when feeding the 82 * state-machine. It's basically a FIFO with respect to the "adddata" & 83 * "takedata" type functions that operate on it. */ 84#define MAX_DATA_SIZE 16384 85typedef struct _buffer_t { 86 unsigned char data[MAX_DATA_SIZE]; 87 unsigned int used; 88 /* Statistical values - counts the total number of bytes read in and 89 * read out (respectively) since "buffer_init()" */ 90 unsigned long total_in, total_out; 91} buffer_t; 92 93/* Initialise a buffer structure before use */ 94void buffer_init(buffer_t *buf); 95/* Cleanup a buffer structure - presently not needed, but if buffer_t is 96 * converted to using dynamic allocation, this would be required - so should be 97 * called to protect against an explosion of memory leaks later if the change is 98 * made. */ 99void buffer_close(buffer_t *buf); 100 101/* Basic functions to manipulate buffers */ 102 103unsigned int buffer_used(buffer_t *buf); /* How much data in the buffer */ 104unsigned int buffer_unused(buffer_t *buf); /* How much space in the buffer */ 105int buffer_full(buffer_t *buf); /* Boolean, is it full? */ 106int buffer_notfull(buffer_t *buf); /* Boolean, is it not full? */ 107int buffer_empty(buffer_t *buf); /* Boolean, is it empty? */ 108int buffer_notempty(buffer_t *buf); /* Boolean, is it not empty? */ 109unsigned long buffer_total_in(buffer_t *buf); /* Total bytes written to buffer */ 110unsigned long buffer_total_out(buffer_t *buf); /* Total bytes read from buffer */ 111 112#if 0 /* Currently used only within buffer.c - better to expose only 113 * higher-level functions anyway */ 114/* Add data to the tail of the buffer, returns the amount that was actually 115 * added (so, you need to check if return value is less than size) */ 116unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr, 117 unsigned int size); 118 119/* Take data from the front of the buffer (and scroll the rest forward). If 120 * "ptr" is NULL, this just removes data off the front of the buffer. Return 121 * value is the amount actually removed (can be less than size if the buffer has 122 * too little data). */ 123unsigned int buffer_takedata(buffer_t *buf, unsigned char *ptr, 124 unsigned int size); 125 126/* Flushes as much data as possible out of the "from" buffer into the "to" 127 * buffer. Return value is the amount moved. The amount moved can be restricted 128 * to a maximum by specifying "cap" - setting it to -1 means no limit. */ 129unsigned int buffer_tobuffer(buffer_t *to, buffer_t *from, int cap); 130#endif 131 132#ifndef NO_IP 133/* Read or write between a file-descriptor and a buffer */ 134int buffer_from_fd(buffer_t *buf, int fd); 135int buffer_to_fd(buffer_t *buf, int fd); 136#endif /* !defined(NO_IP) */ 137 138#ifndef NO_OPENSSL 139/* Read or write between an SSL or BIO and a buffer */ 140void buffer_from_SSL(buffer_t *buf, SSL *ssl); 141void buffer_to_SSL(buffer_t *buf, SSL *ssl); 142void buffer_from_BIO(buffer_t *buf, BIO *bio); 143void buffer_to_BIO(buffer_t *buf, BIO *bio); 144 145/* Callbacks */ 146void cb_ssl_info(const SSL *s, int where, int ret); 147void cb_ssl_info_set_output(FILE *fp); /* Called if output should be sent too */ 148int cb_ssl_verify(int ok, X509_STORE_CTX *ctx); 149void cb_ssl_verify_set_output(FILE *fp); 150void cb_ssl_verify_set_depth(unsigned int verify_depth); 151void cb_ssl_verify_set_level(unsigned int level); 152RSA *cb_generate_tmp_rsa(SSL *s, int is_export, int keylength); 153#endif /* !defined(NO_OPENSSL) */ 154#endif /* !defined(OPENSSL_NO_BUFFER) */ 155 156#ifndef NO_TUNALA 157#ifdef OPENSSL_NO_BUFFER 158#error "TUNALA section of tunala.h requires BUFFER support" 159#endif 160typedef struct _state_machine_t { 161 SSL *ssl; 162 BIO *bio_intossl; 163 BIO *bio_fromssl; 164 buffer_t clean_in, clean_out; 165 buffer_t dirty_in, dirty_out; 166} state_machine_t; 167typedef enum { 168 SM_CLEAN_IN, SM_CLEAN_OUT, 169 SM_DIRTY_IN, SM_DIRTY_OUT 170} sm_buffer_t; 171void state_machine_init(state_machine_t *machine); 172void state_machine_close(state_machine_t *machine); 173buffer_t *state_machine_get_buffer(state_machine_t *machine, sm_buffer_t type); 174SSL *state_machine_get_SSL(state_machine_t *machine); 175int state_machine_set_SSL(state_machine_t *machine, SSL *ssl, int is_server); 176/* Performs the data-IO loop and returns zero if the machine should close */ 177int state_machine_churn(state_machine_t *machine); 178/* Is used to handle closing conditions - namely when one side of the tunnel has 179 * closed but the other should finish flushing. */ 180int state_machine_close_clean(state_machine_t *machine); 181int state_machine_close_dirty(state_machine_t *machine); 182#endif /* !defined(NO_TUNALA) */ 183 184#ifndef NO_IP 185/* Initialise anything related to the networking. This includes blocking pesky 186 * SIGPIPE signals. */ 187int ip_initialise(void); 188/* ip is the 4-byte ip address (eg. 127.0.0.1 is {0x7F,0x00,0x00,0x01}), port is 189 * the port to listen on (host byte order), and the return value is the 190 * file-descriptor or -1 on error. */ 191int ip_create_listener_split(const char *ip, unsigned short port); 192/* Same semantics as above. */ 193int ip_create_connection_split(const char *ip, unsigned short port); 194/* Converts a string into the ip/port before calling the above */ 195int ip_create_listener(const char *address); 196int ip_create_connection(const char *address); 197/* Just does a string conversion on its own. NB: If accept_all_ip is non-zero, 198 * then the address string could be just a port. Ie. it's suitable for a 199 * listening address but not a connecting address. */ 200int ip_parse_address(const char *address, const char **parsed_ip, 201 unsigned short *port, int accept_all_ip); 202/* Accepts an incoming connection through the listener. Assumes selects and 203 * what-not have deemed it an appropriate thing to do. */ 204int ip_accept_connection(int listen_fd); 205#endif /* !defined(NO_IP) */ 206 207/* These functions wrap up things that can be portability hassles. */ 208int int_strtoul(const char *str, unsigned long *val); 209#ifdef HAVE_STRSTR 210#define int_strstr strstr 211#else 212char *int_strstr(const char *haystack, const char *needle); 213#endif 214 215#endif /* !defined(_TUNALA_H) */ 216