diff -Naur frox-0.7.14-orig/PacketAlarm.txt frox-0.7.14/PacketAlarm.txt
--- frox-0.7.14-orig/PacketAlarm.txt	1970-01-01 01:00:00.000000000 +0100
+++ frox-0.7.14/PacketAlarm.txt	2008-02-13 13:56:15.000000000 +0100
@@ -0,0 +1,29 @@
+
+Erweiterungen des Frox FTP Proxies für PacketAlarm
+==================================================
+
+
+1. Proxy Authentication
+-----------------------
+
+Die ACLs wurden so erweitert, dass neben Source-IP, Destination-IP und
+Destination-Port eine Proxy-Authentifizierung definiert werden kann. Dabei
+wurde die ACL Syntax gegenüber der ursprünglichen Syntax
+
+	ACL Allow|Deny SRC - DST [PORTS]
+
+wie folgt erweitert.
+
+	ACL Allow|Deny|{Auth Group-Name} SRC - DST [PORTS]
+
+Bei der Angabe der Options 'Deny' muß zusätzlich die Gruppe definiert werden,
+zu der der Proxy-Benutzer gehören muß. Wird nur ein gültiger Benutzer
+erwartet, so wird dies durch die Pseudo-Gruppe '**ValidUser**' definiert.
+Sonst muß der Name der Gruppe angegeben werden, wie er in der PacketAlarm
+Datenbank unter user_group.name definiert wurde.
+
+Im FTP-Client wird der Proxy-User und das Paßwort im 'Checkpoint' Format
+definiert
+
+	User:		remote-user@proxy-user@remote-host[:port]
+	Passwort:	remote-password@proxy-password
diff -Naur frox-0.7.14-orig/src/common.h frox-0.7.14/src/common.h
--- frox-0.7.14-orig/src/common.h	2004-05-09 23:55:23.000000000 +0200
+++ frox-0.7.14/src/common.h	2008-02-13 13:57:36.000000000 +0100
@@ -23,6 +23,7 @@
 #ifndef COMMON_H
 #define COMMON_H		/*+ To stop multiple inclusions. + */
 
+#include <pa/stat.h>
 #include "config.h"
 
 #include <stdio.h>
@@ -63,6 +64,7 @@
 #endif				/* TIME_WITH_SYS_TIME */
 
 #include "sstr.h"
+#include "pa/spaced.h"
 
 /* Defines */
 #ifdef DEBUG
@@ -161,6 +163,9 @@
 	int server_listen;   /*fd we are listening on */
 	int client_listen;
 
+	unsigned int bytes_rx;
+	unsigned int bytes_tx;
+
 	struct cmd_struct *cmd_arrays[NUM_CMD_ARRAYS];
 
 /*Details related to the current transfer. Mainly for logging*/
@@ -172,7 +177,11 @@
 	int cached; /* 0=cache miss, 1=cache hit */
 	int upload;
 	int anonymous;
+	int filesize;
+	pasd_handle_t *spacedaemon;     /* Handle for PA-Spacedaemon */
 
+	int do_auth;
+	sstr *proxy_user;
 } session_info;
 
 #include "configs.h"
@@ -184,4 +193,11 @@
 session_info *info;
 extern pid_t cmgrpid, tdatapid;
 
+extern struct pa_stat_struct {
+	pa_stat_counter_t *total;
+	pa_stat_counter_t *infected;
+	pa_stat_counter_t *bytes_in;
+	pa_stat_counter_t *bytes_out;
+} pa_stat;
+
 #endif				/* COMMON_H */
diff -Naur frox-0.7.14-orig/src/configs.c frox-0.7.14/src/configs.c
--- frox-0.7.14-orig/src/configs.c	2004-05-09 23:56:03.000000000 +0200
+++ frox-0.7.14/src/configs.c	2008-02-13 13:56:22.000000000 +0100
@@ -32,6 +32,7 @@
 #include <pwd.h>
 #include <grp.h>
 #include <syslog.h>
+#include <pa/authproxy.h>
 
 #include "common.h"
 
