bool CSocks::SocksTCPTunneling(u_int sres, u_int sdest) { register u_int sockr, sockw, ret; register u_int uread, uwrote; char szBuffer[1024]; fd_set fd; timeval tv = {0,0}; do { FD_ZERO(&fd); FD_SET(sres,&fd); FD_SET(sdest,&fd); if((ret = select(2,&fd,NULL,NULL,&tv))>0 && VALID_SOCKET(ret)) { if(FD_ISSET(sres,&fd)) { sockr = sres; sockw = sdest; } else { sockr = sdest; sockw = sres; } uread = recv(sockr,szBuffer,1023,0); szBuffer[uread] = 0; uwrote = 0; if(!VALID_SOCKET(uread) || uread==0) break; while(uwrote<uread) { ret = send(sockw,szBuffer+uwrote,uread-uwrote,0); if(!VALID_SOCKET(ret)) goto __quit; uwrote += ret; } } FD_ZERO(&fd); FD_SET(sres,&fd); FD_SET(sdest,&fd); if(select(2,NULL,NULL,&fd,&tv)>0) break; } while(1); __quit: return(true); }
bool CSocks::SocksUDPTunneling(void* sares, char* sData, u_int len) { register u_int sdest, pos; register u_int sres; struct sockaddr_in sadest; struct timeval tv; struct fd_set fd; char szBuffer[1024]; tv.tv_usec = 0; tv.tv_sec = 7; sadest.sin_family = AF_INET; switch(sData[3]) { case 1: memcpy(szBuffer,sData+4,4); sadest.sin_addr.s_addr = *(u_long*)szBuffer; sadest.sin_port = *(u_short*)(sData+8); pos = 10; break; case 2: memcpy(szBuffer,sData+5,sData[4]); szBuffer[sData[4]] = 0; if(!DNSAddrLookup(szBuffer,&sadest.sin_addr)) return(false); sadest.sin_port = *(u_short*)(sData+5+sData[4]); pos = 7+sData[4]; break; case 3: memcpy(szBuffer,sData+4,16); szBuffer[16] = 0; return(true); default: return(false); } sdest = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); sres = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); if(!VALID_SOCKET(sdest) || VALID_SOCKET(sres)) return(false); sendto(sdest,sData+pos,len-pos,0,(struct sockaddr*)&sadest,sizeof(sadest)); if(bind(sdest,(struct sockaddr*)sares,sizeof(struct sockaddr))) return(false); do { FD_ZERO(&fd); FD_SET(sres,&fd); select(1,&fd,NULL,NULL,&tv); pos = recvfrom(sdest,szBuffer,1023,0,NULL,NULL); sendto(sres,szBuffer,pos,0,(struct sockaddr*)sares,sizeof(struct sockaddr)); } while(pos>0 && VALID_SOCKET(pos)); closesocket(sdest); closesocket(sres); return(true); };
void f_socket_write (void) { int i, fd, port; svalue_t *arg; char addr[ADDR_BUF_SIZE]; int num_arg = st_num_arg; arg = sp - num_arg + 1; if ((num_arg == 3) && (arg[2].type != T_STRING)) { bad_arg(3, F_SOCKET_WRITE); } fd = arg[0].u.number; get_socket_address(fd, addr, &port, 0); if (VALID_SOCKET("write")) { i = socket_write(fd, &arg[1], (num_arg == 3) ? arg[2].u.string : (char *) NULL); pop_n_elems(num_arg - 1); sp->u.number = i; } else { pop_n_elems(num_arg - 1); sp->u.number = EESECURITY; } }
void f_socket_close (void) { int fd, port; char addr[ADDR_BUF_SIZE]; fd = sp->u.number; get_socket_address(fd, addr, &port, 0); sp->u.number = VALID_SOCKET("close") ? socket_close(fd, 0) : EESECURITY; }
void f_socket_accept (void) { int port, fd; char addr[ADDR_BUF_SIZE]; if (!(sp->type & (T_STRING | T_FUNCTION))) { bad_arg(3, F_SOCKET_ACCEPT); } get_socket_address(fd = (sp-2)->u.number, addr, &port, 0); (sp-2)->u.number = VALID_SOCKET("accept") ? socket_accept(fd, (sp - 1), sp) : EESECURITY; pop_2_elems(); }
void f_socket_connect (void) { int i, fd, port; char addr[ADDR_BUF_SIZE]; if (!((sp - 1)->type & (T_FUNCTION | T_STRING))) { bad_arg(3, F_SOCKET_CONNECT); } if (!(sp->type & (T_FUNCTION | T_STRING))) { bad_arg(4, F_SOCKET_CONNECT); } fd = (sp - 3)->u.number; get_socket_address(fd, addr, &port, 0); if (!strcmp(addr, "0.0.0.0") && port == 0) { /* * socket descriptor is not bound yet */ char *s; int start = 0; addr[0] = '\0'; if ((s = strchr((sp - 2)->u.string, ' '))) { /* * use specified address and port */ i = s - (sp - 2)->u.string; if (i > ADDR_BUF_SIZE - 1) { start = i - ADDR_BUF_SIZE - 1; i = ADDR_BUF_SIZE - 1; } strncat(addr, (sp - 2)->u.string + start, i); port = atoi(s + 1); } #ifdef DEBUG } else { fprintf(stderr, "socket_connect: socket already bound to address/port: %s/%d\n", addr, port); fprintf(stderr, "socket_connect: requested on: %s\n", (sp - 2)->u.string); #endif } (sp-3)->u.number = VALID_SOCKET("connect") ? socket_connect(fd, (sp - 2)->u.string, sp - 1, sp) : EESECURITY; pop_3_elems(); }
void f_socket_listen (void) { int i, fd, port; char addr[ADDR_BUF_SIZE]; fd = (sp - 1)->u.number; get_socket_address(fd, addr, &port, 0); if (VALID_SOCKET("listen")) { i = socket_listen(fd, sp); pop_stack(); sp->u.number = i; } else { pop_stack(); sp->u.number = EESECURITY; } }
void f_socket_acquire (void) { int fd, port; char addr[ADDR_BUF_SIZE]; if (!((sp - 1)->type & (T_FUNCTION | T_STRING))) { bad_arg(3, F_SOCKET_ACQUIRE); } if (!(sp->type & (T_FUNCTION | T_STRING))) { bad_arg(4, F_SOCKET_ACQUIRE); } fd = (sp - 3)->u.number; get_socket_address(fd, addr, &port, 0); (sp-3)->u.number = VALID_SOCKET("acquire") ? socket_acquire((sp - 3)->u.number, (sp - 2), (sp - 1), sp) : EESECURITY; pop_3_elems(); }
void f_socket_release (void) { int fd, port; char addr[ADDR_BUF_SIZE]; if (!(sp->type & (T_STRING | T_FUNCTION))) { bad_arg(3, F_SOCKET_RELEASE); } fd = (sp - 2)->u.number; get_socket_address(fd, addr, &port, 0); (sp-2)->u.number = VALID_SOCKET("release") ? socket_release((sp - 2)->u.number, (sp - 1)->u.ob, sp) : EESECURITY; pop_stack(); /* the object might have been dested an removed from the stack */ if (sp->type == T_OBJECT) free_object(sp->u.ob, "socket_release()"); sp--; }
void f_socket_bind (void) { int i, fd, port, num_arg = st_num_arg; svalue_t *arg; char addr[ADDR_BUF_SIZE]; arg = sp - num_arg + 1; if ((num_arg == 3) && (arg[2].type != T_STRING)) { bad_arg(3, F_SOCKET_BIND); } fd = arg[0].u.number; get_socket_address(fd, addr, &port, 0); if (VALID_SOCKET("bind")) { i = socket_bind(fd, arg[1].u.number, (num_arg == 3 ? arg[2].u.string : 0)); pop_n_elems(num_arg - 1); sp->u.number = i; } else { pop_n_elems(num_arg - 1); sp->u.number = EESECURITY; } }
bool CSocks5::ForceConnection(u_int sock) { register u_int schain, ret, i; char szBuffer[1024]; struct fd_set fd; struct timeval tv; struct sockaddr_in sain; SOCKS5REQ req; tv.tv_usec = 0; tv.tv_sec = 11; FD_ZERO(&fd); FD_SET(sock,&fd); if(!VALID_SOCKET(sock)) return(false); if(mode==SOCKS_MODE_TCP) { if(select(1,&fd,NULL,NULL,&tv)>0 && FD_ISSET(sock,&fd)) { schain = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP); if(!VALID_SOCKET(schain)) return(false); recv(sock,szBuffer,2,0); if(szBuffer[0]!=5) return(false); ret = szBuffer[1]; memset(szBuffer,0,11); recv(sock,szBuffer,ret,0); char szLogin[256], szPassword[256]; send(sock,"\x05\x02",2,0); tv.tv_usec = 0; tv.tv_sec = 7; FD_ZERO(&fd); FD_SET(sock,&fd); select(1,&fd,NULL,NULL,&tv); memset(szBuffer,0,128); recv(sock,szBuffer,2,0); if(szBuffer[0]!=1) return(false); recv(sock,szLogin,szBuffer[1],0); szLogin[szBuffer[1]] = 0; recv(sock,szBuffer,1,0); recv(sock,szPassword,szBuffer[0],0); szPassword[szBuffer[0]] = 0; if(strcmp(szLogin,m_sUser.CStr()) && strcmp(szPassword,m_sPass.CStr())) { closesocket(sock); return false; } send(sock,"\x05\x00",2,0); FD_ZERO(&fd); FD_SET(sock,&fd); select(1,&fd,NULL,NULL,&tv); if(!FD_ISSET(sock,&fd)) return(false); recv(sock,(char*)&req,4,0); switch(req.uAddrType) { case 1: recv(sock,(char*)szBuffer,4,0); break; case 3: recv(sock,(char*)szBuffer,1,0); recv(sock,(char*)req.uDstAddr,szBuffer[0],0); req.uDstAddr[szBuffer[0]] = 0; if(!DNSAddrLookup((char*)req.uDstAddr,(struct in_addr*)szBuffer)) { return(false); } break; case 4: return(false); default: ; } recv(sock,(char*)&req.uDstPort,sizeof(req.uDstPort),0); if(req.uCommand==1) { sain.sin_family = AF_INET; sain.sin_port = req.uDstPort; sain.sin_addr.s_addr = *(u_long*)szBuffer; if(connect(schain,(struct sockaddr*)&sain,sizeof(sain))!=0) { return(false); } } else { return(false); } send(sock,"\x05\x00\x00\x01",4,0); // succeeded send(sock,szBuffer,4,0); send(sock,(char*)&req.uDstPort,2,0); SocksTCPTunneling(sock,schain); closesocket(schain); } } else if(mode==SOCKS_MODE_UDP) { do { FD_ZERO(&fd); FD_SET(sock,&fd); select(1,&fd,NULL,NULL,&tv); i = sizeof(sain); ret = recvfrom(sock,szBuffer,1023,0,(struct sockaddr*)&sain,(int*)&i); SocksUDPTunneling(&sain,szBuffer,ret); } while(ret!=0 && VALID_SOCKET(ret) && FD_ISSET(sock,&fd)); } return(true); };