connection_ap.c 6.1 KB

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