]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 1996-2025 The Squid Software Foundation and contributors | |
3 | * | |
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. | |
7 | */ | |
8 | ||
9 | /* DEBUG: section 33 Client-side Routines */ | |
10 | ||
11 | #ifndef SQUID_SRC_SERVERS_FTPSERVER_H | |
12 | #define SQUID_SRC_SERVERS_FTPSERVER_H | |
13 | ||
14 | #include "base/JobWait.h" | |
15 | #include "base/Lock.h" | |
16 | #include "client_side.h" | |
17 | #include "comm/forward.h" | |
18 | #include "http/forward.h" | |
19 | ||
20 | namespace Ftp | |
21 | { | |
22 | ||
23 | typedef enum { | |
24 | fssBegin, | |
25 | fssConnected, | |
26 | fssHandleFeat, | |
27 | fssHandlePasv, | |
28 | fssHandlePort, | |
29 | fssHandleDataRequest, | |
30 | fssHandleUploadRequest, | |
31 | fssHandleEprt, | |
32 | fssHandleEpsv, | |
33 | fssHandleCwd, | |
34 | fssHandlePass, | |
35 | fssHandleCdup, | |
36 | fssError | |
37 | } ServerState; | |
38 | ||
39 | // TODO: This should become a part of MasterXaction when we start sending | |
40 | // master transactions to the clients/ code. | |
41 | /// Transaction information shared among our FTP client and server jobs. | |
42 | class MasterState: public RefCountable | |
43 | { | |
44 | public: | |
45 | typedef RefCount<MasterState> Pointer; | |
46 | ||
47 | MasterState(): serverState(fssBegin), clientReadGreeting(false), userDataDone(0) {} | |
48 | ||
49 | Ip::Address clientDataAddr; ///< address of our FTP client data connection | |
50 | SBuf workingDir; ///< estimated current working directory for URI formation | |
51 | ServerState serverState; ///< what our FTP server is doing | |
52 | bool clientReadGreeting; ///< whether our FTP client read their FTP server greeting | |
53 | /// Squid will send or has sent this final status code to the FTP client | |
54 | int userDataDone; | |
55 | }; | |
56 | ||
57 | /// Manages a control connection from an FTP client. | |
58 | class Server: public ConnStateData | |
59 | { | |
60 | CBDATA_CHILD(Server); | |
61 | ||
62 | public: | |
63 | explicit Server(const MasterXaction::Pointer &xact); | |
64 | ~Server() override; | |
65 | ||
66 | /* AsyncJob API */ | |
67 | void callException(const std::exception &e) override; | |
68 | ||
69 | /// Called by Ftp::Client class when it is start receiving or | |
70 | /// sending data. | |
71 | void startWaitingForOrigin(); | |
72 | ||
73 | /// Called by Ftp::Client class when it is done receiving or | |
74 | /// sending data. Waits for both agents to be done before | |
75 | /// responding to the FTP client and closing the data connection. | |
76 | void stopWaitingForOrigin(int status); | |
77 | ||
78 | // This is a pointer in hope to minimize future changes when MasterState | |
79 | // becomes a part of MasterXaction. Guaranteed not to be nil. | |
80 | MasterState::Pointer master; ///< info shared among our FTP client and server jobs | |
81 | ||
82 | protected: | |
83 | friend void StartListening(); | |
84 | ||
85 | // errors detected before it is possible to create an HTTP request wrapper | |
86 | enum class EarlyErrorKind { | |
87 | HugeRequest, | |
88 | MissingLogin, | |
89 | MissingUsername, | |
90 | MissingHost, | |
91 | UnsupportedCommand, | |
92 | InvalidUri, | |
93 | MalformedCommand | |
94 | }; | |
95 | ||
96 | /* ConnStateData API */ | |
97 | Http::Stream *parseOneRequest() override; | |
98 | void processParsedRequest(Http::StreamPointer &context) override; | |
99 | void notePeerConnection(Comm::ConnectionPointer conn) override; | |
100 | void clientPinnedConnectionClosed(const CommCloseCbParams &io) override; | |
101 | void handleReply(HttpReply *header, StoreIOBuffer receivedData) override; | |
102 | int pipelinePrefetchMax() const override; | |
103 | bool writeControlMsgAndCall(HttpReply *rep, AsyncCall::Pointer &call) override; | |
104 | time_t idleTimeout() const override; | |
105 | ||
106 | /* BodyPipe API */ | |
107 | void noteMoreBodySpaceAvailable(BodyPipe::Pointer) override; | |
108 | void noteBodyConsumerAborted(BodyPipe::Pointer ptr) override; | |
109 | ||
110 | /* AsyncJob API */ | |
111 | void start() override; | |
112 | ||
113 | /* Comm callbacks */ | |
114 | static void AcceptCtrlConnection(const CommAcceptCbParams ¶ms); | |
115 | void acceptDataConnection(const CommAcceptCbParams ¶ms); | |
116 | void readUploadData(const CommIoCbParams &io); | |
117 | void wroteEarlyReply(const CommIoCbParams &io); | |
118 | void wroteReply(const CommIoCbParams &io); | |
119 | void wroteReplyData(const CommIoCbParams &io); | |
120 | void connectedForData(const CommConnectCbParams ¶ms); | |
121 | ||
122 | unsigned int listenForDataConnection(); | |
123 | bool createDataConnection(Ip::Address cltAddr); | |
124 | void closeDataConnection(); | |
125 | ||
126 | /// Called after data transfer on client-to-squid data connection is | |
127 | /// finished. | |
128 | void userDataCompletionCheckpoint(int finalStatusCode); | |
129 | ||
130 | /// Writes the data-transfer status reply to the FTP client and | |
131 | /// closes the data connection. | |
132 | void completeDataDownload(); | |
133 | ||
134 | void calcUri(const SBuf *file); | |
135 | void changeState(const Ftp::ServerState newState, const char *reason); | |
136 | Http::Stream *handleUserRequest(const SBuf &cmd, SBuf ¶ms); | |
137 | bool checkDataConnPost() const; | |
138 | void replyDataWritingCheckpoint(); | |
139 | void maybeReadUploadData(); | |
140 | ||
141 | void setReply(const int code, const char *msg); | |
142 | void writeCustomReply(const int code, const char *msg, const HttpReply *reply = nullptr); | |
143 | void writeEarlyReply(const int code, const char *msg); | |
144 | void writeErrorReply(const HttpReply *reply, const int status); | |
145 | void writeForwardedForeign(const HttpReply *reply); | |
146 | void writeForwardedReply(const HttpReply *reply); | |
147 | void writeForwardedReplyAndCall(const HttpReply *reply, AsyncCall::Pointer &call); | |
148 | void writeReply(MemBuf &mb); | |
149 | ||
150 | Http::Stream *earlyError(const EarlyErrorKind eek); | |
151 | bool handleRequest(HttpRequest *); | |
152 | void setDataCommand(); | |
153 | bool checkDataConnPre(); | |
154 | ||
155 | /// a method handling an FTP command; selected by handleRequest() | |
156 | typedef bool (Ftp::Server::*RequestHandler)(String &cmd, String ¶ms); | |
157 | bool handleFeatRequest(String &cmd, String ¶ms); | |
158 | bool handlePasvRequest(String &cmd, String ¶ms); | |
159 | bool handlePortRequest(String &cmd, String ¶ms); | |
160 | bool handleDataRequest(String &cmd, String ¶ms); | |
161 | bool handleUploadRequest(String &cmd, String ¶ms); | |
162 | bool handleEprtRequest(String &cmd, String ¶ms); | |
163 | bool handleEpsvRequest(String &cmd, String ¶ms); | |
164 | bool handleCwdRequest(String &cmd, String ¶ms); | |
165 | bool handlePassRequest(String &cmd, String ¶ms); | |
166 | bool handleCdupRequest(String &cmd, String ¶ms); | |
167 | ||
168 | /// a method handling an FTP response; selected by handleReply() | |
169 | typedef void (Ftp::Server::*ReplyHandler)(const HttpReply *reply, StoreIOBuffer data); | |
170 | void handleFeatReply(const HttpReply *header, StoreIOBuffer receivedData); | |
171 | void handlePasvReply(const HttpReply *header, StoreIOBuffer receivedData); | |
172 | void handlePortReply(const HttpReply *header, StoreIOBuffer receivedData); | |
173 | void handleErrorReply(const HttpReply *header, StoreIOBuffer receivedData); | |
174 | void handleDataReply(const HttpReply *header, StoreIOBuffer receivedData); | |
175 | void handleUploadReply(const HttpReply *header, StoreIOBuffer receivedData); | |
176 | void handleEprtReply(const HttpReply *header, StoreIOBuffer receivedData); | |
177 | void handleEpsvReply(const HttpReply *header, StoreIOBuffer receivedData); | |
178 | ||
179 | private: | |
180 | void doProcessRequest(); | |
181 | void shovelUploadData(); | |
182 | void resetLogin(const char *reason); | |
183 | ||
184 | SBuf uri; ///< a URI reconstructed from various FTP message details | |
185 | SBuf host; ///< intended dest. of a transparently intercepted FTP conn | |
186 | bool gotEpsvAll; ///< restrict data conn setup commands to just EPSV | |
187 | AsyncCall::Pointer onDataAcceptCall; ///< who to call upon data conn acceptance | |
188 | Comm::ConnectionPointer dataListenConn; ///< data connection listening socket | |
189 | Comm::ConnectionPointer dataConn; ///< data connection | |
190 | char uploadBuf[CLIENT_REQ_BUF_SZ]; ///< data connection input buffer | |
191 | size_t uploadAvailSize; ///< number of yet unused uploadBuf bytes | |
192 | ||
193 | AsyncCall::Pointer listener; ///< set when we are passively listening | |
194 | ||
195 | /// Waits for an FTP data connection to the client to be established/opened. | |
196 | /// This wait only happens in FTP active mode (via PORT or EPRT). | |
197 | JobWait<Comm::ConnOpener> dataConnWait; | |
198 | ||
199 | AsyncCall::Pointer reader; ///< set when we are reading FTP data | |
200 | ||
201 | /// whether we wait for the origin data transfer to end | |
202 | bool waitingForOrigin; | |
203 | /// whether the origin data transfer aborted | |
204 | bool originDataDownloadAbortedOnError; | |
205 | ||
206 | /// a response which writing was postponed until stopWaitingForOrigin() | |
207 | HttpReply::Pointer delayedReply; | |
208 | }; | |
209 | ||
210 | } // namespace Ftp | |
211 | ||
212 | #endif /* SQUID_SRC_SERVERS_FTPSERVER_H */ | |
213 |