Coverage Report

Created: 2023-04-12 06:22

/src/tor/src/trunnel/socks5.c
Line
Count
Source (jump to first uncovered line)
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
0
  do {                              \
12
0
    (obj)->trunnel_error_code_ = 1; \
13
0
  } 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
0
  do {                                                           \
26
0
    if (remaining < (nbytes) OR_DEADCODE_DUMMY) {                \
27
0
      goto label;                                                \
28
0
    }                                                            \
29
0
  } while (0)
30
31
domainname_t *
32
domainname_new(void)
33
0
{
34
0
  domainname_t *val = trunnel_calloc(1, sizeof(domainname_t));
35
0
  if (NULL == val)
36
0
    return NULL;
37
0
  return val;
38
0
}
39
40
/** Release all storage held inside 'obj', but do not free 'obj'.
41
 */
42
static void
43
domainname_clear(domainname_t *obj)
44
0
{
45
0
  (void) obj;
46
0
  TRUNNEL_DYNARRAY_WIPE(&obj->name);
47
0
  TRUNNEL_DYNARRAY_CLEAR(&obj->name);
48
0
}
49
50
void
51
domainname_free(domainname_t *obj)
52
0
{
53
0
  if (obj == NULL)
54
0
    return;
55
0
  domainname_clear(obj);
56
0
  trunnel_memwipe(obj, sizeof(domainname_t));
57
0
  trunnel_free_(obj);
58
0
}
59
60
uint8_t
61
domainname_get_len(const domainname_t *inp)
62
0
{
63
0
  return inp->len;
64
0
}
65
int
66
domainname_set_len(domainname_t *inp, uint8_t val)
67
0
{
68
0
  inp->len = val;
69
0
  return 0;
70
0
}
71
size_t
72
domainname_getlen_name(const domainname_t *inp)
73
0
{
74
0
  return TRUNNEL_DYNARRAY_LEN(&inp->name);
75
0
}
76
77
char
78
domainname_get_name(domainname_t *inp, size_t idx)
79
0
{
80
0
  return TRUNNEL_DYNARRAY_GET(&inp->name, idx);
81
0
}
82
83
char
84
domainname_getconst_name(const domainname_t *inp, size_t idx)
85
0
{
86
0
  return domainname_get_name((domainname_t*)inp, idx);
87
0
}
88
int
89
domainname_set_name(domainname_t *inp, size_t idx, char elt)
90
0
{
91
0
  TRUNNEL_DYNARRAY_SET(&inp->name, idx, elt);
92
0
  return 0;
93
0
}
94
int
95
domainname_add_name(domainname_t *inp, char elt)
96
0
{
97
0
#if SIZE_MAX >= UINT8_MAX
98
0
  if (inp->name.n_ == UINT8_MAX)
99
0
    goto trunnel_alloc_failed;
100
0
#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
0
}
107
108
char *
109
domainname_getarray_name(domainname_t *inp)
110
0
{
111
0
  return inp->name.elts_;
112
0
}
113
const char  *
114
domainname_getconstarray_name(const domainname_t *inp)
115
0
{
116
0
  return (const char  *)domainname_getarray_name((domainname_t*)inp);
117
0
}
118
int
119
domainname_setlen_name(domainname_t *inp, size_t newlen)
120
0
{
121
0
#if UINT8_MAX < SIZE_MAX
122
0
  if (newlen > UINT8_MAX)
123
0
    goto trunnel_alloc_failed;
124
0
#endif
125
0
  return trunnel_string_setlen(&inp->name, newlen,
126
0
            &inp->trunnel_error_code_);
127
0
 trunnel_alloc_failed:
128
0
  TRUNNEL_SET_ERROR_CODE(inp);
129
0
  return -1;
130
0
}
131
const char *
132
domainname_getstr_name(domainname_t *inp)
133
0
{
134
0
  return trunnel_string_getstr(&inp->name);
135
0
}
136
int
137
domainname_setstr0_name(domainname_t *inp, const char *val, size_t len)
138
0
{
139
0
#if UINT8_MAX < SIZE_MAX
140
0
  if (len > UINT8_MAX) {
141
0
    TRUNNEL_SET_ERROR_CODE(inp);
142
0
    return -1;
143
0
  }
144
0
#endif
145
0
  return trunnel_string_setstr0(&inp->name, val, len, &inp->trunnel_error_code_);
146
0
}
147
int
148
domainname_setstr_name(domainname_t *inp, const char *val)
149
0
{
150
0
  return domainname_setstr0_name(inp, val, strlen(val));
151
0
}
152
const char *
153
domainname_check(const domainname_t *obj)
154
0
{
155
0
  if (obj == NULL)
156
0
    return "Object was NULL";
157
0
  if (obj->trunnel_error_code_)
158
0
    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
0
  return NULL;
162
0
}
163
164
ssize_t
165
domainname_encoded_len(const domainname_t *obj)
166
0
{
167
0
  ssize_t result = 0;
168
169
0
  if (NULL != domainname_check(obj))
170
0
     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
0
}
180
int
181
domainname_clear_errors(domainname_t *obj)
182
0
{
183
0
  int r = obj->trunnel_error_code_;
184
0
  obj->trunnel_error_code_ = 0;
185
0
  return r;
186
0
}
187
ssize_t
188
domainname_encode(uint8_t *output, const size_t avail, const domainname_t *obj)
189
0
{
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
0
  {
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
0
  }
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
0
 fail:
244
0
  trunnel_assert(result < 0);
245
0
  return result;
246
0
}
247
248
/** As domainname_parse(), but do not allocate the output object.
249
 */
250
static ssize_t
251
domainname_parse_into(domainname_t *obj, const uint8_t *input, const size_t len_in)
252
0
{
253
0
  const uint8_t *ptr = input;
254
0
  size_t remaining = len_in;
255
0
  ssize_t result = 0;
256
0
  (void)result;
257
258
  /* Parse u8 len */
259
0
  CHECK_REMAINING(1, truncated);
260
0
  obj->len = (trunnel_get_uint8(ptr));
261
0
  remaining -= 1; ptr += 1;
262
263
  /* Parse char name[len] */
264
0
  CHECK_REMAINING(obj->len, truncated);
265
0
  if (domainname_setstr0_name(obj, (const char*)ptr, obj->len))
266
0
    goto fail;
267
0
  ptr += obj->len; remaining -= obj->len;
268
0
  trunnel_assert(ptr + remaining == input + len_in);
269
0
  return len_in - remaining;
270
271
0
 truncated:
272
0
  return -2;
273
0
 fail:
274
0
  result = -1;
275
0
  return result;
276
0
}
277
278
ssize_t
279
domainname_parse(domainname_t **output, const uint8_t *input, const size_t len_in)
280
0
{
281
0
  ssize_t result;
282
0
  *output = domainname_new();
283
0
  if (NULL == *output)
284
0
    return -1;
285
0
  result = domainname_parse_into(*output, input, len_in);
286
0
  if (result < 0) {
287
0
    domainname_free(*output);
288
0
    *output = NULL;
289
0
  }
290
0
  return result;
291
0
}
292
socks4_client_request_t *
293
socks4_client_request_new(void)
294
0
{
295
0
  socks4_client_request_t *val = trunnel_calloc(1, sizeof(socks4_client_request_t));
296
0
  if (NULL == val)
297
0
    return NULL;
298
0
  val->version = 4;
299
0
  val->command = CMD_BIND;
300
0
  return val;
301
0
}
302
303
/** Release all storage held inside 'obj', but do not free 'obj'.
304
 */
305
static void
306
socks4_client_request_clear(socks4_client_request_t *obj)
307
0
{
308
0
  (void) obj;
309
0
  trunnel_wipestr(obj->username);
310
0
  trunnel_free(obj->username);
311
0
  trunnel_wipestr(obj->socks4a_addr_hostname);
312
0
  trunnel_free(obj->socks4a_addr_hostname);
313
0
}
314
315
void
316
socks4_client_request_free(socks4_client_request_t *obj)
317
0
{
318
0
  if (obj == NULL)
319
0
    return;
320
0
  socks4_client_request_clear(obj);
321
0
  trunnel_memwipe(obj, sizeof(socks4_client_request_t));
322
0
  trunnel_free_(obj);
323
0
}
324
325
uint8_t
326
socks4_client_request_get_version(const socks4_client_request_t *inp)
327
0
{
328
0
  return inp->version;
329
0
}
330
int
331
socks4_client_request_set_version(socks4_client_request_t *inp, uint8_t val)
332
0
{
333
0
  if (! ((val == 4))) {
334
0
     TRUNNEL_SET_ERROR_CODE(inp);
335
0
     return -1;
336
0
  }
337
0
  inp->version = val;
338
0
  return 0;
339
0
}
340
uint8_t
341
socks4_client_request_get_command(const socks4_client_request_t *inp)
342
0
{
343
0
  return inp->command;
344
0
}
345
int
346
socks4_client_request_set_command(socks4_client_request_t *inp, uint8_t val)
347
0
{
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
0
  }
352
0
  inp->command = val;
353
0
  return 0;
354
0
}
355
uint16_t
356
socks4_client_request_get_port(const socks4_client_request_t *inp)
357
0
{
358
0
  return inp->port;
359
0
}
360
int
361
socks4_client_request_set_port(socks4_client_request_t *inp, uint16_t val)
362
0
{
363
0
  inp->port = val;
364
0
  return 0;
365
0
}
366
uint32_t
367
socks4_client_request_get_addr(const socks4_client_request_t *inp)
368
0
{
369
0
  return inp->addr;
370
0
}
371
int
372
socks4_client_request_set_addr(socks4_client_request_t *inp, uint32_t val)
373
0
{
374
0
  inp->addr = val;
375
0
  return 0;
376
0
}
377
const char *
378
socks4_client_request_get_username(const socks4_client_request_t *inp)
379
0
{
380
0
  return inp->username;
381
0
}
382
int
383
socks4_client_request_set_username(socks4_client_request_t *inp, const char *val)
384
0
{
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
0
  }
390
0
  return 0;
391
0
}
392
const char *
393
socks4_client_request_get_socks4a_addr_hostname(const socks4_client_request_t *inp)
394
0
{
395
0
  return inp->socks4a_addr_hostname;
396
0
}
397
int
398
socks4_client_request_set_socks4a_addr_hostname(socks4_client_request_t *inp, const char *val)
399
0
{
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
0
  }
405
0
  return 0;
