Pantek Library
Hosting Provided By
CybrHost
High Speed Hosting

Openssh-3.5p1 PATCH: functionality added to sftp server

From: Martinez, Michael - CSREES/ISTM <MMARTINEZ(at)intranet.reeusda.gov>
Date: Mon Feb 10 2003 - 09:07:14 EST


Guys,

I've had several requests for the following patch, hence I am posting it for all to use. A Summary of this Patch is as follows. This patch provides added functionality for the sftp-server. Specifically, new directives are added to sshd_config, which allows sftp server transaction logging on a per-user basis - you can turn logging on or off; which allows umask control over uploaded files - you can either specify an overriding umask or specify no umask (in which case the sftp client or user environment overrides); and which allows you to control whether the client is allowed to issue "chmod" "chown" or "chgrp" commands.

The reason that I created this patch was because, as a sysadmin at U.S. Department of Agriculture, I run a secure ftp server for our web developers. Our web developers belong to different file system groups, with read/write access, and I needed a way to maintain an audit trail of file upload, removal or deletion, and I needed control over file permissions (specifically, I needed to prohibit the user/client from having control over it). These functions are absent in the stock openssh code.

The patch provided below, is a patch made with "diff -u", which means you will need GNU "patch" to use it. In another post, I will provide a context patch which will work without GNU. The patch applies to the top level directory of the source code for openssh-3.5p1. It has been tested and deployed on RedHat 7.1. There are no platform-specific modifications in this patch, so if you can compile stock openssh-3.5p1 on your system, you will be able to compile this patch. Apply the patch and then configure, build and compile the software as normal.

If you use this patch and you like it, I ask that you write Markus Friedl (one of the openssh developers) to ask him to either include it in future openssh releases, or ask him to design his own comparable patch so that this type of functionality can continue to be propagated in future software releases.

The following disclaimer applies:

Disclaimer: This sftp-server patch is provided without any warranty or guarantee of any kind. I have made every reasonable effort to ensure integrity and security of the code modifications, but neither myself, the United States Government, nor the openssh developer team is responsible for any damage, adverse or unwanted effects to your system that may be a direct or indirect result of using this patch. Furthermore, this patch was developed and provided to you by myself. Neither the openssh developers nor the U.S. Government endorses the use of this patch.

The patch follows:

Do you need help?X

Only in openssh-3.5p1-sftp_mods/: Makefile Common subdirectories: openssh-3.5p1/autom4te-2.53.cache and openssh-3.5p1-sftp_mods/autom4te-2.53.cache Common subdirectories: openssh-3.5p1/contrib and openssh-3.5p1-sftp_mods/contrib Common subdirectories: openssh-3.5p1/openbsd-compat and openssh-3.5p1-sftp_mods/openbsd-compat Common subdirectories: openssh-3.5p1/regress and openssh-3.5p1-sftp_mods/regress Common subdirectories: openssh-3.5p1/scard and openssh-3.5p1-sftp_mods/scard diff -u openssh-3.5p1/servconf.c openssh-3.5p1-sftp_mods/servconf.c

--- openssh-3.5p1/servconf.c	Thu Sep  5 00:35:15 2002

+++ openssh-3.5p1-sftp_mods/servconf.c Wed Jan 29 09:43:35 2003
@@ -124,6 +124,15 @@ options->authorized_keys_file = NULL; options->authorized_keys_file2 = NULL;
+ options->log_sftp = LOG_SFTP_NOT_SET;
/* Needs to be accessable in many places */ use_privsep = -1;

 }
@@ -131,7 +140,7 @@
 void
 fill_default_server_options(ServerOptions *options)  {
- /* Portable-specific options */
+/* Portable-specific options */
 	if (options->pam_authentication_via_kbd_int == -1)
 		options->pam_authentication_via_kbd_int = 0;
 
@@ -256,6 +265,24 @@
 	if (options->authorized_keys_file == NULL)
 		options->authorized_keys_file =

_PATH_SSH_USER_PERMITTED_KEYS;  
+ /* Turn sftp-server logging off by default */
 	/* Turn privilege separation on by default */
 	if (use_privsep == -1)
 		use_privsep = 1;
@@ -302,6 +329,9 @@
 	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
 	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
 	sUsePrivilegeSeparation,

+ sLogSftp, sSftpLogFacility, sSftpLogLevel,
sDeprecated

 } ServerOpCodes;  

