Blob Blame History Raw
From a73dbfe3b61459e7c2806d5162b12f0957990cb3 Mon Sep 17 00:00:00 2001
From: TJ Saunders <tj@castaglia.org>
Date: Wed, 17 Jul 2019 09:48:39 -0700
Subject: [PATCH] Backport of fix for Bug#4372 to the 1.3.6 branch.

---
 NEWS               |  1 +
 contrib/mod_copy.c | 36 +++++++++++++++++++++++++++++++++---
 2 files changed, 34 insertions(+), 3 deletions(-)

#diff --git a/NEWS b/NEWS
#index c6635bd1a..048ddb3c9 100644
#--- a/NEWS
#+++ b/NEWS
#@@ -62,6 +62,7 @@
# - Bug 4332 - Symlink navigation broken after 1.3.6 update.  The changes for
#   Bug#4219 have been rolled back.
# - Issue 795 - Unable to connect to ProFTPD using TLSSessionTickets and TLSv1.3.
#+- Bug 4372 - SITE CPFR/CPTO do not honor <Limit> configurations.
# 
# 1.3.6 - Released 09-Apr-2017
# --------------------------------
diff --git a/contrib/mod_copy.c b/contrib/mod_copy.c
index 26b72a91d..c8672c40d 100644
--- a/contrib/mod_copy.c
+++ b/contrib/mod_copy.c
@@ -1,7 +1,7 @@
 /*
  * ProFTPD: mod_copy -- a module supporting copying of files on the server
  *                      without transferring the data to the client and back
- * Copyright (c) 2009-2016 TJ Saunders
+ * Copyright (c) 2009-2019 TJ Saunders
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -657,7 +657,7 @@ MODRET copy_copy(cmd_rec *cmd) {
 MODRET copy_cpfr(cmd_rec *cmd) {
   register unsigned int i;
   int res;
-  char *path = "";
+  char *cmd_name, *path = "";
   unsigned char *authenticated = NULL;
 
   if (copy_engine == FALSE) {
@@ -705,6 +705,21 @@ MODRET copy_cpfr(cmd_rec *cmd) {
     path = pstrcat(cmd->tmp_pool, path, *path ? " " : "", decoded_path, NULL);
   }
 
+  cmd_name = cmd->argv[0];
+  pr_cmd_set_name(cmd, "SITE_CPFR");
+  if (!dir_check(cmd->tmp_pool, cmd, G_READ, path, NULL)) {
+    int xerrno = EPERM;
+
+    pr_cmd_set_name(cmd, cmd_name);
+    pr_response_add_err(R_550, "%s: %s", (char *) cmd->argv[3],
+      strerror(xerrno));
+
+    pr_cmd_set_errno(cmd, xerrno);
+    errno = xerrno;
+    return PR_ERROR(cmd);
+  }
+  pr_cmd_set_name(cmd, cmd_name);
+
   res = pr_filter_allow_path(CURRENT_CONF, path);
   switch (res) {
     case 0:
@@ -758,6 +773,7 @@ MODRET copy_cpfr(cmd_rec *cmd) {
 MODRET copy_cpto(cmd_rec *cmd) {
   register unsigned int i;
   const char *from, *to = "";
+  char *cmd_name;
   unsigned char *authenticated = NULL;
 
   if (copy_engine == FALSE) {
@@ -816,6 +832,20 @@ MODRET copy_cpto(cmd_rec *cmd) {
 
   to = dir_canonical_vpath(cmd->tmp_pool, to);
 
+  cmd_name = cmd->argv[0];
+  pr_cmd_set_name(cmd, "SITE_CPTO");
+  if (!dir_check(cmd->tmp_pool, cmd, G_WRITE, to, NULL)) {
+    int xerrno = EPERM;
+
+    pr_cmd_set_name(cmd, cmd_name);
+    pr_response_add_err(R_550, "%s: %s", to, strerror(xerrno));
+
+    pr_cmd_set_errno(cmd, xerrno);
+    errno = xerrno;
+    return PR_ERROR(cmd);
+  }
+  pr_cmd_set_name(cmd, cmd_name);
+
   if (copy_paths(cmd->tmp_pool, from, to) < 0) {
     int xerrno = errno;
     const char *err_code = R_550;
@@ -940,7 +970,7 @@ static conftable copy_conftab[] = {
 
 static cmdtable copy_cmdtab[] = {
   { CMD, 	C_SITE, G_WRITE,	copy_copy,	FALSE,	FALSE, CL_MISC },
-  { CMD, 	C_SITE, G_DIRS,		copy_cpfr,	FALSE,	FALSE, CL_MISC },
+  { CMD, 	C_SITE, G_READ,		copy_cpfr,	FALSE,	FALSE, CL_MISC },
   { CMD, 	C_SITE, G_WRITE,	copy_cpto,	FALSE,	FALSE, CL_MISC },
   { POST_CMD,	C_PASS,	G_NONE,		copy_post_pass, FALSE,	FALSE },
   { LOG_CMD, 	C_SITE, G_NONE,		copy_log_site,	FALSE,	FALSE },