@@ -111,7 +112,12 @@
   {"VirusScanner",    STRING,  &config.vscanner,    '\0', TRUE, FALSE},
   {"VSOK",            INT,     &config.vscanok,     '\0', TRUE, FALSE},
   {"VSProgressMsgs",  INT,     &config.vscanpm,     '\0', TRUE, FALSE},
+  {"VSDir",           STRING,  &config.vscandir,    '\0', TRUE, FALSE},
 #endif
+  {"banner",          STRING,  &config.banner,      '\0', TRUE, FALSE},
+  {"MaxFileSize",     INT,     &config.maxfilesize, '\0', TRUE, FALSE},
+  {"PassFileSize",    BOOL,    &config.passbigfile, '\0', TRUE, FALSE},
+  {"UseRealSize",     BOOL,    &config.userealsize, '\0', TRUE, FALSE},
   {0, 0, 0, 0, 0, 0}
 };
 
@@ -314,7 +320,12 @@
 	config.vscanner = NULL;
 	config.vscanok = 0;
 	config.vscanpm = 0;
+	config.vscandir = "/var/spool/packetalarm/vscan";
 #endif
+	config.banner = "PacketAlarm\040FTP\040Proxy.";
+	config.maxfilesize = -1;
+	config.passbigfile = TRUE;
+	config.userealsize = FALSE;
 
 	sstr_free(tmp);
 }
@@ -597,6 +608,7 @@
 	struct acl_item item = { };
 
 	tok = sstr_init(0);
+	item.group = strdup("");
 
 	sstr_token(str, tok, " \t\n", 0);
 
@@ -604,9 +616,16 @@
 		item.action = ALLOW;
 	else if (!sstr_casecmp2(tok, "Deny"))
 		item.action = DENY;
+	else if (!sstr_casecmp2(tok, "Auth"))
+		item.action = AUTH;
 	else
 		return (-1);
 
+	if(item.action == AUTH)
+	{
+		sstr_token(str, tok, " \t\n", 0);
+		item.group = strdup(sstr_buf(tok));
+	}
 	sstr_token(str, tok, " -\t\n", 0);
 	item.src = strdup(sstr_buf(tok));
 	sstr_token(str, tok, " \t\n", 0);
@@ -622,6 +641,55 @@
 	acls->num++;
 	return (0);
 }