@@ -380,6 +410,12 @@

 	{ "authorizedkeysfile", sAuthorizedKeysFile },
 	{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
 	{ "useprivilegeseparation", sUsePrivilegeSeparation},

+ { "logsftp", sLogSftp},
{ NULL, sBadOption } }; @@ -445,6 +481,8 @@ char *cp, **charptr, *arg, *p; int *intptr, value, i, n; ServerOpCodes opcode;
+ unsigned int umaskvalue = 0;
cp = line; arg = strdelim(&cp); @@ -888,6 +926,58 @@ case sBanner: charptr = &options->banner; goto parse_filename;
+
+ case sLogSftp:
'%s'",
+ filename, linenum, arg ? arg : "<NONE>");
/* * These options can contain %X options expanded at * connect time, so that you can specify paths like: @@ -923,6 +1013,7 @@ if ((arg = strdelim(&cp)) != NULL && *arg != '\0') fatal("%s line %d: garbage at end of line; \"%.200s\".", filename, linenum, arg);
+
return 0;

 }  

diff -u openssh-3.5p1/servconf.h openssh-3.5p1-sftp_mods/servconf.h

--- openssh-3.5p1/servconf.h	Wed Jul 31 21:28:39 2002

+++ openssh-3.5p1-sftp_mods/servconf.h Wed Jan 29 09:41:06 2003
@@ -32,6 +32,18 @@ #define PERMIT_NO_PASSWD 2 #define PERMIT_YES 3
+/* sftp-server logging */
+#define LOG_SFTP_NOT_SET -1
 

 typedef struct {

         u_int num_ports;
@@ -132,6 +144,13 @@

 	char   *authorized_keys_file;	/* File containing public keys */
 	char   *authorized_keys_file2;
 	int	pam_authentication_via_kbd_int;

+ int log_sftp; /* perform sftp-server logging */
logging. */
+ LogLevel sftp_log_level; /* Level for sftp subsystem logging.
*/
+ char sftp_umask[SFTP_UMASK_LENGTH]; /* Sftp Umask */
} ServerOptions; void initialize_server_options(ServerOptions *); diff -u openssh-3.5p1/session.c openssh-3.5p1-sftp_mods/session.c
Do you need more help?X
--- openssh-3.5p1/session.c Wed Sep 25 20:38:50 2002
+++ openssh-3.5p1-sftp_mods/session.c Wed Jan 29 09:44:18 2003
@@ -111,6 +111,15 @@
 login_cap_t *lc;
 #endif  

+/* so SFTP_LOG_FACILITY and SFTP_LOG_LEVEL can be passed through the
 /* Name and directory of socket for authentication agent forwarding. */ static char *auth_sock_name = NULL; static char *auth_sock_dir = NULL; @@ -957,6 +966,7 @@

 	env = xmalloc(envsize * sizeof(char *));
 	env[0] = NULL;
 