406
0
}
407
const char *
408
socks4_client_request_check(const socks4_client_request_t *obj)
409
0
{
410
0
  if (obj == NULL)
411
0
    return "Object was NULL";
412
0
  if (obj->trunnel_error_code_)
413
0
    return "A set function failed on this object";
414
0
  if (! (obj->version == 4))
415
0
    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
0
    return "Integer out of bounds";
418
0
  if (NULL == obj->username)
419
0
    return "Missing username";
420
0
  switch (obj->addr) {
421
422
0
    case 1:
423
0
    case 2:
424
0
    case 3:
425
0
    case 4:
426
0
    case 5:
427
0
    case 6:
428
0
    case 7:
429
0
    case 8:
430
0
    case 9:
431
0
    case 10:
432
0
    case 11:
433
0
    case 12:
434
0
    case 13:
435
0
    case 14:
436
0
    case 15:
437
0
    case 16:
438
0
    case 17:
439
0
    case 18:
440
0
    case 19:
441
0
    case 20:
442
0
    case 21:
443
0
    case 22:
444
0
    case 23:
445
0
    case 24:
446
0
    case 25:
447
0
    case 26:
448
0
    case 27:
449
0
    case 28:
450
0
    case 29:
451
0
    case 30:
452
0
    case 31:
453
0
    case 32:
454
0
    case 33:
455
0
    case 34:
456
0
    case 35:
457
0
    case 36:
458
0
    case 37:
459
0
    case 38:
460
0
    case 39:
461
0
    case 40:
462
0
    case 41:
463
0
    case 42:
464
0
    case 43:
465
0
    case 44:
466
0
    case 45:
467
0
    case 46:
468
0
    case 47:
469
0
    case 48:
470
0
    case 49:
471
0
    case 50:
472
0
    case 51:
473
0
    case 52:
474
0
    case 53:
475
0
    case 54:
476
0
    case 55:
477
0
    case 56:
478
0
    case 57:
479
0
    case 58:
480
0
    case 59:
481
0
    case 60:
482
0
    case 61:
483
0
    case 62:
484
0
    case 63:
485
0
    case 64:
486
0
    case 65:
487
0
    case 66:
488
0
    case 67:
489
0
    case 68:
490
0
    case 69:
491
0
    case 70:
492
0
    case 71:
493
0
    case 72:
494
0
    case 73:
495
0
    case 74:
496
0
    case 75:
497
0
    case 76:
498
0
    case 77:
499
0
    case 78:
500
0
    case 79:
501
0
    case 80:
502
0
    case 81:
503
0
    case 82:
504
0
    case 83:
505
0
    case 84:
506
0
    case 85:
507
0
    case 86:
508
0
    case 87:
509
0
    case 88:
510
0
    case 89:
511
0
    case 90:
512
0
    case 91:
513
0
    case 92:
514
0
    case 93:
515
0
    case 94:
516
0
    case 95:
517
0
    case 96:
518
0
    case 97:
519
0
    case 98:
520
0
    case 99:
521
0
    case 100:
522
0
    case 101:
523
0
    case 102:
524
0
    case 103:
525
0
    case 104:
526
0
    case 105:
527
0
    case 106:
528
0
    case 107:
529
0
    case 108:
530
0
    case 109:
531
0
    case 110:
532
0
    case 111:
533
0
    case 112:
534
0
    case 113:
535
0
    case 114:
536
0
    case 115:
537
0
    case 116:
538
0
    case 117:
539
0
    case 118:
540
0
    case 119:
541
0
    case 120:
542
0
    case 121:
543
0
    case 122:
544
0
    case 123:
545
0
    case 124:
546
0
    case 125:
547
0
    case 126:
548
0
    case 127:
549
0
    case 128:
550
0
    case 129:
551
0
    case 130:
552
0
    case 131:
553
0
    case 132:
554
0
    case 133:
555
0
    case 134:
556
0
    case 135:
557
0
    case 136:
558
0
    case 137:
559
0
    case 138:
560
0
    case 139:
561
0
    case 140:
562
0
    case 141:
563
0
    case 142:
564
0
    case 143:
565
0
    case 144:
566
0
    case 145:
567
0
    case 146:
568
0
    case 147:
569
0
    case 148:
570
0
    case 149:
571
0
    case 150:
572
0
    case 151:
573
0
    case 152:
574
0
    case 153:
575
0
    case 154:
576
0
    case 155:
577
0
    case 156:
578
0
    case 157:
579
0
    case 158:
580
0
    case 159:
581
0
    case 160:
582
0
    case 161:
583
0
    case 162:
584
0
    case 163:
585
0
    case 164:
586
0
    case 165:
587
0
    case 166:
588
0
    case 167:
589
0
    case 168:
590
0
    case 169:
591
0
    case 170:
592
0
    case 171:
593
0
    case 172:
594
0
    case 173:
595
0
    case 174:
596
0
    case 175:
597
0
    case 176:
598
0
    case 177:
599
0
    case 178:
600
0
    case 179:
601
0
    case 180:
602
0
    case 181:
603
0
    case 182:
604
0
    case 183:
605
0
    case 184:
606
0
    case 185:
607
0
    case 186:
608
0
    case 187:
609
0
    case 188:
610
0
    case 189:
611
0
    case 190:
612
0
    case 191:
613
0
    case 192:
614
0
    case 193:
615
0
    case 194:
616
0
    case 195:
617
0
    case 196:
618
0
    case 197:
619
0
    case 198:
620
0
    case 199:
621
0
    case 200:
622
0
    case 201:
623
0
    case 202:
624
0
    case 203:
625
0
    case 204:
626
0
    case 205:
627
0
    case 206:
628
0
    case 207:
629
0
    case 208:
630
0
    case 209:
631
0
    case 210:
632
0
    case 211:
633
0
    case 212:
634
0
    case 213:
635
0
    case 214:
636
0
    case 215:
637
0
    case 216:
638
0
    case 217:
639
0
    case 218:
640
0
    case 219:
641
0
    case 220:
642
0
    case 221:
643
0
    case 222:
644
0
    case 223:
645
0
    case 224:
646
0
    case 225:
647
0
    case 226:
648
0
    case 227:
649
0
    case 228:
650
0
    case 229:
651
0
    case 230:
652
0
    case 231:
653
0
    case 232:
654
0
    case 233:
655
0
    case 234:
656
0
    case 235:
657
0
    case 236:
658
0
    case 237:
659
0
    case 238:
660
0
    case 239:
661
0
    case 240:
662
0
    case 241:
663
0
    case 242:
664
0
    case 243:
665
0
    case 244:
666
0
    case 245:
667
0
    case 246:
668
0
    case 247:
669
0
    case 248:
670
0
    case 249:
671
0
    case 250:
672
0
    case 251:
673
0
    case 252:
674
0
    case 253:
675
0
    case 254:
676
0
    case 255:
677
0
      if (NULL == obj->socks4a_addr_hostname)
678
0
        return "Missing socks4a_addr_hostname";
679
0
      break;
680
681
0
    default:
682
0
      break;
683
0
  }
684
0
  return NULL;
685
0
}
686
687
ssize_t
688
socks4_client_request_encoded_len(const socks4_client_request_t *obj)
689
0
{
690
0
  ssize_t result = 0;
691
692
0
  if (NULL != socks4_client_request_check(obj))
693
0
     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
0
    case 2:
714
0
    case 3:
715
0
    case 4:
716
0
    case 5:
717
0
    case 6:
718
0
    case 7:
719
0
    case 8:
720
0
    case 9:
721
0
    case 10:
722
0
    case 11:
723
0
    case 12:
724
0
    case 13:
725
0
    case 14:
726
0
    case 15:
727
0
    case 16:
728
0
    case 17:
729
0
    case 18:
730
0
    case 19:
731
0
    case 20:
732
0
    case 21:
733
0
    case 22:
734
0
    case 23:
735
0
    case 24:
736
0
    case 25:
737
0
    case 26:
738
0
    case 27:
739
0
    case 28:
740
0
    case 29:
741
0
    case 30:
742
0
    case 31:
743
0
    case 32:
744
0
    case 33:
745
0
    case 34:
746
0
    case 35:
747
0
    case 36:
748
0
    case 37:
749
0
    case 38:
750
0
    case 39:
751
0
    case 40:
752
0
    case 41:
753
0
    case 42:
754
0
    case 43:
755
0
    case 44:
756
0
    case 45:
757
0
    case 46:
758
0
    case 47:
759
0
    case 48:
760
0
    case 49:
761
0
    case 50:
762
0
    case 51:
763
0
    case 52:
764
0
    case 53:
765
0
    case 54:
766
0
    case 55:
767
0
    case 56:
768
0
    case 57:
769
0
    case 58:
770
0
    case 59:
771
0
    case 60:
772
0
    case 61:
773
0
    case 62:
774
0
    case 63:
775
0
    case 64:
776
0
    case 65:
777
0
    case 66:
778
0
    case 67:
779
0
    case 68:
780
0
    case 69:
781
0
    case 70:
782
0
    case 71:
783
0
    case 72:
784
0
    case 73:
785
0
    case 74:
786
0
    case 75:
787
0
    case 76:
788
0
    case 77:
789
0
    case 78:
790
0
    case 79:
791
0
    case 80:
792
0
    case 81:
793
0
    case 82:
794
0
    case 83:
795
0
    case 84:
796
0
    case 85:
797
0
    case 86:
798
0
    case 87:
799
0
    case 88:
800
0
    case 89:
801
0
    case 90:
802
0
    case 91:
803
0
    case 92:
804
0
    case 93:
805
0
    case 94:
806
0
    case 95:
807
0
    case 96:
808
0
    case 97:
809
0
    case 98:
810
0
    case 99:
811
0
    case 100:
812
0
    case 101:
813
0
    case 102:
814
0
    case 103:
815
0
    case 104:
816
0
    case 105:
817
0
    case 106:
818
0
    case 107:
819
0
    case 108:
820
0
    case 109:
821
0
    case 110:
822
0
    case 111:
823
0
    case 112:
824
0
    case 113:
825
0
    case 114:
826
0
    case 115:
827
0
    case 116:
828
0
    case 117:
829
0
    case 118:
830
0
    case 119:
831
0
    case 120:
832
0
    case 121:
833
0
    case 122:
834
0
    case 123:
835
0
    case 124:
836
0
    case 125:
837
0
    case 126:
838
0
    case 127:
839
0
    case 128:
840
0
    case 129:
841
0
    case 130:
842
0
    case 131:
843
0
    case 132:
844
0
    case 133:
845
0
    case 134:
846
0
    case 135:
847
0
    case 136:
848
0
    case 137:
849
0
    case 138:
850
0
    case 139:
851
0
    case 140:
852
0
    case 141:
853
0
    case 142:
854
0
    case 143:
855
0
    case 144:
856
0
    case 145:
857
0
    case 146:
858
0
    case 147:
859
0
    case 148:
860
0
    case 149:
861
0
    case 150:
862
0
    case 151:
863
0
    case 152:
864
0
    case 153:
865
0
    case 154:
866
0
    case 155:
867
0
    case 156:
868
0
    case 157:
869
0
    case 158:
870
0
    case 159:
871
0
    case 160:
872
0
    case 161:
873
0
    case 162:
874
0
    case 163:
875
0
    case 164:
876
0
    case 165:
877
0
    case 166:
878
0
    case 167:
879
0
    case 168:
880
0
    case 169:
881
0
    case 170:
882
0
    case 171:
883
0
    case 172:
884
0
    case 173:
885
0
    case 174:
886
0
    case 175:
887
0
    case 176:
888
0
    case 177:
889
0
    case 178:
890
0
    case 179:
891
0
    case 180:
892
0
    case 181:
893
0
    case 182:
894
0
    case 183:
895
0
    case 184:
896
0
    case 185:
897
0
    case 186:
898
0
    case 187:
899
0
    case 188:
900
0
    case 189:
901
0
    case 190:
902
0
    case 191:
903
0
    case 192:
904
0
    case 193:
905
0
    case 194:
906
0
    case 195:
907
0
    case 196:
908
0
    case 197:
909
0
    case 198:
910
0
    case 199:
911
0
    case 200:
912
0
    case 201:
913
0
    case 202:
914
0
    case 203:
915
0
    case 204:
916
0
    case 205:
917
0
    case 206:
918
0
    case 207:
919
0
    case 208:
920
0
    case 209:
921
0
    case 210:
922
0
    case 211:
923
0
    case 212:
924
0
    case 213:
925
0
    case 214:
926
0
    case 215:
927
0
    case 216:
928
0
    case 217:
929
0
    case 218:
930
0
    case 219:
931
0
    case 220:
932
0
    case 221:
933
0
    case 222:
934
0
    case 223:
935
0
    case 224:
936
0
    case 225:
937
0
    case 226:
938
0
    case 227:
939
0
    case 228:
940
0
    case 229:
941
0
    case 230:
942
0
    case 231:
943
0
    case 232:
944
0
    case 233:
945
0
    case 234:
946
0
    case 235:
947
0
    case 236:
948
0
    case 237:
949
0
    case 238:
950
0
    case 239:
951
0
    case 240:
952
0
    case 241:
953
0
    case 242:
954
0
    case 243:
955
0
    case 244:
956
0
    case 245:
957
0
    case 246:
958
0
    case 247:
959
0
    case 248:
960
0
    case 249:
961
0
    case 250:
962
0
    case 251:
963
0
    case 252:
964
0
    case 253:
965
0
    case 254:
966
0
    case 255:
967
968
      /* Length of nulterm socks4a_addr_hostname */
969
0
      result += strlen(obj->socks4a_addr_hostname) + 1;
970
0
      break;
971
972
0
    default:
973
0
      break;
974
0
  }
975
0
  return result;