+int config_connectionok_auth(struct sockaddr_in *src, struct sockaddr_in *dst)
+{
+	int i;
+	char *user;
+
+	info->do_auth = 0;
+	for (i = 0; i < config.acls.num; i++)
+	{
+		struct acl_item *item;
+
+		item = config.acls.list + i;
+		if(!match_acl(item, src, dst))
+			continue;
+		if(item->action == DENY)
+		{
+			return(FALSE);
+		}
+		if(item->action == ALLOW)
+		{
+			config_change(src, dst);
+			return(TRUE);
+		}
+		if(item->action == AUTH &&
+		  strcmp(item->group, "**ValidUser**") != 0)
+		{
+			int res;
+			char *msg;
+
+			info->do_auth = 1;
+
+			res = pa_auth_group("FTP", item->group,
+			  sstr_buf(info->proxy_user), &msg);
+			if(res == -1)
+			{
+				write_log(ERROR, "pa-authproxy error: %s", msg);
+				die(ERROR, "pa-authproxy failed", 530,
+				  "Login incorrect.", 0);
+			}
+			free(msg);
+			if(res == 0)
+				return(FALSE);
+		}
+		info->do_auth = 1;
+		config_change(src, dst);
+		return(TRUE);
+	}
+	return (FALSE);
+}
+
 
 /* This is quite horrible, but it does seem to work... We make a
    shallow copy of config, and then recall read_config. config will
diff -Naur frox-0.7.14-orig/src/configs.c.in frox-0.7.14/src/configs.c.in
--- frox-0.7.14-orig/src/configs.c.in	2004-05-09 23:55:23.000000000 +0200
+++ frox-0.7.14/src/configs.c.in	2008-02-13 13:56:15.000000000 +0100
@@ -29,6 +29,7 @@
 #include <pwd.h>
 #include <grp.h>
 #include <syslog.h>
+#include <pa/authproxy.h>
 
 #include "common.h"
 
@@ -508,6 +509,7 @@
 	struct acl_item item = { };
 
 	tok = sstr_init(0);
+	item.group = strdup("");
 
 	sstr_token(str, tok, " \t\n", 0);
 
@@ -515,9 +517,16 @@
 		item.action = ALLOW;
 	else if (!sstr_casecmp2(tok, "Deny"))
 		item.action = DENY;
+	else if (!sstr_casecmp2(tok, "Auth"))
+		item.action = AUTH;
 	else
 		return (-1);
 
+	if(item.action == AUTH)
+	{
+		sstr_token(str, tok, " \t\n", 0);
+		item.group = strdup(sstr_buf(tok));
+	}
 	sstr_token(str, tok, " -\t\n", 0);
 	item.src = strdup(sstr_buf(tok));
 	sstr_token(str, tok, " \t\n", 0);
@@ -533,6 +542,55 @@
 	acls->num++;
 	return (0);
 }
+int config_connectionok_auth(struct sockaddr_in *src, struct sockaddr_in *dst)
+{
+	int i;
+	char *user;
+
+	info->do_auth = 0;
+	for (i = 0; i < config.acls.num; i++)
+	{
+		struct acl_item *item;
+
+		item = config.acls.list + i;
+		if(!match_acl(item, src, dst))
+			continue;
+		if(item->action == DENY)
+		{
+			return(FALSE);
+		}
+		if(item->action == ALLOW)
+		{
+			config_change(src, dst);
+			return(TRUE);
+		}
+		if(item->action == AUTH &&
+		  strcmp(item->group, "**ValidUser**") != 0)
+		{
+			int res;
+			char *msg;
+
+			info->do_auth = 1;
+
+			res = pa_auth_group("FTP", item->group,
+			  sstr_buf(info->proxy_user), &msg);
+			if(res == -1)
+			{
+				write_log(ERROR, "pa-authproxy error: %s", msg);
+				die(ERROR, "pa-authproxy failed", 530,
+				  "Login incorrect.", 0);
+			}
+			free(msg);
+			if(res == 0)
+				return(FALSE);
+		}
+		info->do_auth = 1;
+		config_change(src, dst);
+		return(TRUE);
+	}
+	return (FALSE);
+}
+
 
 /* This is quite horrible, but it does seem to work... We make a
    shallow copy of config, and then recall read_config. config will
diff -Naur frox-0.7.14-orig/src/configs.h frox-0.7.14/src/configs.h
--- frox-0.7.14-orig/src/configs.h	2004-05-09 23:56:03.000000000 +0200
+++ frox-0.7.14/src/configs.h	2008-02-13 13:56:22.000000000 +0100
@@ -39,11 +39,12 @@
 int config_pasvok(struct sockaddr_in *addr);
 
 struct acl_item {
-	enum { ALLOW, DENY } action;
+	enum { ALLOW, DENY, AUTH } action;
 	/*struct in_addr src, smsk;*/
 	/*struct in_addr dst, dmsk;*/
 	char *src, *dst;
 	u_int16_t *ntp_ports;
+	char *group;
 };
 
 
@@ -112,6 +113,11 @@
 	char * vscanner;
 	int vscanok;
 	int vscanpm;
+	char * vscandir;
+	char * banner;
+	int maxfilesize;
+	int passbigfile;
+	int userealsize;
 
 	struct sockaddr_in listen_address;
 	uid_t uid;
diff -Naur frox-0.7.14-orig/src/configs.h.in frox-0.7.14/src/configs.h.in
--- frox-0.7.14-orig/src/configs.h.in	2004-05-09 23:55:23.000000000 +0200
+++ frox-0.7.14/src/configs.h.in	2008-02-13 13:56:15.000000000 +0100
@@ -36,11 +36,12 @@
 int config_pasvok(struct sockaddr_in *addr);
 
 struct acl_item {
-	enum { ALLOW, DENY } action;
+	enum { ALLOW, DENY, AUTH } action;
 	/*struct in_addr src, smsk;*/
 	/*struct in_addr dst, dmsk;*/
 	char *src, *dst;
 	u_int16_t *ntp_ports;
+	char *group;
 };
 
 