+

 #ifdef HAVE_CYGWIN

 	/*
 	 * The Windows environment contains some setting which are
@@ -1083,6 +1093,67 @@
 	if (auth_sock_name != NULL)
 		child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
 		    auth_sock_name);

+
+ /* LOG_SFTP */
 
 	/* read $HOME/.ssh/environment. */
 	if (options.permit_user_env && !options.use_login) {
diff -u openssh-3.5p1/sftp-server.8 openssh-3.5p1-sftp_mods/sftp-server.8
--- openssh-3.5p1/sftp-server.8	Mon Jun 25 00:45:35 2001

+++ openssh-3.5p1-sftp_mods/sftp-server.8 Wed Jan 29 10:11:28 2003
@@ -42,11 +42,26 @@
 option.
 See
 .Xr sshd 8
+for more information. Sftp-server transactions may be logged using the
 for more information.
 .Sh SEE ALSO
 .Xr sftp 1 ,
 .Xr ssh 1 ,
-.Xr sshd 8

+.Xr sshd 8,
+.Xr sshd_config 5
.Rs .%A T. Ylonen .%A S. Lehtinen diff -u openssh-3.5p1/sftp-server.c openssh-3.5p1-sftp_mods/sftp-server.c --- openssh-3.5p1/sftp-server.c Wed Sep 11 19:54:27 2002
+++ openssh-3.5p1-sftp_mods/sftp-server.c Wed Jan 29 09:40:25 2003
@@ -39,6 +39,12 @@ #define get_string(lenp) buffer_get_string(&iqueue, lenp); #define TRACE debug

+/* SFTP_UMASK */
+static mode_t setumask = 0;
 #ifdef HAVE___PROGNAME
 extern char *__progname;
 #else
@@ -391,6 +397,13 @@

 	a = get_attrib();
 	flags = flags_from_portable(pflags);
 	mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;

+
+ if (setumask != 0) {
+ log("setting file creation mode to 0666 and umask to %o",
setumask);
+ mode = 0666;
TRACE("open id %u name %s flags %d mode 0%o", id, name, pflags, mode); fd = open(name, flags, mode); if (fd < 0) { @@ -404,6 +417,7 @@ status = SSH2_FX_OK; } }
+ log("open %s", name);
if (status != SSH2_FX_OK) send_status(id, status); xfree(name); @@ -459,6 +473,7 @@ } } }
+ log("reading file");
if (status != SSH2_FX_OK) send_status(id, status);

 }
@@ -497,6 +512,7 @@
 			}
 		}
 	}

+ log("writing file");
send_status(id, status); xfree(data);

 }
@@ -589,24 +605,40 @@
 	a = get_attrib();
 	TRACE("setstat id %u name %s", id, name);
 	if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {

+log("process_setstat: truncate");
ret = truncate(name, a->size); if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { - ret = chmod(name, a->perm & 0777);
Can't find what you're looking for?X
- if (ret == -1) - status = errno_to_portable(errno);
+ if (permit_chmod == 1) {
+ ret = chmod(name, a->perm & 0777);
+ if (ret == -1)
+ status = errno_to_portable(errno);
+ else
+ log("chmod'ed %s", name);
configuration.", name);
+ }
} if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
+log("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) { - ret = chown(name, a->uid, a->gid); - if (ret == -1) - status = errno_to_portable(errno);
+ if (permit_chown == 1) {
+ ret = chown(name, a->uid, a->gid);
+ if (ret == -1)
+ status = errno_to_portable(errno);
+ else
+ log("chown'ed %s.", name);
configuration.", name);
+ }
} send_status(id, status); xfree(name); @@ -621,6 +653,8 @@ int status = SSH2_FX_OK; char *name;
Can we help you?X

+log("process_fsetstat");

 	id = get_int();
 	handle = get_handle();
 	a = get_attrib();
@@ -631,20 +665,29 @@
 		status = SSH2_FX_FAILURE;
 	} else {
 		if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {

+log("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);
+ ret = fchmod(fd, a->perm & 0777);
#else - ret = chmod(name, a->perm & 0777);
+ ret = chmod(name, a->perm & 0777);
#endif - if (ret == -1) - status = errno_to_portable(errno);
+ if (ret == -1)
+ status = errno_to_portable(errno);
+ else
+ log("chmod: succeeded.");
sftp-server configuration.");
+ }
} if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {

+log("process_fsetstat: utimes");
 #ifdef HAVE_FUTIMES

                         ret = futimes(fd, attrib_to_tv(a));
 #else
@@ -654,13 +697,20 @@

 				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);
+ ret = fchown(fd, a->uid, a->gid);
#else - ret = chown(name, a->uid, a->gid);
+ ret = chown(name, a->uid, a->gid);
#endif - if (ret == -1) - status = errno_to_portable(errno);
+ if (ret == -1)
+ status = errno_to_portable(errno);
+ else
+ log("chown: succeeded");
sftp-server configuration.");
+ }
} } send_status(id, status); @@ -690,6 +740,7 @@ } }
+ log("opendir %s", path);
if (status != SSH2_FX_OK) send_status(id, status); xfree(path); @@ -763,6 +814,7 @@ TRACE("remove id %u name %s", id, name);
Don't know where to look next?X
ret = unlink(name); status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
+ log("remove file %s", name);
send_status(id, status); xfree(name);

 }