976
0
}
977
int
978
socks4_client_request_clear_errors(socks4_client_request_t *obj)
979
0
{
980
0
  int r = obj->trunnel_error_code_;
981
0
  obj->trunnel_error_code_ = 0;
982
0
  return r;
983
0
}
984
ssize_t
985
socks4_client_request_encode(uint8_t *output, const size_t avail, const socks4_client_request_t *obj)
986
0
{
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
0
  {
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
0
  }
1039
1040
  /* Encode union socks4a_addr[addr] */
1041
0
  trunnel_assert(written <= avail);
1042
0
  switch (obj->addr) {
1043
1044
0
    case 1:
1045
0
    case 2:
1046
0
    case 3:
1047
0
    case 4:
1048
0
    case 5:
1049
0
    case 6:
1050
0
    case 7:
1051
0
    case 8:
1052
0
    case 9:
1053
0
    case 10:
1054
0
    case 11:
1055
0
    case 12:
1056
0
    case 13:
1057
0
    case 14:
1058
0
    case 15:
1059
0
    case 16:
1060
0
    case 17:
1061
0
    case 18:
1062
0
    case 19:
1063
0
    case 20:
1064
0
    case 21:
1065
0
    case 22:
1066
0
    case 23:
1067
0
    case 24:
1068
0
    case 25:
1069
0
    case 26:
1070
0
    case 27:
1071
0
    case 28:
1072
0
    case 29:
1073
0
    case 30:
1074
0
    case 31:
1075
0
    case 32:
1076
0
    case 33:
1077
0
    case 34:
1078
0
    case 35:
1079
0
    case 36:
1080
0
    case 37:
1081
0
    case 38:
1082
0
    case 39:
1083
0
    case 40:
1084
0
    case 41:
1085
0
    case 42:
1086
0
    case 43:
1087
0
    case 44:
1088
0
    case 45:
1089
0
    case 46:
1090
0
    case 47:
1091
0
    case 48:
1092
0
    case 49:
1093
0
    case 50:
1094
0
    case 51:
1095
0
    case 52:
1096
0
    case 53:
1097
0
    case 54:
1098
0
    case 55:
1099
0
    case 56:
1100
0
    case 57:
1101
0
    case 58:
1102
0
    case 59:
1103
0
    case 60:
1104
0
    case 61:
1105
0
    case 62:
1106
0
    case 63:
1107
0
    case 64:
1108
0
    case 65:
1109
0
    case 66:
1110
0
    case 67:
1111
0
    case 68:
1112
0
    case 69:
1113
0
    case 70:
1114
0
    case 71:
1115
0
    case 72:
1116
0
    case 73:
1117
0
    case 74:
1118
0
    case 75:
1119
0
    case 76:
1120
0
    case 77:
1121
0
    case 78:
1122
0
    case 79:
1123
0
    case 80:
1124
0
    case 81:
1125
0
    case 82:
1126
0
    case 83:
1127
0
    case 84:
1128
0
    case 85:
1129
0
    case 86:
1130
0
    case 87:
1131
0
    case 88:
1132
0
    case 89:
1133
0
    case 90:
1134
0
    case 91:
1135
0
    case 92:
1136
0
    case 93:
1137
0
    case 94:
1138
0
    case 95:
1139
0
    case 96:
1140
0
    case 97:
1141
0
    case 98:
1142
0
    case 99:
1143
0
    case 100:
1144
0
    case 101:
1145
0
    case 102:
1146
0
    case 103:
1147
0
    case 104:
1148
0
    case 105:
1149
0
    case 106:
1150
0
    case 107:
1151
0
    case 108:
1152
0
    case 109:
1153
0
    case 110:
1154
0
    case 111:
1155
0
    case 112:
1156
0
    case 113:
1157
0
    case 114:
1158
0
    case 115:
1159
0
    case 116:
1160
0
    case 117:
1161
0
    case 118:
1162
0
    case 119:
1163
0
    case 120:
1164
0
    case 121:
1165
0
    case 122:
1166
0
    case 123:
1167
0
    case 124:
1168
0
    case 125:
1169
0
    case 126:
1170
0
    case 127:
1171
0
    case 128:
1172
0
    case 129:
1173
0
    case 130:
1174
0
    case 131:
1175
0
    case 132:
1176
0
    case 133:
1177
0
    case 134:
1178
0
    case 135:
1179
0
    case 136:
1180
0
    case 137:
1181
0
    case 138:
1182
0
    case 139:
1183
0
    case 140:
1184
0
    case 141:
1185
0
    case 142:
1186
0
    case 143:
1187
0
    case 144:
1188
0
    case 145:
1189
0
    case 146:
1190
0
    case 147:
1191
0
    case 148:
1192
0
    case 149:
1193
0
    case 150:
1194
0
    case 151:
1195
0
    case 152:
1196
0
    case 153:
1197
0
    case 154:
1198
0
    case 155:
1199
0
    case 156:
1200
0
    case 157:
1201
0
    case 158:
1202
0
    case 159:
1203
0
    case 160:
1204
0
    case 161:
1205
0
    case 162:
1206
0
    case 163:
1207
0
    case 164:
1208
0
    case 165:
1209
0
    case 166:
1210
0
    case 167:
1211
0
    case 168:
1212
0
    case 169:
1213
0
    case 170:
1214
0
    case 171:
1215
0
    case 172:
1216
0
    case 173:
1217
0
    case 174:
1218
0
    case 175:
1219
0
    case 176:
1220
0
    case 177:
1221
0
    case 178:
1222
0
    case 179:
1223
0
    case 180:
1224
0
    case 181:
1225
0
    case 182:
1226
0
    case 183:
1227
0
    case 184:
1228
0
    case 185:
1229
0
    case 186:
1230
0
    case 187:
1231
0
    case 188:
1232
0
    case 189:
1233
0
    case 190:
1234
0
    case 191:
1235
0
    case 192:
1236
0
    case 193:
1237
0
    case 194:
1238
0
    case 195:
1239
0
    case 196:
1240
0
    case 197:
1241
0
    case 198:
1242
0
    case 199:
1243
0
    case 200:
1244
0
    case 201:
1245
0
    case 202:
1246
0
    case 203:
1247
0
    case 204:
1248
0
    case 205:
1249
0
    case 206:
1250
0
    case 207:
1251
0
    case 208:
1252
0
    case 209:
1253
0
    case 210:
1254
0
    case 211:
1255
0
    case 212:
1256
0
    case 213:
1257
0
    case 214:
1258
0
    case 215:
1259
0
    case 216:
1260
0
    case 217:
1261
0
    case 218:
1262
0
    case 219:
1263
0
    case 220:
1264
0
    case 221:
1265
0
    case 222:
1266
0
    case 223:
1267
0
    case 224:
1268
0
    case 225:
1269
0
    case 226:
1270
0
    case 227:
1271
0
    case 228:
1272
0
    case 229:
1273
0
    case 230:
1274
0
    case 231:
1275
0
    case 232:
1276
0
    case 233:
1277
0
    case 234:
1278
0
    case 235:
1279
0
    case 236:
1280
0
    case 237:
1281
0
    case 238:
1282
0
    case 239:
1283
0
    case 240:
1284
0
    case 241:
1285
0
    case 242:
1286
0
    case 243:
1287
0
    case 244:
1288
0
    case 245:
1289
0
    case 246:
1290
0
    case 247:
1291
0
    case 248:
1292
0
    case 249:
1293
0
    case 250:
1294
0
    case 251:
1295
0
    case 252:
1296
0
    case 253:
1297
0
    case 254:
1298
0
    case 255:
1299
1300
      /* Encode nulterm socks4a_addr_hostname */
1301
0
      {
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
0
      }
1309
0
      break;
1310
1311
0
    default:
1312
0
      break;
1313
0
  }
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
0
 fail:
1335
0
  trunnel_assert(result < 0);
1336
0
  return result;
1337
0
}
1338
1339
/** As socks4_client_request_parse(), but do not allocate the output
1340
 * object.
1341
 */