diff -Naur frox-0.7.14-orig/src/configs.tpl frox-0.7.14/src/configs.tpl
--- frox-0.7.14-orig/src/configs.tpl	2004-05-09 23:55:23.000000000 +0200
+++ frox-0.7.14/src/configs.tpl	2008-02-13 13:56:22.000000000 +0100
@@ -68,7 +68,12 @@
   VirusScanner    STRING   vscanner     - TRUE  FALSE NULL
   VSOK            INT      vscanok      - TRUE  FALSE 0
   VSProgressMsgs  INT      vscanpm      - TRUE  FALSE 0
+  VSDir           STRING   vscandir     - TRUE  FALSE "/var/spool/packetalarm/vscan"
 endif
+  banner          STRING   banner       - TRUE  FALSE "PacketAlarm\040FTP\040Proxy."
+  MaxFileSize     INT      maxfilesize  - TRUE  FALSE -1
+  PassFileSize    BOOL     passbigfile  - TRUE  FALSE TRUE
+  UseRealSize     BOOL     userealsize  - TRUE  FALSE FALSE
 
 # Where an option needs further processing (eg. group --> gid) then
 # this is written manually in process_opts() in configs.c. Any extra
diff -Naur frox-0.7.14-orig/src/control.c frox-0.7.14/src/control.c
--- frox-0.7.14-orig/src/control.c	2004-05-09 23:55:23.000000000 +0200
+++ frox-0.7.14/src/control.c	2008-02-13 13:56:22.000000000 +0100
@@ -101,10 +101,20 @@
 	resolve_addr(&info->final_server_address.sin_addr,
 		     info->server_name);
 
-	if (!config_connectionok(&info->client_control.address,
-				 &info->final_server_address))
-		die(ATTACK, "Denied by ACLs.", 501, "Connection denied. Bye",
-		    0);
+	if(sstr_cmp2(info->proxy_user, "") == 0)
+	{
+		if (!config_connectionok(&info->client_control.address,
+					 &info->final_server_address))
+			die(ATTACK, "Denied by ACLs.", 501,
+			  "Connection denied. Bye", 0);
+	}
+	else
+	{
+		if (!config_connectionok_auth(&info->client_control.address,
+					 &info->final_server_address))
+			die(ATTACK, "Denied by ACLs.", 501,
+			  "Connection denied. Bye", 0);
+	}
 
 	write_log(VERBOSE, "Connecting to server...");
 
@@ -168,6 +178,8 @@
 	get_orig_dest(fd, &i->server_control.address);
 	i->apparent_server_address = i->server_control.address;
 
+	i->filesize = 0;
+	i->spacedaemon = NULL;
 	return i;
 }
 