@@ -780,9 +832,17 @@
 	a = get_attrib();
 	mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
 	    a->perm & 0777 : 0777;

+
+ if (setumask != 0) {
%o.", setumask);
+ mode = 0777;
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;
+ log("mkdir %s", name);
send_status(id, status); xfree(name);

 }
@@ -799,6 +859,7 @@
 	TRACE("rmdir id %u name %s", id, name);
 	ret = rmdir(name);
 	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;

+ log("rmdir %s", name);
send_status(id, status); xfree(name);

 }
@@ -825,6 +886,7 @@
 		s.name = s.long_name = resolvedname;
 		send_names(id, 1, &s);
 	}

+ log("realpath %s", path);
xfree(path);

 }  

@@ -846,6 +908,7 @@

                 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;

 	}
 	send_status(id, status);

+ log("rename old %s new %s", oldpath, newpath);
xfree(oldpath); xfree(newpath);

 }
@@ -871,6 +934,7 @@
 		s.name = s.long_name = link;
 		send_names(id, 1, &s);
 	}

+ log("readlink %s", path);
xfree(path);

 }  

@@ -892,6 +956,7 @@

                 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;

 	}
 	send_status(id, status);

+ log("symlink old %s new %s", oldpath, newpath);
xfree(oldpath); xfree(newpath);

 }
@@ -1013,6 +1078,8 @@
 {
 	fd_set *rset, *wset;
 	int in, out, max;

+ unsigned int val = 0;
ssize_t len, olen, set_size; /* XXX should use getopt */ @@ -1020,10 +1087,45 @@ __progname = get_progname(av[0]); handle_init();
+ /* Transaction logging */
 #ifdef DEBUG_SFTP_SERVER

         log_init("sftp-server", SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 0); #endif  

+ log("Starting sftp-server logging for user %s.", getenv("USER"));
off.", val);
+ setumask = 0;
+ } else {

 	in = dup(STDIN_FILENO);
 	out = dup(STDOUT_FILENO);
 
@@ -1066,6 +1168,7 @@
 			len = read(in, buf, sizeof buf);
 			if (len == 0) {
 				debug("read eof");

+ log("sftp-server finished.");
exit(0); } else if (len < 0) { error("read error");

Only in openssh-3.5p1-sftp_mods/: ssh_prng_cmds diff -u openssh-3.5p1/sshd_config openssh-3.5p1-sftp_mods/sshd_config
--- openssh-3.5p1/sshd_config	Thu Sep 26 23:21:58 2002

+++ openssh-3.5p1-sftp_mods/sshd_config Wed Jan 29 10:08:39 2003
@@ -91,3 +91,14 @@  
Confused? Frustrated?X

 # override default of no subsystems
 Subsystem sftp /usr/libexec/sftp-server
+
+# sftp-server logging
+#LogSftp no
diff -u openssh-3.5p1/sshd_config.5 openssh-3.5p1-sftp_mods/sshd_config.5

--- openssh-3.5p1/sshd_config.5	Wed Sep 18 21:51:22 2002

+++ openssh-3.5p1-sftp_mods/sshd_config.5 Wed Jan 29 10:10:03 2003
@@ -389,6 +389,10 @@
 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
 .It Cm MACs
 Specifies the available MAC (message authentication code) algorithms. The MAC algorithm is used in protocol version 2 @@ -558,6 +562,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
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.
system,
+environment or sftp client permission modes. If
permission
+mode specified by the sftp client. The default is for no umask.
 .It Cm StrictModes
 Specifies whether
 .Nm sshd Received on Mon Feb 10 23:17:25 2003

This archive was generated by hypermail 2.1.8 : Wed Aug 23 2006 - 14:02:54 EDT


Contact Us  Legal Notices  Order Services Online 
Pantek Home  Privacy Policy  IT news  Site Map  Pantek Library