1 /* Copyright (c) 2017-2020, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
5 * \file test_proto_misc.c
6 * \brief Test our smaller buffer-based protocol functions
9 #include "core/or/or.h"
10 #include "test/test.h"
11 #include "lib/buf/buffers.h"
12 #include "core/or/connection_or.h"
13 #include "feature/relay/ext_orport.h"
14 #include "core/proto/proto_cell.h"
15 #include "core/proto/proto_control0.h"
16 #include "core/proto/proto_ext_or.h"
18 #include "core/or/var_cell_st.h"
21 test_proto_var_cell(void *arg
)
24 char *mem_op_hex_tmp
= NULL
;
27 var_cell_t
*cell
= NULL
;
30 memset(tmp
, 0xf0, sizeof(tmp
));
32 /* Short little commands will make us say "no cell yet." */
33 tt_int_op(0, OP_EQ
, fetch_var_cell_from_buf(buf
, &cell
, 4));
34 tt_ptr_op(cell
, OP_EQ
, NULL
);
35 buf_add(buf
, "\x01\x02\x02\0x2", 4);
36 tt_int_op(0, OP_EQ
, fetch_var_cell_from_buf(buf
, &cell
, 4));
37 /* An incomplete fixed-length cell makes us say "no cell yet". */
38 buf_add(buf
, "\x03", 1);
39 tt_int_op(0, OP_EQ
, fetch_var_cell_from_buf(buf
, &cell
, 4));
40 /* A complete fixed length-cell makes us say "not a variable-length cell" */
41 buf_add(buf
, tmp
, 509);
42 tt_int_op(0, OP_EQ
, fetch_var_cell_from_buf(buf
, &cell
, 4));
45 /* An incomplete versions cell is a variable-length cell that isn't ready
48 "\x01\x02\x03\x04" /* circid */
50 "\x00\x04" /* 4 bytes long */
51 "\x00" /* incomplete */, 8);
52 tt_int_op(1, OP_EQ
, fetch_var_cell_from_buf(buf
, &cell
, 4));
53 tt_ptr_op(cell
, OP_EQ
, NULL
);
54 /* Complete it, and it's a variable-length cell. Leave a byte on the end for
56 buf_add(buf
, "\x09\x00\x25\ff", 4);
57 tt_int_op(1, OP_EQ
, fetch_var_cell_from_buf(buf
, &cell
, 4));
58 tt_ptr_op(cell
, OP_NE
, NULL
);
59 tt_int_op(cell
->command
, OP_EQ
, CELL_VERSIONS
);
60 tt_uint_op(cell
->circ_id
, OP_EQ
, 0x01020304);
61 tt_int_op(cell
->payload_len
, OP_EQ
, 4);
62 test_mem_op_hex(cell
->payload
, OP_EQ
, "00090025");
65 tt_int_op(buf_datalen(buf
), OP_EQ
, 1);
68 /* In link protocol 3 and earlier, circid fields were two bytes long. Let's
69 * ensure that gets handled correctly. */
71 "\x23\x45\x81\x00\x06" /* command 81; 6 bytes long */
73 tt_int_op(1, OP_EQ
, fetch_var_cell_from_buf(buf
, &cell
, 3));
74 tt_ptr_op(cell
, OP_NE
, NULL
);
75 tt_int_op(cell
->command
, OP_EQ
, 129);
76 tt_uint_op(cell
->circ_id
, OP_EQ
, 0x2345);
77 tt_int_op(cell
->payload_len
, OP_EQ
, 6);
78 tt_mem_op(cell
->payload
, OP_EQ
, "coraje", 6);
81 tt_int_op(buf_datalen(buf
), OP_EQ
, 0);
83 /* In link protocol 2, only VERSIONS cells counted as variable-length */
85 "\x23\x45\x81\x00\x06"
86 "coraje", 11); /* As above */
87 tt_int_op(0, OP_EQ
, fetch_var_cell_from_buf(buf
, &cell
, 2));
90 "\x23\x45\x07\x00\x06"
92 tt_int_op(1, OP_EQ
, fetch_var_cell_from_buf(buf
, &cell
, 2));
93 tt_ptr_op(cell
, OP_NE
, NULL
);
94 tt_int_op(cell
->command
, OP_EQ
, 7);
95 tt_uint_op(cell
->circ_id
, OP_EQ
, 0x2345);
96 tt_int_op(cell
->payload_len
, OP_EQ
, 6);
97 tt_mem_op(cell
->payload
, OP_EQ
, "futuro", 6);
104 tor_free(mem_op_hex_tmp
);
108 test_proto_control0(void *arg
)
111 buf_t
*buf
= buf_new();
113 /* The only remaining function for the v0 control protocol is the function
114 that detects whether the user has stumbled across an old controller
115 that's using it. The format was:
121 /* Empty buffer -- nothing to do. */
122 tt_int_op(0, OP_EQ
, peek_buf_has_control0_command(buf
));
123 /* 3 chars in buf -- can't tell */
124 buf_add(buf
, "AUT", 3);
125 tt_int_op(0, OP_EQ
, peek_buf_has_control0_command(buf
));
126 /* command in buf -- easy to tell */
127 buf_add(buf
, "HENTICATE ", 10);
128 tt_int_op(0, OP_EQ
, peek_buf_has_control0_command(buf
));
130 /* Control0 command header in buf: make sure we detect it. */
132 buf_add(buf
, "\x09\x05" "\x00\x05" "blah", 8);
133 tt_int_op(1, OP_EQ
, peek_buf_has_control0_command(buf
));
140 test_proto_ext_or_cmd(void *arg
)
142 ext_or_cmd_t
*cmd
= NULL
;
143 buf_t
*buf
= buf_new();
147 /* Empty -- should give "not there. */
148 tt_int_op(0, OP_EQ
, fetch_ext_or_command_from_buf(buf
, &cmd
));
149 tt_ptr_op(NULL
, OP_EQ
, cmd
);
151 /* Three bytes: shouldn't work. */
152 buf_add(buf
, "\x00\x20\x00", 3);
153 tt_int_op(0, OP_EQ
, fetch_ext_or_command_from_buf(buf
, &cmd
));
154 tt_ptr_op(NULL
, OP_EQ
, cmd
);
155 tt_int_op(3, OP_EQ
, buf_datalen(buf
));
157 /* 0020 0000: That's a nil command. It should work. */
158 buf_add(buf
, "\x00", 1);
159 tt_int_op(1, OP_EQ
, fetch_ext_or_command_from_buf(buf
, &cmd
));
160 tt_ptr_op(NULL
, OP_NE
, cmd
);
161 tt_int_op(0x20, OP_EQ
, cmd
->cmd
);
162 tt_int_op(0, OP_EQ
, cmd
->len
);
163 tt_int_op(0, OP_EQ
, buf_datalen(buf
));
164 ext_or_cmd_free(cmd
);
167 /* Now try a length-6 command with one byte missing. */
168 buf_add(buf
, "\x10\x21\x00\x06""abcde", 9);
169 tt_int_op(0, OP_EQ
, fetch_ext_or_command_from_buf(buf
, &cmd
));
170 tt_ptr_op(NULL
, OP_EQ
, cmd
);
171 buf_add(buf
, "f", 1);
172 tt_int_op(1, OP_EQ
, fetch_ext_or_command_from_buf(buf
, &cmd
));
173 tt_ptr_op(NULL
, OP_NE
, cmd
);
174 tt_int_op(0x1021, OP_EQ
, cmd
->cmd
);
175 tt_int_op(6, OP_EQ
, cmd
->len
);
176 tt_mem_op("abcdef", OP_EQ
, cmd
->body
, 6);
177 tt_int_op(0, OP_EQ
, buf_datalen(buf
));
178 ext_or_cmd_free(cmd
);
181 /* Now try a length-10 command with 4 extra bytes. */
182 buf_add(buf
, "\xff\xff\x00\x0aloremipsum\x10\x00\xff\xff", 18);
183 tt_int_op(1, OP_EQ
, fetch_ext_or_command_from_buf(buf
, &cmd
));
184 tt_ptr_op(NULL
, OP_NE
, cmd
);
185 tt_int_op(0xffff, OP_EQ
, cmd
->cmd
);
186 tt_int_op(10, OP_EQ
, cmd
->len
);
187 tt_mem_op("loremipsum", OP_EQ
, cmd
->body
, 10);
188 tt_int_op(4, OP_EQ
, buf_datalen(buf
));
189 ext_or_cmd_free(cmd
);
192 /* Finally, let's try a maximum-length command. We already have the header
194 tt_int_op(0, OP_EQ
, fetch_ext_or_command_from_buf(buf
, &cmd
));
195 tmp
= tor_malloc_zero(65535);
196 buf_add(buf
, tmp
, 65535);
197 tt_int_op(1, OP_EQ
, fetch_ext_or_command_from_buf(buf
, &cmd
));
198 tt_ptr_op(NULL
, OP_NE
, cmd
);
199 tt_int_op(0x1000, OP_EQ
, cmd
->cmd
);
200 tt_int_op(0xffff, OP_EQ
, cmd
->len
);
201 tt_mem_op(tmp
, OP_EQ
, cmd
->body
, 65535);
202 tt_int_op(0, OP_EQ
, buf_datalen(buf
));
203 ext_or_cmd_free(cmd
);
207 ext_or_cmd_free(cmd
);
213 test_proto_line(void *arg
)
217 buf_t
*buf
= buf_new();
218 #define S(str) str, sizeof(str)-1
226 { S("Hello world"), 0, NULL
, 0 },
227 { S("Hello world\n"), 12, "Hello world\n", 1 },
228 { S("Hello world\nMore"), 12, "Hello world\n", 1 },
229 { S("\n oh hello world\nMore"), 1, "\n", 1 },
230 { S("Hello worpd\n\nMore"), 12, "Hello worpd\n", 1 },
231 { S("------------------------------------------------------------\n"), 0,
235 for (i
= 0; i
< ARRAY_LENGTH(cases
); ++i
) {
236 buf_add(buf
, cases
[i
].input
, cases
[i
].input_len
);
237 memset(tmp
, 0xfe, sizeof(tmp
));
238 size_t sz
= sizeof(tmp
);
239 int rv
= buf_get_line(buf
, tmp
, &sz
);
240 tt_int_op(rv
, OP_EQ
, cases
[i
].returnval
);
242 tt_int_op(sz
, OP_LT
, sizeof(tmp
));
243 tt_mem_op(cases
[i
].output
, OP_EQ
, tmp
, sz
+1);
244 tt_int_op(buf_datalen(buf
), OP_EQ
, cases
[i
].input_len
- strlen(tmp
));
245 tt_int_op(sz
, OP_EQ
, cases
[i
].line_len
);
247 tt_int_op(buf_datalen(buf
), OP_EQ
, cases
[i
].input_len
);
248 // tt_int_op(sz, OP_EQ, sizeof(tmp));
257 struct testcase_t proto_misc_tests
[] = {
258 { "var_cell", test_proto_var_cell
, 0, NULL
, NULL
},
259 { "control0", test_proto_control0
, 0, NULL
, NULL
},
260 { "ext_or_cmd", test_proto_ext_or_cmd
, TT_FORK
, NULL
, NULL
},
261 { "line", test_proto_line
, 0, NULL
, NULL
},