--- sftp-server.c.orig 2003-03-26 00:01:11.000000000 -0500 +++ sftp-server.c 2003-09-24 13:25:02.000000000 -0400 @@ -52,6 +52,15 @@ /* Version of client */ int version; +#ifdef SFTP_LOGGING +/* User information. */ +#define CUNAME cuname ? cuname : "UNKNOWN" +struct passwd *upw; +uid_t cuid; +pid_t ppid; +char *cuname; +#endif + /* portable attibutes, etc. */ typedef struct Stat Stat; @@ -93,6 +102,25 @@ return ret; } +#ifdef SFTP_LOGGING +char* +status_to_logstr(int status) +{ + switch (status) { + case SSH2_FX_OK: + return "Successful"; + case SSH2_FX_NO_SUCH_FILE: + return "No such file or directory"; + case SSH2_FX_PERMISSION_DENIED: + return "Permission denied."; + case SSH2_FX_BAD_MESSAGE: + return "Bad message"; + default: + return "Unknown error"; + } +} +#endif + static int flags_from_portable(int pflags) { @@ -115,6 +143,31 @@ return flags; } +#ifdef SFTP_LOGGING +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'; + return; +} +#endif + static Attrib * get_attrib(void) { @@ -372,6 +425,9 @@ version = get_int(); TRACE("client version %d", version); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) Client version %d.", ppid, cuid, CUNAME, version); +#endif buffer_init(&msg); buffer_put_char(&msg, SSH2_FXP_VERSION); buffer_put_int(&msg, SSH2_FILEXFER_VERSION); @@ -385,6 +441,9 @@ u_int32_t id, pflags; Attrib *a; char *name; +#ifdef SFTP_LOGGING + char sflags[7] = "------"; +#endif int handle, fd, flags, mode, status = SSH2_FX_FAILURE; id = get_int(); @@ -392,18 +451,30 @@ pflags = get_int(); /* portable flags */ a = get_attrib(); flags = flags_from_portable(pflags); +#ifdef SFTP_LOGGING + sflags_from_portable(&sflags[0], pflags); +#endif mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; TRACE("open id %u name %s flags %d mode 0%o", id, name, pflags, mode); fd = open(name, flags, mode); if (fd < 0) { status = errno_to_portable(errno); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) File/Dir open failed - %s: %s (%s,%04o)", ppid, cuid, CUNAME, status_to_logstr(status), name, sflags, mode); +#endif } else { handle = handle_new(HANDLE_FILE, name, fd, NULL); if (handle < 0) { close(fd); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) File/Dir open failed - Could not allocate SFTP handle: %s (%s,%04o).", ppid, cuid, CUNAME, name, sflags, mode); +#endif } else { send_handle(id, handle); status = SSH2_FX_OK; +#ifdef SFTP_LOGGING + log("(%d/%d/%s) File/Dir opened: %s (%s,%04o).", ppid, cuid, CUNAME, name, sflags, mode); +#endif } } if (status != SSH2_FX_OK) @@ -592,23 +663,48 @@ TRACE("setstat id %u name %s", id, name); if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { ret = truncate(name, a->size); - if (ret == -1) + if (ret == -1) { status = errno_to_portable(errno); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) Truncate file failed - %s: %s.", ppid, cuid, CUNAME, status_to_logstr(status), name); + } else { + log("(%d/%d/%s) Truncated file: %s.", ppid, cuid, CUNAME, name); +#endif + } + } if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { ret = chmod(name, a->perm & 0777); - if (ret == -1) + if (ret == -1) { status = errno_to_portable(errno); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) Set file/dir permissions failed - %s: %s (%04o).", ppid, cuid, CUNAME, status_to_logstr(status), name, a->perm & 0777); + } else { + log("(%d/%d/%s) Set file/dir permissions: %s (%04o).", ppid, cuid, CUNAME, name, a->perm & 0777); +#endif + } } if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { ret = utimes(name, attrib_to_tv(a)); - if (ret == -1) + if (ret == -1) { status = errno_to_portable(errno); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) Set file/dir times failed - %s: %s.", ppid, cuid, CUNAME, status_to_logstr(status), name); + } else { + log("(%d/%d/%s) Set file/dir times: %s.", ppid, cuid, CUNAME, name); +#endif + } } if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { ret = chown(name, a->uid, a->gid); - if (ret == -1) + if (ret == -1) { status = errno_to_portable(errno); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) Set file/dir owner/group failed - %s: %s (%d/%d).", ppid, cuid, CUNAME, status_to_logstr(status), name, a->uid, a->gid); + } else { + log("(%d/%d/%s) Set file/dir owner/group: %s (%d/%d).", ppid, cuid, CUNAME, name, a->uid, a->gid); +#endif + } } send_status(id, status); xfree(name); @@ -631,11 +727,20 @@ name = handle_to_name(handle); if (fd < 0 || name == NULL) { status = SSH2_FX_FAILURE; +#ifdef SFTP_LOGGING + log("(%d/%d/%s) Set file/dir stats failed - could not get name from handle: %d.", ppid, cuid, CUNAME, handle); +#endif } else { if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { ret = ftruncate(fd, a->size); - if (ret == -1) + if (ret == -1) { status = errno_to_portable(errno); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) Truncate file failed - %s: %s.", ppid, cuid, CUNAME, status_to_logstr(status), name); + } else { + log("(%d/%d/%s) Truncated file: %s.", ppid, cuid, CUNAME, name); +#endif + } } if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { #ifdef HAVE_FCHMOD @@ -643,8 +748,14 @@ #else ret = chmod(name, a->perm & 0777); #endif - if (ret == -1) + if (ret == -1) { status = errno_to_portable(errno); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) Set file/dir permissions failed - %s: %s (%04o).", ppid, cuid, CUNAME, status_to_logstr(status), name, a->perm & 0777); + } else { + log("(%d/%d/%s) Set file/dir permissions: %s (%04o).", ppid, cuid, CUNAME, name, a->perm & 0777); +#endif + } } if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { #ifdef HAVE_FUTIMES @@ -652,8 +763,14 @@ #else ret = utimes(name, attrib_to_tv(a)); #endif - if (ret == -1) + if (ret == -1) { status = errno_to_portable(errno); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) Set file/dir times failed - %s: %s.", ppid, cuid, CUNAME, status_to_logstr(status), name); + } else { + log("(%d/%d/%s) Set file/dir times: %s.", ppid, cuid, CUNAME, name); +#endif + } } if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { #ifdef HAVE_FCHOWN @@ -661,8 +778,14 @@ #else ret = chown(name, a->uid, a->gid); #endif - if (ret == -1) + if (ret == -1) { status = errno_to_portable(errno); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) Set file/dir owner/group failed - %s: %s (%d/%d).", ppid, cuid, CUNAME, status_to_logstr(status), name, a->uid, a->gid); + } else { + log("(%d/%d/%s) Set file/dir owner/group: %s (%d/%d).", ppid, cuid, CUNAME, name, a->uid, a->gid); +#endif + } } } send_status(id, status); @@ -764,7 +887,17 @@ name = get_string(NULL); TRACE("remove id %u name %s", id, name); ret = unlink(name); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; + if (ret == -1) { + status = errno_to_portable(errno); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) File deletion failed - %s: %s.", ppid, cuid, CUNAME, status_to_logstr(status), name); +#endif + } else { + status = SSH2_FX_OK; +#ifdef SFTP_LOGGING + log("(%d/%d/%s) File deleted: %s.", ppid, cuid, CUNAME, name); +#endif +} send_status(id, status); xfree(name); } @@ -784,7 +917,18 @@ a->perm & 0777 : 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; + if (ret == -1) { + status = errno_to_portable(errno); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) Directory creation failed - %s: %s.", ppid, cuid, CUNAME, status_to_logstr(status), name); +#endif + } else { + status = SSH2_FX_OK; +#ifdef SFTP_LOGGING + log("(%d/%d/%s) Directory created: %s.", ppid, cuid, CUNAME, name); +#endif + } + send_status(id, status); xfree(name); } @@ -800,7 +944,18 @@ name = get_string(NULL); TRACE("rmdir id %u name %s", id, name); ret = rmdir(name); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; + if (ret == -1) { + status = errno_to_portable(errno); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) Directory deletion failed - %s: %s.", ppid, cuid, CUNAME, status_to_logstr(status), name); +#endif + } else { + status = SSH2_FX_OK; +#ifdef SFTP_LOGGING + log("(%d/%d/%s) Directory deleted: %s.", ppid, cuid, CUNAME, name); +#endif + } + send_status(id, status); xfree(name); } @@ -843,23 +998,43 @@ newpath = get_string(NULL); TRACE("rename id %u old %s new %s", id, oldpath, newpath); status = SSH2_FX_FAILURE; - if (lstat(oldpath, &sb) == -1) + if (lstat(oldpath, &sb) == -1) { status = errno_to_portable(errno); - else if (S_ISREG(sb.st_mode)) { +#ifdef SFTP_LOGGING + log("(%d/%d/%s) File/Dir renaming failed - %s: %s -> %s.", ppid, cuid, CUNAME, status_to_logstr(status), oldpath, newpath); +#endif + } else if (S_ISREG(sb.st_mode)) { /* Race-free rename of regular files */ - if (link(oldpath, newpath) == -1) + if (link(oldpath, newpath) == -1) { status = errno_to_portable(errno); - else if (unlink(oldpath) == -1) { +#ifdef SFTP_LOGGING + log("(%d/%d/%s) File/Dir renaming failed - %s: %s -> %s.", ppid, cuid, CUNAME, status_to_logstr(status), oldpath, newpath); +#endif + } else if (unlink(oldpath) == -1) { status = errno_to_portable(errno); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) File/Dir renaming failed - %s: %s -> %s.", ppid, cuid, CUNAME, status_to_logstr(status), oldpath, newpath); +#endif /* clean spare link */ unlink(newpath); - } else + } else { status = SSH2_FX_OK; +#ifdef SFTP_LOGGING + log("(%d/%d/%s) File/Dir renamed: %s -> %s.", ppid, cuid, CUNAME, oldpath, newpath); +#endif + } } else if (stat(newpath, &sb) == -1) { - if (rename(oldpath, newpath) == -1) + if (rename(oldpath, newpath) == -1) { status = errno_to_portable(errno); - else +#ifdef SFTP_LOGGING + log("(%d/%d/%s) File/Dir renaming failed - %s: %s -> %s.", ppid, cuid, CUNAME, status_to_logstr(status), oldpath, newpath); +#endif + } else { status = SSH2_FX_OK; +#ifdef SFTP_LOGGING + log("(%d/%d/%s) File/Dir renamed: %s -> %s.", ppid, cuid, CUNAME, oldpath, newpath); +#endif + } } send_status(id, status); xfree(oldpath); @@ -917,6 +1092,9 @@ id = get_int(); request = get_string(NULL); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) Extended operation attempted - Ignoring.", ppid, cuid, CUNAME); +#endif send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */ xfree(request); } @@ -939,6 +1117,9 @@ msg_len = GET_32BIT(cp); if (msg_len > 256 * 1024) { error("bad message "); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) SFTP session closing (%s).", ppid, cuid, CUNAME, "Bad Message"); +#endif exit(11); } if (buf_len < msg_len + 4) @@ -1033,6 +1214,25 @@ __progname = get_progname(av[0]); handle_init(); +#ifdef SFTP_LOGGING + /* Initialize the username of the user running the process. */ + cuid = getuid(); + if ((upw = getpwuid(cuid)) == NULL) { + cuname = NULL; + } else { + cuname = xstrdup(upw->pw_name); + } + + /* Initialize the parent process ID. */ + ppid = getppid(); + + /* Initialize the logfile. */ + log_init("sftp-server", SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0); + + /* Log session start. */ + log("(%d/%d/%s) SFTP session started.", ppid, cuid, CUNAME); +#endif + #ifdef DEBUG_SFTP_SERVER log_init("sftp-server", SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 0); #endif @@ -1070,6 +1270,9 @@ if (select(max+1, rset, wset, NULL, NULL) < 0) { if (errno == EINTR) continue; +#ifdef SFTP_LOGGING + log("(%d/%d/%s) SFTP session closing (%s).", ppid, cuid, CUNAME, "Select Error"); +#endif exit(2); } @@ -1079,9 +1282,15 @@ len = read(in, buf, sizeof buf); if (len == 0) { debug("read eof"); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) SFTP session closing (%s).", ppid, cuid, CUNAME, "EOF"); +#endif exit(0); } else if (len < 0) { error("read error"); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) SFTP session closing (%s).", ppid, cuid, CUNAME, "Read Error"); +#endif exit(1); } else { buffer_append(&iqueue, buf, len); @@ -1092,6 +1301,9 @@ len = write(out, buffer_ptr(&oqueue), olen); if (len < 0) { error("write error"); +#ifdef SFTP_LOGGING + log("(%d/%d/%s) SFTP session closing (%s).", ppid, cuid, CUNAME, "Write Error"); +#endif exit(1); } else { buffer_consume(&oqueue, len);