1342
static ssize_t
1343
socks4_client_request_parse_into(socks4_client_request_t *obj, const uint8_t *input, const size_t len_in)
1344
0
{
1345
0
  const uint8_t *ptr = input;
1346
0
  size_t remaining = len_in;
1347
0
  ssize_t result = 0;
1348
0
  (void)result;
1349
1350
  /* Parse u8 version IN [4] */
1351
0
  CHECK_REMAINING(1, truncated);
1352
0
  obj->version = (trunnel_get_uint8(ptr));
1353
0
  remaining -= 1; ptr += 1;
1354
0
  if (! (obj->version == 4))
1355
0
    goto fail;
1356
1357
  /* Parse u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR] */
1358
0
  CHECK_REMAINING(1, truncated);
1359
0
  obj->command = (trunnel_get_uint8(ptr));
1360
0
  remaining -= 1; ptr += 1;
1361
0
  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
0
  CHECK_REMAINING(2, truncated);
1366
0
  obj->port = trunnel_ntohs(trunnel_get_uint16(ptr));
1367
0
  remaining -= 2; ptr += 2;
1368
1369
  /* Parse u32 addr */
1370
0
  CHECK_REMAINING(4, truncated);
1371
0
  obj->addr = trunnel_ntohl(trunnel_get_uint32(ptr));
1372
0
  remaining -= 4; ptr += 4;
1373
1374
  /* Parse nulterm username */
1375
0
  {
1376
0
    uint8_t *eos = (uint8_t*)memchr(ptr, 0, remaining);
1377
0
    size_t memlen;
1378
0
    if (eos == NULL)
1379
0
      goto truncated;
1380
0
    trunnel_assert(eos >= ptr);
1381
0
    trunnel_assert((size_t)(eos - ptr) < SIZE_MAX - 1);
1382
0
    memlen = ((size_t)(eos - ptr)) + 1;
1383
0
    if (!(obj->username = trunnel_malloc(memlen)))
1384
0
      goto fail;
1385
0
    memcpy(obj->username, ptr, memlen);
1386
0
    remaining -= memlen; ptr += memlen;
1387
0
  }
1388
1389
  /* Parse union socks4a_addr[addr] */
1390
0
  switch (obj->addr) {
1391
1392
0
    case 1:
1393
0
    case 2:
1394
0
    case 3:
1395
0
    case 4:
1396
0
    case 5:
1397
0
    case 6:
1398
0
    case 7:
1399
0
    case 8:
1400
0
    case 9:
1401
0
    case 10:
1402
0
    case 11:
1403
0
    case 12:
1404
0
    case 13:
1405
0
    case 14:
1406
0
    case 15:
1407
0
    case 16:
1408
0
    case 17:
1409
0
    case 18:
1410
0
    case 19:
1411
0
    case 20:
1412
0
    case 21:
1413
0
    case 22:
1414
0
    case 23:
1415
0
    case 24:
1416
0
    case 25:
1417
0
    case 26:
1418
0
    case 27:
1419
0
    case 28:
1420
0
    case 29:
1421
0
    case 30:
1422
0
    case 31:
1423
0
    case 32:
1424
0
    case 33:
1425
0
    case 34:
1426
0
    case 35:
1427
0
    case 36:
1428
0
    case 37:
1429
0
    case 38:
1430
0
    case 39:
1431
0
    case 40:
1432
0
    case 41:
1433
0
    case 42:
1434
0
    case 43:
1435
0
    case 44:
1436
0
    case 45:
1437
0
    case 46:
1438
0
    case 47:
1439
0
    case 48:
1440
0
    case 49:
1441
0
    case 50:
1442
0
    case 51:
1443
0
    case 52:
1444
0
    case 53:
1445
0
    case 54:
1446
0
    case 55:
1447
0
    case 56:
1448
0
    case 57:
1449
0
    case 58:
1450
0
    case 59:
1451
0
    case 60:
1452
0
    case 61:
1453
0
    case 62:
1454
0
    case 63:
1455
0
    case 64:
1456
0
    case 65:
1457
0
    case 66:
1458
0
    case 67:
1459
0
    case 68:
1460
0
    case 69:
1461
0
    case 70:
1462
0
    case 71:
1463
0
    case 72:
1464
0
    case 73:
1465
0
    case 74:
1466
0
    case 75:
1467
0
    case 76:
1468
0
    case 77:
1469
0
    case 78:
1470
0
    case 79:
1471
0
    case 80:
1472
0
    case 81:
1473
0
    case 82:
1474
0
    case 83:
1475
0
    case 84:
1476
0
    case 85:
1477
0
    case 86:
1478
0
    case 87:
1479
0
    case 88:
1480
0
    case 89:
1481
0
    case 90:
1482
0
    case 91:
1483
0
    case 92:
1484
0
    case 93:
1485
0
    case 94:
1486
0
    case 95:
1487
0
    case 96:
1488
0
    case 97:
1489
0
    case 98:
1490
0
    case 99:
1491
0
    case 100:
1492
0
    case 101:
1493
0
    case 102:
1494
0
    case 103:
1495
0
    case 104:
1496
0
    case 105:
1497
0
    case 106:
1498
0
    case 107:
1499
0
    case 108:
1500
0
    case 109:
1501
0
    case 110:
1502
0
    case 111:
1503
0
    case 112:
1504
0
    case 113:
1505
0
    case 114:
1506
0
    case 115:
1507
0
    case 116:
1508
0
    case 117:
1509
0
    case 118:
1510
0
    case 119:
1511
0
    case 120:
1512
0
    case 121:
1513
0
    case 122:
1514
0
    case 123:
1515
0
    case 124:
1516
0
    case 125:
1517
0
    case 126:
1518
0
    case 127:
1519
0
    case 128:
1520
0
    case 129:
1521
0
    case 130:
1522
0
    case 131:
1523
0
    case 132:
1524
0
    case 133:
1525
0
    case 134:
1526
0
    case 135:
1527
0
    case 136:
1528
0
    case 137:
1529
0
    case 138:
1530
0
    case 139:
1531
0
    case 140:
1532
0
    case 141:
1533
0
    case 142:
1534
0
    case 143:
1535
0
    case 144:
1536
0
    case 145:
1537
0
    case 146:
1538
0
    case 147:
1539
0
    case 148:
1540
0
    case 149:
1541
0
    case 150:
1542
0
    case 151:
1543
0
    case 152:
1544
0
    case 153:
1545
0
    case 154:
1546
0
    case 155:
1547
0
    case 156:
1548
0
    case 157:
1549
0
    case 158:
1550
0
    case 159:
1551
0
    case 160:
1552
0
    case 161:
1553
0
    case 162:
1554
0
    case 163:
1555
0
    case 164:
1556
0
    case 165:
1557
0
    case 166:
1558
0
    case 167:
1559
0
    case 168:
1560
0
    case 169:
1561
0
    case 170:
1562
0
    case 171:
1563
0
    case 172:
1564
0
    case 173:
1565
0
    case 174:
1566
0
    case 175:
1567
0
    case 176:
1568
0
    case 177:
1569
0
    case 178:
1570
0
    case 179:
1571
0
    case 180:
1572
0
    case 181:
1573
0
    case 182:
1574
0
    case 183:
1575
0
    case 184:
1576
0
    case 185:
1577
0
    case 186:
1578
0
    case 187:
1579
0
    case 188:
1580
0
    case 189:
1581
0
    case 190:
1582
0
    case 191:
1583
0
    case 192:
1584
0
    case 193:
1585
0
    case 194:
1586
0
    case 195:
1587
0
    case 196:
1588
0
    case 197:
1589
0
    case 198:
1590
0
    case 199:
1591
0
    case 200:
1592
0
    case 201:
1593
0
    case 202:
1594
0
    case 203:
1595
0
    case 204:
1596
0
    case 205:
1597
0
    case 206:
1598
0
    case 207:
1599
0
    case 208:
1600
0
    case 209:
1601
0
    case 210:
1602
0
    case 211:
1603
0
    case 212:
1604
0
    case 213:
1605
0
    case 214:
1606
0
    case 215:
1607
0
    case 216:
1608
0
    case 217:
1609
0
    case 218:
1610
0
    case 219:
1611
0
    case 220:
1612
0
    case 221:
1613
0
    case 222:
1614
0
    case 223:
1615
0
    case 224:
1616
0
    case 225:
1617
0
    case 226:
1618
0
    case 227:
1619
0
    case 228:
1620
0
    case 229:
1621
0
    case 230:
1622
0
    case 231:
1623
0
    case 232:
1624
0
    case 233:
1625
0
    case 234:
1626
0
    case 235:
1627
0
    case 236:
1628
0
    case 237:
1629
0
    case 238:
1630
0
    case 239:
1631
0
    case 240:
1632
0
    case 241:
1633
0
    case 242:
1634
0
    case 243:
1635
0
    case 244:
1636
0
    case 245:
1637
0
    case 246:
1638
0
    case 247:
1639
0
    case 248:
1640
0
    case 249:
1641
0
    case 250:
1642
0
    case 251:
1643
0
    case 252:
1644
0
    case 253:
1645
0
    case 254:
1646
0
    case 255:
1647
1648
      /* Parse nulterm socks4a_addr_hostname */
1649
0
      {
1650
0
        uint8_t *eos = (uint8_t*)memchr(ptr, 0, remaining);
1651
0
        size_t memlen;
1652
0
        if (eos == NULL)
1653
0
          goto truncated;
1654
0
        trunnel_assert(eos >= ptr);
1655
0
        trunnel_assert((size_t)(eos - ptr) < SIZE_MAX - 1);
1656
0
        memlen = ((size_t)(eos - ptr)) + 1;
1657
0
        if (!(obj->socks4a_addr_hostname = trunnel_malloc(memlen)))
1658
0
          goto fail;
1659
0
        memcpy(obj->socks4a_addr_hostname, ptr, memlen);
1660
0
        remaining -= memlen; ptr += memlen;
1661
0
      }
1662
0
      break;
1663
1664
0
    default:
1665
0
      break;
1666
0
  }
1667
0
  trunnel_assert(ptr + remaining == input + len_in);
1668
0
  return len_in - remaining;
1669
1670
0
 truncated:
1671
0
  return -2;
1672
0
 fail:
1673
0
  result = -1;
1674
0
  return result;
1675
0
}
1676
1677
ssize_t
1678
socks4_client_request_parse(socks4_client_request_t **output, const uint8_t *input, const size_t len_in)
1679
0
{
1680
0
  ssize_t result;
1681
0
  *output = socks4_client_request_new();
1682
0
  if (NULL == *output)
1683
0
    return -1;
1684
0
  result = socks4_client_request_parse_into(*output, input, len_in);
1685
0
  if (result < 0) {
1686
0
    socks4_client_request_free(*output);
1687
0
    *output = NULL;
1688
0
  }
1689
0
  return result;
1690
0
}
1691
socks4_server_reply_t *
1692
socks4_server_reply_new(void)
1693
0
{
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
0
  return val;
1698
0
}
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
0
{
1705
0
  (void) obj;
1706
0
}
1707
1708
void
1709
socks4_server_reply_free(socks4_server_reply_t *obj)
1710
0
{
1711
0
  if (obj == NULL)
1712
0
    return;
1713
0
  socks4_server_reply_clear(obj);
1714
0
  trunnel_memwipe(obj, sizeof(socks4_server_reply_t));
1715
0
  trunnel_free_(obj);
1716
0
}
1717
1718
uint8_t
1719
socks4_server_reply_get_version(const socks4_server_reply_t *inp)
1720
0
{
1721
0
  return inp->version;
1722
0
}
1723
int
1724
socks4_server_reply_set_version(socks4_server_reply_t *inp, uint8_t val)
1725
0
{
1726
0
  if (! ((val == 0 || val == 4))) {
1727
0
     TRUNNEL_SET_ERROR_CODE(inp);
1728
0
     return -1;
1729
0
  }
1730
0
  inp->version = val;
1731
0
  return 0;
1732
0
}
1733
uint8_t
1734
socks4_server_reply_get_status(const socks4_server_reply_t *inp)
1735
0
{
1736
0
  return inp->status;
1737
0
}
1738
int
1739
socks4_server_reply_set_status(socks4_server_reply_t *inp, uint8_t val)
1740
0
{
1741
0
  inp->status = val;
1742
0
  return 0;
1743
0
}
1744
uint16_t
1745
socks4_server_reply_get_port(const socks4_server_reply_t *inp)
1746
0
{
1747
0
  return inp->port;
1748
0
}
1749
int
1750
socks4_server_reply_set_port(socks4_server_reply_t *inp, uint16_t val)
1751
0
{
1752
0
  inp->port = val;
1753
0
  return 0;
1754
0
}
1755
uint32_t
1756
socks4_server_reply_get_addr(const socks4_server_reply_t *inp)
1757
0
{
1758
0
  return inp->addr;
1759
0
}
1760
int
1761
socks4_server_reply_set_addr(socks4_server_reply_t *inp, uint32_t val)
1762
0
{
1763
0
  inp->addr = val;
1764
0
  return 0;
1765
0
}
1766
const char *
1767
socks4_server_reply_check(const socks4_server_reply_t *obj)
1768
0
{
1769
0
  if (obj == NULL)
1770
0
    return "Object was NULL";
1771
0
  if (obj->trunnel_error_code_)
1772
0
    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
0
  return NULL;
1776
0
}
1777
1778
ssize_t
1779
socks4_server_reply_encoded_len(const socks4_server_reply_t *obj)
1780
0
{
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
0
  result += 1;
1789
1790
  /* Length of u8 status */
1791
0
  result += 1;
1792
1793
  /* Length of u16 port */
1794
0
  result += 2;
1795
1796
  /* Length of u32 addr */
1797
0
  result += 4;
1798
0
  return result;
1799
0
}
1800
int
1801
socks4_server_reply_clear_errors(socks4_server_reply_t *obj)
1802
0
{
1803
0
  int r = obj->trunnel_error_code_;
1804
0
  obj->trunnel_error_code_ = 0;
1805
0
  return r;
1806
0
}
1807
ssize_t
1808
socks4_server_reply_encode(uint8_t *output, const size_t avail, const socks4_server_reply_t *obj)
1809
0
{
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
0
  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
0
 fail:
1873
0
  trunnel_assert(result < 0);
1874
0
  return result;
1875
0
}
1876
1877
/** As socks4_server_reply_parse(), but do not allocate the output
1878
 * object.
1879
 */
1880
static ssize_t
1881
socks4_server_reply_parse_into(socks4_server_reply_t *obj, const uint8_t *input, const size_t len_in)
1882
0
{
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
0
  return len_in - remaining;
1911
1912
0
 truncated:
1913
0
  return -2;
1914
0
 fail:
1915
0
  result = -1;
1916
0
  return result;
1917
0
}
1918
1919
ssize_t
1920
socks4_server_reply_parse(socks4_server_reply_t **output, const uint8_t *input, const size_t len_in)
1921
0
{
1922
0
  ssize_t result;
1923
0
  *output = socks4_server_reply_new();
1924
0
  if (NULL == *output)
1925
0
    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
0
  }
1931
0
  return result;
1932
0
}
1933
socks5_client_userpass_auth_t *
1934
socks5_client_userpass_auth_new(void)
1935
0
{
1936
0
  socks5_client_userpass_auth_t *val = trunnel_calloc(1, sizeof(socks5_client_userpass_auth_t));
1937
0
  if (NULL == val)
1938
0
    return NULL;
1939
0
  val->version = 1;
1940
0
  return val;
1941
0
}
1942
1943
/** Release all storage held inside 'obj', but do not free 'obj'.
1944
 */
