connection_ap.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. #include "or.h"
  5. int ap_handshake_process_socks(connection_t *conn) {
  6. socks4_t socks4_info;
  7. circuit_t *circ;
  8. char tmpbuf[512];
  9. int amt;
  10. assert(conn);
  11. log_fn(LOG_DEBUG,"entered.");
  12. if(!conn->socks_version) { /* try to pull it in */
  13. if(conn->inbuf_datalen < sizeof(socks4_t)) /* basic info available? */
  14. return 0; /* not yet */
  15. connection_fetch_from_buf((char *)&socks4_info,sizeof(socks4_t),conn);
  16. log_fn(LOG_DEBUG,"Successfully read socks info.");
  17. if(socks4_info.version != 4) {
  18. log_fn(LOG_NOTICE,"Unrecognized version %d.",socks4_info.version);
  19. ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT);
  20. return -1;
  21. }
  22. conn->socks_version = socks4_info.version;
  23. if(socks4_info.command != 1) { /* not a connect? we don't support it. */
  24. log_fn(LOG_NOTICE,"command %d not '1'.",socks4_info.command);
  25. ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT);
  26. return -1;
  27. }
  28. conn->dest_port = ntohs(*(uint16_t*)&socks4_info.destport);
  29. if(!conn->dest_port) {
  30. log_fn(LOG_NOTICE,"Port is zero.");
  31. ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT);
  32. return -1;
  33. }
  34. log_fn(LOG_NOTICE,"Dest port is %d.",conn->dest_port);
  35. if(socks4_info.destip[0] ||
  36. socks4_info.destip[1] ||
  37. socks4_info.destip[2] ||
  38. !socks4_info.destip[3]) { /* not 0.0.0.x */
  39. log_fn(LOG_NOTICE,"destip not in form 0.0.0.x.");
  40. sprintf(tmpbuf, "%d.%d.%d.%d", socks4_info.destip[0],
  41. socks4_info.destip[1], socks4_info.destip[2], socks4_info.destip[3]);
  42. conn->dest_addr = strdup(tmpbuf);
  43. log_fn(LOG_DEBUG,"Successfully read destip (%s)", conn->dest_addr);
  44. }
  45. }
  46. if(!conn->read_username) { /* the socks spec says we've got to read stuff until we get a null */
  47. amt = connection_find_on_inbuf("\0", 1, conn);
  48. if(amt < 0) /* not there yet */
  49. return 0;
  50. if(amt > 500) {
  51. log_fn(LOG_NOTICE,"username too long.");
  52. ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT);
  53. return -1;
  54. }
  55. connection_fetch_from_buf(tmpbuf,amt,conn);
  56. conn->read_username = 1;
  57. log_fn(LOG_DEBUG,"Successfully read username.");
  58. }
  59. if(!conn->dest_addr) { /* no dest_addr found yet */
  60. amt = connection_find_on_inbuf("\0", 1, conn);
  61. if(amt < 0) /* not there yet */
  62. return 0;
  63. if(amt > 500) {
  64. log_fn(LOG_NOTICE,"dest_addr too long.");
  65. ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT);
  66. return -1;
  67. }
  68. connection_fetch_from_buf(tmpbuf,amt,conn);
  69. conn->dest_addr = strdup(tmpbuf);
  70. log_fn(LOG_NOTICE,"successfully read dest addr '%s'",
  71. conn->dest_addr);
  72. }
  73. /* find the circuit that we should use, if there is one. */
  74. circ = circuit_get_newest_ap();
  75. if(!circ) {
  76. log_fn(LOG_INFO,"No circuit ready. Closing.");
  77. return -1;
  78. }
  79. circ->dirty = 1;
  80. /* add it into the linked list of streams on this circuit */
  81. log_fn(LOG_DEBUG,"attaching new conn to circ. n_aci %d.", circ->n_aci);
  82. conn->next_stream = circ->p_streams;
  83. circ->p_streams = conn;
  84. assert(circ->cpath && circ->cpath->prev);
  85. assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
  86. conn->cpath_layer = circ->cpath->prev;
  87. if(ap_handshake_send_begin(conn, circ) < 0) {
  88. circuit_close(circ);
  89. return -1;
  90. }
  91. return 0;
  92. }
  93. int ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ) {
  94. cell_t cell;
  95. memset(&cell, 0, sizeof(cell_t));
  96. /* deliver the dest_addr in a relay cell */
  97. cell.command = CELL_RELAY;
  98. cell.aci = circ->n_aci;
  99. SET_CELL_RELAY_COMMAND(cell, RELAY_COMMAND_BEGIN);
  100. if(crypto_pseudo_rand(STREAM_ID_SIZE, ap_conn->stream_id) < 0)
  101. return -1;
  102. /* FIXME check for collisions */
  103. SET_CELL_STREAM_ID(cell, ZERO_STREAM);
  104. memcpy(cell.payload+RELAY_HEADER_SIZE, ap_conn->stream_id, STREAM_ID_SIZE);
  105. cell.length =
  106. snprintf(cell.payload+RELAY_HEADER_SIZE+STREAM_ID_SIZE, CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE-STREAM_ID_SIZE,
  107. "%s:%d", ap_conn->dest_addr, ap_conn->dest_port) +
  108. 1 + STREAM_ID_SIZE + RELAY_HEADER_SIZE;
  109. log_fn(LOG_DEBUG,"Sending relay cell (id %d) to begin stream %d.", *(int *)(cell.payload+1),*(int *)ap_conn->stream_id);
  110. if(circuit_deliver_relay_cell(&cell, circ, CELL_DIRECTION_OUT, ap_conn->cpath_layer) < 0) {
  111. log_fn(LOG_DEBUG,"failed to deliver begin cell. Closing.");
  112. return -1;
  113. }
  114. ap_conn->package_window = STREAMWINDOW_START;
  115. ap_conn->deliver_window = STREAMWINDOW_START;
  116. ap_conn->state = AP_CONN_STATE_OPEN;
  117. log_fn(LOG_INFO,"Address/port sent, ap socket %d, n_aci %d",ap_conn->s,circ->n_aci);
  118. return 0;
  119. }
  120. int ap_handshake_socks_reply(connection_t *conn, char result) {
  121. socks4_t socks4_info;
  122. assert(conn);
  123. socks4_info.version = 0;
  124. socks4_info.command = result;
  125. socks4_info.destport[0] = socks4_info.destport[1] = 0;
  126. socks4_info.destip[0] = socks4_info.destip[1] = socks4_info.destip[2] = socks4_info.destip[3] = 0;
  127. if(connection_write_to_buf((char *)&socks4_info, sizeof(socks4_t), conn) < 0)
  128. return -1;
  129. return connection_flush_buf(conn); /* try to flush it, in case we're about to close the conn */
  130. }
  131. /*
  132. Local Variables:
  133. mode:c
  134. indent-tabs-mode:nil
  135. c-basic-offset:2
  136. End:
  137. */