diff options
Diffstat (limited to 'feature-openssh-7.4-hima-sftpserver-oom-and-fix.patch')
-rw-r--r-- | feature-openssh-7.4-hima-sftpserver-oom-and-fix.patch | 911 |
1 files changed, 911 insertions, 0 deletions
diff --git a/feature-openssh-7.4-hima-sftpserver-oom-and-fix.patch b/feature-openssh-7.4-hima-sftpserver-oom-and-fix.patch new file mode 100644 index 0000000..7af483c --- /dev/null +++ b/feature-openssh-7.4-hima-sftpserver-oom-and-fix.patch @@ -0,0 +1,911 @@ +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 + |