コード例 #1
0
ファイル: webadmin.c プロジェクト: CSRedRat/3proxy
static void stdpr(struct printparam* pp, char *buf, int inbuf){
	if((pp->inbuf + inbuf > 1024) || !buf) {
		socksend(pp->cp->clisock, (unsigned char *)pp->buf, pp->inbuf, conf.timeouts[STRING_S]);
		pp->inbuf = 0;
		if(!buf) return;
	}
	if(inbuf >= 1000){
		socksend(pp->cp->clisock, (unsigned char *)buf, inbuf, conf.timeouts[STRING_S]);		
	}
	else {
		memcpy(pp->buf + pp->inbuf, buf, inbuf);
		pp->inbuf += inbuf;
	}
}
コード例 #2
0
ファイル: ftp.c プロジェクト: CocoBir/3proxy
SOCKET ftpcommand(struct clientparam *param, unsigned char * command, unsigned char  *arg) {
	char buf[1024];
	int i;
	SOCKET s;


	s = ftpdata(param);
	if(s==INVALID_SOCKET) return INVALID_SOCKET;
	sprintf(buf, "%.15s%s%.512s\r\n", command, arg?
		(unsigned char *)" ":(unsigned char *)"", 
		arg?arg:(unsigned char *)"");
	if((int)socksend(param->remsock, (unsigned char *)buf, (int)strlen(buf), conf.timeouts[STRING_S]) != (int)strlen(buf)){
		so._closesocket(s);
		return INVALID_SOCKET;
	}
	param->statscli64 += (int)strlen(buf);
	param->nwrites++;
	while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
	}
	if(i < 3) {
		so._closesocket(s);
		return INVALID_SOCKET;
	}
	if(buf[0] != '1') {
		so._closesocket(s);
		return INVALID_SOCKET;
	}
	return s;
}
コード例 #3
0
ファイル: pop3p.c プロジェクト: areiter/InMemoryFuzzing
void * pop3pchild(void * data) {
#define param ((struct clientparam*)data)
 int i=0, res;
 unsigned char buf[320];
 unsigned char *se;

 if(socksend(param->clisock, (unsigned char *)"+OK Proxy\r\n", 11, conf.timeouts[STRING_S])!=11) {RETURN (611);}
 i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
 while(i > 4 && strncasecmp((char *)buf, "USER", 4)){
	if(!strncasecmp((char *)buf, "QUIT", 4)){
		socksend(param->clisock, (unsigned char *)"+OK\r\n", 5,conf.timeouts[STRING_S]);	
		RETURN(0);
	}
	socksend(param->clisock, (unsigned char *)"-ERR need USER first\r\n", 22, conf.timeouts[STRING_S]);	
	i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
 }
 if(i<6) {RETURN(612);}
 
 buf[i] = 0;
 if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0;
 if (strncasecmp((char *)buf, "USER ", 5)){RETURN (614);}
 if(!param->hostname && param->remsock == INVALID_SOCKET) {
	if(parseconnusername((char *)buf +5, param, 0, 110)){RETURN(615);}
 }
 else if(parseusername((char *)buf + 5, param, 0)) {RETURN(616);}
 param->operation = CONNECT;
 res = (*param->authfunc)(param);
 if(res) {RETURN(res);}
 i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
 param->statssrv+=i;
 if( i < 3 ) {RETURN(621);}
 buf[i] = 0;
 if(strncasecmp((char *)buf, "+OK", 3)||!strncasecmp((char *)buf+4, "PROXY", 5)){RETURN(622);}
 if( socksend(param->remsock, (unsigned char *)"USER ", 5, conf.timeouts[STRING_S])!= 5 || 
	socksend(param->remsock, param->extusername, strlen((char *)param->extusername), conf.timeouts[STRING_S]) <= 0 ||
	socksend(param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2)
		{RETURN(623);}
 param->statscli += (strlen((char *)param->extusername) + 7);
 RETURN (sockmap(param, 180));
CLEANRET:

 if(param->hostname&&param->extusername) {
	sprintf((char *)buf, "%.64s@%.128s%c%hu", param->extusername, param->hostname, (ntohs(param->sins.sin_port)==110)?0:':', ntohs(param->sins.sin_port));
	 (*param->logfunc)(param, buf);
 }
 else (*param->logfunc)(param, NULL);
 if(param->clisock != INVALID_SOCKET) {
	if ((param->res > 0 && param->res < 100) || (param->res > 611 && param->res <700)) socksend(param->clisock, (unsigned char *)"-ERR\r\n", 6,conf.timeouts[STRING_S]);
 }
 freeparam(param);
 return (NULL);
}
コード例 #4
0
ファイル: ftp.c プロジェクト: CocoBir/3proxy
SOCKET ftpdata(struct clientparam *param){
	char buf[1024];
	int i;
	char *sb, *se;
	SOCKET s = INVALID_SOCKET, rem;
	unsigned long b1, b2, b3, b4;
	unsigned short b5, b6;
	SASIZETYPE sasize;

	if(socksend(param->remsock, (unsigned char *)"PASV\r\n", 6, conf.timeouts[STRING_S]) != 6){
		return INVALID_SOCKET;
	}
	param->statscli64 += 6;
	param->nwrites++;
	while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
	}
	if(i < 7) return INVALID_SOCKET;
	if(buf[0] != '2') return INVALID_SOCKET;
	buf[i-2] = 0;
	if(!(sb = strchr(buf+4, '(')) || !(se= strchr(sb, ')'))) return INVALID_SOCKET;
	if(sscanf(sb+1, "%lu,%lu,%lu,%lu,%hu,%hu", &b1, &b2, &b3, &b4, &b5, &b6)!=6) return INVALID_SOCKET;
	sasize = sizeof(param->sinsl);
	if(so._getsockname(param->remsock, (struct sockaddr *)&param->sinsl, &sasize)){return INVALID_SOCKET;}
	sasize = sizeof(param->sinsr);
	if(so._getpeername(param->remsock, (struct sockaddr *)&param->sinsr, &sasize)){return INVALID_SOCKET;}
	rem = param->remsock;
	param->remsock = INVALID_SOCKET;
	param->req = param->sinsr;
	*SAPORT(&param->req) = *SAPORT(&param->sinsr) = htons((unsigned short)((b5<<8)^b6));
	*SAPORT(&param->sinsl) = 0;
	i = param->operation;
	param->operation = FTP_DATA;
	if((param->res = (*param->srv->authfunc)(param))) {
		if(param->remsock != INVALID_SOCKET) {
			so._closesocket(param->remsock);
			param->remsock = INVALID_SOCKET;
		}
		memset(&param->sinsl, 0, sizeof(param->sinsl));
		if((param->res = (*param->srv->authfunc)(param))) {
			param->remsock = rem;
			return INVALID_SOCKET;
		}
	}
	param->operation = i;
	s = param->remsock;
	param->remsock = rem;
	return s;
}
コード例 #5
0
ファイル: ftp.c プロジェクト: CocoBir/3proxy
int ftptype(struct clientparam *param, unsigned char* f_type){
	char buf[1024];
	int i;

	sprintf(buf, "TYPE %.512s\r\n", f_type);
	if((int)socksend(param->remsock, (unsigned char *)buf, (int)strlen(buf), conf.timeouts[STRING_S]) != (int)strlen(buf)){
		return 741;
	}
	param->statscli64 += (int)strlen(buf);
	param->nwrites++;
	while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
	}
	if(i < 3) return 742;
	if(buf[0] != '2') return 740;
	return 0;
}
コード例 #6
0
ファイル: ftp.c プロジェクト: CocoBir/3proxy
int ftpsyst(struct clientparam *param, unsigned char *buf, unsigned len){
	int i;

	if(socksend(param->remsock, (unsigned char *)"SYST\r\n", 6, conf.timeouts[STRING_S]) != 6){
		return 721;
	}
	param->statscli64 += 6;
	param->nwrites++;
	while((i = sockgetlinebuf(param, SERVER, buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
	}
	if(i < 7) return 722;
	buf[3] = 0;
	if(atoi((char *)buf)/100 != 2) return 723;
	buf[i-2] = 0;
	strcpy((char *)buf, (char *)buf+4);
	return 0;
}
コード例 #7
0
ファイル: knllog.c プロジェクト: 0TK0/muZic_kernel_ivoryss
/* Output a string to one of the various output mechanisms */
static int outputStr(char *str, int verbose)
{
#if CONFIG_NET
   if (knllog.sock)
   {
      int rc = socksend(str, strlen(str));
      if (rc != 0)
      {
         return rc;
      }
      if (verbose)
      {
         printk(str);
      }
   }
   else
#endif
   if (knllog.logfile)
   {
      if (strcmp(knllog.filename, "console") == 0)
      {
         printk(str);
      }
      else
      {
         if (knllog.file)
         {
            mm_segment_t old_fs = get_fs();
            set_fs(KERNEL_DS);
            knllog.file->f_op->write(knllog.file, str, strlen(str), &knllog.file->f_pos);
            set_fs(old_fs);
            if (verbose)
            {
               printk(str);
            }
         }
      }
   }
   return 0;
}
コード例 #8
0
ファイル: ftp.c プロジェクト: CocoBir/3proxy
int ftpcd(struct clientparam *param, unsigned char* path, char *nbuf, int *innbuf){
	char buf[1024];
	int i;
	int inbuf = 0;

	sprintf(buf, "CWD %.512s\r\n", path);
	if((int)socksend(param->remsock, (unsigned char *)buf, (int)strlen(buf), conf.timeouts[STRING_S]) != (int)strlen(buf)){
		return 711;
	}
	param->statscli64 += (int)strlen(buf);
	param->nwrites++;
	while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
		if(nbuf && innbuf && inbuf + i < *innbuf && i > 6) {
			memcpy(nbuf + inbuf, buf, i);
			inbuf += i;
		}
	}
	if(innbuf)*innbuf = inbuf;
	if(i < 3) return 712;
	buf[3] = 0;
	if(buf[0] != '2') return 710;
	return 0;
}
コード例 #9
0
ファイル: ftp.c プロジェクト: CocoBir/3proxy
int ftppwd(struct clientparam *param, unsigned char *buf, unsigned len){
	int i;
	char *b, *e;

	if(socksend(param->remsock, (unsigned char *)"PWD\r\n", 5, conf.timeouts[STRING_S]) != 5){
		return 731;
	}
	param->statscli64 += 5;
	param->nwrites++;
	while((i = sockgetlinebuf(param, SERVER, buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
	}
	if(i < 7) return 732;
	buf[3] = 0;
	if(atoi((char *)buf)/100 != 2) return 733;
	buf[i-2] = 0;
	b = (char *)buf+4;
	if(*b == '\"' && (e = strchr(b+1, '\"'))){
		b++;
		*e = 0;
	}
	strcpy((char *)buf, b);
	return 0;
}
コード例 #10
0
ファイル: iodump.c プロジェクト: kzlin129/tt-gpl
/****************************************************************************
*
*  iodump_thread
*
*   Worker thread to transfer data to the file or socket.
*
***************************************************************************/
static int iodump_thread(void *data)
{
    daemonize("iodump");

    while (1)
    {
        // wait for a batch of tdm, network ingress/egress data before writing */
        if (0 == wait_event_interruptible(IoDumpWakeQ, IoDumpWake))
        {
            int size;
            char *writeSnapshot;   // We don't want to worry about the write pointer changing under us

            IoDumpWake = 0;

            writeSnapshot = IoDump.bufwritep;
            if (writeSnapshot >= IoDump.bufreadp)
            {
                size = writeSnapshot - IoDump.bufreadp;
            }
            else
            {
                size = IoDump.bufsize - (IoDump.bufreadp - writeSnapshot);
            }
            //KNLLOG("enable = %d, size = %d\n", IoDump.enable, size);
            if (IoDump.enable && size)
            {
                if (writeSnapshot >= IoDump.bufreadp)
                {
#if CONFIG_NET
                    if (IoDump.sock)
                    {
                        int rc = socksend(IoDump.bufreadp, size);
                        if ((rc == -EAGAIN) || (rc == 0))
                        {
                            continue;  // Nothing sent, retry next timer tick
                        }
                    }
                    else
#endif
                        if (IoDump.file)
                        {
                            mm_segment_t old_fs = get_fs();
                            set_fs(KERNEL_DS);
                            IoDump.file->f_op->write(IoDump.file, IoDump.bufreadp, size, &IoDump.file->f_pos);
                            set_fs(old_fs);
                            incrReadPtr(size);
                        }
                }
                else
                {
                    int size1 = IoDump.bufendp - IoDump.bufreadp;  // size to end of buffer
                    int size2 = writeSnapshot - IoDump.bufp;        // size from start to write
#if CONFIG_NET
                    if (IoDump.sock)
                    {
                        int rc = socksend(IoDump.bufreadp, size1);
                        if ((rc == -EAGAIN) || (rc == 0))
                        {
                            continue;  // Nothing sent, retry next timer tick
                        }

                        if (size2)
                        {
                            int rc = socksend(IoDump.bufreadp, size2);
                            if ((rc == -EAGAIN) || (rc == 0))
                            {
                                continue;       // Nothing sent, retry next timer tick
                            }
                        }
                    }
                    else
#endif
                        if (IoDump.file)
                        {
                            mm_segment_t old_fs = get_fs();
                            set_fs(KERNEL_DS);
                            IoDump.file->f_op->write(IoDump.file, IoDump.bufreadp, size1, &IoDump.file->f_pos);
                            if (size2)
                            {
                                IoDump.file->f_op->write(IoDump.file, IoDump.bufp, size2, &IoDump.file->f_pos);
                            }
                            set_fs(old_fs);
                            incrReadPtr(size);
                        }
                }
            }
        }
    }
    complete_and_exit(&IoDumpExited, 0);
}
コード例 #11
0
int communicator_loop() {
   client_t *c;

   int r, len, i;

   unsigned int size;

   unsigned long time_current, ms, sql_t = 0, chk_t = 0;

   struct timespec tms_current, tms_sql;

   char buf[1024] = {0};

   while (1) {
      clock_gettime(CLOCK_MONOTONIC_RAW, &tms_current);

      if (timespec_diff_ms(&tms_current, &tms_sql) >= 200) {
         data_refresh();
         if (g_dbc_error)
            return 0;
         tms_sql = tms_current;
      }

      time_current = time(NULL);
      srand(time_current);

      c = g_clients;

      while (c) {

         if (g_dbc_error)
            return 0;

         //_log("%u %u %u", c->ip, c->sock, c->time_connected);
         if (c->active) {
            if (sizeof (c->rbuf) - 1 > c->rn)
               size = sizeof (c->rbuf) - c->rn - 1;
            else
               size = sizeof (c->rbuf) - 1;
            if ((r = recv(c->sock, c->rbuf + c->rn, size, 0)) > 0) {
               c->rn += r;
               c->rbuf[c->rn] = NULL;
               _log("BUF: %s", c->rbuf);

            } else if (errno != EAGAIN) {
               if (opt.debug_log)
                  _log("[Notice] communicator_loop: (errno!=EAGAIN)");

               client_operation(c, 1);
               close(c->sock);
               c->active = 0;
               continue;
            } else if (!c->initialized && time_current - c->time_connected > UNINITIALIZED_CLIENT_TIMEOUT_S) {
               if (opt.debug_log)
                  _log("[Notice] communicator_loop: Uninitialized client timed out. Disconnecting it.");

               client_operation(c, 1);
               close(c->sock);
               c->active = 0;
               continue;
            }


            if (c->initialized && c->rn >= 2 && c->rbuf[c->rn - 1] == '\n') {
               c->rbuf[c->rn - 1] = NULL;
               if (c->rbuf[c->rn - 2] == '\r')
                  c->rbuf[c->rn - 2] = NULL;

               if (c->rn > 2)
                  client_operation(c, 2);

               c->rn = 0;
            }

            if (!c->initialized && c->rn > 4 && c->rbuf[c->rn - 1] == '\n') {
               c->rbuf[c->rn - 1] = NULL;
               if (c->rbuf[c->rn - 2] == '\r')
                  c->rbuf[c->rn - 2] = NULL;

               client_initialize(c);
               c->rn = 0;
            }

            if (c->initialized && time_current > c->time_checked) {
               socksend(c->sock, (unsigned char*) "P", 1, 1);
               c->time_checked = time_current + 30;
            }

            if (*c->sbuf != 0) {
               if (opt.debug_log)
                  _log("[Notice] communicator_loop: Sending sbuf. Data: %s", c->sbuf);

               i = strlen(c->sbuf);
               c->sbuf[i] = '\r';
               c->sbuf[i + 1] = '\n';
               socksend(c->sock, (unsigned char*) c->sbuf, i + 2, 1);
               *c->sbuf = 0;
            }

            if (c->rn > 120)
               c->rn = 0;
         }

         c = c->next;
      }

      usleep(1000 * 50);
   }

   return 1;
}
コード例 #12
0
ファイル: ftppr.c プロジェクト: sweetcard/3proxy
void * ftpprchild(struct clientparam* param) {
 int i=0, res;
 unsigned char *buf;
 unsigned char *se;
 int status = 0;
 int inbuf;
 int pasv = 0;
 SOCKET sc = INVALID_SOCKET, ss = INVALID_SOCKET, clidatasock = INVALID_SOCKET;
 SASIZETYPE sasize;
 char * req = NULL;
 struct linger lg;
 struct pollfd fds;

 if(!(buf = myalloc(BUFSIZE))) RETURN(876);
 param->ctrlsock = param->clisock;
 param->operation = CONNECT;
 lg.l_onoff = 1;
 lg.l_linger = conf.timeouts[STRING_L];;
 if(socksend(param->ctrlsock, (unsigned char *)"220 Ready\r\n", 11, conf.timeouts[STRING_S])!=11) {RETURN (801);}
 for(;;){
	i = sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 10, '\n', conf.timeouts[CONNECTION_S]);
	if(!i) {
		RETURN(0);
	}
	if(i<4) {RETURN(802);}
	buf[i] = 0;
	if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0;
	if (req) myfree (req);
	req = NULL;

	if (!strncasecmp((char *)buf, "OPEN ", 5)){
		if(parsehostname((char *)buf+5, param, 21)){RETURN(803);}
		if(param->remsock != INVALID_SOCKET) {
			so._shutdown(param->remsock, SHUT_RDWR);
			so._closesocket(param->remsock);
			param->remsock = INVALID_SOCKET;
		}
		if((res = (*param->srv->authfunc)(param))) {RETURN(res);}
		param->ctrlsocksrv = param->remsock;
		if(socksend(param->ctrlsock, (unsigned char *)"220 Ready\r\n", 11, conf.timeouts[STRING_S])!=11) {RETURN (801);}
		status = 1;
	}
	else if (!strncasecmp((char *)buf, "USER ", 5)){
		if(parseconnusername((char *)buf +5, param, 0, 21)){RETURN(804);}
		if(!status){
			if((res = (*param->srv->authfunc)(param))) {RETURN(res);}
			param->ctrlsocksrv = param->remsock;
		}
		if(socksend(param->ctrlsock, (unsigned char *)"331 ok\r\n", 8, conf.timeouts[STRING_S])!=8) {RETURN (807);}
		status = 2;

	}
	else if (!strncasecmp((char *)buf, "PASS ", 5)){
		param->extpassword = (unsigned char *)mystrdup((char *)buf+5);
		inbuf = BUFSIZE;
		res = ftplogin(param, (char *)buf, &inbuf);
		param->res = res;
		if(inbuf && inbuf != BUFSIZE && socksend(param->ctrlsock, buf, inbuf, conf.timeouts[STRING_S])!=inbuf) {RETURN (807);}
		if(!res) status = 3;
		sprintf((char *)buf, "%.64s@%.128s%c%hu", param->extusername, param->hostname, (ntohs(param->sins.sin_port)==21)?0:':', ntohs(param->sins.sin_port));
		req = mystrdup((char *)buf);
#ifndef WITHMAIN
		{
			int action, reqbufsize, reqsize;
			reqbufsize = BUFSIZE;
			reqsize = (int)strlen(buf) + 1;
			
			action = handlereqfilters(param, &buf, &reqbufsize, 0, &reqsize);
			if(action == HANDLED){
				RETURN(0);
			}
			if(action != PASS) RETURN(877);
		}
#endif
	}
	else if (status >= 3 && (
			(!strncasecmp((char *)buf, "PASV", 4) && (pasv = 1)) ||
			(!strncasecmp((char *)buf, "PORT ", 5) && !(pasv = 0))
		)){
#ifndef WITHMAIN
		{
			int action, reqbufsize, reqsize;
			reqbufsize = BUFSIZE;
			reqsize = (int)strlen(buf) + 1;
			
			action = handlehdrfilterscli(param, &buf, &reqbufsize, 0, &reqsize);
			if(action == HANDLED){
				RETURN(0);
			}
			if(action != PASS) RETURN(878);
		}
#endif
		if(sc != INVALID_SOCKET) {
			so._shutdown(sc, SHUT_RDWR);
			so._closesocket(sc);
			sc = INVALID_SOCKET;
		}
		if(ss != INVALID_SOCKET) {
			so._shutdown(ss, SHUT_RDWR);
			so._closesocket(ss);
			ss = INVALID_SOCKET;
		}
		if(clidatasock != INVALID_SOCKET) {
			so._shutdown(clidatasock, SHUT_RDWR);
			so._closesocket(clidatasock);
			clidatasock = INVALID_SOCKET;
		}
		if ((clidatasock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
		sasize = sizeof(struct sockaddr_in);
		if(so._getsockname(param->ctrlsock, (struct sockaddr *)&param->sinc, &sasize)){RETURN(824);}
		param->sinc.sin_port = 0;
		if(so._bind(clidatasock, (struct sockaddr *)&param->sinc, sasize)){RETURN(822);}
		if (pasv) {
			if(so._listen(clidatasock, 1)) {RETURN(823);}
			if(so._getsockname(clidatasock, (struct sockaddr *)&param->sinc, &sasize)){RETURN(824);}
			sprintf((char *)buf, "227 OK (%u,%u,%u,%u,%u,%u)\r\n",
				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[0]),
				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[1]),
				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[2]),
				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[3]),
				 (unsigned)(((unsigned char *)(&param->sinc.sin_port))[0]),
				 (unsigned)(((unsigned char *)(&param->sinc.sin_port))[1])
				);
		}
		else {
			unsigned long b1, b2, b3, b4;
			unsigned short b5, b6;

			if(sscanf((char *)buf+5, "%lu,%lu,%lu,%lu,%hu,%hu", &b1, &b2, &b3, &b4, &b5, &b6)!=6) {RETURN(828);}
			param->sinc.sin_family = AF_INET;
			param->sinc.sin_port = htons((unsigned short)((b5<<8)^b6));
			param->sinc.sin_addr.s_addr = htonl((b1<<24)^(b2<<16)^(b3<<8)^b4);
			if(so._connect(clidatasock, (struct sockaddr *)&param->sinc, sasize)) {
				so._closesocket(clidatasock);
				clidatasock = INVALID_SOCKET;
				RETURN(826);
			}
			sprintf(buf, "200 OK\r\n");
		}
#ifndef WITHMAIN
		{
			int action, reqbufsize, reqsize;
			reqbufsize = BUFSIZE;
			reqsize = (int)strlen(buf) + 1;
			
			action = handlehdrfilterssrv(param, &buf, &reqbufsize, 0, &reqsize);
			if(action == HANDLED){
				RETURN(0);
			}
			if(action != PASS) RETURN(879);
		}
#endif
		if(socksend(param->ctrlsock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S])!=(int)strlen((char *)buf)) {RETURN (825);}
		status = 4;
	}
	else if (status == 4 && (
		!(strncasecmp((char *)buf, "RETR ", 5) && (param->operation = FTP_GET)) ||
		!(strncasecmp((char *)buf, "LIST", 4) && (param->operation = FTP_LIST))||
		!(strncasecmp((char *)buf, "NLST ", 5) && (param->operation = FTP_LIST)) ||
		!(strncasecmp((char *)buf, "MLSD", 4) && (param->operation = FTP_LIST)) ||
		!(strncasecmp((char *)buf, "APPE ", 5) && (param->operation = FTP_PUT)) ||
		!(strncasecmp((char *)buf, "STOR ", 5) && (param->operation = FTP_PUT))
	)){
		int arg = (buf[4] && buf[5])? 1:0;
		int ressent = 0;


#ifndef WITHMAIN
		{
			int action, reqbufsize, reqsize;
			reqbufsize = BUFSIZE;
			reqsize = (int)strlen(buf) + 1;
			
			action = handlehdrfilterscli(param, &buf, &reqbufsize, 0, &reqsize);
			if(action == HANDLED){
				RETURN(0);
			}
			if(action != PASS) RETURN(880);
		}
#endif
		if(clidatasock == INVALID_SOCKET) { RETURN (829);}
		if(pasv){

			memset(&fds, 0, sizeof(fds));
			fds.fd = clidatasock;
			fds.events = POLLIN;

			res = so._poll (&fds, 1, conf.timeouts[STRING_L]*1000);
			if(res != 1) {
				RETURN(857);
			}
			sasize = sizeof(struct sockaddr_in);
			ss = so._accept(clidatasock, (struct sockaddr *)&param->sinc, &sasize);
			if (ss == INVALID_SOCKET) { RETURN (858);}
			so._shutdown(clidatasock, SHUT_RDWR);
			so._closesocket(clidatasock);
			clidatasock = ss;
			ss = INVALID_SOCKET;
		}
		if(clidatasock == INVALID_SOCKET){RETURN(828);}
		req = mystrdup((char *)buf);
		buf[4] = 0;
		status = 3;
		ss = ftpcommand(param, buf, arg? buf+5 : NULL);
		if (ss == INVALID_SOCKET) {
			so._shutdown(clidatasock, SHUT_RDWR);
			so._closesocket(clidatasock);
			clidatasock = INVALID_SOCKET;
			
			if(socksend(param->ctrlsock, (unsigned char *)"550 err\r\n", 9, conf.timeouts[STRING_S])!=9) {RETURN (831);}
			continue;
		}

		if(socksend(param->ctrlsock, (unsigned char *)"125 data\r\n", 10, conf.timeouts[STRING_S]) != 10) {
			param->remsock = INVALID_SOCKET;
			RETURN (832);
		}
		if(param->srvoffset < param->srvinbuf)while((i = sockgetlinebuf(param, SERVER, buf, BUFSIZE, '\n', 0)) > 3){
			if(socksend(param->ctrlsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN(833);}
			if(isnumber(*buf) && buf[3] != '-') {
				ressent = 1;
				break;
			}
		}
		sc = param->remsock;
		param->remsock = ss;
		so._setsockopt(param->remsock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg));
		so._setsockopt(clidatasock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg));
		param->clisock = clidatasock;
		res = sockmap(param, conf.timeouts[CONNECTION_S]);
		if(param->remsock != INVALID_SOCKET) {
			so._shutdown (param->remsock, SHUT_RDWR);
			so._closesocket(param->remsock);
		}
		if(param->clisock != INVALID_SOCKET) {
			so._shutdown (param->clisock, SHUT_RDWR);
			so._closesocket(param->clisock);
		}
		param->clisock = param->ctrlsock;
		param->remsock = sc;
		sc = INVALID_SOCKET;
		ss = INVALID_SOCKET;
		clidatasock = INVALID_SOCKET;
		if(!ressent){
			while((i = sockgetlinebuf(param, SERVER, buf, BUFSIZE, '\n', conf.timeouts[STRING_L])) > 3){
				if(socksend(param->ctrlsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN(833);}
				if(isnumber(*buf) && buf[3] != '-') break;
			}
			if(i < 3) {RETURN(834);}
		}
	}
	else {
		if(status < 3) {
			if(socksend(param->remsock, (unsigned char *)"530 login\r\n", 11, conf.timeouts[STRING_S])!=1) {RETURN (810);}
			continue;
		}
		if(!strncasecmp((char *)buf, "QUIT", 4)) status = 5;
		if(!strncasecmp((char *)buf, "CWD ", 4)) req = mystrdup((char *)buf);
		i = (int)strlen((char *)buf);
		buf[i++] = '\r';
		buf[i++] = '\n';
		if(socksend(param->remsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN (811);}
		param->statscli += i;
		param->nwrites++;
		while((i = sockgetlinebuf(param, SERVER, buf, BUFSIZE, '\n', conf.timeouts[STRING_L])) > 0){
			if(socksend(param->ctrlsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN (812);}
			if(i > 4 && isnumber(*buf) && buf[3] != '-') break;
		}
		if(status == 5) {RETURN (0);}
		if(i < 3) {RETURN (813);}
	}
	sasize = sizeof(struct sockaddr_in);
	if(so._getpeername(param->ctrlsock, (struct sockaddr *)&param->sinc, &sasize)){RETURN(819);}
	if(req && (param->statscli || param->statssrv)){
		(*param->srv->logfunc)(param, (unsigned char *)req);
	}
 }

CLEANRET:

 if(sc != INVALID_SOCKET) {
	so._shutdown(sc, SHUT_RDWR);
	so._closesocket(sc);
 }
 if(ss != INVALID_SOCKET) {
	so._shutdown(ss, SHUT_RDWR);
	so._closesocket(ss);
 }
 if(clidatasock != INVALID_SOCKET) {
	so._shutdown(clidatasock, SHUT_RDWR);
	so._closesocket(clidatasock);
 }
 sasize = sizeof(struct sockaddr_in);
 so._getpeername(param->ctrlsock, (struct sockaddr *)&param->sinc, &sasize);
 if(param->res != 0 || param->statscli || param->statssrv ){
	(*param->srv->logfunc)(param, (unsigned char *)((req && (param->res > 802))? req:NULL));
 }
 if(req) myfree(req);
 if(buf) myfree(buf);
 freeparam(param);
 return (NULL);
}
コード例 #13
0
ファイル: socket.c プロジェクト: graue/bsfirc
/* PROTO */
ssize_t
sendPkt(void *handle, pkt_t * packet)
{
	return socksend(handle, packet->data, packet->len);
}
コード例 #14
0
ファイル: proxy.c プロジェクト: digsrc/3proxy
void * proxychild(struct clientparam* param) {
 int res=0, i=0;
 unsigned char* buf = NULL, *newbuf;
 int inbuf;
 int bufsize;
 unsigned reqlen = 0;
 unsigned char	*sb=NULL, *sg=NULL, *se=NULL, *sp=NULL,
		*req=NULL, *su=NULL, *ss = NULL;
 unsigned char *ftpbase=NULL;
 unsigned char username[1024];
 int keepalive = 0;
 uint64_t contentlength64 = 0;
 int hascontent =0;
 int isconnect = 0;
 int redirect = 0;
 int prefix = 0, ckeepalive=0;
 int ftp = 0;
 int anonymous;
 int sleeptime = 0;
 int reqsize, reqbufsize;
 int authenticate;
 struct pollfd fds[2];
 SOCKET ftps;
 char ftpbuf[FTPBUFSIZE];
 int inftpbuf = 0;
#ifndef WITHMAIN
 FILTER_ACTION action;
#endif



 
 if(!(buf = myalloc(BUFSIZE))) {RETURN(21);}
 bufsize = BUFSIZE;
 anonymous = param->srv->singlepacket;
for(;;){
 memset(buf, 0, bufsize);
 inbuf = 0;


 if(keepalive && (param->cliinbuf == param->clioffset) && (param->remsock != INVALID_SOCKET)){
	memset(fds, 0, sizeof(fds));
	fds[0].fd = param->clisock;
	fds[0].events = POLLIN;
	fds[1].fd = param->remsock;
	fds[1].events = POLLIN;
	res = so._poll(fds, 2, conf.timeouts[STRING_S]*1000);
	if(res<=0) {
		RETURN(555);
	}
	if((fds[1].revents & (POLLIN|POLLHUP|POLLERR|POLLNVAL))) {
		if(param->transparent || (!param->redirected && param->redirtype == R_HTTP)) RETURN(555);
		ckeepalive = 0;
		so._shutdown(param->remsock, SHUT_RDWR);
		so._closesocket(param->remsock);
		param->remsock = INVALID_SOCKET;
		param->redirected = 0;
		param->redirtype = 0;
	}
 }

 i = sockgetlinebuf(param, CLIENT, buf, LINESIZE - 1, '\n', conf.timeouts[STRING_L]);
 if(i<=0) {
	RETURN((keepalive)?555:(i)?507:508);
 }
 if (i==2 && buf[0]=='\r' && buf[1]=='\n') continue;
 buf[i] = 0;
 
 if(req) {
	if(!param->transparent && !param->srv->transparent && param->redirtype != R_HTTP && (i<=prefix || strncasecmp((char *)buf, (char *)req, prefix))){
		ckeepalive = 0;
		if(param->remsock != INVALID_SOCKET){
			so._shutdown(param->remsock, SHUT_RDWR);
			so._closesocket(param->remsock);
		}
		param->remsock = INVALID_SOCKET;
		param->redirected = 0;
		param->redirtype = 0;
	}
	myfree(req);
 }
 req = (unsigned char *)mystrdup((char *)buf);
 if(!req){RETURN(510);}
 if(i<10) {
	RETURN(511);
 }
 if(buf[i-3] == '1') keepalive = 2; 
 if((isconnect = !strncasecmp((char *)buf, "CONNECT", 7))) keepalive = 2;

 if ((sb=(unsigned char *)(unsigned char *)strchr((char *)buf, ' ')) == NULL) {RETURN(512);}
 ss = ++sb;
 if(!isconnect) {
	if (!strncasecmp((char *)sb, "http://", 7)) {
		sb += 7;
	}
	else if (!strncasecmp((char *)sb, "ftp://", 6)) {
		ftp = 1;
		sb += 6;
	}
	else if(*sb == '/') {
		param->transparent = 1;
	}
	else {
		RETURN (513);
	}
 }
 else {
	 if ((se=(unsigned char *)(unsigned char *)strchr((char *)sb, ' ')) == NULL || sb==se) {RETURN (514);}
	 *se = 0;
 }
 if(!param->transparent || isconnect) {
	if(!isconnect) {
		if ((se=(unsigned char *)(unsigned char *)strchr((char *)sb, '/')) == NULL 
			|| sb==se
			|| !(sg=(unsigned char *)strchr((char *)sb, ' '))) {RETURN (515);}
		if(se > sg) se=sg;
 		*se = 0;
	}
	prefix = (int)(se - buf);
	su = (unsigned char*)strrchr((char *)sb, '@');
	if(su) {
		su = mystrdup(sb);
		decodeurl(su, 0);
		parseconnusername((char *)su, (struct clientparam *)param, 1, (unsigned short)((ftp)?21:80));
		myfree(su);
	}
	else parsehostname((char *)sb, (struct clientparam *)param, (unsigned short)((ftp)? 21:80));
	if(!isconnect){
		if(se==sg)*se-- = ' ';
		*se = '/';
		memmove(ss, se, i - (se - sb) + 1);
	}
 }
 reqlen = i = (int)strlen((char *)buf);
 if(!strncasecmp((char *)buf, "CONNECT", 7))param->operation = HTTP_CONNECT;
 else if(!strncasecmp((char *)buf, "GET", 3))param->operation = (ftp)?FTP_GET:HTTP_GET;
 else if(!strncasecmp((char *)buf, "PUT", 3))param->operation = (ftp)?FTP_PUT:HTTP_PUT;
 else if(!strncasecmp((char *)buf, "POST", 4)||!strncasecmp((char *)buf, "BITS_POST", 9))param->operation = HTTP_POST;
 else if(!strncasecmp((char *)buf, "HEAD", 4))param->operation = HTTP_HEAD;
 else param->operation = HTTP_OTHER;
 do {
	buf[inbuf+i]=0;
/*printf("Got: %s\n", buf+inbuf);*/
#ifndef WITHMAIN
	if(i > 25 && !param->srv->transparent && (!strncasecmp((char *)(buf+inbuf), "proxy-authorization", 19))){
		sb = (unsigned char *)strchr((char *)(buf+inbuf), ':');
		if(!sb)continue;
		++sb;
		while(isspace(*sb))sb++;
		if(!*sb) continue;
		if(!strncasecmp((char *)sb, "basic", 5)){
			sb+=5;
			while(isspace(*sb))sb++;
			i = de64(sb, username, 255);
			if(i<=0)continue;
			username[i] = 0;
			sb = (unsigned char *)strchr((char *)username, ':');
			if(sb){
				*sb = 0;
				if(param->password)myfree(param->password);
				param->password = (unsigned char *)mystrdup((char *)sb+1);
				param->pwtype = 0;
			}
			if(param->username)myfree(param->username);
			param->username = (unsigned char *)mystrdup((char *)username);
			continue;
		}
#ifndef NOCRYPT
		if(param->srv->usentlm && !strncasecmp((char *)sb, "ntlm", 4)){
			sb+=4;
			while(isspace(*sb))sb++;
			i = de64(sb, username, 1023);
			if(i<=16)continue;
			username[i] = 0;
			if(strncasecmp((char *)username, "NTLMSSP", 8)) continue;
			if(username[8] == 1) {
				while( (i = sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, '\n', conf.timeouts[STRING_S])) > 2){
					if(i> 15 && (!strncasecmp((char *)(buf), "content-length", 14))){
						buf[i]=0;
						sscanf((char *)buf + 15, "%"PRINTF_INT64_MODIFIER"u", &contentlength64);
					}
				}
				while( contentlength64 > 0 && (i = sockgetlinebuf(param, CLIENT, buf, (BUFSIZE < contentlength64)? BUFSIZE - 1:(int)contentlength64, '\n', conf.timeouts[STRING_S])) > 0){
					if ((uint64_t)i > contentlength64) break;
					contentlength64-=i;
				}
				contentlength64 = 0;
				if(param->password)myfree(param->password);
				param->password = myalloc(32);
				param->pwtype = 2;
				i = (int)strlen(proxy_stringtable[13]);
				memcpy(buf, proxy_stringtable[13], i);
				genchallenge(param, (char *)param->password, (char *)buf + i);
				memcpy(buf + strlen((char *)buf), "\r\n\r\n", 5);
				socksend(param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
				ckeepalive = keepalive = 1;
				goto REQUESTEND;
			}
			if(username[8] == 3 && param->pwtype == 2 && i>=80) {
				unsigned offset, len;

				len = username[20] + (((unsigned)username[21]) << 8);
				offset = username[24] + (((unsigned)username[25]) << 8);
				if(len != 24 || len + offset > (unsigned)i) continue;
				memcpy(param->password + 8, username + offset, 24);
				len = username[36] + (((unsigned)username[37]) << 8);
				offset = username[40] + (((unsigned)username[41]) << 8);
				if(len> 255 || len + offset > (unsigned)i) continue;
				if(param->username) myfree(param->username);
				unicode2text((char *)username+offset, (char *)username+offset, (len>>1));
				param->username = (unsigned char *)mystrdup((char *)username+offset);
			}
			continue;
		}
#endif
	}
コード例 #15
0
ファイル: ftp.c プロジェクト: CocoBir/3proxy
int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) {
	char tbuf[256];
	int i;
	char *buf;
	int len;
	int res;

	buf = nbuf?nbuf:tbuf;
	len = nbuf?*innbuf:sizeof(tbuf);

	if(innbuf)*innbuf = 0;
	if(len < 140) return 707;
	while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
	}
	if(i < 3) return 706;
	buf[i] = 0;
	if(atoi(buf)/100 != 2) {
		*innbuf = i;
		return 702;
	}
	sprintf(buf, "USER %.128s\r\n", param->extusername?param->extusername:(unsigned char *)"anonymous");
	if((int)socksend(param->remsock, (unsigned char *)buf, (int)strlen(buf), conf.timeouts[STRING_S]) != (int)strlen(buf)){
		return 703;
	}
	param->statscli64 += (int)strlen(buf);
	param->nwrites++;
	while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
	}
	if(i < 3) return 704;
	buf[i] = 0;
	res = atoi(buf)/100;
	if(res == 3){
		sprintf(buf, "PASS %.128s\r\n", 
			param->extusername?
				(param->extpassword?
					param->extpassword:(unsigned char *)"")
				:(unsigned char *)"3proxy@");
		res = (int)strlen(buf);
		if((int)socksend(param->remsock, (unsigned char *)buf, res, conf.timeouts[STRING_S]) != (int)strlen(buf)){
			return 705;
		}
	param->statscli64 += res;
		param->nwrites++;
		while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0){
			buf[i] = 0;
			res = (i>3 && buf[3] != '-')? atoi(buf)/100 : 0;
			if(res || (nbuf && (len-i) > 256 && i > 3)) {
				buf += i;
				len -= i;
				if(innbuf)*innbuf += i;
			}
			if(res) break;
		}
		if(i < 3) {
			return 701;
		}
	}
	if(res != 2) {
		return 700;
	}
	return 0;
}
コード例 #16
0
ファイル: auth.c プロジェクト: Inzaghi2012/3proxy
int clientnegotiate(struct chain * redir, struct clientparam * param, struct sockaddr * addr){
	unsigned char *buf;
	unsigned char *username;
	int res;
	int len=0;
	unsigned char * user, *pass;


	user = redir->extuser;
	pass = redir->extpass;
	if (param->srvinbuf < 4096){
		if(param->srvbuf)myfree(param->srvbuf);
		param->srvbuf = myalloc(4096);
		param->srvbufsize = 4096;
	}
	buf = param->srvbuf;
	username = buf + 2048;
	if(user) {
		if (*user == '*') {
			if(!param->username) return 4;
			user = param->username;
			pass = param->password;
		}
	}
	switch(redir->type){
		case R_TCP:
		case R_HTTP:
			return 0;
		case R_CONNECT:
		case R_CONNECTP:
		{
			len = sprintf((char *)buf, "CONNECT ");
			if(redir->type == R_CONNECTP && param->hostname) {
				char * needreplace;
				needreplace = strchr((char *)param->hostname, ':');
				if(needreplace) buf[len++] = '[';
				len += sprintf((char *)buf + len, "%.256s", (char *)param->hostname);
				if(needreplace) buf[len++] = ']';
			}
			else {
				if(*SAFAMILY(addr) == AF_INET6) buf[len++] = '[';
				len += myinet_ntop(*SAFAMILY(addr), SAADDR(addr), (char *)buf+len, 256);
				if(*SAFAMILY(addr) == AF_INET6) buf[len++] = ']';
			}
			len += sprintf((char *)buf + len,
				":%hu HTTP/1.0\r\nProxy-Connection: keep-alive\r\n", ntohs(*SAPORT(addr)));
			if(user){
				len += sprintf((char *)buf + len, "Proxy-authorization: basic ");
				sprintf((char *)username, "%.128s:%.64s", user, pass?pass:(unsigned char *)"");
				en64(username, buf+len, (int)strlen((char *)username));
				len = (int)strlen((char *)buf);
				len += sprintf((char *)buf + len, "\r\n");
			}
			len += sprintf((char *)buf + len, "\r\n");
			if(socksend(param->remsock, buf, len, conf.timeouts[CHAIN_TO]) != (int)strlen((char *)buf))
				return 31;
			param->statssrv64+=len;
			param->nwrites++;
			if((res = sockgetlinebuf(param, SERVER,buf,13,'\n',conf.timeouts[CHAIN_TO])) < 13)
				return 32;
			if(buf[9] != '2') return 33;
			while((res = sockgetlinebuf(param, SERVER,buf,1023,'\n', conf.timeouts[CHAIN_TO])) > 2);
			if(res <= 0) return 34;
			return 0;
		}
		case R_SOCKS4:
		case R_SOCKS4P:
		case R_SOCKS4B:
		{

			if(*SAFAMILY(addr) != AF_INET) return 44;
			buf[0] = 4;
			buf[1] = 1;
			memcpy(buf+2, SAPORT(addr), 2);
			if(redir->type == R_SOCKS4P && param->hostname) {
				buf[4] = buf[5] = buf[6] = 0;
				buf[7] = 3;
			}
			else memcpy(buf+4, SAADDR(addr), 4);
			if(!user)user = (unsigned char *)"anonymous";
			len = (int)strlen((char *)user) + 1;
			memcpy(buf+8, user, len);
			len += 8;
			if(redir->type == R_SOCKS4P && param->hostname) {
				int hostnamelen;

				hostnamelen = (int)strlen((char *)param->hostname) + 1;
				if(hostnamelen > 255) hostnamelen = 255;
				memcpy(buf+len, param->hostname, hostnamelen);
				len += hostnamelen;
			}
			if(socksend(param->remsock, buf, len, conf.timeouts[CHAIN_TO]) < len){
				return 41;
			}
			param->statssrv64+=len;
			param->nwrites++;
			if((len = sockgetlinebuf(param, SERVER, buf, (redir->type == R_SOCKS4B)? 3:8, EOF, conf.timeouts[CHAIN_TO])) != ((redir->type == R_SOCKS4B)? 3:8)){
				return 42;
			}
			if(buf[1] != 90) {
				return 43;
			}

		}
		return 0;

		case R_SOCKS5:
		case R_SOCKS5P:
		case R_SOCKS5B:
		{
		 int inbuf = 0;
			buf[0] = 5;
			buf[1] = 1;
			buf[2] = user? 2 : 0;
			if(socksend(param->remsock, buf, 3, conf.timeouts[CHAIN_TO]) != 3){
				return 51;
			}
			param->statssrv64+=len;
			param->nwrites++;
			if(sockgetlinebuf(param, SERVER, buf, 2, EOF, conf.timeouts[CHAIN_TO]) != 2){
				return 52;
			}
			if(buf[0] != 5) {
				return 53;
			}
			if(buf[1] != 0 && !(buf[1] == 2 && user)){
				return 54;
			}
			if(buf[1] == 2){
				buf[inbuf++] = 1;
				buf[inbuf] = (unsigned char)strlen((char *)user);
				memcpy(buf+inbuf+1, user, buf[inbuf]);
				inbuf += buf[inbuf] + 1;
				buf[inbuf] = pass?(unsigned char)strlen((char *)pass):0;
				if(pass)memcpy(buf+inbuf+1, pass, buf[inbuf]);
				inbuf += buf[inbuf] + 1;
				if(socksend(param->remsock, buf, inbuf, conf.timeouts[CHAIN_TO]) != inbuf){
					return 51;
				}
				param->statssrv64+=inbuf;
				param->nwrites++;
				if(sockgetlinebuf(param, SERVER, buf, 2, EOF, 60) != 2){
					return 55;
				}
				if(buf[0] != 1 || buf[1] != 0) {
					return 56;
				}
			}
			buf[0] = 5;
			buf[1] = 1;
			buf[2] = 0;
			if(redir->type == R_SOCKS5P && param->hostname) {
				buf[3] = 3;
				len = (int)strlen((char *)param->hostname);
				if(len > 255) len = 255;
				buf[4] = len;
				memcpy(buf + 5, param->hostname, len);
				len += 5;
			}
			else {
				len = 3;
				buf[len++] = (*SAFAMILY(addr) == AF_INET)? 1 : 4;
				memcpy(buf+len, SAADDR(addr), SAADDRLEN(addr));
				len += SAADDRLEN(addr);
			}
			memcpy(buf+len, SAPORT(addr), 2);
			len += 2;
			if(socksend(param->remsock, buf, len, conf.timeouts[CHAIN_TO]) != len){
				return 51;
			}
			param->statssrv64+=len;
			param->nwrites++;
			if(sockgetlinebuf(param, SERVER, buf, 4, EOF, conf.timeouts[CHAIN_TO]) != 4){
				return 57;
			}
			if(buf[0] != 5) {
				return 53;
			}
			if(buf[1] != 0) {
				return 60 + (buf[1] % 10);
			}
			if(buf[3] != 1) {
				return 58;
			}
			if (redir->type != R_SOCKS5B && sockgetlinebuf(param, SERVER, buf, 6, EOF, conf.timeouts[CHAIN_TO]) != 6){
				return 59;
			}
			return 0;
		}

		default:

			return 30;
	}
}
コード例 #17
0
ファイル: socks.c プロジェクト: BuddhaLabs/3proxy-OSX
void * sockschild(struct clientparam* param) {
 int res;
 unsigned i=0;
 SOCKET s;
 unsigned size;
 SASIZETYPE sasize;
 unsigned char * buf=NULL;
 unsigned char c;
 unsigned char command=0;
 struct pollfd fds[3];
 int ver=0;
 int havepass = 0;
 struct sockaddr_in sin;
 int len;


 param->req.sin_addr.s_addr = 0;
 param->service = S_SOCKS;

 if(!(buf = myalloc(BUFSIZE))) {RETURN(21);}
 memset(buf, 0, BUFSIZE);
 if ((ver = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5 && ver != 4) {
	RETURN(401);
 } /* version */
 param->service = ver;
 if(ver == 5){
	 if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} /* nmethods */
	 for (; i; i--) {
		if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(442);}
		if (res == 2 && !param->srv->nouser) {
			havepass = res;
		}
	 }
	 buf[0] = 5;
	 buf[1] = havepass;
	 if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);}
	 if (havepass) {
		if (((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0))) != 1) {
			RETURN(412);
		}
		if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(443);}
		if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(444);};
		buf[i] = 0;
		if(!param->username)param->username = (unsigned char *)mystrdup((char *)buf);
		if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(445);}
		if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(446);};
		buf[i] = 0;
		if(!param->password)param->password = (unsigned char *)mystrdup((char *)buf);
		buf[0] = 1;
		buf[1] = 0;
		if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);}
	 }
	 if ((c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5) {
		RETURN(421);
         } /* version */
 }
 if( (command = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) < 1 || command > 3){command = 0; RETURN(407);} /* command */
 if(ver == 5){
	 if (sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0) == EOF) {RETURN(447);} /* reserved */
	 c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0); /* atype */
 }
 else {
	if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(448);}
	buf[0] = (unsigned char) res;
	if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(449);}
	buf[1] = (unsigned char) res;
	param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf;
	c = 1;
 }
 
 switch(c) {
	case 1:
		for (i = 0; i<4; i++){
			if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(450);}
			buf[i] = (unsigned char)res;
		}
		param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = *(unsigned long *)buf;
		if(command==1 && !param->req.sin_addr.s_addr) {
			RETURN(422);
		}
		myinet_ntoa(param->sins.sin_addr, (char *)buf);
		break;
	case 3:
		if ((size = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);} /* nmethods */
		for (i=0; i<size; i++){ /* size < 256 */
			if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(452);}
			buf[i] = (unsigned char)res;
		}
		buf[i] = 0;
		param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = getip(buf);
		if(command==1 && !param->req.sin_addr.s_addr) {
			RETURN(100);
		}
		break;
	default:
		RETURN(998);
 }
 if(param->hostname)myfree(param->hostname);
 param->hostname = (unsigned char *)mystrdup((char *)buf);
 if (ver == 5) {
	 if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(453);}
	 buf[0] = (unsigned char) res;
	 if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(454);}
	 buf[1] = (unsigned char) res;
	 param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf;
 }
 else {
	sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]);
	buf[127] = 0;
	if(!param->srv->nouser && *buf && !param->username)param->username = (unsigned char *)mystrdup((char *)buf);
	if(param->sins.sin_addr.s_addr && ntohl(param->sins.sin_addr.s_addr)<256){
		param->service = S_SOCKS45;
		sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]);
		buf[127] = 0;
		if(param->hostname)myfree(param->hostname);
		param->hostname = (unsigned char *)mystrdup((char *)buf);
		param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = getip(buf);
	}
 }
 if(command == 1 && !param->req.sin_port) {RETURN(424);}
 param->sins.sin_family = AF_INET;
 switch(command) { 
	case 1:
	 param->operation = CONNECT;
	 break;
 	case 2:
	 param->sins.sin_addr.s_addr = param->extip;
	 param->sins.sin_port = param->extport?param->extport:param->req.sin_port;
	 if ((param->remsock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);}
	 param->operation = BIND;
	 break;
	case 3:
	 param->sins.sin_port = param->extport?param->extport:param->req.sin_port;
	 param->sins.sin_addr.s_addr = param->extip;
	 if ((param->remsock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
	 param->operation = UDPASSOC;
	 break;
	default:
	 RETURN(997);
 }

 if((res = (*param->srv->authfunc)(param))) {RETURN(res);}

 if(command > 1) {
	if(bind(param->remsock,(struct sockaddr *)&param->sins,sizeof(param->sins))) {
		param->sins.sin_port = 0;
		if(bind(param->remsock,(struct sockaddr *)&param->sins,sizeof(param->sins)))RETURN (12);
#if SOCKSTRACE > 0
fprintf(stderr, "%s:%hu binded to communicate with server\n",
			inet_ntoa(param->sins.sin_addr),
			ntohs(param->sins.sin_port)
	);
fflush(stderr);
#endif
	}
	sasize = sizeof(struct sockaddr_in);
	getsockname(param->remsock, (struct sockaddr *)&param->sins,  &sasize);
	if(command == 3) {
		param->ctrlsock = param->clisock;
		param->clisock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
		if(param->clisock == INVALID_SOCKET) {RETURN(11);}
		sin.sin_family = AF_INET;
		sin.sin_addr.s_addr = param->srv->intip;
		sin.sin_port = htons(0);
		if(bind(param->clisock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))) {RETURN (12);}
#if SOCKSTRACE > 0
fprintf(stderr, "%s:%hu binded to communicate with client\n",
			inet_ntoa(sin.sin_addr),
			ntohs(sin.sin_port)
	);
fflush(stderr);
#endif
	}
 }
 param->res = 0;

CLEANRET:

 if(param->clisock != INVALID_SOCKET){
	sasize = sizeof(struct sockaddr_in);
	if(command != 3) getsockname(param->remsock, (struct sockaddr *)&sin,  &sasize);
	else getsockname(param->clisock, (struct sockaddr *)&sin,  &sasize);
#if SOCKSTRACE > 0
fprintf(stderr, "Sending confirmation to client with code %d for %s with %s:%hu\n",
			param->res,
			commands[command],
			inet_ntoa(sin.sin_addr),
			ntohs(sin.sin_port)
	);
fflush(stderr);
#endif
	if(ver == 5){
		buf[0] = 5;
		buf[1] = param->res%10;
		buf[2] = 0;
		buf[3] = 1;
		memcpy(buf+4, &sin.sin_addr.s_addr, 4);
		memcpy(buf+8, &sin.sin_port, 2);
		socksend((command == 3)?param->ctrlsock:param->clisock, buf, 10, conf.timeouts[STRING_S]);
	}
	else{
		buf[0] = 0;
		buf[1] = 90 + (param->res%10);
		memcpy(buf+2, &sin.sin_port, 2);
		memcpy(buf+4, &sin.sin_addr.s_addr, 4);
		socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]);
	}

	if (param->res == 0) {
		switch(command) {
			case 1:
				if(param->redirectfunc){
					if(buf)myfree(buf);
					return (*param->redirectfunc)(param);
				}
				param->res = sockmap(param, conf.timeouts[CONNECTION_L]);
				break;
			case 2:
				listen (param->remsock, 1);
				
				fds[0].fd = param->remsock;
				fds[1].fd = param->clisock;
				fds[0].events = fds[1].events = POLLIN;
				res = poll(fds, 2, conf.timeouts[(param->req.sin_addr.s_addr)?CONNECTION_S:CONNECTION_L] * 1000);
				if (res < 1 || fds[1].revents) {
					res = 460;
					break;
				}
				sasize = sizeof(param->sins);
				s = accept(param->remsock, (struct sockaddr *)&param->sins, &sasize);
				closesocket(param->remsock);
				param->remsock = s;
				if(s == INVALID_SOCKET) {
					param->res = 462;
					break;
				}
				if(param->req.sin_addr.s_addr && param->req.sin_addr.s_addr != param->sins.sin_addr.s_addr) {
					param->res = 470;
					break;
				}
#if SOCKSTRACE > 0
fprintf(stderr, "Sending incoming connection to client with code %d for %s with %s:%hu\n",
			param->res,
			commands[command],
			inet_ntoa(param->sins.sin_addr),
			ntohs(param->sins.sin_port)
	);
fflush(stderr);
#endif
				if(ver == 5){
					memcpy (buf+4, &param->sins.sin_addr, 4);
					memcpy (buf+8, &param->sins.sin_port, 2);
					socksend(param->clisock, buf, 10, conf.timeouts[STRING_S]);
				}
				else {
					memcpy (buf+2, &param->sins.sin_port, 2);
					memcpy (buf+4, &param->sins.sin_addr, 4);
					socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]);
				}

				param->res = sockmap(param, conf.timeouts[CONNECTION_S]);
				break;
			case 3:
				param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr;
				param->sins.sin_port = param->req.sin_port;
				myfree(buf);
				if(!(buf = myalloc(LARGEBUFSIZE))) {RETURN(21);}

				for(;;){
					fds[0].fd = param->remsock;
					fds[1].fd = param->clisock;
					fds[2].fd = param->ctrlsock;
					fds[2].events = fds[1].events = fds[0].events = POLLIN;

					res = poll(fds, 3, conf.timeouts[CONNECTION_L]*1000);
					if(res <= 0) {
						param->res = 463;
						break;
					}
					if (fds[2].revents) {
						param->res = 0;
						break;
					}
					if (fds[1].revents) {
						sasize = sizeof(struct sockaddr_in);
						if((len = recvfrom(param->clisock, buf, 65535, 0, (struct sockaddr *)&sin, &sasize)) <= 10) {
							param->res = 464;
							break;
						}
						if(sin.sin_addr.s_addr != param->sinc.sin_addr.s_addr){
							param->res = 465;
							break;
						}
						if(buf[0] || buf[1] || buf[2]) {
							param->res = 466;
							break;
						}
						switch(buf[3]) {
							case 1:
								i = 8;
								memcpy(&param->sins.sin_addr.s_addr, buf+4, 4);
								break;
							case 3:
								size = buf[4];
								for (i=4; size; i++, size--){
									buf[i] = buf[i+1];
								}
								buf[i++] = 0;
								param->sins.sin_addr.s_addr = getip(buf+4);
								break;
							default:
								RETURN(996);
						 }

						memcpy(&param->sins.sin_port, buf+i, 2);
						i+=2;

						sasize = sizeof(param->sins);
						if(len > (int)i){
							if(socksendto(param->remsock, &param->sins, buf+i, len - i, conf.timeouts[SINGLEBYTE_L]*1000) <= 0){
								param->res = 467;
								break;
							}
							param->statscli+=(len - i);
							param->nwrites++;
#if SOCKSTRACE > 1
fprintf(stderr, "UDP packet relayed from client to %s:%hu size %d, header %d\n",
			inet_ntoa(param->sins.sin_addr),
			ntohs(param->sins.sin_port),
			(len - i),
			i
	);
fprintf(stderr, "client address is assumed to be %s:%hu\n",
			inet_ntoa(sin.sin_addr),
			ntohs(sin.sin_port)
	);
fflush(stderr);
#endif
						}

					}
					if (fds[0].revents) {
						struct sockaddr_in tsin;
						sasize = sizeof(tsin);
						buf[0]=buf[1]=buf[2]=0;
						buf[3]=1;
						if((len = recvfrom(param->remsock, buf+10, 65535 - 10, 0, (struct sockaddr *)&tsin, &sasize)) <= 0) {
							param->res = 468;
							break;
						}
						param->statssrv+=len;
						param->nreads++;
						memcpy(buf+4, &tsin.sin_addr.s_addr, 4);
						memcpy(buf+8, &tsin.sin_port, 2);
						sasize = sizeof(param->sins);
						if(socksendto(param->clisock, &sin, buf, len + 10, conf.timeouts[SINGLEBYTE_L]*1000) <=0){
							param->res = 469;
							break;
						}
#if SOCKSTRACE > 1
fprintf(stderr, "UDP packet relayed to client from %s:%hu size %d\n",
			inet_ntoa(tsin.sin_addr),
			ntohs(tsin.sin_port),
			len
	);
fflush(stderr);
#endif

					}
				}
				break;
			default:
				param->res = 417;
				break;
		}
	}
 }
 
 if(command > 3) command = 0;
 if(buf){
	 sprintf((char *)buf, "%s ", commands[command]);
	 if(param->hostname){
	  sprintf((char *)buf + strlen((char *)buf), "%.265s", param->hostname);
	 }
	 else myinet_ntoa(param->req.sin_addr, (char *)buf+strlen((char *)buf));
         sprintf((char *)buf+strlen((char *)buf), ":%hu", ntohs(param->req.sin_port));
	 (*param->srv->logfunc)(param, buf);
	 myfree(buf);
 }
 freeparam(param);
 return (NULL);
}
コード例 #18
0
ファイル: socks.c プロジェクト: digsrc/3proxy
void * sockschild(struct clientparam* param) {
 int res;
 unsigned i=0;
 SOCKET s;
 unsigned size;
 SASIZETYPE sasize;
 unsigned short port = 0;
 unsigned char * buf=NULL;
 unsigned char c;
 unsigned char command=0;
 struct pollfd fds[3];
 int ver=0;
 int havepass = 0;
#ifndef NOIPV6
 struct sockaddr_in6 sin = {AF_INET6};
#else
 struct sockaddr_in sin = {AF_INET};
#endif
 int len;


 param->service = S_SOCKS;

 if(!(buf = myalloc(BUFSIZE))) {RETURN(21);}
 memset(buf, 0, BUFSIZE);
 if ((ver = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5 && ver != 4) {
	RETURN(401);
 } /* version */
 param->service = ver;
 if(ver == 5){
	 if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} /* nmethods */
	 for (; i; i--) {
		if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
		if (res == 2 && param->srv->needuser) {
			havepass = res;
		}
	 }
	 buf[0] = 5;
	 buf[1] = (param->srv->needuser > 1 && !havepass)? 255 : havepass;
	 if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(401);}
	 if (param->srv->needuser > 1 && !havepass) RETURN(4);
	 if (havepass) {
		if (((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0))) != 1) {
			RETURN(412);
		}
		if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);}
		if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(441);};
		buf[i] = 0;
		if(!param->username)param->username = (unsigned char *)mystrdup((char *)buf);
		if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(445);}
		if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(441);};
		buf[i] = 0;
		if(!param->password)param->password = (unsigned char *)mystrdup((char *)buf);
		buf[0] = 1;
		buf[1] = 0;
		if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(481);}
	 }
	 if ((c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5) {
		RETURN(421);
         } /* version */
 }
 if( (command = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) < 1 || command > 3){command = 0; RETURN(407);} /* command */
 if(ver == 5){
	 if (sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0) == EOF) {RETURN(447);} /* reserved */
	 c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0); /* atype */
 }
 else {
	if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
	buf[0] = (unsigned char) res;
	if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
	buf[1] = (unsigned char) res;
	port = *(unsigned short*)buf;
	c = 1;
 }
 
 size = 4;
 *SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = AF_INET;
 switch(c) {
#ifndef NOIPV6
	case 4:
		if(param->srv->family == 4) RETURN(997);
		size = 16;
		*SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = AF_INET6;
#endif
	case 1:
		for (i = 0; i<size; i++){
			if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
			buf[i] = (unsigned char)res;
		}
#ifndef NOIPV6
		if (c == 1 && param->srv->family==6){
			char prefix[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255};
			*SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = AF_INET6;
			memcpy(SAADDR(&param->sinsr), prefix, 12);
			memcpy(12 + (char *)SAADDR(&param->sinsr), buf, 4);
			memcpy(SAADDR(&param->req), prefix, 12);
			memcpy(12 + (char *)SAADDR(&param->req), buf, 4);
		}
		else {
#endif
			memcpy(SAADDR(&param->sinsr), buf, size);
			memcpy(SAADDR(&param->req), buf, size);
#ifndef NOIPV6
		}
#endif
		if(SAISNULL(&param->req)) {
			RETURN(421);
		}
		myinet_ntop(*SAFAMILY(&param->sinsr), SAADDR(&param->sinsr), (char *)buf, 64);
		break;
	case 3:
		if ((size = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);} /* nmethods */
		for (i=0; i<size; i++){ /* size < 256 */
			if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);}
			buf[i] = (unsigned char)res;
		}
		buf[i] = 0;
		if(!getip46(param->srv->family, buf, (struct sockaddr *) &param->req)) RETURN(100);
		memcpy(&param->sinsr, &param->req, sizeof(param->req));
		break;
	default:
		RETURN(997);
 }
 if(param->hostname)myfree(param->hostname);
 param->hostname = (unsigned char *)mystrdup((char *)buf);
 if (ver == 5) {
	 if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
	 buf[0] = (unsigned char) res;
	 if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
	 buf[1] = (unsigned char) res;
	 port = *(unsigned short*)buf;

 }
 else {
	sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]);
	buf[127] = 0;
	if(param->srv->needuser && *buf && !param->username)param->username = (unsigned char *)mystrdup((char *)buf);
	if(!memcmp(SAADDR(&param->req), "\0\0\0", 3)){
		param->service = S_SOCKS45;
		sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]);
		buf[127] = 0;
		if(param->hostname)myfree(param->hostname);
		param->hostname = (unsigned char *)mystrdup((char *)buf);
		if(!getip46(param->srv->family, buf, (struct sockaddr *) &param->req)) RETURN(100);
		memcpy(&param->sinsr, &param->req, sizeof(&param->req));
	}
 }

 *SAPORT(&param->sinsr) = *SAPORT(&param->req) = port;
 if(command == 1 && !*SAPORT(&param->sinsr)) {RETURN(421);}
 switch(command) { 
	case 1:
	 param->operation = CONNECT;
	 break;
 	case 2:
	case 3:

#ifndef NOIPV6	 
	 memcpy(&param->sinsl, *SAFAMILY(&param->req)==AF_INET6? (struct sockaddr *)&param->srv->extsa6:(struct sockaddr *)&param->srv->extsa, SASIZE(&param->req)); 
#else
	 memcpy(&param->sinsl, &param->srv->extsa, SASIZE(&param->req)); 
#endif
	 if ((param->remsock=so._socket(SASOCK(&param->req), command == 2? SOCK_STREAM:SOCK_DGRAM, command == 2?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
	 param->operation = command == 2?BIND:UDPASSOC;
	 break;

	default:
	 RETURN(997);
 }

 if((res = (*param->srv->authfunc)(param))) {
	RETURN(res);
 }

 if(command > 1) {
	if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,SASIZE(&param->sinsl))) {
		*SAPORT(&param->sinsl) = 0;
		if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,SASIZE(&param->sinsl)))RETURN (12);
#if SOCKSTRACE > 0
fprintf(stderr, "%hu binded to communicate with server\n", *SAPORT(&param->sins));
fflush(stderr);
#endif
	}
	sasize = SASIZE(&param->sinsl);
	so._getsockname(param->remsock, (struct sockaddr *)&param->sinsl,  &sasize);
	if(command == 3) {
		param->ctrlsock = param->clisock;
		param->clisock = so._socket(SASOCK(&param->sincr), SOCK_DGRAM, IPPROTO_UDP);
		if(param->clisock == INVALID_SOCKET) {RETURN(11);}
		memcpy(&sin, &param->sincl, sizeof(&sin));
		*SAPORT(&sin) = 0;
		if(so._bind(param->clisock,(struct sockaddr *)&sin,sizeof(sin))) {RETURN (12);}
#if SOCKSTRACE > 0
fprintf(stderr, "%hu binded to communicate with client\n",
			ntohs(*SAPORT(&sin))
	);
fflush(stderr);
#endif
	}
 }
 param->res = 0;