1945
static void
1946
socks5_client_userpass_auth_clear(socks5_client_userpass_auth_t *obj)
1947
0
{
1948
0
  (void) obj;
1949
0
  TRUNNEL_DYNARRAY_WIPE(&obj->username);
1950
0
  TRUNNEL_DYNARRAY_CLEAR(&obj->username);
1951
0
  TRUNNEL_DYNARRAY_WIPE(&obj->passwd);
1952
0
  TRUNNEL_DYNARRAY_CLEAR(&obj->passwd);
1953
0
}
1954
1955
void
1956
socks5_client_userpass_auth_free(socks5_client_userpass_auth_t *obj)
1957
0
{
1958
0
  if (obj == NULL)
1959
0
    return;
1960
0
  socks5_client_userpass_auth_clear(obj);
1961
0
  trunnel_memwipe(obj, sizeof(socks5_client_userpass_auth_t));
1962
0
  trunnel_free_(obj);
1963
0
}
1964
1965
uint8_t
1966
socks5_client_userpass_auth_get_version(const socks5_client_userpass_auth_t *inp)
1967
0
{
1968
0
  return inp->version;
1969
0
}
1970
int
1971
socks5_client_userpass_auth_set_version(socks5_client_userpass_auth_t *inp, uint8_t val)
1972
0
{
1973
0
  if (! ((val == 1))) {
1974
0
     TRUNNEL_SET_ERROR_CODE(inp);
1975
0
     return -1;
1976
0
  }
1977
0
  inp->version = val;
1978
0
  return 0;
1979
0
}
1980
uint8_t
1981
socks5_client_userpass_auth_get_username_len(const socks5_client_userpass_auth_t *inp)
1982
0
{
1983
0
  return inp->username_len;
1984
0
}
1985
int
1986
socks5_client_userpass_auth_set_username_len(socks5_client_userpass_auth_t *inp, uint8_t val)
1987
0
{
1988
0
  inp->username_len = val;
1989
0
  return 0;
1990
0
}
1991
size_t
1992
socks5_client_userpass_auth_getlen_username(const socks5_client_userpass_auth_t *inp)
1993
0
{
1994
0
  return TRUNNEL_DYNARRAY_LEN(&inp->username);
1995
0
}
1996
1997
char
1998
socks5_client_userpass_auth_get_username(socks5_client_userpass_auth_t *inp, size_t idx)
1999
0
{
2000
0
  return TRUNNEL_DYNARRAY_GET(&inp->username, idx);
2001
0
}
2002
2003
char
2004
socks5_client_userpass_auth_getconst_username(const socks5_client_userpass_auth_t *inp, size_t idx)
2005
0
{
2006
0
  return socks5_client_userpass_auth_get_username((socks5_client_userpass_auth_t*)inp, idx);
2007
0
}
2008
int
2009
socks5_client_userpass_auth_set_username(socks5_client_userpass_auth_t *inp, size_t idx, char elt)
2010
0
{
2011
0
  TRUNNEL_DYNARRAY_SET(&inp->username, idx, elt);
2012
0
  return 0;
2013
0
}
2014
int
2015
socks5_client_userpass_auth_add_username(socks5_client_userpass_auth_t *inp, char elt)
2016
0
{
2017
0
#if SIZE_MAX >= UINT8_MAX
2018
0
  if (inp->username.n_ == UINT8_MAX)
2019
0
    goto trunnel_alloc_failed;
2020
0
#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
0
}
2027
2028
char *
2029
socks5_client_userpass_auth_getarray_username(socks5_client_userpass_auth_t *inp)
2030
0
{
2031
0
  return inp->username.elts_;
2032
0
}
2033
const char  *
2034
socks5_client_userpass_auth_getconstarray_username(const socks5_client_userpass_auth_t *inp)
2035
0
{
2036
0
  return (const char  *)socks5_client_userpass_auth_getarray_username((socks5_client_userpass_auth_t*)inp);
2037
0
}
2038
int
2039
socks5_client_userpass_auth_setlen_username(socks5_client_userpass_auth_t *inp, size_t newlen)
2040
0
{
2041
0
#if UINT8_MAX < SIZE_MAX
2042
0
  if (newlen > UINT8_MAX)
2043
0
    goto trunnel_alloc_failed;
2044
0
#endif
2045
0
  return trunnel_string_setlen(&inp->username, newlen,
2046
0
            &inp->trunnel_error_code_);
2047
0
 trunnel_alloc_failed:
2048
0
  TRUNNEL_SET_ERROR_CODE(inp);
2049
0
  return -1;
2050
0
}
2051
const char *
2052
socks5_client_userpass_auth_getstr_username(socks5_client_userpass_auth_t *inp)
2053
0
{
2054
0
  return trunnel_string_getstr(&inp->username);
2055
0
}
2056
int
2057
socks5_client_userpass_auth_setstr0_username(socks5_client_userpass_auth_t *inp, const char *val, size_t len)
2058
0
{
2059
0
#if UINT8_MAX < SIZE_MAX
2060
0
  if (len > UINT8_MAX) {
2061
0
    TRUNNEL_SET_ERROR_CODE(inp);
2062
0
    return -1;
2063
0
  }
2064
0
#endif
2065
0
  return trunnel_string_setstr0(&inp->username, val, len, &inp->trunnel_error_code_);
2066
0
}
2067
int
2068
socks5_client_userpass_auth_setstr_username(socks5_client_userpass_auth_t *inp, const char *val)
2069
0
{
2070
0
  return socks5_client_userpass_auth_setstr0_username(inp, val, strlen(val));
2071
0
}
2072
uint8_t
2073
socks5_client_userpass_auth_get_passwd_len(const socks5_client_userpass_auth_t *inp)
2074
0
{
2075
0
  return inp->passwd_len;
2076
0
}
2077
int
2078
socks5_client_userpass_auth_set_passwd_len(socks5_client_userpass_auth_t *inp, uint8_t val)
2079
0
{
2080
0
  inp->passwd_len = val;
2081
0
  return 0;
2082
0
}
2083
size_t
2084
socks5_client_userpass_auth_getlen_passwd(const socks5_client_userpass_auth_t *inp)
2085
0
{
2086
0
  return TRUNNEL_DYNARRAY_LEN(&inp->passwd);
2087
0
}
2088
2089
char
2090
socks5_client_userpass_auth_get_passwd(socks5_client_userpass_auth_t *inp, size_t idx)
2091
0
{
2092
0
  return TRUNNEL_DYNARRAY_GET(&inp->passwd, idx);
2093
0
}
2094
2095
char
2096
socks5_client_userpass_auth_getconst_passwd(const socks5_client_userpass_auth_t *inp, size_t idx)
2097
0
{
2098
0
  return socks5_client_userpass_auth_get_passwd((socks5_client_userpass_auth_t*)inp, idx);
2099
0
}
2100
int
2101
socks5_client_userpass_auth_set_passwd(socks5_client_userpass_auth_t *inp, size_t idx, char elt)
2102
0
{
2103
0
  TRUNNEL_DYNARRAY_SET(&inp->passwd, idx, elt);
2104
0
  return 0;
2105
0
}
2106
int
2107
socks5_client_userpass_auth_add_passwd(socks5_client_userpass_auth_t *inp, char elt)
2108
0
{
2109
0
#if SIZE_MAX >= UINT8_MAX
2110
0
  if (inp->passwd.n_ == UINT8_MAX)
2111
0
    goto trunnel_alloc_failed;
2112
0
#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
0
}
2119
2120
char *
2121
socks5_client_userpass_auth_getarray_passwd(socks5_client_userpass_auth_t *inp)
2122
0
{
2123
0
  return inp->passwd.elts_;
2124
0
}
2125
const char  *
2126
socks5_client_userpass_auth_getconstarray_passwd(const socks5_client_userpass_auth_t *inp)
2127
0
{
2128
0
  return (const char  *)socks5_client_userpass_auth_getarray_passwd((socks5_client_userpass_auth_t*)inp);
2129
0
}
2130
int
2131
socks5_client_userpass_auth_setlen_passwd(socks5_client_userpass_auth_t *inp, size_t newlen)
2132
0
{
2133
0
#if UINT8_MAX < SIZE_MAX
2134
0
  if (newlen > UINT8_MAX)
2135
0
    goto trunnel_alloc_failed;
2136
0
#endif
2137
0
  return trunnel_string_setlen(&inp->passwd, newlen,
2138
0
            &inp->trunnel_error_code_);
2139
0
 trunnel_alloc_failed:
2140
0
  TRUNNEL_SET_ERROR_CODE(inp);
2141
0
  return -1;
2142
0
}
2143
const char *
2144
socks5_client_userpass_auth_getstr_passwd(socks5_client_userpass_auth_t *inp)
2145
0
{
2146
0
  return trunnel_string_getstr(&inp->passwd);
2147
0
}
2148
int
2149
socks5_client_userpass_auth_setstr0_passwd(socks5_client_userpass_auth_t *inp, const char *val, size_t len)
2150
0
{
2151
0
#if UINT8_MAX < SIZE_MAX
2152
0
  if (len > UINT8_MAX) {
2153
0
    TRUNNEL_SET_ERROR_CODE(inp);
2154
0
    return -1;
2155
0
  }
2156
0
#endif
2157
0
  return trunnel_string_setstr0(&inp->passwd, val, len, &inp->trunnel_error_code_);
2158
0
}
2159
int
2160
socks5_client_userpass_auth_setstr_passwd(socks5_client_userpass_auth_t *inp, const char *val)
2161
0
{
2162
0
  return socks5_client_userpass_auth_setstr0_passwd(inp, val, strlen(val));
2163
0
}
2164
const char *
2165
socks5_client_userpass_auth_check(const socks5_client_userpass_auth_t *obj)
2166
0
{
2167
0
  if (obj == NULL)
2168
0
    return "Object was NULL";
2169
0
  if (obj->trunnel_error_code_)
2170
0
    return "A set function failed on this object";
2171
0
  if (! (obj->version == 1))
2172
0
    return "Integer out of bounds";
2173
0
  if (TRUNNEL_DYNARRAY_LEN(&obj->username) != obj->username_len)
2174
0
    return "Length mismatch for username";
2175
0
  if (TRUNNEL_DYNARRAY_LEN(&obj->passwd) != obj->passwd_len)
2176
0
    return "Length mismatch for passwd";
2177
0
  return NULL;
2178
0
}
2179
2180
ssize_t
2181
socks5_client_userpass_auth_encoded_len(const socks5_client_userpass_auth_t *obj)
2182
0
{
2183
0
  ssize_t result = 0;
2184
2185
0
  if (NULL != socks5_client_userpass_auth_check(obj))
2186
0
     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
0
}
2205
int
2206
socks5_client_userpass_auth_clear_errors(socks5_client_userpass_auth_t *obj)
2207
0
{
2208
0
  int r = obj->trunnel_error_code_;
2209
0
  obj->trunnel_error_code_ = 0;
2210
0
  return r;
2211
0
}
2212
ssize_t
2213
socks5_client_userpass_auth_encode(uint8_t *output, const size_t avail, const socks5_client_userpass_auth_t *obj)
2214
0
{
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
0
  {
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
0
  }
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
0
  {
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
0
  }
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
0
 fail:
2295
0
  trunnel_assert(result < 0);
2296
0
  return result;
2297
0
}
2298
2299
/** As socks5_client_userpass_auth_parse(), but do not allocate the
2300
 * output object.
2301
 */
2302
static ssize_t
2303
socks5_client_userpass_auth_parse_into(socks5_client_userpass_auth_t *obj, const uint8_t *input, const size_t len_in)
2304
0
{
2305
0
  const uint8_t *ptr = input;
2306
0
  size_t remaining = len_in;
2307
0
  ssize_t result = 0;
2308
0
  (void)result;
2309
2310
  /* Parse u8 version IN [1] */
2311
0
  CHECK_REMAINING(1, truncated);
2312
0
  obj->version = (trunnel_get_uint8(ptr));
2313
0
  remaining -= 1; ptr += 1;
2314
0
  if (! (obj->version == 1))
2315
0
    goto fail;
2316
2317
  /* Parse u8 username_len */
2318
0
  CHECK_REMAINING(1, truncated);
2319
0
  obj->username_len = (trunnel_get_uint8(ptr));
2320
0
  remaining -= 1; ptr += 1;
2321
2322
  /* Parse char username[username_len] */
2323
0
  CHECK_REMAINING(obj->username_len, truncated);
2324
0
  if (socks5_client_userpass_auth_setstr0_username(obj, (const char*)ptr, obj->username_len))
2325
0
    goto fail;
2326
0
  ptr += obj->username_len; remaining -= obj->username_len;
2327
2328
  /* Parse u8 passwd_len */
2329
0
  CHECK_REMAINING(1, truncated);
2330
0
  obj->passwd_len = (trunnel_get_uint8(ptr));
2331
0
  remaining -= 1; ptr += 1;
2332
2333
  /* Parse char passwd[passwd_len] */
2334
0
  CHECK_REMAINING(obj->passwd_len, truncated);
2335
0
  if (socks5_client_userpass_auth_setstr0_passwd(obj, (const char*)ptr, obj->passwd_len))
2336
0
    goto fail;
2337
0
  ptr += obj->passwd_len; remaining -= obj->passwd_len;
2338
0
  trunnel_assert(ptr + remaining == input + len_in);
2339
0
  return len_in - remaining;
2340
2341
0
 truncated:
2342
0
  return -2;
2343
0
 fail:
2344
0
  result = -1;
2345
0
  return result;
2346
0
}
2347
2348
ssize_t
2349
socks5_client_userpass_auth_parse(socks5_client_userpass_auth_t **output, const uint8_t *input, const size_t len_in)
2350
0
{
2351
0
  ssize_t result;
2352
0
  *output = socks5_client_userpass_auth_new();
2353
0
  if (NULL == *output)
2354
0
    return -1;
2355
0
  result = socks5_client_userpass_auth_parse_into(*output, input, len_in);
2356
0
  if (result < 0) {
2357
0
    socks5_client_userpass_auth_free(*output);
2358
0
    *output = NULL;
2359
0
  }
2360
0
  return result;
2361
0
}
2362
socks5_client_version_t *
2363
socks5_client_version_new(void)
2364
0
{
2365
0
  socks5_client_version_t *val = trunnel_calloc(1, sizeof(socks5_client_version_t));
2366
0
  if (NULL == val)
2367
0
    return NULL;
2368
0
  val->version = 5;
2369
0
  return val;
2370
0
}
2371
2372
/** Release all storage held inside 'obj', but do not free 'obj'.
2373
 */
