]> git.ipfire.org Git - thirdparty/squid.git/blame - src/clients/FtpClient.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / clients / FtpClient.cc
CommitLineData
434a79b0 1/*
bbc27441 2 * Copyright (C) 1996-2014 The Squid Software Foundation and contributors
434a79b0 3 *
bbc27441
AJ
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
434a79b0
DK
7 */
8
bbc27441
AJ
9/* DEBUG: section 09 File Transfer Protocol (FTP) */
10
434a79b0 11#include "squid.h"
f8e4867b 12#include "acl/FilledChecklist.h"
434a79b0 13#include "client_side.h"
27c841f6 14#include "clients/FtpClient.h"
434a79b0 15#include "comm/ConnOpener.h"
8ea0d847 16#include "comm/Read.h"
000e664b 17#include "comm/TcpAcceptor.h"
434a79b0
DK
18#include "comm/Write.h"
19#include "errorpage.h"
20#include "fd.h"
92ae4c86 21#include "ftp/Parsing.h"
000e664b 22#include "ip/tools.h"
27c841f6 23#include "SquidConfig.h"
54a6c0cd 24#include "SquidString.h"
27c841f6 25#include "StatCounters.h"
434a79b0
DK
26#include "tools.h"
27#include "wordlist.h"
3cc0f4e7 28
54a6c0cd 29#include <set>
434a79b0 30
27c841f6
AR
31namespace Ftp
32{
434a79b0
DK
33
34const char *const crlf = "\r\n";
35
434a79b0
DK
36static char *
37escapeIAC(const char *buf)
38{
39 int n;
40 char *ret;
41 unsigned const char *p;
42 unsigned char *r;
43
44 for (p = (unsigned const char *)buf, n = 1; *p; ++n, ++p)
45 if (*p == 255)
46 ++n;
47
48 ret = (char *)xmalloc(n);
49
50 for (p = (unsigned const char *)buf, r=(unsigned char *)ret; *p; ++p) {
51 *r = *p;
52 ++r;
53
54 if (*p == 255) {
55 *r = 255;
56 ++r;
57 }
58 }
59
60 *r = '\0';
61 ++r;
62 assert((r - (unsigned char *)ret) == n );
63 return ret;
64}
65
e7ce227f
AR
66/* Ftp::Channel */
67
434a79b0
DK
68/// configures the channel with a descriptor and registers a close handler
69void
5517260a 70Ftp::Channel::opened(const Comm::ConnectionPointer &newConn,
27c841f6 71 const AsyncCall::Pointer &aCloser)
434a79b0
DK
72{
73 assert(!Comm::IsConnOpen(conn));
74 assert(closer == NULL);
75
76 assert(Comm::IsConnOpen(newConn));
77 assert(aCloser != NULL);
78
79 conn = newConn;
80 closer = aCloser;
81 comm_add_close_handler(conn->fd, closer);
82}
83
84/// planned close: removes the close handler and calls comm_close
85void
5517260a 86Ftp::Channel::close()
434a79b0
DK
87{
88 // channels with active listeners will be closed when the listener handler dies.
89 if (Comm::IsConnOpen(conn)) {
90 comm_remove_close_handler(conn->fd, closer);
91 conn->close(); // we do not expect to be called back
92 }
93 clear();
94}
95
96void
5517260a 97Ftp::Channel::forget()
434a79b0 98{
5948d8e9
AR
99 if (Comm::IsConnOpen(conn)) {
100 commUnsetConnTimeout(conn);
434a79b0 101 comm_remove_close_handler(conn->fd, closer);
5948d8e9 102 }
29f23abf 103 clear();
434a79b0
DK
104}
105
106void
5517260a 107Ftp::Channel::clear()
434a79b0
DK
108{
109 conn = NULL;
110 closer = NULL;
111}
112
e7ce227f
AR
113/* Ftp::CtrlChannel */
114
115Ftp::CtrlChannel::CtrlChannel():
f53969cc
SM
116 buf(NULL),
117 size(0),
118 offset(0),
119 message(NULL),
120 last_command(NULL),
121 last_reply(NULL),
122 replycode(0)
434a79b0 123{
e7ce227f
AR
124 buf = static_cast<char*>(memAllocBuf(4096, &size));
125}
434a79b0 126
e7ce227f
AR
127Ftp::CtrlChannel::~CtrlChannel()
128{
129 memFreeBuf(size, buf);
130 if (message)
131 wordlistDestroy(&message);
132 safe_free(last_command);
133 safe_free(last_reply);
134}
434a79b0 135
e7ce227f
AR
136/* Ftp::DataChannel */
137
138Ftp::DataChannel::DataChannel():
f53969cc
SM
139 readBuf(NULL),
140 host(NULL),
141 port(0),
142 read_pending(false)
e7ce227f
AR
143{
144}
145
146Ftp::DataChannel::~DataChannel()
147{
148 delete readBuf;
434a79b0
DK
149}
150
73950ceb 151void
e7ce227f 152Ftp::DataChannel::addr(const Ip::Address &import)
73950ceb 153{
27c841f6
AR
154 static char addrBuf[MAX_IPSTRLEN];
155 import.toStr(addrBuf, sizeof(addrBuf));
156 xfree(host);
157 host = xstrdup(addrBuf);
158 port = import.port();
73950ceb
AR
159}
160
e7ce227f
AR
161/* Ftp::Client */
162
163Ftp::Client::Client(FwdState *fwdState):
f53969cc
SM
164 AsyncJob("Ftp::Client"),
165 ::Client(fwdState),
166 ctrl(),
167 data(),
168 state(BEGIN),
169 old_request(NULL),
170 old_reply(NULL),
171 shortenReadTimeout(false)
e7ce227f
AR
172{
173 ++statCounter.server.all.requests;
174 ++statCounter.server.ftp.requests;
175
176 ctrl.last_command = xstrdup("Connect to server");
177
178 typedef CommCbMemFunT<Client, CommCloseCbParams> Dialer;
179 const AsyncCall::Pointer closer = JobCallback(9, 5, Dialer, this,
27c841f6 180 Ftp::Client::ctrlClosed);
e7ce227f
AR
181 ctrl.opened(fwdState->serverConnection(), closer);
182}
183
5517260a 184Ftp::Client::~Client()
434a79b0
DK
185{
186 if (data.opener != NULL) {
5517260a 187 data.opener->cancel("Ftp::Client destructed");
434a79b0
DK
188 data.opener = NULL;
189 }
190 data.close();
191
434a79b0 192 safe_free(old_request);
434a79b0 193 safe_free(old_reply);
434a79b0
DK
194 fwd = NULL; // refcounted
195}
196
197void
5517260a 198Ftp::Client::start()
434a79b0
DK
199{
200 scheduleReadControlReply(0);
201}
202
adaff124 203void
5517260a 204Ftp::Client::initReadBuf()
adaff124
DK
205{
206 if (data.readBuf == NULL) {
207 data.readBuf = new MemBuf;
208 data.readBuf->init(4096, SQUID_TCP_SO_RCVBUF);
209 }
210}
211
434a79b0
DK
212/**
213 * Close the FTP server connection(s). Used by serverComplete().
214 */
215void
5517260a 216Ftp::Client::closeServer()
434a79b0
DK
217{
218 if (Comm::IsConnOpen(ctrl.conn)) {
e7ce227f 219 debugs(9, 3, "closing FTP server FD " << ctrl.conn->fd << ", this " << this);
434a79b0
DK
220 fwd->unregister(ctrl.conn);
221 ctrl.close();
222 }
223
224 if (Comm::IsConnOpen(data.conn)) {
e7ce227f 225 debugs(9, 3, "closing FTP data FD " << data.conn->fd << ", this " << this);
434a79b0
DK
226 data.close();
227 }
228
e7ce227f 229 debugs(9, 3, "FTP ctrl and data connections closed. this " << this);
434a79b0
DK
230}
231
232/**
233 * Did we close all FTP server connection(s)?
234 *
e7ce227f
AR
235 \retval true Both server control and data channels are closed. And not waiting for a new data connection to open.
236 \retval false Either control channel or data is still active.
434a79b0
DK
237 */
238bool
5517260a 239Ftp::Client::doneWithServer() const
434a79b0
DK
240{
241 return !Comm::IsConnOpen(ctrl.conn) && !Comm::IsConnOpen(data.conn);
242}
243
244void
5517260a 245Ftp::Client::failed(err_type error, int xerrno)
434a79b0 246{
e7ce227f 247 debugs(9, 3, "entry-null=" << (entry?entry->isEmpty():0) << ", entry=" << entry);
434a79b0 248
434a79b0
DK
249 const char *command, *reply;
250 const Http::StatusCode httpStatus = failedHttpStatus(error);
251 ErrorState *const ftperr = new ErrorState(error, httpStatus, fwd->request);
252 ftperr->xerrno = xerrno;
253
254 ftperr->ftp.server_msg = ctrl.message;
255 ctrl.message = NULL;
256
257 if (old_request)
258 command = old_request;
259 else
260 command = ctrl.last_command;
261
262 if (command && strncmp(command, "PASS", 4) == 0)
263 command = "PASS <yourpassword>";
264
265 if (old_reply)
266 reply = old_reply;
267 else
268 reply = ctrl.last_reply;
269
270 if (command)
271 ftperr->ftp.request = xstrdup(command);
272
273 if (reply)
274 ftperr->ftp.reply = xstrdup(reply);
275
000e664b 276 fwd->request->detailError(error, xerrno);
719c885c
AR
277 fwd->fail(ftperr);
278
279 closeServer(); // we failed, so no serverComplete()
434a79b0
DK
280}
281
282Http::StatusCode
5517260a 283Ftp::Client::failedHttpStatus(err_type &error)
434a79b0
DK
284{
285 if (error == ERR_NONE)
286 error = ERR_FTP_FAILURE;
f8e4867b 287 return error == ERR_READ_TIMEOUT ? Http::scGatewayTimeout :
27c841f6 288 Http::scBadGateway;
434a79b0
DK
289}
290
291/**
292 * DPW 2007-04-23
293 * Looks like there are no longer anymore callers that set
294 * buffered_ok=1. Perhaps it can be removed at some point.
295 */
296void
5517260a 297Ftp::Client::scheduleReadControlReply(int buffered_ok)
434a79b0 298{
e7ce227f 299 debugs(9, 3, ctrl.conn);
434a79b0
DK
300
301 if (buffered_ok && ctrl.offset > 0) {
302 /* We've already read some reply data */
303 handleControlReply();
304 } else {
305 /*
306 * Cancel the timeout on the Data socket (if any) and
307 * establish one on the control socket.
308 */
309 if (Comm::IsConnOpen(data.conn)) {
310 commUnsetConnTimeout(data.conn);
311 }
312
e7ce227f
AR
313 const time_t tout = shortenReadTimeout ?
314 min(Config.Timeout.connect, Config.Timeout.read):
315 Config.Timeout.read;
316 shortenReadTimeout = false; // we only need to do this once, after PASV
317
5517260a
AR
318 typedef CommCbMemFunT<Client, CommTimeoutCbParams> TimeoutDialer;
319 AsyncCall::Pointer timeoutCall = JobCallback(9, 5, TimeoutDialer, this, Ftp::Client::timeout);
e7ce227f 320 commSetConnTimeout(ctrl.conn, tout, timeoutCall);
434a79b0 321
5517260a
AR
322 typedef CommCbMemFunT<Client, CommIoCbParams> Dialer;
323 AsyncCall::Pointer reader = JobCallback(9, 5, Dialer, this, Ftp::Client::readControlReply);
434a79b0
DK
324 comm_read(ctrl.conn, ctrl.buf + ctrl.offset, ctrl.size - ctrl.offset, reader);
325 }
326}
327
328void
5517260a 329Ftp::Client::readControlReply(const CommIoCbParams &io)
434a79b0 330{
e7ce227f 331 debugs(9, 3, "FD " << io.fd << ", Read " << io.size << " bytes");
434a79b0
DK
332
333 if (io.size > 0) {
334 kb_incr(&(statCounter.server.all.kbytes_in), io.size);
335 kb_incr(&(statCounter.server.ftp.kbytes_in), io.size);
336 }
337
8ea0d847 338 if (io.flag == Comm::ERR_CLOSING)
434a79b0
DK
339 return;
340
341 if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
342 abortTransaction("entry aborted during control reply read");
343 return;
344 }
345
346 assert(ctrl.offset < ctrl.size);
347
8ea0d847 348 if (io.flag == Comm::OK && io.size > 0) {
434a79b0
DK
349 fd_bytes(io.fd, io.size, FD_READ);
350 }
351
8ea0d847 352 if (io.flag != Comm::OK) {
434a79b0 353 debugs(50, ignoreErrno(io.xerrno) ? 3 : DBG_IMPORTANT,
e7ce227f 354 "FTP control reply read error: " << xstrerr(io.xerrno));
434a79b0
DK
355
356 if (ignoreErrno(io.xerrno)) {
357 scheduleReadControlReply(0);
358 } else {
359 failed(ERR_READ_ERROR, io.xerrno);
360 /* failed closes ctrl.conn and frees ftpState */
361 }
362 return;
363 }
364
365 if (io.size == 0) {
366 if (entry->store_status == STORE_PENDING) {
367 failed(ERR_FTP_FAILURE, 0);
368 /* failed closes ctrl.conn and frees ftpState */
369 return;
370 }
371
372 /* XXX this may end up having to be serverComplete() .. */
373 abortTransaction("zero control reply read");
374 return;
375 }
376
377 unsigned int len =io.size + ctrl.offset;
378 ctrl.offset = len;
379 assert(len <= ctrl.size);
5948d8e9
AR
380 if (Comm::IsConnOpen(ctrl.conn))
381 commUnsetConnTimeout(ctrl.conn); // we are done waiting for ctrl reply
434a79b0
DK
382 handleControlReply();
383}
384
385void
5517260a 386Ftp::Client::handleControlReply()
434a79b0 387{
e7ce227f 388 debugs(9, 3, status());
434a79b0
DK
389
390 size_t bytes_used = 0;
391 wordlistDestroy(&ctrl.message);
434a79b0 392
a2c7f09a 393 if (!parseControlReply(bytes_used)) {
434a79b0
DK
394 /* didn't get complete reply yet */
395
396 if (ctrl.offset == ctrl.size) {
e7ce227f 397 ctrl.buf = static_cast<char*>(memReallocBuf(ctrl.buf, ctrl.size << 1, &ctrl.size));
434a79b0
DK
398 }
399
400 scheduleReadControlReply(0);
401 return;
e7ce227f 402 }
a2c7f09a
AR
403
404 assert(ctrl.message); // the entire FTP server response, line by line
405 assert(ctrl.replycode >= 0); // FTP status code (from the last line)
406 assert(ctrl.last_reply); // FTP reason (from the last line)
407
408 if (ctrl.offset == bytes_used) {
434a79b0
DK
409 /* used it all up */
410 ctrl.offset = 0;
411 } else {
412 /* Got some data past the complete reply */
413 assert(bytes_used < ctrl.offset);
414 ctrl.offset -= bytes_used;
415 memmove(ctrl.buf, ctrl.buf + bytes_used, ctrl.offset);
416 }
417
e7ce227f 418 debugs(9, 3, "state=" << state << ", code=" << ctrl.replycode);
434a79b0
DK
419}
420
421bool
5517260a 422Ftp::Client::handlePasvReply(Ip::Address &srvAddr)
434a79b0
DK
423{
424 int code = ctrl.replycode;
434a79b0 425 char *buf;
e7ce227f 426 debugs(9, 3, status());
434a79b0
DK
427
428 if (code != 227) {
429 debugs(9, 2, "PASV not supported by remote end");
430 return false;
431 }
432
433 /* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */
434 /* ANSI sez [^0-9] is undefined, it breaks on Watcom cc */
e7ce227f 435 debugs(9, 5, "scanning: " << ctrl.last_reply);
434a79b0
DK
436
437 buf = ctrl.last_reply + strcspn(ctrl.last_reply, "0123456789");
438
cff221ee
AR
439 const char *forceIp = Config.Ftp.sanitycheck ?
440 fd_table[ctrl.conn->fd].ipaddr : NULL;
73950ceb 441 if (!Ftp::ParseIpPort(buf, forceIp, srvAddr)) {
434a79b0
DK
442 debugs(9, DBG_IMPORTANT, "Unsafe PASV reply from " <<
443 ctrl.conn->remote << ": " << ctrl.last_reply);
444 return false;
445 }
446
73950ceb
AR
447 data.addr(srvAddr);
448
434a79b0
DK
449 return true;
450}
451
000e664b 452bool
5517260a 453Ftp::Client::handleEpsvReply(Ip::Address &remoteAddr)
000e664b
AR
454{
455 int code = ctrl.replycode;
456 char *buf;
e7ce227f 457 debugs(9, 3, status());
000e664b
AR
458
459 if (code != 229 && code != 522) {
460 if (code == 200) {
461 /* handle broken servers (RFC 2428 says OK code for EPSV MUST be 229 not 200) */
462 /* vsftpd for one send '200 EPSV ALL ok.' without even port info.
463 * Its okay to re-send EPSV 1/2 but nothing else. */
464 debugs(9, DBG_IMPORTANT, "Broken FTP Server at " << ctrl.conn->remote << ". Wrong accept code for EPSV");
465 } else {
466 debugs(9, 2, "EPSV not supported by remote end");
467 }
468 return sendPassive();
469 }
470
471 if (code == 522) {
e7ce227f
AR
472 /* Peer responded with a list of supported methods:
473 * 522 Network protocol not supported, use (1)
474 * 522 Network protocol not supported, use (1,2)
475 * 522 Network protocol not supported, use (2)
476 * TODO: Handle the (1,2) case which may happen after EPSV ALL. Close
477 * data + control without self-destructing and re-open from scratch.
478 */
479 debugs(9, 5, "scanning: " << ctrl.last_reply);
000e664b
AR
480 buf = ctrl.last_reply;
481 while (buf != NULL && *buf != '\0' && *buf != '\n' && *buf != '(')
482 ++buf;
483 if (buf != NULL && *buf == '\n')
484 ++buf;
485
486 if (buf == NULL || *buf == '\0') {
487 /* handle broken server (RFC 2428 says MUST specify supported protocols in 522) */
488 debugs(9, DBG_IMPORTANT, "Broken FTP Server at " << ctrl.conn->remote << ". 522 error missing protocol negotiation hints");
489 return sendPassive();
490 } else if (strcmp(buf, "(1)") == 0) {
491 state = SENT_EPSV_2; /* simulate having sent and failed EPSV 2 */
492 return sendPassive();
493 } else if (strcmp(buf, "(2)") == 0) {
494 if (Ip::EnableIpv6) {
495 /* If server only supports EPSV 2 and we have already tried that. Go straight to EPRT */
496 if (state == SENT_EPSV_2) {
497 return sendEprt();
498 } else {
499 /* or try the next Passive mode down the chain. */
500 return sendPassive();
501 }
502 } else {
503 /* Server only accept EPSV in IPv6 traffic. */
504 state = SENT_EPSV_1; /* simulate having sent and failed EPSV 1 */
505 return sendPassive();
506 }
507 } else {
508 /* handle broken server (RFC 2428 says MUST specify supported protocols in 522) */
509 debugs(9, DBG_IMPORTANT, "WARNING: Server at " << ctrl.conn->remote << " sent unknown protocol negotiation hint: " << buf);
510 return sendPassive();
511 }
512 failed(ERR_FTP_FAILURE, 0);
513 return false;
514 }
515
516 /* 229 Entering Extended Passive Mode (|||port|) */
517 /* ANSI sez [^0-9] is undefined, it breaks on Watcom cc */
518 debugs(9, 5, "scanning: " << ctrl.last_reply);
519
520 buf = ctrl.last_reply + strcspn(ctrl.last_reply, "(");
521
522 char h1, h2, h3, h4;
523 unsigned short port;
524 int n = sscanf(buf, "(%c%c%c%hu%c)", &h1, &h2, &h3, &port, &h4);
525
526 if (n < 4 || h1 != h2 || h1 != h3 || h1 != h4) {
527 debugs(9, DBG_IMPORTANT, "Invalid EPSV reply from " <<
528 ctrl.conn->remote << ": " <<
529 ctrl.last_reply);
530
531 return sendPassive();
532 }
533
534 if (0 == port) {
535 debugs(9, DBG_IMPORTANT, "Unsafe EPSV reply from " <<
536 ctrl.conn->remote << ": " <<
537 ctrl.last_reply);
538
539 return sendPassive();
540 }
541
542 if (Config.Ftp.sanitycheck) {
543 if (port < 1024) {
544 debugs(9, DBG_IMPORTANT, "Unsafe EPSV reply from " <<
545 ctrl.conn->remote << ": " <<
546 ctrl.last_reply);
547
548 return sendPassive();
549 }
550 }
551
552 remoteAddr = ctrl.conn->remote;
553 remoteAddr.port(port);
554 data.addr(remoteAddr);
555 return true;
556}
557
e7ce227f 558// FTP clients do not support EPRT and PORT commands yet.
5517260a 559// The Ftp::Client::sendEprt() will fail because of the unimplemented
000e664b
AR
560// openListenSocket() or sendPort() methods
561bool
5517260a 562Ftp::Client::sendEprt()
000e664b
AR
563{
564 if (!Config.Ftp.eprt) {
565 /* Disabled. Switch immediately to attempting old PORT command. */
566 debugs(9, 3, "EPRT disabled by local administrator");
567 return sendPort();
568 }
569
e7ce227f 570 debugs(9, 3, status());
000e664b
AR
571
572 if (!openListenSocket()) {
573 failed(ERR_FTP_FAILURE, 0);
574 return false;
575 }
576
577 debugs(9, 3, "Listening for FTP data connection with FD " << data.conn);
578 if (!Comm::IsConnOpen(data.conn)) {
e7ce227f 579 // TODO: Set error message.
000e664b
AR
580 failed(ERR_FTP_FAILURE, 0);
581 return false;
582 }
583
584 static MemBuf mb;
585 mb.reset();
586 char buf[MAX_IPSTRLEN];
587 /* RFC 2428 defines EPRT as IPv6 equivalent to IPv4 PORT command. */
588 /* Which can be used by EITHER protocol. */
589 debugs(9, 3, "Listening for FTP data connection on port" << comm_local_port(data.conn->fd) << " or port?" << data.conn->local.port());
590 mb.Printf("EPRT |%d|%s|%d|%s",
591 ( data.conn->local.isIPv6() ? 2 : 1 ),
592 data.conn->local.toStr(buf,MAX_IPSTRLEN),
593 comm_local_port(data.conn->fd), Ftp::crlf );
594
595 state = SENT_EPRT;
596 writeCommand(mb.content());
597 return true;
598}
599
600bool
5517260a 601Ftp::Client::sendPort()
000e664b
AR
602{
603 failed(ERR_FTP_FAILURE, 0);
604 return false;
605}
606
607bool
5517260a 608Ftp::Client::sendPassive()
000e664b 609{
e7ce227f 610 debugs(9, 3, status());
000e664b
AR
611
612 /** \par
613 * Checks for EPSV ALL special conditions:
614 * If enabled to be sent, squid MUST NOT request any other connect methods.
615 * If 'ALL' is sent and fails the entire FTP Session fails.
616 * NP: By my reading exact EPSV protocols maybe attempted, but only EPSV method. */
617 if (Config.Ftp.epsv_all && state == SENT_EPSV_1 ) {
618 // We are here because the last "EPSV 1" failed, but because of epsv_all
619 // no other method allowed.
620 debugs(9, DBG_IMPORTANT, "FTP does not allow PASV method after 'EPSV ALL' has been sent.");
621 failed(ERR_FTP_FAILURE, 0);
622 return false;
623 }
624
000e664b
AR
625 /// Closes any old FTP-Data connection which may exist. */
626 data.close();
627
628 /** \par
629 * Checks for previous EPSV/PASV failures on this server/session.
630 * Diverts to EPRT immediately if they are not working. */
631 if (!Config.Ftp.passive || state == SENT_PASV) {
632 sendEprt();
633 return true;
634 }
635
636 static MemBuf mb;
637 mb.reset();
638 /** \par
639 * Send EPSV (ALL,2,1) or PASV on the control channel.
640 *
641 * - EPSV ALL is used if enabled.
642 * - EPSV 2 is used if ALL is disabled and IPv6 is available and ctrl channel is IPv6.
643 * - EPSV 1 is used if EPSV 2 (IPv6) fails or is not available or ctrl channel is IPv4.
644 * - PASV is used if EPSV 1 fails.
645 */
646 switch (state) {
647 case SENT_EPSV_ALL: /* EPSV ALL resulted in a bad response. Try ther EPSV methods. */
648 if (ctrl.conn->local.isIPv6()) {
e7ce227f 649 debugs(9, 5, "FTP Channel is IPv6 (" << ctrl.conn->remote << ") attempting EPSV 2 after EPSV ALL has failed.");
000e664b
AR
650 mb.Printf("EPSV 2%s", Ftp::crlf);
651 state = SENT_EPSV_2;
652 break;
653 }
f53969cc 654 // else fall through to skip EPSV 2
000e664b 655
f8e4867b 656 case SENT_EPSV_2: /* EPSV IPv6 failed. Try EPSV IPv4 */
000e664b 657 if (ctrl.conn->local.isIPv4()) {
e7ce227f 658 debugs(9, 5, "FTP Channel is IPv4 (" << ctrl.conn->remote << ") attempting EPSV 1 after EPSV ALL has failed.");
000e664b
AR
659 mb.Printf("EPSV 1%s", Ftp::crlf);
660 state = SENT_EPSV_1;
661 break;
662 } else if (Config.Ftp.epsv_all) {
663 debugs(9, DBG_IMPORTANT, "FTP does not allow PASV method after 'EPSV ALL' has been sent.");
664 failed(ERR_FTP_FAILURE, 0);
665 return false;
666 }
f53969cc 667 // else fall through to skip EPSV 1
000e664b
AR
668
669 case SENT_EPSV_1: /* EPSV options exhausted. Try PASV now. */
e7ce227f 670 debugs(9, 5, "FTP Channel (" << ctrl.conn->remote << ") rejects EPSV connection attempts. Trying PASV instead.");
000e664b
AR
671 mb.Printf("PASV%s", Ftp::crlf);
672 state = SENT_PASV;
673 break;
674
f8e4867b
AR
675 default: {
676 bool doEpsv = true;
677 if (Config.accessList.ftp_epsv) {
678 ACLFilledChecklist checklist(Config.accessList.ftp_epsv, fwd->request, NULL);
679 doEpsv = (checklist.fastCheck() == ACCESS_ALLOWED);
680 }
681 if (!doEpsv) {
e7ce227f 682 debugs(9, 5, "EPSV support manually disabled. Sending PASV for FTP Channel (" << ctrl.conn->remote <<")");
000e664b
AR
683 mb.Printf("PASV%s", Ftp::crlf);
684 state = SENT_PASV;
685 } else if (Config.Ftp.epsv_all) {
e7ce227f 686 debugs(9, 5, "EPSV ALL manually enabled. Attempting with FTP Channel (" << ctrl.conn->remote <<")");
000e664b
AR
687 mb.Printf("EPSV ALL%s", Ftp::crlf);
688 state = SENT_EPSV_ALL;
689 } else {
690 if (ctrl.conn->local.isIPv6()) {
e7ce227f 691 debugs(9, 5, "FTP Channel (" << ctrl.conn->remote << "). Sending default EPSV 2");
000e664b
AR
692 mb.Printf("EPSV 2%s", Ftp::crlf);
693 state = SENT_EPSV_2;
694 }
695 if (ctrl.conn->local.isIPv4()) {
e7ce227f 696 debugs(9, 5, "Channel (" << ctrl.conn->remote <<"). Sending default EPSV 1");
000e664b
AR
697 mb.Printf("EPSV 1%s", Ftp::crlf);
698 state = SENT_EPSV_1;
699 }
700 }
701 break;
702 }
e7ce227f 703 }
000e664b
AR
704
705 if (ctrl.message)
706 wordlistDestroy(&ctrl.message);
707 ctrl.message = NULL; //No message to return to client.
708 ctrl.offset = 0; //reset readed response, to make room read the next response
709
710 writeCommand(mb.content());
000e664b 711
e7ce227f 712 shortenReadTimeout = true;
f8e4867b 713 return true;
000e664b
AR
714}
715
434a79b0 716void
5517260a 717Ftp::Client::connectDataChannel()
434a79b0
DK
718{
719 safe_free(ctrl.last_command);
720
721 safe_free(ctrl.last_reply);
722
723 ctrl.last_command = xstrdup("Connect to server data port");
724
73950ceb 725 // Generate a new data channel descriptor to be opened.
434a79b0 726 Comm::ConnectionPointer conn = new Comm::Connection;
8ea0d847 727 conn->setAddrs(ctrl.conn->local, data.host);
73950ceb 728 conn->local.port(0);
73950ceb 729 conn->remote.port(data.port);
8ea0d847
AR
730 conn->tos = ctrl.conn->tos;
731 conn->nfmark = ctrl.conn->nfmark;
434a79b0 732
e7ce227f 733 debugs(9, 3, "connecting to " << conn->remote);
434a79b0 734
43446566
AR
735 typedef CommCbMemFunT<Client, CommConnectCbParams> Dialer;
736 data.opener = JobCallback(9, 3, Dialer, this, Ftp::Client::dataChannelConnected);
434a79b0 737 Comm::ConnOpener *cs = new Comm::ConnOpener(conn, data.opener, Config.Timeout.connect);
73950ceb 738 cs->setHost(data.host);
434a79b0
DK
739 AsyncJob::Start(cs);
740}
741
000e664b 742bool
5517260a 743Ftp::Client::openListenSocket()
000e664b
AR
744{
745 return false;
746}
747
434a79b0
DK
748/// creates a data channel Comm close callback
749AsyncCall::Pointer
5517260a 750Ftp::Client::dataCloser()
434a79b0 751{
5517260a
AR
752 typedef CommCbMemFunT<Client, CommCloseCbParams> Dialer;
753 return JobCallback(9, 5, Dialer, this, Ftp::Client::dataClosed);
434a79b0
DK
754}
755
756/// handler called by Comm when FTP data channel is closed unexpectedly
757void
5517260a 758Ftp::Client::dataClosed(const CommCloseCbParams &io)
434a79b0 759{
e7ce227f 760 debugs(9, 4, status());
434a79b0
DK
761 if (data.listenConn != NULL) {
762 data.listenConn->close();
763 data.listenConn = NULL;
764 // NP clear() does the: data.fd = -1;
765 }
766 data.clear();
767}
768
769void
5517260a 770Ftp::Client::writeCommand(const char *buf)
434a79b0
DK
771{
772 char *ebuf;
773 /* trace FTP protocol communications at level 2 */
774 debugs(9, 2, "ftp<< " << buf);
775
776 if (Config.Ftp.telnet)
777 ebuf = escapeIAC(buf);
778 else
779 ebuf = xstrdup(buf);
780
781 safe_free(ctrl.last_command);
782
783 safe_free(ctrl.last_reply);
784
785 ctrl.last_command = ebuf;
786
787 if (!Comm::IsConnOpen(ctrl.conn)) {
e7ce227f 788 debugs(9, 2, "cannot send to closing ctrl " << ctrl.conn);
434a79b0
DK
789 // TODO: assert(ctrl.closer != NULL);
790 return;
791 }
792
5517260a 793 typedef CommCbMemFunT<Client, CommIoCbParams> Dialer;
434a79b0 794 AsyncCall::Pointer call = JobCallback(9, 5, Dialer, this,
5517260a 795 Ftp::Client::writeCommandCallback);
434a79b0
DK
796 Comm::Write(ctrl.conn, ctrl.last_command, strlen(ctrl.last_command), call, NULL);
797
798 scheduleReadControlReply(0);
799}
800
801void
5517260a 802Ftp::Client::writeCommandCallback(const CommIoCbParams &io)
434a79b0
DK
803{
804
e7ce227f 805 debugs(9, 5, "wrote " << io.size << " bytes");
434a79b0
DK
806
807 if (io.size > 0) {
808 fd_bytes(io.fd, io.size, FD_WRITE);
809 kb_incr(&(statCounter.server.all.kbytes_out), io.size);
810 kb_incr(&(statCounter.server.ftp.kbytes_out), io.size);
811 }
812
8ea0d847 813 if (io.flag == Comm::ERR_CLOSING)
434a79b0
DK
814 return;
815
816 if (io.flag) {
e7ce227f 817 debugs(9, DBG_IMPORTANT, "FTP command write error: " << io.conn << ": " << xstrerr(io.xerrno));
434a79b0
DK
818 failed(ERR_WRITE_ERROR, io.xerrno);
819 /* failed closes ctrl.conn and frees ftpState */
820 return;
821 }
822}
823
824/// handler called by Comm when FTP control channel is closed unexpectedly
825void
5517260a 826Ftp::Client::ctrlClosed(const CommCloseCbParams &io)
434a79b0 827{
e7ce227f 828 debugs(9, 4, status());
434a79b0 829 ctrl.clear();
5517260a 830 mustStop("Ftp::Client::ctrlClosed");
434a79b0
DK
831}
832
833void
5517260a 834Ftp::Client::timeout(const CommTimeoutCbParams &io)
434a79b0 835{
e7ce227f 836 debugs(9, 4, io.conn << ": '" << entry->url() << "'" );
434a79b0
DK
837
838 if (abortOnBadEntry("entry went bad while waiting for a timeout"))
839 return;
840
841 failed(ERR_READ_TIMEOUT, 0);
842 /* failed() closes ctrl.conn and frees ftpState */
843}
844
845const Comm::ConnectionPointer &
5517260a 846Ftp::Client::dataConnection() const
434a79b0
DK
847{
848 return data.conn;
849}
850
851void
5517260a 852Ftp::Client::maybeReadVirginBody()
434a79b0
DK
853{
854 // too late to read
855 if (!Comm::IsConnOpen(data.conn) || fd_table[data.conn->fd].closing())
856 return;
857
858 if (data.read_pending)
859 return;
860
adaff124
DK
861 initReadBuf();
862
434a79b0
DK
863 const int read_sz = replyBodySpace(*data.readBuf, 0);
864
aea65fec 865 debugs(9, 9, "FTP may read up to " << read_sz << " bytes");
434a79b0 866
e7ce227f 867 if (read_sz < 2) // see http.cc
434a79b0
DK
868 return;
869
870 data.read_pending = true;
871
5517260a 872 typedef CommCbMemFunT<Client, CommTimeoutCbParams> TimeoutDialer;
434a79b0 873 AsyncCall::Pointer timeoutCall = JobCallback(9, 5,
5517260a 874 TimeoutDialer, this, Ftp::Client::timeout);
434a79b0
DK
875 commSetConnTimeout(data.conn, Config.Timeout.read, timeoutCall);
876
e7ce227f 877 debugs(9,5,"queueing read on FD " << data.conn->fd);
434a79b0 878
5517260a 879 typedef CommCbMemFunT<Client, CommIoCbParams> Dialer;
434a79b0 880 entry->delayAwareRead(data.conn, data.readBuf->space(), read_sz,
5517260a 881 JobCallback(9, 5, Dialer, this, Ftp::Client::dataRead));
434a79b0
DK
882}
883
884void
5517260a 885Ftp::Client::dataRead(const CommIoCbParams &io)
434a79b0
DK
886{
887 int j;
888 int bin;
889
890 data.read_pending = false;
891
e7ce227f 892 debugs(9, 3, "FD " << io.fd << " Read " << io.size << " bytes");
434a79b0
DK
893
894 if (io.size > 0) {
895 kb_incr(&(statCounter.server.all.kbytes_in), io.size);
896 kb_incr(&(statCounter.server.ftp.kbytes_in), io.size);
897 }
898
8ea0d847 899 if (io.flag == Comm::ERR_CLOSING)
434a79b0
DK
900 return;
901
902 assert(io.fd == data.conn->fd);
903
904 if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
905 abortTransaction("entry aborted during dataRead");
906 return;
907 }
908
8ea0d847
AR
909 if (io.flag == Comm::OK && io.size > 0) {
910 debugs(9, 5, "appended " << io.size << " bytes to readBuf");
434a79b0
DK
911 data.readBuf->appended(io.size);
912#if USE_DELAY_POOLS
913 DelayId delayId = entry->mem_obj->mostBytesAllowed();
914 delayId.bytesIn(io.size);
915#endif
916 ++ IOStats.Ftp.reads;
917
918 for (j = io.size - 1, bin = 0; j; ++bin)
919 j >>= 1;
920
921 ++ IOStats.Ftp.read_hist[bin];
922 }
923
8ea0d847 924 if (io.flag != Comm::OK) {
434a79b0 925 debugs(50, ignoreErrno(io.xerrno) ? 3 : DBG_IMPORTANT,
e7ce227f 926 "FTP data read error: " << xstrerr(io.xerrno));
434a79b0
DK
927
928 if (ignoreErrno(io.xerrno)) {
434a79b0
DK
929 maybeReadVirginBody();
930 } else {
931 failed(ERR_READ_ERROR, 0);
932 /* failed closes ctrl.conn and frees ftpState */
933 return;
934 }
935 } else if (io.size == 0) {
e7ce227f 936 debugs(9, 3, "Calling dataComplete() because io.size == 0");
434a79b0
DK
937 /*
938 * DPW 2007-04-23
939 * Dangerous curves ahead. This call to dataComplete was
940 * calling scheduleReadControlReply, handleControlReply,
941 * and then ftpReadTransferDone. If ftpReadTransferDone
942 * gets unexpected status code, it closes down the control
943 * socket and our FtpStateData object gets destroyed. As
944 * a workaround we no longer set the 'buffered_ok' flag in
945 * the scheduleReadControlReply call.
946 */
947 dataComplete();
948 }
949
950 processReplyBody();
951}
952
953void
5517260a 954Ftp::Client::dataComplete()
434a79b0 955{
e7ce227f 956 debugs(9, 3,status());
434a79b0
DK
957
958 /* Connection closed; transfer done. */
959
960 /// Close data channel, if any, to conserve resources while we wait.
961 data.close();
962
963 /* expect the "transfer complete" message on the control socket */
964 /*
965 * DPW 2007-04-23
966 * Previously, this was the only place where we set the
967 * 'buffered_ok' flag when calling scheduleReadControlReply().
968 * It caused some problems if the FTP server returns an unexpected
969 * status code after the data command. FtpStateData was being
970 * deleted in the middle of dataRead().
971 */
972 /* AYJ: 2011-01-13: Bug 2581.
973 * 226 status is possibly waiting in the ctrl buffer.
974 * The connection will hang if we DONT send buffered_ok.
975 * This happens on all transfers which can be completly sent by the
976 * server before the 150 started status message is read in by Squid.
977 * ie all transfers of about one packet hang.
978 */
979 scheduleReadControlReply(1);
980}
981
982/**
983 * Quickly abort the transaction
984 *
985 \todo destruction should be sufficient as the destructor should cleanup,
e7ce227f 986 * including canceling close handlers
434a79b0
DK
987 */
988void
5517260a 989Ftp::Client::abortTransaction(const char *reason)
434a79b0 990{
e7ce227f 991 debugs(9, 3, "aborting transaction for " << reason <<
434a79b0
DK
992 "; FD " << (ctrl.conn!=NULL?ctrl.conn->fd:-1) << ", Data FD " << (data.conn!=NULL?data.conn->fd:-1) << ", this " << this);
993 if (Comm::IsConnOpen(ctrl.conn)) {
994 ctrl.conn->close();
995 return;
996 }
997
998 fwd->handleUnregisteredServerEnd();
5517260a 999 mustStop("Ftp::Client::abortTransaction");
434a79b0
DK
1000}
1001
1002/**
1003 * Cancel the timeout on the Control socket and establish one
1004 * on the data socket
1005 */
1006void
5517260a 1007Ftp::Client::switchTimeoutToDataChannel()
434a79b0
DK
1008{
1009 commUnsetConnTimeout(ctrl.conn);
1010
5517260a 1011 typedef CommCbMemFunT<Client, CommTimeoutCbParams> TimeoutDialer;
434a79b0 1012 AsyncCall::Pointer timeoutCall = JobCallback(9, 5, TimeoutDialer, this,
27c841f6 1013 Ftp::Client::timeout);
434a79b0
DK
1014 commSetConnTimeout(data.conn, Config.Timeout.read, timeoutCall);
1015}
1016
1017void
5517260a 1018Ftp::Client::sentRequestBody(const CommIoCbParams &io)
434a79b0
DK
1019{
1020 if (io.size > 0)
1021 kb_incr(&(statCounter.server.ftp.kbytes_out), io.size);
fccd4a86 1022 ::Client::sentRequestBody(io);
434a79b0
DK
1023}
1024
1025/**
1026 * called after we wrote the last byte of the request body
1027 */
1028void
5517260a 1029Ftp::Client::doneSendingRequestBody()
434a79b0 1030{
fccd4a86 1031 ::Client::doneSendingRequestBody();
e7ce227f 1032 debugs(9, 3, status());
434a79b0
DK
1033 dataComplete();
1034 /* NP: RFC 959 3.3. DATA CONNECTION MANAGEMENT
1035 * if transfer type is 'stream' call dataComplete()
1036 * otherwise leave open. (reschedule control channel read?)
1037 */
1038}
1039
a2c7f09a
AR
1040/// Parses FTP server control response into ctrl structure fields,
1041/// setting bytesUsed and returning true on success.
1042bool
5517260a 1043Ftp::Client::parseControlReply(size_t &bytesUsed)
434a79b0
DK
1044{
1045 char *s;
1046 char *sbuf;
1047 char *end;
1048 int usable;
1049 int complete = 0;
1050 wordlist *head = NULL;
1051 wordlist *list;
1052 wordlist **tail = &head;
434a79b0 1053 size_t linelen;
e7ce227f 1054 debugs(9, 3, status());
434a79b0
DK
1055 /*
1056 * We need a NULL-terminated buffer for scanning, ick
1057 */
a2c7f09a 1058 const size_t len = ctrl.offset;
434a79b0 1059 sbuf = (char *)xmalloc(len + 1);
a2c7f09a 1060 xstrncpy(sbuf, ctrl.buf, len + 1);
434a79b0
DK
1061 end = sbuf + len - 1;
1062
1063 while (*end != '\r' && *end != '\n' && end > sbuf)
1064 --end;
1065
1066 usable = end - sbuf;
1067
e7ce227f 1068 debugs(9, 3, "usable = " << usable);
434a79b0
DK
1069
1070 if (usable == 0) {
e7ce227f 1071 debugs(9, 3, "didn't find end of line");
434a79b0 1072 safe_free(sbuf);
a2c7f09a 1073 return false;
434a79b0
DK
1074 }
1075
e7ce227f 1076 debugs(9, 3, len << " bytes to play with");
434a79b0
DK
1077 ++end;
1078 s = sbuf;
1079 s += strspn(s, crlf);
1080
1081 for (; s < end; s += strcspn(s, crlf), s += strspn(s, crlf)) {
1082 if (complete)
1083 break;
1084
e7ce227f 1085 debugs(9, 5, "s = {" << s << "}");
434a79b0
DK
1086
1087 linelen = strcspn(s, crlf) + 1;
1088
1089 if (linelen < 2)
1090 break;
1091
1092 if (linelen > 3)
1093 complete = (*s >= '0' && *s <= '9' && *(s + 3) == ' ');
1094
434a79b0
DK
1095 list = new wordlist();
1096
a2c7f09a 1097 list->key = (char *)xmalloc(linelen);
434a79b0 1098
a2c7f09a 1099 xstrncpy(list->key, s, linelen);
434a79b0
DK
1100
1101 /* trace the FTP communication chat at level 2 */
a2c7f09a
AR
1102 debugs(9, 2, "ftp>> " << list->key);
1103
1104 if (complete) {
1105 // use list->key for last_reply because s contains the new line
1106 ctrl.last_reply = xstrdup(list->key + 4);
1107 ctrl.replycode = atoi(list->key);
1108 }
434a79b0
DK
1109
1110 *tail = list;
1111
1112 tail = &list->next;
1113 }
1114
a2c7f09a 1115 bytesUsed = static_cast<size_t>(s - sbuf);
434a79b0
DK
1116 safe_free(sbuf);
1117
a2c7f09a 1118 if (!complete) {
434a79b0 1119 wordlistDestroy(&head);
a2c7f09a
AR
1120 return false;
1121 }
434a79b0 1122
a2c7f09a
AR
1123 ctrl.message = head;
1124 assert(ctrl.replycode >= 0);
1125 assert(ctrl.last_reply);
1126 assert(ctrl.message);
1127 return true;
434a79b0
DK
1128}
1129
1130}; // namespace Ftp
f53969cc 1131