CLEANRET:

 if(param->clisock != INVALID_SOCKET){
	int repcode;

	sasize = sizeof(sin);
	if(command != 3) so._getsockname(param->remsock, (struct sockaddr *)&sin,  &sasize);
	else so._getsockname(param->clisock, (struct sockaddr *)&sin,  &sasize);
#if SOCKSTRACE > 0
fprintf(stderr, "Sending confirmation to client with code %d for %s with %s:%hu\n",
			param->res,
			commands[command],
			inet_ntoa(sin.sin_addr),
			ntohs(sin.sin_port)
	);
fflush(stderr);
#endif
	if(!param->res) repcode = 0;
	else if(param->res <= 10) repcode = 2;
	else if (param->res < 20) repcode = 5;
	else if (param->res < 30) repcode = 1;
	else if (param->res < 100) repcode = 4;
	else repcode = param->res%10;

	if(ver == 5){
		buf[0] = 5;
		buf[1] = repcode;
		buf[2] = 0;
		buf[3] = (*SAFAMILY(&sin) == AF_INET)?1:4;
		memcpy(buf+4, SAADDR(&sin), SAADDRLEN(&sin));
		memcpy(buf+4+SAADDRLEN(&sin), SAPORT(&sin), 2);
		socksend((command == 3)?param->ctrlsock:param->clisock, buf, 6+SAADDRLEN(&sin), conf.timeouts[STRING_S]);
	}
	else{
		buf[0] = 0;
		buf[1] = 90 + !!(repcode);
		memcpy(buf+2, SAPORT(&sin), 2);
		memcpy(buf+4, SAADDR(&sin), 4);
		socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]);
	}

	if (param->res == 0) {
		switch(command) {
			case 1:
				if(param->redirectfunc){
					if(buf)myfree(buf);
					return (*param->redirectfunc)(param);
				}
				param->res = sockmap(param, conf.timeouts[CONNECTION_L]);
				break;
			case 2:
				so._listen (param->remsock, 1);
				
				fds[0].fd = param->remsock;
				fds[1].fd = param->clisock;
				fds[0].events = fds[1].events = POLLIN;
				res = so._poll(fds, 2, conf.timeouts[CONNECTION_L] * 1000);
				if (res < 1 || fds[1].revents) {
					res = 460;
					break;
				}
				sasize = sizeof(param->sinsr);
				s = so._accept(param->remsock, (struct sockaddr *)&param->sinsr, &sasize);
				so._closesocket(param->remsock);
				param->remsock = s;
				if(s == INVALID_SOCKET) {
					param->res = 462;
					break;
				}
				if(SAISNULL(&param->req) &&
				 memcmp(SAADDR(&param->req),SAADDR(&param->sinsr),SAADDRLEN(&param->req))) {
					param->res = 470;
					break;
				}
#if SOCKSTRACE > 0
fprintf(stderr, "Sending incoming connection to client with code %d for %s with %hu\n",
			param->res,
			commands[command],
			*SAPORT(param->sins);
	);
fflush(stderr);
#endif
				if(ver == 5){
					buf[3] = (*SAFAMILY(&param->sinsr) == AF_INET)?1:4;
					memcpy(buf+4, SAADDR(&param->sinsr), SAADDRLEN(&param->sinsr));
					memcpy(buf+4+SAADDRLEN(&param->sinsr), SAPORT(&param->sinsr), 2);
					socksend(param->clisock, buf, 6+SAADDRLEN(&param->sinsr), conf.timeouts[STRING_S]);
				}
				else {
					memcpy (buf+2, SAPORT(&param->sinsr), 2);
					memcpy (buf+4, SAADDR(&param->sinsr), 4);
					socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]);
				}

				param->res = sockmap(param, conf.timeouts[CONNECTION_S]);
				break;
			case 3:
				memcpy(&param->sinsr, &param->req, sizeof(param->sinsr));
				myfree(buf);
				if(!(buf = myalloc(LARGEBUFSIZE))) {RETURN(21);}

				for(;;){
					fds[0].fd = param->remsock;
					fds[1].fd = param->clisock;
					fds[2].fd = param->ctrlsock;
					fds[2].events = fds[1].events = fds[0].events = POLLIN;

					res = so._poll(fds, 3, conf.timeouts[CONNECTION_L]*1000);
					if(res <= 0) {
						param->res = 463;
						break;
					}
					if (fds[2].revents) {
						param->res = 0;
						break;
					}
					if (fds[1].revents) {
						sasize = sizeof(sin);
						if((len = so._recvfrom(param->clisock, buf, 65535, 0, (struct sockaddr *)&sin, &sasize)) <= 10) {
							param->res = 464;
							break;
						}
						if(SAADDRLEN(&sin) != SAADDRLEN(&param->sincr) || memcmp(SAADDR(&sin), SAADDR(&param->sincr), SAADDRLEN(&sin))){
							param->res = 465;
							break;
						}
						if(buf[0] || buf[1] || buf[2]) {
							param->res = 466;
							break;
						}
						size = 4;
						switch(buf[3]) {
							case 4:
								size = 16;
							case 1:
								i = 4+size;
								memcpy(SAADDR(&param->sinsr), buf+4, size);
								*SAFAMILY(&param->sinsr) = (size == 4)?AF_INET:AF_INET6;
								break;
							case 3:
								size = buf[4];
								for (i=4; size; i++, size--){
									buf[i] = buf[i+1];
								}
								buf[i++] = 0;
								if(!getip46(param->srv->family, buf, (struct sockaddr *) &param->sinsr)) RETURN(100);
								break;
							default:
								RETURN(997);
						 }

						memcpy(SAPORT(&param->sinsr), buf+i, 2);
						i+=2;

						sasize = sizeof(param->sinsr);
						if(len > (int)i){
							if(socksendto(param->remsock, (struct sockaddr *)&param->sinsr, buf+i, len - i, conf.timeouts[SINGLEBYTE_L]*1000) <= 0){
								param->res = 467;
								break;
							}
							param->statscli64+=(len - i);
							param->nwrites++;
#if SOCKSTRACE > 1
fprintf(stderr, "UDP packet relayed from client to %s:%hu size %d, header %d\n",
			inet_ntoa(param->sins.sin_addr),
			ntohs(param->sins.sin_port),
			(len - i),
			i
	);
fprintf(stderr, "client address is assumed to be %s:%hu\n",
			inet_ntoa(sin.sin_addr),
			ntohs(sin.sin_port)
	);
fflush(stderr);
#endif
						}

					}
					if (fds[0].revents) {
						sasize = sizeof(param->sinsr);
						buf[0]=buf[1]=buf[2]=0;
						buf[3]=(*SAFAMILY(&param->sinsl) == AF_INET)?1:4;
						if((len = so._recvfrom(param->remsock, buf+6+SAADDRLEN(&param->sinsl), 65535 - 10, 0, (struct sockaddr *)&param->sinsr, &sasize)) <= 0) {
							param->res = 468;
							break;
						}
						param->statssrv64+=len;
						param->nreads++;
						memcpy(buf+4, SAADDR(&param->sinsr), SAADDRLEN(&param->sinsr));
						memcpy(buf+4+SAADDRLEN(&param->sinsr), SAPORT(&param->sinsr), 2);
						sasize = sizeof(sin);
						if(socksendto(param->clisock, (struct sockaddr *)&sin, buf, len + 6 + SAADDRLEN(&param->sinsr), conf.timeouts[SINGLEBYTE_L]*1000) <=0){
							param->res = 469;
							break;
						}
#if SOCKSTRACE > 1
fprintf(stderr, "UDP packet relayed to client from %hu size %d\n",
			ntohs(*SAPORT(&param->sinsr)),
			len
	);
fflush(stderr);
#endif

					}
				}
				break;
			default:
				param->res = 417;
				break;
		}
	}