Main Page | Alphabetical List | Class List | File List | Class Members | File Members

Socks4Socket.cpp

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2004  Anders Hedstrom
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 */
00023 //#include <stdio.h>
00024 #include <ListenSocket.h>
00025 
00026 #include "Socks4Handler.h"
00027 #include "RemoteSocket.h"
00028 #include "Socks4Socket.h"
00029 
00030 
00031 
00032 
00033 Socks4Socket::Socks4Socket(ISocketHandler& h)
00034 :TcpSocket(h)
00035 ,m_state(STATE_VN)
00036 ,m_userid_ptr(0)
00037 ,m_pRemote(NULL)
00038 ,m_bSocks5(false)
00039 ,m_state5(STATE5_VER)
00040 ,m_s5_method(0)
00041 {
00042 }
00043 
00044 
00045 Socks4Socket::~Socks4Socket()
00046 {
00047 }
00048 
00049 
00050 
00051 
00052 void Socks4Socket::OnRead()
00053 {
00054         // ibuf is inherited member variable of TcpSocket
00055         TcpSocket::OnRead();
00056         if (m_bSocks5)
00057                 Socks5Read();
00058         else
00059                 Socks4Read();
00060 }
00061 
00062 
00063 void Socks4Socket::Socks4Read()
00064 {
00065         bool need_more = false;
00066         while (ibuf.GetLength() && !need_more && !CloseAndDelete() )
00067         {
00068                 size_t l = ibuf.GetLength();
00069                 switch (m_state)
00070                 {
00071                 case STATE_VN: // get socks version
00072                         ibuf.Read( (char *)&m_vn, 1);
00073                         if (m_vn == 5) // socks5
00074                         {
00075                                 m_bSocks5 = true;
00076                                 m_state5 = STATE5_NMETHODS;
00077                         }
00078                         else
00079                         if (m_vn == 4)
00080                         {
00081                                 m_state = STATE_CD;
00082                         }
00083                         else
00084                         {
00085                                 Handler().LogError(this, "OnRead", m_vn, "Unsupported socks version", LOG_LEVEL_FATAL);
00086                                 SetCloseAndDelete();
00087                         }
00088                         break;
00089                 case STATE_CD:
00090                         ibuf.Read( (char *)&m_cd, 1);
00091                         if (m_cd != 1 && m_cd != 2)
00092                         {
00093                                 Handler().LogError(this, "OnRead", m_cd, "Bad command code", LOG_LEVEL_FATAL);
00094                                 SetCloseAndDelete();
00095                         }
00096                         else
00097                         {
00098                                 m_state = STATE_DSTPORT;
00099                         }
00100                         break;
00101                 case STATE_DSTPORT:
00102                         if (l > 1)
00103                         {
00104                                 ibuf.Read( (char *)&m_dstport, 2);
00105                                 m_state = STATE_DSTIP;
00106                         }
00107                         else
00108                         {
00109                                 need_more = true;
00110                         }
00111                         break;
00112                 case STATE_DSTIP:
00113                         if (l > 3)
00114                         {
00115                                 ibuf.Read( (char *)&m_dstip, 4);
00116                                 m_state = STATE_USERID;
00117                         }
00118                         else
00119                         {
00120                                 need_more = true;
00121                         }
00122                         break;
00123                 case STATE_USERID:
00124                         if (m_userid_ptr < MAXLEN_USERID)
00125                         {
00126                                 ibuf.Read(m_userid + m_userid_ptr, 1);
00127                                 if (m_userid[m_userid_ptr] == 0)
00128                                 {
00129                                         switch (m_cd)
00130                                         {
00131                                         case 1:
00132                                                 SetupConnect();
00133                                                 break;
00134                                         case 2:
00135                                                 SetupBind();
00136                                                 break;
00137                                         }
00138                                 }
00139                                 m_userid_ptr++;
00140                         }
00141                         else
00142                         {
00143                                 Handler().LogError(this, "OnRead", m_userid_ptr, "Userid too long", LOG_LEVEL_FATAL);
00144                                 SetCloseAndDelete();
00145                         }
00146                         break;
00147                 case STATE_TRY_CONNECT:
00148                         break;
00149                 case STATE_CONNECTED:
00150                         {
00151                                 char buf[TCP_BUFSIZE_READ];
00152                                 ibuf.Read(buf, l);
00153                                 if (m_pRemote && Handler().Valid(m_pRemote))
00154                                 {
00155                                         m_pRemote -> SendBuf(buf, l);
00156                                 }
00157                         }
00158                         break;
00159                 case STATE_FAILED:
00160                         SetCloseAndDelete();
00161                         break;
00162                 case STATE_ACCEPT:
00163                         break;
00164                 }
00165         }
00166 }
00167 
00168 
00169 void Socks4Socket::Connected()
00170 {
00171         if (m_state == STATE_TRY_CONNECT)
00172         {
00173                 char reply[8];
00174                 reply[0] = 0;
00175                 reply[1] = 90; // granted
00176                 memcpy(reply + 2, &m_dstport, 2);
00177                 memcpy(reply + 4, &m_dstip, 4);
00178                 SendBuf(reply, 8);
00179                 m_state = STATE_CONNECTED;
00180         }
00181         else
00182         {
00183                 Handler().LogError(this, "Connected", m_state, "bad state", LOG_LEVEL_FATAL);
00184                 SetCloseAndDelete();
00185         }
00186 }
00187 
00188 
00189 void Socks4Socket::ConnectFailed()
00190 {
00191         if (m_state == STATE_TRY_CONNECT)
00192         {
00193                 char reply[8];
00194                 reply[0] = 0;
00195                 reply[1] = 91; // failed
00196                 memcpy(reply + 2, &m_dstport, 2);
00197                 memcpy(reply + 4, &m_dstip, 4);
00198                 SendBuf(reply, 8);
00199                 m_state = STATE_FAILED;
00200                 SetCloseAndDelete();
00201         }
00202         else
00203         {
00204                 Handler().LogError(this, "ConnectFailed", m_state, "bad state", LOG_LEVEL_FATAL);
00205                 SetCloseAndDelete();
00206         }
00207 }
00208 
00209 
00210 void Socks4Socket::SetupConnect()
00211 {
00212         m_pRemote = new RemoteSocket(Handler());
00213         port_t port = ntohs(m_dstport);
00214         ipaddr_t addr = m_dstip; //ntohl(m_dstip);
00215         m_pRemote -> Open(addr, port);
00216         m_pRemote -> SetDeleteByHandler();
00217         m_pRemote -> SetRemote(this);
00218         Handler().Add(m_pRemote);
00219         //
00220         m_state = STATE_TRY_CONNECT;
00221 }
00222 
00223 
00224 void Socks4Socket::SetupBind()
00225 {
00226         ListenSocket<RemoteSocket> *p = new ListenSocket<RemoteSocket>(Handler());
00227         p -> SetDeleteByHandler();
00228         p -> Bind(0);
00229         Handler().Add(p);
00230         static_cast<Socks4Handler&>(Handler()).SetBind(p, this);
00231 
00232         char reply[8];
00233         reply[0] = 0;
00234         reply[1] = 90;
00235         port_t port = p -> GetPort();
00236         unsigned short s = htons(port);
00237         memcpy(reply + 2,&s,2);
00238         memset(reply + 4,0,4);
00239         SendBuf(reply, 8);
00240         //
00241         m_state = STATE_ACCEPT;
00242 }
00243 
00244 
00245 void Socks4Socket::Accept()
00246 {
00247         if (m_state == STATE_ACCEPT)
00248         {
00249                 ipaddr_t remote = m_pRemote -> GetRemoteIP4();
00250                 ipaddr_t dstip = ntohl(m_dstip);
00251                 char reply[8];
00252                 reply[0] = 0;
00253                 reply[1] = (dstip == remote) ? 90 : 91;
00254                 memcpy(reply + 2, &m_dstport, 2);
00255                 memcpy(reply + 4, &m_dstip, 4);
00256                 SendBuf(reply, 8);
00257                 m_state = (dstip == remote) ? STATE_CONNECTED : STATE_FAILED;
00258                 if (m_state == STATE_FAILED)
00259                 {
00260                         Handler().LogError(this, "Accept", remote, "Remote ip mismatch", LOG_LEVEL_FATAL);
00261                         SetCloseAndDelete();
00262                 }
00263         }
00264         else
00265         {
00266                 Handler().LogError(this, "Accept", m_state, "bad state", LOG_LEVEL_FATAL);
00267                 SetCloseAndDelete();
00268         }
00269 }
00270 
00271 
00272 void Socks4Socket::Socks5Read()
00273 {
00274 /*
00275                 STATE5_VER = 0,
00276                 STATE5_NMETHODS,
00277                 STATE5_METHODS,
00278                 STATE5_GSSAPI, // not implemented
00279                 STATE5_USERPASSWORD_VER,
00280                 STATE5_USERPASSWORD_ULEN,
00281                 STATE5_USERPASSWORD_UNAME,
00282                 STATE5_USERPASSWORD_PLEN,
00283                 STATE5_USERPASSWORD_PASSWD,
00284                 STATE5_VER2,
00285                 STATE5_CMD,
00286                 STATE5_RSV,
00287                 STATE5_ATYP,
00288                 STATE5_ALEN,
00289                 STATE5_DST_ADDR,
00290                 STATE5_DST_PORT,
00291 */
00292         bool need_more = false;
00293         while (ibuf.GetLength() && !need_more && !CloseAndDelete() )
00294         {
00295                 size_t l = ibuf.GetLength();
00296                 switch (m_state5)
00297                 {
00298                 case STATE5_VER: // always done by Socks4Read
00299                         break;
00300                 case STATE5_NMETHODS:
00301                         ibuf.Read( (char *)&m_s5_nmethods, 1);
00302                         m_state5 = STATE5_METHODS;
00303                         m_s5_method = 0;
00304                         memset(m_s5_methods, 0, sizeof(m_s5_methods));
00305                         break;
00306                 case STATE5_METHODS:
00307                         while (ibuf.GetLength() && m_s5_method < m_s5_nmethods)
00308                         {
00309                                 unsigned char c;
00310                                 ibuf.Read( (char *)&c, 1);
00311                                 m_s5_methods[c] = 1;
00312                                 m_s5_method++;
00313                         }
00314                         if (m_s5_method == m_s5_nmethods)
00315                         {
00316                                 char reply[2];
00317                                 // select method
00318                                 if (m_s5_methods[2]) // username/password
00319                                 {
00320                                         reply[0] = 5; // 5?
00321                                         reply[1] = 2;
00322                                         SendBuf(reply, 2);
00323                                         m_state5 = STATE5_USERPASSWORD_VER;
00324                                 }
00325                                 else
00326                                 if (m_s5_methods[0]) // no auth
00327                                 {
00328                                         reply[0] = 5; // 5?
00329                                         reply[1] = 0;
00330                                         SendBuf(reply, 2);
00331                                         m_state5 = STATE5_VER2;
00332                                 }
00333                                 else
00334                                 {
00335                                         reply[0] = 5; // 5?
00336                                         reply[1] = 255;
00337                                         SendBuf(reply, 2);
00338                                         m_state5 = STATE5_FAILED;
00339                                 }
00340                         }
00341                         else
00342                         {
00343                                 need_more = true;
00344                         }
00345                         break;
00346                 case STATE5_FAILED:
00347                         break;
00348                 case STATE5_GSSAPI: // not implemented
00349                         break;
00350                 case STATE5_USERPASSWORD_VER:
00351                         ibuf.Read( &m_s5_userpassword_ver, 1);
00352                         if (m_s5_userpassword_ver == 1)
00353                                 m_state5 = STATE5_USERPASSWORD_ULEN;
00354                         else
00355                         {
00356                                 Handler().LogError(this, "Socks5", m_s5_userpassword_ver, "Username/Password version number != 1", LOG_LEVEL_FATAL);
00357                                 m_state5 = STATE5_FAILED;
00358                                 SetCloseAndDelete();
00359                         }
00360                         break;
00361                 case STATE5_USERPASSWORD_ULEN:
00362                         ibuf.Read( (char *)&m_s5_userpassword_ulen, 1);
00363                         m_state5 = STATE5_USERPASSWORD_UNAME;
00364                         m_s5_uptr = 0;
00365                         break;
00366                 case STATE5_USERPASSWORD_UNAME:
00367                         while (ibuf.GetLength() && m_s5_uptr < m_s5_userpassword_ulen)
00368                         {
00369                                 ibuf.Read( &m_s5_userpassword_uname[m_s5_uptr], 1);
00370                                 m_s5_uptr++;
00371                         }
00372                         if (m_s5_uptr == m_s5_userpassword_ulen)
00373                         {
00374                                 m_s5_userpassword_uname[m_s5_uptr] = 0;
00375                                 m_state5 = STATE5_USERPASSWORD_PLEN;
00376                         }
00377                         else
00378                         {
00379                                 need_more = true;
00380                         }
00381                         break;
00382                 case STATE5_USERPASSWORD_PLEN:
00383                         ibuf.Read( (char *)&m_s5_userpassword_plen, 1);
00384                         m_state5 = STATE5_USERPASSWORD_PASSWD;
00385                         m_s5_pptr = 0;
00386                         break;
00387                 case STATE5_USERPASSWORD_PASSWD:
00388                         while (ibuf.GetLength() && m_s5_pptr < m_s5_userpassword_plen)
00389                         {
00390                                 ibuf.Read( &m_s5_userpassword_passwd[m_s5_pptr], 1);
00391                                 m_s5_pptr++;
00392                         }
00393                         if (m_s5_pptr == m_s5_userpassword_plen)
00394                         {
00395                                 m_s5_userpassword_passwd[m_s5_pptr] = 0;
00396                                 // %! verify username/password
00397                                 m_state5 = STATE5_VER2;
00398                         }
00399                         else
00400                         {
00401                                 need_more = true;
00402                         }
00403                         break;
00404                 case STATE5_VER2:
00405                         ibuf.Read(&m_s5_ver2, 1);
00406                         if (m_s5_ver2 == 5)
00407                                 m_state5 = STATE5_CMD;
00408                         else
00409                         {
00410                                 Handler().LogError(this, "Socks5", m_s5_ver2, "Version != 5", LOG_LEVEL_FATAL);
00411                                 m_state5 = STATE5_FAILED;
00412                                 SetCloseAndDelete();
00413                         }
00414                         break;
00415                 case STATE5_CMD:
00416                         ibuf.Read(&m_s5_cmd, 1);
00417                         if (m_s5_cmd == 1 || m_s5_cmd == 2 || m_s5_cmd == 3)
00418                                 m_state5 = STATE5_RSV;
00419                         else
00420                         {
00421                                 Handler().LogError(this, "Socks5", m_s5_cmd, "Bad command code", LOG_LEVEL_FATAL);
00422                                 m_state5 = STATE5_FAILED;
00423                                 SetCloseAndDelete();
00424                         }
00425                         break;
00426                 case STATE5_RSV:
00427                         m_state5 = STATE5_ATYP;
00428                         break;
00429                 case STATE5_ATYP:
00430                         ibuf.Read(&m_s5_atyp, 1);
00431                         switch (m_s5_atyp)
00432                         {
00433                         case 1: // IPv4
00434                                 m_state5 = STATE5_DST_ADDR;
00435                                 m_s5_alen = 4;
00436                                 break;
00437                         case 3: // domain name
00438                                 m_state5 = STATE5_ALEN;
00439                                 break;
00440                         case 4: // IPv6
00441                                 m_state5 = STATE5_DST_ADDR;
00442                                 m_s5_alen = 6;
00443                                 break;
00444                         default:
00445                                 Handler().LogError(this, "Socks5", m_s5_atyp, "Bad address type", LOG_LEVEL_FATAL);
00446                                 m_state5 = STATE5_FAILED;
00447                                 SetCloseAndDelete();
00448                         }
00449                         m_s5_aptr = 0;
00450                         break;
00451                 case STATE5_ALEN:
00452                         ibuf.Read( (char *)&m_s5_alen,1);
00453                         m_state5 = STATE5_DST_ADDR;
00454                         break;
00455                 case STATE5_DST_ADDR:
00456                         while (ibuf.GetLength() && m_s5_aptr < m_s5_alen)
00457                         {
00458                                 ibuf.Read( (char *)&m_s5_dst_addr[m_s5_aptr], 1);
00459                                 m_s5_aptr++;
00460                         }
00461                         if (m_s5_aptr == m_s5_alen)
00462                         {
00463                                 m_s5_dst_addr[m_s5_aptr] = 0;
00464                                 m_state5 = STATE5_DST_PORT;
00465                         }
00466                         else
00467                         {
00468                                 need_more = true;
00469                         }
00470                         break;
00471                 case STATE5_DST_PORT:
00472                         if (l > 1)
00473                         {
00474                                 ibuf.Read( (char *)&m_s5_dst_port, 2);
00475                                 DoSocks5();
00476                         }
00477                         else
00478                         {
00479                                 need_more = true;
00480                         }
00481                         break;
00482                 }
00483         }
00484 }
00485 
00486 
00487 void Socks4Socket::DoSocks5()
00488 {
00489         switch (m_s5_cmd)
00490         {
00491         case 1: // CONNECT
00492                 break;
00493         case 2: // BIND
00494                 break;
00495         case 3: // UDP ASSOCIATE
00496                 break;
00497         }
00498 }
00499 
00500 

Generated on Tue Oct 3 23:44:54 2006 for Socks4 Server by  doxygen 1.4.4