1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
|
/* Copyright (c) 2002 Roger Dingledine. See LICENSE for licensing information */
/* $Id$ */
#ifndef __OR_H
#define __OR_H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <netdb.h>
#include <ctype.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <assert.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include "../common/cell.h"
#include "../common/config.h"
#include "../common/key.h"
#include "../common/log.h"
#include "../common/onion.h"
#include "../common/ss.h"
#define MAXCONNECTIONS 200 /* upper bound on max connections.
can be overridden by config file */
#define MAX_BUF_SIZE (64*1024)
#define ACI_TYPE_LOWER 0
#define ACI_TYPE_HIGHER 1
#define CONN_TYPE_OP_LISTENER 1
#define CONN_TYPE_OP 2
#define CONN_TYPE_OR_LISTENER 3
#define CONN_TYPE_OR 4
#define CONN_TYPE_EXIT 5
#define CONN_TYPE_AP_LISTENER 6
#define CONN_TYPE_AP 7
#define LISTENER_STATE_READY 0
#define OP_CONN_STATE_AWAITING_KEYS 0
#define OP_CONN_STATE_OPEN 1
#if 0
#define OP_CONN_STATE_CLOSE 2 /* flushing the buffer, then will close */
#define OP_CONN_STATE_CLOSE_WAIT 3 /* have sent a destroy, awaiting a confirmation */
#endif
/* how to read these states:
* foo_CONN_STATE_bar_baz:
* "I am acting as a bar, currently in stage baz of talking with a foo."
*/
#define OR_CONN_STATE_OP_CONNECTING 0
#define OR_CONN_STATE_OP_SENDING_KEYS 1
#define OR_CONN_STATE_CLIENT_CONNECTING 2
#define OR_CONN_STATE_CLIENT_SENDING_AUTH 3 /* sending address and info */
#define OR_CONN_STATE_CLIENT_AUTH_WAIT 4 /* have sent address and info, waiting */
#define OR_CONN_STATE_CLIENT_SENDING_NONCE 5 /* sending nonce, last piece of handshake */
#define OR_CONN_STATE_SERVER_AUTH_WAIT 6 /* waiting for address and info */
#define OR_CONN_STATE_SERVER_SENDING_AUTH 7 /* writing auth and nonce */
#define OR_CONN_STATE_SERVER_NONCE_WAIT 8 /* waiting for confirmation of nonce */
#define OR_CONN_STATE_OPEN 9 /* ready to send/receive cells. */
#define EXIT_CONN_STATE_CONNECTING_WAIT 0 /* waiting for standard structure or dest info */
#define EXIT_CONN_STATE_CONNECTING 1
#define EXIT_CONN_STATE_OPEN 2
#if 0
#define EXIT_CONN_STATE_CLOSE 3 /* flushing the buffer, then will close */
#define EXIT_CONN_STATE_CLOSE_WAIT 4 /* have sent a destroy, awaiting a confirmation */
#endif
#define AP_CONN_STATE_SS_WAIT 0
#define AP_CONN_STATE_OR_WAIT 1
#define AP_CONN_STATE_OPEN 2
#define CIRCUIT_STATE_OPEN_WAIT 0 /* receiving/processing the onion */
#define CIRCUIT_STATE_OPEN 1 /* onion processed, ready to send data along the connection */
#define CIRCUIT_STATE_CLOSE_WAIT1 2 /* sent two "destroy" signals, waiting for acks */
#define CIRCUIT_STATE_CLOSE_WAIT2 3 /* received one ack, waiting for one more
(or if just one was sent, waiting for that one */
//#define CIRCUIT_STATE_CLOSE 4 /* both acks received, connection is dead */ /* NOT USED */
typedef uint16_t aci_t;
typedef struct
{
/* Used by all types: */
unsigned char type;
int state;
int s; /* our socket */
int poll_index;
int marked_for_close;
char *inbuf;
size_t inbuflen;
size_t inbuf_datalen;
int inbuf_reached_eof;
char *outbuf;
size_t outbuflen;
size_t outbuf_datalen;
/* used by OP and App: */
uint16_t aci; /* anonymous connection identifier */
/* used by OR and OP: */
uint32_t bandwidth; /* connection bandwidth */
int window_sent; /* how many cells can i still send? */
int window_received; /* how many cells do i still expect to receive? */
/* link encryption */
unsigned char f_session_key[8];
unsigned char b_session_key[8];
unsigned char f_session_iv[8];
unsigned char b_session_iv[8];
EVP_CIPHER_CTX f_ctx;
EVP_CIPHER_CTX b_ctx;
// struct timeval lastsend; /* time of last transmission to the client */
// struct timeval interval; /* transmission interval */
uint32_t addr; /* these two uniquely identify a router */
uint16_t port;
/* used by exit: */
ss_t ss; /* standard structure */
int ss_received; /* size of ss, received so far */
/* used by OR, to keep state while connect()ing: Kludge. */
RSA *prkey;
struct sockaddr_in local;
/* link info */
uint32_t min;
uint32_t max;
char *address; /* strdup into this, gets free_connection frees it */
RSA *pkey; /* public RSA key for the other side */
char nonce[8];
} connection_t;
/* config stuff we know about the other ORs in the network */
typedef struct
{
char *address;
uint32_t addr;
uint16_t port;
RSA *pkey; /* public RSA key */
/* link info */
uint32_t min;
uint32_t max;
// struct timeval min_interval;
/* time when last data was sent to that router */
// struct timeval lastsend;
/* socket */
// int s;
void *next;
} routerinfo_t;
/* per-anonymous-connection struct */
typedef struct
{
#if 0
uint32_t p_addr; /* all in network order */
uint16_t p_port;
#endif
uint32_t n_addr;
uint16_t n_port;
connection_t *p_conn;
connection_t *n_conn;
aci_t p_aci; /* connection identifiers */
aci_t n_aci;
unsigned char p_f; /* crypto functions */
unsigned char n_f;
unsigned char p_key[128]; /* crypto keys */
unsigned char n_key[128];
unsigned char p_iv[16]; /* initialization vectors */
unsigned char n_iv[16];
EVP_CIPHER_CTX p_ctx; /* cipher context */
EVP_CIPHER_CTX n_ctx;
uint32_t expire; /* expiration time for the corresponding onion */
int state;
unsigned char *onion; /* stores the onion when state is CONN_STATE_OPEN_WAIT */
uint32_t onionlen; /* total onion length */
uint32_t recvlen; /* length of the onion so far */
void *next;
} circuit_t;
/* all the function prototypes go here */
/********************************* args.c ***************************/
/* print help*/
void print_usage();
/* get command-line arguments */
int getargs(int argc,char *argv[], char *args,char **conf_filename, int *loglevel);
/********************************* buffers.c ***************************/
int buf_new(char **buf, size_t *buflen, size_t *buf_datalen);
void buf_free(char *buf);
int read_to_buf(int s, char **buf, size_t *buflen, size_t *buf_datalen, int *reached_eof);
/* grab from s, put onto buf, return how many bytes read */
int flush_buf(int s, char **buf, size_t *buflen, size_t *buf_datalen);
/* push from buf onto s
* then memmove to front of buf
* return -1 or how many bytes remain on the buf */
int write_to_buf(char *string, size_t string_len,
char **buf, size_t *buflen, size_t *buf_datalen);
/* append string to buf (growing as needed, return -1 if "too big")
* return total number of bytes on the buf
*/
int fetch_from_buf(char *string, size_t string_len,
char **buf, size_t *buflen, size_t *buf_datalen);
/* if there is string_len bytes in buf, write them onto string,
* * then memmove buf back (that is, remove them from buf) */
/********************************* cell.c ***************************/
int check_sane_cell(cell_t *cell);
/********************************* circuit.c ***************************/
void circuit_add(circuit_t *circ);
void circuit_remove(circuit_t *circ);
circuit_t *circuit_new(aci_t p_aci, connection_t *p_conn);
/* internal */
aci_t get_unique_aci_by_addr_port(uint32_t addr, uint16_t port, int aci_type);
circuit_t *circuit_get_by_aci_conn(aci_t aci, connection_t *conn);
circuit_t *circuit_get_by_conn(connection_t *conn);
int circuit_deliver_data_cell(cell_t *cell, circuit_t *circ, connection_t *conn, int crypt_type);
int circuit_crypt(circuit_t *circ, char *in, size_t inlen, char crypt_type);
int circuit_init(circuit_t *circ, int aci_type);
void circuit_free(circuit_t *circ);
void circuit_close(circuit_t *circ);
void circuit_about_to_close_connection(connection_t *conn);
/* flush and send destroys for all circuits using conn */
/********************************* command.c ***************************/
void command_process_cell(cell_t *cell, connection_t *conn);
void command_process_create_cell(cell_t *cell, connection_t *conn);
void command_process_data_cell(cell_t *cell, connection_t *conn);
void command_process_destroy_cell(cell_t *cell, connection_t *conn);
/********************************* config.c ***************************/
/* loads the configuration file */
int getconfig(char *filename, config_opt_t *options);
/********************************* connection.c ***************************/
connection_t *connection_new(int type);
void connection_free(connection_t *conn);
int connection_create_listener(RSA *prkey, struct sockaddr_in *local, int type);
int connection_handle_listener_read(connection_t *conn, int new_type, int new_state);
/* start all connections that should be up but aren't */
int retry_all_connections(routerinfo_t **router_array, int rarray_len,
RSA *prkey, uint16_t or_port, uint16_t op_port, uint16_t ap_port);
int connection_read_to_buf(connection_t *conn);
int connection_fetch_from_buf(char *string, int len, connection_t *conn);
int connection_flush_buf(connection_t *conn);
int connection_write_to_buf(char *string, int len, connection_t *conn);
int connection_send_destroy(aci_t aci, connection_t *conn);
int connection_encrypt_cell_header(cell_t *cellp, connection_t *conn);
int connection_write_cell_to_buf(cell_t *cellp, connection_t *conn);
int connection_process_inbuf(connection_t *conn);
int connection_process_cell_from_inbuf(connection_t *conn);
int connection_finished_flushing(connection_t *conn);
/********************************* connection_or.c ***************************/
int connection_or_process_inbuf(connection_t *conn);
int connection_or_finished_flushing(connection_t *conn);
void conn_or_init_crypto(connection_t *conn);
int or_handshake_client_process_auth(connection_t *conn);
int or_handshake_client_send_auth(connection_t *conn);
int or_handshake_server_process_auth(connection_t *conn);
int or_handshake_server_process_nonce(connection_t *conn);
int connect_to_router(routerinfo_t *router, RSA *prkey, struct sockaddr_in *local);
int connection_or_create_listener(RSA *prkey, struct sockaddr_in *local);
int connection_or_handle_listener_read(connection_t *conn);
/********************************* connection_op.c ***************************/
int op_handshake_process_keys(connection_t *conn);
int connection_op_process_inbuf(connection_t *conn);
int connection_op_finished_flushing(connection_t *conn);
int connection_op_create_listener(RSA *prkey, struct sockaddr_in *local);
int connection_op_handle_listener_read(connection_t *conn);
/********************************* connection_exit.c ***************************/
int connection_exit_process_inbuf(connection_t *conn);
int connection_exit_package_inbuf(connection_t *conn);
int connection_exit_process_data_cell(cell_t *cell, connection_t *conn);
int connection_exit_finished_flushing(connection_t *conn);
/********************************* main.c ***************************/
int connection_add(connection_t *conn);
int connection_remove(connection_t *conn);
void connection_set_poll_socket(connection_t *conn);
connection_t *connection_get_by_addr_port(uint32_t addr, uint16_t port);
connection_t *connection_get_by_type(int type);
routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port);
void connection_watch_events(connection_t *conn, short events);
void check_conn_read(int i);
void check_conn_marked(int i);
void check_conn_write(int i);
void check_conn_hup(int i);
int do_main_loop(void);
int main(int argc, char *argv[]);
/********************************* onion.c ***************************/
int decide_aci_type(uint32_t local_addr, uint16_t local_port,
uint32_t remote_addr, uint16_t remote_port);
int process_onion(circuit_t *circ, connection_t *conn);
/********************************* routers.c ***************************/
routerinfo_t **getrouters(char *routerfile, size_t *listlenp);
void delete_routerlist(routerinfo_t *list);
/* create an NULL-terminated array of pointers pointing to elements of a router list */
routerinfo_t **make_rarray(routerinfo_t* list, size_t *listlenp);
#endif
|