Просмотр исходного кода

Merge remote-tracking branch 'refs/remotes/origin/devel'

# Conflicts:
#	src/version.h
z3APA3A 9 лет назад
Родитель
Сommit
63bafa5a62
21 измененных файлов с 197 добавлено и 74 удалено
  1. 1 0
      .gitignore
  2. 43 0
      Makefile.watcom
  3. 1 1
      doc/html/faqr.html
  4. 2 0
      man/3proxy.cfg.3
  5. 5 1
      src/3proxy.c
  6. 8 9
      src/auth.c
  7. 36 15
      src/common.c
  8. 32 16
      src/conf.c
  9. 3 1
      src/datatypes.c
  10. 20 7
      src/ftp.c
  11. 1 1
      src/ftppr.c
  12. 3 3
      src/icqpr.c
  13. 5 2
      src/plugins/PamAuth/pamauth.c
  14. 1 1
      src/pop3p.c
  15. 10 3
      src/proxy.c
  16. 3 3
      src/proxy.h
  17. 8 4
      src/proxymain.c
  18. 1 1
      src/smtpp.c
  19. 5 0
      src/sockmap.c
  20. 3 3
      src/socks.c
  21. 6 3
      src/structures.h

+ 1 - 0
.gitignore

@@ -15,6 +15,7 @@ tmp/
 *.swp
 *.o
 *.idb
+*.err
 res
 version.c
 3proxy.res

+ 43 - 0
Makefile.watcom

@@ -0,0 +1,43 @@
+#
+# 3 proxy Makefile for Open Watcom 2
+#
+# You can try to remove -DWITH_STD_MALLOC to CFLAGS to use optimized malloc
+# libraries
+#
+# Add /DSAFESQL to CFLAGS if you are using poorely written/tested ODBC driver
+
+BUILDDIR = ../bin/
+CC = cl
+CFLAGS = /nologo /Ox /MT /D "NOIPV6" /D "NODEBUG" /D "NOODBC" /D "MSVC" /D "WITH_STD_MALLOC" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_WIN32" /c
+COUT = /Fo
+LN = link
+LDFLAGS = /nologo /subsystem:console /incremental:no 
+DLFLAGS = /DLL
+DLSUFFICS = .dll
+LIBS = ws2_32.lib advapi32.lib user32.lib kernel32.lib
+LIBSOLD = libeay32MT.lib ssleay32MT.lib
+LIBSPREFIX = 
+LIBSSUFFIX = .lib
+LIBEXT = .lib                                                                                               
+LNOUT = /out:
+EXESUFFICS = .exe
+OBJSUFFICS = .obj
+DEFINEOPTION = /D 
+COMPFILES = *.pch *.idb *.err
+REMOVECOMMAND = del 2>NUL >NUL
+TYPECOMMAND = type
+COMPATLIBS =
+MAKEFILE = Makefile.watcom
+PLUGINS = utf8tocp1251 WindowsAuthentication TrafficPlugin StringsPlugin PCREPlugin
+VERFILE = $(VERFILE)
+
+include Makefile.inc
+
+../3proxy.res:
+	rc /fo../3proxy.res ../3proxy.rc
+
+3proxyres.obj: ../3proxy.res
+	cvtres /out:3proxyres.obj ../3proxy.res
+
+allplugins:
+	call ../makeplugins.bat	

+ 1 - 1
doc/html/faqr.html

@@ -129,7 +129,7 @@
   невозможен. Защитить соединение можно с помощью TLS (например, stunnel) или
   IPSec.
   </p>
-  <li><a name="#CRASH"><i>Q: Почему прокси крэшится при обработке запроса?</a></i></li>
+  <li><a name="CRASH"><i>Q: Почему прокси крэшится при обработке запроса?</a></i></li>
   <p>
   <i>A:</i> Возможно, недостаточен размер стека потока по-умолчанию, это может
   быть при использовани каких-либо сторонних плагинов (PAM, ODBC) или на

+ 2 - 0
man/3proxy.cfg.3

@@ -300,6 +300,8 @@ with space and all time based elemnts are in local time zone.
   %R - Remote IP
 .br
   %r - Remote port
+.br
+  %i - Internal IP used to accept client connection
 .br
   %e - External IP used to establish connection
 .br

+ 5 - 1
src/3proxy.c

@@ -59,8 +59,8 @@ void __stdcall CommandHandler( DWORD dwCommand )
     case SERVICE_CONTROL_STOP:
     case SERVICE_CONTROL_SHUTDOWN:
         SetStatus( SERVICE_STOP_PENDING, 0, 1 );
-	conf.paused++;
 	conf.timetoexit = 1;
+	conf.paused++;
 	Sleep(2000);
         SetStatus( SERVICE_STOPPED, 0, 0 );
 #ifndef NOODBC
