socks4.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * SOCKS 4 proxy negotiation.
  3. */
  4. #include "putty.h"
  5. #include "network.h"
  6. #include "proxy.h"
  7. #include "socks.h"
  8. #include "sshcr.h"
  9. typedef struct Socks4ProxyNegotiator {
  10. int crLine;
  11. ProxyNegotiator pn;
  12. } Socks4ProxyNegotiator;
  13. static ProxyNegotiator *proxy_socks4_new(const ProxyNegotiatorVT *vt)
  14. {
  15. Socks4ProxyNegotiator *s = snew(Socks4ProxyNegotiator);
  16. s->pn.vt = vt;
  17. s->crLine = 0;
  18. return &s->pn;
  19. }
  20. static void proxy_socks4_free(ProxyNegotiator *pn)
  21. {
  22. Socks4ProxyNegotiator *s = container_of(pn, Socks4ProxyNegotiator, pn);
  23. sfree(s);
  24. }
  25. static void proxy_socks4_process_queue(ProxyNegotiator *pn)
  26. {
  27. Socks4ProxyNegotiator *s = container_of(pn, Socks4ProxyNegotiator, pn);
  28. crBegin(s->crLine);
  29. {
  30. char hostname[512];
  31. bool write_hostname = false;
  32. /*
  33. * SOCKS 4 request packet:
  34. *
  35. * byte version
  36. * byte command
  37. * uint16 destination port number
  38. * uint32 destination IPv4 address (or something in the
  39. * SOCKS4A_NAME_FOLLOWS range)
  40. * asciz username
  41. * asciz destination hostname (if we sent SOCKS4A_NAME_FOLLOWS_*)
  42. */
  43. put_byte(pn->output, SOCKS4_REQUEST_VERSION);
  44. put_byte(pn->output, SOCKS_CMD_CONNECT);
  45. put_uint16(pn->output, pn->ps->remote_port);
  46. switch (sk_addrtype(pn->ps->remote_addr)) {
  47. case ADDRTYPE_IPV4: {
  48. char addr[4];
  49. sk_addrcopy(pn->ps->remote_addr, addr);
  50. put_data(pn->output, addr, 4);
  51. break;
  52. }
  53. case ADDRTYPE_NAME:
  54. put_uint32(pn->output, SOCKS4A_NAME_FOLLOWS_BASE);
  55. sk_getaddr(pn->ps->remote_addr, hostname, lenof(hostname));
  56. write_hostname = true;
  57. break;
  58. case ADDRTYPE_IPV6:
  59. pn->error = dupstr("SOCKS version 4 does not support IPv6");
  60. crStopV;
  61. }
  62. put_asciz(pn->output, conf_get_str(pn->ps->conf, CONF_proxy_username));
  63. if (write_hostname)
  64. put_asciz(pn->output, hostname);
  65. }
  66. crReturnV;
  67. {
  68. unsigned char data[8];
  69. crMaybeWaitUntilV(bufchain_try_fetch_consume(pn->input, data, 8));
  70. /*
  71. * SOCKS 4 response packet:
  72. *
  73. * byte version
  74. * byte status
  75. * uint16 port number
  76. * uint32 IPv4 address
  77. *
  78. * We don't need to worry about the port and destination address.
  79. */
  80. if (data[0] != SOCKS4_REPLY_VERSION) {
  81. pn->error = dupprintf("SOCKS proxy response contained reply "
  82. "version number %d (expected %d)",
  83. (int)data[0], SOCKS4_REPLY_VERSION);
  84. crStopV;
  85. }
  86. switch (data[1]) {
  87. case SOCKS4_RESP_SUCCESS:
  88. pn->done = true;
  89. break;
  90. case SOCKS4_RESP_FAILURE:
  91. pn->error = dupstr("SOCKS server reported failure to connect");
  92. break;
  93. case SOCKS4_RESP_WANT_IDENTD:
  94. pn->error = dupstr("SOCKS server wanted IDENTD on client");
  95. break;
  96. case SOCKS4_RESP_IDENTD_MISMATCH:
  97. pn->error = dupstr("Username and IDENTD on client don't agree");
  98. break;
  99. default:
  100. pn->error = dupprintf("SOCKS server sent unrecognised error "
  101. "code %d", (int)data[1]);
  102. break;
  103. }
  104. crStopV;
  105. }
  106. crFinishV;
  107. }
  108. const struct ProxyNegotiatorVT socks4_proxy_negotiator_vt = {
  109. .new = proxy_socks4_new,
  110. .free = proxy_socks4_free,
  111. .process_queue = proxy_socks4_process_queue,
  112. .type = "SOCKS 4",
  113. };