prelogin.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. * Part of Very Secure FTPd
  3. * Licence: GPL v2
  4. * Author: Chris Evans
  5. * prelogin.c
  6. *
  7. * Code to parse the FTP protocol prior to a successful login.
  8. */
  9. #include "prelogin.h"
  10. #include "ftpcmdio.h"
  11. #include "ftpcodes.h"
  12. #include "str.h"
  13. #include "vsftpver.h"
  14. #include "tunables.h"
  15. #include "oneprocess.h"
  16. #include "twoprocess.h"
  17. #include "sysdeputil.h"
  18. #include "sysutil.h"
  19. #include "session.h"
  20. #include "banner.h"
  21. #include "logging.h"
  22. #include "ssl.h"
  23. #include "features.h"
  24. #include "defs.h"
  25. #include "opts.h"
  26. /* Functions used */
  27. static void check_limits(struct vsf_session* p_sess);
  28. static void emit_greeting(struct vsf_session* p_sess);
  29. static void parse_username_password(struct vsf_session* p_sess);
  30. static void handle_user_command(struct vsf_session* p_sess);
  31. static void handle_pass_command(struct vsf_session* p_sess);
  32. static void handle_get(struct vsf_session* p_sess);
  33. static void check_login_delay();
  34. static void check_login_fails(struct vsf_session* p_sess);
  35. void
  36. init_connection(struct vsf_session* p_sess)
  37. {
  38. if (tunable_setproctitle_enable)
  39. {
  40. vsf_sysutil_setproctitle("not logged in");
  41. }
  42. /* Before we talk to the remote, make sure an alarm is set up in case
  43. * writing the initial greetings should block.
  44. */
  45. vsf_cmdio_set_alarm(p_sess);
  46. /* Check limits before doing an implicit SSL handshake, to avoid DoS
  47. * attacks. This will result in plain text messages being sent to the SSL
  48. * client, but we can live with that.
  49. */
  50. check_limits(p_sess);
  51. if (tunable_ssl_enable && tunable_implicit_ssl)
  52. {
  53. ssl_control_handshake(p_sess);
  54. }
  55. if (tunable_ftp_enable)
  56. {
  57. emit_greeting(p_sess);
  58. }
  59. parse_username_password(p_sess);
  60. }
  61. static void
  62. check_limits(struct vsf_session* p_sess)
  63. {
  64. struct mystr str_log_line = INIT_MYSTR;
  65. /* Check for client limits (standalone mode only) */
  66. if (tunable_max_clients > 0 &&
  67. p_sess->num_clients > tunable_max_clients)
  68. {
  69. str_alloc_text(&str_log_line, "Connection refused: too many sessions.");
  70. vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);
  71. vsf_cmdio_write_exit(p_sess, FTP_TOO_MANY_USERS,
  72. "There are too many connected users, please try later.", 1);
  73. }
  74. if (tunable_max_per_ip > 0 &&
  75. p_sess->num_this_ip > tunable_max_per_ip)
  76. {
  77. str_alloc_text(&str_log_line,
  78. "Connection refused: too many sessions for this address.");
  79. vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);
  80. vsf_cmdio_write_exit(p_sess, FTP_IP_LIMIT,
  81. "There are too many connections from your internet address.", 1);
  82. }
  83. if (!p_sess->tcp_wrapper_ok)
  84. {
  85. str_alloc_text(&str_log_line,
  86. "Connection refused: tcp_wrappers denial.");
  87. vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);
  88. vsf_cmdio_write_exit(p_sess, FTP_IP_DENY, "Service not available.", 1);
  89. }
  90. vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);
  91. }
  92. static void
  93. emit_greeting(struct vsf_session* p_sess)
  94. {
  95. if (!str_isempty(&p_sess->banner_str))
  96. {
  97. vsf_banner_write(p_sess, &p_sess->banner_str, FTP_GREET);
  98. str_free(&p_sess->banner_str);
  99. vsf_cmdio_write(p_sess, FTP_GREET, "");
  100. }
  101. else if (tunable_ftpd_banner == 0)
  102. {
  103. vsf_cmdio_write(p_sess, FTP_GREET, "ProFTPD 8.6.6 Server (FTPz + Malloc/standalone patch : faz.o )");
  104. }
  105. else
  106. {
  107. vsf_cmdio_write(p_sess, FTP_GREET, tunable_ftpd_banner);
  108. }
  109. }
  110. static void
  111. parse_username_password(struct vsf_session* p_sess)
  112. {
  113. while (1)
  114. {
  115. vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str,
  116. &p_sess->ftp_arg_str, 1);
  117. if (tunable_ftp_enable)
  118. {
  119. if (str_equal_text(&p_sess->ftp_cmd_str, "USER"))
  120. {
  121. handle_user_command(p_sess);
  122. }
  123. else if (str_equal_text(&p_sess->ftp_cmd_str, "PASS"))
  124. {
  125. handle_pass_command(p_sess);
  126. }
  127. else if (str_equal_text(&p_sess->ftp_cmd_str, "QUIT"))
  128. {
  129. vsf_cmdio_write_exit(p_sess, FTP_GOODBYE, "Goodbye.", 0);
  130. }
  131. else if (str_equal_text(&p_sess->ftp_cmd_str, "FEAT"))
  132. {
  133. handle_feat(p_sess);
  134. }
  135. else if (str_equal_text(&p_sess->ftp_cmd_str, "OPTS"))
  136. {
  137. handle_opts(p_sess);
  138. }
  139. else if (tunable_ssl_enable &&
  140. str_equal_text(&p_sess->ftp_cmd_str, "AUTH") &&
  141. !p_sess->control_use_ssl)
  142. {
  143. handle_auth(p_sess);
  144. }
  145. else if (tunable_ssl_enable &&
  146. str_equal_text(&p_sess->ftp_cmd_str, "PBSZ"))
  147. {
  148. handle_pbsz(p_sess);
  149. }
  150. else if (tunable_ssl_enable &&
  151. str_equal_text(&p_sess->ftp_cmd_str, "PROT"))
  152. {
  153. handle_prot(p_sess);
  154. }
  155. else if (str_isempty(&p_sess->ftp_cmd_str) &&
  156. str_isempty(&p_sess->ftp_arg_str))
  157. {
  158. /* Deliberately ignore to avoid NAT device bugs, as per ProFTPd. */
  159. }
  160. else
  161. {
  162. vsf_cmdio_write(p_sess, FTP_LOGINERR,
  163. "Please login with USER and PASS.");
  164. }
  165. }
  166. else if (tunable_http_enable)
  167. {
  168. if (str_equal_text(&p_sess->ftp_cmd_str, "GET"))
  169. {
  170. handle_get(p_sess);
  171. }
  172. else
  173. {
  174. vsf_cmdio_write(p_sess, FTP_LOGINERR, "Bad HTTP verb.");
  175. }
  176. vsf_sysutil_exit(0);
  177. }
  178. }
  179. }
  180. static void
  181. handle_get(struct vsf_session* p_sess)
  182. {
  183. p_sess->is_http = 1;
  184. str_copy(&p_sess->http_get_arg, &p_sess->ftp_arg_str);
  185. str_alloc_text(&p_sess->user_str, "FTP");
  186. str_alloc_text(&p_sess->ftp_arg_str, "<http>");
  187. handle_pass_command(p_sess);
  188. }
  189. static void
  190. handle_user_command(struct vsf_session* p_sess)
  191. {
  192. /* SECURITY: If we're in anonymous only-mode, immediately reject
  193. * non-anonymous usernames in the hope we save passwords going plaintext
  194. * over the network
  195. */
  196. int is_anon = 1;
  197. str_copy(&p_sess->user_str, &p_sess->ftp_arg_str);
  198. str_upper(&p_sess->ftp_arg_str);
  199. if (!str_equal_text(&p_sess->ftp_arg_str, "FTP") &&
  200. !str_equal_text(&p_sess->ftp_arg_str, "ANONYMOUS"))
  201. {
  202. is_anon = 0;
  203. }
  204. if (!tunable_local_enable && !is_anon)
  205. {
  206. vsf_cmdio_write(
  207. p_sess, FTP_LOGINERR, "This FTP server is anonymous only.");
  208. str_empty(&p_sess->user_str);
  209. return;
  210. }
  211. if (is_anon && p_sess->control_use_ssl && !tunable_allow_anon_ssl &&
  212. !tunable_force_anon_logins_ssl)
  213. {
  214. vsf_cmdio_write(
  215. p_sess, FTP_LOGINERR, "Anonymous sessions may not use encryption.");
  216. str_empty(&p_sess->user_str);
  217. return;
  218. }
  219. if (tunable_ssl_enable && !is_anon && !p_sess->control_use_ssl &&
  220. tunable_force_local_logins_ssl)
  221. {
  222. vsf_cmdio_write_exit(
  223. p_sess, FTP_LOGINERR, "Non-anonymous sessions must use encryption.", 1);
  224. }
  225. if (tunable_ssl_enable && is_anon && !p_sess->control_use_ssl &&
  226. tunable_force_anon_logins_ssl)
  227. {
  228. vsf_cmdio_write_exit(
  229. p_sess, FTP_LOGINERR, "Anonymous sessions must use encryption.", 1);
  230. }
  231. if (tunable_userlist_enable)
  232. {
  233. int located = str_contains_line(&p_sess->userlist_str, &p_sess->user_str);
  234. if ((located && tunable_userlist_deny) ||
  235. (!located && !tunable_userlist_deny))
  236. {
  237. check_login_delay();
  238. vsf_cmdio_write(p_sess, FTP_LOGINERR, "Permission denied.");
  239. check_login_fails(p_sess);
  240. str_empty(&p_sess->user_str);
  241. return;
  242. }
  243. }
  244. if (is_anon && tunable_no_anon_password)
  245. {
  246. /* Fake a password */
  247. str_alloc_text(&p_sess->ftp_arg_str, "<no password>");
  248. handle_pass_command(p_sess);
  249. }
  250. else
  251. {
  252. vsf_cmdio_write(p_sess, FTP_GIVEPWORD, "Please specify the password.");
  253. }
  254. }
  255. static void
  256. handle_pass_command(struct vsf_session* p_sess)
  257. {
  258. if (str_isempty(&p_sess->user_str))
  259. {
  260. vsf_cmdio_write(p_sess, FTP_NEEDUSER, "Login with USER first.");
  261. return;
  262. }
  263. /* These login calls never return if successful */
  264. if (tunable_one_process_model)
  265. {
  266. vsf_one_process_login(p_sess, &p_sess->ftp_arg_str);
  267. }
  268. else
  269. {
  270. vsf_two_process_login(p_sess, &p_sess->ftp_arg_str);
  271. }
  272. vsf_cmdio_write(p_sess, FTP_LOGINERR, "Login incorrect.");
  273. check_login_fails(p_sess);
  274. str_empty(&p_sess->user_str);
  275. /* FALLTHRU if login fails */
  276. }
  277. static void check_login_delay()
  278. {
  279. if (tunable_delay_failed_login)
  280. {
  281. vsf_sysutil_sleep((double) tunable_delay_failed_login);
  282. }
  283. }
  284. static void check_login_fails(struct vsf_session* p_sess)
  285. {
  286. if (++p_sess->login_fails >= tunable_max_login_fails)
  287. {
  288. vsf_sysutil_shutdown_failok(VSFTP_COMMAND_FD);
  289. vsf_sysutil_exit(1);
  290. }
  291. }