2374
static void
2375
socks5_client_version_clear(socks5_client_version_t *obj)
2376
0
{
2377
0
  (void) obj;
2378
0
  TRUNNEL_DYNARRAY_WIPE(&obj->methods);
2379
0
  TRUNNEL_DYNARRAY_CLEAR(&obj->methods);
2380
0
}
2381
2382
void
2383
socks5_client_version_free(socks5_client_version_t *obj)
2384
0
{
2385
0
  if (obj == NULL)
2386
0
    return;
2387
0
  socks5_client_version_clear(obj);
2388
0
  trunnel_memwipe(obj, sizeof(socks5_client_version_t));
2389
0
  trunnel_free_(obj);
2390
0
}
2391
2392
uint8_t
2393
socks5_client_version_get_version(const socks5_client_version_t *inp)
2394
0
{
2395
0
  return inp->version;
2396
0
}
2397
int
2398
socks5_client_version_set_version(socks5_client_version_t *inp, uint8_t val)
2399
0
{
2400
0
  if (! ((val == 5))) {
2401
0
     TRUNNEL_SET_ERROR_CODE(inp);
2402
0
     return -1;
2403
0
  }
2404
0
  inp->version = val;
2405
0
  return 0;
2406
0
}
2407
uint8_t
2408
socks5_client_version_get_n_methods(const socks5_client_version_t *inp)
2409
0
{
2410
0
  return inp->n_methods;
2411
0
}
2412
int
2413
socks5_client_version_set_n_methods(socks5_client_version_t *inp, uint8_t val)
2414
0
{
2415
0
  inp->n_methods = val;
2416
0
  return 0;
2417
0
}
2418
size_t
2419
socks5_client_version_getlen_methods(const socks5_client_version_t *inp)
2420
0
{
2421
0
  return TRUNNEL_DYNARRAY_LEN(&inp->methods);
2422
0
}
2423
2424
uint8_t
2425
socks5_client_version_get_methods(socks5_client_version_t *inp, size_t idx)
2426
0
{
2427
0
  return TRUNNEL_DYNARRAY_GET(&inp->methods, idx);
2428
0
}
2429
2430
uint8_t
2431
socks5_client_version_getconst_methods(const socks5_client_version_t *inp, size_t idx)
2432
0
{
2433
0
  return socks5_client_version_get_methods((socks5_client_version_t*)inp, idx);
2434
0
}
2435
int
2436
socks5_client_version_set_methods(socks5_client_version_t *inp, size_t idx, uint8_t elt)
2437
0
{
2438
0
  TRUNNEL_DYNARRAY_SET(&inp->methods, idx, elt);
2439
0
  return 0;
2440
0
}
2441
int
2442
socks5_client_version_add_methods(socks5_client_version_t *inp, uint8_t elt)
2443
0
{
2444
0
#if SIZE_MAX >= UINT8_MAX
2445
0
  if (inp->methods.n_ == UINT8_MAX)
2446
0
    goto trunnel_alloc_failed;
2447
0
#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
0
}
2454
2455
uint8_t *
2456
socks5_client_version_getarray_methods(socks5_client_version_t *inp)
2457
0
{
2458
0
  return inp->methods.elts_;
2459
0
}
2460
const uint8_t  *
2461
socks5_client_version_getconstarray_methods(const socks5_client_version_t *inp)
2462
0
{
2463
0
  return (const uint8_t  *)socks5_client_version_getarray_methods((socks5_client_version_t*)inp);
2464
0
}
2465
int
2466
socks5_client_version_setlen_methods(socks5_client_version_t *inp, size_t newlen)
2467
0
{
2468
0
  uint8_t *newptr;
2469
0
#if UINT8_MAX < SIZE_MAX
2470
0
  if (newlen > UINT8_MAX)
2471
0
    goto trunnel_alloc_failed;
2472
0
#endif
2473
0
  newptr = trunnel_dynarray_setlen(&inp->methods.allocated_,
2474
0
                 &inp->methods.n_, inp->methods.elts_, newlen,
2475
0
                 sizeof(inp->methods.elts_[0]), (trunnel_free_fn_t) NULL,
2476
0
                 &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
0
}
2485
const char *
2486
socks5_client_version_check(const socks5_client_version_t *obj)
2487
0
{
2488
0
  if (obj == NULL)
2489
0
    return "Object was NULL";
2490
0
  if (obj->trunnel_error_code_)
2491
0
    return "A set function failed on this object";
2492
0
  if (! (obj->version == 5))
2493
0
    return "Integer out of bounds";
2494
0
  if (TRUNNEL_DYNARRAY_LEN(&obj->methods) != obj->n_methods)
2495
0
    return "Length mismatch for methods";
2496
0
  return NULL;
2497
0
}
2498
2499
ssize_t
2500
socks5_client_version_encoded_len(const socks5_client_version_t *obj)
2501
0
{
2502
0
  ssize_t result = 0;
2503
2504
0
  if (NULL != socks5_client_version_check(obj))
2505
0
     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
0
}
2518
int
2519
socks5_client_version_clear_errors(socks5_client_version_t *obj)
2520
0
{
2521
0
  int r = obj->trunnel_error_code_;
2522
0
  obj->trunnel_error_code_ = 0;
2523
0
  return r;
2524
0
}
2525
ssize_t
2526
socks5_client_version_encode(uint8_t *output, const size_t avail, const socks5_client_version_t *obj)
2527
0
{
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
0
  {
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
0
  }
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
0
 fail:
2589
0
  trunnel_assert(result < 0);
2590
0
  return result;
2591
0
}
2592
2593
/** As socks5_client_version_parse(), but do not allocate the output
2594
 * object.
2595
 */
2596
static ssize_t
2597
socks5_client_version_parse_into(socks5_client_version_t *obj, const uint8_t *input, const size_t len_in)
2598
0
{
2599
0
  const uint8_t *ptr = input;
2600
0
  size_t remaining = len_in;
2601
0
  ssize_t result = 0;
2602
0
  (void)result;
2603
2604
  /* Parse u8 version IN [5] */
2605
0
  CHECK_REMAINING(1, truncated);
2606
0
  obj->version = (trunnel_get_uint8(ptr));
2607
0
  remaining -= 1; ptr += 1;
2608
0
  if (! (obj->version == 5))
2609
0
    goto fail;
2610
2611
  /* Parse u8 n_methods */
2612
0
  CHECK_REMAINING(1, truncated);
2613
0
  obj->n_methods = (trunnel_get_uint8(ptr));
2614
0
  remaining -= 1; ptr += 1;
2615
2616
  /* Parse u8 methods[n_methods] */
2617
0
  CHECK_REMAINING(obj->n_methods, truncated);
2618
0
  TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->methods, obj->n_methods, {});
2619
0
  obj->methods.n_ = obj->n_methods;
2620
0
  if (obj->n_methods)
2621
0
    memcpy(obj->methods.elts_, ptr, obj->n_methods);
2622
0
  ptr += obj->n_methods; remaining -= obj->n_methods;
2623
0
  trunnel_assert(ptr + remaining == input + len_in);
2624
0
  return len_in - remaining;
2625
2626
0
 truncated:
2627
0
  return -2;
2628
0
 trunnel_alloc_failed:
2629
0
  return -1;
2630
0
 fail:
2631
0
  result = -1;
2632
0
  return result;
2633
0
}
2634
2635
ssize_t
2636
socks5_client_version_parse(socks5_client_version_t **output, const uint8_t *input, const size_t len_in)
2637
0
{
2638
0
  ssize_t result;
2639
0
  *output = socks5_client_version_new();
2640
0
  if (NULL == *output)
2641
0
    return -1;
2642
0
  result = socks5_client_version_parse_into(*output, input, len_in);
2643
0
  if (result < 0) {
2644
0
    socks5_client_version_free(*output);
2645
0
    *output = NULL;
2646
0
  }
2647
0
  return result;
2648
0
}
2649
socks5_server_method_t *
2650
socks5_server_method_new(void)
2651
0
{
2652
0
  socks5_server_method_t *val = trunnel_calloc(1, sizeof(socks5_server_method_t));
2653
0
  if (NULL == val)
2654
0
    return NULL;
2655
0
  val->version = 5;
2656
0
  return val;
2657
0
}
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
0
{
2664
0
  (void) obj;
2665
0
}
2666
2667
void
2668
socks5_server_method_free(socks5_server_method_t *obj)
2669
0
{
2670
0
  if (obj == NULL)
2671
0
    return;
2672
0
  socks5_server_method_clear(obj);
2673
0
  trunnel_memwipe(obj, sizeof(socks5_server_method_t));
2674
0
  trunnel_free_(obj);
2675
0
}
2676
2677
uint8_t
2678
socks5_server_method_get_version(const socks5_server_method_t *inp)
2679
0
{
2680
0
  return inp->version;
2681
0
}
2682
int
2683
socks5_server_method_set_version(socks5_server_method_t *inp, uint8_t val)
2684
0
{
2685
0
  if (! ((val == 5))) {
2686
0
     TRUNNEL_SET_ERROR_CODE(inp);
2687
0
     return -1;
2688
0
  }
2689
0
  inp->version = val;
2690
0
  return 0;
2691
0
}
2692
uint8_t
2693
socks5_server_method_get_method(const socks5_server_method_t *inp)
2694
0
{
2695
0
  return inp->method;
2696
0
}
2697
int
2698
socks5_server_method_set_method(socks5_server_method_t *inp, uint8_t val)
2699
0
{
2700
0
  inp->method = val;
2701
0
  return 0;
2702
0
}
2703
const char *
2704
socks5_server_method_check(const socks5_server_method_t *obj)
2705
0
{
2706
0
  if (obj == NULL)
2707
0
    return "Object was NULL";
2708
0
  if (obj->trunnel_error_code_)
2709
0
    return "A set function failed on this object";
2710
0
  if (! (obj->version == 5))
2711
0
    return "Integer out of bounds";
2712
0
  return NULL;
2713
0
}
2714
2715
ssize_t
2716
socks5_server_method_encoded_len(const socks5_server_method_t *obj)
2717
0
{
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
0
  result += 1;
2726
2727
  /* Length of u8 method */
2728
0
  result += 1;
2729
0
  return result;
2730
0
}
2731
int
2732
socks5_server_method_clear_errors(socks5_server_method_t *obj)
2733
0
{
2734
0
  int r = obj->trunnel_error_code_;
2735
0
  obj->trunnel_error_code_ = 0;
2736
0
  return r;
2737
0
}
2738
ssize_t
2739
socks5_server_method_encode(uint8_t *output, const size_t avail, const socks5_server_method_t *obj)
2740
0
{
2741
0
  ssize_t result = 0;
2742
0
  size_t written = 0;
2743
0
  uint8_t *ptr = output;
2744
0
  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
0
  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
0
  trunnel_assert(written <= avail);
2758
0
  if (avail - written < 1)
2759
0
    goto truncated;
2760
0
  trunnel_set_uint8(ptr, (obj->version));
2761
0
  written += 1; ptr += 1;
2762
2763
  /* Encode u8 method */
2764
0
  trunnel_assert(written <= avail);
2765
0
  if (avail - written < 1)
2766
0
    goto truncated;
2767
0
  trunnel_set_uint8(ptr, (obj->method));
2768
0
  written += 1; ptr += 1;
2769
2770
2771
0
  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
0
  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
0
 fail:
2790
0
  trunnel_assert(result < 0);
2791
0
  return result;
2792
0
}
2793
2794
/** As socks5_server_method_parse(), but do not allocate the output
2795
 * object.
2796
 */
2797
static ssize_t
2798
socks5_server_method_parse_into(socks5_server_method_t *obj, const uint8_t *input, const size_t len_in)
2799
0
{
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
0
  return len_in - remaining;
2818
2819
0
 truncated:
2820
0
  return -2;
2821
0
 fail:
2822
0
  result = -1;
2823
0
  return result;
2824
0
}
2825
2826
ssize_t
2827
socks5_server_method_parse(socks5_server_method_t **output, const uint8_t *input, const size_t len_in)
2828
0
{
2829
0
  ssize_t result;
2830
0
  *output = socks5_server_method_new();
2831
0
  if (NULL == *output)
2832
0
    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
0
  }
2838
0
  return result;
2839
0
}
2840
socks5_server_userpass_auth_t *
2841
socks5_server_userpass_auth_new(void)
2842
0
{
2843
0
  socks5_server_userpass_auth_t *val = trunnel_calloc(1, sizeof(socks5_server_userpass_auth_t));
2844
0
  if (NULL == val)
2845
0
    return NULL;
2846
0
  val->version = 1;
2847
0
  return val;
2848
0
}
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
0
{
2855
0
  (void) obj;
2856
0
}
2857
2858
void
2859
socks5_server_userpass_auth_free(socks5_server_userpass_auth_t *obj)
2860
0
{
2861
0
  if (obj == NULL)
2862
0
    return;
2863
0
  socks5_server_userpass_auth_clear(obj);
2864
0
  trunnel_memwipe(obj, sizeof(socks5_server_userpass_auth_t));
2865
0
  trunnel_free_(obj);
2866
0
}
2867
2868
uint8_t
2869
socks5_server_userpass_auth_get_version(const socks5_server_userpass_auth_t *inp)
2870
0
{
2871
0
  return inp->version;
2872
0
}
2873
int
2874
socks5_server_userpass_auth_set_version(socks5_server_userpass_auth_t *inp, uint8_t val)
2875
0
{
2876
0
  if (! ((val == 1))) {
2877
0
     TRUNNEL_SET_ERROR_CODE(inp);
2878
0
     return -1;
2879
0
  }
2880
0
  inp->version = val;
2881
0
  return 0;
2882
0
}
2883
uint8_t
2884
socks5_server_userpass_auth_get_status(const socks5_server_userpass_auth_t *inp)
2885
0
{
2886
0
  return inp->status;
2887
0
}
2888
int
2889
socks5_server_userpass_auth_set_status(socks5_server_userpass_auth_t *inp, uint8_t val)
2890
0
{
2891
0
  inp->status = val;
2892
0
  return 0;
2893
0
}
2894
const char *
2895
socks5_server_userpass_auth_check(const socks5_server_userpass_auth_t *obj)
2896
0
{
2897
0
  if (obj == NULL)
2898
0
    return "Object was NULL";
2899
0
  if (obj->trunnel_error_code_)
2900
0
    return "A set function failed on this object";
2901
0
  if (! (obj->version == 1))
2902
0
    return "Integer out of bounds";
2903
0
  return NULL;
2904
0
}
2905
2906
ssize_t
2907
socks5_server_userpass_auth_encoded_len(const socks5_server_userpass_auth_t *obj)
2908
0
{
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
0
  result += 1;
2917
2918
  /* Length of u8 status */
2919
0
  result += 1;
2920
0
  return result;
2921
0
}
2922
int
2923
socks5_server_userpass_auth_clear_errors(socks5_server_userpass_auth_t *obj)
2924
0
{
2925
0
  int r = obj->trunnel_error_code_;
2926
0
  obj->trunnel_error_code_ = 0;
2927
0
  return r;
2928
0
}
2929
ssize_t
2930
socks5_server_userpass_auth_encode(uint8_t *output, const size_t avail, const socks5_server_userpass_auth_t *obj)
2931
0
{
2932
0
  ssize_t result = 0;
2933
0
  size_t written = 0;
2934
0
  uint8_t *ptr = output;
2935
0
  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
0
  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
0
  trunnel_assert(written <= avail);
2949
0
  if (avail - written < 1)
2950
0
    goto truncated;
2951
0
  trunnel_set_uint8(ptr, (obj->version));
2952
0
  written += 1; ptr += 1;
2953
2954
  /* Encode u8 status */
2955
0
  trunnel_assert(written <= avail);
2956
0
  if (avail - written < 1)
2957
0
    goto truncated;
2958
0
  trunnel_set_uint8(ptr, (obj->status));
2959
0
  written += 1; ptr += 1;
2960
2961
2962
0
  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
0
  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
0
 fail:
2981
0
  trunnel_assert(result < 0);
2982
0
  return result;
2983
0
}
2984
2985
/** As socks5_server_userpass_auth_parse(), but do not allocate the
2986
 * output object.
2987
 */
