912 lines
25 KiB
Diff
912 lines
25 KiB
Diff
From 6d98c61e18fe65a52e21df9cece74675f9c18125 Mon Sep 17 00:00:00 2001
|
|
From: shenyining <shenyining@huawei.com>
|
|
Date: Thu, 16 Apr 2020 17:13:24 +0800
|
|
Subject: [PATCH] sync patch, add new judgement and
|
|
delete default sftp-put-check.cfg
|
|
|
|
Signed-off-by: shenyining <shenyining@huawei.com>
|
|
|
|
---
|
|
sftp-server.c | 702 +++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
1 file changed, 690 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/sftp-server.c b/sftp-server.c
|
|
index 5677aa3..4eb06d1 100644
|
|
--- a/sftp-server.c
|
|
+++ b/sftp-server.c
|
|
@@ -30,6 +30,12 @@
|
|
#include <sys/statvfs.h>
|
|
#endif
|
|
|
|
+/* add begin sftp oom fix */
|
|
+#include <sys/sysinfo.h>
|
|
+#include <sys/vfs.h>
|
|
+#include <linux/magic.h>
|
|
+/* add end sftp oom fix */
|
|
+
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
@@ -57,6 +63,17 @@
|
|
#include "sftp.h"
|
|
#include "sftp-common.h"
|
|
|
|
+static int storage_flag = 0;
|
|
+/* add begin 2013/10/12 SR-0000287268 */
|
|
+#define RETURN_OK 0
|
|
+#define RETURN_ERROR -1
|
|
+#define FLAG_PROTECTDIR 0
|
|
+#define FLAG_PERMITOP 1
|
|
+/* add end 2013/10/12 SR-0000287268 */
|
|
+/*add for oom*/
|
|
+static int cflag = 0;
|
|
+/*add for oom end*/
|
|
+
|
|
char *sftp_realpath(const char *, char *); /* sftp-realpath.c */
|
|
|
|
/* Maximum data read that we are willing to accept */
|
|
@@ -98,6 +115,452 @@ struct Stat {
|
|
Attrib attrib;
|
|
};
|
|
|
|
+/* add begin 2013/10/12 SR-0000287268*/
|
|
+#define MAX_DIR_NUM 100
|
|
+/* sftppermit path array */
|
|
+char szPermitPath[MAX_DIR_NUM][MAXPATHLEN] = {0};
|
|
+char szDenyPath[MAX_DIR_NUM][MAXPATHLEN] = {0};
|
|
+const char *pszPermitPath = "/usr/local/etc/sftppermit.config";
|
|
+const char *pszDenyPath = "/usr/local/etc/sftpdeny.config";
|
|
+char szPermitPath_other[MAX_DIR_NUM][MAXPATHLEN] = {0};
|
|
+char szDenyPath_other[MAX_DIR_NUM][MAXPATHLEN] = {0};
|
|
+const char *pszPermitPath_other = "/usr/local/etc/other_sftppermit.config";
|
|
+const char *pszDenyPath_other= "/usr/local/etc/other_sftpdeny.config";
|
|
+static int
|
|
+read_config_file(const char* pszPath, char(*szConfigPath)[MAXPATHLEN])
|
|
+{
|
|
+ FILE *fd = NULL;
|
|
+ char *szBuffer = NULL;
|
|
+ size_t len = 0;
|
|
+ unsigned long linenum = 0;
|
|
+
|
|
+ if (NULL == pszPath)
|
|
+ {
|
|
+ debug("[sftp-server]Config file %s is NULL.\n", pszPath);
|
|
+ return RETURN_ERROR;
|
|
+ }
|
|
+
|
|
+ if (NULL == (fd = fopen(pszPath, "r")))
|
|
+ {
|
|
+ debug("[sftp-server]Open config file %s failed.\n", pszPath);
|
|
+ return RETURN_ERROR;
|
|
+ }
|
|
+
|
|
+ while (RETURN_ERROR != getline(&szBuffer, &len, fd))
|
|
+ {
|
|
+ linenum++;
|
|
+ //Fix bug exceed max permit dir 2013-10-18 begin
|
|
+ if ( linenum > MAX_DIR_NUM )
|
|
+ {
|
|
+ debug("[sftp-server]Exceed max number of config dir.\n");
|
|
+ break;
|
|
+ }
|
|
+ //Fix bug exceed max permit dir 2013-10-18 end
|
|
+ memcpy(szConfigPath[linenum-1], szBuffer , strlen(szBuffer));
|
|
+ if ( szConfigPath[linenum-1][strlen(szBuffer)-1] == '\n' )
|
|
+ {
|
|
+ szConfigPath[linenum-1][strlen(szBuffer)-1] = '\0';
|
|
+ if ( szConfigPath[linenum-1][strlen(szBuffer)-2] == '\r' )
|
|
+ {
|
|
+ szConfigPath[linenum-1][strlen(szBuffer)-2] = '\0';
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ fclose(fd);
|
|
+ storage_flag = 1;
|
|
+ return RETURN_OK;
|
|
+}
|
|
+
|
|
+static int
|
|
+path_permition_check(const char *pszPath,int iflag)
|
|
+{
|
|
+ unsigned int iCount = 0;
|
|
+ char szResolvedname[MAXPATHLEN] = {0};
|
|
+ gid_t server_user_gid, local_user_gid;
|
|
+ int path_len = 0;
|
|
+
|
|
+ if(storage_flag != 1)
|
|
+ return RETURN_OK;
|
|
+
|
|
+ if(NULL == pszPath)
|
|
+ {
|
|
+ debug("[sftp-server]Inputed param for check is NULL.\n");
|
|
+ return RETURN_ERROR;
|
|
+ }
|
|
+
|
|
+ realpath(pszPath, szResolvedname);
|
|
+ local_user_gid = pw->pw_gid;
|
|
+ server_user_gid = local_user_gid;
|
|
+ if(NULL != szResolvedname)
|
|
+ {
|
|
+ if (server_user_gid == 0)
|
|
+ {
|
|
+ for (iCount=0; iCount < MAX_DIR_NUM ; iCount++)
|
|
+ {
|
|
+ path_len = strlen(szDenyPath[iCount]);
|
|
+ if((0 != szDenyPath[iCount][0]) && (szResolvedname == strstr(szResolvedname,szDenyPath[iCount]))){
|
|
+ if(szResolvedname[path_len] == '\0' || szResolvedname[path_len] == '/')
|
|
+ return RETURN_ERROR;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (iCount=0; iCount < MAX_DIR_NUM ; iCount++)
|
|
+ {
|
|
+ path_len = strlen(szPermitPath[iCount]);
|
|
+ if((0 != szPermitPath[iCount][0])
|
|
+ && (szResolvedname == strstr(szResolvedname,szPermitPath[iCount]))
|
|
+ && (szResolvedname[path_len] == '\0' || szResolvedname[path_len] == '/'))
|
|
+ {
|
|
+ if ((FLAG_PROTECTDIR == iflag) && (0 == strcmp(szResolvedname,szPermitPath[iCount])))
|
|
+ {
|
|
+ debug("[sftp-server]Can't operate protected dir.\n");
|
|
+ return RETURN_ERROR;
|
|
+ }
|
|
+ return RETURN_OK;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ for (iCount=0; iCount < MAX_DIR_NUM ; iCount++)
|
|
+ {
|
|
+ path_len = strlen(szDenyPath_other[iCount]);
|
|
+ if((0 != szDenyPath_other[iCount][0]) && (szResolvedname == strstr(szResolvedname,szDenyPath_other[iCount])))
|
|
+ if(szResolvedname[path_len] == '\0' || szResolvedname[path_len] == '/')
|
|
+ return RETURN_ERROR;
|
|
+ }
|
|
+
|
|
+ for (iCount=0; iCount < MAX_DIR_NUM ; iCount++)
|
|
+ {
|
|
+ path_len = strlen(szPermitPath_other[iCount]);
|
|
+ if((0 != szPermitPath_other[iCount][0])
|
|
+ && (szResolvedname == strstr(szResolvedname,szPermitPath_other[iCount]))
|
|
+ && (szResolvedname[path_len] == '\0' || szResolvedname[path_len] == '/'))
|
|
+ {
|
|
+ if ((FLAG_PROTECTDIR == iflag) && (0 == strcmp(szResolvedname,szPermitPath_other[iCount])))
|
|
+ {
|
|
+ debug("[sftp-server]Can't operate protected dir.\n");
|
|
+ return RETURN_ERROR;
|
|
+ }
|
|
+ return RETURN_OK;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return RETURN_ERROR;
|
|
+}
|
|
+/* add end 2013/10/12 SR-0000287268 */
|
|
+
|
|
+/* add begin sftp oom fix */
|
|
+#define BUF_MAX_LEN 4096 /*Max lenth*/
|
|
+#define MAX_LINE_LEN 80 /*Max line lenth*/
|
|
+
|
|
+#define DEFAULT_FILESIZE 4096
|
|
+#define DEFAULT_MEMSIZE 0
|
|
+
|
|
+const char *ck_config_file_name = "/usr/local/etc/sftp-put-check.cfg";
|
|
+
|
|
+typedef struct {
|
|
+ int max_file_size;
|
|
+ int min_freemem_size;
|
|
+}CheckOptions;
|
|
+
|
|
+static CheckOptions ckoptions;
|
|
+
|
|
+/* Keyword tokens. */
|
|
+typedef enum {
|
|
+ sBadOption,
|
|
+ sMaxFileSize,
|
|
+ sMinFreeMemSize
|
|
+} checkOpCodes;
|
|
+
|
|
+static struct {
|
|
+ const char *name;
|
|
+ checkOpCodes opcode;
|
|
+} keywords[] = {
|
|
+ { "MaxFileSize", sMaxFileSize },
|
|
+ { "MinFreeMemSize", sMinFreeMemSize },
|
|
+ { NULL, sBadOption }
|
|
+};
|
|
+
|
|
+static checkOpCodes
|
|
+ck_parse_token(const char *cp, const char *filename, int linenum)
|
|
+{
|
|
+ int i;
|
|
+ for (i = 0; keywords[i].name; i++)
|
|
+ {
|
|
+ if (strcasecmp(cp, keywords[i].name) == 0)
|
|
+ {
|
|
+ return keywords[i].opcode;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ error("%s: line %d: Bad configuration option: %s", filename, linenum, cp);
|
|
+
|
|
+ return sBadOption;
|
|
+}
|
|
+static int
|
|
+ck_process_server_config_line(char *line, const char *filename, int linenum)
|
|
+{
|
|
+ char *cp, *arg, *endofnumber;
|
|
+ endofnumber = NULL;
|
|
+ cp = NULL;
|
|
+ arg = NULL;
|
|
+ int *intptr = NULL;
|
|
+ int value;
|
|
+ checkOpCodes opcode;
|
|
+
|
|
+ cp = line;
|
|
+ if ((arg = strdelim(&cp)) == NULL)
|
|
+ {
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ /* Ignore leading whitespace */
|
|
+ if (*arg == '\0')
|
|
+ {
|
|
+ arg = strdelim(&cp);
|
|
+ }
|
|
+
|
|
+ if (!arg || !*arg || *arg == '#')
|
|
+ {
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ opcode = ck_parse_token(arg, filename, linenum);
|
|
+
|
|
+ switch (opcode)
|
|
+ {
|
|
+ case sBadOption:
|
|
+ /* don't panic, but count bad ckoptions */
|
|
+ return 0;
|
|
+ case sMaxFileSize:
|
|
+ intptr = &ckoptions.max_file_size;
|
|
+ goto parse_int;
|
|
+
|
|
+ case sMinFreeMemSize:
|
|
+ intptr = &ckoptions.min_freemem_size;
|
|
+ goto parse_int;
|
|
+parse_int:
|
|
+ arg = strdelim(&cp);
|
|
+ if (!arg || *arg == '\0')
|
|
+ {
|
|
+ error("%.200s line %d: Missing argument.", filename, linenum);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (arg[0] < '0' || arg[0] > '9')
|
|
+ {
|
|
+ error("%.200s line %d: Bad number.", filename, linenum);
|
|
+ return 0;
|
|
+ }
|
|
+ /* Octal, decimal, or hex format? */
|
|
+ value = strtol(arg, &endofnumber, 0);
|
|
+ if (arg == endofnumber)
|
|
+ {
|
|
+ error("%.200s line %d: Bad number.", filename, linenum);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ *intptr = value;
|
|
+
|
|
+ break;
|
|
+ default:
|
|
+ error("%s line %d: Missing handler for opcode %s (%d) ", filename, linenum, arg, opcode);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
|
|
+ {
|
|
+ error("%s line %d: garbage at end of line; \"%.200s\". ", filename, linenum, arg);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int
|
|
+ck_load_server_config(const char *filename, char *conf)
|
|
+{
|
|
+ char line[MAX_LINE_LEN + 1], *cp;
|
|
+ cp = NULL;
|
|
+ FILE *f;
|
|
+ int lineno = 0;
|
|
+ int lenth = 0;
|
|
+
|
|
+ if ((f = fopen(filename, "r")) == NULL)
|
|
+ {
|
|
+ error("Failed to open config file: %s ,use default setting", filename);
|
|
+ return 2;
|
|
+ }
|
|
+
|
|
+ while (fgets(line, sizeof(line), f))
|
|
+ {
|
|
+ lineno++;
|
|
+ if (strlen(line) > MAX_LINE_LEN)
|
|
+ {
|
|
+ error("%s line %d too long, the max length is %d", filename, lineno, MAX_LINE_LEN);
|
|
+ fclose(f);
|
|
+ return 0;
|
|
+ }
|
|
+ /*
|
|
+ * * Trim out comments and strip whitespace
|
|
+ * * NB - preserve newlines, they are needed to reproduce
|
|
+ * * line numbers later for error messages
|
|
+ * */
|
|
+ if ((cp = strchr(line, '#')) != NULL)
|
|
+ {
|
|
+ memcpy(cp, "\n", 2);
|
|
+ }
|
|
+ cp = line + strspn(line, " \t\r");
|
|
+
|
|
+ if(lenth + strlen(cp) > BUF_MAX_LEN)
|
|
+ {
|
|
+ error("%s too big, the max size is %d!", filename, BUF_MAX_LEN);
|
|
+ fclose(f);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ memcpy(conf + lenth, cp, strlen(cp));
|
|
+
|
|
+ lenth += strlen(cp);
|
|
+ }
|
|
+
|
|
+ memcpy(conf + lenth, "\0", 1);
|
|
+
|
|
+ fclose(f);
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int
|
|
+ck_parse_server_config(const char *filename)
|
|
+{
|
|
+ int linenum, ret_load, bad_options = 0;
|
|
+ char *cp = NULL;
|
|
+ char *obuf = NULL;
|
|
+ char *cbuf = NULL;
|
|
+
|
|
+ obuf = cbuf = malloc(BUF_MAX_LEN);
|
|
+ if (cbuf == NULL)
|
|
+ {
|
|
+ error("Malloc: out of memory (allocating %lu bytes)", BUF_MAX_LEN);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ ret_load = ck_load_server_config(filename, cbuf);
|
|
+
|
|
+ if(ret_load == 0)
|
|
+ {
|
|
+ error("Config file %s is not set properly", filename);
|
|
+ free(obuf);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if(ret_load == 2)
|
|
+ {
|
|
+ debug("Load config file %s error, use default setting", filename);
|
|
+ free(obuf);
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ linenum = 1;
|
|
+ while ((cp = strsep(&cbuf, "\n")) != NULL)
|
|
+ {
|
|
+ if (!ck_process_server_config_line(cp, filename, linenum++) )
|
|
+ {
|
|
+ bad_options++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ free(obuf);
|
|
+
|
|
+ if (bad_options > 0)
|
|
+ {
|
|
+ error("%s: terminating, %d bad configuration ckoptions", filename, bad_options);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+void
|
|
+initialize_check_options(CheckOptions *ckoptions)
|
|
+{
|
|
+ memset(ckoptions, 0, sizeof(*ckoptions));
|
|
+
|
|
+ ckoptions->max_file_size = DEFAULT_FILESIZE;
|
|
+
|
|
+ ckoptions->min_freemem_size = DEFAULT_MEMSIZE;
|
|
+}
|
|
+
|
|
+static int
|
|
+check_before_write(const char *path, u_int64_t size)
|
|
+{
|
|
+ struct sysinfo meminfo;
|
|
+ u_int64_t maxfilesize = 0;
|
|
+ u_int64_t minfreememsize = 0;
|
|
+
|
|
+ if (storage_flag != 1)
|
|
+ return 1;
|
|
+
|
|
+ if (NULL == path)
|
|
+ {
|
|
+ error("process_write: Upload file is NULL.");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (cflag == 0)
|
|
+ {
|
|
+ debug3("not put file to tmpfs or ramfs, do not need check free memory");
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ debug("check file size and free mem info before write");
|
|
+
|
|
+ sysinfo(&meminfo);
|
|
+ maxfilesize = (u_int64_t)(ckoptions.max_file_size)*1024*1024;
|
|
+ minfreememsize = (u_int64_t)(ckoptions.min_freemem_size)*1024*1024;
|
|
+
|
|
+ logit("upload file :%s size %llu freeram %lu bytes MaxFileSize %lu bytes MinFreeMemSize %lu bytes.",
|
|
+ path, size, meminfo.freeram, maxfilesize, minfreememsize);
|
|
+
|
|
+ /*check file size*/
|
|
+ if (size >= maxfilesize){
|
|
+ error("process_write: file %s exceed %d MB, upload failed.", path, ckoptions.max_file_size);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /*check free mem*/
|
|
+ if (meminfo.freeram <= minfreememsize){
|
|
+ error("process_write: Memory limit set to %d MB, no space(memeroy system) left, upload failed.",
|
|
+ ckoptions.min_freemem_size);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static void
|
|
+check_fstype(const char *path)
|
|
+{
|
|
+ struct statfs buf;
|
|
+
|
|
+ memset(&buf, 0, sizeof(buf));
|
|
+ if (statfs(path, &buf) !=0)
|
|
+ {
|
|
+ error("fstype unkown, do not check free memeroy.");
|
|
+ }
|
|
+ else if (buf.f_type == TMPFS_MAGIC || buf.f_type == RAMFS_MAGIC)
|
|
+ {
|
|
+ cflag = 1;
|
|
+ }
|
|
+}
|
|
+/* add end sftp oom fix */
|
|
+
|
|
/* Packet handlers */
|
|
static void process_open(u_int32_t id);
|
|
static void process_close(u_int32_t id);
|
|
@@ -755,6 +1218,15 @@ process_open(u_int32_t id)
|
|
(r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */
|
|
(r = decode_attrib(iqueue, &a)) != 0)
|
|
fatal_fr(r, "parse");
|
|
+ /* add begin 2013/10/12 SR-0000287268 */
|
|
+ if (RETURN_OK != path_permition_check(name,FLAG_PERMITOP))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(name);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+ /* add end 2013/10/12 SR-0000287268 */
|
|
|
|
debug3("request %u: open flags %d", id, pflags);
|
|
flags = flags_from_portable(pflags);
|
|
@@ -788,6 +1260,8 @@ process_open(u_int32_t id)
|
|
(void) umask(old_umask); /* restore umask to something sane */
|
|
if (status != SSH2_FX_OK)
|
|
send_status(id, status);
|
|
+ if (storage_flag == 1)
|
|
+ check_fstype(name);
|
|
free(name);
|
|
}
|
|
|
|
@@ -820,6 +1294,17 @@ process_read(u_int32_t id)
|
|
(r = sshbuf_get_u32(iqueue, &len)) != 0)
|
|
fatal_fr(r, "parse");
|
|
|
|
+ /* add begin 2013/10/12 SR-0000287268*/
|
|
+ char *path = NULL;
|
|
+ path = handle_to_name(handle);
|
|
+ if (RETURN_OK != path_permition_check(path,FLAG_PERMITOP))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+ /* add end 2013/10/12 SR-0000287268*/
|
|
+
|
|
debug("request %u: read \"%s\" (handle %d) off %llu len %u",
|
|
id, handle_to_name(handle), handle, (unsigned long long)off, len);
|
|
if ((fd = handle_to_fd(handle)) == -1)
|
|
@@ -874,6 +1359,18 @@ process_write(u_int32_t id)
|
|
(r = sshbuf_get_string(iqueue, &data, &len)) != 0)
|
|
fatal_fr(r, "parse");
|
|
|
|
+ /* add begin 2013/10/12 SR-0000287268*/
|
|
+ char *path = NULL;
|
|
+ path = handle_to_name(handle);
|
|
+ if (RETURN_OK != path_permition_check(path,FLAG_PERMITOP))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(data);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+ /* add end 2013/10/12 SR-0000287268*/
|
|
+
|
|
debug("request %u: write \"%s\" (handle %d) off %llu len %zu",
|
|
id, handle_to_name(handle), handle, (unsigned long long)off, len);
|
|
fd = handle_to_fd(handle);
|
|
@@ -888,17 +1385,30 @@ process_write(u_int32_t id)
|
|
strerror(errno));
|
|
} else {
|
|
/* XXX ATOMICIO ? */
|
|
- ret = write(fd, data, len);
|
|
- if (ret == -1) {
|
|
- status = errno_to_portable(errno);
|
|
- error_f("write \"%.100s\": %s",
|
|
- handle_to_name(handle), strerror(errno));
|
|
- } else if ((size_t)ret == len) {
|
|
- status = SSH2_FX_OK;
|
|
- handle_update_write(handle, ret);
|
|
- } else {
|
|
- debug2_f("nothing at all written");
|
|
+ /* add begin sftp oom fix */
|
|
+ if (storage_flag == 1)
|
|
+ debug("cflag is %d",cflag);
|
|
+ if (!check_before_write(handle_to_name(handle), off)){
|
|
+ error("check file size and free mem info before write failed");
|
|
+ unlink(handle_to_name(handle));
|
|
status = SSH2_FX_FAILURE;
|
|
+ send_status(id, status);
|
|
+ free(data);
|
|
+ sftp_server_cleanup_exit(1);
|
|
+ /* add end sftp oom fix */
|
|
+ } else {
|
|
+
|
|
+ ret = write(fd, data, len);
|
|
+ if (ret < 0) {
|
|
+ error("process_write: write failed");
|
|
+ status = errno_to_portable(errno);
|
|
+ } else if ((size_t)ret == len) {
|
|
+ status = SSH2_FX_OK;
|
|
+ handle_update_write(handle, ret);
|
|
+ } else {
|
|
+ debug2("nothing at all written");
|
|
+ status = SSH2_FX_FAILURE;
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -917,6 +1427,16 @@ process_do_stat(u_int32_t id, int do_lstat)
|
|
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
|
|
fatal_fr(r, "parse");
|
|
|
|
+ /* add begin 2013/10/12 SR-0000287268 */
|
|
+ if (RETURN_OK != path_permition_check(name,FLAG_PERMITOP))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(name);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+ /* add end 2013/10/12 SR-0000287268 */
|
|
+
|
|
debug3("request %u: %sstat", id, do_lstat ? "l" : "");
|
|
verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name);
|
|
r = do_lstat ? lstat(name, &st) : stat(name, &st);
|
|
@@ -953,6 +1473,16 @@ process_fstat(u_int32_t id)
|
|
|
|
if ((r = get_handle(iqueue, &handle)) != 0)
|
|
fatal_fr(r, "parse");
|
|
+
|
|
+ char *path = NULL;
|
|
+ path = handle_to_name(handle);
|
|
+ if (RETURN_OK != path_permition_check(path,FLAG_PERMITOP))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
debug("request %u: fstat \"%s\" (handle %u)",
|
|
id, handle_to_name(handle), handle);
|
|
fd = handle_to_fd(handle);
|
|
@@ -1005,6 +1535,14 @@ process_setstat(u_int32_t id)
|
|
(r = decode_attrib(iqueue, &a)) != 0)
|
|
fatal_fr(r, "parse");
|
|
|
|
+ if (RETURN_OK != path_permition_check(name,FLAG_PROTECTDIR))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(name);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
debug("request %u: setstat name \"%s\"", id, name);
|
|
if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
|
|
logit("set \"%s\" size %llu",
|
|
@@ -1059,6 +1597,13 @@ process_fsetstat(u_int32_t id)
|
|
else {
|
|
char *name = handle_to_name(handle);
|
|
|
|
+ if (RETURN_OK != path_permition_check(name,FLAG_PROTECTDIR))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
|
|
logit("set \"%s\" size %llu",
|
|
name, (unsigned long long)a.size);
|
|
@@ -1116,6 +1661,14 @@ process_opendir(u_int32_t id)
|
|
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
|
|
fatal_fr(r, "parse");
|
|
|
|
+ if (RETURN_OK != path_permition_check(path,FLAG_PERMITOP))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(path);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
debug3("request %u: opendir", id);
|
|
logit("opendir \"%s\"", path);
|
|
dirp = opendir(path);
|
|
@@ -1170,6 +1723,9 @@ process_readdir(u_int32_t id)
|
|
strcmp(path, "/") ? "/" : "", dp->d_name);
|
|
if (lstat(pathname, &st) == -1)
|
|
continue;
|
|
+ if (RETURN_OK != path_permition_check(pathname,FLAG_PERMITOP)) {
|
|
+ continue;
|
|
+ }
|
|
stat_to_attrib(&st, &(stats[count].attrib));
|
|
stats[count].name = xstrdup(dp->d_name);
|
|
stats[count].long_name = ls_file(dp->d_name, &st,
|
|
@@ -1202,6 +1758,14 @@ process_remove(u_int32_t id)
|
|
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
|
|
fatal_fr(r, "parse");
|
|
|
|
+ if (RETURN_OK != path_permition_check(name,FLAG_PROTECTDIR))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(name);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
debug3("request %u: remove", id);
|
|
logit("remove name \"%s\"", name);
|
|
r = unlink(name);
|
|
@@ -1221,6 +1785,14 @@ process_mkdir(u_int32_t id)
|
|
(r = decode_attrib(iqueue, &a)) != 0)
|
|
fatal_fr(r, "parse");
|
|
|
|
+ if (RETURN_OK != path_permition_check(name,FLAG_PERMITOP))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(name);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
|
|
a.perm & 07777 : 0777;
|
|
debug3("request %u: mkdir", id);
|
|
@@ -1240,6 +1812,14 @@ process_rmdir(u_int32_t id)
|
|
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
|
|
fatal_fr(r, "parse");
|
|
|
|
+ if (RETURN_OK != path_permition_check(name,FLAG_PROTECTDIR))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(name);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
debug3("request %u: rmdir", id);
|
|
logit("rmdir name \"%s\"", name);
|
|
r = rmdir(name);
|
|
@@ -1264,8 +1844,12 @@ process_realpath(u_int32_t id)
|
|
}
|
|
debug3("request %u: realpath", id);
|
|
verbose("realpath \"%s\"", path);
|
|
- if (sftp_realpath(path, resolvedname) == NULL) {
|
|
- send_status(id, errno_to_portable(errno));
|
|
+ if ((sftp_realpath(path, resolvedname) == NULL)
|
|
+ || (RETURN_OK != path_permition_check(resolvedname,FLAG_PERMITOP))) {
|
|
+ if (storage_flag != 1)
|
|
+ send_status(id, errno_to_portable(errno));
|
|
+ else
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
} else {
|
|
Stat s;
|
|
attrib_clear(&s.attrib);
|
|
@@ -1286,6 +1870,16 @@ process_rename(u_int32_t id)
|
|
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
|
|
fatal_fr(r, "parse");
|
|
|
|
+ if ((RETURN_OK != path_permition_check(oldpath,FLAG_PROTECTDIR))
|
|
+ || (RETURN_OK != path_permition_check(newpath,FLAG_PROTECTDIR)))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(oldpath);
|
|
+ free(newpath);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
debug3("request %u: rename", id);
|
|
logit("rename old \"%s\" new \"%s\"", oldpath, newpath);
|
|
status = SSH2_FX_FAILURE;
|
|
@@ -1345,6 +1939,14 @@ process_readlink(u_int32_t id)
|
|
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
|
|
fatal_fr(r, "parse");
|
|
|
|
+ if (RETURN_OK != path_permition_check(path,FLAG_PERMITOP))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(path);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
debug3("request %u: readlink", id);
|
|
verbose("readlink \"%s\"", path);
|
|
if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1)
|
|
@@ -1370,6 +1972,16 @@ process_symlink(u_int32_t id)
|
|
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
|
|
fatal_fr(r, "parse");
|
|
|
|
+ if ((RETURN_OK != path_permition_check(oldpath,FLAG_PROTECTDIR))
|
|
+ || (RETURN_OK != path_permition_check(newpath,FLAG_PROTECTDIR)))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(oldpath);
|
|
+ free(newpath);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
debug3("request %u: symlink", id);
|
|
logit("symlink old \"%s\" new \"%s\"", oldpath, newpath);
|
|
/* this will fail if 'newpath' exists */
|
|
@@ -1390,6 +2002,16 @@ process_extended_posix_rename(u_int32_t id)
|
|
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
|
|
fatal_fr(r, "parse");
|
|
|
|
+ if ((RETURN_OK != path_permition_check(oldpath,FLAG_PROTECTDIR))
|
|
+ || (RETURN_OK != path_permition_check(newpath,FLAG_PROTECTDIR)))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(oldpath);
|
|
+ free(newpath);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
debug3("request %u: posix-rename", id);
|
|
logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath);
|
|
r = rename(oldpath, newpath);
|
|
@@ -1408,6 +2030,15 @@ process_extended_statvfs(u_int32_t id)
|
|
|
|
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
|
|
fatal_fr(r, "parse");
|
|
+
|
|
+ if (RETURN_OK != path_permition_check(path,FLAG_PERMITOP))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(path);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
debug3("request %u: statvfs", id);
|
|
logit("statvfs \"%s\"", path);
|
|
|
|
@@ -1426,6 +2057,17 @@ process_extended_fstatvfs(u_int32_t id)
|
|
|
|
if ((r = get_handle(iqueue, &handle)) != 0)
|
|
fatal_fr(r, "parse");
|
|
+
|
|
+ char *path = NULL;
|
|
+ path = handle_to_name(handle);
|
|
+ if (RETURN_OK != path_permition_check(path,FLAG_PERMITOP))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(path);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
debug("request %u: fstatvfs \"%s\" (handle %u)",
|
|
id, handle_to_name(handle), handle);
|
|
if ((fd = handle_to_fd(handle)) < 0) {
|
|
@@ -1448,6 +2090,15 @@ process_extended_hardlink(u_int32_t id)
|
|
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
|
|
fatal_fr(r, "parse");
|
|
|
|
+ if ((RETURN_OK != path_permition_check(oldpath,FLAG_PROTECTDIR))
|
|
+ || (RETURN_OK != path_permition_check(newpath,FLAG_PROTECTDIR)))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(oldpath);
|
|
+ free(newpath);
|
|
+ return;
|
|
+ }
|
|
+
|
|
debug3("request %u: hardlink", id);
|
|
logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath);
|
|
r = link(oldpath, newpath);
|
|
@@ -1464,6 +2115,17 @@ process_extended_fsync(u_int32_t id)
|
|
|
|
if ((r = get_handle(iqueue, &handle)) != 0)
|
|
fatal_fr(r, "parse");
|
|
+
|
|
+ char *path = NULL;
|
|
+ path = handle_to_name(handle);
|
|
+ if (RETURN_OK != path_permition_check(path,FLAG_PERMITOP))
|
|
+ {
|
|
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
|
|
+ free(path);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
debug3("request %u: fsync (handle %u)", id, handle);
|
|
verbose("fsync \"%s\"", handle_to_name(handle));
|
|
if ((fd = handle_to_fd(handle)) < 0)
|
|
@@ -2006,6 +2668,22 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handle
|
|
|
|
log_init_handler(__progname, log_level, log_facility, log_stderr, reset_handler);
|
|
|
|
+ read_config_file(pszPermitPath, szPermitPath);
|
|
+ read_config_file(pszDenyPath, szDenyPath);
|
|
+ read_config_file(pszPermitPath_other, szPermitPath_other);
|
|
+ read_config_file(pszDenyPath_other, szDenyPath_other);
|
|
+
|
|
+ if (storage_flag == 1)
|
|
+ {
|
|
+ initialize_check_options(&ckoptions);
|
|
+ debug("Parse config file: %s", ck_config_file_name);
|
|
+ if(!ck_parse_server_config(ck_config_file_name))
|
|
+ {
|
|
+ error("Failed to parse config file: %s!", ck_config_file_name);
|
|
+ sftp_server_cleanup_exit(1);
|
|
+ }
|
|
+ }
|
|
+
|
|
/*
|
|
* On platforms where we can, avoid making /proc/self/{mem,maps}
|
|
* available to the user so that sftp access doesn't automatically
|
|
--
|
|
2.27.0
|
|
|