dnscrypto-proxy: Support files updated.
[tomato.git] / release / src / router / vsftpd / prelogin.c
blob4c11a76573a89ebee1a29c41a6007684a8b6c23a
1 /*
2 * Part of Very Secure FTPd
3 * Licence: GPL v2
4 * Author: Chris Evans
5 * prelogin.c
7 * Code to parse the FTP protocol prior to a successful login.
8 */
10 #include "prelogin.h"
11 #include "ftpcmdio.h"
12 #include "ftpcodes.h"
13 #include "str.h"
14 #include "vsftpver.h"
15 #include "tunables.h"
16 #include "oneprocess.h"
17 #include "twoprocess.h"
18 #include "sysdeputil.h"
19 #include "sysutil.h"
20 #include "session.h"
21 #include "banner.h"
22 #include "logging.h"
23 #include "ssl.h"
24 #include "features.h"
25 #include "defs.h"
26 #include "opts.h"
28 /* Functions used */
29 static void check_limits(struct vsf_session* p_sess);
30 static void emit_greeting(struct vsf_session* p_sess);
31 static void parse_username_password(struct vsf_session* p_sess);
32 static void handle_user_command(struct vsf_session* p_sess);
33 static void handle_pass_command(struct vsf_session* p_sess);
34 static void handle_get(struct vsf_session* p_sess);
35 static void check_login_delay();
36 static void check_login_fails(struct vsf_session* p_sess);
38 void
39 init_connection(struct vsf_session* p_sess)
41 if (tunable_setproctitle_enable)
43 vsf_sysutil_setproctitle("not logged in");
45 /* Before we talk to the remote, make sure an alarm is set up in case
46 * writing the initial greetings should block.
48 vsf_cmdio_set_alarm(p_sess);
49 /* Check limits before doing an implicit SSL handshake, to avoid DoS
50 * attacks. This will result in plain text messages being sent to the SSL
51 * client, but we can live with that.
53 check_limits(p_sess);
54 if (tunable_ssl_enable && tunable_implicit_ssl)
56 ssl_control_handshake(p_sess);
58 if (tunable_ftp_enable)
60 emit_greeting(p_sess);
62 parse_username_password(p_sess);
65 static void
66 check_limits(struct vsf_session* p_sess)
68 struct mystr str_log_line = INIT_MYSTR;
69 /* Check for client limits (standalone mode only) */
70 if (tunable_max_clients > 0 &&
71 p_sess->num_clients > tunable_max_clients)
73 str_alloc_text(&str_log_line, "Connection refused: too many sessions.");
74 vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);
75 vsf_cmdio_write_exit(p_sess, FTP_TOO_MANY_USERS,
76 "There are too many connected users, please try later.");
78 if (tunable_max_per_ip > 0 &&
79 p_sess->num_this_ip > tunable_max_per_ip)
81 str_alloc_text(&str_log_line,
82 "Connection refused: too many sessions for this address.");
83 vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);
84 vsf_cmdio_write_exit(p_sess, FTP_IP_LIMIT,
85 "There are too many connections from your internet address.");
87 if (!p_sess->tcp_wrapper_ok)
89 str_alloc_text(&str_log_line,
90 "Connection refused: tcp_wrappers denial.");
91 vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);
92 vsf_cmdio_write_exit(p_sess, FTP_IP_DENY, "Service not available.");
94 vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);
97 static void
98 emit_greeting(struct vsf_session* p_sess)
100 if (!str_isempty(&p_sess->banner_str))
102 vsf_banner_write(p_sess, &p_sess->banner_str, FTP_GREET);
103 str_free(&p_sess->banner_str);
104 vsf_cmdio_write(p_sess, FTP_GREET, "");
106 else if (tunable_ftpd_banner == 0)
108 vsf_cmdio_write(p_sess, FTP_GREET, "(vsFTPd " VSF_VERSION
109 ")");
111 else
113 vsf_cmdio_write(p_sess, FTP_GREET, tunable_ftpd_banner);
117 static void
118 parse_username_password(struct vsf_session* p_sess)
120 while (1)
122 vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str,
123 &p_sess->ftp_arg_str, 1);
124 if (tunable_ftp_enable)
126 if (str_equal_text(&p_sess->ftp_cmd_str, "USER"))
128 handle_user_command(p_sess);
130 else if (str_equal_text(&p_sess->ftp_cmd_str, "PASS"))
132 handle_pass_command(p_sess);
134 else if (str_equal_text(&p_sess->ftp_cmd_str, "QUIT"))
136 vsf_cmdio_write_exit(p_sess, FTP_GOODBYE, "Goodbye.");
138 else if (str_equal_text(&p_sess->ftp_cmd_str, "FEAT"))
140 handle_feat(p_sess);
142 else if (str_equal_text(&p_sess->ftp_cmd_str, "OPTS"))
144 handle_opts(p_sess);
146 else if (tunable_ssl_enable &&
147 str_equal_text(&p_sess->ftp_cmd_str, "AUTH") &&
148 !p_sess->control_use_ssl)
150 handle_auth(p_sess);
152 else if (tunable_ssl_enable &&
153 str_equal_text(&p_sess->ftp_cmd_str, "PBSZ"))
155 handle_pbsz(p_sess);
157 else if (tunable_ssl_enable &&
158 str_equal_text(&p_sess->ftp_cmd_str, "PROT"))
160 handle_prot(p_sess);
162 else if (str_isempty(&p_sess->ftp_cmd_str) &&
163 str_isempty(&p_sess->ftp_arg_str))
165 /* Deliberately ignore to avoid NAT device bugs, as per ProFTPd. */
167 else
169 vsf_cmdio_write(p_sess, FTP_LOGINERR,
170 "Please login with USER and PASS.");
173 else if (tunable_http_enable)
175 if (str_equal_text(&p_sess->ftp_cmd_str, "GET"))
177 handle_get(p_sess);
179 else
181 vsf_cmdio_write(p_sess, FTP_LOGINERR, "Bad HTTP verb.");
183 vsf_sysutil_exit(0);
188 static void
189 handle_get(struct vsf_session* p_sess)
191 p_sess->is_http = 1;
192 str_copy(&p_sess->http_get_arg, &p_sess->ftp_arg_str);
193 str_alloc_text(&p_sess->user_str, "FTP");
194 str_alloc_text(&p_sess->ftp_arg_str, "<http>");
195 handle_pass_command(p_sess);
198 static void
199 handle_user_command(struct vsf_session* p_sess)
201 /* SECURITY: If we're in anonymous only-mode, immediately reject
202 * non-anonymous usernames in the hope we save passwords going plaintext
203 * over the network
205 int is_anon = 1;
206 str_copy(&p_sess->user_str, &p_sess->ftp_arg_str);
207 str_upper(&p_sess->ftp_arg_str);
208 if (!str_equal_text(&p_sess->ftp_arg_str, "FTP") &&
209 !str_equal_text(&p_sess->ftp_arg_str, "ANONYMOUS"))
211 is_anon = 0;
213 if (!tunable_local_enable && !is_anon)
215 vsf_cmdio_write(
216 p_sess, FTP_LOGINERR, "This FTP server is anonymous only.");
217 str_empty(&p_sess->user_str);
218 return;
220 if (is_anon && p_sess->control_use_ssl && !tunable_allow_anon_ssl &&
221 !tunable_force_anon_logins_ssl)
223 vsf_cmdio_write(
224 p_sess, FTP_LOGINERR, "Anonymous sessions may not use encryption.");
225 str_empty(&p_sess->user_str);
226 return;
228 if (tunable_ssl_enable && !is_anon && !p_sess->control_use_ssl &&
229 tunable_force_local_logins_ssl)
231 vsf_cmdio_write(
232 p_sess, FTP_LOGINERR, "Non-anonymous sessions must use encryption.");
233 vsf_sysutil_exit(0);
235 if (tunable_ssl_enable && is_anon && !p_sess->control_use_ssl &&
236 tunable_force_anon_logins_ssl)
238 vsf_cmdio_write(
239 p_sess, FTP_LOGINERR, "Anonymous sessions must use encryption.");
240 vsf_sysutil_exit(0);
242 if (tunable_userlist_enable)
244 int located = str_contains_line(&p_sess->userlist_str, &p_sess->user_str);
245 if ((located && tunable_userlist_deny) ||
246 (!located && !tunable_userlist_deny))
248 check_login_delay();
249 vsf_cmdio_write(p_sess, FTP_LOGINERR, "Permission denied.");
250 check_login_fails(p_sess);
251 str_empty(&p_sess->user_str);
252 return;
255 if (is_anon && tunable_no_anon_password)
257 /* Fake a password */
258 str_alloc_text(&p_sess->ftp_arg_str, "<no password>");
259 handle_pass_command(p_sess);
261 else
263 vsf_cmdio_write(p_sess, FTP_GIVEPWORD, "Please specify the password.");
267 static void
268 handle_pass_command(struct vsf_session* p_sess)
270 if (str_isempty(&p_sess->user_str))
272 vsf_cmdio_write(p_sess, FTP_NEEDUSER, "Login with USER first.");
273 return;
275 /* These login calls never return if successful */
276 if (tunable_one_process_model)
278 vsf_one_process_login(p_sess, &p_sess->ftp_arg_str);
280 else
282 vsf_two_process_login(p_sess, &p_sess->ftp_arg_str);
284 vsf_cmdio_write(p_sess, FTP_LOGINERR, "Login incorrect.");
285 check_login_fails(p_sess);
286 str_empty(&p_sess->user_str);
287 /* FALLTHRU if login fails */
290 static void check_login_delay()
292 if (tunable_delay_failed_login)
294 vsf_sysutil_sleep((double) tunable_delay_failed_login);
298 static void check_login_fails(struct vsf_session* p_sess)
300 if (++p_sess->login_fails >= tunable_max_login_fails)
302 vsf_sysutil_exit(0);