2988
static ssize_t
2989
socks5_server_userpass_auth_parse_into(socks5_server_userpass_auth_t *obj, const uint8_t *input, const size_t len_in)
2990
0
{
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
0
  return len_in - remaining;
3009
3010
0
 truncated:
3011
0
  return -2;
3012
0
 fail:
3013
0
  result = -1;
3014
0
  return result;
3015
0
}
3016
3017
ssize_t
3018
socks5_server_userpass_auth_parse(socks5_server_userpass_auth_t **output, const uint8_t *input, const size_t len_in)
3019
0
{
3020
0
  ssize_t result;
3021
0
  *output = socks5_server_userpass_auth_new();
3022
0
  if (NULL == *output)
3023
0
    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
0
  }
3029
0
  return result;
3030
0
}
3031
socks5_client_request_t *
3032
socks5_client_request_new(void)
3033
0
{
3034
0
  socks5_client_request_t *val = trunnel_calloc(1, sizeof(socks5_client_request_t));
3035
0
  if (NULL == val)
3036
0
    return NULL;
3037
0
  val->version = 5;
3038
0
  val->command = CMD_BIND;
3039
0
  return val;
3040
0
}
3041
3042
/** Release all storage held inside 'obj', but do not free 'obj'.
3043
 */
3044
static void
3045
socks5_client_request_clear(socks5_client_request_t *obj)
3046
0
{
3047
0
  (void) obj;
3048
0
  domainname_free(obj->dest_addr_domainname);
3049
0
  obj->dest_addr_domainname = NULL;
3050
0
}
3051
3052
void
3053
socks5_client_request_free(socks5_client_request_t *obj)
3054
0
{
3055
0
  if (obj == NULL)
3056
0
    return;
3057
0
  socks5_client_request_clear(obj);
3058
0
  trunnel_memwipe(obj, sizeof(socks5_client_request_t));
3059
0
  trunnel_free_(obj);
3060
0
}
3061
3062
uint8_t
3063
socks5_client_request_get_version(const socks5_client_request_t *inp)
3064
0
{
3065
0
  return inp->version;
3066
0
}
3067
int
3068
socks5_client_request_set_version(socks5_client_request_t *inp, uint8_t val)
3069
0
{
3070
0
  if (! ((val == 5))) {
3071
0
     TRUNNEL_SET_ERROR_CODE(inp);
3072
0
     return -1;
3073
0
  }
3074
0
  inp->version = val;
3075
0
  return 0;
3076
0
}
3077
uint8_t
3078
socks5_client_request_get_command(const socks5_client_request_t *inp)
3079
0
{
3080
0
  return inp->command;
3081
0
}
3082
int
3083
socks5_client_request_set_command(socks5_client_request_t *inp, uint8_t val)
3084
0
{
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
0
  }
3089
0
  inp->command = val;
3090
0
  return 0;
3091
0
}
3092
uint8_t
3093
socks5_client_request_get_reserved(const socks5_client_request_t *inp)
3094
0
{
3095
0
  return inp->reserved;
3096
0
}
3097
int
3098
socks5_client_request_set_reserved(socks5_client_request_t *inp, uint8_t val)
3099
0
{
3100
0
  if (! ((val == 0))) {
3101
0
     TRUNNEL_SET_ERROR_CODE(inp);
3102
0
     return -1;
3103
0
  }
3104
0
  inp->reserved = val;
3105
0
  return 0;
3106
0
}
3107
uint8_t
3108
socks5_client_request_get_atype(const socks5_client_request_t *inp)
3109
0
{
3110
0
  return inp->atype;
3111
0
}
3112
int
3113
socks5_client_request_set_atype(socks5_client_request_t *inp, uint8_t val)
3114
0
{
3115
0
  inp->atype = val;
3116
0
  return 0;
3117
0
}
3118
uint32_t
3119
socks5_client_request_get_dest_addr_ipv4(const socks5_client_request_t *inp)
3120
0
{
3121
0
  return inp->dest_addr_ipv4;
3122
0
}
3123
int
3124
socks5_client_request_set_dest_addr_ipv4(socks5_client_request_t *inp, uint32_t val)
3125
0
{
3126
0
  inp->dest_addr_ipv4 = val;
3127
0
  return 0;
3128
0
}
3129
size_t
3130
socks5_client_request_getlen_dest_addr_ipv6(const socks5_client_request_t *inp)
3131
0
{
3132
0
  (void)inp;  return 16;
3133
0
}
3134
3135
uint8_t
3136
socks5_client_request_get_dest_addr_ipv6(socks5_client_request_t *inp, size_t idx)
3137
0
{
3138
0
  trunnel_assert(idx < 16);
3139
0
  return inp->dest_addr_ipv6[idx];
3140
0
}
3141
3142
uint8_t
3143
socks5_client_request_getconst_dest_addr_ipv6(const socks5_client_request_t *inp, size_t idx)
3144
0
{
3145
0
  return socks5_client_request_get_dest_addr_ipv6((socks5_client_request_t*)inp, idx);
3146
0
}
3147
int
3148
socks5_client_request_set_dest_addr_ipv6(socks5_client_request_t *inp, size_t idx, uint8_t elt)
3149
0
{
3150
0
  trunnel_assert(idx < 16);
3151
0
  inp->dest_addr_ipv6[idx] = elt;
3152
0
  return 0;
3153
0
}
3154
3155
uint8_t *
3156
socks5_client_request_getarray_dest_addr_ipv6(socks5_client_request_t *inp)
3157
0
{
3158
0
  return inp->dest_addr_ipv6;
3159
0
}
3160
const uint8_t  *
3161
socks5_client_request_getconstarray_dest_addr_ipv6(const socks5_client_request_t *inp)
3162
0
{
3163
0
  return (const uint8_t  *)socks5_client_request_getarray_dest_addr_ipv6((socks5_client_request_t*)inp);
3164
0
}
3165
struct domainname_st *
3166
socks5_client_request_get_dest_addr_domainname(socks5_client_request_t *inp)
3167
0
{
3168
0
  return inp->dest_addr_domainname;
3169
0
}
3170
const struct domainname_st *
3171
socks5_client_request_getconst_dest_addr_domainname(const socks5_client_request_t *inp)
3172
0
{
3173
0
  return socks5_client_request_get_dest_addr_domainname((socks5_client_request_t*) inp);
3174
0
}
3175
int
3176
socks5_client_request_set_dest_addr_domainname(socks5_client_request_t *inp, struct domainname_st *val)
3177
0
{
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
0
}
3182
int
3183
socks5_client_request_set0_dest_addr_domainname(socks5_client_request_t *inp, struct domainname_st *val)
3184
0
{
3185
0
  inp->dest_addr_domainname = val;
3186
0
  return 0;
3187
0
}
3188
uint16_t
3189
socks5_client_request_get_dest_port(const socks5_client_request_t *inp)
3190
0
{
3191
0
  return inp->dest_port;
3192
0
}
3193
int
3194
socks5_client_request_set_dest_port(socks5_client_request_t *inp, uint16_t val)
3195
0
{
3196
0
  inp->dest_port = val;
3197
0
  return 0;
3198
0
}
3199
const char *
3200
socks5_client_request_check(const socks5_client_request_t *obj)
3201
0
{
3202
0
  if (obj == NULL)
3203
0
    return "Object was NULL";
3204
0
  if (obj->trunnel_error_code_)
3205
0
    return "A set function failed on this object";
3206
0
  if (! (obj->version == 5))
3207
0
    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
0
    return "Integer out of bounds";
3210
0
  if (! (obj->reserved == 0))
3211
0
    return "Integer out of bounds";
3212
0
  switch (obj->atype) {
3213
3214
0
    case ATYPE_IPV4:
3215
0
      break;
3216
3217
0
    case ATYPE_IPV6:
3218
0
      break;
3219
3220
0
    case ATYPE_DOMAINNAME:
3221
0
      {
3222
0
        const char *msg;
3223
0
        if (NULL != (msg = domainname_check(obj->dest_addr_domainname)))
3224
0
          return msg;
3225
0
      }
3226
0
      break;
3227
3228
0
    default:
3229
0
        return "Bad tag for union";
3230
0
      break;
3231
0
  }
3232
0
  return NULL;
3233
0
}
3234
3235
ssize_t
3236
socks5_client_request_encoded_len(const socks5_client_request_t *obj)
3237
0
{
3238
0
  ssize_t result = 0;
3239
3240
0
  if (NULL != socks5_client_request_check(obj))
3241
0
     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
0
    case ATYPE_IPV4:
3258
3259
      /* Length of u32 dest_addr_ipv4 */
3260
0
      result += 4;
3261
0
      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
0
    default:
3276
0
      trunnel_assert(0);
3277
0
      break;
3278
0
  }
3279
3280
  /* Length of u16 dest_port */
3281
0
  result += 2;
3282
0
  return result;
3283
0
}
3284
int
3285
socks5_client_request_clear_errors(socks5_client_request_t *obj)
3286
0
{
3287
0
  int r = obj->trunnel_error_code_;
3288
0
  obj->trunnel_error_code_ = 0;
3289
0
  return r;
3290
0
}
3291
ssize_t
3292
socks5_client_request_encode(uint8_t *output, const size_t avail, const socks5_client_request_t *obj)
3293
0
{
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
0
    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
0
    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
0
    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
0
    default:
3372
0
      trunnel_assert(0);
3373
0
      break;
3374
0
  }
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
0
  return result;
3405
0
}
3406
3407
/** As socks5_client_request_parse(), but do not allocate the output
3408
 * object.
3409
 */
3410
static ssize_t
3411
socks5_client_request_parse_into(socks5_client_request_t *obj, const uint8_t *input, const size_t len_in)
3412
0
{
3413
0
  const uint8_t *ptr = input;
3414
0
  size_t remaining = len_in;
3415
0
  ssize_t result = 0;
3416
0
  (void)result;
3417
3418
  /* Parse u8 version IN [5] */
3419
0
  CHECK_REMAINING(1, truncated);
3420
0
  obj->version = (trunnel_get_uint8(ptr));
3421
0
  remaining -= 1; ptr += 1;
3422
0
  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
0
  CHECK_REMAINING(1, truncated);
3427
0
  obj->command = (trunnel_get_uint8(ptr));
3428
0
  remaining -= 1; ptr += 1;
3429
0
  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
0
  CHECK_REMAINING(1, truncated);
3434
0
  obj->reserved = (trunnel_get_uint8(ptr));
3435
0
  remaining -= 1; ptr += 1;
3436
0
  if (! (obj->reserved == 0))
3437
0
    goto fail;
3438
3439
  /* Parse u8 atype */
3440
0
  CHECK_REMAINING(1, truncated);
3441
0
  obj->atype = (trunnel_get_uint8(ptr));
3442
0
  remaining -= 1; ptr += 1;
3443
3444
  /* Parse union dest_addr[atype] */
3445
0
  switch (obj->atype) {
3446
3447
0
    case ATYPE_IPV4:
3448
3449
      /* Parse u32 dest_addr_ipv4 */
3450
0
      CHECK_REMAINING(4, truncated);
3451
0
      obj->dest_addr_ipv4 = trunnel_ntohl(trunnel_get_uint32(ptr));
3452
0
      remaining -= 4; ptr += 4;
3453
0
      break;
3454
3455
0
    case ATYPE_IPV6:
3456
3457
      /* Parse u8 dest_addr_ipv6[16] */
3458
0
      CHECK_REMAINING(16, truncated);
3459
0
      memcpy(obj->dest_addr_ipv6, ptr, 16);
3460
0
      remaining -= 16; ptr += 16;
3461
0
      break;
3462
3463
0
    case ATYPE_DOMAINNAME:
3464
3465
      /* Parse struct domainname dest_addr_domainname */
3466
0
      result = domainname_parse(&obj->dest_addr_domainname, ptr, remaining);
3467
0
      if (result < 0)
3468
0
        goto relay_fail;
3469
0
      trunnel_assert((size_t)result <= remaining);
3470
0
      remaining -= result; ptr += result;
3471
0
      break;
3472
3473
0
    default:
3474
0
      goto fail;
3475
0
      break;
3476
0
  }
3477
3478
  /* Parse u16 dest_port */
3479
0
  CHECK_REMAINING(2, truncated);
3480
0
  obj->dest_port = trunnel_ntohs(trunnel_get_uint16(ptr));
3481
0
  remaining -= 2; ptr += 2;
3482
0
  trunnel_assert(ptr + remaining == input + len_in);
3483
0
  return len_in - remaining;
3484
3485
0
 truncated:
3486
0
  return -2;
3487
0
 relay_fail:
3488
0
  trunnel_assert(result < 0);
3489
0
  return result;
3490
0
 fail:
3491
0
  result = -1;
3492
0
  return result;
3493
0
}
3494
3495
ssize_t
3496
socks5_client_request_parse(socks5_client_request_t **output, const uint8_t *input, const size_t len_in)
3497
0
{
3498
0
  ssize_t result;
3499
0
  *output = socks5_client_request_new();
3500
0
  if (NULL == *output)
3501
0
    return -1;
3502
0
  result = socks5_client_request_parse_into(*output, input, len_in);
3503
0
  if (result < 0) {
3504
0
    socks5_client_request_free(*output);
3505
0
    *output = NULL;
3506
0
  }
3507
0
  return result;
3508
0
}
3509
socks5_server_reply_t *
3510
socks5_server_reply_new(void)
3511
0
{
3512
0
  socks5_server_reply_t *val = trunnel_calloc(1, sizeof(socks5_server_reply_t));
3513
0
  if (NULL == val)
3514
0
    return NULL;
3515
0
  val->version = 5;
3516
0
  return val;
3517
0
}
3518
3519
/** Release all storage held inside 'obj', but do not free 'obj'.
3520
 */
