Browse Source

added patch based on http://sftplogging.sf.net/ which allows controlled umask-ing and controls chown/chmod in SFTP sessions

Christoph Schug 21 years ago
parent
commit
5aa25c042f
2 changed files with 727 additions and 10 deletions
  1. 712 0
      openssh/openssh.patch.sftplogging
  2. 15 10
      openssh/openssh.spec

+ 712 - 0
openssh/openssh.patch.sftplogging

@@ -0,0 +1,712 @@
+diff -wur openssh-3.8p1.orig/servconf.c openssh-3.8p1/servconf.c
+--- openssh-3.8p1.orig/servconf.c	2004-01-23 12:03:10.000000000 +0100
++++ openssh-3.8p1/servconf.c	2004-03-29 10:44:26.000000000 +0200
+@@ -102,6 +102,15 @@
+ 	options->authorized_keys_file = NULL;
+ 	options->authorized_keys_file2 = NULL;
+ 
++	options->log_sftp = LOG_SFTP_NOT_SET;
++        options->sftp_log_facility = SYSLOG_FACILITY_NOT_SET;
++        options->sftp_log_level = SYSLOG_LEVEL_NOT_SET;
++
++	memset(options->sftp_umask, 0, SFTP_UMASK_LENGTH);
++
++	options->sftp_permit_chmod = SFTP_PERMIT_NOT_SET;
++	options->sftp_permit_chown = SFTP_PERMIT_NOT_SET;
++
+ 	/* Needs to be accessable in many places */
+ 	use_privsep = -1;
+ }
+@@ -228,6 +237,24 @@
+ 	if (options->authorized_keys_file == NULL)
+ 		options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
+ 
++	/* Turn sftp-server logging off by default */
++	if (options->log_sftp == LOG_SFTP_NOT_SET)
++		options->log_sftp = LOG_SFTP_NO;
++        if (options->sftp_log_facility == SYSLOG_FACILITY_NOT_SET)
++                options->sftp_log_facility = SYSLOG_FACILITY_AUTH;
++        if (options->sftp_log_level == SYSLOG_LEVEL_NOT_SET)
++                options->sftp_log_level = SYSLOG_LEVEL_INFO;
++
++	/* Don't set sftp-server umask */
++	if (!options->sftp_umask)
++		memset(options->sftp_umask, 0, SFTP_UMASK_LENGTH);
++
++	/* allow sftp client to issue chmod, chown / chgrp commands */
++	if (options->sftp_permit_chmod == SFTP_PERMIT_NOT_SET)
++		options->sftp_permit_chmod = SFTP_PERMIT_YES;
++	if (options->sftp_permit_chown == SFTP_PERMIT_NOT_SET)
++		options->sftp_permit_chown = SFTP_PERMIT_YES;
++
+ 	/* Turn privilege separation on by default */
+ 	if (use_privsep == -1)
+ 		use_privsep = 1;
+@@ -268,6 +295,9 @@
+ 	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
+ 	sGssAuthentication, sGssCleanupCreds,
+ 	sUsePrivilegeSeparation,
++	sLogSftp, sSftpLogFacility, sSftpLogLevel,
++	sSftpUmask,
++	sSftpPermitChown, sSftpPermitChmod,
+ 	sDeprecated, sUnsupported
+ } ServerOpCodes;
+ 
+@@ -366,6 +396,12 @@
+ 	{ "authorizedkeysfile", sAuthorizedKeysFile },
+ 	{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
+ 	{ "useprivilegeseparation", sUsePrivilegeSeparation},
++	{ "logsftp", sLogSftp},
++	{ "sftplogfacility", sSftpLogFacility},
++	{ "sftploglevel", sSftpLogLevel},
++	{ "sftpumask", sSftpUmask},
++	{ "sftppermitchmod", sSftpPermitChmod},
++	{ "sftppermitchown", sSftpPermitChown},
+ 	{ NULL, sBadOption }
+ };
+ 
+@@ -431,6 +467,8 @@
+ 	char *cp, **charptr, *arg, *p;
+ 	int *intptr, value, i, n;
+ 	ServerOpCodes opcode;
++	unsigned int umaskvalue = 0;
++	char *umaskptr;
+ 
+ 	cp = line;
+ 	arg = strdelim(&cp);
+@@ -871,6 +909,58 @@
+ 	case sBanner:
+ 		charptr = &options->banner;
+ 		goto parse_filename;
++
++        case sLogSftp:
++                intptr = &options->log_sftp;
++                goto parse_flag;
++
++        case sSftpLogFacility:
++                intptr = (int *) &options->sftp_log_facility;
++                arg = strdelim(&cp);
++                value = log_facility_number(arg);
++                if (value == SYSLOG_FACILITY_NOT_SET)
++                        fatal("%.200s line %d: unsupported log facility '%s'",
++                            filename, linenum, arg ? arg : "<NONE>");
++                if (*intptr == -1)
++                        *intptr = (SyslogFacility) value;
++                break;
++
++        case sSftpLogLevel:
++                intptr = (int *) &options->sftp_log_level;
++                arg = strdelim(&cp);
++                value = log_level_number(arg);
++                if (value == SYSLOG_LEVEL_NOT_SET)
++                        fatal("%.200s line %d: unsupported log level '%s'",
++                            filename, linenum, arg ? arg : "<NONE>");
++                if (*intptr == -1)
++                        *intptr = (LogLevel) value;
++                break;
++
++        case sSftpUmask:
++                arg = strdelim(&cp);
++		umaskptr = arg;
++                while (*arg && *arg >= '0' && *arg <= '9')
++                    umaskvalue = umaskvalue * 8 + *arg++ - '0';
++                if (*arg || umaskvalue > 0777)
++                    fatal("%s line %d: bad value for umask",
++			    filename, linenum);
++		else {
++			while (*umaskptr && *umaskptr == '0')
++					*umaskptr++;
++			strncpy(options->sftp_umask, umaskptr,
++				SFTP_UMASK_LENGTH);
++		}
++
++                break;
++
++        case sSftpPermitChmod:
++                intptr = &options->sftp_permit_chmod;
++                goto parse_flag;
++
++        case sSftpPermitChown:
++                intptr = &options->sftp_permit_chown;
++                goto parse_flag;
++
+ 	/*
+ 	 * These options can contain %X options expanded at
+ 	 * connect time, so that you can specify paths like:
+@@ -913,6 +1003,7 @@
+ 	if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
+ 		fatal("%s line %d: garbage at end of line; \"%.200s\".",
+ 		    filename, linenum, arg);
++
+ 	return 0;
+ }
+ 
+diff -wur openssh-3.8p1.orig/servconf.h openssh-3.8p1/servconf.h
+--- openssh-3.8p1.orig/servconf.h	2003-12-31 01:37:34.000000000 +0100
++++ openssh-3.8p1/servconf.h	2004-03-29 10:44:26.000000000 +0200
+@@ -32,6 +32,18 @@
+ #define	PERMIT_NO_PASSWD	2
+ #define	PERMIT_YES		3
+ 
++/* sftp-server logging */
++#define LOG_SFTP_NOT_SET	-1
++#define LOG_SFTP_NO		0
++#define LOG_SFTP_YES		1
++
++/* sftp-server umask control */
++#define SFTP_UMASK_LENGTH	5
++
++/* sftp-server client priviledge */
++#define SFTP_PERMIT_NOT_SET	-1
++#define SFTP_PERMIT_NO		0
++#define SFTP_PERMIT_YES		1
+ 
+ typedef struct {
+ 	u_int num_ports;
+@@ -125,6 +137,13 @@
+ 	char   *authorized_keys_file;	/* File containing public keys */
+ 	char   *authorized_keys_file2;
+ 	int	use_pam;		/* Enable auth via PAM */
++	int	log_sftp;		/* perform sftp-server logging */
++        SyslogFacility sftp_log_facility;    /* Facility for sftp subsystem logging. */
++        LogLevel sftp_log_level;     /* Level for sftp subsystem logging. */
++	char	sftp_umask[SFTP_UMASK_LENGTH];		/* Sftp Umask */
++	int	sftp_permit_chmod;
++	int	sftp_permit_chown;
++
+ }       ServerOptions;
+ 
+ void	 initialize_server_options(ServerOptions *);
+diff -wur openssh-3.8p1.orig/session.c openssh-3.8p1/session.c
+--- openssh-3.8p1.orig/session.c	2004-02-23 14:01:27.000000000 +0100
++++ openssh-3.8p1/session.c	2004-03-29 10:44:26.000000000 +0200
+@@ -112,6 +112,15 @@
+ 
+ static int is_child = 0;
+ 
++/* so SFTP_LOG_FACILITY and SFTP_LOG_LEVEL can be passed through the 
++   environment to the sftp-server subsystem. */
++static const char *sysfac_to_int[] = { "0", "1", "2", "3", "4", "5", "6",
++	"7", "8", "9", "10", "11", "-1" };
++static const char *syslevel_to_int[] = { "0", "1", "2", "3", "4", "5", "6",
++	"7", "-1" };
++
++static char *sftpumask;
++
+ /* Name and directory of socket for authentication agent forwarding. */
+ static char *auth_sock_name = NULL;
+ static char *auth_sock_dir = NULL;
+@@ -971,6 +980,7 @@
+ 	env = xmalloc(envsize * sizeof(char *));
+ 	env[0] = NULL;
+ 
++
+ #ifdef HAVE_CYGWIN
+ 	/*
+ 	 * The Windows environment contains some setting which are
+@@ -1111,6 +1121,67 @@
+ 		child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
+ 		    auth_sock_name);
+ 
++	/* LOG_SFTP */
++	if (options.log_sftp == -1 )
++		child_set_env(&env, &envsize, "LOG_SFTP", "-1");
++	else if (options.log_sftp == 0)
++		child_set_env(&env, &envsize, "LOG_SFTP", "0");
++	else
++		child_set_env(&env, &envsize, "LOG_SFTP", "1");
++
++	/* SFTP_LOG_FACILITY */
++	if (options.sftp_log_facility < 0)
++		child_set_env(&env, &envsize, "SFTP_LOG_FACILITY",
++			"-1");
++	else
++		child_set_env(&env, &envsize, "SFTP_LOG_FACILITY", 
++			sysfac_to_int[options.sftp_log_facility]);
++
++	/* SFTP_LOG_LEVEL */
++        if (options.sftp_log_level < 0)
++                child_set_env(&env, &envsize, "SFTP_LOG_LEVEL",
++                        "-1");
++        else
++                child_set_env(&env, &envsize, "SFTP_LOG_LEVEL",
++                        syslevel_to_int[options.sftp_log_level]);
++
++	/* SFTP_UMASK */
++
++	if (options.sftp_umask[0] == '\0')
++		child_set_env(&env, &envsize, "SFTP_UMASK", 
++			"" );
++	else {
++		if (!(sftpumask = calloc(SFTP_UMASK_LENGTH,1))) {
++
++logit("session.c: unabled to allocate memory for SftpUmask. SftpUmask control \
++will be turned off.");
++
++		child_set_env(&env, &envsize, "SFTP_UMASK", 
++			"" );
++		} else {
++			strncpy(sftpumask, options.sftp_umask,
++				SFTP_UMASK_LENGTH);
++			child_set_env(&env, &envsize, "SFTP_UMASK", 
++				sftpumask );
++		}
++	}
++
++        /* SFTP_PERMIT_CHMOD */
++        if (options.sftp_permit_chmod == -1 )
++                child_set_env(&env, &envsize, "SFTP_PERMIT_CHMOD", "-1");
++        else if (options.sftp_permit_chmod == 0)
++                child_set_env(&env, &envsize, "SFTP_PERMIT_CHMOD", "0");
++        else
++                child_set_env(&env, &envsize, "SFTP_PERMIT_CHMOD", "1");
++
++        /* SFTP_PERMIT_CHOWN */
++        if (options.sftp_permit_chown == -1 )
++                child_set_env(&env, &envsize, "SFTP_PERMIT_CHOWN", "-1");
++        else if (options.sftp_permit_chown == 0)
++                child_set_env(&env, &envsize, "SFTP_PERMIT_CHOWN", "0");
++        else
++                child_set_env(&env, &envsize, "SFTP_PERMIT_CHOWN", "1");
++
+ 	/* read $HOME/.ssh/environment. */
+ 	if (options.permit_user_env && !options.use_login) {
+ 		snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
+diff -wur openssh-3.8p1.orig/sftp-server.8 openssh-3.8p1/sftp-server.8
+--- openssh-3.8p1.orig/sftp-server.8	2003-10-15 07:50:43.000000000 +0200
++++ openssh-3.8p1/sftp-server.8	2004-03-29 10:44:26.000000000 +0200
+@@ -41,6 +41,20 @@
+ .Cm Subsystem
+ option.
+ See
++.Xr sshd 8
++for more information. Sftp-server transactions may be logged
++using the
++.Cm LogSftp , 
++.Cm SftpLogFacility ,
++and
++.Cm SftpLogLevel
++options. The administrator may exert control over the file and directory
++permission and ownership, with
++.Cm SftpUmask ,
++.Cm SftpPermitChmod ,
++and
++.Cm SftpPermitChown
++. See
+ .Xr sshd_config 5
+ for more information.
+ .Sh SEE ALSO
+diff -wur openssh-3.8p1.orig/sftp-server.c openssh-3.8p1/sftp-server.c
+--- openssh-3.8p1.orig/sftp-server.c	2004-02-23 23:19:15.000000000 +0100
++++ openssh-3.8p1/sftp-server.c	2004-03-29 10:45:39.000000000 +0200
+@@ -31,6 +31,13 @@
+ #define get_string(lenp)		buffer_get_string(&iqueue, lenp);
+ #define TRACE				debug
+ 
++/* SFTP_UMASK */
++static mode_t setumask = 0;
++
++static int permit_chmod = 1;
++static int permit_chown = 1;
++static int permit_logging = 0;
++
+ #ifdef HAVE___PROGNAME
+ extern char *__progname;
+ #else
+@@ -385,6 +392,14 @@
+ 	a = get_attrib();
+ 	flags = flags_from_portable(pflags);
+ 	mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;
++
++	if (setumask != 0) {
++		if ( permit_logging == 1 )
++		logit("setting file creation mode to 0666 and umask to %o", setumask);
++		mode = 0666;
++		umask(setumask);
++	}
++
+ 	TRACE("open id %u name %s flags %d mode 0%o", id, name, pflags, mode);
+ 	fd = open(name, flags, mode);
+ 	if (fd < 0) {
+@@ -398,6 +413,8 @@
+ 			status = SSH2_FX_OK;
+ 		}
+ 	}
++	if ( permit_logging == 1 )
++	logit("open %s", name);
+ 	if (status != SSH2_FX_OK)
+ 		send_status(id, status);
+ 	xfree(name);
+@@ -434,6 +451,7 @@
+ 	    (u_int64_t)off, len);
+ 	if (len > sizeof buf) {
+ 		len = sizeof buf;
++		if ( permit_logging == 1 )
+ 		logit("read change len %d", len);
+ 	}
+ 	fd = handle_to_fd(handle);
+@@ -453,6 +471,8 @@
+ 			}
+ 		}
+ 	}
++	if ( permit_logging == 1 )
++	logit("reading file");
+ 	if (status != SSH2_FX_OK)
+ 		send_status(id, status);
+ }
+@@ -487,10 +507,13 @@
+ 			} else if (ret == len) {
+ 				status = SSH2_FX_OK;
+ 			} else {
++				if ( permit_logging == 1 )
+ 				logit("nothing at all written");
+ 			}
+ 		}
+ 	}
++	if ( permit_logging == 1 )
++	logit("writing file");
+ 	send_status(id, status);
+ 	xfree(data);
+ }
+@@ -583,24 +606,46 @@
+ 	a = get_attrib();
+ 	TRACE("setstat id %u name %s", id, name);
+ 	if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
++if ( permit_logging == 1 )
++logit("process_setstat: truncate");
+ 		ret = truncate(name, a->size);
+ 		if (ret == -1)
+ 			status = errno_to_portable(errno);
+ 	}
+ 	if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
++		if (permit_chmod == 1) {
+ 		ret = chmod(name, a->perm & 0777);
+ 		if (ret == -1)
+ 			status = errno_to_portable(errno);
++			else
++				if ( permit_logging == 1 )
++				logit("chmod'ed %s", name);
++		} else {
++			status = SSH2_FX_PERMISSION_DENIED;
++			if ( permit_logging == 1 )
++			logit("chmod %s: operation prohibited by sftp-server configuration.", name);
++		}
+ 	}
+ 	if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
++if ( permit_logging == 1 )
++logit("process_setstat: utimes");
+ 		ret = utimes(name, attrib_to_tv(a));
+ 		if (ret == -1)
+ 			status = errno_to_portable(errno);
+ 	}
+ 	if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
++		if (permit_chown == 1) {
+ 		ret = chown(name, a->uid, a->gid);
+ 		if (ret == -1)
+ 			status = errno_to_portable(errno);
++			else
++				if ( permit_logging == 1 )
++				logit("chown'ed %s.", name);
++		} else {
++			status = SSH2_FX_PERMISSION_DENIED;
++			if ( permit_logging == 1 )
++			logit("chown %s: operation prohibited by sftp-server configuration.", name);
++		}
+ 	}
+ 	send_status(id, status);
+ 	xfree(name);
+@@ -615,6 +660,9 @@
+ 	int status = SSH2_FX_OK;
+ 	char *name;
+ 
++if ( permit_logging == 1 )
++logit("process_fsetstat");
++
+ 	id = get_int();
+ 	handle = get_handle();
+ 	a = get_attrib();
+@@ -625,11 +673,14 @@
+ 		status = SSH2_FX_FAILURE;
+ 	} else {
+ 		if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
++if ( permit_logging == 1 )
++logit("process_fsetstat: ftruncate");
+ 			ret = ftruncate(fd, a->size);
+ 			if (ret == -1)
+ 				status = errno_to_portable(errno);
+ 		}
+ 		if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
++			if (permit_chmod == 1) {
+ #ifdef HAVE_FCHMOD
+ 			ret = fchmod(fd, a->perm & 0777);
+ #else
+@@ -637,8 +688,18 @@
+ #endif
+ 			if (ret == -1)
+ 				status = errno_to_portable(errno);
++				else
++					if ( permit_logging == 1 )
++					logit("chmod: succeeded.");
++			} else {
++	                        status = SSH2_FX_PERMISSION_DENIED;
++				if ( permit_logging == 1 )
++				logit("chmod: operation prohibited by sftp-server configuration.");
++			}
+ 		}
+ 		if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
++if ( permit_logging == 1 )
++logit("process_fsetstat: utimes");
+ #ifdef HAVE_FUTIMES
+ 			ret = futimes(fd, attrib_to_tv(a));
+ #else
+@@ -648,6 +709,7 @@
+ 				status = errno_to_portable(errno);
+ 		}
+ 		if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
++			if (permit_chown == 1) {
+ #ifdef HAVE_FCHOWN
+ 			ret = fchown(fd, a->uid, a->gid);
+ #else
+@@ -655,6 +717,14 @@
+ #endif
+ 			if (ret == -1)
+ 				status = errno_to_portable(errno);
++				else
++					if ( permit_logging == 1 )
++					logit("chown: succeeded");
++			} else {
++				status = SSH2_FX_PERMISSION_DENIED;
++				if ( permit_logging == 1 )
++				logit("chown: operation prohibited by sftp-server configuration.");
++			}
+ 		}
+ 	}
+ 	send_status(id, status);
+@@ -684,6 +754,8 @@
+ 		}
+ 
+ 	}
++	if ( permit_logging == 1 )
++	logit("opendir %s", path);
+ 	if (status != SSH2_FX_OK)
+ 		send_status(id, status);
+ 	xfree(path);
+@@ -757,6 +829,8 @@
+ 	TRACE("remove id %u name %s", id, name);
+ 	ret = unlink(name);
+ 	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
++	if ( permit_logging == 1 )
++	logit("remove file %s", name);
+ 	send_status(id, status);
+ 	xfree(name);
+ }
+@@ -774,9 +848,19 @@
+ 	a = get_attrib();
+ 	mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
+ 	    a->perm & 0777 : 0777;
++
++        if (setumask != 0) {
++		if ( permit_logging == 1 )
++                logit("setting directory creation mode to 0777 and umask to %o.", setumask);
++                mode = 0777;
++                umask(setumask);
++        }
++
+ 	TRACE("mkdir id %u name %s mode 0%o", id, name, mode);
+ 	ret = mkdir(name, mode);
+ 	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
++	if ( permit_logging == 1 )
++	logit("mkdir %s", name);
+ 	send_status(id, status);
+ 	xfree(name);
+ }
+@@ -793,6 +877,8 @@
+ 	TRACE("rmdir id %u name %s", id, name);
+ 	ret = rmdir(name);
+ 	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
++	if ( permit_logging == 1 )
++	logit("rmdir %s", name);
+ 	send_status(id, status);
+ 	xfree(name);
+ }
+@@ -819,6 +905,8 @@
+ 		s.name = s.long_name = resolvedname;
+ 		send_names(id, 1, &s);
+ 	}
++	if ( permit_logging == 1 )
++	logit("realpath %s", path);
+ 	xfree(path);
+ }
+ 
+@@ -854,6 +942,8 @@
+ 			status = SSH2_FX_OK;
+ 	}
+ 	send_status(id, status);
++	if ( permit_logging == 1 )
++	logit("rename old %s new %s", oldpath, newpath);
+ 	xfree(oldpath);
+ 	xfree(newpath);
+ }
+@@ -879,6 +969,8 @@
+ 		s.name = s.long_name = link;
+ 		send_names(id, 1, &s);
+ 	}
++	if ( permit_logging == 1 )
++	logit("readlink %s", path);
+ 	xfree(path);
+ }
+ 
+@@ -897,6 +989,8 @@
+ 	ret = symlink(oldpath, newpath);
+ 	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
+ 	send_status(id, status);
++	if ( permit_logging == 1 )
++	logit("symlink old %s new %s", oldpath, newpath);
+ 	xfree(oldpath);
+ 	xfree(newpath);
+ }
+@@ -1018,6 +1112,8 @@
+ {
+ 	fd_set *rset, *wset;
+ 	int in, out, max;
++	unsigned int val = 0;
++	char *umask_env;
+ 	ssize_t len, olen, set_size;
+ 
+ 	/* XXX should use getopt */
+@@ -1025,6 +1121,16 @@
+ 	__progname = ssh_get_progname(av[0]);
+ 	handle_init();
+ 
++	/* Transaction logging */
++
++	if (atoi(getenv("LOG_SFTP")) == 1)
++	{
++		permit_logging = 1;
++		log_init("sftp-server", atoi(getenv("SFTP_LOG_LEVEL")),
++			atoi(getenv("SFTP_LOG_FACILITY")), 0);
++	};
++
++
+ #ifdef DEBUG_SFTP_SERVER
+ 	log_init("sftp-server", SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 0);
+ #endif
+@@ -1032,6 +1138,39 @@
+ 	in = dup(STDIN_FILENO);
+ 	out = dup(STDOUT_FILENO);
+ 
++	if ( permit_logging == 1 )
++	logit("Starting sftp-server logging for user %s.", getenv("USER"));
++
++	/* Umask control */
++
++	umask_env = getenv("SFTP_UMASK");
++	while (*umask_env && *umask_env >= '0' && *umask_env <= '9')
++		val = val * 8 + *umask_env++ - '0';
++
++	if (*umask_env || val > 0777 || val == 0) {
++		if ( permit_logging == 1 )
++		logit("bad value %o for SFTP_UMASK, turning umask control off.", val);
++		setumask = 0;
++	} else {
++		if ( permit_logging == 1 )
++		logit("umask control is on.");
++		setumask = val;
++	};
++
++
++	/* Sensitive client commands */
++	
++        if (atoi(getenv("SFTP_PERMIT_CHMOD")) != 1) {
++		permit_chmod = 0;
++		if ( permit_logging == 1 )
++                logit("client is not permitted to chmod.");
++	};
++        if (atoi(getenv("SFTP_PERMIT_CHOWN")) != 1) {
++		permit_chown = 0;
++		if ( permit_logging == 1 )
++                logit("client is not permitted to chown.");
++	};
++
+ #ifdef HAVE_CYGWIN
+ 	setmode(in, O_BINARY);
+ 	setmode(out, O_BINARY);
+@@ -1071,6 +1210,8 @@
+ 			len = read(in, buf, sizeof buf);
+ 			if (len == 0) {
+ 				debug("read eof");
++				if ( permit_logging == 1 )
++				logit("sftp-server finished.");
+ 				exit(0);
+ 			} else if (len < 0) {
+ 				error("read error");
+diff -wur openssh-3.8p1.orig/sshd_config openssh-3.8p1/sshd_config
+--- openssh-3.8p1.orig/sshd_config	2003-12-31 01:38:32.000000000 +0100
++++ openssh-3.8p1/sshd_config	2004-03-29 10:44:26.000000000 +0200
+@@ -95,3 +95,14 @@
+ 
+ # override default of no subsystems
+ Subsystem	sftp	/usr/libexec/sftp-server
++
++# sftp-server logging
++#LogSftp no
++#SftpLogFacility AUTH
++#SftpLogLevel INFO
++
++# sftp-server umask control
++#SftpUmask
++
++#SftpPermitChmod yes
++#SftpPermitChown yes
+diff -wur openssh-3.8p1.orig/sshd_config.5 openssh-3.8p1/sshd_config.5
+--- openssh-3.8p1.orig/sshd_config.5	2004-02-18 04:31:24.000000000 +0100
++++ openssh-3.8p1/sshd_config.5	2004-03-29 10:44:26.000000000 +0200
+@@ -374,6 +374,10 @@
+ DEBUG and DEBUG1 are equivalent.
+ DEBUG2 and DEBUG3 each specify higher levels of debugging output.
+ Logging with a DEBUG level violates the privacy of users and is not recommended.
++.It Cm LogSftp
++Specifies whether to perform logging of
++.Nm sftp-server
++subsystem transactions. Must be "yes" or "no." The default value is "no."
+ .It Cm MACs
+ Specifies the available MAC (message authentication code) algorithms.
+ The MAC algorithm is used in protocol version 2
+@@ -526,6 +530,37 @@
+ .It Cm ServerKeyBits
+ Defines the number of bits in the ephemeral protocol version 1 server key.
+ The minimum value is 512, and the default is 768.
++.It Cm SftpLogFacility
++Gives the facility code that is used when logging
++.Nm sftp-server .
++transactions. The possible values are: DAEMON, USER, AUTH, LOCAL0,
++LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
++The default is AUTH.
++.It Cm SftpLogLevel
++Gives the verbosity level that is used when logging messages from
++.Nm sftp-server .
++The possible values are:
++QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2 and DEBUG3.
++The default is INFO.  DEBUG and DEBUG1 are equivalent.  DEBUG2
++and DEBUG3 each specify higher levels of debugging output.
++Logging with a DEBUG level violates the privacy of users
++and is not recommended.
++.It Cm SftpPermitChmod
++Specifies whether the sftp-server allows the sftp client to execute chmod 
++commands on the server. The default is yes.
++.It Cm SftpPermitChown
++Specifies whether the sftp-server allows the sftp client to execute chown
++or chgrp commands on the server. Turning this value on means that the client
++is allowed to execute both chown and chgrp commands. Turning it off means that
++the client is prohibited from executing either chown or chgrp.
++ The default is yes.
++.It Cm SftpUmask
++Specifies an optional umask for 
++.Nm sftp-server
++subsystem transactions. If a umask is given, this umask will override all system, 
++environment or sftp client permission modes. If
++no umask or an invalid umask is given, file creation mode defaults to the permission
++mode specified by the sftp client. The default is for no umask.
+ .It Cm StrictModes
+ Specifies whether
+ .Nm sshd

+ 15 - 10
openssh/openssh.spec

@@ -42,18 +42,19 @@ Class:        CORE
 Group:        Security
 License:      BSD
 Version:      %{V_base}%{V_portable}
-Release:      20040324
+Release:      20040329
 
 #   package options
-%option       with_fsl      yes
-%option       with_pam      no
-%option       with_skey     no
-%option       with_x11      no
-%option       with_chroot   no
-%option       with_alias    no
-%option       with_watchdog no
-%option       with_ldap     no
-%option       with_wrap     no
+%option       with_fsl          yes
+%option       with_alias        no
+%option       with_chroot       no
+%option       with_ldap         no
+%option       with_pam          no
+%option       with_sftplogging  no
+%option       with_skey         no
+%option       with_watchdog     no
+%option       with_wrap         no
+%option       with_x11          no
 
 #   list of sources
 Source0:      ftp://ftp.openssh.com/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz
@@ -70,6 +71,7 @@ Patch1:       openssh.patch.chroot
 Patch2:       openssh.patch.alias
 Patch3:       http://www.sc.isc.tohoku.ac.jp/~hgot/sources/openssh-%{V_watchdog}-watchdog.patch.tgz
 Patch4:       http://ldappubkey.gcu-squad.org/%{V_ldap_vers1}/ldappubkey-ossh%{V_ldap_base}-%{V_ldap_vers2}.patch
+Patch5:       openssh.patch.sftplogging
 
 #   build information
 Prefix:       %{l_prefix}
@@ -148,6 +150,9 @@ AutoReqProv:  no
 %if "%{with_ldap}" == "yes"
     %{l_gzip} -d -c %{SOURCE ldappubkey-ossh%{V_ldap_base}-%{V_ldap_vers2}.patch} | %{l_patch} -p0
 %endif
+%if "%{with_sftplogging}" == "yes"
+    %patch -p1 -P 5
+%endif
 
 %build
     #   configure package