00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 #include "libts.h"
00031 #include "StatSystem.h"
00032 #include "P_Net.h"
00033 #include "I_OneWayTunnel.h"
00034 #include "HttpSessionAccept.h"
00035 
00036 enum
00037 {
00038   socksproxy_http_connections_stat,
00039   socksproxy_tunneled_connections_stat,
00040 
00041   socksproxy_stat_count
00042 };
00043 static RecRawStatBlock *socksproxy_stat_block;
00044 
00045 #define SOCKSPROXY_INC_STAT(x) \
00046         RecIncrRawStat(socksproxy_stat_block, mutex->thread_holding, x)
00047 
00048 struct SocksProxy: public Continuation
00049 {
00050   typedef int (SocksProxy::*EventHandler) (int event, void *data);
00051 
00052   enum
00053   { SOCKS_INIT = 1, SOCKS_ACCEPT, AUTH_DONE, SERVER_TUNNEL,
00054     HTTP_REQ, RESP_TO_CLIENT, ALL_DONE, SOCKS_ERROR
00055   };
00056 
00057     SocksProxy()
00058   : Continuation(),
00059     clientVC(0), clientVIO(0), buf(0), timeout(0),
00060     auth_handler(0), version(0), state(SOCKS_INIT), recursion(0), pending_action(NULL)
00061   {
00062   }
00063    ~SocksProxy()
00064   {
00065   }
00066 
00067 
00068   
00069   int mainEvent(int event, void *data);
00070   int setupHttpRequest(unsigned char *p);
00071   
00072 
00073   int sendResp(bool granted);
00074 
00075   void init(NetVConnection * netVC);
00076   void free();
00077 
00078 private:
00079 
00080   NetVConnection * clientVC;
00081   VIO *clientVIO;
00082 
00083   MIOBuffer *buf;
00084   IOBufferReader *reader;
00085   Event *timeout;
00086 
00087   SocksAuthHandler auth_handler;
00088 
00089   unsigned char version;
00090 
00091   int state;
00092   int recursion;
00093   Action *pending_action;
00094 };
00095 
00096 ClassAllocator<SocksProxy> socksProxyAllocator("socksProxyAllocator");
00097 
00098 void
00099 SocksProxy::init(NetVConnection * netVC)
00100 {
00101   mutex = new_ProxyMutex();
00102   buf = new_MIOBuffer();
00103   reader = buf->alloc_reader();
00104 
00105   MUTEX_LOCK(lock, mutex, this_ethread());
00106 
00107   SET_HANDLER((EventHandler) & SocksProxy::mainEvent);
00108 
00109   mainEvent(NET_EVENT_ACCEPT, netVC);
00110 }
00111 
00112 void
00113 SocksProxy::free()
00114 {
00115   if (buf)
00116     free_MIOBuffer(buf);
00117 
00118   mutex = NULL;
00119 
00120   socksProxyAllocator.free(this);
00121 }
00122 
00123 int
00124 SocksProxy::mainEvent(int event, void *data)
00125 {
00126   int ret = EVENT_DONE;
00127   unsigned char *p;
00128 
00129   VIO *vio;
00130   int64_t n_read_avail;
00131   
00132 
00133   recursion++;
00134 
00135   switch (event) {
00136 
00137   case NET_EVENT_ACCEPT:
00138     state = SOCKS_ACCEPT;
00139     Debug("SocksProxy", "Proxy got accept event\n");
00140 
00141     clientVC = (NetVConnection *) data;
00142     clientVC->socks_addr.reset();
00143     
00144   case VC_EVENT_WRITE_COMPLETE:
00145 
00146     switch (state) {
00147     case HTTP_REQ:{
00148       HttpSessionAccept::Options ha_opt;
00149       
00150 
00151       SOCKSPROXY_INC_STAT(socksproxy_http_connections_stat);
00152       Debug("SocksProxy", "Handing over the HTTP request\n");
00153 
00154       ha_opt.transport_type = clientVC->attributes;
00155       HttpSessionAccept http_accept(ha_opt);
00156       http_accept.mainEvent(NET_EVENT_ACCEPT, clientVC);
00157       state = ALL_DONE;
00158       break;
00159       }
00160 
00161     case RESP_TO_CLIENT:
00162       state = SOCKS_ERROR;
00163       break;
00164 
00165     default:
00166       buf->reset();
00167       timeout = this_ethread()
00168         ->schedule_in(this, HRTIME_SECONDS(netProcessor.socks_conf_stuff->socks_timeout));
00169       clientVC->do_io_read(this, INT64_MAX, buf);
00170     }
00171 
00172     break;
00173 
00174   case VC_EVENT_WRITE_READY:
00175     Debug("SocksProxy", "Received unexpected write_ready\n");
00176     break;
00177 
00178   case VC_EVENT_READ_COMPLETE:
00179     Debug("SocksProxy", "Oops! We should never get Read_Complete.\n");
00180     
00181   case VC_EVENT_READ_READY:{
00182       unsigned char *port_ptr = 0;
00183 
00184       ret = EVENT_CONT;
00185       vio = (VIO *) data;
00186 
00187       n_read_avail = reader->block_read_avail();
00188       ink_assert(n_read_avail == reader->read_avail());
00189       p = (unsigned char *) reader->start();
00190 
00191       if (n_read_avail >= 2) {
00192 
00193         Debug(state == SOCKS_ACCEPT ? "SocksProxy" : "", "Accepted connection from a version %d client\n", (int) p[0]);
00194 
00195         
00196         switch (p[0]) {
00197 
00198         case SOCKS4_VERSION:
00199           ink_assert(state == SOCKS_ACCEPT);
00200 
00201           if (n_read_avail > 8) {
00202             
00203             int i = 8;
00204             while (p[i] != 0 && n_read_avail > i)
00205               i++;
00206 
00207             if (p[i] == 0) {
00208               port_ptr = &p[2];
00209               clientVC->socks_addr.type = SOCKS_ATYPE_IPV4;
00210               reader->consume(i + 1);
00211               
00212               ret = EVENT_DONE;
00213             }
00214           }
00215           break;
00216 
00217         case SOCKS5_VERSION:
00218 
00219           if (state == SOCKS_ACCEPT) {
00220             if (n_read_avail >= 2 + p[1]) {
00221               auth_handler = &socks5ServerAuthHandler;
00222               ret = EVENT_DONE;
00223             }
00224           } else {
00225             ink_assert(state == AUTH_DONE);
00226 
00227             if (n_read_avail >= 5) {
00228               int req_len;
00229 
00230               switch (p[3]) {
00231               case SOCKS_ATYPE_IPV4:
00232                 req_len = 10;
00233                 break;
00234               case SOCKS_ATYPE_FQHN:
00235                 req_len = 7 + p[4];
00236                 break;
00237               case SOCKS_ATYPE_IPV6:
00238                 req_len = 22;
00239                 break;
00240               default:
00241                 req_len = INT_MAX;
00242                 Debug("SocksProxy", "Illegal address type(%d)\n", (int) p[3]);
00243               }
00244 
00245               if (n_read_avail >= req_len) {
00246                 port_ptr = &p[req_len - 2];
00247                 clientVC->socks_addr.type = p[3];
00248                 auth_handler = NULL;
00249                 reader->consume(req_len);
00250                 ret = EVENT_DONE;
00251               }
00252             }
00253           }
00254           break;
00255 
00256         default:
00257           Warning("Wrong version for Socks: %d\n", p[0]);
00258           state = SOCKS_ERROR;
00259         }
00260       }
00261 
00262       if (ret == EVENT_DONE) {
00263         timeout->cancel(this);
00264         timeout = 0;
00265 
00266         if (auth_handler) {
00267 
00268           
00269           vio->nbytes = vio->ndone;
00270 
00271           
00272           if (invokeSocksAuthHandler(auth_handler, SOCKS_AUTH_READ_COMPLETE, p) >= 0) {
00273             buf->reset();
00274             p = (unsigned char *) buf->start();
00275 
00276             int n_bytes = invokeSocksAuthHandler(auth_handler,
00277                                                  SOCKS_AUTH_FILL_WRITE_BUF, p);
00278             ink_assert(n_bytes > 0);
00279 
00280             buf->fill(n_bytes);
00281 
00282             clientVC->do_io_write(this, n_bytes, reader, 0);
00283 
00284             state = AUTH_DONE;
00285           } else {
00286             Debug("SocksProxy", "Auth_handler returned error\n");
00287             state = SOCKS_ERROR;
00288           }
00289 
00290         } else {
00291           int port = port_ptr[0] * 256 + port_ptr[1];
00292           version = p[0];
00293 
00294           if (port == netProcessor.socks_conf_stuff->http_port && p[1] == SOCKS_CONNECT) {
00295 
00296             
00297             vio->nbytes = vio->ndone;
00298 
00299             ret = setupHttpRequest(p);
00300             sendResp(true);
00301             state = HTTP_REQ;
00302 
00303           } else {
00304             SOCKSPROXY_INC_STAT(socksproxy_tunneled_connections_stat);
00305             Debug("SocksProxy", "Tunnelling the connection for port %d", port);
00306 
00307             if (clientVC->socks_addr.type != SOCKS_ATYPE_IPV4) {
00308               
00309               
00310               mainEvent(NET_EVENT_OPEN_FAILED, NULL);
00311               break;
00312             }
00313 
00314             uint32_t ip;
00315             struct sockaddr_in addr;
00316 
00317             memcpy(&ip, &p[4], 4);
00318             ats_ip4_set(&addr, ip, htons(port));
00319 
00320             state = SERVER_TUNNEL;
00321             clientVIO = vio;    
00322 
00323             
00324 
00325             NetVCOptions vc_options;
00326             vc_options.socks_support = p[1];
00327             vc_options.socks_version = version;
00328 
00329             Action *action = netProcessor.connect_re(this, ats_ip_sa_cast(&addr), &vc_options);
00330             if (action != ACTION_RESULT_DONE) {
00331               ink_assert(pending_action == NULL);
00332               pending_action = action;
00333             }
00334           }
00335         }
00336       }                         
00337 
00338       break;
00339     }
00340 
00341   case NET_EVENT_OPEN:{
00342       pending_action = NULL;
00343       ink_assert(state == SERVER_TUNNEL);
00344       Debug("SocksProxy", "open to Socks server succeeded\n");
00345 
00346       NetVConnection *serverVC;
00347       serverVC = (NetVConnection *) data;
00348 
00349       OneWayTunnel *c_to_s = OneWayTunnel::OneWayTunnel_alloc();
00350       OneWayTunnel *s_to_c = OneWayTunnel::OneWayTunnel_alloc();
00351 
00352       c_to_s->init(clientVC, serverVC, NULL, clientVIO, reader);
00353       s_to_c->init(serverVC, clientVC,  NULL, 0  ,
00354                    c_to_s->mutex);
00355 
00356       OneWayTunnel::SetupTwoWayTunnel(c_to_s, s_to_c);
00357 
00358       buf = 0;                  
00359       state = ALL_DONE;
00360       break;
00361     }
00362 
00363   case NET_EVENT_OPEN_FAILED:
00364     pending_action = NULL;
00365     sendResp(false);
00366     state = RESP_TO_CLIENT;
00367     Debug("SocksProxy", "open to Socks server failed\n");
00368     break;
00369 
00370   case EVENT_INTERVAL:
00371     timeout = 0;
00372     Debug("SocksProxy", "SocksProxy timeout, state = %d\n", state);
00373     state = SOCKS_ERROR;
00374     break;
00375 
00376   case VC_EVENT_ERROR:
00377   case VC_EVENT_INACTIVITY_TIMEOUT:
00378   case VC_EVENT_ACTIVE_TIMEOUT:
00379   case VC_EVENT_EOS:
00380     Debug("SocksProxy", "VC_EVENT (state: %d error: %s)\n", state, get_vc_event_name(event));
00381     state = SOCKS_ERROR;
00382     break;
00383 
00384   default:
00385     ink_assert(!"bad case value\n");
00386     state = SOCKS_ERROR;
00387   }
00388 
00389   if (state == SOCKS_ERROR) {
00390     if (pending_action)
00391       pending_action->cancel();
00392 
00393     if (timeout)
00394       timeout->cancel(this);
00395 
00396     if (clientVC) {
00397       Debug("SocksProxy", "Closing clientVC on error\n");
00398       clientVC->do_io_close();
00399       clientVC = NULL;
00400     }
00401 
00402     state = ALL_DONE;
00403   }
00404 
00405   recursion--;
00406 
00407   if (state == ALL_DONE && recursion == 0) {
00408     free();
00409   }
00410 
00411   return ret;
00412 }
00413 
00414 int
00415 SocksProxy::sendResp(bool granted)
00416 {
00417   int n_bytes;
00418 
00419   
00420   
00421   
00422   
00423   
00424 
00425 
00426   buf->reset();
00427   unsigned char *p = (unsigned char *) buf->start();
00428 
00429   if (version == SOCKS4_VERSION) {
00430     p[0] = 0;
00431     p[1] = (granted) ? SOCKS4_REQ_GRANTED : SOCKS4_CONN_FAILED;
00432     n_bytes = 8;
00433   } else {
00434     p[0] = SOCKS5_VERSION;
00435     p[1] = (granted) ? SOCKS5_REQ_GRANTED : SOCKS5_CONN_FAILED;
00436     p[2] = 0;
00437     p[3] = SOCKS_ATYPE_IPV4;
00438     p[4] = p[5] = p[6] = p[7] = p[8] = p[9] = 0;
00439     n_bytes = 10;
00440   }
00441 
00442   buf->fill(n_bytes);
00443   clientVC->do_io_write(this, n_bytes, reader, 0);
00444 
00445   return n_bytes;
00446 }
00447 
00448 
00449 int
00450 SocksProxy::setupHttpRequest(unsigned char *p)
00451 {
00452   int ret = EVENT_DONE;
00453 
00454   SocksAddrType *a = &clientVC->socks_addr;
00455 
00456   
00457   
00458   switch (a->type) {
00459 
00460   case SOCKS_ATYPE_IPV4:
00461     a->addr.ipv4[0] = p[4];
00462     a->addr.ipv4[1] = p[5];
00463     a->addr.ipv4[2] = p[6];
00464     a->addr.ipv4[3] = p[7];
00465     break;
00466 
00467   case SOCKS_ATYPE_FQHN:
00468     
00469     a->addr.buf = (unsigned char *)ats_malloc(p[4] + 1);
00470     memcpy(a->addr.buf, &p[5], p[4]);
00471     a->addr.buf[p[4]] = 0;
00472     break;
00473   case SOCKS_ATYPE_IPV6:
00474     
00475     
00476     
00477     
00478     a->type = SOCKS_ATYPE_IPV4;
00479     a->addr.ipv4[0] = p[16];
00480     a->addr.ipv4[0] = p[17];
00481     a->addr.ipv4[0] = p[18];
00482     a->addr.ipv4[0] = p[19];
00483 
00484     break;
00485   default:
00486     ink_assert(!"bad case value");
00487   }
00488 
00489   return ret;
00490 }
00491 
00492 
00493 
00494 
00495 static void
00496 new_SocksProxy(NetVConnection * netVC)
00497 {
00498   SocksProxy *proxy = socksProxyAllocator.alloc();
00499   proxy->init(netVC);
00500 }
00501 
00502 struct SocksAccepter: public Continuation
00503 {
00504 
00505   typedef int (SocksAccepter::*SocksAccepterHandler) (int, void *);
00506 
00507   int mainEvent(int event, NetVConnection * netVC)
00508   {
00509 
00510     ink_assert(event == NET_EVENT_ACCEPT);
00511     
00512 
00513     new_SocksProxy(netVC);
00514 
00515     return EVENT_CONT;
00516   }
00517 
00518   
00519   SocksAccepter():Continuation(NULL)
00520   {
00521     SET_HANDLER((SocksAccepterHandler) & SocksAccepter::mainEvent);
00522   }
00523 };
00524 
00525 void
00526 start_SocksProxy(int port)
00527 {
00528   Debug("SocksProxy", "Accepting SocksProxy connections on port %d\n", port);
00529   NetProcessor::AcceptOptions opt;
00530   opt.local_port = port;
00531   netProcessor.main_accept(new SocksAccepter(), NO_FD, opt);
00532 
00533   socksproxy_stat_block = RecAllocateRawStatBlock(socksproxy_stat_count);
00534 
00535   if (socksproxy_stat_block) {
00536     RecRegisterRawStat(socksproxy_stat_block, RECT_PROCESS,
00537                        "proxy.process.socks.proxy.http_connections",
00538                        RECD_INT, RECP_PERSISTENT, socksproxy_http_connections_stat, RecRawStatSyncCount);
00539 
00540     RecRegisterRawStat(socksproxy_stat_block, RECT_PROCESS,
00541                        "proxy.process.socks.proxy.tunneled_connections",
00542                        RECD_INT, RECP_PERSISTENT, socksproxy_tunneled_connections_stat, RecRawStatSyncCount);
00543   }
00544 }
00545 
00546 int
00547 socks5ServerAuthHandler(int event, unsigned char *p, void (**h_ptr) (void))
00548 {
00549 
00550   int ret = 0;
00551   
00552 
00553   switch (event) {
00554 
00555   case SOCKS_AUTH_READ_COMPLETE:
00556 
00557     ink_assert(p[0] == SOCKS5_VERSION);
00558     Debug("SocksProxy", "Socks read initial auth info\n");
00559     
00560     break;
00561 
00562   case SOCKS_AUTH_FILL_WRITE_BUF:
00563     Debug("SocksProxy", "No authentication is required\n");
00564     p[0] = SOCKS5_VERSION;
00565     p[1] = 0;                   
00566     ret = 2;
00567     
00568   case SOCKS_AUTH_WRITE_COMPLETE:
00569     
00570     *h_ptr = NULL;
00571     break;
00572 
00573   default:
00574     ink_assert(!"bad case value");
00575     ret = -1;
00576   }
00577 
00578   return ret;
00579 }