@@ -192,6 +192,7 @@ void doschedule(void){
 
 void dumpcounters(struct trafcount *tlin, int counterd){
 
+ unsigned char tmpbuf[8192];
  struct trafcount *tl;
  if(counterd >= 0 && tlin) {
 
@@ -234,6 +235,7 @@ void dumpcounters(struct trafcount *tlin, int counterd){
 void cyclestep(void){
  struct tm *tm;
  time_t minutecounter;
+ unsigned char tmpbuf[8192];
 
  minutecounter = time(0);
  for(;;){
@@ -362,6 +364,7 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int
 #ifdef _WIN32
   unsigned char * arg;
   WSADATA wd;
+  unsigned char tmpbuf[8192];
 
   WSAStartup(MAKEWORD( 1, 1 ), &wd);
   osv.dwOSVersionInfoSize = sizeof(osv);
@@ -519,6 +522,7 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int
 
   freeconf(&conf);
   res = readconfig(fp);
+  conf.version++;
 
   if(res) RETURN(res);
   if(!writable)fclose(fp);

+ 8 - 9
src/auth.c

@@ -57,7 +57,7 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, struct soc
 				":%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 *)"");
+				sprintf((char *)username, "%.128s:%.128s", 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");
@@ -317,8 +317,8 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
 		connected = 1;
 	}
 
-	if(!connected) return 9;
-	return (redir)?clientnegotiate(redir, param, (struct sockaddr *)&param->req):0;
+	if(!connected || !redir) return 0;
+	return clientnegotiate(redir, param, (struct sockaddr *)&param->req);
 }
 
 int IPInentry(struct sockaddr *sa, struct iplist *ipentry){
@@ -476,8 +476,8 @@ unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nb
 	
 	if(!nbytesin && !nbytesout) return 0;
 	pthread_mutex_lock(&bandlim_mutex);
-	if(param->srv->version != conf.paused){
-		initbandlims(param);
+	if(param->paused != conf.paused){
+		return (1);
 	}
 	for(i=0; nbytesin&& i<MAXBANDLIMS && param->bandlims[i]; i++){
 		if( !param->bandlims[i]->basetime || 
@@ -558,7 +558,6 @@ int alwaysauth(struct clientparam * param){
 
 	res = doconnect(param);
 	if(!res){
-		if(param->srv->version != conf.paused) return 333;
 		initbandlims(param);
 		for(tc = conf.trafcounter; tc; tc = tc->next) {
 			if(tc->disabled) continue;
@@ -655,7 +654,7 @@ int cacheauth(struct clientparam * param){
 			
 		}
 		if(((!(conf.authcachetype&2)) || (param->username && ac->username && !strcmp(ac->username, (char *)param->username))) &&
-		   ((!(conf.authcachetype&1)) || (*SAFAMILY(&ac->sa) ==  *SAFAMILY(&param->sincr) && !memcmp(SAADDR(&ac->sa), &param->sincr, SAADDRLEN(&ac->sa)))) && 
+		   ((!(conf.authcachetype&1)) || (*SAFAMILY(&ac->sa) ==  *SAFAMILY(&param->sincr) && !memcmp(SAADDR(&ac->sa), SAADDR(&param->sincr), SAADDRLEN(&ac->sa)))) && 
 		   (!(conf.authcachetype&4) || (ac->password && param->password && !strcmp(ac->password, (char *)param->password)))) {
 			if(param->username){
 				myfree(param->username);
@@ -689,7 +688,7 @@ int doauth(struct clientparam * param){
 				pthread_mutex_lock(&hash_mutex);
 				for(ac = authc; ac; ac = ac->next){
 					if((!(conf.authcachetype&2) || !strcmp(ac->username, (char *)param->username)) &&
-					   (!(conf.authcachetype&1) || (*SAFAMILY(&ac->sa) ==  *SAFAMILY(&param->sincr) && !memcmp(SAADDR(&ac->sa), &param->sincr, SAADDRLEN(&ac->sa))))  &&
+					   (!(conf.authcachetype&1) || (*SAFAMILY(&ac->sa) ==  *SAFAMILY(&param->sincr) && !memcmp(SAADDR(&ac->sa), SAADDR(&param->sincr), SAADDRLEN(&ac->sa))))  &&
 					   (!(conf.authcachetype&4) || (ac->password && !strcmp(ac->password, (char *)param->password)))) {
 						ac->expires = conf.time + conf.authcachetime;
 						if(strcmp(ac->username, (char *)param->username)){
@@ -710,7 +709,7 @@ int doauth(struct clientparam * param){
 					ac = myalloc(sizeof(struct authcache));
 					if(ac){
 						ac->expires = conf.time + conf.authcachetime;
-						ac->username = mystrdup((char *)param->username);
+						ac->username = param->username?mystrdup((char *)param->username):NULL;
 						ac->sa = param->sincr;
 						ac->password = NULL;
 						if((conf.authcachetype&4) && param->password) ac->password = mystrdup((char *)param->password);

+ 36 - 15
src/common.c

@@ -17,6 +17,16 @@ int randomizer = 1;
 
 #ifndef _WIN32
  pthread_attr_t pa;
+
+
+ void daemonize(void){
+	if(fork() > 0) {
+		usleep(SLEEPTIME);
+		_exit(0); 
+	}
+	setsid();
+ }
+
 #endif
 
 unsigned char **stringtable = NULL;
@@ -63,7 +73,7 @@ struct extparam conf = {
 #else
 	0,
 #endif
-	0, -1, 0, 0, 0, 0, 0, 500, 0, 0, 0,
+	0, -1, 0, 0, 0, 0, 0, 500, 0, 0, 0, 0, 0,
 	6, 600,
 	1048576,
 	NULL, NULL,
@@ -221,30 +231,34 @@ int ceparseargs(const char *str){
 
 #endif
 
-void parsehost(int family, unsigned char *host, struct sockaddr *sa){
+int parsehost(int family, unsigned char *host, struct sockaddr *sa){
 	char *sp=NULL,*se=NULL;
-	unsigned short port;
+	unsigned short port=0;
+	int ret = 0;
 
+	if(!host) return 2;
 	if(*host == '[') se=strchr((char *)host, ']');
-	if ( (sp = strchr(se?se:(char *)host, ':')) ) *sp = 0;
+	if ( (sp = strchr(se?se:(char *)host, ':')) && !strchr(sp+1, ':')) *sp = 0;
 	if(se){
 		*se = 0;
 	}
 	if(sp){
 		port = atoi(sp+1);
 	}
-	getip46(family, host + (se!=0), (struct sockaddr *)sa);
+	ret = !getip46(family, host + (se!=0), (struct sockaddr *)sa);
 	if(se) *se = ']';
 	if(sp) *sp = ':';
-	*SAPORT(sa) = htons(port);
+	if(port)*SAPORT(sa) = htons(port);
+	return ret;
 }
 
 int parsehostname(char *hostname, struct clientparam *param, unsigned short port){
 	char *sp=NULL,*se=NULL;
+	int ret = 0;
 
-	if(!hostname || !*hostname)return 1;
+	if(!hostname || !*hostname)return 2;
 	if(*hostname == '[') se=strchr(hostname, ']');
-	if ( (sp = strchr(se?se:hostname, ':')) ) *sp = 0;
+	if ( (sp = strchr(se?se:hostname, ':'))  && !strchr(sp+1, ':')) *sp = 0;
 	if(se){
 		*se = 0;
 	}
@@ -255,12 +269,12 @@ int parsehostname(char *hostname, struct clientparam *param, unsigned short port
 	if(sp){
 		port = atoi(sp+1);
 	}
-	getip46(param->srv->family, param->hostname, (struct sockaddr *)&param->req);
+	ret = !getip46(param->srv->family, param->hostname, (struct sockaddr *)&param->req);
 	if(se) *se = ']';
 	if(sp) *sp = ':';
 	*SAPORT(&param->req) = htons(port);
 	memset(&param->sinsr, 0, sizeof(param->sinsr));
-	return 0;
+	return ret;
 }
 
 int parseusername(char *username, struct clientparam *param, int extpasswd){
@@ -498,6 +512,9 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char
 				case 'e':
 				 i += myinet_ntop(*SAFAMILY(&param->sinsl), SAADDR(&param->sinsl), (char *)buf + i, 64);
 				 break;
+				case 'i':
+				 i += myinet_ntop(*SAFAMILY(&param->sincl), SAADDR(&param->sincl), (char *)buf + i, 64);
+				 break;
 				case 'C':
 				 i += myinet_ntop(*SAFAMILY(&param->sincr), SAADDR(&param->sincr), (char *)buf + i, 64);
 				 break;
@@ -631,7 +648,8 @@ void logsyslog(struct clientparam * param, const unsigned char *s) {
 #endif
 
 int doconnect(struct clientparam * param){
- SASIZETYPE size = sizeof(param->sinsr);
+ SASIZETYPE size;
+
 
  if (*SAFAMILY(&param->sincr) == *SAFAMILY(&param->req) && !memcmp(SAADDR(&param->sincr), SAADDR(&param->req), SAADDRLEN(&param->req)) &&
 	*SAPORT(&param->sincr) == *SAPORT(&param->req)) return 519;
@@ -639,6 +657,7 @@ int doconnect(struct clientparam * param){
  if (param->operation == ADMIN || param->operation == DNSRESOLVE || param->operation == BIND || param->operation == UDPASSOC)
 	return 0;
  if (param->remsock != INVALID_SOCKET){
+	size = sizeof(param->sinsr);
 	if(so._getpeername(param->remsock, (struct sockaddr *)&param->sinsr, &size)==-1) {return (15);}
  }
  else {
@@ -669,11 +688,13 @@ int doconnect(struct clientparam * param){
 	}
 #endif
 
+	if(SAISNULL(&param->sinsl)){
 #ifndef NOIPV6
-	if(*SAFAMILY(&param->sinsr) == AF_INET6) param->sinsl = param->srv->extsa6;
-	else
+		if(*SAFAMILY(&param->sinsr) == AF_INET6) param->sinsl = param->srv->extsa6;
+		else
 #endif
-		param->sinsl = param->srv->extsa;
+			param->sinsl = param->srv->extsa;
+	}
 	*SAPORT(&param->sinsl) = 0;
 	if(so._bind(param->remsock, (struct sockaddr*)&param->sinsl, SASIZE(&param->sinsl))==-1) {
 		return 12;
@@ -692,8 +713,8 @@ int doconnect(struct clientparam * param){
 #else
 		fcntl(param->remsock,F_SETFL,O_NONBLOCK);
 #endif
-		size = sizeof(param->sinsl);
 	}
+	size = sizeof(param->sinsl);
 	if(so._getsockname(param->remsock, (struct sockaddr *)&param->sinsl, &size)==-1) {return (15);}
  }
  return 0;

+ 32 - 16
src/conf.c

@@ -285,6 +285,7 @@ static int h_external(int argc, unsigned char ** argv){
 }
 
 static int h_log(int argc, unsigned char ** argv){ 
+	unsigned char tmpbuf[8192];
 	conf.logfunc = logstdout;
 	if(conf.logtarget){
 		myfree(conf.logtarget);
@@ -317,14 +318,12 @@ static int h_log(int argc, unsigned char ** argv){
 			conf.logname = (unsigned char *)mystrdup((char *)argv[1]);
 			fp = fopen((char *)dologname (tmpbuf, conf.logname, NULL, conf.logtype, conf.logtime), "a");
 			if(!fp){
-				perror("fopen()");
+				perror((char *)tmpbuf);
 				return 1;
 			}
 			else {
-				pthread_mutex_lock(&log_mutex);
 				if(conf.stdlog)fclose(conf.stdlog);
 				conf.stdlog = fp;
-				pthread_mutex_unlock(&log_mutex);
 #ifdef _WINCE
 				freopen(tmpbuf, "w", stdout);
 				freopen(tmpbuf, "w", stderr);
@@ -340,6 +339,17 @@ static int h_stacksize(int argc, unsigned char **argv){
 	return 0;
 }
 
+
+static int h_force(int argc, unsigned char **argv){
+	conf.noforce = 0;
+	return 0;
+}
+
+static int h_noforce(int argc, unsigned char **argv){
+	conf.noforce = 1;
+	return 0;
+}
+
 static int h_service(int argc, unsigned char **argv){
 	return 0;
 }
@@ -395,17 +405,22 @@ static int h_counter(int argc, unsigned char **argv){
 			fprintf(stderr, "Not a counter file %s, line %d\n", argv[1], linenum);
 			return 2;
 		}
-#ifdef  _MSC_VER
 #ifdef _TIME64_T_DEFINED
-#ifndef _MAX__TIME64_T
-#define _MAX__TIME64_T     0x793406fffi64
+#ifdef _MAX__TIME64_T
+#define MAX_COUNTER_TIME (_MAX__TIME64_T)
+#elif defined (MAX__TIME64_T)
+#define MAX_COUNTER_TIME (MAX__TIME64_T)
+#else
+#define MAX_COUNTER_TIME (0x793406fff)
 #endif 
+#else
+#define MAX_COUNTER_TIME ((sizeof(time_t)>4)?(time_t)0x793406fff:(time_t)0x7fffffff)
 #endif
-		if(ch1.updated >= _MAX__TIME64_T){
+
+		if(ch1.updated < 0 || ch1.updated >= MAX_COUNTER_TIME){
 			fprintf(stderr, "Invalid or corrupted counter file %s. Use countersutil utility to convert from older version\n", argv[1]);
 			return 3;
 		}
-#endif
 		cheader.updated = ch1.updated;
 	}
 	if(argc >=4) {
@@ -548,8 +563,8 @@ static int h_nserver(int argc, unsigned char **argv){
 	if(numservers < MAXNSERVERS) {
 		if((str = strchr((char *)argv[1], '/')))
 			*str = 0;
-		if(!getip46(46, argv[1], (struct sockaddr *)&nservers[numservers].addr)) return 1;
 		*SAPORT(&nservers[numservers].addr) = htons(53);
+		if(parsehost(46, argv[1], (struct sockaddr *)&nservers[numservers].addr)) return 1;
 		if(str) {
 			nservers[numservers].usetcp = strstr(str + 1, "tcp")? 1:0;
 			*str = '/';
@@ -566,7 +581,7 @@ static int h_authnserver(int argc, unsigned char **argv){
 
 	if((str = strchr((char *)argv[1], '/')))
 		*str = 0;
-	if(!getip46(46, argv[1], (struct sockaddr *)&authnserver.addr)) return 1;
+	if(parsehost(46, argv[1], (struct sockaddr *)&authnserver.addr)) return 1;
 	*SAPORT(&authnserver.addr) = htons(53);
 	if(str) {
 		authnserver.usetcp = strstr(str + 1, "tcp")? 1:0;
@@ -1199,12 +1214,10 @@ static int h_ace(int argc, unsigned char **argv){
 				tl->traf64 = crecord.traf64;
 				tl->cleared = crecord.cleared;
 				tl->updated = crecord.updated;
-#ifdef _MAX__TIME64_T
-				if(tl->cleared >=  _MAX__TIME64_T || tl->updated >=  _MAX__TIME64_T){
-					fprintf(stderr, "Invalid or corrupted counter file. Use countersutil utility to convert from older version\n");
+				if(tl->cleared < 0 || tl->cleared >=  MAX_COUNTER_TIME || tl->updated < 0 || tl->updated >=  MAX_COUNTER_TIME){
+					fprintf(stderr, "Invalid, incompatible or corrupted counter file.\n");
 					return(6);
 				}
-#endif
 			}
 		}
 		pthread_mutex_lock(&tc_mutex);
@@ -1293,7 +1306,7 @@ static int h_plugin(int argc, unsigned char **argv){
 static int h_setuid(int argc, unsigned char **argv){
   int res;
 	res = atoi((char *)argv[1]);
-	if(!res || setuid(res)) {
+	if(!res || setreuid(res,res)) {
 		fprintf(stderr, "Unable to set uid %d", res);
 		return(1);
 	}
@@ -1304,7 +1317,7 @@ static int h_setgid(int argc, unsigned char **argv){
   int res;
 
 	res = atoi((char *)argv[1]);
-	if(!res || setgid(res)) {
+	if(!res || setregid(res,res)) {
 		fprintf(stderr, "Unable to set gid %d", res);
 		return(1);
 	}
@@ -1399,6 +1412,8 @@ struct commands commandhandlers[]={
 	{commandhandlers+56, "delimchar",h_delimchar, 2, 2},
 	{commandhandlers+57, "authnserver", h_authnserver, 2, 2},
 	{commandhandlers+58, "stacksize", h_stacksize, 2, 2},
+	{commandhandlers+59, "force", h_force, 1, 1},
+	{commandhandlers+60, "noforce", h_noforce, 1, 1},
 	{specificcommands, 	 "", h_noop, 1, 0}
 };
 
@@ -1686,6 +1701,7 @@ int reload (void){
 	fp = confopen();
 	if(fp){
 		error = readconfig(fp);
+		conf.version++;
 		if(error) {
 			 freeconf(&conf);
 		}

+ 3 - 1
src/datatypes.c

@@ -61,14 +61,16 @@ static void pr_ip(struct node *node, CBFUNC cbf, void*cb){
 	if(node->value)(*cbf)(cb, buf, myinet_ntop(AF_INET, node -> value, buf, 4));
 }
 
+#ifndef NOIPV6
 static void pr_ip6(struct node *node, CBFUNC cbf, void*cb){
 	char buf[64];
 	if(node->value)(*cbf)(cb, buf, myinet_ntop(AF_INET6, node -> value, buf, 16));
 }
+#endif
 
 static void pr_sa(struct node *node, CBFUNC cbf, void*cb){
 #ifdef NOIPV6
-	if(node->value)return pr_ip(node, cbf, cb);
+	if(node->value)pr_ip(node, cbf, cb);
 #else
 	char buf[64];
 	buf[0] = '[';

+ 20 - 7
src/ftp.c

@@ -9,17 +9,17 @@
 
 
 int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) {
-	char tbuf[1024];
+	char tbuf[256];
 	int i;
 	char *buf;
 	int len;
 	int res;
 
 	buf = nbuf?nbuf:tbuf;
-	len = nbuf?*innbuf:1024;
+	len = nbuf?*innbuf:sizeof(tbuf);
 
 	if(innbuf)*innbuf = 0;
-	if(len < 48) return 707;
+	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;
@@ -28,7 +28,7 @@ int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) {
 		*innbuf = i;
 		return 702;
 	}
-	sprintf(buf, "USER %.32s\r\n", param->extusername?param->extusername:(unsigned char *)"anonymous");
+	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;
 	}
@@ -40,7 +40,7 @@ int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) {
 	buf[i] = 0;
 	res = atoi(buf)/100;
 	if(res == 3){
-		sprintf(buf, "PASS %.32s\r\n", 
+		sprintf(buf, "PASS %.128s\r\n", 
 			param->extusername?
 				(param->extpassword?
 					param->extpassword:(unsigned char *)"")
@@ -174,6 +174,7 @@ SOCKET ftpdata(struct clientparam *param){
 	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;
@@ -187,15 +188,27 @@ SOCKET ftpdata(struct clientparam *param){
 	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))) {
-		param->remsock = rem;
-		return INVALID_SOCKET;
+		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;

+ 1 - 1
src/ftppr.c

@@ -70,7 +70,7 @@ void * ftpprchild(struct clientparam* param) {
 		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(*SAPORT(&param->sinsr))==21)?0:':', ntohs(*SAPORT(&param->sinsr)));
+		sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, (ntohs(*SAPORT(&param->sinsr))==21)?0:':', ntohs(*SAPORT(&param->sinsr)));
 		req = mystrdup((char *)buf);
 #ifndef WITHMAIN
 		{

+ 3 - 3
src/icqpr.c

@@ -25,20 +25,20 @@ struct flap_header {
 	unsigned char chan;
 	unsigned short seq;
 	unsigned short size;
-	char data[0];
+	char data[1];
 };
 
 struct snack_header {
 	unsigned family;
 	unsigned short flags;
 	unsigned id;
-	char data[0];
+	char data[1];
 };
 
 struct tlv_header {
 	unsigned short type;
 	unsigned short size;
-	char data[0];
+	char data[1];
 };
 
 

+ 5 - 2
src/plugins/PamAuth/pamauth.c

@@ -12,7 +12,7 @@ Kirill Lopuchov <lopuchov@mail.ru>
 #include <security/pam_appl.h>
 
 
-
+pthread_mutex_t pam_mutex;
 
 static int         already_loaded = 0;
 
@@ -89,9 +89,10 @@ static int pamfunc(struct clientparam *param)
   /*start process auth */  
   conv.appdata_ptr = (char *) param->password;
 
+  pthread_mutex_lock(&pam_mutex);
   if (!pamh)
     {
-      retval = pam_start ((char *)service, "3proxy@" , &conv, &pamh);
+	retval = pam_start ((char *)service, "3proxy@" , &conv, &pamh);
     }
    if (retval == PAM_SUCCESS)
        retval = pam_set_item (pamh, PAM_USER, param->username); 
@@ -110,6 +111,7 @@ static int pamfunc(struct clientparam *param)
       retval = pam_end (pamh, retval);
    if (retval != PAM_SUCCESS)
       {  pamh = NULL;   }
+  pthread_mutex_unlock(&pam_mutex);
 
   return rc;
 
@@ -130,6 +132,7 @@ int start(struct pluginlink * pluginlink, int argc, unsigned char** argv)
 
  already_loaded = 1;
     
+ pthread_mutex_init(&pam_mutex, NULL);
  pamauth.authenticate = pamfunc;
  pamauth.authorize = pluginlink->checkACL;
  pamauth.desc = "pam";

+ 1 - 1
src/pop3p.c

@@ -48,7 +48,7 @@ void * pop3pchild(struct clientparam* param) {
 CLEANRET:
 
  if(param->hostname&&param->extusername) {
-	sprintf((char *)buf, "%.64s@%.128s%c%hu", param->extusername, param->hostname, (*SAPORT(&param->sinsr)==110)?0:':', ntohs(*SAPORT(&param->sinsr)));
+	sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, (*SAPORT(&param->sinsr)==110)?0:':', ntohs(*SAPORT(&param->sinsr)));
 	 (*param->srv->logfunc)(param, buf);
  }
  else (*param->srv->logfunc)(param, NULL);

+ 10 - 3
src/proxy.c

@@ -131,8 +131,8 @@ char * proxy_stringtable[] = {
 	NULL
 };
 
-#define BUFSIZE 8192
 #define LINESIZE 4096
+#define BUFSIZE (LINESIZE*2)
 #define FTPBUFSIZE 1536
 
 static void logurl(struct clientparam * param, char * buf, char * req, int ftp){
@@ -152,7 +152,7 @@ static void logurl(struct clientparam * param, char * buf, char * req, int ftp){
 		strcpy(se, sb);
 	}
  }
- if(param->res != 555)(*param->srv->logfunc)(param, (unsigned char *)(req?buf:NULL));
+ if(param->res != 555 && param->res != 508)(*param->srv->logfunc)(param, (unsigned char *)(req?buf:NULL));
 }
 
 void decodeurl(unsigned char *s, int allowcr){
@@ -264,6 +264,9 @@ for(;;){
 		param->remsock = INVALID_SOCKET;
 		param->redirected = 0;
 		param->redirtype = 0;
+		memset(&param->sinsl, 0, sizeof(param->sinsl));
+		memset(&param->sinsr, 0, sizeof(param->sinsr));
+		memset(&param->req, 0, sizeof(param->req));
 	}
  }
 
@@ -284,6 +287,9 @@ for(;;){
 		param->remsock = INVALID_SOCKET;
 		param->redirected = 0;
 		param->redirtype = 0;
+		memset(&param->sinsl, 0, sizeof(param->sinsl));
+		memset(&param->sinsr, 0, sizeof(param->sinsr));
+		memset(&param->req, 0, sizeof(param->req));
 	}
 	myfree(req);
  }
@@ -546,6 +552,7 @@ for(;;){
 
 #endif
 
+ if(param->srv->needuser > 1 && !param->username) {RETURN(4);}
  if((res = (*param->srv->authfunc)(param))) {RETURN(res);}
 
  if(ftp && param->redirtype != R_HTTP){
@@ -843,7 +850,7 @@ for(;;){
  if(keepalive <= 1) sprintf((char*)buf+strlen((char *)buf), "%s: %s\r\n", (param->redirtype == R_HTTP)?"Proxy-Connection":"Connection", keepalive? "keep-alive":"close");
  if(param->extusername){
 	sprintf((char*)buf + strlen((char *)buf), "%s: basic ", (redirect)?"Proxy-Authorization":"Authorization");
-	sprintf((char*)username, "%.128s:%.64s", param->extusername, param->extpassword?param->extpassword:(unsigned char*)"");
+	sprintf((char*)username, "%.128s:%.128s", param->extusername, param->extpassword?param->extpassword:(unsigned char*)"");
 	en64(username, buf+strlen((char *)buf), (int)strlen((char *)username));
 	sprintf((char*)buf + strlen((char *)buf), "\r\n");
  }

+ 3 - 3
src/proxy.h

@@ -104,7 +104,7 @@
 #define PTHREAD_STACK_MIN 32768
 #define sockerror strerror
 #endif
-#define daemonize() {if(fork())exit(0); else setsid();}
+void daemonize(void);
 #define SLEEPTIME 1000
 #ifndef O_BINARY
 #define O_BINARY 0
@@ -188,7 +188,7 @@ unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nb
 int scanaddr(const unsigned char *s, unsigned long * ip, unsigned long * mask);
 int myinet_ntop(int af, void *src, char *dst, socklen_t size);
 extern struct nserver nservers[MAXNSERVERS];
-struct nserver authnserver;
+extern struct nserver authnserver;
 unsigned long getip(unsigned char *name);
 unsigned long getip46(int family, unsigned char *name,  struct sockaddr *sa);
 unsigned long myresolver(int, unsigned char *, unsigned char *);
@@ -233,7 +233,7 @@ void mschap(const unsigned char *win_password,
 struct hashtable;
 void hashadd(struct hashtable *ht, const unsigned char* name, unsigned char* value, time_t expires);
 
-void parsehost(int family, unsigned char *host, struct sockaddr *sa);
+int parsehost(int family, unsigned char *host, struct sockaddr *sa);
 int parsehostname(char *hostname, struct clientparam *param, unsigned short port);
 int parseusername(char *username, struct clientparam *param, int extpasswd);
 int parseconnusername(char *username, struct clientparam *param, int extpasswd, unsigned short port);

+ 8 - 4
src/proxymain.c

@@ -509,7 +509,7 @@ int MODULEMAINFUNC (int argc, char** argv){
 
  for (;;) {
 	for(;;){
-		while((conf.paused == srv.version && srv.childcount >= srv.maxchild)){
+		while((conf.paused == srv.paused && srv.childcount >= srv.maxchild)){
 			nlog++;			
 			if(!srv.silent && nlog > 5000) {
 				sprintf((char *)buf, "Warning: too many connected clients (%d/%d)", srv.childcount, srv.maxchild);
@@ -519,7 +519,7 @@ int MODULEMAINFUNC (int argc, char** argv){
 			usleep(SLEEPTIME);
 		}
 		if (iscbc) break;
-		if (conf.paused != srv.version) break;
+		if (conf.paused != srv.paused) break;
 		if (srv.fds.events & POLLIN) {
 			error = so._poll(&srv.fds, 1, 1000);
 		}
@@ -535,7 +535,7 @@ int MODULEMAINFUNC (int argc, char** argv){
 			break;
 		}
 	}
-	if((conf.paused != srv.version) || (error < 0)) break;
+	if((conf.paused != srv.paused) || (error < 0)) break;
 	error = 0;
 	if(!isudp){
 		size = sizeof(defparam.sincr);
@@ -710,8 +710,10 @@ int MODULEMAINFUNC (int argc, char** argv){
 void srvinit(struct srvparam * srv, struct clientparam *param){
 
  memset(srv, 0, sizeof(struct srvparam));
- srv->version = conf.paused;
+ srv->version = conf.version + 1;
+ srv->paused = conf.paused;
  srv->logfunc = conf.logfunc;
+ srv->noforce = conf.noforce;
  if(srv->logformat)myfree(srv->logformat);
  srv->logformat = conf.logformat? (unsigned char *)mystrdup((char *)conf.logformat) : NULL;
  srv->authfunc = conf.authfunc;
@@ -730,6 +732,8 @@ void srvinit(struct srvparam * srv, struct clientparam *param){
  srv->needuser = 1;
  memset(param, 0, sizeof(struct clientparam));
  param->srv = srv;
+ param->version = srv->version;
+ param->paused = srv->paused;
  param->remsock = param->clisock = param->ctrlsock = param->ctrlsocksrv = INVALID_SOCKET;
  *SAFAMILY(&param->req) = *SAFAMILY(&param->sinsl) = *SAFAMILY(&param->sinsr) = *SAFAMILY(&param->sincr) = *SAFAMILY(&param->sincl) = AF_INET;
  pthread_mutex_init(&srv->counter_mutex, NULL);

+ 1 - 1
src/smtpp.c

@@ -291,7 +291,7 @@ void * smtppchild(struct clientparam* param) {
 CLEANRET:
 
  if(param->hostname&&param->extusername) {
-	sprintf((char *)buf, "%.64s@%.128s%c%hu", param->extusername, param->hostname, *SAPORT(&param->sinsr)==25?0:':',ntohs(*SAPORT(&param->sinsr)));
+	sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, *SAPORT(&param->sinsr)==25?0:':',ntohs(*SAPORT(&param->sinsr)));
 	 (*param->srv->logfunc)(param, buf);
  }
  else (*param->srv->logfunc)(param, NULL);

+ 5 - 0
src/sockmap.c

@@ -68,6 +68,11 @@ int sockmap(struct clientparam * param, int timeo){
 
  while (!stop&&!conf.timetoexit){
 	sasize = sizeof(struct sockaddr_in);
+	if(param->version < conf.version){
+		if((res = (*param->srv->authfunc)(param)) && res != 2 && !param->srv->noforce) {return(res);}
+		param->paused = conf.paused;
+		param->version = conf.version;
+	}
 	if((param->maxtrafin64 && param->statssrv64 >= param->maxtrafin64) || (param->maxtrafout64 && param->statscli64 >= param->maxtrafout64)){
 		return (10);
 	}

+ 3 - 3
src/socks.c

@@ -120,8 +120,8 @@ void * sockschild(struct clientparam* param) {
 #ifndef NOIPV6
 		}
 #endif
-		if(SAISNULL(&param->req)) {
-			RETURN(421);
+		if(command == 1 && SAISNULL(&param->req)) {
+			RETURN(431);
 		}
 		myinet_ntop(*SAFAMILY(&param->sinsr), SAADDR(&param->sinsr), (char *)buf, 64);
 		break;
@@ -164,7 +164,7 @@ void * sockschild(struct clientparam* param) {
  }
 
  *SAPORT(&param->sinsr) = *SAPORT(&param->req) = port;
- if(command == 1 && !*SAPORT(&param->sinsr)) {RETURN(421);}
+ if(command == 1 && !*SAPORT(&param->sinsr)) {RETURN(461);}
  switch(command) { 
 	case 1:
 	 param->operation = CONNECT;

+ 6 - 3
src/structures.h

@@ -364,7 +364,7 @@ struct srvparam {
 	SOCKET srvsock, cbsock;
 	int childcount;
 	int maxchild;
-	int version;
+	int paused, version;
 	int singlepacket;
 	int usentlm;
 	int needuser;
@@ -373,6 +373,7 @@ struct srvparam {
 	int nfilters, nreqfilters, nhdrfilterscli, nhdrfilterssrv, npredatfilters, ndatfilterscli, ndatfilterssrv;
 	int family;
 	int stacksize;
+	int noforce;
 	unsigned bufsize;
 	unsigned logdumpsrv, logdumpcli;
 #ifndef NOIPV6
@@ -440,7 +441,9 @@ struct clientparam {
 		nolongdatfilter,
 		nooverwritefilter,
 		transparent,
-		chunked;
+		chunked,
+		paused,
+		version;
 
 	unsigned char 	*hostname,
 			*username,
@@ -494,7 +497,7 @@ struct extparam {
 	struct trafcount * trafcounter;
 	struct srvparam *services;
 	int stacksize, threadinit, counterd, haveerror, rotate, paused, archiverc,
-		demon, maxchild, singlepacket, needreload, timetoexit;
+		demon, maxchild, singlepacket, needreload, timetoexit, version, noforce;
 	int authcachetype, authcachetime;
 	int filtermaxsize;
 	unsigned char *logname, **archiver;