@@ -233,11 +245,41 @@
 void parse_client_cmd(sstr * cmd, sstr * arg)
 {
 	struct cmd_struct *p;
-	int i;
+	int i, code;
+	sstr *msg;
 
 	if(!ccp_allowcmd(cmd, arg)) return;
 	sstr_cpy(info->last_command,cmd);
 
+	/* additionally intercept RETR command, but only if virus scanning is
+	 * active and a maximal filesize has been set.  Immediately abort, if
+	 * the server already tells us that the file will be too big.
+	 * Otherwise reserve appropriate space from the space daemon */
+	if (strcmp(sstr_buf(cmd),"RETR") == 0
+	  && config.vscanner && config.maxfilesize > 0) {
+		send_ccommand("SIZE", sstr_buf(arg));
+		get_message(&code, &msg);
+		if (code / 100 == 2) {
+			info->filesize = sstr_atoi(msg);
+			if(info->filesize > config.maxfilesize
+			  && !config.passbigfile) {
+				write_log(VERBOSE, "File %s is too big (%d >= %d)",
+				  sstr_buf(arg), info->filesize, config.maxfilesize);
+				send_cmessage(451, "File is too large. Aborting");
+				return;
+			}
+		} else {
+			info->filesize = 0;
+		}
+		/* Allocate space from SpaceDaemon */
+		if(! (info->spacedaemon = pasd_request(pasd_client_type_ftp,
+		  config.userealsize ? info->filesize : config.maxfilesize))) {
+			write_log(VERBOSE, "PA-SpaceDaemon returned: %s",
+			  pasd_errstr);
+			send_cmessage(451, "Internal Error");
+			return;
+		}
+	}
 	for(i=0;i<NUM_CMD_ARRAYS;i++) {
 		if(!info->cmd_arrays[i]) continue;
 		for (p = info->cmd_arrays[i]; p && p->cmd; p++) {
diff -Naur frox-0.7.14-orig/src/data.c frox-0.7.14/src/data.c
--- frox-0.7.14-orig/src/data.c	2004-05-09 23:55:23.000000000 +0200
+++ frox-0.7.14/src/data.c	2008-02-13 13:57:43.000000000 +0100
@@ -230,6 +230,7 @@
 		closecd();
 		return;
 	}
+	info->bytes_tx += i;
 	if(config.maxulrate) bwlimit(i, config.maxulrate);
  	if(info->state!=UPLOAD) sstr_empty(info->server_data.buf);
 
@@ -260,6 +261,7 @@
 		if(!vscan_switchover()) closesd();
 		return;
 	}
+	info->bytes_rx += i;
 	if(dlrate) bwlimit(i, dlrate);
  	if(info->state!=DOWNLOAD) sstr_empty(info->client_data.buf);
 
diff -Naur frox-0.7.14-orig/src/ftp-cmds.c frox-0.7.14/src/ftp-cmds.c
--- frox-0.7.14-orig/src/ftp-cmds.c	2004-05-09 23:55:23.000000000 +0200
+++ frox-0.7.14/src/ftp-cmds.c	2008-02-13 13:57:50.000000000 +0100
@@ -22,6 +22,7 @@
   ***************************************/
 
 #include <fcntl.h>
+#include <pa/authproxy.h>
 #include "ftp-cmds.h"
 #include "control.h"
 #include "data.h"
@@ -120,6 +121,39 @@
 
 void save_pass(sstr * cmd, sstr * arg)
 {
+	int i;
+
+	if(info->do_auth && config.ntp)
+	{
+		sstr *proxyPass;
+		int res;
+		char *msg;
+
+		proxyPass = sstr_init(0);
+		for(i=sstr_len(arg)-1;i>=0;i--)
+			if(sstr_getchar(arg, i)=='@') break;
+		if(i > 0)
+		{
+			sstr_split(arg, proxyPass, i, sstr_len(arg) - i);
+			sstr_strip(proxyPass, "@");
+		}
+		write_log(VERBOSE, "proxy pass: %s", sstr_buf(proxyPass));
+		res = pa_auth_passwd("FTP", sstr_buf(info->proxy_user),
+		  sstr_buf(proxyPass), &msg);
+		if(res == 0)
+		{
+			die(ATTACK, "Invalid proxy authentication",
+			  530, "Login incorrect.", 0);
+		}
+		else if(res == -1)
+		{
+			write_log(ERROR, "pa-authproxy error: %s", msg);
+			die(ERROR, "pa-authproxy failed", 530,
+			  "Login incorrect.", 0);
+		}
+		free(msg);
+		sstr_free(proxyPass);
+	}
 	sstr_cpy(info->passwd, arg);
 	send_command(cmd, arg);
 }
@@ -384,6 +418,8 @@
 	send_command(cmd, arg);
 
 	if(!sstr_casecmp2(cmd, "RETR"))
-		vscan_new(0);
+		vscan_new(info->filesize);
+	info->bytes_rx = 0;
+	info->bytes_tx = 0;
 }
 
diff -Naur frox-0.7.14-orig/src/main.c frox-0.7.14/src/main.c
--- frox-0.7.14-orig/src/main.c	2004-05-09 23:55:23.000000000 +0200
+++ frox-0.7.14/src/main.c	2008-02-13 13:57:57.000000000 +0100
@@ -30,6 +30,7 @@
 #include <netdb.h>
 #include <time.h>
 #include <stdlib.h>
