Line data Source code
1 : /* socks5.c -- generated by Trunnel v1.5.3.
2 : * https://gitweb.torproject.org/trunnel.git
3 : * You probably shouldn't edit this file.
4 : */
5 : #include <stdlib.h>
6 : #include "trunnel-impl.h"
7 :
8 : #include "socks5.h"
9 :
10 : #define TRUNNEL_SET_ERROR_CODE(obj) \
11 : do { \
12 : (obj)->trunnel_error_code_ = 1; \
13 : } while (0)
14 :
15 : #if defined(__COVERITY__) || defined(__clang_analyzer__)
16 : /* If we're running a static analysis tool, we don't want it to complain
17 : * that some of our remaining-bytes checks are dead-code. */
18 : int socks_deadcode_dummy__ = 0;
19 : #define OR_DEADCODE_DUMMY || socks_deadcode_dummy__
20 : #else
21 : #define OR_DEADCODE_DUMMY
22 : #endif
23 :
24 : #define CHECK_REMAINING(nbytes, label) \
25 : do { \
26 : if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
27 : goto label; \
28 : } \
29 : } while (0)
30 :
31 : domainname_t *
32 290 : domainname_new(void)
33 : {
34 290 : domainname_t *val = trunnel_calloc(1, sizeof(domainname_t));
35 290 : if (NULL == val)
36 0 : return NULL;
37 : return val;
38 : }
39 :
40 : /** Release all storage held inside 'obj', but do not free 'obj'.
41 : */
42 : static void
43 290 : domainname_clear(domainname_t *obj)
44 : {
45 290 : (void) obj;
46 290 : TRUNNEL_DYNARRAY_WIPE(&obj->name);
47 290 : TRUNNEL_DYNARRAY_CLEAR(&obj->name);
48 290 : }
49 :
50 : void
51 615 : domainname_free(domainname_t *obj)
52 : {
53 615 : if (obj == NULL)
54 : return;
55 290 : domainname_clear(obj);
56 290 : trunnel_memwipe(obj, sizeof(domainname_t));
57 290 : trunnel_free_(obj);
58 : }
59 :
60 : uint8_t
61 0 : domainname_get_len(const domainname_t *inp)
62 : {
63 0 : return inp->len;
64 : }
65 : int
66 0 : domainname_set_len(domainname_t *inp, uint8_t val)
67 : {
68 0 : inp->len = val;
69 0 : return 0;
70 : }
71 : size_t
72 0 : domainname_getlen_name(const domainname_t *inp)
73 : {
74 0 : return TRUNNEL_DYNARRAY_LEN(&inp->name);
75 : }
76 :
77 : char
78 0 : domainname_get_name(domainname_t *inp, size_t idx)
79 : {
80 0 : return TRUNNEL_DYNARRAY_GET(&inp->name, idx);
81 : }
82 :
83 : char
84 0 : domainname_getconst_name(const domainname_t *inp, size_t idx)
85 : {
86 0 : return domainname_get_name((domainname_t*)inp, idx);
87 : }
88 : int
89 0 : domainname_set_name(domainname_t *inp, size_t idx, char elt)
90 : {
91 0 : TRUNNEL_DYNARRAY_SET(&inp->name, idx, elt);
92 0 : return 0;
93 : }
94 : int
95 0 : domainname_add_name(domainname_t *inp, char elt)
96 : {
97 : #if SIZE_MAX >= UINT8_MAX
98 0 : if (inp->name.n_ == UINT8_MAX)
99 0 : goto trunnel_alloc_failed;
100 : #endif
101 0 : TRUNNEL_DYNARRAY_ADD(char, &inp->name, elt, {});
102 0 : return 0;
103 0 : trunnel_alloc_failed:
104 0 : TRUNNEL_SET_ERROR_CODE(inp);
105 0 : return -1;
106 : }
107 :
108 : char *
109 9 : domainname_getarray_name(domainname_t *inp)
110 : {
111 9 : return inp->name.elts_;
112 : }
113 : const char *
114 9 : domainname_getconstarray_name(const domainname_t *inp)
115 : {
116 9 : return (const char *)domainname_getarray_name((domainname_t*)inp);
117 : }
118 : int
119 0 : domainname_setlen_name(domainname_t *inp, size_t newlen)
120 : {
121 : #if UINT8_MAX < SIZE_MAX
122 0 : if (newlen > UINT8_MAX)
123 0 : goto trunnel_alloc_failed;
124 : #endif
125 0 : return trunnel_string_setlen(&inp->name, newlen,
126 : &inp->trunnel_error_code_);
127 0 : trunnel_alloc_failed:
128 0 : TRUNNEL_SET_ERROR_CODE(inp);
129 0 : return -1;
130 : }
131 : const char *
132 0 : domainname_getstr_name(domainname_t *inp)
133 : {
134 0 : return trunnel_string_getstr(&inp->name);
135 : }
136 : int
137 15 : domainname_setstr0_name(domainname_t *inp, const char *val, size_t len)
138 : {
139 : #if UINT8_MAX < SIZE_MAX
140 15 : if (len > UINT8_MAX) {
141 0 : TRUNNEL_SET_ERROR_CODE(inp);
142 0 : return -1;
143 : }
144 : #endif
145 15 : return trunnel_string_setstr0(&inp->name, val, len, &inp->trunnel_error_code_);
146 : }
147 : int
148 0 : domainname_setstr_name(domainname_t *inp, const char *val)
149 : {
150 0 : return domainname_setstr0_name(inp, val, strlen(val));
151 : }
152 : const char *
153 0 : domainname_check(const domainname_t *obj)
154 : {
155 0 : if (obj == NULL)
156 : return "Object was NULL";
157 0 : if (obj->trunnel_error_code_)
158 : return "A set function failed on this object";
159 0 : if (TRUNNEL_DYNARRAY_LEN(&obj->name) != obj->len)
160 0 : return "Length mismatch for name";
161 : return NULL;
162 : }
163 :
164 : ssize_t
165 0 : domainname_encoded_len(const domainname_t *obj)
166 : {
167 0 : ssize_t result = 0;
168 :
169 0 : if (NULL != domainname_check(obj))
170 : return -1;
171 :
172 :
173 : /* Length of u8 len */
174 0 : result += 1;
175 :
176 : /* Length of char name[len] */
177 0 : result += TRUNNEL_DYNARRAY_LEN(&obj->name);
178 0 : return result;
179 : }
180 : int
181 0 : domainname_clear_errors(domainname_t *obj)
182 : {
183 0 : int r = obj->trunnel_error_code_;
184 0 : obj->trunnel_error_code_ = 0;
185 0 : return r;
186 : }
187 : ssize_t
188 0 : domainname_encode(uint8_t *output, const size_t avail, const domainname_t *obj)
189 : {
190 0 : ssize_t result = 0;
191 0 : size_t written = 0;
192 0 : uint8_t *ptr = output;
193 0 : const char *msg;
194 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
195 : const ssize_t encoded_len = domainname_encoded_len(obj);
196 : #endif
197 :
198 0 : if (NULL != (msg = domainname_check(obj)))
199 0 : goto check_failed;
200 :
201 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
202 : trunnel_assert(encoded_len >= 0);
203 : #endif
204 :
205 : /* Encode u8 len */
206 0 : trunnel_assert(written <= avail);
207 0 : if (avail - written < 1)
208 0 : goto truncated;
209 0 : trunnel_set_uint8(ptr, (obj->len));
210 0 : written += 1; ptr += 1;
211 :
212 : /* Encode char name[len] */
213 : {
214 0 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->name);
215 0 : trunnel_assert(obj->len == elt_len);
216 0 : trunnel_assert(written <= avail);
217 0 : if (avail - written < elt_len)
218 0 : goto truncated;
219 0 : if (elt_len)
220 0 : memcpy(ptr, obj->name.elts_, elt_len);
221 0 : written += elt_len; ptr += elt_len;
222 : }
223 :
224 :
225 0 : trunnel_assert(ptr == output + written);
226 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
227 : {
228 : trunnel_assert(encoded_len >= 0);
229 : trunnel_assert((size_t)encoded_len == written);
230 : }
231 :
232 : #endif
233 :
234 0 : return written;
235 :
236 0 : truncated:
237 0 : result = -2;
238 0 : goto fail;
239 0 : check_failed:
240 0 : (void)msg;
241 0 : result = -1;
242 0 : goto fail;
243 : fail:
244 : trunnel_assert(result < 0);
245 : return result;
246 : }
247 :
248 : /** As domainname_parse(), but do not allocate the output object.
249 : */
250 : static ssize_t
251 290 : domainname_parse_into(domainname_t *obj, const uint8_t *input, const size_t len_in)
252 : {
253 290 : const uint8_t *ptr = input;
254 290 : size_t remaining = len_in;
255 290 : ssize_t result = 0;
256 290 : (void)result;
257 :
258 : /* Parse u8 len */
259 290 : CHECK_REMAINING(1, truncated);
260 287 : obj->len = (trunnel_get_uint8(ptr));
261 287 : remaining -= 1; ptr += 1;
262 :
263 : /* Parse char name[len] */
264 287 : CHECK_REMAINING(obj->len, truncated);
265 15 : if (domainname_setstr0_name(obj, (const char*)ptr, obj->len))
266 0 : goto fail;
267 15 : ptr += obj->len; remaining -= obj->len;
268 15 : trunnel_assert(ptr + remaining == input + len_in);
269 15 : return len_in - remaining;
270 :
271 : truncated:
272 : return -2;
273 0 : fail:
274 0 : result = -1;
275 0 : return result;
276 : }
277 :
278 : ssize_t
279 290 : domainname_parse(domainname_t **output, const uint8_t *input, const size_t len_in)
280 : {
281 290 : ssize_t result;
282 290 : *output = domainname_new();
283 290 : if (NULL == *output)
284 : return -1;
285 290 : result = domainname_parse_into(*output, input, len_in);
286 290 : if (result < 0) {
287 275 : domainname_free(*output);
288 275 : *output = NULL;
289 : }
290 : return result;
291 : }
292 : socks4_client_request_t *
293 53 : socks4_client_request_new(void)
294 : {
295 53 : socks4_client_request_t *val = trunnel_calloc(1, sizeof(socks4_client_request_t));
296 53 : if (NULL == val)
297 : return NULL;
298 53 : val->version = 4;
299 53 : val->command = CMD_BIND;
300 53 : return val;
301 : }
302 :
303 : /** Release all storage held inside 'obj', but do not free 'obj'.
304 : */
305 : static void
306 53 : socks4_client_request_clear(socks4_client_request_t *obj)
307 : {
308 53 : (void) obj;
309 53 : trunnel_wipestr(obj->username);
310 53 : trunnel_free(obj->username);
311 53 : trunnel_wipestr(obj->socks4a_addr_hostname);
312 53 : trunnel_free(obj->socks4a_addr_hostname);
313 53 : }
314 :
315 : void
316 98 : socks4_client_request_free(socks4_client_request_t *obj)
317 : {
318 98 : if (obj == NULL)
319 : return;
320 53 : socks4_client_request_clear(obj);
321 53 : trunnel_memwipe(obj, sizeof(socks4_client_request_t));
322 53 : trunnel_free_(obj);
323 : }
324 :
325 : uint8_t
326 0 : socks4_client_request_get_version(const socks4_client_request_t *inp)
327 : {
328 0 : return inp->version;
329 : }
330 : int
331 0 : socks4_client_request_set_version(socks4_client_request_t *inp, uint8_t val)
332 : {
333 0 : if (! ((val == 4))) {
334 0 : TRUNNEL_SET_ERROR_CODE(inp);
335 0 : return -1;
336 : }
337 0 : inp->version = val;
338 0 : return 0;
339 : }
340 : uint8_t
341 8 : socks4_client_request_get_command(const socks4_client_request_t *inp)
342 : {
343 8 : return inp->command;
344 : }
345 : int
346 0 : socks4_client_request_set_command(socks4_client_request_t *inp, uint8_t val)
347 : {
348 0 : if (! ((val == CMD_BIND || val == CMD_CONNECT || val == CMD_RESOLVE || val == CMD_RESOLVE_PTR))) {
349 0 : TRUNNEL_SET_ERROR_CODE(inp);
350 0 : return -1;
351 : }
352 0 : inp->command = val;
353 0 : return 0;
354 : }
355 : uint16_t
356 8 : socks4_client_request_get_port(const socks4_client_request_t *inp)
357 : {
358 8 : return inp->port;
359 : }
360 : int
361 0 : socks4_client_request_set_port(socks4_client_request_t *inp, uint16_t val)
362 : {
363 0 : inp->port = val;
364 0 : return 0;
365 : }
366 : uint32_t
367 8 : socks4_client_request_get_addr(const socks4_client_request_t *inp)
368 : {
369 8 : return inp->addr;
370 : }
371 : int
372 0 : socks4_client_request_set_addr(socks4_client_request_t *inp, uint32_t val)
373 : {
374 0 : inp->addr = val;
375 0 : return 0;
376 : }
377 : const char *
378 6 : socks4_client_request_get_username(const socks4_client_request_t *inp)
379 : {
380 6 : return inp->username;
381 : }
382 : int
383 0 : socks4_client_request_set_username(socks4_client_request_t *inp, const char *val)
384 : {
385 0 : trunnel_free(inp->username);
386 0 : if (NULL == (inp->username = trunnel_strdup(val))) {
387 0 : TRUNNEL_SET_ERROR_CODE(inp);
388 0 : return -1;
389 : }
390 : return 0;
391 : }
392 : const char *
393 2 : socks4_client_request_get_socks4a_addr_hostname(const socks4_client_request_t *inp)
394 : {
395 2 : return inp->socks4a_addr_hostname;
396 : }
397 : int
398 0 : socks4_client_request_set_socks4a_addr_hostname(socks4_client_request_t *inp, const char *val)
399 : {
400 0 : trunnel_free(inp->socks4a_addr_hostname);
401 0 : if (NULL == (inp->socks4a_addr_hostname = trunnel_strdup(val))) {
402 0 : TRUNNEL_SET_ERROR_CODE(inp);
403 0 : return -1;
404 : }
405 : return 0;
406 : }
407 : const char *
408 0 : socks4_client_request_check(const socks4_client_request_t *obj)
409 : {
410 0 : if (obj == NULL)
411 : return "Object was NULL";
412 0 : if (obj->trunnel_error_code_)
413 : return "A set function failed on this object";
414 0 : if (! (obj->version == 4))
415 : return "Integer out of bounds";
416 0 : if (! (obj->command == CMD_BIND || obj->command == CMD_CONNECT || obj->command == CMD_RESOLVE || obj->command == CMD_RESOLVE_PTR))
417 : return "Integer out of bounds";
418 0 : if (NULL == obj->username)
419 : return "Missing username";
420 0 : switch (obj->addr) {
421 :
422 0 : case 1:
423 : case 2:
424 : case 3:
425 : case 4:
426 : case 5:
427 : case 6:
428 : case 7:
429 : case 8:
430 : case 9:
431 : case 10:
432 : case 11:
433 : case 12:
434 : case 13:
435 : case 14:
436 : case 15:
437 : case 16:
438 : case 17:
439 : case 18:
440 : case 19:
441 : case 20:
442 : case 21:
443 : case 22:
444 : case 23:
445 : case 24:
446 : case 25:
447 : case 26:
448 : case 27:
449 : case 28:
450 : case 29:
451 : case 30:
452 : case 31:
453 : case 32:
454 : case 33:
455 : case 34:
456 : case 35:
457 : case 36:
458 : case 37:
459 : case 38:
460 : case 39:
461 : case 40:
462 : case 41:
463 : case 42:
464 : case 43:
465 : case 44:
466 : case 45:
467 : case 46:
468 : case 47:
469 : case 48:
470 : case 49:
471 : case 50:
472 : case 51:
473 : case 52:
474 : case 53:
475 : case 54:
476 : case 55:
477 : case 56:
478 : case 57:
479 : case 58:
480 : case 59:
481 : case 60:
482 : case 61:
483 : case 62:
484 : case 63:
485 : case 64:
486 : case 65:
487 : case 66:
488 : case 67:
489 : case 68:
490 : case 69:
491 : case 70:
492 : case 71:
493 : case 72:
494 : case 73:
495 : case 74:
496 : case 75:
497 : case 76:
498 : case 77:
499 : case 78:
500 : case 79:
501 : case 80:
502 : case 81:
503 : case 82:
504 : case 83:
505 : case 84:
506 : case 85:
507 : case 86:
508 : case 87:
509 : case 88:
510 : case 89:
511 : case 90:
512 : case 91:
513 : case 92:
514 : case 93:
515 : case 94:
516 : case 95:
517 : case 96:
518 : case 97:
519 : case 98:
520 : case 99:
521 : case 100:
522 : case 101:
523 : case 102:
524 : case 103:
525 : case 104:
526 : case 105:
527 : case 106:
528 : case 107:
529 : case 108:
530 : case 109:
531 : case 110:
532 : case 111:
533 : case 112:
534 : case 113:
535 : case 114:
536 : case 115:
537 : case 116:
538 : case 117:
539 : case 118:
540 : case 119:
541 : case 120:
542 : case 121:
543 : case 122:
544 : case 123:
545 : case 124:
546 : case 125:
547 : case 126:
548 : case 127:
549 : case 128:
550 : case 129:
551 : case 130:
552 : case 131:
553 : case 132:
554 : case 133:
555 : case 134:
556 : case 135:
557 : case 136:
558 : case 137:
559 : case 138:
560 : case 139:
561 : case 140:
562 : case 141:
563 : case 142:
564 : case 143:
565 : case 144:
566 : case 145:
567 : case 146:
568 : case 147:
569 : case 148:
570 : case 149:
571 : case 150:
572 : case 151:
573 : case 152:
574 : case 153:
575 : case 154:
576 : case 155:
577 : case 156:
578 : case 157:
579 : case 158:
580 : case 159:
581 : case 160:
582 : case 161:
583 : case 162:
584 : case 163:
585 : case 164:
586 : case 165:
587 : case 166:
588 : case 167:
589 : case 168:
590 : case 169:
591 : case 170:
592 : case 171:
593 : case 172:
594 : case 173:
595 : case 174:
596 : case 175:
597 : case 176:
598 : case 177:
599 : case 178:
600 : case 179:
601 : case 180:
602 : case 181:
603 : case 182:
604 : case 183:
605 : case 184:
606 : case 185:
607 : case 186:
608 : case 187:
609 : case 188:
610 : case 189:
611 : case 190:
612 : case 191:
613 : case 192:
614 : case 193:
615 : case 194:
616 : case 195:
617 : case 196:
618 : case 197:
619 : case 198:
620 : case 199:
621 : case 200:
622 : case 201:
623 : case 202:
624 : case 203:
625 : case 204:
626 : case 205:
627 : case 206:
628 : case 207:
629 : case 208:
630 : case 209:
631 : case 210:
632 : case 211:
633 : case 212:
634 : case 213:
635 : case 214:
636 : case 215:
637 : case 216:
638 : case 217:
639 : case 218:
640 : case 219:
641 : case 220:
642 : case 221:
643 : case 222:
644 : case 223:
645 : case 224:
646 : case 225:
647 : case 226:
648 : case 227:
649 : case 228:
650 : case 229:
651 : case 230:
652 : case 231:
653 : case 232:
654 : case 233:
655 : case 234:
656 : case 235:
657 : case 236:
658 : case 237:
659 : case 238:
660 : case 239:
661 : case 240:
662 : case 241:
663 : case 242:
664 : case 243:
665 : case 244:
666 : case 245:
667 : case 246:
668 : case 247:
669 : case 248:
670 : case 249:
671 : case 250:
672 : case 251:
673 : case 252:
674 : case 253:
675 : case 254:
676 : case 255:
677 0 : if (NULL == obj->socks4a_addr_hostname)
678 0 : return "Missing socks4a_addr_hostname";
679 : break;
680 :
681 : default:
682 : break;
683 : }
684 : return NULL;
685 : }
686 :
687 : ssize_t
688 0 : socks4_client_request_encoded_len(const socks4_client_request_t *obj)
689 : {
690 0 : ssize_t result = 0;
691 :
692 0 : if (NULL != socks4_client_request_check(obj))
693 : return -1;
694 :
695 :
696 : /* Length of u8 version IN [4] */
697 0 : result += 1;
698 :
699 : /* Length of u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR] */
700 0 : result += 1;
701 :
702 : /* Length of u16 port */
703 0 : result += 2;
704 :
705 : /* Length of u32 addr */
706 0 : result += 4;
707 :
708 : /* Length of nulterm username */
709 0 : result += strlen(obj->username) + 1;
710 0 : switch (obj->addr) {
711 :
712 0 : case 1:
713 : case 2:
714 : case 3:
715 : case 4:
716 : case 5:
717 : case 6:
718 : case 7:
719 : case 8:
720 : case 9:
721 : case 10:
722 : case 11:
723 : case 12:
724 : case 13:
725 : case 14:
726 : case 15:
727 : case 16:
728 : case 17:
729 : case 18:
730 : case 19:
731 : case 20:
732 : case 21:
733 : case 22:
734 : case 23:
735 : case 24:
736 : case 25:
737 : case 26:
738 : case 27:
739 : case 28:
740 : case 29:
741 : case 30:
742 : case 31:
743 : case 32:
744 : case 33:
745 : case 34:
746 : case 35:
747 : case 36:
748 : case 37:
749 : case 38:
750 : case 39:
751 : case 40:
752 : case 41:
753 : case 42:
754 : case 43:
755 : case 44:
756 : case 45:
757 : case 46:
758 : case 47:
759 : case 48:
760 : case 49:
761 : case 50:
762 : case 51:
763 : case 52:
764 : case 53:
765 : case 54:
766 : case 55:
767 : case 56:
768 : case 57:
769 : case 58:
770 : case 59:
771 : case 60:
772 : case 61:
773 : case 62:
774 : case 63:
775 : case 64:
776 : case 65:
777 : case 66:
778 : case 67:
779 : case 68:
780 : case 69:
781 : case 70:
782 : case 71:
783 : case 72:
784 : case 73:
785 : case 74:
786 : case 75:
787 : case 76:
788 : case 77:
789 : case 78:
790 : case 79:
791 : case 80:
792 : case 81:
793 : case 82:
794 : case 83:
795 : case 84:
796 : case 85:
797 : case 86:
798 : case 87:
799 : case 88:
800 : case 89:
801 : case 90:
802 : case 91:
803 : case 92:
804 : case 93:
805 : case 94:
806 : case 95:
807 : case 96:
808 : case 97:
809 : case 98:
810 : case 99:
811 : case 100:
812 : case 101:
813 : case 102:
814 : case 103:
815 : case 104:
816 : case 105:
817 : case 106:
818 : case 107:
819 : case 108:
820 : case 109:
821 : case 110:
822 : case 111:
823 : case 112:
824 : case 113:
825 : case 114:
826 : case 115:
827 : case 116:
828 : case 117:
829 : case 118:
830 : case 119:
831 : case 120:
832 : case 121:
833 : case 122:
834 : case 123:
835 : case 124:
836 : case 125:
837 : case 126:
838 : case 127:
839 : case 128:
840 : case 129:
841 : case 130:
842 : case 131:
843 : case 132:
844 : case 133:
845 : case 134:
846 : case 135:
847 : case 136:
848 : case 137:
849 : case 138:
850 : case 139:
851 : case 140:
852 : case 141:
853 : case 142:
854 : case 143:
855 : case 144:
856 : case 145:
857 : case 146:
858 : case 147:
859 : case 148:
860 : case 149:
861 : case 150:
862 : case 151:
863 : case 152:
864 : case 153:
865 : case 154:
866 : case 155:
867 : case 156:
868 : case 157:
869 : case 158:
870 : case 159:
871 : case 160:
872 : case 161:
873 : case 162:
874 : case 163:
875 : case 164:
876 : case 165:
877 : case 166:
878 : case 167:
879 : case 168:
880 : case 169:
881 : case 170:
882 : case 171:
883 : case 172:
884 : case 173:
885 : case 174:
886 : case 175:
887 : case 176:
888 : case 177:
889 : case 178:
890 : case 179:
891 : case 180:
892 : case 181:
893 : case 182:
894 : case 183:
895 : case 184:
896 : case 185:
897 : case 186:
898 : case 187:
899 : case 188:
900 : case 189:
901 : case 190:
902 : case 191:
903 : case 192:
904 : case 193:
905 : case 194:
906 : case 195:
907 : case 196:
908 : case 197:
909 : case 198:
910 : case 199:
911 : case 200:
912 : case 201:
913 : case 202:
914 : case 203:
915 : case 204:
916 : case 205:
917 : case 206:
918 : case 207:
919 : case 208:
920 : case 209:
921 : case 210:
922 : case 211:
923 : case 212:
924 : case 213:
925 : case 214:
926 : case 215:
927 : case 216:
928 : case 217:
929 : case 218:
930 : case 219:
931 : case 220:
932 : case 221:
933 : case 222:
934 : case 223:
935 : case 224:
936 : case 225:
937 : case 226:
938 : case 227:
939 : case 228:
940 : case 229:
941 : case 230:
942 : case 231:
943 : case 232:
944 : case 233:
945 : case 234:
946 : case 235:
947 : case 236:
948 : case 237:
949 : case 238:
950 : case 239:
951 : case 240:
952 : case 241:
953 : case 242:
954 : case 243:
955 : case 244:
956 : case 245:
957 : case 246:
958 : case 247:
959 : case 248:
960 : case 249:
961 : case 250:
962 : case 251:
963 : case 252:
964 : case 253:
965 : case 254:
966 : case 255:
967 :
968 : /* Length of nulterm socks4a_addr_hostname */
969 0 : result += strlen(obj->socks4a_addr_hostname) + 1;
970 0 : break;
971 :
972 : default:
973 : break;
974 : }
975 : return result;
976 : }
977 : int
978 0 : socks4_client_request_clear_errors(socks4_client_request_t *obj)
979 : {
980 0 : int r = obj->trunnel_error_code_;
981 0 : obj->trunnel_error_code_ = 0;
982 0 : return r;
983 : }
984 : ssize_t
985 0 : socks4_client_request_encode(uint8_t *output, const size_t avail, const socks4_client_request_t *obj)
986 : {
987 0 : ssize_t result = 0;
988 0 : size_t written = 0;
989 0 : uint8_t *ptr = output;
990 0 : const char *msg;
991 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
992 : const ssize_t encoded_len = socks4_client_request_encoded_len(obj);
993 : #endif
994 :
995 0 : if (NULL != (msg = socks4_client_request_check(obj)))
996 0 : goto check_failed;
997 :
998 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
999 : trunnel_assert(encoded_len >= 0);
1000 : #endif
1001 :
1002 : /* Encode u8 version IN [4] */
1003 0 : trunnel_assert(written <= avail);
1004 0 : if (avail - written < 1)
1005 0 : goto truncated;
1006 0 : trunnel_set_uint8(ptr, (obj->version));
1007 0 : written += 1; ptr += 1;
1008 :
1009 : /* Encode u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR] */
1010 0 : trunnel_assert(written <= avail);
1011 0 : if (avail - written < 1)
1012 0 : goto truncated;
1013 0 : trunnel_set_uint8(ptr, (obj->command));
1014 0 : written += 1; ptr += 1;
1015 :
1016 : /* Encode u16 port */
1017 0 : trunnel_assert(written <= avail);
1018 0 : if (avail - written < 2)
1019 0 : goto truncated;
1020 0 : trunnel_set_uint16(ptr, trunnel_htons(obj->port));
1021 0 : written += 2; ptr += 2;
1022 :
1023 : /* Encode u32 addr */
1024 0 : trunnel_assert(written <= avail);
1025 0 : if (avail - written < 4)
1026 0 : goto truncated;
1027 0 : trunnel_set_uint32(ptr, trunnel_htonl(obj->addr));
1028 0 : written += 4; ptr += 4;
1029 :
1030 : /* Encode nulterm username */
1031 : {
1032 0 : size_t len = strlen(obj->username);
1033 0 : trunnel_assert(written <= avail);
1034 0 : if (avail - written < len + 1)
1035 0 : goto truncated;
1036 0 : memcpy(ptr, obj->username, len + 1);
1037 0 : ptr += len + 1; written += len + 1;
1038 : }
1039 :
1040 : /* Encode union socks4a_addr[addr] */
1041 0 : trunnel_assert(written <= avail);
1042 0 : switch (obj->addr) {
1043 :
1044 0 : case 1:
1045 : case 2:
1046 : case 3:
1047 : case 4:
1048 : case 5:
1049 : case 6:
1050 : case 7:
1051 : case 8:
1052 : case 9:
1053 : case 10:
1054 : case 11:
1055 : case 12:
1056 : case 13:
1057 : case 14:
1058 : case 15:
1059 : case 16:
1060 : case 17:
1061 : case 18:
1062 : case 19:
1063 : case 20:
1064 : case 21:
1065 : case 22:
1066 : case 23:
1067 : case 24:
1068 : case 25:
1069 : case 26:
1070 : case 27:
1071 : case 28:
1072 : case 29:
1073 : case 30:
1074 : case 31:
1075 : case 32:
1076 : case 33:
1077 : case 34:
1078 : case 35:
1079 : case 36:
1080 : case 37:
1081 : case 38:
1082 : case 39:
1083 : case 40:
1084 : case 41:
1085 : case 42:
1086 : case 43:
1087 : case 44:
1088 : case 45:
1089 : case 46:
1090 : case 47:
1091 : case 48:
1092 : case 49:
1093 : case 50:
1094 : case 51:
1095 : case 52:
1096 : case 53:
1097 : case 54:
1098 : case 55:
1099 : case 56:
1100 : case 57:
1101 : case 58:
1102 : case 59:
1103 : case 60:
1104 : case 61:
1105 : case 62:
1106 : case 63:
1107 : case 64:
1108 : case 65:
1109 : case 66:
1110 : case 67:
1111 : case 68:
1112 : case 69:
1113 : case 70:
1114 : case 71:
1115 : case 72:
1116 : case 73:
1117 : case 74:
1118 : case 75:
1119 : case 76:
1120 : case 77:
1121 : case 78:
1122 : case 79:
1123 : case 80:
1124 : case 81:
1125 : case 82:
1126 : case 83:
1127 : case 84:
1128 : case 85:
1129 : case 86:
1130 : case 87:
1131 : case 88:
1132 : case 89:
1133 : case 90:
1134 : case 91:
1135 : case 92:
1136 : case 93:
1137 : case 94:
1138 : case 95:
1139 : case 96:
1140 : case 97:
1141 : case 98:
1142 : case 99:
1143 : case 100:
1144 : case 101:
1145 : case 102:
1146 : case 103:
1147 : case 104:
1148 : case 105:
1149 : case 106:
1150 : case 107:
1151 : case 108:
1152 : case 109:
1153 : case 110:
1154 : case 111:
1155 : case 112:
1156 : case 113:
1157 : case 114:
1158 : case 115:
1159 : case 116:
1160 : case 117:
1161 : case 118:
1162 : case 119:
1163 : case 120:
1164 : case 121:
1165 : case 122:
1166 : case 123:
1167 : case 124:
1168 : case 125:
1169 : case 126:
1170 : case 127:
1171 : case 128:
1172 : case 129:
1173 : case 130:
1174 : case 131:
1175 : case 132:
1176 : case 133:
1177 : case 134:
1178 : case 135:
1179 : case 136:
1180 : case 137:
1181 : case 138:
1182 : case 139:
1183 : case 140:
1184 : case 141:
1185 : case 142:
1186 : case 143:
1187 : case 144:
1188 : case 145:
1189 : case 146:
1190 : case 147:
1191 : case 148:
1192 : case 149:
1193 : case 150:
1194 : case 151:
1195 : case 152:
1196 : case 153:
1197 : case 154:
1198 : case 155:
1199 : case 156:
1200 : case 157:
1201 : case 158:
1202 : case 159:
1203 : case 160:
1204 : case 161:
1205 : case 162:
1206 : case 163:
1207 : case 164:
1208 : case 165:
1209 : case 166:
1210 : case 167:
1211 : case 168:
1212 : case 169:
1213 : case 170:
1214 : case 171:
1215 : case 172:
1216 : case 173:
1217 : case 174:
1218 : case 175:
1219 : case 176:
1220 : case 177:
1221 : case 178:
1222 : case 179:
1223 : case 180:
1224 : case 181:
1225 : case 182:
1226 : case 183:
1227 : case 184:
1228 : case 185:
1229 : case 186:
1230 : case 187:
1231 : case 188:
1232 : case 189:
1233 : case 190:
1234 : case 191:
1235 : case 192:
1236 : case 193:
1237 : case 194:
1238 : case 195:
1239 : case 196:
1240 : case 197:
1241 : case 198:
1242 : case 199:
1243 : case 200:
1244 : case 201:
1245 : case 202:
1246 : case 203:
1247 : case 204:
1248 : case 205:
1249 : case 206:
1250 : case 207:
1251 : case 208:
1252 : case 209:
1253 : case 210:
1254 : case 211:
1255 : case 212:
1256 : case 213:
1257 : case 214:
1258 : case 215:
1259 : case 216:
1260 : case 217:
1261 : case 218:
1262 : case 219:
1263 : case 220:
1264 : case 221:
1265 : case 222:
1266 : case 223:
1267 : case 224:
1268 : case 225:
1269 : case 226:
1270 : case 227:
1271 : case 228:
1272 : case 229:
1273 : case 230:
1274 : case 231:
1275 : case 232:
1276 : case 233:
1277 : case 234:
1278 : case 235:
1279 : case 236:
1280 : case 237:
1281 : case 238:
1282 : case 239:
1283 : case 240:
1284 : case 241:
1285 : case 242:
1286 : case 243:
1287 : case 244:
1288 : case 245:
1289 : case 246:
1290 : case 247:
1291 : case 248:
1292 : case 249:
1293 : case 250:
1294 : case 251:
1295 : case 252:
1296 : case 253:
1297 : case 254:
1298 : case 255:
1299 :
1300 : /* Encode nulterm socks4a_addr_hostname */
1301 : {
1302 0 : size_t len = strlen(obj->socks4a_addr_hostname);
1303 0 : trunnel_assert(written <= avail);
1304 0 : if (avail - written < len + 1)
1305 0 : goto truncated;
1306 0 : memcpy(ptr, obj->socks4a_addr_hostname, len + 1);
1307 0 : ptr += len + 1; written += len + 1;
1308 : }
1309 0 : break;
1310 :
1311 : default:
1312 : break;
1313 : }
1314 :
1315 :
1316 0 : trunnel_assert(ptr == output + written);
1317 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1318 : {
1319 : trunnel_assert(encoded_len >= 0);
1320 : trunnel_assert((size_t)encoded_len == written);
1321 : }
1322 :
1323 : #endif
1324 :
1325 0 : return written;
1326 :
1327 0 : truncated:
1328 0 : result = -2;
1329 0 : goto fail;
1330 0 : check_failed:
1331 0 : (void)msg;
1332 0 : result = -1;
1333 0 : goto fail;
1334 : fail:
1335 : trunnel_assert(result < 0);
1336 : return result;
1337 : }
1338 :
1339 : /** As socks4_client_request_parse(), but do not allocate the output
1340 : * object.
1341 : */
1342 : static ssize_t
1343 53 : socks4_client_request_parse_into(socks4_client_request_t *obj, const uint8_t *input, const size_t len_in)
1344 : {
1345 53 : const uint8_t *ptr = input;
1346 53 : size_t remaining = len_in;
1347 53 : ssize_t result = 0;
1348 53 : (void)result;
1349 :
1350 : /* Parse u8 version IN [4] */
1351 53 : CHECK_REMAINING(1, truncated);
1352 53 : obj->version = (trunnel_get_uint8(ptr));
1353 53 : remaining -= 1; ptr += 1;
1354 53 : if (! (obj->version == 4))
1355 0 : goto fail;
1356 :
1357 : /* Parse u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR] */
1358 53 : CHECK_REMAINING(1, truncated);
1359 53 : obj->command = (trunnel_get_uint8(ptr));
1360 53 : remaining -= 1; ptr += 1;
1361 53 : if (! (obj->command == CMD_BIND || obj->command == CMD_CONNECT || obj->command == CMD_RESOLVE || obj->command == CMD_RESOLVE_PTR))
1362 0 : goto fail;
1363 :
1364 : /* Parse u16 port */
1365 53 : CHECK_REMAINING(2, truncated);
1366 53 : obj->port = trunnel_ntohs(trunnel_get_uint16(ptr));
1367 53 : remaining -= 2; ptr += 2;
1368 :
1369 : /* Parse u32 addr */
1370 53 : CHECK_REMAINING(4, truncated);
1371 53 : obj->addr = trunnel_ntohl(trunnel_get_uint32(ptr));
1372 53 : remaining -= 4; ptr += 4;
1373 :
1374 : /* Parse nulterm username */
1375 : {
1376 53 : uint8_t *eos = (uint8_t*)memchr(ptr, 0, remaining);
1377 53 : size_t memlen;
1378 53 : if (eos == NULL)
1379 12 : goto truncated;
1380 41 : trunnel_assert(eos >= ptr);
1381 41 : trunnel_assert((size_t)(eos - ptr) < SIZE_MAX - 1);
1382 41 : memlen = ((size_t)(eos - ptr)) + 1;
1383 41 : if (!(obj->username = trunnel_malloc(memlen)))
1384 0 : goto fail;
1385 41 : memcpy(obj->username, ptr, memlen);
1386 41 : remaining -= memlen; ptr += memlen;
1387 : }
1388 :
1389 : /* Parse union socks4a_addr[addr] */
1390 41 : switch (obj->addr) {
1391 :
1392 36 : case 1:
1393 : case 2:
1394 : case 3:
1395 : case 4:
1396 : case 5:
1397 : case 6:
1398 : case 7:
1399 : case 8:
1400 : case 9:
1401 : case 10:
1402 : case 11:
1403 : case 12:
1404 : case 13:
1405 : case 14:
1406 : case 15:
1407 : case 16:
1408 : case 17:
1409 : case 18:
1410 : case 19:
1411 : case 20:
1412 : case 21:
1413 : case 22:
1414 : case 23:
1415 : case 24:
1416 : case 25:
1417 : case 26:
1418 : case 27:
1419 : case 28:
1420 : case 29:
1421 : case 30:
1422 : case 31:
1423 : case 32:
1424 : case 33:
1425 : case 34:
1426 : case 35:
1427 : case 36:
1428 : case 37:
1429 : case 38:
1430 : case 39:
1431 : case 40:
1432 : case 41:
1433 : case 42:
1434 : case 43:
1435 : case 44:
1436 : case 45:
1437 : case 46:
1438 : case 47:
1439 : case 48:
1440 : case 49:
1441 : case 50:
1442 : case 51:
1443 : case 52:
1444 : case 53:
1445 : case 54:
1446 : case 55:
1447 : case 56:
1448 : case 57:
1449 : case 58:
1450 : case 59:
1451 : case 60:
1452 : case 61:
1453 : case 62:
1454 : case 63:
1455 : case 64:
1456 : case 65:
1457 : case 66:
1458 : case 67:
1459 : case 68:
1460 : case 69:
1461 : case 70:
1462 : case 71:
1463 : case 72:
1464 : case 73:
1465 : case 74:
1466 : case 75:
1467 : case 76:
1468 : case 77:
1469 : case 78:
1470 : case 79:
1471 : case 80:
1472 : case 81:
1473 : case 82:
1474 : case 83:
1475 : case 84:
1476 : case 85:
1477 : case 86:
1478 : case 87:
1479 : case 88:
1480 : case 89:
1481 : case 90:
1482 : case 91:
1483 : case 92:
1484 : case 93:
1485 : case 94:
1486 : case 95:
1487 : case 96:
1488 : case 97:
1489 : case 98:
1490 : case 99:
1491 : case 100:
1492 : case 101:
1493 : case 102:
1494 : case 103:
1495 : case 104:
1496 : case 105:
1497 : case 106:
1498 : case 107:
1499 : case 108:
1500 : case 109:
1501 : case 110:
1502 : case 111:
1503 : case 112:
1504 : case 113:
1505 : case 114:
1506 : case 115:
1507 : case 116:
1508 : case 117:
1509 : case 118:
1510 : case 119:
1511 : case 120:
1512 : case 121:
1513 : case 122:
1514 : case 123:
1515 : case 124:
1516 : case 125:
1517 : case 126:
1518 : case 127:
1519 : case 128:
1520 : case 129:
1521 : case 130:
1522 : case 131:
1523 : case 132:
1524 : case 133:
1525 : case 134:
1526 : case 135:
1527 : case 136:
1528 : case 137:
1529 : case 138:
1530 : case 139:
1531 : case 140:
1532 : case 141:
1533 : case 142:
1534 : case 143:
1535 : case 144:
1536 : case 145:
1537 : case 146:
1538 : case 147:
1539 : case 148:
1540 : case 149:
1541 : case 150:
1542 : case 151:
1543 : case 152:
1544 : case 153:
1545 : case 154:
1546 : case 155:
1547 : case 156:
1548 : case 157:
1549 : case 158:
1550 : case 159:
1551 : case 160:
1552 : case 161:
1553 : case 162:
1554 : case 163:
1555 : case 164:
1556 : case 165:
1557 : case 166:
1558 : case 167:
1559 : case 168:
1560 : case 169:
1561 : case 170:
1562 : case 171:
1563 : case 172:
1564 : case 173:
1565 : case 174:
1566 : case 175:
1567 : case 176:
1568 : case 177:
1569 : case 178:
1570 : case 179:
1571 : case 180:
1572 : case 181:
1573 : case 182:
1574 : case 183:
1575 : case 184:
1576 : case 185:
1577 : case 186:
1578 : case 187:
1579 : case 188:
1580 : case 189:
1581 : case 190:
1582 : case 191:
1583 : case 192:
1584 : case 193:
1585 : case 194:
1586 : case 195:
1587 : case 196:
1588 : case 197:
1589 : case 198:
1590 : case 199:
1591 : case 200:
1592 : case 201:
1593 : case 202:
1594 : case 203:
1595 : case 204:
1596 : case 205:
1597 : case 206:
1598 : case 207:
1599 : case 208:
1600 : case 209:
1601 : case 210:
1602 : case 211:
1603 : case 212:
1604 : case 213:
1605 : case 214:
1606 : case 215:
1607 : case 216:
1608 : case 217:
1609 : case 218:
1610 : case 219:
1611 : case 220:
1612 : case 221:
1613 : case 222:
1614 : case 223:
1615 : case 224:
1616 : case 225:
1617 : case 226:
1618 : case 227:
1619 : case 228:
1620 : case 229:
1621 : case 230:
1622 : case 231:
1623 : case 232:
1624 : case 233:
1625 : case 234:
1626 : case 235:
1627 : case 236:
1628 : case 237:
1629 : case 238:
1630 : case 239:
1631 : case 240:
1632 : case 241:
1633 : case 242:
1634 : case 243:
1635 : case 244:
1636 : case 245:
1637 : case 246:
1638 : case 247:
1639 : case 248:
1640 : case 249:
1641 : case 250:
1642 : case 251:
1643 : case 252:
1644 : case 253:
1645 : case 254:
1646 : case 255:
1647 :
1648 : /* Parse nulterm socks4a_addr_hostname */
1649 : {
1650 36 : uint8_t *eos = (uint8_t*)memchr(ptr, 0, remaining);
1651 36 : size_t memlen;
1652 36 : if (eos == NULL)
1653 33 : goto truncated;
1654 3 : trunnel_assert(eos >= ptr);
1655 3 : trunnel_assert((size_t)(eos - ptr) < SIZE_MAX - 1);
1656 3 : memlen = ((size_t)(eos - ptr)) + 1;
1657 3 : if (!(obj->socks4a_addr_hostname = trunnel_malloc(memlen)))
1658 0 : goto fail;
1659 3 : memcpy(obj->socks4a_addr_hostname, ptr, memlen);
1660 3 : remaining -= memlen; ptr += memlen;
1661 : }
1662 3 : break;
1663 :
1664 : default:
1665 : break;
1666 : }
1667 8 : trunnel_assert(ptr + remaining == input + len_in);
1668 8 : return len_in - remaining;
1669 :
1670 : truncated:
1671 : return -2;
1672 : fail:
1673 53 : result = -1;
1674 : return result;
1675 : }
1676 :
1677 : ssize_t
1678 53 : socks4_client_request_parse(socks4_client_request_t **output, const uint8_t *input, const size_t len_in)
1679 : {
1680 53 : ssize_t result;
1681 53 : *output = socks4_client_request_new();
1682 53 : if (NULL == *output)
1683 : return -1;
1684 53 : result = socks4_client_request_parse_into(*output, input, len_in);
1685 53 : if (result < 0) {
1686 45 : socks4_client_request_free(*output);
1687 45 : *output = NULL;
1688 : }
1689 : return result;
1690 : }
1691 : socks4_server_reply_t *
1692 0 : socks4_server_reply_new(void)
1693 : {
1694 0 : socks4_server_reply_t *val = trunnel_calloc(1, sizeof(socks4_server_reply_t));
1695 0 : if (NULL == val)
1696 0 : return NULL;
1697 : return val;
1698 : }
1699 :
1700 : /** Release all storage held inside 'obj', but do not free 'obj'.
1701 : */
1702 : static void
1703 : socks4_server_reply_clear(socks4_server_reply_t *obj)
1704 : {
1705 : (void) obj;
1706 : }
1707 :
1708 : void
1709 0 : socks4_server_reply_free(socks4_server_reply_t *obj)
1710 : {
1711 0 : if (obj == NULL)
1712 : return;
1713 0 : socks4_server_reply_clear(obj);
1714 0 : trunnel_memwipe(obj, sizeof(socks4_server_reply_t));
1715 0 : trunnel_free_(obj);
1716 : }
1717 :
1718 : uint8_t
1719 0 : socks4_server_reply_get_version(const socks4_server_reply_t *inp)
1720 : {
1721 0 : return inp->version;
1722 : }
1723 : int
1724 0 : socks4_server_reply_set_version(socks4_server_reply_t *inp, uint8_t val)
1725 : {
1726 0 : if (! ((val == 0 || val == 4))) {
1727 0 : TRUNNEL_SET_ERROR_CODE(inp);
1728 0 : return -1;
1729 : }
1730 0 : inp->version = val;
1731 0 : return 0;
1732 : }
1733 : uint8_t
1734 0 : socks4_server_reply_get_status(const socks4_server_reply_t *inp)
1735 : {
1736 0 : return inp->status;
1737 : }
1738 : int
1739 0 : socks4_server_reply_set_status(socks4_server_reply_t *inp, uint8_t val)
1740 : {
1741 0 : inp->status = val;
1742 0 : return 0;
1743 : }
1744 : uint16_t
1745 0 : socks4_server_reply_get_port(const socks4_server_reply_t *inp)
1746 : {
1747 0 : return inp->port;
1748 : }
1749 : int
1750 0 : socks4_server_reply_set_port(socks4_server_reply_t *inp, uint16_t val)
1751 : {
1752 0 : inp->port = val;
1753 0 : return 0;
1754 : }
1755 : uint32_t
1756 0 : socks4_server_reply_get_addr(const socks4_server_reply_t *inp)
1757 : {
1758 0 : return inp->addr;
1759 : }
1760 : int
1761 0 : socks4_server_reply_set_addr(socks4_server_reply_t *inp, uint32_t val)
1762 : {
1763 0 : inp->addr = val;
1764 0 : return 0;
1765 : }
1766 : const char *
1767 0 : socks4_server_reply_check(const socks4_server_reply_t *obj)
1768 : {
1769 0 : if (obj == NULL)
1770 : return "Object was NULL";
1771 0 : if (obj->trunnel_error_code_)
1772 : return "A set function failed on this object";
1773 0 : if (! (obj->version == 0 || obj->version == 4))
1774 0 : return "Integer out of bounds";
1775 : return NULL;
1776 : }
1777 :
1778 : ssize_t
1779 0 : socks4_server_reply_encoded_len(const socks4_server_reply_t *obj)
1780 : {
1781 0 : ssize_t result = 0;
1782 :
1783 0 : if (NULL != socks4_server_reply_check(obj))
1784 0 : return -1;
1785 :
1786 :
1787 : /* Length of u8 version IN [0, 4] */
1788 : result += 1;
1789 :
1790 : /* Length of u8 status */
1791 : result += 1;
1792 :
1793 : /* Length of u16 port */
1794 : result += 2;
1795 :
1796 : /* Length of u32 addr */
1797 0 : result += 4;
1798 : return result;
1799 : }
1800 : int
1801 0 : socks4_server_reply_clear_errors(socks4_server_reply_t *obj)
1802 : {
1803 0 : int r = obj->trunnel_error_code_;
1804 0 : obj->trunnel_error_code_ = 0;
1805 0 : return r;
1806 : }
1807 : ssize_t
1808 0 : socks4_server_reply_encode(uint8_t *output, const size_t avail, const socks4_server_reply_t *obj)
1809 : {
1810 0 : ssize_t result = 0;
1811 0 : size_t written = 0;
1812 0 : uint8_t *ptr = output;
1813 0 : const char *msg;
1814 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1815 : const ssize_t encoded_len = socks4_server_reply_encoded_len(obj);
1816 : #endif
1817 :
1818 0 : if (NULL != (msg = socks4_server_reply_check(obj)))
1819 0 : goto check_failed;
1820 :
1821 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1822 : trunnel_assert(encoded_len >= 0);
1823 : #endif
1824 :
1825 : /* Encode u8 version IN [0, 4] */
1826 0 : trunnel_assert(written <= avail);
1827 0 : if (avail - written < 1)
1828 0 : goto truncated;
1829 0 : trunnel_set_uint8(ptr, (obj->version));
1830 0 : written += 1; ptr += 1;
1831 :
1832 : /* Encode u8 status */
1833 0 : trunnel_assert(written <= avail);
1834 0 : if (avail - written < 1)
1835 0 : goto truncated;
1836 0 : trunnel_set_uint8(ptr, (obj->status));
1837 0 : written += 1; ptr += 1;
1838 :
1839 : /* Encode u16 port */
1840 0 : trunnel_assert(written <= avail);
1841 0 : if (avail - written < 2)
1842 0 : goto truncated;
1843 0 : trunnel_set_uint16(ptr, trunnel_htons(obj->port));
1844 0 : written += 2; ptr += 2;
1845 :
1846 : /* Encode u32 addr */
1847 0 : trunnel_assert(written <= avail);
1848 0 : if (avail - written < 4)
1849 0 : goto truncated;
1850 0 : trunnel_set_uint32(ptr, trunnel_htonl(obj->addr));
1851 0 : written += 4; ptr += 4;
1852 :
1853 :
1854 0 : trunnel_assert(ptr == output + written);
1855 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1856 : {
1857 : trunnel_assert(encoded_len >= 0);
1858 : trunnel_assert((size_t)encoded_len == written);
1859 : }
1860 :
1861 : #endif
1862 :
1863 : return written;
1864 :
1865 0 : truncated:
1866 0 : result = -2;
1867 0 : goto fail;
1868 0 : check_failed:
1869 0 : (void)msg;
1870 0 : result = -1;
1871 0 : goto fail;
1872 : fail:
1873 : trunnel_assert(result < 0);
1874 : return result;
1875 : }
1876 :
1877 : /** As socks4_server_reply_parse(), but do not allocate the output
1878 : * object.
1879 : */
1880 : static ssize_t
1881 0 : socks4_server_reply_parse_into(socks4_server_reply_t *obj, const uint8_t *input, const size_t len_in)
1882 : {
1883 0 : const uint8_t *ptr = input;
1884 0 : size_t remaining = len_in;
1885 0 : ssize_t result = 0;
1886 0 : (void)result;
1887 :
1888 : /* Parse u8 version IN [0, 4] */
1889 0 : CHECK_REMAINING(1, truncated);
1890 0 : obj->version = (trunnel_get_uint8(ptr));
1891 0 : remaining -= 1; ptr += 1;
1892 0 : if (! (obj->version == 0 || obj->version == 4))
1893 0 : goto fail;
1894 :
1895 : /* Parse u8 status */
1896 0 : CHECK_REMAINING(1, truncated);
1897 0 : obj->status = (trunnel_get_uint8(ptr));
1898 0 : remaining -= 1; ptr += 1;
1899 :
1900 : /* Parse u16 port */
1901 0 : CHECK_REMAINING(2, truncated);
1902 0 : obj->port = trunnel_ntohs(trunnel_get_uint16(ptr));
1903 0 : remaining -= 2; ptr += 2;
1904 :
1905 : /* Parse u32 addr */
1906 0 : CHECK_REMAINING(4, truncated);
1907 0 : obj->addr = trunnel_ntohl(trunnel_get_uint32(ptr));
1908 0 : remaining -= 4; ptr += 4;
1909 0 : trunnel_assert(ptr + remaining == input + len_in);
1910 : return len_in - remaining;
1911 :
1912 : truncated:
1913 : return -2;
1914 0 : fail:
1915 0 : result = -1;
1916 0 : return result;
1917 : }
1918 :
1919 : ssize_t
1920 0 : socks4_server_reply_parse(socks4_server_reply_t **output, const uint8_t *input, const size_t len_in)
1921 : {
1922 0 : ssize_t result;
1923 0 : *output = socks4_server_reply_new();
1924 0 : if (NULL == *output)
1925 : return -1;
1926 0 : result = socks4_server_reply_parse_into(*output, input, len_in);
1927 0 : if (result < 0) {
1928 0 : socks4_server_reply_free(*output);
1929 0 : *output = NULL;
1930 : }
1931 : return result;
1932 : }
1933 : socks5_client_userpass_auth_t *
1934 520 : socks5_client_userpass_auth_new(void)
1935 : {
1936 520 : socks5_client_userpass_auth_t *val = trunnel_calloc(1, sizeof(socks5_client_userpass_auth_t));
1937 520 : if (NULL == val)
1938 : return NULL;
1939 520 : val->version = 1;
1940 520 : return val;
1941 : }
1942 :
1943 : /** Release all storage held inside 'obj', but do not free 'obj'.
1944 : */
1945 : static void
1946 520 : socks5_client_userpass_auth_clear(socks5_client_userpass_auth_t *obj)
1947 : {
1948 520 : (void) obj;
1949 520 : TRUNNEL_DYNARRAY_WIPE(&obj->username);
1950 520 : TRUNNEL_DYNARRAY_CLEAR(&obj->username);
1951 520 : TRUNNEL_DYNARRAY_WIPE(&obj->passwd);
1952 520 : TRUNNEL_DYNARRAY_CLEAR(&obj->passwd);
1953 520 : }
1954 :
1955 : void
1956 1035 : socks5_client_userpass_auth_free(socks5_client_userpass_auth_t *obj)
1957 : {
1958 1035 : if (obj == NULL)
1959 : return;
1960 520 : socks5_client_userpass_auth_clear(obj);
1961 520 : trunnel_memwipe(obj, sizeof(socks5_client_userpass_auth_t));
1962 520 : trunnel_free_(obj);
1963 : }
1964 :
1965 : uint8_t
1966 0 : socks5_client_userpass_auth_get_version(const socks5_client_userpass_auth_t *inp)
1967 : {
1968 0 : return inp->version;
1969 : }
1970 : int
1971 0 : socks5_client_userpass_auth_set_version(socks5_client_userpass_auth_t *inp, uint8_t val)
1972 : {
1973 0 : if (! ((val == 1))) {
1974 0 : TRUNNEL_SET_ERROR_CODE(inp);
1975 0 : return -1;
1976 : }
1977 0 : inp->version = val;
1978 0 : return 0;
1979 : }
1980 : uint8_t
1981 5 : socks5_client_userpass_auth_get_username_len(const socks5_client_userpass_auth_t *inp)
1982 : {
1983 5 : return inp->username_len;
1984 : }
1985 : int
1986 0 : socks5_client_userpass_auth_set_username_len(socks5_client_userpass_auth_t *inp, uint8_t val)
1987 : {
1988 0 : inp->username_len = val;
1989 0 : return 0;
1990 : }
1991 : size_t
1992 0 : socks5_client_userpass_auth_getlen_username(const socks5_client_userpass_auth_t *inp)
1993 : {
1994 0 : return TRUNNEL_DYNARRAY_LEN(&inp->username);
1995 : }
1996 :
1997 : char
1998 0 : socks5_client_userpass_auth_get_username(socks5_client_userpass_auth_t *inp, size_t idx)
1999 : {
2000 0 : return TRUNNEL_DYNARRAY_GET(&inp->username, idx);
2001 : }
2002 :
2003 : char
2004 0 : socks5_client_userpass_auth_getconst_username(const socks5_client_userpass_auth_t *inp, size_t idx)
2005 : {
2006 0 : return socks5_client_userpass_auth_get_username((socks5_client_userpass_auth_t*)inp, idx);
2007 : }
2008 : int
2009 0 : socks5_client_userpass_auth_set_username(socks5_client_userpass_auth_t *inp, size_t idx, char elt)
2010 : {
2011 0 : TRUNNEL_DYNARRAY_SET(&inp->username, idx, elt);
2012 0 : return 0;
2013 : }
2014 : int
2015 0 : socks5_client_userpass_auth_add_username(socks5_client_userpass_auth_t *inp, char elt)
2016 : {
2017 : #if SIZE_MAX >= UINT8_MAX
2018 0 : if (inp->username.n_ == UINT8_MAX)
2019 0 : goto trunnel_alloc_failed;
2020 : #endif
2021 0 : TRUNNEL_DYNARRAY_ADD(char, &inp->username, elt, {});
2022 0 : return 0;
2023 0 : trunnel_alloc_failed:
2024 0 : TRUNNEL_SET_ERROR_CODE(inp);
2025 0 : return -1;
2026 : }
2027 :
2028 : char *
2029 5 : socks5_client_userpass_auth_getarray_username(socks5_client_userpass_auth_t *inp)
2030 : {
2031 5 : return inp->username.elts_;
2032 : }
2033 : const char *
2034 5 : socks5_client_userpass_auth_getconstarray_username(const socks5_client_userpass_auth_t *inp)
2035 : {
2036 5 : return (const char *)socks5_client_userpass_auth_getarray_username((socks5_client_userpass_auth_t*)inp);
2037 : }
2038 : int
2039 0 : socks5_client_userpass_auth_setlen_username(socks5_client_userpass_auth_t *inp, size_t newlen)
2040 : {
2041 : #if UINT8_MAX < SIZE_MAX
2042 0 : if (newlen > UINT8_MAX)
2043 0 : goto trunnel_alloc_failed;
2044 : #endif
2045 0 : return trunnel_string_setlen(&inp->username, newlen,
2046 : &inp->trunnel_error_code_);
2047 0 : trunnel_alloc_failed:
2048 0 : TRUNNEL_SET_ERROR_CODE(inp);
2049 0 : return -1;
2050 : }
2051 : const char *
2052 0 : socks5_client_userpass_auth_getstr_username(socks5_client_userpass_auth_t *inp)
2053 : {
2054 0 : return trunnel_string_getstr(&inp->username);
2055 : }
2056 : int
2057 264 : socks5_client_userpass_auth_setstr0_username(socks5_client_userpass_auth_t *inp, const char *val, size_t len)
2058 : {
2059 : #if UINT8_MAX < SIZE_MAX
2060 264 : if (len > UINT8_MAX) {
2061 0 : TRUNNEL_SET_ERROR_CODE(inp);
2062 0 : return -1;
2063 : }
2064 : #endif
2065 264 : return trunnel_string_setstr0(&inp->username, val, len, &inp->trunnel_error_code_);
2066 : }
2067 : int
2068 0 : socks5_client_userpass_auth_setstr_username(socks5_client_userpass_auth_t *inp, const char *val)
2069 : {
2070 0 : return socks5_client_userpass_auth_setstr0_username(inp, val, strlen(val));
2071 : }
2072 : uint8_t
2073 5 : socks5_client_userpass_auth_get_passwd_len(const socks5_client_userpass_auth_t *inp)
2074 : {
2075 5 : return inp->passwd_len;
2076 : }
2077 : int
2078 0 : socks5_client_userpass_auth_set_passwd_len(socks5_client_userpass_auth_t *inp, uint8_t val)
2079 : {
2080 0 : inp->passwd_len = val;
2081 0 : return 0;
2082 : }
2083 : size_t
2084 0 : socks5_client_userpass_auth_getlen_passwd(const socks5_client_userpass_auth_t *inp)
2085 : {
2086 0 : return TRUNNEL_DYNARRAY_LEN(&inp->passwd);
2087 : }
2088 :
2089 : char
2090 0 : socks5_client_userpass_auth_get_passwd(socks5_client_userpass_auth_t *inp, size_t idx)
2091 : {
2092 0 : return TRUNNEL_DYNARRAY_GET(&inp->passwd, idx);
2093 : }
2094 :
2095 : char
2096 0 : socks5_client_userpass_auth_getconst_passwd(const socks5_client_userpass_auth_t *inp, size_t idx)
2097 : {
2098 0 : return socks5_client_userpass_auth_get_passwd((socks5_client_userpass_auth_t*)inp, idx);
2099 : }
2100 : int
2101 0 : socks5_client_userpass_auth_set_passwd(socks5_client_userpass_auth_t *inp, size_t idx, char elt)
2102 : {
2103 0 : TRUNNEL_DYNARRAY_SET(&inp->passwd, idx, elt);
2104 0 : return 0;
2105 : }
2106 : int
2107 0 : socks5_client_userpass_auth_add_passwd(socks5_client_userpass_auth_t *inp, char elt)
2108 : {
2109 : #if SIZE_MAX >= UINT8_MAX
2110 0 : if (inp->passwd.n_ == UINT8_MAX)
2111 0 : goto trunnel_alloc_failed;
2112 : #endif
2113 0 : TRUNNEL_DYNARRAY_ADD(char, &inp->passwd, elt, {});
2114 0 : return 0;
2115 0 : trunnel_alloc_failed:
2116 0 : TRUNNEL_SET_ERROR_CODE(inp);
2117 0 : return -1;
2118 : }
2119 :
2120 : char *
2121 5 : socks5_client_userpass_auth_getarray_passwd(socks5_client_userpass_auth_t *inp)
2122 : {
2123 5 : return inp->passwd.elts_;
2124 : }
2125 : const char *
2126 5 : socks5_client_userpass_auth_getconstarray_passwd(const socks5_client_userpass_auth_t *inp)
2127 : {
2128 5 : return (const char *)socks5_client_userpass_auth_getarray_passwd((socks5_client_userpass_auth_t*)inp);
2129 : }
2130 : int
2131 0 : socks5_client_userpass_auth_setlen_passwd(socks5_client_userpass_auth_t *inp, size_t newlen)
2132 : {
2133 : #if UINT8_MAX < SIZE_MAX
2134 0 : if (newlen > UINT8_MAX)
2135 0 : goto trunnel_alloc_failed;
2136 : #endif
2137 0 : return trunnel_string_setlen(&inp->passwd, newlen,
2138 : &inp->trunnel_error_code_);
2139 0 : trunnel_alloc_failed:
2140 0 : TRUNNEL_SET_ERROR_CODE(inp);
2141 0 : return -1;
2142 : }
2143 : const char *
2144 0 : socks5_client_userpass_auth_getstr_passwd(socks5_client_userpass_auth_t *inp)
2145 : {
2146 0 : return trunnel_string_getstr(&inp->passwd);
2147 : }
2148 : int
2149 5 : socks5_client_userpass_auth_setstr0_passwd(socks5_client_userpass_auth_t *inp, const char *val, size_t len)
2150 : {
2151 : #if UINT8_MAX < SIZE_MAX
2152 5 : if (len > UINT8_MAX) {
2153 0 : TRUNNEL_SET_ERROR_CODE(inp);
2154 0 : return -1;
2155 : }
2156 : #endif
2157 5 : return trunnel_string_setstr0(&inp->passwd, val, len, &inp->trunnel_error_code_);
2158 : }
2159 : int
2160 0 : socks5_client_userpass_auth_setstr_passwd(socks5_client_userpass_auth_t *inp, const char *val)
2161 : {
2162 0 : return socks5_client_userpass_auth_setstr0_passwd(inp, val, strlen(val));
2163 : }
2164 : const char *
2165 0 : socks5_client_userpass_auth_check(const socks5_client_userpass_auth_t *obj)
2166 : {
2167 0 : if (obj == NULL)
2168 : return "Object was NULL";
2169 0 : if (obj->trunnel_error_code_)
2170 : return "A set function failed on this object";
2171 0 : if (! (obj->version == 1))
2172 : return "Integer out of bounds";
2173 0 : if (TRUNNEL_DYNARRAY_LEN(&obj->username) != obj->username_len)
2174 : return "Length mismatch for username";
2175 0 : if (TRUNNEL_DYNARRAY_LEN(&obj->passwd) != obj->passwd_len)
2176 0 : return "Length mismatch for passwd";
2177 : return NULL;
2178 : }
2179 :
2180 : ssize_t
2181 0 : socks5_client_userpass_auth_encoded_len(const socks5_client_userpass_auth_t *obj)
2182 : {
2183 0 : ssize_t result = 0;
2184 :
2185 0 : if (NULL != socks5_client_userpass_auth_check(obj))
2186 : return -1;
2187 :
2188 :
2189 : /* Length of u8 version IN [1] */
2190 0 : result += 1;
2191 :
2192 : /* Length of u8 username_len */
2193 0 : result += 1;
2194 :
2195 : /* Length of char username[username_len] */
2196 0 : result += TRUNNEL_DYNARRAY_LEN(&obj->username);
2197 :
2198 : /* Length of u8 passwd_len */
2199 0 : result += 1;
2200 :
2201 : /* Length of char passwd[passwd_len] */
2202 0 : result += TRUNNEL_DYNARRAY_LEN(&obj->passwd);
2203 0 : return result;
2204 : }
2205 : int
2206 0 : socks5_client_userpass_auth_clear_errors(socks5_client_userpass_auth_t *obj)
2207 : {
2208 0 : int r = obj->trunnel_error_code_;
2209 0 : obj->trunnel_error_code_ = 0;
2210 0 : return r;
2211 : }
2212 : ssize_t
2213 0 : socks5_client_userpass_auth_encode(uint8_t *output, const size_t avail, const socks5_client_userpass_auth_t *obj)
2214 : {
2215 0 : ssize_t result = 0;
2216 0 : size_t written = 0;
2217 0 : uint8_t *ptr = output;
2218 0 : const char *msg;
2219 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2220 : const ssize_t encoded_len = socks5_client_userpass_auth_encoded_len(obj);
2221 : #endif
2222 :
2223 0 : if (NULL != (msg = socks5_client_userpass_auth_check(obj)))
2224 0 : goto check_failed;
2225 :
2226 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2227 : trunnel_assert(encoded_len >= 0);
2228 : #endif
2229 :
2230 : /* Encode u8 version IN [1] */
2231 0 : trunnel_assert(written <= avail);
2232 0 : if (avail - written < 1)
2233 0 : goto truncated;
2234 0 : trunnel_set_uint8(ptr, (obj->version));
2235 0 : written += 1; ptr += 1;
2236 :
2237 : /* Encode u8 username_len */
2238 0 : trunnel_assert(written <= avail);
2239 0 : if (avail - written < 1)
2240 0 : goto truncated;
2241 0 : trunnel_set_uint8(ptr, (obj->username_len));
2242 0 : written += 1; ptr += 1;
2243 :
2244 : /* Encode char username[username_len] */
2245 : {
2246 0 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->username);
2247 0 : trunnel_assert(obj->username_len == elt_len);
2248 0 : trunnel_assert(written <= avail);
2249 0 : if (avail - written < elt_len)
2250 0 : goto truncated;
2251 0 : if (elt_len)
2252 0 : memcpy(ptr, obj->username.elts_, elt_len);
2253 0 : written += elt_len; ptr += elt_len;
2254 : }
2255 :
2256 : /* Encode u8 passwd_len */
2257 0 : trunnel_assert(written <= avail);
2258 0 : if (avail - written < 1)
2259 0 : goto truncated;
2260 0 : trunnel_set_uint8(ptr, (obj->passwd_len));
2261 0 : written += 1; ptr += 1;
2262 :
2263 : /* Encode char passwd[passwd_len] */
2264 : {
2265 0 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->passwd);
2266 0 : trunnel_assert(obj->passwd_len == elt_len);
2267 0 : trunnel_assert(written <= avail);
2268 0 : if (avail - written < elt_len)
2269 0 : goto truncated;
2270 0 : if (elt_len)
2271 0 : memcpy(ptr, obj->passwd.elts_, elt_len);
2272 0 : written += elt_len; ptr += elt_len;
2273 : }
2274 :
2275 :
2276 0 : trunnel_assert(ptr == output + written);
2277 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2278 : {
2279 : trunnel_assert(encoded_len >= 0);
2280 : trunnel_assert((size_t)encoded_len == written);
2281 : }
2282 :
2283 : #endif
2284 :
2285 0 : return written;
2286 :
2287 0 : truncated:
2288 0 : result = -2;
2289 0 : goto fail;
2290 0 : check_failed:
2291 0 : (void)msg;
2292 0 : result = -1;
2293 0 : goto fail;
2294 : fail:
2295 : trunnel_assert(result < 0);
2296 : return result;
2297 : }
2298 :
2299 : /** As socks5_client_userpass_auth_parse(), but do not allocate the
2300 : * output object.
2301 : */
2302 : static ssize_t
2303 520 : socks5_client_userpass_auth_parse_into(socks5_client_userpass_auth_t *obj, const uint8_t *input, const size_t len_in)
2304 : {
2305 520 : const uint8_t *ptr = input;
2306 520 : size_t remaining = len_in;
2307 520 : ssize_t result = 0;
2308 520 : (void)result;
2309 :
2310 : /* Parse u8 version IN [1] */
2311 520 : CHECK_REMAINING(1, truncated);
2312 520 : obj->version = (trunnel_get_uint8(ptr));
2313 520 : remaining -= 1; ptr += 1;
2314 520 : if (! (obj->version == 1))
2315 0 : goto fail;
2316 :
2317 : /* Parse u8 username_len */
2318 520 : CHECK_REMAINING(1, truncated);
2319 520 : obj->username_len = (trunnel_get_uint8(ptr));
2320 520 : remaining -= 1; ptr += 1;
2321 :
2322 : /* Parse char username[username_len] */
2323 520 : CHECK_REMAINING(obj->username_len, truncated);
2324 264 : if (socks5_client_userpass_auth_setstr0_username(obj, (const char*)ptr, obj->username_len))
2325 0 : goto fail;
2326 264 : ptr += obj->username_len; remaining -= obj->username_len;
2327 :
2328 : /* Parse u8 passwd_len */
2329 264 : CHECK_REMAINING(1, truncated);
2330 261 : obj->passwd_len = (trunnel_get_uint8(ptr));
2331 261 : remaining -= 1; ptr += 1;
2332 :
2333 : /* Parse char passwd[passwd_len] */
2334 261 : CHECK_REMAINING(obj->passwd_len, truncated);
2335 5 : if (socks5_client_userpass_auth_setstr0_passwd(obj, (const char*)ptr, obj->passwd_len))
2336 0 : goto fail;
2337 5 : ptr += obj->passwd_len; remaining -= obj->passwd_len;
2338 5 : trunnel_assert(ptr + remaining == input + len_in);
2339 5 : return len_in - remaining;
2340 :
2341 : truncated:
2342 : return -2;
2343 : fail:
2344 520 : result = -1;
2345 : return result;
2346 : }
2347 :
2348 : ssize_t
2349 520 : socks5_client_userpass_auth_parse(socks5_client_userpass_auth_t **output, const uint8_t *input, const size_t len_in)
2350 : {
2351 520 : ssize_t result;
2352 520 : *output = socks5_client_userpass_auth_new();
2353 520 : if (NULL == *output)
2354 : return -1;
2355 520 : result = socks5_client_userpass_auth_parse_into(*output, input, len_in);
2356 520 : if (result < 0) {
2357 515 : socks5_client_userpass_auth_free(*output);
2358 515 : *output = NULL;
2359 : }
2360 : return result;
2361 : }
2362 : socks5_client_version_t *
2363 872 : socks5_client_version_new(void)
2364 : {
2365 872 : socks5_client_version_t *val = trunnel_calloc(1, sizeof(socks5_client_version_t));
2366 872 : if (NULL == val)
2367 : return NULL;
2368 872 : val->version = 5;
2369 872 : return val;
2370 : }
2371 :
2372 : /** Release all storage held inside 'obj', but do not free 'obj'.
2373 : */
2374 : static void
2375 872 : socks5_client_version_clear(socks5_client_version_t *obj)
2376 : {
2377 872 : (void) obj;
2378 872 : TRUNNEL_DYNARRAY_WIPE(&obj->methods);
2379 872 : TRUNNEL_DYNARRAY_CLEAR(&obj->methods);
2380 872 : }
2381 :
2382 : void
2383 875 : socks5_client_version_free(socks5_client_version_t *obj)
2384 : {
2385 875 : if (obj == NULL)
2386 : return;
2387 872 : socks5_client_version_clear(obj);
2388 872 : trunnel_memwipe(obj, sizeof(socks5_client_version_t));
2389 872 : trunnel_free_(obj);
2390 : }
2391 :
2392 : uint8_t
2393 0 : socks5_client_version_get_version(const socks5_client_version_t *inp)
2394 : {
2395 0 : return inp->version;
2396 : }
2397 : int
2398 0 : socks5_client_version_set_version(socks5_client_version_t *inp, uint8_t val)
2399 : {
2400 0 : if (! ((val == 5))) {
2401 0 : TRUNNEL_SET_ERROR_CODE(inp);
2402 0 : return -1;
2403 : }
2404 0 : inp->version = val;
2405 0 : return 0;
2406 : }
2407 : uint8_t
2408 869 : socks5_client_version_get_n_methods(const socks5_client_version_t *inp)
2409 : {
2410 869 : return inp->n_methods;
2411 : }
2412 : int
2413 0 : socks5_client_version_set_n_methods(socks5_client_version_t *inp, uint8_t val)
2414 : {
2415 0 : inp->n_methods = val;
2416 0 : return 0;
2417 : }
2418 : size_t
2419 0 : socks5_client_version_getlen_methods(const socks5_client_version_t *inp)
2420 : {
2421 0 : return TRUNNEL_DYNARRAY_LEN(&inp->methods);
2422 : }
2423 :
2424 : uint8_t
2425 873 : socks5_client_version_get_methods(socks5_client_version_t *inp, size_t idx)
2426 : {
2427 873 : return TRUNNEL_DYNARRAY_GET(&inp->methods, idx);
2428 : }
2429 :
2430 : uint8_t
2431 0 : socks5_client_version_getconst_methods(const socks5_client_version_t *inp, size_t idx)
2432 : {
2433 0 : return socks5_client_version_get_methods((socks5_client_version_t*)inp, idx);
2434 : }
2435 : int
2436 0 : socks5_client_version_set_methods(socks5_client_version_t *inp, size_t idx, uint8_t elt)
2437 : {
2438 0 : TRUNNEL_DYNARRAY_SET(&inp->methods, idx, elt);
2439 0 : return 0;
2440 : }
2441 : int
2442 0 : socks5_client_version_add_methods(socks5_client_version_t *inp, uint8_t elt)
2443 : {
2444 : #if SIZE_MAX >= UINT8_MAX
2445 0 : if (inp->methods.n_ == UINT8_MAX)
2446 0 : goto trunnel_alloc_failed;
2447 : #endif
2448 0 : TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->methods, elt, {});
2449 0 : return 0;
2450 0 : trunnel_alloc_failed:
2451 0 : TRUNNEL_SET_ERROR_CODE(inp);
2452 0 : return -1;
2453 : }
2454 :
2455 : uint8_t *
2456 0 : socks5_client_version_getarray_methods(socks5_client_version_t *inp)
2457 : {
2458 0 : return inp->methods.elts_;
2459 : }
2460 : const uint8_t *
2461 0 : socks5_client_version_getconstarray_methods(const socks5_client_version_t *inp)
2462 : {
2463 0 : return (const uint8_t *)socks5_client_version_getarray_methods((socks5_client_version_t*)inp);
2464 : }
2465 : int
2466 0 : socks5_client_version_setlen_methods(socks5_client_version_t *inp, size_t newlen)
2467 : {
2468 0 : uint8_t *newptr;
2469 : #if UINT8_MAX < SIZE_MAX
2470 0 : if (newlen > UINT8_MAX)
2471 0 : goto trunnel_alloc_failed;
2472 : #endif
2473 0 : newptr = trunnel_dynarray_setlen(&inp->methods.allocated_,
2474 0 : &inp->methods.n_, inp->methods.elts_, newlen,
2475 : sizeof(inp->methods.elts_[0]), (trunnel_free_fn_t) NULL,
2476 : &inp->trunnel_error_code_);
2477 0 : if (newlen != 0 && newptr == NULL)
2478 0 : goto trunnel_alloc_failed;
2479 0 : inp->methods.elts_ = newptr;
2480 0 : return 0;
2481 0 : trunnel_alloc_failed:
2482 0 : TRUNNEL_SET_ERROR_CODE(inp);
2483 0 : return -1;
2484 : }
2485 : const char *
2486 0 : socks5_client_version_check(const socks5_client_version_t *obj)
2487 : {
2488 0 : if (obj == NULL)
2489 : return "Object was NULL";
2490 0 : if (obj->trunnel_error_code_)
2491 : return "A set function failed on this object";
2492 0 : if (! (obj->version == 5))
2493 : return "Integer out of bounds";
2494 0 : if (TRUNNEL_DYNARRAY_LEN(&obj->methods) != obj->n_methods)
2495 0 : return "Length mismatch for methods";
2496 : return NULL;
2497 : }
2498 :
2499 : ssize_t
2500 0 : socks5_client_version_encoded_len(const socks5_client_version_t *obj)
2501 : {
2502 0 : ssize_t result = 0;
2503 :
2504 0 : if (NULL != socks5_client_version_check(obj))
2505 : return -1;
2506 :
2507 :
2508 : /* Length of u8 version IN [5] */
2509 0 : result += 1;
2510 :
2511 : /* Length of u8 n_methods */
2512 0 : result += 1;
2513 :
2514 : /* Length of u8 methods[n_methods] */
2515 0 : result += TRUNNEL_DYNARRAY_LEN(&obj->methods);
2516 0 : return result;
2517 : }
2518 : int
2519 0 : socks5_client_version_clear_errors(socks5_client_version_t *obj)
2520 : {
2521 0 : int r = obj->trunnel_error_code_;
2522 0 : obj->trunnel_error_code_ = 0;
2523 0 : return r;
2524 : }
2525 : ssize_t
2526 0 : socks5_client_version_encode(uint8_t *output, const size_t avail, const socks5_client_version_t *obj)
2527 : {
2528 0 : ssize_t result = 0;
2529 0 : size_t written = 0;
2530 0 : uint8_t *ptr = output;
2531 0 : const char *msg;
2532 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2533 : const ssize_t encoded_len = socks5_client_version_encoded_len(obj);
2534 : #endif
2535 :
2536 0 : if (NULL != (msg = socks5_client_version_check(obj)))
2537 0 : goto check_failed;
2538 :
2539 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2540 : trunnel_assert(encoded_len >= 0);
2541 : #endif
2542 :
2543 : /* Encode u8 version IN [5] */
2544 0 : trunnel_assert(written <= avail);
2545 0 : if (avail - written < 1)
2546 0 : goto truncated;
2547 0 : trunnel_set_uint8(ptr, (obj->version));
2548 0 : written += 1; ptr += 1;
2549 :
2550 : /* Encode u8 n_methods */
2551 0 : trunnel_assert(written <= avail);
2552 0 : if (avail - written < 1)
2553 0 : goto truncated;
2554 0 : trunnel_set_uint8(ptr, (obj->n_methods));
2555 0 : written += 1; ptr += 1;
2556 :
2557 : /* Encode u8 methods[n_methods] */
2558 : {
2559 0 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->methods);
2560 0 : trunnel_assert(obj->n_methods == elt_len);
2561 0 : trunnel_assert(written <= avail);
2562 0 : if (avail - written < elt_len)
2563 0 : goto truncated;
2564 0 : if (elt_len)
2565 0 : memcpy(ptr, obj->methods.elts_, elt_len);
2566 0 : written += elt_len; ptr += elt_len;
2567 : }
2568 :
2569 :
2570 0 : trunnel_assert(ptr == output + written);
2571 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2572 : {
2573 : trunnel_assert(encoded_len >= 0);
2574 : trunnel_assert((size_t)encoded_len == written);
2575 : }
2576 :
2577 : #endif
2578 :
2579 0 : return written;
2580 :
2581 0 : truncated:
2582 0 : result = -2;
2583 0 : goto fail;
2584 0 : check_failed:
2585 0 : (void)msg;
2586 0 : result = -1;
2587 0 : goto fail;
2588 : fail:
2589 : trunnel_assert(result < 0);
2590 : return result;
2591 : }
2592 :
2593 : /** As socks5_client_version_parse(), but do not allocate the output
2594 : * object.
2595 : */
2596 : static ssize_t
2597 872 : socks5_client_version_parse_into(socks5_client_version_t *obj, const uint8_t *input, const size_t len_in)
2598 : {
2599 872 : const uint8_t *ptr = input;
2600 872 : size_t remaining = len_in;
2601 872 : ssize_t result = 0;
2602 872 : (void)result;
2603 :
2604 : /* Parse u8 version IN [5] */
2605 872 : CHECK_REMAINING(1, truncated);
2606 872 : obj->version = (trunnel_get_uint8(ptr));
2607 872 : remaining -= 1; ptr += 1;
2608 872 : if (! (obj->version == 5))
2609 0 : goto fail;
2610 :
2611 : /* Parse u8 n_methods */
2612 872 : CHECK_REMAINING(1, truncated);
2613 872 : obj->n_methods = (trunnel_get_uint8(ptr));
2614 872 : remaining -= 1; ptr += 1;
2615 :
2616 : /* Parse u8 methods[n_methods] */
2617 872 : CHECK_REMAINING(obj->n_methods, truncated);
2618 869 : TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->methods, obj->n_methods, {});
2619 869 : obj->methods.n_ = obj->n_methods;
2620 869 : if (obj->n_methods)
2621 869 : memcpy(obj->methods.elts_, ptr, obj->n_methods);
2622 869 : ptr += obj->n_methods; remaining -= obj->n_methods;
2623 869 : trunnel_assert(ptr + remaining == input + len_in);
2624 869 : return len_in - remaining;
2625 :
2626 : truncated:
2627 : return -2;
2628 0 : trunnel_alloc_failed:
2629 0 : return -1;
2630 0 : fail:
2631 0 : result = -1;
2632 0 : return result;
2633 : }
2634 :
2635 : ssize_t
2636 872 : socks5_client_version_parse(socks5_client_version_t **output, const uint8_t *input, const size_t len_in)
2637 : {
2638 872 : ssize_t result;
2639 872 : *output = socks5_client_version_new();
2640 872 : if (NULL == *output)
2641 : return -1;
2642 872 : result = socks5_client_version_parse_into(*output, input, len_in);
2643 872 : if (result < 0) {
2644 3 : socks5_client_version_free(*output);
2645 3 : *output = NULL;
2646 : }
2647 : return result;
2648 : }
2649 : socks5_server_method_t *
2650 869 : socks5_server_method_new(void)
2651 : {
2652 869 : socks5_server_method_t *val = trunnel_calloc(1, sizeof(socks5_server_method_t));
2653 869 : if (NULL == val)
2654 : return NULL;
2655 869 : val->version = 5;
2656 869 : return val;
2657 : }
2658 :
2659 : /** Release all storage held inside 'obj', but do not free 'obj'.
2660 : */
2661 : static void
2662 : socks5_server_method_clear(socks5_server_method_t *obj)
2663 : {
2664 : (void) obj;
2665 : }
2666 :
2667 : void
2668 869 : socks5_server_method_free(socks5_server_method_t *obj)
2669 : {
2670 869 : if (obj == NULL)
2671 : return;
2672 869 : socks5_server_method_clear(obj);
2673 869 : trunnel_memwipe(obj, sizeof(socks5_server_method_t));
2674 869 : trunnel_free_(obj);
2675 : }
2676 :
2677 : uint8_t
2678 0 : socks5_server_method_get_version(const socks5_server_method_t *inp)
2679 : {
2680 0 : return inp->version;
2681 : }
2682 : int
2683 869 : socks5_server_method_set_version(socks5_server_method_t *inp, uint8_t val)
2684 : {
2685 869 : if (! ((val == 5))) {
2686 0 : TRUNNEL_SET_ERROR_CODE(inp);
2687 0 : return -1;
2688 : }
2689 869 : inp->version = val;
2690 869 : return 0;
2691 : }
2692 : uint8_t
2693 0 : socks5_server_method_get_method(const socks5_server_method_t *inp)
2694 : {
2695 0 : return inp->method;
2696 : }
2697 : int
2698 869 : socks5_server_method_set_method(socks5_server_method_t *inp, uint8_t val)
2699 : {
2700 869 : inp->method = val;
2701 869 : return 0;
2702 : }
2703 : const char *
2704 1738 : socks5_server_method_check(const socks5_server_method_t *obj)
2705 : {
2706 1738 : if (obj == NULL)
2707 : return "Object was NULL";
2708 1738 : if (obj->trunnel_error_code_)
2709 : return "A set function failed on this object";
2710 1738 : if (! (obj->version == 5))
2711 0 : return "Integer out of bounds";
2712 : return NULL;
2713 : }
2714 :
2715 : ssize_t
2716 0 : socks5_server_method_encoded_len(const socks5_server_method_t *obj)
2717 : {
2718 0 : ssize_t result = 0;
2719 :
2720 0 : if (NULL != socks5_server_method_check(obj))
2721 0 : return -1;
2722 :
2723 :
2724 : /* Length of u8 version IN [5] */
2725 : result += 1;
2726 :
2727 : /* Length of u8 method */
2728 0 : result += 1;
2729 : return result;
2730 : }
2731 : int
2732 0 : socks5_server_method_clear_errors(socks5_server_method_t *obj)
2733 : {
2734 0 : int r = obj->trunnel_error_code_;
2735 0 : obj->trunnel_error_code_ = 0;
2736 0 : return r;
2737 : }
2738 : ssize_t
2739 869 : socks5_server_method_encode(uint8_t *output, const size_t avail, const socks5_server_method_t *obj)
2740 : {
2741 869 : ssize_t result = 0;
2742 869 : size_t written = 0;
2743 869 : uint8_t *ptr = output;
2744 869 : const char *msg;
2745 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2746 : const ssize_t encoded_len = socks5_server_method_encoded_len(obj);
2747 : #endif
2748 :
2749 869 : if (NULL != (msg = socks5_server_method_check(obj)))
2750 0 : goto check_failed;
2751 :
2752 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2753 : trunnel_assert(encoded_len >= 0);
2754 : #endif
2755 :
2756 : /* Encode u8 version IN [5] */
2757 869 : trunnel_assert(written <= avail);
2758 869 : if (avail - written < 1)
2759 0 : goto truncated;
2760 869 : trunnel_set_uint8(ptr, (obj->version));
2761 869 : written += 1; ptr += 1;
2762 :
2763 : /* Encode u8 method */
2764 869 : trunnel_assert(written <= avail);
2765 869 : if (avail - written < 1)
2766 0 : goto truncated;
2767 869 : trunnel_set_uint8(ptr, (obj->method));
2768 869 : written += 1; ptr += 1;
2769 :
2770 :
2771 869 : trunnel_assert(ptr == output + written);
2772 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2773 : {
2774 : trunnel_assert(encoded_len >= 0);
2775 : trunnel_assert((size_t)encoded_len == written);
2776 : }
2777 :
2778 : #endif
2779 :
2780 : return written;
2781 :
2782 0 : truncated:
2783 0 : result = -2;
2784 0 : goto fail;
2785 0 : check_failed:
2786 0 : (void)msg;
2787 0 : result = -1;
2788 0 : goto fail;
2789 : fail:
2790 : trunnel_assert(result < 0);
2791 : return result;
2792 : }
2793 :
2794 : /** As socks5_server_method_parse(), but do not allocate the output
2795 : * object.
2796 : */
2797 : static ssize_t
2798 0 : socks5_server_method_parse_into(socks5_server_method_t *obj, const uint8_t *input, const size_t len_in)
2799 : {
2800 0 : const uint8_t *ptr = input;
2801 0 : size_t remaining = len_in;
2802 0 : ssize_t result = 0;
2803 0 : (void)result;
2804 :
2805 : /* Parse u8 version IN [5] */
2806 0 : CHECK_REMAINING(1, truncated);
2807 0 : obj->version = (trunnel_get_uint8(ptr));
2808 0 : remaining -= 1; ptr += 1;
2809 0 : if (! (obj->version == 5))
2810 0 : goto fail;
2811 :
2812 : /* Parse u8 method */
2813 0 : CHECK_REMAINING(1, truncated);
2814 0 : obj->method = (trunnel_get_uint8(ptr));
2815 0 : remaining -= 1; ptr += 1;
2816 0 : trunnel_assert(ptr + remaining == input + len_in);
2817 : return len_in - remaining;
2818 :
2819 : truncated:
2820 : return -2;
2821 0 : fail:
2822 0 : result = -1;
2823 0 : return result;
2824 : }
2825 :
2826 : ssize_t
2827 0 : socks5_server_method_parse(socks5_server_method_t **output, const uint8_t *input, const size_t len_in)
2828 : {
2829 0 : ssize_t result;
2830 0 : *output = socks5_server_method_new();
2831 0 : if (NULL == *output)
2832 : return -1;
2833 0 : result = socks5_server_method_parse_into(*output, input, len_in);
2834 0 : if (result < 0) {
2835 0 : socks5_server_method_free(*output);
2836 0 : *output = NULL;
2837 : }
2838 : return result;
2839 : }
2840 : socks5_server_userpass_auth_t *
2841 5 : socks5_server_userpass_auth_new(void)
2842 : {
2843 5 : socks5_server_userpass_auth_t *val = trunnel_calloc(1, sizeof(socks5_server_userpass_auth_t));
2844 5 : if (NULL == val)
2845 : return NULL;
2846 5 : val->version = 1;
2847 5 : return val;
2848 : }
2849 :
2850 : /** Release all storage held inside 'obj', but do not free 'obj'.
2851 : */
2852 : static void
2853 : socks5_server_userpass_auth_clear(socks5_server_userpass_auth_t *obj)
2854 : {
2855 : (void) obj;
2856 : }
2857 :
2858 : void
2859 5 : socks5_server_userpass_auth_free(socks5_server_userpass_auth_t *obj)
2860 : {
2861 5 : if (obj == NULL)
2862 : return;
2863 5 : socks5_server_userpass_auth_clear(obj);
2864 5 : trunnel_memwipe(obj, sizeof(socks5_server_userpass_auth_t));
2865 5 : trunnel_free_(obj);
2866 : }
2867 :
2868 : uint8_t
2869 0 : socks5_server_userpass_auth_get_version(const socks5_server_userpass_auth_t *inp)
2870 : {
2871 0 : return inp->version;
2872 : }
2873 : int
2874 4 : socks5_server_userpass_auth_set_version(socks5_server_userpass_auth_t *inp, uint8_t val)
2875 : {
2876 4 : if (! ((val == 1))) {
2877 0 : TRUNNEL_SET_ERROR_CODE(inp);
2878 0 : return -1;
2879 : }
2880 4 : inp->version = val;
2881 4 : return 0;
2882 : }
2883 : uint8_t
2884 0 : socks5_server_userpass_auth_get_status(const socks5_server_userpass_auth_t *inp)
2885 : {
2886 0 : return inp->status;
2887 : }
2888 : int
2889 4 : socks5_server_userpass_auth_set_status(socks5_server_userpass_auth_t *inp, uint8_t val)
2890 : {
2891 4 : inp->status = val;
2892 4 : return 0;
2893 : }
2894 : const char *
2895 8 : socks5_server_userpass_auth_check(const socks5_server_userpass_auth_t *obj)
2896 : {
2897 8 : if (obj == NULL)
2898 : return "Object was NULL";
2899 8 : if (obj->trunnel_error_code_)
2900 : return "A set function failed on this object";
2901 8 : if (! (obj->version == 1))
2902 0 : return "Integer out of bounds";
2903 : return NULL;
2904 : }
2905 :
2906 : ssize_t
2907 0 : socks5_server_userpass_auth_encoded_len(const socks5_server_userpass_auth_t *obj)
2908 : {
2909 0 : ssize_t result = 0;
2910 :
2911 0 : if (NULL != socks5_server_userpass_auth_check(obj))
2912 0 : return -1;
2913 :
2914 :
2915 : /* Length of u8 version IN [1] */
2916 : result += 1;
2917 :
2918 : /* Length of u8 status */
2919 0 : result += 1;
2920 : return result;
2921 : }
2922 : int
2923 0 : socks5_server_userpass_auth_clear_errors(socks5_server_userpass_auth_t *obj)
2924 : {
2925 0 : int r = obj->trunnel_error_code_;
2926 0 : obj->trunnel_error_code_ = 0;
2927 0 : return r;
2928 : }
2929 : ssize_t
2930 4 : socks5_server_userpass_auth_encode(uint8_t *output, const size_t avail, const socks5_server_userpass_auth_t *obj)
2931 : {
2932 4 : ssize_t result = 0;
2933 4 : size_t written = 0;
2934 4 : uint8_t *ptr = output;
2935 4 : const char *msg;
2936 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2937 : const ssize_t encoded_len = socks5_server_userpass_auth_encoded_len(obj);
2938 : #endif
2939 :
2940 4 : if (NULL != (msg = socks5_server_userpass_auth_check(obj)))
2941 0 : goto check_failed;
2942 :
2943 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2944 : trunnel_assert(encoded_len >= 0);
2945 : #endif
2946 :
2947 : /* Encode u8 version IN [1] */
2948 4 : trunnel_assert(written <= avail);
2949 4 : if (avail - written < 1)
2950 0 : goto truncated;
2951 4 : trunnel_set_uint8(ptr, (obj->version));
2952 4 : written += 1; ptr += 1;
2953 :
2954 : /* Encode u8 status */
2955 4 : trunnel_assert(written <= avail);
2956 4 : if (avail - written < 1)
2957 0 : goto truncated;
2958 4 : trunnel_set_uint8(ptr, (obj->status));
2959 4 : written += 1; ptr += 1;
2960 :
2961 :
2962 4 : trunnel_assert(ptr == output + written);
2963 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2964 : {
2965 : trunnel_assert(encoded_len >= 0);
2966 : trunnel_assert((size_t)encoded_len == written);
2967 : }
2968 :
2969 : #endif
2970 :
2971 : return written;
2972 :
2973 0 : truncated:
2974 0 : result = -2;
2975 0 : goto fail;
2976 0 : check_failed:
2977 0 : (void)msg;
2978 0 : result = -1;
2979 0 : goto fail;
2980 : fail:
2981 : trunnel_assert(result < 0);
2982 : return result;
2983 : }
2984 :
2985 : /** As socks5_server_userpass_auth_parse(), but do not allocate the
2986 : * output object.
2987 : */
2988 : static ssize_t
2989 0 : socks5_server_userpass_auth_parse_into(socks5_server_userpass_auth_t *obj, const uint8_t *input, const size_t len_in)
2990 : {
2991 0 : const uint8_t *ptr = input;
2992 0 : size_t remaining = len_in;
2993 0 : ssize_t result = 0;
2994 0 : (void)result;
2995 :
2996 : /* Parse u8 version IN [1] */
2997 0 : CHECK_REMAINING(1, truncated);
2998 0 : obj->version = (trunnel_get_uint8(ptr));
2999 0 : remaining -= 1; ptr += 1;
3000 0 : if (! (obj->version == 1))
3001 0 : goto fail;
3002 :
3003 : /* Parse u8 status */
3004 0 : CHECK_REMAINING(1, truncated);
3005 0 : obj->status = (trunnel_get_uint8(ptr));
3006 0 : remaining -= 1; ptr += 1;
3007 0 : trunnel_assert(ptr + remaining == input + len_in);
3008 : return len_in - remaining;
3009 :
3010 : truncated:
3011 : return -2;
3012 0 : fail:
3013 0 : result = -1;
3014 0 : return result;
3015 : }
3016 :
3017 : ssize_t
3018 0 : socks5_server_userpass_auth_parse(socks5_server_userpass_auth_t **output, const uint8_t *input, const size_t len_in)
3019 : {
3020 0 : ssize_t result;
3021 0 : *output = socks5_server_userpass_auth_new();
3022 0 : if (NULL == *output)
3023 : return -1;
3024 0 : result = socks5_server_userpass_auth_parse_into(*output, input, len_in);
3025 0 : if (result < 0) {
3026 0 : socks5_server_userpass_auth_free(*output);
3027 0 : *output = NULL;
3028 : }
3029 : return result;
3030 : }
3031 : socks5_client_request_t *
3032 333 : socks5_client_request_new(void)
3033 : {
3034 333 : socks5_client_request_t *val = trunnel_calloc(1, sizeof(socks5_client_request_t));
3035 333 : if (NULL == val)
3036 : return NULL;
3037 333 : val->version = 5;
3038 333 : val->command = CMD_BIND;
3039 333 : return val;
3040 : }
3041 :
3042 : /** Release all storage held inside 'obj', but do not free 'obj'.
3043 : */
3044 : static void
3045 333 : socks5_client_request_clear(socks5_client_request_t *obj)
3046 : {
3047 333 : (void) obj;
3048 333 : domainname_free(obj->dest_addr_domainname);
3049 333 : obj->dest_addr_domainname = NULL;
3050 333 : }
3051 :
3052 : void
3053 649 : socks5_client_request_free(socks5_client_request_t *obj)
3054 : {
3055 649 : if (obj == NULL)
3056 : return;
3057 333 : socks5_client_request_clear(obj);
3058 333 : trunnel_memwipe(obj, sizeof(socks5_client_request_t));
3059 333 : trunnel_free_(obj);
3060 : }
3061 :
3062 : uint8_t
3063 17 : socks5_client_request_get_version(const socks5_client_request_t *inp)
3064 : {
3065 17 : return inp->version;
3066 : }
3067 : int
3068 0 : socks5_client_request_set_version(socks5_client_request_t *inp, uint8_t val)
3069 : {
3070 0 : if (! ((val == 5))) {
3071 0 : TRUNNEL_SET_ERROR_CODE(inp);
3072 0 : return -1;
3073 : }
3074 0 : inp->version = val;
3075 0 : return 0;
3076 : }
3077 : uint8_t
3078 17 : socks5_client_request_get_command(const socks5_client_request_t *inp)
3079 : {
3080 17 : return inp->command;
3081 : }
3082 : int
3083 0 : socks5_client_request_set_command(socks5_client_request_t *inp, uint8_t val)
3084 : {
3085 0 : if (! ((val == CMD_BIND || val == CMD_CONNECT || val == CMD_RESOLVE || val == CMD_RESOLVE_PTR || val == CMD_UDP_ASSOCIATE))) {
3086 0 : TRUNNEL_SET_ERROR_CODE(inp);
3087 0 : return -1;
3088 : }
3089 0 : inp->command = val;
3090 0 : return 0;
3091 : }
3092 : uint8_t
3093 0 : socks5_client_request_get_reserved(const socks5_client_request_t *inp)
3094 : {
3095 0 : return inp->reserved;
3096 : }
3097 : int
3098 0 : socks5_client_request_set_reserved(socks5_client_request_t *inp, uint8_t val)
3099 : {
3100 0 : if (! ((val == 0))) {
3101 0 : TRUNNEL_SET_ERROR_CODE(inp);
3102 0 : return -1;
3103 : }
3104 0 : inp->reserved = val;
3105 0 : return 0;
3106 : }
3107 : uint8_t
3108 17 : socks5_client_request_get_atype(const socks5_client_request_t *inp)
3109 : {
3110 17 : return inp->atype;
3111 : }
3112 : int
3113 0 : socks5_client_request_set_atype(socks5_client_request_t *inp, uint8_t val)
3114 : {
3115 0 : inp->atype = val;
3116 0 : return 0;
3117 : }
3118 : uint32_t
3119 6 : socks5_client_request_get_dest_addr_ipv4(const socks5_client_request_t *inp)
3120 : {
3121 6 : return inp->dest_addr_ipv4;
3122 : }
3123 : int
3124 0 : socks5_client_request_set_dest_addr_ipv4(socks5_client_request_t *inp, uint32_t val)
3125 : {
3126 0 : inp->dest_addr_ipv4 = val;
3127 0 : return 0;
3128 : }
3129 : size_t
3130 0 : socks5_client_request_getlen_dest_addr_ipv6(const socks5_client_request_t *inp)
3131 : {
3132 0 : (void)inp; return 16;
3133 : }
3134 :
3135 : uint8_t
3136 0 : socks5_client_request_get_dest_addr_ipv6(socks5_client_request_t *inp, size_t idx)
3137 : {
3138 0 : trunnel_assert(idx < 16);
3139 0 : return inp->dest_addr_ipv6[idx];
3140 : }
3141 :
3142 : uint8_t
3143 0 : socks5_client_request_getconst_dest_addr_ipv6(const socks5_client_request_t *inp, size_t idx)
3144 : {
3145 0 : return socks5_client_request_get_dest_addr_ipv6((socks5_client_request_t*)inp, idx);
3146 : }
3147 : int
3148 0 : socks5_client_request_set_dest_addr_ipv6(socks5_client_request_t *inp, size_t idx, uint8_t elt)
3149 : {
3150 0 : trunnel_assert(idx < 16);
3151 0 : inp->dest_addr_ipv6[idx] = elt;
3152 0 : return 0;
3153 : }
3154 :
3155 : uint8_t *
3156 2 : socks5_client_request_getarray_dest_addr_ipv6(socks5_client_request_t *inp)
3157 : {
3158 2 : return inp->dest_addr_ipv6;
3159 : }
3160 : const uint8_t *
3161 0 : socks5_client_request_getconstarray_dest_addr_ipv6(const socks5_client_request_t *inp)
3162 : {
3163 0 : return (const uint8_t *)socks5_client_request_getarray_dest_addr_ipv6((socks5_client_request_t*)inp);
3164 : }
3165 : struct domainname_st *
3166 9 : socks5_client_request_get_dest_addr_domainname(socks5_client_request_t *inp)
3167 : {
3168 9 : return inp->dest_addr_domainname;
3169 : }
3170 : const struct domainname_st *
3171 9 : socks5_client_request_getconst_dest_addr_domainname(const socks5_client_request_t *inp)
3172 : {
3173 9 : return socks5_client_request_get_dest_addr_domainname((socks5_client_request_t*) inp);
3174 : }
3175 : int
3176 0 : socks5_client_request_set_dest_addr_domainname(socks5_client_request_t *inp, struct domainname_st *val)
3177 : {
3178 0 : if (inp->dest_addr_domainname && inp->dest_addr_domainname != val)
3179 0 : domainname_free(inp->dest_addr_domainname);
3180 0 : return socks5_client_request_set0_dest_addr_domainname(inp, val);
3181 : }
3182 : int
3183 0 : socks5_client_request_set0_dest_addr_domainname(socks5_client_request_t *inp, struct domainname_st *val)
3184 : {
3185 0 : inp->dest_addr_domainname = val;
3186 0 : return 0;
3187 : }
3188 : uint16_t
3189 17 : socks5_client_request_get_dest_port(const socks5_client_request_t *inp)
3190 : {
3191 17 : return inp->dest_port;
3192 : }
3193 : int
3194 0 : socks5_client_request_set_dest_port(socks5_client_request_t *inp, uint16_t val)
3195 : {
3196 0 : inp->dest_port = val;
3197 0 : return 0;
3198 : }
3199 : const char *
3200 0 : socks5_client_request_check(const socks5_client_request_t *obj)
3201 : {
3202 0 : if (obj == NULL)
3203 : return "Object was NULL";
3204 0 : if (obj->trunnel_error_code_)
3205 : return "A set function failed on this object";
3206 0 : if (! (obj->version == 5))
3207 : return "Integer out of bounds";
3208 0 : if (! (obj->command == CMD_BIND || obj->command == CMD_CONNECT || obj->command == CMD_RESOLVE || obj->command == CMD_RESOLVE_PTR || obj->command == CMD_UDP_ASSOCIATE))
3209 : return "Integer out of bounds";
3210 0 : if (! (obj->reserved == 0))
3211 : return "Integer out of bounds";
3212 0 : switch (obj->atype) {
3213 :
3214 : case ATYPE_IPV4:
3215 : break;
3216 :
3217 : case ATYPE_IPV6:
3218 : break;
3219 :
3220 0 : case ATYPE_DOMAINNAME:
3221 : {
3222 0 : const char *msg;
3223 0 : if (NULL != (msg = domainname_check(obj->dest_addr_domainname)))
3224 0 : return msg;
3225 : }
3226 : break;
3227 :
3228 : default:
3229 : return "Bad tag for union";
3230 : break;
3231 : }
3232 : return NULL;
3233 : }
3234 :
3235 : ssize_t
3236 0 : socks5_client_request_encoded_len(const socks5_client_request_t *obj)
3237 : {
3238 0 : ssize_t result = 0;
3239 :
3240 0 : if (NULL != socks5_client_request_check(obj))
3241 : return -1;
3242 :
3243 :
3244 : /* Length of u8 version IN [5] */
3245 0 : result += 1;
3246 :
3247 : /* Length of u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR, CMD_UDP_ASSOCIATE] */
3248 0 : result += 1;
3249 :
3250 : /* Length of u8 reserved IN [0] */
3251 0 : result += 1;
3252 :
3253 : /* Length of u8 atype */
3254 0 : result += 1;
3255 0 : switch (obj->atype) {
3256 :
3257 : case ATYPE_IPV4:
3258 :
3259 : /* Length of u32 dest_addr_ipv4 */
3260 : result += 4;
3261 : break;
3262 :
3263 0 : case ATYPE_IPV6:
3264 :
3265 : /* Length of u8 dest_addr_ipv6[16] */
3266 0 : result += 16;
3267 0 : break;
3268 :
3269 0 : case ATYPE_DOMAINNAME:
3270 :
3271 : /* Length of struct domainname dest_addr_domainname */
3272 0 : result += domainname_encoded_len(obj->dest_addr_domainname);
3273 0 : break;
3274 :
3275 : default:
3276 0 : trunnel_assert(0);
3277 : break;
3278 : }
3279 :
3280 : /* Length of u16 dest_port */
3281 0 : result += 2;
3282 0 : return result;
3283 : }
3284 : int
3285 0 : socks5_client_request_clear_errors(socks5_client_request_t *obj)
3286 : {
3287 0 : int r = obj->trunnel_error_code_;
3288 0 : obj->trunnel_error_code_ = 0;
3289 0 : return r;
3290 : }
3291 : ssize_t
3292 0 : socks5_client_request_encode(uint8_t *output, const size_t avail, const socks5_client_request_t *obj)
3293 : {
3294 0 : ssize_t result = 0;
3295 0 : size_t written = 0;
3296 0 : uint8_t *ptr = output;
3297 0 : const char *msg;
3298 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
3299 : const ssize_t encoded_len = socks5_client_request_encoded_len(obj);
3300 : #endif
3301 :
3302 0 : if (NULL != (msg = socks5_client_request_check(obj)))
3303 0 : goto check_failed;
3304 :
3305 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
3306 : trunnel_assert(encoded_len >= 0);
3307 : #endif
3308 :
3309 : /* Encode u8 version IN [5] */
3310 0 : trunnel_assert(written <= avail);
3311 0 : if (avail - written < 1)
3312 0 : goto truncated;
3313 0 : trunnel_set_uint8(ptr, (obj->version));
3314 0 : written += 1; ptr += 1;
3315 :
3316 : /* Encode u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR, CMD_UDP_ASSOCIATE] */
3317 0 : trunnel_assert(written <= avail);
3318 0 : if (avail - written < 1)
3319 0 : goto truncated;
3320 0 : trunnel_set_uint8(ptr, (obj->command));
3321 0 : written += 1; ptr += 1;
3322 :
3323 : /* Encode u8 reserved IN [0] */
3324 0 : trunnel_assert(written <= avail);
3325 0 : if (avail - written < 1)
3326 0 : goto truncated;
3327 0 : trunnel_set_uint8(ptr, (obj->reserved));
3328 0 : written += 1; ptr += 1;
3329 :
3330 : /* Encode u8 atype */
3331 0 : trunnel_assert(written <= avail);
3332 0 : if (avail - written < 1)
3333 0 : goto truncated;
3334 0 : trunnel_set_uint8(ptr, (obj->atype));
3335 0 : written += 1; ptr += 1;
3336 :
3337 : /* Encode union dest_addr[atype] */
3338 0 : trunnel_assert(written <= avail);
3339 0 : switch (obj->atype) {
3340 :
3341 : case ATYPE_IPV4:
3342 :
3343 : /* Encode u32 dest_addr_ipv4 */
3344 0 : trunnel_assert(written <= avail);
3345 0 : if (avail - written < 4)
3346 0 : goto truncated;
3347 0 : trunnel_set_uint32(ptr, trunnel_htonl(obj->dest_addr_ipv4));
3348 0 : written += 4; ptr += 4;
3349 0 : break;
3350 :
3351 : case ATYPE_IPV6:
3352 :
3353 : /* Encode u8 dest_addr_ipv6[16] */
3354 0 : trunnel_assert(written <= avail);
3355 0 : if (avail - written < 16)
3356 0 : goto truncated;
3357 0 : memcpy(ptr, obj->dest_addr_ipv6, 16);
3358 0 : written += 16; ptr += 16;
3359 0 : break;
3360 :
3361 : case ATYPE_DOMAINNAME:
3362 :
3363 : /* Encode struct domainname dest_addr_domainname */
3364 0 : trunnel_assert(written <= avail);
3365 0 : result = domainname_encode(ptr, avail - written, obj->dest_addr_domainname);
3366 0 : if (result < 0)
3367 0 : goto fail; /* XXXXXXX !*/
3368 0 : written += result; ptr += result;
3369 0 : break;
3370 :
3371 : default:
3372 0 : trunnel_assert(0);
3373 : break;
3374 : }
3375 :
3376 : /* Encode u16 dest_port */
3377 0 : trunnel_assert(written <= avail);
3378 0 : if (avail - written < 2)
3379 0 : goto truncated;
3380 0 : trunnel_set_uint16(ptr, trunnel_htons(obj->dest_port));
3381 0 : written += 2; ptr += 2;
3382 :
3383 :
3384 0 : trunnel_assert(ptr == output + written);
3385 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
3386 : {
3387 : trunnel_assert(encoded_len >= 0);
3388 : trunnel_assert((size_t)encoded_len == written);
3389 : }
3390 :
3391 : #endif
3392 :
3393 0 : return written;
3394 :
3395 0 : truncated:
3396 0 : result = -2;
3397 0 : goto fail;
3398 0 : check_failed:
3399 0 : (void)msg;
3400 0 : result = -1;
3401 0 : goto fail;
3402 0 : fail:
3403 0 : trunnel_assert(result < 0);
3404 : return result;
3405 : }
3406 :
3407 : /** As socks5_client_request_parse(), but do not allocate the output
3408 : * object.
3409 : */
3410 : static ssize_t
3411 333 : socks5_client_request_parse_into(socks5_client_request_t *obj, const uint8_t *input, const size_t len_in)
3412 : {
3413 333 : const uint8_t *ptr = input;
3414 333 : size_t remaining = len_in;
3415 333 : ssize_t result = 0;
3416 333 : (void)result;
3417 :
3418 : /* Parse u8 version IN [5] */
3419 333 : CHECK_REMAINING(1, truncated);
3420 333 : obj->version = (trunnel_get_uint8(ptr));
3421 333 : remaining -= 1; ptr += 1;
3422 333 : if (! (obj->version == 5))
3423 0 : goto fail;
3424 :
3425 : /* Parse u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR, CMD_UDP_ASSOCIATE] */
3426 333 : CHECK_REMAINING(1, truncated);
3427 333 : obj->command = (trunnel_get_uint8(ptr));
3428 333 : remaining -= 1; ptr += 1;
3429 333 : if (! (obj->command == CMD_BIND || obj->command == CMD_CONNECT || obj->command == CMD_RESOLVE || obj->command == CMD_RESOLVE_PTR || obj->command == CMD_UDP_ASSOCIATE))
3430 0 : goto fail;
3431 :
3432 : /* Parse u8 reserved IN [0] */
3433 333 : CHECK_REMAINING(1, truncated);
3434 328 : obj->reserved = (trunnel_get_uint8(ptr));
3435 328 : remaining -= 1; ptr += 1;
3436 328 : if (! (obj->reserved == 0))
3437 0 : goto fail;
3438 :
3439 : /* Parse u8 atype */
3440 328 : CHECK_REMAINING(1, truncated);
3441 323 : obj->atype = (trunnel_get_uint8(ptr));
3442 323 : remaining -= 1; ptr += 1;
3443 :
3444 : /* Parse union dest_addr[atype] */
3445 323 : switch (obj->atype) {
3446 :
3447 12 : case ATYPE_IPV4:
3448 :
3449 : /* Parse u32 dest_addr_ipv4 */
3450 12 : CHECK_REMAINING(4, truncated);
3451 8 : obj->dest_addr_ipv4 = trunnel_ntohl(trunnel_get_uint32(ptr));
3452 8 : remaining -= 4; ptr += 4;
3453 8 : break;
3454 :
3455 20 : case ATYPE_IPV6:
3456 :
3457 : /* Parse u8 dest_addr_ipv6[16] */
3458 20 : CHECK_REMAINING(16, truncated);
3459 4 : memcpy(obj->dest_addr_ipv6, ptr, 16);
3460 4 : remaining -= 16; ptr += 16;
3461 4 : break;
3462 :
3463 290 : case ATYPE_DOMAINNAME:
3464 :
3465 : /* Parse struct domainname dest_addr_domainname */
3466 290 : result = domainname_parse(&obj->dest_addr_domainname, ptr, remaining);
3467 290 : if (result < 0)
3468 275 : goto relay_fail;
3469 15 : trunnel_assert((size_t)result <= remaining);
3470 15 : remaining -= result; ptr += result;
3471 15 : break;
3472 :
3473 1 : default:
3474 1 : goto fail;
3475 27 : break;
3476 : }
3477 :
3478 : /* Parse u16 dest_port */
3479 27 : CHECK_REMAINING(2, truncated);
3480 17 : obj->dest_port = trunnel_ntohs(trunnel_get_uint16(ptr));
3481 17 : remaining -= 2; ptr += 2;
3482 17 : trunnel_assert(ptr + remaining == input + len_in);
3483 17 : return len_in - remaining;
3484 :
3485 : truncated:
3486 : return -2;
3487 275 : relay_fail:
3488 275 : trunnel_assert(result < 0);
3489 : return result;
3490 : fail:
3491 333 : result = -1;
3492 : return result;
3493 : }
3494 :
3495 : ssize_t
3496 333 : socks5_client_request_parse(socks5_client_request_t **output, const uint8_t *input, const size_t len_in)
3497 : {
3498 333 : ssize_t result;
3499 333 : *output = socks5_client_request_new();
3500 333 : if (NULL == *output)
3501 : return -1;
3502 333 : result = socks5_client_request_parse_into(*output, input, len_in);
3503 333 : if (result < 0) {
3504 316 : socks5_client_request_free(*output);
3505 316 : *output = NULL;
3506 : }
3507 : return result;
3508 : }
3509 : socks5_server_reply_t *
3510 7 : socks5_server_reply_new(void)
3511 : {
3512 7 : socks5_server_reply_t *val = trunnel_calloc(1, sizeof(socks5_server_reply_t));
3513 7 : if (NULL == val)
3514 : return NULL;
3515 7 : val->version = 5;
3516 7 : return val;
3517 : }
3518 :
3519 : /** Release all storage held inside 'obj', but do not free 'obj'.
3520 : */
3521 : static void
3522 7 : socks5_server_reply_clear(socks5_server_reply_t *obj)
3523 : {
3524 7 : (void) obj;
3525 7 : domainname_free(obj->bind_addr_domainname);
3526 7 : obj->bind_addr_domainname = NULL;
3527 7 : }
3528 :
3529 : void
3530 7 : socks5_server_reply_free(socks5_server_reply_t *obj)
3531 : {
3532 7 : if (obj == NULL)
3533 : return;
3534 7 : socks5_server_reply_clear(obj);
3535 7 : trunnel_memwipe(obj, sizeof(socks5_server_reply_t));
3536 7 : trunnel_free_(obj);
3537 : }
3538 :
3539 : uint8_t
3540 0 : socks5_server_reply_get_version(const socks5_server_reply_t *inp)
3541 : {
3542 0 : return inp->version;
3543 : }
3544 : int
3545 7 : socks5_server_reply_set_version(socks5_server_reply_t *inp, uint8_t val)
3546 : {
3547 7 : if (! ((val == 5))) {
3548 0 : TRUNNEL_SET_ERROR_CODE(inp);
3549 0 : return -1;
3550 : }
3551 7 : inp->version = val;
3552 7 : return 0;
3553 : }
3554 : uint8_t
3555 0 : socks5_server_reply_get_reply(const socks5_server_reply_t *inp)
3556 : {
3557 0 : return inp->reply;
3558 : }
3559 : int
3560 7 : socks5_server_reply_set_reply(socks5_server_reply_t *inp, uint8_t val)
3561 : {
3562 7 : inp->reply = val;
3563 7 : return 0;
3564 : }
3565 : uint8_t
3566 0 : socks5_server_reply_get_reserved(const socks5_server_reply_t *inp)
3567 : {
3568 0 : return inp->reserved;
3569 : }
3570 : int
3571 0 : socks5_server_reply_set_reserved(socks5_server_reply_t *inp, uint8_t val)
3572 : {
3573 0 : if (! ((val == 0))) {
3574 0 : TRUNNEL_SET_ERROR_CODE(inp);
3575 0 : return -1;
3576 : }
3577 0 : inp->reserved = val;
3578 0 : return 0;
3579 : }
3580 : uint8_t
3581 0 : socks5_server_reply_get_atype(const socks5_server_reply_t *inp)
3582 : {
3583 0 : return inp->atype;
3584 : }
3585 : int
3586 7 : socks5_server_reply_set_atype(socks5_server_reply_t *inp, uint8_t val)
3587 : {
3588 7 : inp->atype = val;
3589 7 : return 0;
3590 : }
3591 : uint32_t
3592 0 : socks5_server_reply_get_bind_addr_ipv4(const socks5_server_reply_t *inp)
3593 : {
3594 0 : return inp->bind_addr_ipv4;
3595 : }
3596 : int
3597 0 : socks5_server_reply_set_bind_addr_ipv4(socks5_server_reply_t *inp, uint32_t val)
3598 : {
3599 0 : inp->bind_addr_ipv4 = val;
3600 0 : return 0;
3601 : }
3602 : size_t
3603 0 : socks5_server_reply_getlen_bind_addr_ipv6(const socks5_server_reply_t *inp)
3604 : {
3605 0 : (void)inp; return 16;
3606 : }
3607 :
3608 : uint8_t
3609 0 : socks5_server_reply_get_bind_addr_ipv6(socks5_server_reply_t *inp, size_t idx)
3610 : {
3611 0 : trunnel_assert(idx < 16);
3612 0 : return inp->bind_addr_ipv6[idx];
3613 : }
3614 :
3615 : uint8_t
3616 0 : socks5_server_reply_getconst_bind_addr_ipv6(const socks5_server_reply_t *inp, size_t idx)
3617 : {
3618 0 : return socks5_server_reply_get_bind_addr_ipv6((socks5_server_reply_t*)inp, idx);
3619 : }
3620 : int
3621 0 : socks5_server_reply_set_bind_addr_ipv6(socks5_server_reply_t *inp, size_t idx, uint8_t elt)
3622 : {
3623 0 : trunnel_assert(idx < 16);
3624 0 : inp->bind_addr_ipv6[idx] = elt;
3625 0 : return 0;
3626 : }
3627 :
3628 : uint8_t *
3629 0 : socks5_server_reply_getarray_bind_addr_ipv6(socks5_server_reply_t *inp)
3630 : {
3631 0 : return inp->bind_addr_ipv6;
3632 : }
3633 : const uint8_t *
3634 0 : socks5_server_reply_getconstarray_bind_addr_ipv6(const socks5_server_reply_t *inp)
3635 : {
3636 0 : return (const uint8_t *)socks5_server_reply_getarray_bind_addr_ipv6((socks5_server_reply_t*)inp);
3637 : }
3638 : struct domainname_st *
3639 0 : socks5_server_reply_get_bind_addr_domainname(socks5_server_reply_t *inp)
3640 : {
3641 0 : return inp->bind_addr_domainname;
3642 : }
3643 : const struct domainname_st *
3644 0 : socks5_server_reply_getconst_bind_addr_domainname(const socks5_server_reply_t *inp)
3645 : {
3646 0 : return socks5_server_reply_get_bind_addr_domainname((socks5_server_reply_t*) inp);
3647 : }
3648 : int
3649 0 : socks5_server_reply_set_bind_addr_domainname(socks5_server_reply_t *inp, struct domainname_st *val)
3650 : {
3651 0 : if (inp->bind_addr_domainname && inp->bind_addr_domainname != val)
3652 0 : domainname_free(inp->bind_addr_domainname);
3653 0 : return socks5_server_reply_set0_bind_addr_domainname(inp, val);
3654 : }
3655 : int
3656 0 : socks5_server_reply_set0_bind_addr_domainname(socks5_server_reply_t *inp, struct domainname_st *val)
3657 : {
3658 0 : inp->bind_addr_domainname = val;
3659 0 : return 0;
3660 : }
3661 : uint16_t
3662 0 : socks5_server_reply_get_bind_port(const socks5_server_reply_t *inp)
3663 : {
3664 0 : return inp->bind_port;
3665 : }
3666 : int
3667 0 : socks5_server_reply_set_bind_port(socks5_server_reply_t *inp, uint16_t val)
3668 : {
3669 0 : inp->bind_port = val;
3670 0 : return 0;
3671 : }
3672 : const char *
3673 14 : socks5_server_reply_check(const socks5_server_reply_t *obj)
3674 : {
3675 14 : if (obj == NULL)
3676 : return "Object was NULL";
3677 14 : if (obj->trunnel_error_code_)
3678 : return "A set function failed on this object";
3679 14 : if (! (obj->version == 5))
3680 : return "Integer out of bounds";
3681 14 : if (! (obj->reserved == 0))
3682 : return "Integer out of bounds";
3683 14 : switch (obj->atype) {
3684 :
3685 : case ATYPE_IPV4:
3686 : break;
3687 :
3688 : case ATYPE_IPV6:
3689 : break;
3690 :
3691 0 : case ATYPE_DOMAINNAME:
3692 : {
3693 0 : const char *msg;
3694 0 : if (NULL != (msg = domainname_check(obj->bind_addr_domainname)))
3695 0 : return msg;
3696 : }
3697 : break;
3698 :
3699 : default:
3700 : return "Bad tag for union";
3701 : break;
3702 : }
3703 : return NULL;
3704 : }
3705 :
3706 : ssize_t
3707 0 : socks5_server_reply_encoded_len(const socks5_server_reply_t *obj)
3708 : {
3709 0 : ssize_t result = 0;
3710 :
3711 0 : if (NULL != socks5_server_reply_check(obj))
3712 : return -1;
3713 :
3714 :
3715 : /* Length of u8 version IN [5] */
3716 0 : result += 1;
3717 :
3718 : /* Length of u8 reply */
3719 0 : result += 1;
3720 :
3721 : /* Length of u8 reserved IN [0] */
3722 0 : result += 1;
3723 :
3724 : /* Length of u8 atype */
3725 0 : result += 1;
3726 0 : switch (obj->atype) {
3727 :
3728 : case ATYPE_IPV4:
3729 :
3730 : /* Length of u32 bind_addr_ipv4 */
3731 : result += 4;
3732 : break;
3733 :
3734 0 : case ATYPE_IPV6:
3735 :
3736 : /* Length of u8 bind_addr_ipv6[16] */
3737 0 : result += 16;
3738 0 : break;
3739 :
3740 0 : case ATYPE_DOMAINNAME:
3741 :
3742 : /* Length of struct domainname bind_addr_domainname */
3743 0 : result += domainname_encoded_len(obj->bind_addr_domainname);
3744 0 : break;
3745 :
3746 : default:
3747 0 : trunnel_assert(0);
3748 : break;
3749 : }
3750 :
3751 : /* Length of u16 bind_port */
3752 0 : result += 2;
3753 0 : return result;
3754 : }
3755 : int
3756 0 : socks5_server_reply_clear_errors(socks5_server_reply_t *obj)
3757 : {
3758 0 : int r = obj->trunnel_error_code_;
3759 0 : obj->trunnel_error_code_ = 0;
3760 0 : return r;
3761 : }
3762 : ssize_t
3763 7 : socks5_server_reply_encode(uint8_t *output, const size_t avail, const socks5_server_reply_t *obj)
3764 : {
3765 7 : ssize_t result = 0;
3766 7 : size_t written = 0;
3767 7 : uint8_t *ptr = output;
3768 7 : const char *msg;
3769 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
3770 : const ssize_t encoded_len = socks5_server_reply_encoded_len(obj);
3771 : #endif
3772 :
3773 7 : if (NULL != (msg = socks5_server_reply_check(obj)))
3774 0 : goto check_failed;
3775 :
3776 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
3777 : trunnel_assert(encoded_len >= 0);
3778 : #endif
3779 :
3780 : /* Encode u8 version IN [5] */
3781 7 : trunnel_assert(written <= avail);
3782 7 : if (avail - written < 1)
3783 0 : goto truncated;
3784 7 : trunnel_set_uint8(ptr, (obj->version));
3785 7 : written += 1; ptr += 1;
3786 :
3787 : /* Encode u8 reply */
3788 7 : trunnel_assert(written <= avail);
3789 7 : if (avail - written < 1)
3790 0 : goto truncated;
3791 7 : trunnel_set_uint8(ptr, (obj->reply));
3792 7 : written += 1; ptr += 1;
3793 :
3794 : /* Encode u8 reserved IN [0] */
3795 7 : trunnel_assert(written <= avail);
3796 7 : if (avail - written < 1)
3797 0 : goto truncated;
3798 7 : trunnel_set_uint8(ptr, (obj->reserved));
3799 7 : written += 1; ptr += 1;
3800 :
3801 : /* Encode u8 atype */
3802 7 : trunnel_assert(written <= avail);
3803 7 : if (avail - written < 1)
3804 0 : goto truncated;
3805 7 : trunnel_set_uint8(ptr, (obj->atype));
3806 7 : written += 1; ptr += 1;
3807 :
3808 : /* Encode union bind_addr[atype] */
3809 7 : trunnel_assert(written <= avail);
3810 7 : switch (obj->atype) {
3811 :
3812 : case ATYPE_IPV4:
3813 :
3814 : /* Encode u32 bind_addr_ipv4 */
3815 7 : trunnel_assert(written <= avail);
3816 7 : if (avail - written < 4)
3817 0 : goto truncated;
3818 7 : trunnel_set_uint32(ptr, trunnel_htonl(obj->bind_addr_ipv4));
3819 7 : written += 4; ptr += 4;
3820 7 : break;
3821 :
3822 : case ATYPE_IPV6:
3823 :
3824 : /* Encode u8 bind_addr_ipv6[16] */
3825 0 : trunnel_assert(written <= avail);
3826 0 : if (avail - written < 16)
3827 0 : goto truncated;
3828 0 : memcpy(ptr, obj->bind_addr_ipv6, 16);
3829 0 : written += 16; ptr += 16;
3830 0 : break;
3831 :
3832 : case ATYPE_DOMAINNAME:
3833 :
3834 : /* Encode struct domainname bind_addr_domainname */
3835 0 : trunnel_assert(written <= avail);
3836 0 : result = domainname_encode(ptr, avail - written, obj->bind_addr_domainname);
3837 0 : if (result < 0)
3838 0 : goto fail; /* XXXXXXX !*/
3839 0 : written += result; ptr += result;
3840 0 : break;
3841 :
3842 : default:
3843 0 : trunnel_assert(0);
3844 : break;
3845 : }
3846 :
3847 : /* Encode u16 bind_port */
3848 7 : trunnel_assert(written <= avail);
3849 7 : if (avail - written < 2)
3850 0 : goto truncated;
3851 7 : trunnel_set_uint16(ptr, trunnel_htons(obj->bind_port));
3852 7 : written += 2; ptr += 2;
3853 :
3854 :
3855 7 : trunnel_assert(ptr == output + written);
3856 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
3857 : {
3858 : trunnel_assert(encoded_len >= 0);
3859 : trunnel_assert((size_t)encoded_len == written);
3860 : }
3861 :
3862 : #endif
3863 :
3864 7 : return written;
3865 :
3866 0 : truncated:
3867 0 : result = -2;
3868 0 : goto fail;
3869 0 : check_failed:
3870 0 : (void)msg;
3871 0 : result = -1;
3872 0 : goto fail;
3873 0 : fail:
3874 0 : trunnel_assert(result < 0);
3875 : return result;
3876 : }
3877 :
3878 : /** As socks5_server_reply_parse(), but do not allocate the output
3879 : * object.
3880 : */
3881 : static ssize_t
3882 0 : socks5_server_reply_parse_into(socks5_server_reply_t *obj, const uint8_t *input, const size_t len_in)
3883 : {
3884 0 : const uint8_t *ptr = input;
3885 0 : size_t remaining = len_in;
3886 0 : ssize_t result = 0;
3887 0 : (void)result;
3888 :
3889 : /* Parse u8 version IN [5] */
3890 0 : CHECK_REMAINING(1, truncated);
3891 0 : obj->version = (trunnel_get_uint8(ptr));
3892 0 : remaining -= 1; ptr += 1;
3893 0 : if (! (obj->version == 5))
3894 0 : goto fail;
3895 :
3896 : /* Parse u8 reply */
3897 0 : CHECK_REMAINING(1, truncated);
3898 0 : obj->reply = (trunnel_get_uint8(ptr));
3899 0 : remaining -= 1; ptr += 1;
3900 :
3901 : /* Parse u8 reserved IN [0] */
3902 0 : CHECK_REMAINING(1, truncated);
3903 0 : obj->reserved = (trunnel_get_uint8(ptr));
3904 0 : remaining -= 1; ptr += 1;
3905 0 : if (! (obj->reserved == 0))
3906 0 : goto fail;
3907 :
3908 : /* Parse u8 atype */
3909 0 : CHECK_REMAINING(1, truncated);
3910 0 : obj->atype = (trunnel_get_uint8(ptr));
3911 0 : remaining -= 1; ptr += 1;
3912 :
3913 : /* Parse union bind_addr[atype] */
3914 0 : switch (obj->atype) {
3915 :
3916 0 : case ATYPE_IPV4:
3917 :
3918 : /* Parse u32 bind_addr_ipv4 */
3919 0 : CHECK_REMAINING(4, truncated);
3920 0 : obj->bind_addr_ipv4 = trunnel_ntohl(trunnel_get_uint32(ptr));
3921 0 : remaining -= 4; ptr += 4;
3922 0 : break;
3923 :
3924 0 : case ATYPE_IPV6:
3925 :
3926 : /* Parse u8 bind_addr_ipv6[16] */
3927 0 : CHECK_REMAINING(16, truncated);
3928 0 : memcpy(obj->bind_addr_ipv6, ptr, 16);
3929 0 : remaining -= 16; ptr += 16;
3930 0 : break;
3931 :
3932 0 : case ATYPE_DOMAINNAME:
3933 :
3934 : /* Parse struct domainname bind_addr_domainname */
3935 0 : result = domainname_parse(&obj->bind_addr_domainname, ptr, remaining);
3936 0 : if (result < 0)
3937 0 : goto relay_fail;
3938 0 : trunnel_assert((size_t)result <= remaining);
3939 0 : remaining -= result; ptr += result;
3940 0 : break;
3941 :
3942 0 : default:
3943 0 : goto fail;
3944 0 : break;
3945 : }
3946 :
3947 : /* Parse u16 bind_port */
3948 0 : CHECK_REMAINING(2, truncated);
3949 0 : obj->bind_port = trunnel_ntohs(trunnel_get_uint16(ptr));
3950 0 : remaining -= 2; ptr += 2;
3951 0 : trunnel_assert(ptr + remaining == input + len_in);
3952 0 : return len_in - remaining;
3953 :
3954 : truncated:
3955 : return -2;
3956 0 : relay_fail:
3957 0 : trunnel_assert(result < 0);
3958 : return result;
3959 : fail:
3960 0 : result = -1;
3961 : return result;
3962 : }
3963 :
3964 : ssize_t
3965 0 : socks5_server_reply_parse(socks5_server_reply_t **output, const uint8_t *input, const size_t len_in)
3966 : {
3967 0 : ssize_t result;
3968 0 : *output = socks5_server_reply_new();
3969 0 : if (NULL == *output)
3970 : return -1;
3971 0 : result = socks5_server_reply_parse_into(*output, input, len_in);
3972 0 : if (result < 0) {
3973 0 : socks5_server_reply_free(*output);
3974 0 : *output = NULL;
3975 : }
3976 : return result;
3977 : }
|