/*
- * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
Must(http != NULL);
HttpRequest *const request = http->request;
Must(request != NULL);
-
- // this is not an idle connection, so we do not want I/O monitoring
- const bool monitor = false;
-
// make FTP peer connection exclusive to our request
- pinConnection(conn, request, conn->getPeer(), false, monitor);
+ pinBusyConnection(conn, request);
}
void
void
Ftp::Server::calcUri(const SBuf *file)
{
+ // TODO: fill a class AnyP::Uri instead of string
uri = "ftp://";
uri.append(host);
if (port->ftp_track_dirs && master->workingDir.length()) {
const SBuf *path = (params.length() && CommandHasPathParameter(cmd)) ?
¶ms : NULL;
calcUri(path);
- char *newUri = xstrdup(uri.c_str());
- HttpRequest *const request = HttpRequest::CreateFromUrl(newUri, method);
+ MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initClient);
+ mx->tcpClient = clientConnection;
+ auto * const request = HttpRequest::FromUrl(uri, mx, method);
if (!request) {
debugs(33, 5, "Invalid FTP URL: " << uri);
uri.clear();
- safe_free(newUri);
return earlyError(EarlyErrorKind::InvalidUri);
}
+ char *newUri = xstrdup(uri.c_str());
request->flags.ftpNative = true;
request->http_ver = Http::ProtocolVersion(Ftp::ProtocolVersion().major, Ftp::ProtocolVersion().minor);
}
ClientHttpRequest *const http = new ClientHttpRequest(this);
- http->request = request;
- HTTPMSGLOCK(http->request);
http->req_sz = tok.parsedSize();
http->uri = newUri;
+ http->initRequest(request);
Http::Stream *const result =
new Http::Stream(clientConnection, http);
Http::StreamPointer context = pipeline.front();
assert(context != nullptr);
- if (context->http && context->http->al != NULL &&
- !context->http->al->reply && reply) {
- context->http->al->reply = reply;
- HTTPMSGLOCK(context->http->al->reply);
- }
-
static ReplyHandler handlers[] = {
NULL, // fssBegin
NULL, // fssConnected
}
#endif
- Must(reply);
- const char *reason = reply->header.has(Http::HdrType::FTP_REASON) ?
- reply->header.getStr(Http::HdrType::FTP_REASON):
- reply->sline.reason();
+ const char *reason = "Lost Error";
+ if (reply) {
+ reason = reply->header.has(Http::HdrType::FTP_REASON) ?
+ reply->header.getStr(Http::HdrType::FTP_REASON):
+ reply->sline.reason();
+ }
mb.appendf("%i %s\r\n", scode, reason); // error terminating line
Comm::ConnectionPointer conn = new Comm::Connection();
conn->flags |= COMM_DOBIND;
- // Use local IP address of the control connection as the source address
- // of the active data connection, or some clients will refuse to accept.
- conn->setAddrs(clientConnection->local, cltAddr);
+ if (clientConnection->flags & COMM_INTERCEPTION) {
+ // In the case of NAT interception conn->local value is not set
+ // because the TCP stack will automatically pick correct source
+ // address for the data connection. We must only ensure that IP
+ // version matches client's address.
+ conn->local.setAnyAddr();
+
+ if (cltAddr.isIPv4())
+ conn->local.setIPv4();
+
+ conn->remote = cltAddr;
+ } else {
+ // In the case of explicit-proxy the local IP of the control connection
+ // is the Squid IP the client is knowingly talking to.
+ //
+ // In the case of TPROXY the IP address of the control connection is
+ // server IP the client is connecting to, it can be spoofed by Squid.
+ //
+ // In both cases some clients may refuse to accept data connections if
+ // these control connectin local-IP's are not used.
+ conn->setAddrs(clientConnection->local, cltAddr);
+
+ // Using non-local addresses in TPROXY mode requires appropriate socket option.
+ if (clientConnection->flags & COMM_TRANSPARENT)
+ conn->flags |= COMM_TRANSPARENT;
+ }
+
// RFC 959 requires active FTP connections to originate from port 20
// but that would preclude us from supporting concurrent transfers! (XXX?)
conn->local.port(0);
ClientHttpRequest *http = pipeline.front()->http;
HttpRequest *request = http->request;
ACLFilledChecklist bodyContinuationCheck(Config.accessList.forceRequestBodyContinuation, request, NULL);
- if (bodyContinuationCheck.fastCheck() == ACCESS_ALLOWED) {
+ bodyContinuationCheck.al = http->al;
+ bodyContinuationCheck.syncAle(request, http->log_uri);
+ if (bodyContinuationCheck.fastCheck().allowed()) {
request->forcedBodyContinuation = true;
if (checkDataConnPost()) {
// Write control Msg
HttpReply *const reply = Ftp::HttpReplyWrapper(code, msg, Http::scNoContent, 0);
- setLogUri(http, urlCanonicalClean(http->request));
-
clientStreamNode *const node = context->getClientReplyContext();
clientReplyContext *const repContext =
dynamic_cast<clientReplyContext *>(node->data.getRaw());
// because we want to signal the FTP user that we are not fully
// done processing its data stream, even though all data bytes
// have been sent or received already.
- debugs(33, 5, "Transfering from FTP server is not complete");
+ debugs(33, 5, "Transferring from FTP server is not complete");
return;
}
// Adjust our reply if the server aborted with an error before we are done.
if (master->userDataDone == 226 && originDataDownloadAbortedOnError) {
- debugs(33, 5, "Transfering from FTP server terminated with an error, adjust status code");
+ debugs(33, 5, "Transferring from FTP server terminated with an error, adjust status code");
master->userDataDone = 451;
}
completeDataDownload();