+#include <libgen.h>
 
 #include "vscan.h"
 #include "control.h"
@@ -46,7 +47,7 @@
 
 void daemonify(void);
 void write_pidfile(void);
-int init_log(void);
+int init_log(char *progname);
 
 static RETSIGTYPE signal_handle(int signo);
 static int listen_sockfd, noforks = 0;
@@ -62,11 +63,22 @@
 void add_client(pid_t, struct sockaddr_in client);
 void rm_client(pid_t pid);
 
+struct pa_stat_struct pa_stat;
+
 int main(int argc, char *argv[])
 {
 	struct sockaddr_in listen_address;
 	int i;
+	char *progname, *tmp;
 
+	pa_stat.total = pa_stat_getcnt("ftptotal");
+	pa_stat.infected = pa_stat_getcnt("ftpvirus");
+	pa_stat.bytes_in = pa_stat_getcnt("ftpbytes_in");
+	pa_stat.bytes_out = pa_stat_getcnt("ftpbytes_out");
+
+	tmp = strdup(argv[0]);
+	progname = strdup(basename(tmp));
+	free(tmp);
 	sstr_setopts(sstrerr, 0);
 	info=NULL;
 	process_cmdline(argc, argv);
@@ -101,7 +113,7 @@
 	if(config.maxforksph)
 		clients=malloc(sizeof(struct client_info)*config.maxforks);
 
-	init_log();
+	init_log(progname);
 	ftpcmds_init();
 	
 	signal(SIGCHLD, signal_handle);
@@ -266,7 +278,7 @@
 }
 
 
-int init_log(void)
+int init_log(char *progname)
 {
 	time_t t;
 	
@@ -281,7 +293,7 @@
 			return (-1);
 		}
 	}
-	openlog("frox", LOG_PID | LOG_CONS | LOG_NDELAY, LOG_DAEMON);
+	openlog(progname, LOG_PID | LOG_CONS | LOG_NDELAY, LOG_DAEMON);
 
 	/* These are necessary so that syslog() and ctime() can do their
 	 * initialisation (specifically timezone stuff) before we chroot()
diff -Naur frox-0.7.14-orig/src/Makefile.in frox-0.7.14/src/Makefile.in
--- frox-0.7.14-orig/src/Makefile.in	2004-05-09 23:56:17.000000000 +0200
+++ frox-0.7.14/src/Makefile.in	2008-02-13 13:56:15.000000000 +0100
@@ -87,7 +87,7 @@
 sbin_PROGRAMS = frox
 frox_SOURCES = configs.h configs.c data.c main.c misc.c control.c ftp-cmds.c common.h control.h data.h ftp-cmds.h cache.h ccp.h misc.h ntp.h os.h vscan.h
 BUILT_SOURCES = configs.c configs.h
-frox_LDADD = @VSCAN_STUFF@ @CACHE_STUFF@ @HCACHE_STUFF@ @LCACHE_STUFF@ @NTP_STUFF@ @CCP_STUFF@ @TD_STUFF@ @HOST_FILE@ -lsstr @LIBIPTC@ @ARCH_LIBS@
+frox_LDADD = @VSCAN_STUFF@ @CACHE_STUFF@ @HCACHE_STUFF@ @LCACHE_STUFF@ @NTP_STUFF@ @CCP_STUFF@ @TD_STUFF@ @HOST_FILE@ -lsstr @LIBIPTC@ @ARCH_LIBS@ -lpaiface
 
 frox_DEPENDENCIES = @VSCAN_STUFF@ @CACHE_STUFF@ @HCACHE_STUFF@ @LCACHE_STUFF@ @NTP_STUFF@ @CCP_STUFF@ @TD_STUFF@ @HOST_FILE@
 
diff -Naur frox-0.7.14-orig/src/misc.c frox-0.7.14/src/misc.c
--- frox-0.7.14-orig/src/misc.c	2004-05-09 23:55:23.000000000 +0200
+++ frox-0.7.14/src/misc.c	2008-02-13 13:58:05.000000000 +0100
@@ -47,8 +47,11 @@
 int listen_on_socket(struct sockaddr_in *listen_address, int portrange[2])
 {
 	int sockfd;
+	int i;
 
 	sockfd = socket(AF_INET, SOCK_STREAM, 0);
+	i = 1;
+	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
 
 	if (!portrange) {
 		if (bind(sockfd, (struct sockaddr *) listen_address,
@@ -259,6 +262,13 @@
   scanned) */
 void xfer_log(void)
 {
+	if(config.ntp) {
+		pa_stat_inc(pa_stat.total);
+		if(info->virus == 1)
+			pa_stat_inc(pa_stat.infected);
+		pa_stat_add(pa_stat.bytes_out, info->bytes_tx);
+		pa_stat_add(pa_stat.bytes_in, info->bytes_rx / 2);
+	}
 	if(!info->needs_logging) return;
 	if(!config.xferlogging) return;
 	write_log(-1, "%s ftp://%s@%s/%s%s %s%s",
@@ -270,6 +280,9 @@
 		  info->virus == -1 ? "" : 
 		  (info->virus ? " VIRUS_INFECTED" : " VIRUS_CLEAN"),
 		  info->cached ? " CACHE_HIT" : "");
+	/* Release Space from SpaceDaemon */
+	if(info->spacedaemon != NULL)
+		pasd_release(info->spacedaemon);
 	info->needs_logging = FALSE;
 }
 
