diff -r df75a8cb8663 -r b622c682317d components/proftpd/patches/013.24793845-ignoreascii.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/proftpd/patches/013.24793845-ignoreascii.patch Wed Nov 23 00:29:59 2016 -0800 @@ -0,0 +1,263 @@ +This patch is a backport of proftpd Bug#4159 from 1.3.6.rc2 to 1.3.5b. It should +be removed as soon as we sync with stable 1.3.6 release. + +This patch is hand crafted combination of following two commits. No test files +are included. + +Fix regression, caused by change for Bug#4159 with the ASCII translation handling of LIST/NLST output +https://github.com/proftpd/proftpd/commit/3892250b429661dd8d166a55230f9a0da923a26b + +Bug#4159: Support ability to disable ASCII translation transparently to FTP clients. +https://github.com/proftpd/proftpd/commit/68229c0bc839260a43ac1c9b9f7ed68e39aa0f1a + +http://bugs.proftpd.org/show_bug.cgi?id=4159 + +diff --git a/doc/modules/mod_xfer.html b/doc/modules/mod_xfer.html +index 19179fa..52b02c0 100644 +--- a/doc/modules/mod_xfer.html ++++ b/doc/modules/mod_xfer.html +@@ -33,6 +33,7 @@ file transfers. +
  • StoreUniquePrefix +
  • TimeoutNoTransfer +
  • TimeoutStalled ++
  • TransferOptions +
  • TransferPriority +
  • TransferRate +
  • UseSendfile +@@ -330,6 +331,36 @@ The maximum allowed seconds value is 65535 (108 minutes). + +

    +


    ++

    TransferOptions

    ++Syntax: TransferOptions opt1 ...
    ++Default: None
    ++Context: server config, <VirtualHost>, <Global>
    ++Module: mod_xfer
    ++Compatibility: 1.3.5b and later ++ ++

    ++The TransferOptions directive to configure various optional data ++transfer behaviors. ++ ++

    ++The currently implemented options are: ++

    ++ ++

    ++


    +

    TransferPriority

    + Syntax: TransferPriority cmd-list "low"|"medium"|"high"|number
    + Default: None
    +diff --git a/include/data.h b/include/data.h +index 4eaf5d9..fd5f9d9 100644 +--- a/include/data.h ++++ b/include/data.h +@@ -31,6 +31,11 @@ + #ifndef PR_DATACONN_H + #define PR_DATACONN_H + ++/* Toggles whether to actually perform ASCII translation during the data ++ * transfer. ++ */ ++int pr_data_ignore_ascii(int); ++ + void pr_data_init(char *, int); + void pr_data_cleanup(void); + int pr_data_open(char *, char *, int, off_t); +@@ -40,6 +45,7 @@ int pr_data_xfer(char *, size_t); + void pr_data_reset(void); + void pr_data_set_linger(long); + ++ + /* Clear the session.xfer.p pool, if present, and reset any associated + * state. + */ +diff --git a/modules/mod_xfer.c b/modules/mod_xfer.c +index de5c52a..4b75034 100644 +--- a/modules/mod_xfer.c ++++ b/modules/mod_xfer.c +@@ -61,6 +61,7 @@ static int xfer_check_limit(cmd_rec *); + + /* TransferOptions */ + #define PR_XFER_OPT_HANDLE_ALLO 0x0001 ++#define PR_XFER_OPT_IGNORE_ASCII 0x0002 + static unsigned long xfer_opts = PR_XFER_OPT_HANDLE_ALLO; + + /* Transfer priority */ +@@ -1923,7 +1924,8 @@ MODRET xfer_rest(cmd_rec *cmd) { + * clients. + */ + if ((session.sf_flags & SF_ASCII) && +- pos != 0) { ++ pos != 0 && ++ !(xfer_opts & PR_XFER_OPT_IGNORE_ASCII)) { + pr_log_debug(DEBUG5, "%s not allowed in ASCII mode", cmd->argv[0]); + pr_response_add_err(R_501, + _("%s: Resuming transfers not allowed in ASCII mode"), cmd->argv[0]); +@@ -2587,6 +2589,26 @@ MODRET xfer_post_pass(cmd_rec *cmd) { + */ + } + ++ /* ++ * Check for TransferOptions ++ */ ++ c = find_config(main_server->conf, CONF_PARAM, "TransferOptions", FALSE); ++ while (c != NULL) { ++ unsigned long opts = 0; ++ ++ pr_signals_handle(); ++ ++ opts = *((unsigned long *) c->argv[0]); ++ xfer_opts |= opts; ++ ++ c = find_config_next(c, c->next, CONF_PARAM, "TransferOptions", FALSE); ++ } ++ ++ if (xfer_opts & PR_XFER_OPT_IGNORE_ASCII) { ++ pr_log_debug(DEBUG8, "Ignoring ASCII translation for this session"); ++ pr_data_ignore_ascii(TRUE); ++ } ++ + /* Check for TransferPriority. */ + c = find_config(TOPLEVEL_CONF, CONF_PARAM, "TransferPriority", FALSE); + if (c) { +@@ -2999,6 +3021,36 @@ MODRET set_timeoutstalled(cmd_rec *cmd) { + return PR_HANDLED(cmd); + } + ++/* usage: TransferOptions opt1 opt2 ... */ ++MODRET set_transferoptions(cmd_rec *cmd) { ++ config_rec *c = NULL; ++ register unsigned int i = 0; ++ unsigned long opts = 0UL; ++ ++ if (cmd->argc-1 == 0) { ++ CONF_ERROR(cmd, "wrong number of parameters"); ++ } ++ ++ CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL); ++ ++ c = add_config_param(cmd->argv[0], 1, NULL); ++ ++ for (i = 1; i < cmd->argc; i++) { ++ if (strcasecmp(cmd->argv[i], "IgnoreASCII") == 0) { ++ opts |= PR_XFER_OPT_IGNORE_ASCII; ++ ++ } else { ++ CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown TransferOption '", ++ cmd->argv[i], "'", NULL)); ++ } ++ } ++ ++ c->argv[0] = pcalloc(c->pool, sizeof(unsigned long)); ++ *((unsigned long *) c->argv[0]) = opts; ++ ++ return PR_HANDLED(cmd); ++} ++ + /* usage: TransferPriority cmds "low"|"medium"|"high"|number + */ + MODRET set_transferpriority(cmd_rec *cmd) { +@@ -3459,6 +3511,7 @@ static conftable xfer_conftab[] = { + { "StoreUniquePrefix", set_storeuniqueprefix, NULL }, + { "TimeoutNoTransfer", set_timeoutnoxfer, NULL }, + { "TimeoutStalled", set_timeoutstalled, NULL }, ++ { "TransferOptions", set_transferoptions, NULL }, + { "TransferPriority", set_transferpriority, NULL }, + { "TransferRate", set_transferrate, NULL }, + { "UseSendfile", set_usesendfile, NULL }, +diff --git a/src/data.c b/src/data.c +index 5136f5f..0c45c77 100644 +--- a/src/data.c ++++ b/src/data.c +@@ -40,6 +40,9 @@ + + static const char *trace_channel = "data"; + ++#define PR_DATA_OPT_IGNORE_ASCII 0x0001 ++static unsigned long data_opts = 0UL; ++ + /* local macro */ + + #define MODE_STRING (session.sf_flags & (SF_ASCII|SF_ASCII_OVERRIDE) ? \ +@@ -580,6 +583,33 @@ void pr_data_reset(void) { + session.sf_flags &= (SF_ALL^(SF_ABORT|SF_POST_ABORT|SF_XFER|SF_PASSIVE|SF_ASCII_OVERRIDE|SF_EPSV_ALL)); + } + ++int pr_data_ignore_ascii(int ignore_ascii) { ++ int res; ++ ++ if (ignore_ascii != TRUE && ++ ignore_ascii != FALSE) { ++ errno = EINVAL; ++ return -1; ++ } ++ ++ if (data_opts & PR_DATA_OPT_IGNORE_ASCII) { ++ if (!ignore_ascii) { ++ data_opts &= ~PR_DATA_OPT_IGNORE_ASCII; ++ } ++ ++ res = TRUE; ++ ++ } else { ++ if (ignore_ascii) { ++ data_opts |= PR_DATA_OPT_IGNORE_ASCII; ++ } ++ ++ res = FALSE; ++ } ++ ++ return res; ++} ++ + void pr_data_init(char *filename, int direction) { + if (session.xfer.p == NULL) { + data_new_xfer(filename, direction); +@@ -1155,7 +1185,15 @@ int pr_data_xfer(char *cl_buf, size_t cl_size) { + char *buf = session.xfer.buf; + pr_buffer_t *pbuf; + +- if (session.sf_flags & (SF_ASCII|SF_ASCII_OVERRIDE)) { ++ /* We use ASCII translation if: ++ * ++ * - SF_ASCII_OVERRIDE session flag is set (e.g. for LIST/NLST) ++ * - SF_ASCII session flag is set, AND IGNORE_ASCII data opt NOT set ++ */ ++ if ((session.sf_flags & SF_ASCII_OVERRIDE) || ++ ((session.sf_flags & SF_ASCII) && ++ !(data_opts & PR_DATA_OPT_IGNORE_ASCII))) { ++ + int adjlen, buflen; + + do { +@@ -1330,8 +1368,14 @@ int pr_data_xfer(char *cl_buf, size_t cl_size) { + + /* Fill up our internal buffer. */ + memcpy(session.xfer.buf, cl_buf, buflen); +- +- if (session.sf_flags & (SF_ASCII|SF_ASCII_OVERRIDE)) { ++ /* We use ASCII translation if: ++ * ++ * - SF_ASCII_OVERRIDE session flag is set (e.g. for LIST/NLST) ++ * - SF_ASCII session flag is set, AND IGNORE_ASCII data opt NOT set ++ */ ++ if ((session.sf_flags & SF_ASCII_OVERRIDE) || ++ ((session.sf_flags & SF_ASCII) && ++ !(data_opts & PR_DATA_OPT_IGNORE_ASCII))) { + /* Scan the internal buffer, looking for LFs with no preceding CRs. + * Add CRs (and expand the internal buffer) as necessary. xferbuflen + * will be adjusted so that it contains the length of data in