Explanation, tips, etc.
[openssl.git] / demos / tunala / tunala.h
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 #ifndef NO_SYSTEM_H
21 #include <string.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <netdb.h>
25 #include <signal.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #endif /* !defined(NO_SYSTEM_H) */
29
30 #ifndef NO_OPENSSL
31 #include <openssl/err.h>
32 #include <openssl/engine.h>
33 #include <openssl/ssl.h>
34 #endif /* !defined(NO_OPENSSL) */
35
36 #ifndef NO_BUFFER
37 /* This is the generic "buffer" type that is used when feeding the
38  * state-machine. It's basically a FIFO with respect to the "adddata" &
39  * "takedata" type functions that operate on it. */
40 #define MAX_DATA_SIZE 16384
41 typedef struct _buffer_t {
42         unsigned char data[MAX_DATA_SIZE];
43         unsigned int used;
44 } buffer_t;
45
46 /* Initialise a buffer structure before use */
47 void buffer_init(buffer_t *buf);
48 /* Cleanup a buffer structure - presently not needed, but if buffer_t is
49  * converted to using dynamic allocation, this would be required - so should be
50  * called to protect against an explosion of memory leaks later if the change is
51  * made. */
52 void buffer_close(buffer_t *buf);
53
54 /* Basic functions to manipulate buffers */
55
56 unsigned int buffer_used(buffer_t *buf); /* How much data in the buffer */
57 unsigned int buffer_unused(buffer_t *buf); /* How much space in the buffer */
58 int buffer_full(buffer_t *buf); /* Boolean, is it full? */
59 int buffer_notfull(buffer_t *buf); /* Boolean, is it not full? */
60 int buffer_empty(buffer_t *buf); /* Boolean, is it empty? */
61 int buffer_notempty(buffer_t *buf); /* Boolean, is it not empty? */
62
63 /* Add data to the tail of the buffer, returns the amount that was actually
64  * added (so, you need to check if return value is less than size) */
65 unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr,
66                 unsigned int size);
67
68 /* Take data from the front of the buffer (and scroll the rest forward). If
69  * "ptr" is NULL, this just removes data off the front of the buffer. Return
70  * value is the amount actually removed (can be less than size if the buffer has
71  * too little data). */
72 unsigned int buffer_takedata(buffer_t *buf, unsigned char *ptr,
73                 unsigned int size);
74
75 /* Flushes as much data as possible out of the "from" buffer into the "to"
76  * buffer. Return value is the amount moved. The amount moved can be restricted
77  * to a maximum by specifying "cap" - setting it to -1 means no limit. */
78 unsigned int buffer_tobuffer(buffer_t *to, buffer_t *from, int cap);
79
80 #ifndef NO_IP
81 /* Read or write between a file-descriptor and a buffer */
82 int buffer_from_fd(buffer_t *buf, int fd);
83 int buffer_to_fd(buffer_t *buf, int fd);
84 #endif /* !defined(NO_IP) */
85
86 #ifndef NO_OPENSSL
87 /* Read or write between an SSL or BIO and a buffer */
88 void buffer_from_SSL(buffer_t *buf, SSL *ssl);
89 void buffer_to_SSL(buffer_t *buf, SSL *ssl);
90 void buffer_from_BIO(buffer_t *buf, BIO *bio);
91 void buffer_to_BIO(buffer_t *buf, BIO *bio);
92 #endif /* !defined(NO_OPENSSL) */
93 #endif /* !defined(NO_BUFFER) */
94
95 #ifndef NO_TUNALA
96 #ifdef NO_BUFFER
97 #error "TUNALA section of tunala.h requires BUFFER support"
98 #endif
99 typedef struct _state_machine_t {
100         SSL *ssl;
101         BIO *bio_intossl;
102         BIO *bio_fromssl;
103         buffer_t clean_in, clean_out;
104         buffer_t dirty_in, dirty_out;
105 } state_machine_t;
106 typedef enum {
107         SM_CLEAN_IN, SM_CLEAN_OUT,
108         SM_DIRTY_IN, SM_DIRTY_OUT
109 } sm_buffer_t;
110 void state_machine_init(state_machine_t *machine);
111 void state_machine_close(state_machine_t *machine);
112 buffer_t *state_machine_get_buffer(state_machine_t *machine, sm_buffer_t type);
113 SSL *state_machine_get_SSL(state_machine_t *machine);
114 void state_machine_set_SSL(state_machine_t *machine, SSL *ssl, int is_server);
115 /* Performs the data-IO loop and returns zero if the machine should close */
116 int state_machine_churn(state_machine_t *machine);
117 /* Is used to handle closing conditions - namely when one side of the tunnel has
118  * closed but the other should finish flushing. */
119 int state_machine_close_clean(state_machine_t *machine);
120 int state_machine_close_dirty(state_machine_t *machine);
121 #endif /* !defined(NO_TUNALA) */
122
123 #ifndef NO_IP
124 /* Initialise anything related to the networking. This includes blocking pesky
125  * SIGPIPE signals. */
126 int ip_initialise(void);
127 /* ip is the 4-byte ip address (eg. 127.0.0.1 is {0x7F,0x00,0x00,0x01}), port is
128  * the port to listen on (host byte order), and the return value is the
129  * file-descriptor or -1 on error. */
130 int ip_create_listener_split(const unsigned char *ip, unsigned short port);
131 /* Same semantics as above. */
132 int ip_create_connection_split(const unsigned char *ip, unsigned short port);
133 /* Converts a string into the ip/port before calling the above */
134 int ip_create_listener(const char *address);
135 int ip_create_connection(const char *address);
136 /* Just does a string conversion on its own. NB: If accept_all_ip is non-zero,
137  * then the address string could be just a port. Ie. it's suitable for a
138  * listening address but not a connecting address. */
139 int ip_parse_address(const char *address, unsigned char **parsed_ip,
140                 unsigned short *port, int accept_all_ip);
141 /* Accepts an incoming connection through the listener. Assumes selects and
142  * what-not have deemed it an appropriate thing to do. */
143 int ip_accept_connection(int listen_fd);
144 #endif /* !defined(NO_IP) */
145
146 #endif /* !defined(_TUNALA_H) */