@@ -388,6 +401,10 @@
 	if(message) send_cmessage(mcode, message);
 	if(lmessage) write_log(loglevel, lmessage);
 	write_log(INFO, "Closing session");
+	//FIXME
+	write_log(INFO, "Closing session to server %s", sstr_buf(info->server_name));
+	if(info->spacedaemon != NULL)
+		pasd_release(info->spacedaemon);
 	kill_procs();
 	vscan_abort();
 	exit(exitcode);
diff -Naur frox-0.7.14-orig/src/ntp.c frox-0.7.14/src/ntp.c
--- frox-0.7.14-orig/src/ntp.c	2004-05-09 23:55:23.000000000 +0200
+++ frox-0.7.14/src/ntp.c	2008-02-13 13:56:15.000000000 +0100
@@ -54,6 +54,40 @@
 static sstr *user = NULL;
 static int working = FALSE;
 
+
+void stripProxyUser(sstr *arg)
+{
+	sstr *host, *remoteUser, *temp;
+	int i, j;
+
+	info->proxy_user = sstr_init(0);
+	write_log(VERBOSE, "DEBUG: %s", sstr_buf(arg));
+	for(i=sstr_len(arg)-1;i>=0;i--)
+		if(sstr_getchar(arg, i)=='@') break;
+	for(j = i - 1; j >= 0; j--)
+		if(sstr_getchar(arg, j)=='@') break;
+	if(i < 0 || j < 0)
+	{
+		write_log(VERBOSE, "no proxy user specified");
+		return;
+	}
+	remoteUser = sstr_init(0);
+	temp = sstr_init(0);
+	sstr_split(arg, temp, 0, i);
+	host = sstr_dup(arg);
+	sstr_strip(host, "@");
+	sstr_split(temp, remoteUser, 0, j);
+	sstr_strip(temp, "@");
+	sstr_cpy(arg, remoteUser);
+	sstr_ncat2(arg, "@", 1);
+	sstr_cat(arg, host);
+	write_log(VERBOSE, "proxy user -> %s", sstr_buf(temp));
+	sstr_cpy(info->proxy_user, temp);
+	sstr_free(host);
+	sstr_free(remoteUser);
+	sstr_free(temp);
+}
+
 /* ------------------------------------------------------------- **
 **  Called before the proxy connects to the server.
 **  
@@ -63,6 +97,7 @@
 {
 	sstr *cmd, *arg;
 	struct sockaddr_in tmp;
+	char banner[500];
 
 	if (!config.ntp)
 		return;
@@ -80,8 +115,9 @@
 	if (!user)
 		user = sstr_init(MAX_LINE_LEN);
 
-	send_cmessage(220,
-		      "Frox transparent ftp proxy. Login with username[@host[:port]]");
+	snprintf(banner, sizeof(banner),
+	  "%s Login with username[@host[:port]]", config.banner);
+	send_cmessage(220, banner);
 	do {
 		get_command(&cmd, &arg);
 		if(!sstr_casecmp2(cmd, "QUIT")) 
@@ -90,6 +126,7 @@
 			send_cmessage(530, "Please login with USER first");
 	} while (sstr_casecmp2(cmd, "USER"));
 
+	stripProxyUser(arg);
 	parseuser(arg);
 }
 
diff -Naur frox-0.7.14-orig/src/vscan.c frox-0.7.14/src/vscan.c
--- frox-0.7.14-orig/src/vscan.c	2004-05-09 23:55:23.000000000 +0200
+++ frox-0.7.14/src/vscan.c	2008-02-13 13:56:22.000000000 +0100
@@ -61,6 +61,7 @@
 static int fd = -1;
 static char scanfile[BUF_LEN];
 static time_t lastprog;
+static char vscanInfo[1000];
 
 int vscan_scan(void);
 
@@ -81,20 +82,25 @@
 		if(*p==0) break;
 		*p++=0;
 		if(!strcmp(argv[i], "%s")) argv[i]=scanfile;
+		if(!strcmp(argv[i], "%i")) argv[i]=vscanInfo;
 	}
 	argv[i]=NULL;
 
-	if(make_tmpdir()==-1) return (-1);
-
-	snprintf(scanfile, BUF_LEN, "%s/tmp/VS_%d", config.chroot, getpid());
+	snprintf(scanfile, BUF_LEN, "%s/VS_%d", config.vscandir, getpid());
 	write_log(VERBOSE, "VS: Virus scanner temp file is %s", scanfile);
 	return 0;
 }
 
 void vscan_new(int sz)
 {
-	if (!config.vscanner)
-		return;
+	/* We need to decide here, if a file is to be scanned at all.
+	 * If no virus scanner is configured the file is not scanned.
+	 * If a maximum file size has been set and the reported size is bigger
+	 * than the file size, the file is not scanned either. This can only
+	 * happen, if passbigfile is TRUE, otherwise we would have aborted
+	 * the transfer already */
+	if (!config.vscanner) return;
+	if (config.maxfilesize > 0 && sz > config.maxfilesize) return;
 	fd = creat(scanfile, S_IRUSR | S_IWUSR);
 	status = INCOMING;
 	expected_reply = STARTING;
