/* WebDownloader for X-Window * Copyright (C) 1999-2002 Koshelev Maxim * This Program is free but not GPL!!! You can't modify it * without agreement with author. You can't distribute modified * program but you can distribute unmodified program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include "socks.h" #include "dbc.h" #include #include #include #include #include enum D4X_SOCKS_AUTH{ SOCKS_AUTH_NONE=0, SOCKS_AUTH_GSSAPI, SOCKS_AUTH_USER }; #define SOCKS_AUTH_FAILED 0xFF enum D4X_SOCKS_CMDS{ SOCKS_CMD_UNKNOWN=0, SOCKS_CMD_CONNECT, SOCKS_CMD_BIND, SOCKS_CMD_UDP }; enum D4X_SOCKS_ATYPES{ SOCKS_ATYPE_UNKNOWN=0, SOCKS_ATYPE_IPV4, SOCKS_ATYPE_RESERVED, SOCKS_ATYPE_DOMAIN, SOCKS_ATYPE_IPV6 }; enum D4X_SOCKS_REPLIES{ SOCKS_REP_SUCCESS, SOCKS_REP_FAILURE, SOCKS_REP_FORBIDEN, SOCKS_REP_NETFAILED, SOCKS_REP_HOSTFAILED, SOCKS_REP_REFUSED, SOCKS_REP_EXPIRED, SOCKS_REP_NOTSUPPORTED, SOCKS_REP_WRONGTYPE }; #define SOCKS_VERSION 5 /****************************************************************/ tSocksSocket::tSocksSocket():tSocket(){ socks_port=0; }; tSocksSocket::tSocksSocket(char *host,unsigned short int port, char *use,char *pas):tSocket(){ user.set(use); pass.set(pas); socks_host.set(host); socks_port=port; }; tSocksSocket::~tSocksSocket(){ }; void tSocksSocket::socks_init(){ DBC_RETURN_IF_FAIL(socks_host.get()!=NULL); if (tSocket::open_port(socks_host.get(),socks_port)){ down(); return; }; if (user.get()==NULL || pass.get()==NULL){ unsigned char request[]={SOCKS_VERSION,1,SOCKS_AUTH_NONE}; write(fd,request,sizeof(request)); }else{ unsigned char request[]={SOCKS_VERSION,2, SOCKS_AUTH_NONE, SOCKS_AUTH_USER}; write(fd,request,sizeof(request)); }; if (read(fd,socks_buf,2)<2){ down(); return; }; if (socks_buf[1]==SOCKS_AUTH_NONE) return; //successfull initiated if (socks_buf[1]==SOCKS_AUTH_USER && user.get() && pass.get()){ unsigned char tmp=1; write(fd,&tmp,sizeof(tmp)); tmp=strlen(user.get()); write(fd,&tmp,sizeof(tmp)); write(fd,user.get(),tmp); tmp=strlen(pass.get()); write(fd,&tmp,sizeof(tmp)); write(fd,pass.get(),tmp); if (read(fd,&socks_buf,2)<2){ down(); return; }; if (socks_buf[1]==0) return; }; down(); //failed to connect }; int tSocksSocket::socks_connect_reply(){ int repsize=read(fd,socks_buf,10); if (repsize<10){ down(); return(SOCKET_CANT_CONNECT); }; switch(socks_buf[1]){ case SOCKS_REP_SUCCESS:{ break; }; case SOCKS_REP_FAILURE: case SOCKS_REP_NETFAILED: case SOCKS_REP_HOSTFAILED: return(SOCKET_UNKNOWN_HOST); default: return(SOCKET_CANT_CONNECT); }; return 0; }; int tSocksSocket::open_port(char *host, guint16 port) { DBC_RETVAL_IF_FAIL(host!=NULL,SOCKET_CANT_CONNECT); socks_init(); if (fd<0) return(SOCKET_CANT_CONNECT); socks_buf[0]=SOCKS_VERSION; socks_buf[1]=SOCKS_CMD_CONNECT; socks_buf[2]=0; socks_buf[3]=SOCKS_ATYPE_DOMAIN; write(fd,socks_buf,4); unsigned char tmp=strlen(host); write(fd,&tmp,1); write(fd,host,tmp); port=htons(port); write(fd,&port,2); return(socks_connect_reply()); }; int tSocksSocket::open_port(guint32 host,guint16 port) { // port=htons(port); // host=htonl(host); socks_init(); if (fd<0) return(SOCKET_CANT_CONNECT); socks_buf[0]=SOCKS_VERSION; socks_buf[1]=SOCKS_CMD_CONNECT; socks_buf[2]=0; socks_buf[3]=SOCKS_ATYPE_IPV4; write(fd,socks_buf,4); write(fd,&host,4); write(fd,&port,2); return(socks_connect_reply()); }; unsigned int tSocksSocket::get_addr(){ return(bnd_host); }; unsigned short int tSocksSocket::get_port(){ return(bnd_port); }; int tSocksSocket::socks_bind_reply(){ int repsize=read(fd,socks_buf,10); if (repsize<10){ down(); return(SOCKET_CANT_CONNECT); }; switch(socks_buf[1]){ case SOCKS_REP_SUCCESS:{ break; }; case SOCKS_REP_FAILURE: case SOCKS_REP_NETFAILED: case SOCKS_REP_HOSTFAILED: return(SOCKET_UNKNOWN_HOST); default: return(SOCKET_CANT_CONNECT); }; memcpy(&bnd_host,socks_buf+4,4); memcpy(&bnd_port,socks_buf+8,2); bnd_host=ntohl(bnd_host); bnd_port=ntohs(bnd_port); return 0; }; int tSocksSocket::accepting(char *host){ DBC_RETVAL_IF_FAIL(host!=NULL,-1); int repsize=read(fd,socks_buf,10); if (repsize<10){ down(); return(-1); }; if (socks_buf[1]!=SOCKS_REP_SUCCESS){ down(); return(-1); }; return(0); }; int tSocksSocket::open_any(char * host){ DBC_RETVAL_IF_FAIL(host!=NULL,SOCKET_CANT_CONNECT); socks_init(); if (fd<0) return(SOCKET_CANT_CONNECT); socks_buf[0]=SOCKS_VERSION; socks_buf[1]=SOCKS_CMD_BIND; socks_buf[2]=0; socks_buf[3]=SOCKS_ATYPE_DOMAIN; write(fd,socks_buf,4); unsigned char tmp=strlen(host); write(fd,&tmp,1); write(fd,host,tmp); guint16 port=0; write(fd,&port,2); return(socks_bind_reply()); }; int tSocksSocket::open_any(guint32 host) { host=htonl(host); socks_init(); if (fd<0) return(SOCKET_CANT_CONNECT); socks_buf[0]=SOCKS_VERSION; socks_buf[1]=SOCKS_CMD_BIND; socks_buf[2]=0; socks_buf[3]=SOCKS_ATYPE_IPV4; write(fd,socks_buf,4); // guint32 me=htonl(tSocket::get_addr()); // write(fd,&me,4); /* char a[6]={0,0,0,0,0,0}; write(fd,a,6); */ write(fd,&host,4); guint16 port=0; write(fd,&port,2); return(socks_bind_reply()); };