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 85 typedef 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 */ 94 void 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. */ 99 void buffer_close(buffer_t *buf); 100 101 /* Basic functions to manipulate buffers */ 102 103 unsigned int buffer_used(buffer_t *buf); /* How much data in the buffer */ 104 unsigned int buffer_unused(buffer_t *buf); /* How much space in the buffer */ 105 int buffer_full(buffer_t *buf); /* Boolean, is it full? */ 106 int buffer_notfull(buffer_t *buf); /* Boolean, is it not full? */ 107 int buffer_empty(buffer_t *buf); /* Boolean, is it empty? */ 108 int buffer_notempty(buffer_t *buf); /* Boolean, is it not empty? */ 109 unsigned long buffer_total_in(buffer_t *buf); /* Total bytes written to buffer */ 110 unsigned 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) */ 116 unsigned 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). */ 123 unsigned 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. */ 129 unsigned 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 */ 134 int buffer_from_fd(buffer_t *buf, int fd); 135 int 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 */ 140 void buffer_from_SSL(buffer_t *buf, SSL *ssl); 141 void buffer_to_SSL(buffer_t *buf, SSL *ssl); 142 void buffer_from_BIO(buffer_t *buf, BIO *bio); 143 void buffer_to_BIO(buffer_t *buf, BIO *bio); 144 145 /* Callbacks */ 146 void cb_ssl_info(const SSL *s, int where, int ret); 147 void cb_ssl_info_set_output(FILE *fp); /* Called if output should be sent too */ 148 int cb_ssl_verify(int ok, X509_STORE_CTX *ctx); 149 void cb_ssl_verify_set_output(FILE *fp); 150 void cb_ssl_verify_set_depth(unsigned int verify_depth); 151 void cb_ssl_verify_set_level(unsigned int level); 152 RSA *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 160 typedef 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; 167 typedef enum { 168 SM_CLEAN_IN, SM_CLEAN_OUT, 169 SM_DIRTY_IN, SM_DIRTY_OUT 170 } sm_buffer_t; 171 void state_machine_init(state_machine_t *machine); 172 void state_machine_close(state_machine_t *machine); 173 buffer_t *state_machine_get_buffer(state_machine_t *machine, sm_buffer_t type); 174 SSL *state_machine_get_SSL(state_machine_t *machine); 175 int 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 */ 177 int 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. */ 180 int state_machine_close_clean(state_machine_t *machine); 181 int 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. */ 187 int 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. */ 191 int ip_create_listener_split(const char *ip, unsigned short port); 192 /* Same semantics as above. */ 193 int ip_create_connection_split(const char *ip, unsigned short port); 194 /* Converts a string into the ip/port before calling the above */ 195 int ip_create_listener(const char *address); 196 int 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. */ 200 int 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. */ 204 int ip_accept_connection(int listen_fd); 205 #endif /* !defined(NO_IP) */ 206 207 /* These functions wrap up things that can be portability hassles. */ 208 int int_strtoul(const char *str, unsigned long *val); 209 #ifdef HAVE_STRSTR 210 #define int_strstr strstr 211 #else 212 char *int_strstr(const char *haystack, const char *needle); 213 #endif 214 215 #endif /* !defined(_TUNALA_H) */ 216