@@ -112,6 +118,15 @@
 		return;
 	if (status == INCOMING) {
 		tsize += sstr_len(inc);
+		/* If passbigfile is TRUE but the actual size is bigger than
+		 * maxfilesize, we can only reach this code if the server lied
+		 * about the file size or does not implement SIZE. That is a
+		 * current limitation of passbigfile */
+		if(config.maxfilesize > 0 && tsize > config.maxfilesize) {
+			write_log(VERBOSE, "File %s is too big (%d >= %d)",
+			  sstr_buf(info->filename), info->filesize, config.maxfilesize);
+			send_cmessage(451, "File is too large. Aborting");
+		}
 		sstr_write(fd, inc, 0);
 		sstr_empty(inc);
 		time(&tmp);
@@ -223,6 +238,21 @@
 	return (FALSE);
 }
 
+
+void vscan_info(void)
+{
+	char src[16];
+	char dst[16];
+
+	strcpy(src, inet_ntoa(info->client_control.address.sin_addr));
+	strcpy(dst, inet_ntoa(info->server_control.address.sin_addr));
+	snprintf(vscanInfo, sizeof(vscanInfo),
+	  "Client: %s, Server: %s, File: /%s%s", src, dst,
+	  sstr_buf(info->strictpath), sstr_buf(info->filename));
+
+}
+
+
 int vscan_scan(void)
 {
 	int i;
@@ -230,6 +260,7 @@
 	write_log(VERBOSE, "VS: Now scanning file");
 	if(config.vscanpm)
 		send_cmessage(0, "150-Scanning file for viruses");
+	vscan_info();
 
 	switch(fork()){
 	case 0: /*Child*/

