SFTP Logging
Jason A . Dour
jason at dour.org
Sat Jun 16 00:37:49 EST 2001
On Fri, Jun 15, 2001 at 10:27:54AM +1000, Andrew Bartlett wrote:
> Remember that it will amout to moot unless you use a restricted
> shell, like the one I have posted to this list earlier, as
> otherwise users can just use their own SFTP server - without your
> logging capabilities.
True. But I'm also coding such a shell to meet my needs for
SFTP/SCP restricted users only. And I'm also spelunking the OpenSSH
codebase to see about separating authentication and authorization.
I don't know if authent/auhtoriz separation has been discussed
before, but regardless of the authentication method I've allowed, I
need to restrict what a user can do. I havne't come up with a clear
solution yet, but I've a few ideas forming...
On Thu, Jun 14, 2001 at 06:25:58PM -0700, Jason Stone wrote:
> I'm always in favor of more logging options.
I've attached a diff versus the 2.9p1 release (I apologize for my
lack of CVS-ness). It covers logging of most major operations.
The logline is constructed to include the parent PID, the UID of the
user, and the UserName of the user for tracking/tie-back purposes:
sftp-server[PID]: (PPID/UID/UNAME) Entry
Possible cleanups...look at a better way to do sflags_from_portable.
Presently the function that converts portable to "string flags" such
as "(rwacte)" presently uses pointers to modify character values in
a fixed-length string. I did it this way to avoid using any
string.h functions that are not used throughout the program.
Possible additions...look at logging a virtual current working
directory via logging send_names. Not great since there really
isn't a CWD with SFTP server, but it is a potential tidbit of
information admins might want. Also potentially log uses of '..' in
realpath as a paranoia check for admins who might want it. chroot()
would be a better answer for this paranoia, but I presently do not
have a chroot() solution.
Feedback is appreciated. I apologize if I'm a bit unorthodox in my
delivery of this contribution...it's been a while since I've been
eye-deep in code (since the birth of suEXEC actually), and I'm a bit
rusty.
Cheers,
Jason
# "Jason A. Dour" <jason at dour.org> http://dour.org/
# Founder / Executive Producer - PJ Harvey Online - http://pjh.org/
-------------- next part --------------
*** sftp-server.c.orig Mon Jun 11 12:18:31 2001
--- sftp-server.c Fri Jun 15 09:06:31 2001
***************
*** 52,59 ****
/* Version of client */
int version;
! /* portable attibutes, etc. */
typedef struct Stat Stat;
struct Stat {
--- 52,65 ----
/* Version of client */
int version;
! /* User information. */
! #define CUNAME cuname ? cuname : "UNKNOWN"
! struct passwd *upw;
! uid_t cuid;
! pid_t ppid;
! char *cuname;
+ /* portable attibutes, etc. */
typedef struct Stat Stat;
struct Stat {
***************
*** 115,120 ****
--- 121,148 ----
return flags;
}
+ void
+ sflags_from_portable(char *psflags, int pflags)
+ {
+ if (pflags & SSH2_FXF_READ)
+ *psflags = 'r';
+ psflags++;
+ if (pflags & SSH2_FXF_WRITE)
+ *psflags = 'w';
+ psflags++;
+ if (pflags & SSH2_FXF_APPEND)
+ *psflags = 'a';
+ psflags++;
+ if (pflags & SSH2_FXF_CREAT)
+ *psflags = 'c';
+ psflags++;
+ if (pflags & SSH2_FXF_TRUNC)
+ *psflags = 't';
+ psflags++;
+ if (pflags & SSH2_FXF_EXCL)
+ *psflags = 'e';
+ }
+
Attrib *
get_attrib(void)
{
***************
*** 370,375 ****
--- 398,404 ----
version = buffer_get_int(&iqueue);
TRACE("client version %d", version);
+ log("(%d/%d/%s) Client version %d", ppid, cuid, CUNAME, version);
buffer_init(&msg);
buffer_put_char(&msg, SSH2_FXP_VERSION);
buffer_put_int(&msg, SSH2_FILEXFER_VERSION);
***************
*** 382,388 ****
{
u_int32_t id, pflags;
Attrib *a;
! char *name;
int handle, fd, flags, mode, status = SSH2_FX_FAILURE;
id = get_int();
--- 411,417 ----
{
u_int32_t id, pflags;
Attrib *a;
! char *name, sflags[7] = "------";
int handle, fd, flags, mode, status = SSH2_FX_FAILURE;
id = get_int();
***************
*** 390,397 ****
--- 419,428 ----
pflags = get_int(); /* portable flags */
a = get_attrib();
flags = flags_from_portable(pflags);
+ sflags_from_portable(&sflags[0], pflags);
mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;
TRACE("open id %d name %s flags %d mode 0%o", id, name, pflags, mode);
+ log("(%d/%d/%s) File/Dir opened: %s (%s,%04o)", ppid, cuid, CUNAME, name, sflags, mode);
fd = open(name, flags, mode);
if (fd < 0) {
status = errno_to_portable(errno);
***************
*** 589,594 ****
--- 620,626 ----
name = get_string(NULL);
a = get_attrib();
TRACE("setstat id %d name %s", id, name);
+ log("(%d/%d/%s) Permissions altered: %s (%04o).", ppid, cuid, CUNAME, name, a->perm & 0777);
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
ret = chmod(name, a->perm & 0777);
if (ret == -1)
***************
*** 623,628 ****
--- 655,661 ----
TRACE("fsetstat id %d handle %d", id, handle);
fd = handle_to_fd(handle);
name = handle_to_name(handle);
+ log("(%d/%d/%s) Permissions altered: %s (%04o).", ppid, cuid, CUNAME, name, a->perm & 0777);
if (fd < 0 || name == NULL) {
status = SSH2_FX_FAILURE;
} else {
***************
*** 790,795 ****
--- 823,829 ----
id = get_int();
name = get_string(NULL);
TRACE("remove id %d name %s", id, name);
+ log("(%d/%d/%s) File deleted: %s", ppid, cuid, CUNAME, name);
ret = unlink(name);
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status);
***************
*** 810,815 ****
--- 844,850 ----
mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
a->perm & 0777 : 0777;
TRACE("mkdir id %d name %s mode 0%o", id, name, mode);
+ log("(%d/%d/%s) Directory created: %s", ppid, cuid, CUNAME, name);
ret = mkdir(name, mode);
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status);
***************
*** 826,831 ****
--- 861,867 ----
id = get_int();
name = get_string(NULL);
TRACE("rmdir id %d name %s", id, name);
+ log("(%d/%d/%s) Directory deleted: %s", ppid, cuid, CUNAME, name);
ret = rmdir(name);
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status);
***************
*** 869,874 ****
--- 905,911 ----
oldpath = get_string(NULL);
newpath = get_string(NULL);
TRACE("rename id %d old %s new %s", id, oldpath, newpath);
+ log("(%d/%d/%s) File/Dir renamed: %s -> %s", ppid, cuid, CUNAME, oldpath, newpath);
/* fail if 'newpath' exists */
if (stat(newpath, &st) == -1) {
ret = rename(oldpath, newpath);
***************
*** 914,919 ****
--- 951,957 ----
oldpath = get_string(NULL);
newpath = get_string(NULL);
TRACE("symlink id %d old %s new %s", id, oldpath, newpath);
+ log("(%d/%d/%s) Symbolic link created: %s -> %s", ppid, cuid, CUNAME, oldpath, newpath);
/* fail if 'newpath' exists */
if (stat(newpath, &st) == -1) {
ret = symlink(oldpath, newpath);
***************
*** 951,956 ****
--- 989,995 ----
msg_len = GET_32BIT(cp);
if (msg_len > 256 * 1024) {
error("bad message ");
+ log("(%d/%d/%s) SFTP session closing (%s).", ppid, cuid, CUNAME, "Bad Message");
exit(11);
}
if (buffer_len(&iqueue) < msg_len + 4)
***************
*** 1031,1045 ****
--- 1070,1102 ----
int in, out, max;
ssize_t len, olen, set_size;
+
/* XXX should use getopt */
__progname = get_progname(av[0]);
handle_init();
+ /* Initialize the username of the user running the process. */
+ cuid = getuid();
+ if ((upw = getpwuid(cuid)) == NULL) {
+ cuname = NULL;
+ } else {
+ cuname = upw->pw_name;
+ }
+
+ /* Initialize the parent process ID. */
+ ppid = getppid();
+
+ /* Initialize the logfile, loglevel dependent on DEBUG compile-time setting. */
#ifdef DEBUG_SFTP_SERVER
log_init("sftp-server", SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 0);
+ #else
+ log_init("sftp-server", SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0);
#endif
+ /* Log session start. */
+ log("(%d/%d/%s) SFTP session started.", ppid, cuid, CUNAME);
+
in = dup(STDIN_FILENO);
out = dup(STDOUT_FILENO);
***************
*** 1073,1078 ****
--- 1130,1136 ----
if (select(max+1, rset, wset, NULL, NULL) < 0) {
if (errno == EINTR)
continue;
+ log("(%d/%d/%s) SFTP session closing (%s).", ppid, cuid, CUNAME, "Select Error");
exit(2);
}
***************
*** 1082,1090 ****
--- 1140,1150 ----
len = read(in, buf, sizeof buf);
if (len == 0) {
debug("read eof");
+ log("(%d/%d/%s) SFTP session closing (%s).", ppid, cuid, CUNAME, "EOF");
exit(0);
} else if (len < 0) {
error("read error");
+ log("(%d/%d/%s) SFTP session closing (%s).", ppid, cuid, CUNAME, "Read Error");
exit(1);
} else {
buffer_append(&iqueue, buf, len);
***************
*** 1095,1100 ****
--- 1155,1161 ----
len = write(out, buffer_ptr(&oqueue), olen);
if (len < 0) {
error("write error");
+ log("(%d/%d/%s) SFTP session closing (%s).", ppid, cuid, CUNAME, "Write Error");
exit(1);
} else {
buffer_consume(&oqueue, len);
More information about the openssh-unix-dev
mailing list