3521
static void
3522
socks5_server_reply_clear(socks5_server_reply_t *obj)
3523
0
{
3524
0
  (void) obj;
3525
0
  domainname_free(obj->bind_addr_domainname);
3526
0
  obj->bind_addr_domainname = NULL;
3527
0
}
3528
3529
void
3530
socks5_server_reply_free(socks5_server_reply_t *obj)
3531
0
{
3532
0
  if (obj == NULL)
3533
0
    return;
3534
0
  socks5_server_reply_clear(obj);
3535
0
  trunnel_memwipe(obj, sizeof(socks5_server_reply_t));
3536
0
  trunnel_free_(obj);
3537
0
}
3538
3539
uint8_t
3540
socks5_server_reply_get_version(const socks5_server_reply_t *inp)
3541
0
{
3542
0
  return inp->version;
3543
0
}
3544
int
3545
socks5_server_reply_set_version(socks5_server_reply_t *inp, uint8_t val)
3546
0
{
3547
0
  if (! ((val == 5))) {
3548
0
     TRUNNEL_SET_ERROR_CODE(inp);
3549
0
     return -1;
3550
0
  }
3551
0
  inp->version = val;
3552
0
  return 0;
3553
0
}
3554
uint8_t
3555
socks5_server_reply_get_reply(const socks5_server_reply_t *inp)
3556
0
{
3557
0
  return inp->reply;
3558
0
}
3559
int
3560
socks5_server_reply_set_reply(socks5_server_reply_t *inp, uint8_t val)
3561
0
{
3562
0
  inp->reply = val;
3563
0
  return 0;
3564
0
}
3565
uint8_t
3566
socks5_server_reply_get_reserved(const socks5_server_reply_t *inp)
3567
0
{
3568
0
  return inp->reserved;
3569
0
}
3570
int
3571
socks5_server_reply_set_reserved(socks5_server_reply_t *inp, uint8_t val)
3572
0
{
3573
0
  if (! ((val == 0))) {
3574
0
     TRUNNEL_SET_ERROR_CODE(inp);
3575
0
     return -1;
3576
0
  }
3577
0
  inp->reserved = val;
3578
0
  return 0;
3579
0
}
3580
uint8_t
3581
socks5_server_reply_get_atype(const socks5_server_reply_t *inp)
3582
0
{
3583
0
  return inp->atype;
3584
0
}
3585
int
3586
socks5_server_reply_set_atype(socks5_server_reply_t *inp, uint8_t val)
3587
0
{
3588
0
  inp->atype = val;
3589
0
  return 0;
3590
0
}
3591
uint32_t
3592
socks5_server_reply_get_bind_addr_ipv4(const socks5_server_reply_t *inp)
3593
0
{
3594
0
  return inp->bind_addr_ipv4;
3595
0
}
3596
int
3597
socks5_server_reply_set_bind_addr_ipv4(socks5_server_reply_t *inp, uint32_t val)
3598
0
{
3599
0
  inp->bind_addr_ipv4 = val;
3600
0
  return 0;
3601
0
}
3602
size_t
3603
socks5_server_reply_getlen_bind_addr_ipv6(const socks5_server_reply_t *inp)
3604
0
{
3605
0
  (void)inp;  return 16;
3606
0
}
3607
3608
uint8_t
3609
socks5_server_reply_get_bind_addr_ipv6(socks5_server_reply_t *inp, size_t idx)
3610
0
{
3611
0
  trunnel_assert(idx < 16);
3612
0
  return inp->bind_addr_ipv6[idx];
3613
0
}
3614
3615
uint8_t
3616
socks5_server_reply_getconst_bind_addr_ipv6(const socks5_server_reply_t *inp, size_t idx)
3617
0
{
3618
0
  return socks5_server_reply_get_bind_addr_ipv6((socks5_server_reply_t*)inp, idx);
3619
0
}
3620
int
3621
socks5_server_reply_set_bind_addr_ipv6(socks5_server_reply_t *inp, size_t idx, uint8_t elt)
3622
0
{
3623
0
  trunnel_assert(idx < 16);
3624
0
  inp->bind_addr_ipv6[idx] = elt;
3625
0
  return 0;
3626
0
}
3627
3628
uint8_t *
3629
socks5_server_reply_getarray_bind_addr_ipv6(socks5_server_reply_t *inp)
3630
0
{
3631
0
  return inp->bind_addr_ipv6;
3632
0
}
3633
const uint8_t  *
3634
socks5_server_reply_getconstarray_bind_addr_ipv6(const socks5_server_reply_t *inp)
3635
0
{
3636
0
  return (const uint8_t  *)socks5_server_reply_getarray_bind_addr_ipv6((socks5_server_reply_t*)inp);
3637
0
}
3638
struct domainname_st *
3639
socks5_server_reply_get_bind_addr_domainname(socks5_server_reply_t *inp)
3640
0
{
3641
0
  return inp->bind_addr_domainname;
3642
0
}
3643
const struct domainname_st *
3644
socks5_server_reply_getconst_bind_addr_domainname(const socks5_server_reply_t *inp)
3645
0
{
3646
0
  return socks5_server_reply_get_bind_addr_domainname((socks5_server_reply_t*) inp);
3647
0
}
3648
int
3649
socks5_server_reply_set_bind_addr_domainname(socks5_server_reply_t *inp, struct domainname_st *val)
3650
0
{
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
0
}
3655
int
3656
socks5_server_reply_set0_bind_addr_domainname(socks5_server_reply_t *inp, struct domainname_st *val)
3657
0
{
3658
0
  inp->bind_addr_domainname = val;
3659
0
  return 0;
3660
0
}
3661
uint16_t
3662
socks5_server_reply_get_bind_port(const socks5_server_reply_t *inp)
3663
0
{
3664
0
  return inp->bind_port;
3665
0
}
3666
int
3667
socks5_server_reply_set_bind_port(socks5_server_reply_t *inp, uint16_t val)
3668
0
{
3669
0
  inp->bind_port = val;
3670
0
  return 0;
3671
0
}
3672
const char *
3673
socks5_server_reply_check(const socks5_server_reply_t *obj)
3674
0
{
3675
0
  if (obj == NULL)
3676
0
    return "Object was NULL";
3677
0
  if (obj->trunnel_error_code_)
3678
0
    return "A set function failed on this object";
3679
0
  if (! (obj->version == 5))
3680
0
    return "Integer out of bounds";
3681
0
  if (! (obj->reserved == 0))
3682
0
    return "Integer out of bounds";
3683
0
  switch (obj->atype) {
3684
3685
0
    case ATYPE_IPV4:
3686
0
      break;
3687
3688
0
    case ATYPE_IPV6:
3689
0
      break;
3690
3691
0
    case ATYPE_DOMAINNAME:
3692
0
      {
3693
0
        const char *msg;
3694
0
        if (NULL != (msg = domainname_check(obj->bind_addr_domainname)))
3695
0
          return msg;
3696
0
      }
3697
0
      break;
3698
3699
0
    default:
3700
0
        return "Bad tag for union";
3701
0
      break;
3702
0
  }
3703
0
  return NULL;
3704
0
}
3705
3706
ssize_t
3707
socks5_server_reply_encoded_len(const socks5_server_reply_t *obj)
3708
0
{
3709
0
  ssize_t result = 0;
3710
3711
0
  if (NULL != socks5_server_reply_check(obj))
3712
0
     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
0
    case ATYPE_IPV4:
3729
3730
      /* Length of u32 bind_addr_ipv4 */
3731
0
      result += 4;
3732
0
      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
0
    default:
3747
0
      trunnel_assert(0);
3748
0
      break;
3749
0
  }
3750
3751
  /* Length of u16 bind_port */
3752
0
  result += 2;
3753
0
  return result;
3754
0
}
3755
int
3756
socks5_server_reply_clear_errors(socks5_server_reply_t *obj)
3757
0
{
3758
0
  int r = obj->trunnel_error_code_;
3759
0
  obj->trunnel_error_code_ = 0;
3760
0
  return r;
3761
0
}
3762
ssize_t
3763
socks5_server_reply_encode(uint8_t *output, const size_t avail, const socks5_server_reply_t *obj)
3764
0
{
3765
0
  ssize_t result = 0;
3766
0
  size_t written = 0;
3767
0
  uint8_t *ptr = output;
3768
0
  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
0
  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
0
  trunnel_assert(written <= avail);
3782
0
  if (avail - written < 1)
3783
0
    goto truncated;
3784
0
  trunnel_set_uint8(ptr, (obj->version));
3785
0
  written += 1; ptr += 1;
3786
3787
  /* Encode u8 reply */
3788
0
  trunnel_assert(written <= avail);
3789
0
  if (avail - written < 1)
3790
0
    goto truncated;
3791
0
  trunnel_set_uint8(ptr, (obj->reply));
3792
0
  written += 1; ptr += 1;
3793
3794
  /* Encode u8 reserved IN [0] */
3795
0
  trunnel_assert(written <= avail);
3796
0
  if (avail - written < 1)
3797
0
    goto truncated;
3798
0
  trunnel_set_uint8(ptr, (obj->reserved));
3799
0
  written += 1; ptr += 1;
3800
3801
  /* Encode u8 atype */
3802
0
  trunnel_assert(written <= avail);
3803
0
  if (avail - written < 1)
3804
0
    goto truncated;
3805
0
  trunnel_set_uint8(ptr, (obj->atype));
3806
0
  written += 1; ptr += 1;
3807
3808
  /* Encode union bind_addr[atype] */
3809
0
  trunnel_assert(written <= avail);
3810
0
  switch (obj->atype) {
3811
3812
0
    case ATYPE_IPV4:
3813
3814
      /* Encode u32 bind_addr_ipv4 */
3815
0
      trunnel_assert(written <= avail);
3816
0
      if (avail - written < 4)
3817
0
        goto truncated;
3818
0
      trunnel_set_uint32(ptr, trunnel_htonl(obj->bind_addr_ipv4));
3819
0
      written += 4; ptr += 4;
3820
0
      break;
3821
3822
0
    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
0
    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
0
    default:
3843
0
      trunnel_assert(0);
3844
0
      break;
3845
0
  }
3846
3847
  /* Encode u16 bind_port */
3848
0
  trunnel_assert(written <= avail);
3849
0
  if (avail - written < 2)
3850
0
    goto truncated;
3851
0
  trunnel_set_uint16(ptr, trunnel_htons(obj->bind_port));
3852
0
  written += 2; ptr += 2;
3853
3854
3855
0
  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
0
  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
0
  return result;
3876
0
}
3877
3878
/** As socks5_server_reply_parse(), but do not allocate the output
3879
 * object.
3880
 */
3881
static ssize_t
3882
socks5_server_reply_parse_into(socks5_server_reply_t *obj, const uint8_t *input, const size_t len_in)
3883
0
{
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
0
  }
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
0
 truncated:
3955
0
  return -2;
3956
0
 relay_fail:
3957
0
  trunnel_assert(result < 0);
3958
0
  return result;
3959
0
 fail:
3960
0
  result = -1;
3961
0
  return result;
3962
0
}
3963
3964
ssize_t
3965
socks5_server_reply_parse(socks5_server_reply_t **output, const uint8_t *input, const size_t len_in)
3966
0
{
3967
0
  ssize_t result;
3968
0
  *output = socks5_server_reply_new();
3969
0
  if (NULL == *output)
3970
0
    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
0
  }
3976
0
  return result;
3977
0
}