static void free_sslproxy_ssl_bump(acl_access **ssl_bump);
#endif /* USE_OPENSSL */
+static void parse_ftp_epsv(acl_access **ftp_epsv);
+static void dump_ftp_epsv(StoreEntry *entry, const char *name, acl_access *ftp_epsv);
+static void free_ftp_epsv(acl_access **ftp_epsv);
+
static void parse_b_size_t(size_t * var);
static void parse_b_int64_t(int64_t * var);
notes->clean();
}
+static bool FtpEspvDeprecated = false;
+static void parse_ftp_epsv(acl_access **ftp_epsv)
+{
+ allow_t ftpEpsvDeprecatedAction;
+ bool ftpEpsvIsDeprecatedRule = false;
+
+ char *t = ConfigParser::PeekAtToken();
+ if (!t){
+ self_destruct();
+ return;
+ }
+
+ if (!strcmp(t, "off")) {
+ (void)ConfigParser::NextToken();
+ ftpEpsvIsDeprecatedRule = true;
+ ftpEpsvDeprecatedAction = allow_t(ACCESS_DENIED);
+ } else if (!strcmp(t, "on")) {
+ (void)ConfigParser::NextToken();
+ ftpEpsvIsDeprecatedRule = true;
+ ftpEpsvDeprecatedAction = allow_t(ACCESS_ALLOWED);
+ }
+
+ // Check for mixing "ftp_epsv on|off" and "ftp_epsv allow|deny .." rules:
+ // 1) if this line is "ftp_epsv allow|deny ..." and already exist rules of "ftp_epsv on|off"
+ // 2) if this line is "ftp_epsv on|off" and already exist rules of "ftp_epsv allow|deny ..."
+ // then abort
+ if ((!ftpEpsvIsDeprecatedRule && FtpEspvDeprecated) ||
+ (ftpEpsvIsDeprecatedRule && !FtpEspvDeprecated && *ftp_epsv != NULL)) {
+ debugs(3, DBG_CRITICAL, "FATAL: do not mix \"ftp_epsv on|off\" cfg lines with \"ftp_epsv allow|deny ...\" cfg lines. Update your ftp_epsv rules.");
+ self_destruct();
+ }
+
+ if (ftpEpsvIsDeprecatedRule) {
+ // overwrite previous ftp_epsv lines
+ delete *ftp_epsv;
+ if (ftpEpsvDeprecatedAction == allow_t(ACCESS_DENIED)) {
+ Acl::AndNode *ftpEpsvRule = new Acl::AndNode;
+ ftpEpsvRule->context("(ftp_epsv rule)", config_input_line);
+ ACL *a = ACL::FindByName("all");
+ if (!a) {
+ self_destruct();
+ return;
+ }
+ ftpEpsvRule->add(a);
+ *ftp_epsv = new Acl::Tree;
+ (*ftp_epsv)->context("(ftp_epsv rules)", config_input_line);
+ (*ftp_epsv)->add(ftpEpsvRule, ftpEpsvDeprecatedAction);
+ } else
+ *ftp_epsv = NULL;
+ FtpEspvDeprecated = true;
+ } else {
+ aclParseAccessLine(cfg_directive, LegacyParser, ftp_epsv);
+ }
+}
+
+static void dump_ftp_epsv(StoreEntry *entry, const char *name, acl_access *ftp_epsv)
+{
+ if (ftp_epsv) {
+ wordlist *lines = ftp_epsv->treeDump(name, NULL);
+ dump_wordlist(entry, lines);
+ wordlistDestroy(&lines);
+ }
+}
+
+static void free_ftp_epsv(acl_access **ftp_epsv)
+{
+ free_acl_access(ftp_epsv);
+ FtpEspvDeprecated = false;
+}
+
static void
parse_configuration_includes_quoted_values(bool *recognizeQuotedValues)
{
DOC_END
NAME: ftp_epsv
-TYPE: onoff
-DEFAULT: on
-LOC: Config.Ftp.epsv
+TYPE: ftp_epsv
+DEFAULT: none
+LOC: Config.accessList.ftp_epsv
DOC_START
FTP Protocol extensions permit the use of a special "EPSV" command.
and therefore, translation of the data portion of the segments
will never be needed.
- Turning this OFF will prevent EPSV being attempted.
- WARNING: Doing so will convert Squid back to the old behavior with all
- the related problems with external NAT devices/layers.
+ EPSV is often required to interoperate with FTP servers on IPv6
+ networks. On the other hand, it may break some IPv4 servers.
+
+ By default, EPSV may try EPSV with any FTP server. To fine tune
+ that decision, you may restrict EPSV to certain clients or servers
+ using ACLs:
+
+ ftp_epsv allow|deny al1 acl2 ...
+
+ WARNING: Disabling EPSV may cause problems with external NAT and IPv6.
+ Only fast ACLs are supported.
Requires ftp_passive to be ON (default) for any effect.
DOC_END
*/
#include "squid.h"
+#include "acl/FilledChecklist.h"
#include "comm.h"
#include "comm/ConnOpener.h"
#include "comm/TcpAcceptor.h"
ftpState->state = SENT_PASV;
break;
- default:
- if (!Config.Ftp.epsv) {
+ default: {
+ bool doEpsv = true;
+ if (Config.accessList.ftp_epsv) {
+ ACLFilledChecklist checklist(Config.accessList.ftp_epsv, ftpState->fwd->request, NULL);
+ doEpsv = (checklist.fastCheck() == ACCESS_ALLOWED);
+ }
+ if (!doEpsv) {
debugs(9, 5, HERE << "EPSV support manually disabled. Sending PASV for FTP Channel (" << ftpState->ctrl.conn->remote <<")");
snprintf(cbuf, CTRL_BUFLEN, "PASV\r\n");
ftpState->state = SENT_PASV;
ftpState->state = SENT_EPSV_1;
}
}
+ }
break;
}