PageRenderTime 41ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/vsftpd-3.0.0/prelogin.c

#
C | 317 lines | 281 code | 11 blank | 25 comment | 57 complexity | 81d6a721d454eca4449d89408e1bb767 MD5 | raw file
Possible License(s): GPL-2.0
  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, "(vsFTPd " VSF_VERSION
  104. ")");
  105. }
  106. else
  107. {
  108. vsf_cmdio_write(p_sess, FTP_GREET, tunable_ftpd_banner);
  109. }
  110. }
  111. static void
  112. parse_username_password(struct vsf_session* p_sess)
  113. {
  114. while (1)
  115. {
  116. vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str,
  117. &p_sess->ftp_arg_str, 1);
  118. if (tunable_ftp_enable)
  119. {
  120. if (str_equal_text(&p_sess->ftp_cmd_str, "USER"))
  121. {
  122. handle_user_command(p_sess);
  123. }
  124. else if (str_equal_text(&p_sess->ftp_cmd_str, "PASS"))
  125. {
  126. handle_pass_command(p_sess);
  127. }
  128. else if (str_equal_text(&p_sess->ftp_cmd_str, "QUIT"))
  129. {
  130. vsf_cmdio_write_exit(p_sess, FTP_GOODBYE, "Goodbye.", 0);
  131. }
  132. else if (str_equal_text(&p_sess->ftp_cmd_str, "FEAT"))
  133. {
  134. handle_feat(p_sess);
  135. }
  136. else if (str_equal_text(&p_sess->ftp_cmd_str, "OPTS"))
  137. {
  138. handle_opts(p_sess);
  139. }
  140. else if (tunable_ssl_enable &&
  141. str_equal_text(&p_sess->ftp_cmd_str, "AUTH") &&
  142. !p_sess->control_use_ssl)
  143. {
  144. handle_auth(p_sess);
  145. }
  146. else if (tunable_ssl_enable &&
  147. str_equal_text(&p_sess->ftp_cmd_str, "PBSZ"))
  148. {
  149. handle_pbsz(p_sess);
  150. }
  151. else if (tunable_ssl_enable &&
  152. str_equal_text(&p_sess->ftp_cmd_str, "PROT"))
  153. {
  154. handle_prot(p_sess);
  155. }
  156. else if (str_isempty(&p_sess->ftp_cmd_str) &&
  157. str_isempty(&p_sess->ftp_arg_str))
  158. {
  159. /* Deliberately ignore to avoid NAT device bugs, as per ProFTPd. */
  160. }
  161. else
  162. {
  163. vsf_cmdio_write(p_sess, FTP_LOGINERR,
  164. "Please login with USER and PASS.");
  165. }
  166. }
  167. else if (tunable_http_enable)
  168. {
  169. if (str_equal_text(&p_sess->ftp_cmd_str, "GET"))
  170. {
  171. handle_get(p_sess);
  172. }
  173. else
  174. {
  175. vsf_cmdio_write(p_sess, FTP_LOGINERR, "Bad HTTP verb.");
  176. }
  177. vsf_sysutil_exit(0);
  178. }
  179. }
  180. }
  181. static void
  182. handle_get(struct vsf_session* p_sess)
  183. {
  184. p_sess->is_http = 1;
  185. str_copy(&p_sess->http_get_arg, &p_sess->ftp_arg_str);
  186. str_alloc_text(&p_sess->user_str, "FTP");
  187. str_alloc_text(&p_sess->ftp_arg_str, "<http>");
  188. handle_pass_command(p_sess);
  189. }
  190. static void
  191. handle_user_command(struct vsf_session* p_sess)
  192. {
  193. /* SECURITY: If we're in anonymous only-mode, immediately reject
  194. * non-anonymous usernames in the hope we save passwords going plaintext
  195. * over the network
  196. */
  197. int is_anon = 1;
  198. str_copy(&p_sess->user_str, &p_sess->ftp_arg_str);
  199. str_upper(&p_sess->ftp_arg_str);
  200. if (!str_equal_text(&p_sess->ftp_arg_str, "FTP") &&
  201. !str_equal_text(&p_sess->ftp_arg_str, "ANONYMOUS"))
  202. {
  203. is_anon = 0;
  204. }
  205. if (!tunable_local_enable && !is_anon)
  206. {
  207. vsf_cmdio_write(
  208. p_sess, FTP_LOGINERR, "This FTP server is anonymous only.");
  209. str_empty(&p_sess->user_str);
  210. return;
  211. }
  212. if (is_anon && p_sess->control_use_ssl && !tunable_allow_anon_ssl &&
  213. !tunable_force_anon_logins_ssl)
  214. {
  215. vsf_cmdio_write(
  216. p_sess, FTP_LOGINERR, "Anonymous sessions may not use encryption.");
  217. str_empty(&p_sess->user_str);
  218. return;
  219. }
  220. if (tunable_ssl_enable && !is_anon && !p_sess->control_use_ssl &&
  221. tunable_force_local_logins_ssl)
  222. {
  223. vsf_cmdio_write_exit(
  224. p_sess, FTP_LOGINERR, "Non-anonymous sessions must use encryption.", 1);
  225. }
  226. if (tunable_ssl_enable && is_anon && !p_sess->control_use_ssl &&
  227. tunable_force_anon_logins_ssl)
  228. {
  229. vsf_cmdio_write_exit(
  230. p_sess, FTP_LOGINERR, "Anonymous sessions must use encryption.", 1);
  231. }
  232. if (tunable_userlist_enable)
  233. {
  234. int located = str_contains_line(&p_sess->userlist_str, &p_sess->user_str);
  235. if ((located && tunable_userlist_deny) ||
  236. (!located && !tunable_userlist_deny))
  237. {
  238. check_login_delay();
  239. vsf_cmdio_write(p_sess, FTP_LOGINERR, "Permission denied.");
  240. check_login_fails(p_sess);
  241. if (tunable_userlist_log)
  242. {
  243. struct mystr str_log_line = INIT_MYSTR;
  244. if (tunable_userlist_deny)
  245. {
  246. str_alloc_text(&str_log_line, "User is in the deny user list.");
  247. }
  248. else
  249. {
  250. str_alloc_text(&str_log_line, "User is not in the allow user list.");
  251. }
  252. vsf_log_failed_line(p_sess, kVSFLogEntryLogin, &str_log_line);
  253. str_free(&str_log_line);
  254. }
  255. str_empty(&p_sess->user_str);
  256. return;
  257. }
  258. }
  259. if (is_anon && tunable_no_anon_password)
  260. {
  261. /* Fake a password */
  262. str_alloc_text(&p_sess->ftp_arg_str, "<no password>");
  263. handle_pass_command(p_sess);
  264. }
  265. else
  266. {
  267. vsf_cmdio_write(p_sess, FTP_GIVEPWORD, "Please specify the password.");
  268. }
  269. }
  270. static void
  271. handle_pass_command(struct vsf_session* p_sess)
  272. {
  273. if (str_isempty(&p_sess->user_str))
  274. {
  275. vsf_cmdio_write(p_sess, FTP_NEEDUSER, "Login with USER first.");
  276. return;
  277. }
  278. /* These login calls never return if successful */
  279. if (tunable_one_process_model)
  280. {
  281. vsf_one_process_login(p_sess, &p_sess->ftp_arg_str);
  282. }
  283. else
  284. {
  285. vsf_two_process_login(p_sess, &p_sess->ftp_arg_str);
  286. }
  287. vsf_cmdio_write(p_sess, FTP_LOGINERR, "Login incorrect.");
  288. check_login_fails(p_sess);
  289. str_empty(&p_sess->user_str);
  290. /* FALLTHRU if login fails */
  291. }
  292. static void check_login_delay()
  293. {
  294. if (tunable_delay_failed_login)
  295. {
  296. vsf_sysutil_sleep((double) tunable_delay_failed_login);
  297. }
  298. }
  299. static void check_login_fails(struct vsf_session* p_sess)
  300. {
  301. if (++p_sess->login_fails >= tunable_max_login_fails)
  302. {
  303. vsf_sysutil_shutdown_failok(VSFTP_COMMAND_FD);
  304. vsf_sysutil_exit(1);
  305. }
  306. }