main.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /*
  2. * Part of Very Secure FTPd
  3. * Licence: GPL v2
  4. * Author: Chris Evans
  5. * main.c
  6. */
  7. #include "session.h"
  8. #include "utility.h"
  9. #include "tunables.h"
  10. #include "logging.h"
  11. #include "str.h"
  12. #include "filestr.h"
  13. #include "ftpcmdio.h"
  14. #include "sysutil.h"
  15. #include "sysdeputil.h"
  16. #include "defs.h"
  17. #include "parseconf.h"
  18. #include "oneprocess.h"
  19. #include "twoprocess.h"
  20. #include "standalone.h"
  21. #include "tcpwrap.h"
  22. #include "vsftpver.h"
  23. #include "ssl.h"
  24. /*
  25. * Forward decls of helper functions
  26. */
  27. static void die_unless_privileged(void);
  28. static void do_sanity_checks(void);
  29. static void session_init(struct vsf_session* p_sess);
  30. static void env_init(void);
  31. static void limits_init(void);
  32. int
  33. main(int argc, const char* argv[])
  34. {
  35. struct vsf_session the_session =
  36. {
  37. /* Control connection */
  38. 0, 0, 0, 0, 0,
  39. /* Data connection */
  40. -1, 0, -1, 0, 0, 0, 0,
  41. /* Login */
  42. 1, 0, INIT_MYSTR, INIT_MYSTR,
  43. /* Protocol state */
  44. 0, 1, INIT_MYSTR, 0, 0,
  45. /* HTTP hacks */
  46. 0, INIT_MYSTR,
  47. /* Session state */
  48. 0,
  49. /* Userids */
  50. -1, -1, -1,
  51. /* Pre-chroot() cache */
  52. INIT_MYSTR, INIT_MYSTR, INIT_MYSTR, INIT_MYSTR, 1,
  53. /* Logging */
  54. -1, -1, INIT_MYSTR, 0, 0, 0, INIT_MYSTR, 0,
  55. /* Buffers */
  56. INIT_MYSTR, INIT_MYSTR,
  57. /* Parent <-> child comms */
  58. -1, -1,
  59. /* Number of clients */
  60. 0, 0,
  61. /* Home directory */
  62. INIT_MYSTR,
  63. /* Secure connection state */
  64. 0, 0, 0, 0, 0, INIT_MYSTR, 0, -1, -1,
  65. /* Login fails */
  66. 0
  67. };
  68. int config_loaded = 0;
  69. int i;
  70. tunables_load_defaults();
  71. /* This might need to open /dev/zero on systems lacking MAP_ANON. Needs
  72. * to be done early (i.e. before config file parse, which may use
  73. * anonymous pages
  74. */
  75. vsf_sysutil_map_anon_pages_init();
  76. /* Argument parsing. Any argument not starting with "-" is a config file,
  77. * loaded in the order encountered. -o opt=value options are loading in the
  78. * order encountered, including correct ordering with respect intermingled
  79. * config files.
  80. * If we see -v (version) or an unknown option, parsing bails and exits.
  81. */
  82. if (argc == 0)
  83. {
  84. die("missing argv[0]");
  85. }
  86. for (i = 1; i < argc; ++i)
  87. {
  88. const char* p_arg = argv[i];
  89. if (p_arg[0] != '-')
  90. {
  91. config_loaded = 1;
  92. vsf_parseconf_load_file(p_arg, 1);
  93. }
  94. else
  95. {
  96. if (p_arg[1] == 'v')
  97. {
  98. vsf_exit("ProFTPD 1.3.5 Server\n");
  99. }
  100. else if (p_arg[1] == 'o')
  101. {
  102. vsf_parseconf_load_setting(&p_arg[2], 1);
  103. }
  104. else
  105. {
  106. die2("unrecognise option: ", p_arg);
  107. }
  108. }
  109. }
  110. /* Parse default config file if necessary */
  111. if (!config_loaded) {
  112. struct vsf_sysutil_statbuf* p_statbuf = 0;
  113. int retval = vsf_sysutil_stat(VSFTP_DEFAULT_CONFIG, &p_statbuf);
  114. if (!vsf_sysutil_retval_is_error(retval))
  115. {
  116. vsf_parseconf_load_file(VSFTP_DEFAULT_CONFIG, 1);
  117. }
  118. vsf_sysutil_free(p_statbuf);
  119. }
  120. /* Resolve pasv_address if required */
  121. if (tunable_pasv_address && tunable_pasv_addr_resolve)
  122. {
  123. struct vsf_sysutil_sockaddr* p_addr = 0;
  124. const char* p_numeric_addr;
  125. vsf_sysutil_dns_resolve(&p_addr, tunable_pasv_address);
  126. vsf_sysutil_free((char*) tunable_pasv_address);
  127. p_numeric_addr = vsf_sysutil_inet_ntop(p_addr);
  128. tunable_pasv_address = vsf_sysutil_strdup(p_numeric_addr);
  129. vsf_sysutil_free(p_addr);
  130. }
  131. if (!tunable_run_as_launching_user)
  132. {
  133. /* Just get out unless we start with requisite privilege */
  134. die_unless_privileged();
  135. }
  136. if (tunable_setproctitle_enable)
  137. {
  138. /* Warning -- warning -- may nuke argv, environ */
  139. vsf_sysutil_setproctitle_init(argc, argv);
  140. }
  141. /* Initialize the SSL system here if needed - saves the overhead of each
  142. * child doing this itself.
  143. */
  144. if (tunable_ssl_enable)
  145. {
  146. ssl_init(&the_session);
  147. }
  148. if (tunable_listen || tunable_listen_ipv6)
  149. {
  150. /* Standalone mode */
  151. struct vsf_client_launch ret = vsf_standalone_main();
  152. the_session.num_clients = ret.num_children;
  153. the_session.num_this_ip = ret.num_this_ip;
  154. }
  155. if (tunable_tcp_wrappers)
  156. {
  157. the_session.tcp_wrapper_ok = vsf_tcp_wrapper_ok(VSFTP_COMMAND_FD);
  158. }
  159. {
  160. const char* p_load_conf = vsf_sysutil_getenv("VSFTPD_LOAD_CONF");
  161. if (p_load_conf)
  162. {
  163. vsf_parseconf_load_file(p_load_conf, 1);
  164. }
  165. }
  166. /* Sanity checks - exit with a graceful error message if our STDIN is not
  167. * a socket. Also check various config options don't collide.
  168. */
  169. do_sanity_checks();
  170. /* Initializes session globals - e.g. IP addr's etc. */
  171. session_init(&the_session);
  172. /* Set up "environment", e.g. process group etc. */
  173. env_init();
  174. /* Set up resource limits. */
  175. limits_init();
  176. /* Set up logging - must come after global init because we need the remote
  177. * address to convert into text
  178. */
  179. vsf_log_init(&the_session);
  180. str_alloc_text(&the_session.remote_ip_str,
  181. vsf_sysutil_inet_ntop(the_session.p_remote_addr));
  182. /* Set up options on the command socket */
  183. vsf_cmdio_sock_setup();
  184. if (tunable_setproctitle_enable)
  185. {
  186. vsf_sysutil_set_proctitle_prefix(&the_session.remote_ip_str);
  187. vsf_sysutil_setproctitle("connected");
  188. }
  189. /* We might chroot() very soon (one process model), so we need to open
  190. * any required config files here.
  191. */
  192. /* SSL may have been enabled by a per-IP configuration.. */
  193. if (tunable_ssl_enable)
  194. {
  195. ssl_init(&the_session);
  196. ssl_add_entropy(&the_session);
  197. }
  198. if (tunable_deny_email_enable)
  199. {
  200. int retval = -1;
  201. if (tunable_banned_email_file)
  202. {
  203. retval = str_fileread(&the_session.banned_email_str,
  204. tunable_banned_email_file, VSFTP_CONF_FILE_MAX);
  205. }
  206. if (vsf_sysutil_retval_is_error(retval))
  207. {
  208. die2(":", tunable_banned_email_file);
  209. }
  210. }
  211. if (tunable_banner_file)
  212. {
  213. int retval = str_fileread(&the_session.banner_str, tunable_banner_file,
  214. VSFTP_CONF_FILE_MAX);
  215. if (vsf_sysutil_retval_is_error(retval))
  216. {
  217. die2(":", tunable_banner_file);
  218. }
  219. }
  220. if (tunable_secure_email_list_enable)
  221. {
  222. int retval = -1;
  223. if (tunable_email_password_file)
  224. {
  225. retval = str_fileread(&the_session.email_passwords_str,
  226. tunable_email_password_file,
  227. VSFTP_CONF_FILE_MAX);
  228. }
  229. if (vsf_sysutil_retval_is_error(retval))
  230. {
  231. die2(":", tunable_email_password_file);
  232. }
  233. }
  234. if (tunable_run_as_launching_user)
  235. {
  236. tunable_one_process_model = 1;
  237. if (!vsf_sysutil_running_as_root())
  238. {
  239. tunable_connect_from_port_20 = 0;
  240. tunable_chown_uploads = 0;
  241. }
  242. }
  243. if (tunable_one_process_model)
  244. {
  245. vsf_one_process_start(&the_session);
  246. }
  247. else
  248. {
  249. vsf_two_process_start(&the_session);
  250. }
  251. /* NOTREACHED */
  252. bug("should not get here: main");
  253. return 1;
  254. }
  255. static void
  256. die_unless_privileged(void)
  257. {
  258. if (!vsf_sysutil_running_as_root())
  259. {
  260. die(" must be started as root");
  261. }
  262. }
  263. static void
  264. do_sanity_checks(void)
  265. {
  266. {
  267. struct vsf_sysutil_statbuf* p_statbuf = 0;
  268. vsf_sysutil_fstat(VSFTP_COMMAND_FD, &p_statbuf);
  269. if (!vsf_sysutil_statbuf_is_socket(p_statbuf))
  270. {
  271. die("");
  272. }
  273. vsf_sysutil_free(p_statbuf);
  274. }
  275. if (tunable_one_process_model)
  276. {
  277. if (tunable_local_enable)
  278. {
  279. die("'one_process_model' is anonymous only");
  280. }
  281. if (!vsf_sysdep_has_capabilities_as_non_root())
  282. {
  283. die("'one_process_model' needs a better OS");
  284. }
  285. }
  286. if (!tunable_local_enable && !tunable_anonymous_enable)
  287. {
  288. die("");
  289. }
  290. if (!tunable_ftp_enable && !tunable_http_enable)
  291. {
  292. die("");
  293. }
  294. if (tunable_http_enable && !tunable_one_process_model)
  295. {
  296. die("");
  297. }
  298. }
  299. static void
  300. env_init(void)
  301. {
  302. vsf_sysutil_make_session_leader();
  303. /* Set up a secure umask - we'll set the proper one after login */
  304. vsf_sysutil_set_umask(VSFTP_SECURE_UMASK);
  305. /* Fire up libc's timezone initialisation, before we chroot()! */
  306. vsf_sysutil_tzset();
  307. /* Signals. We'll always take -EPIPE rather than a rude signal, thanks */
  308. vsf_sysutil_install_null_sighandler(kVSFSysUtilSigPIPE);
  309. }
  310. static void
  311. limits_init(void)
  312. {
  313. unsigned long limit = VSFTP_AS_LIMIT;
  314. if (tunable_text_userdb_names)
  315. {
  316. /* Turns out, LDAP lookups for lots of userid -> name mappings can really
  317. * bloat memory usage.
  318. */
  319. limit *= 3;
  320. }
  321. vsf_sysutil_set_address_space_limit(limit);
  322. }
  323. static void
  324. session_init(struct vsf_session* p_sess)
  325. {
  326. /* Get the addresses of the control connection */
  327. vsf_sysutil_getpeername(VSFTP_COMMAND_FD, &p_sess->p_remote_addr);
  328. vsf_sysutil_getsockname(VSFTP_COMMAND_FD, &p_sess->p_local_addr);
  329. /* If anonymous mode is active, fetch the uid of the anonymous user */
  330. if (tunable_anonymous_enable)
  331. {
  332. const struct vsf_sysutil_user* p_user = 0;
  333. if (tunable_ftp_username)
  334. {
  335. p_user = vsf_sysutil_getpwnam(tunable_ftp_username);
  336. }
  337. if (p_user == 0)
  338. {
  339. die2("",
  340. tunable_ftp_username);
  341. }
  342. p_sess->anon_ftp_uid = vsf_sysutil_user_getuid(p_user);
  343. }
  344. if (tunable_guest_enable)
  345. {
  346. const struct vsf_sysutil_user* p_user = 0;
  347. if (tunable_guest_username)
  348. {
  349. p_user = vsf_sysutil_getpwnam(tunable_guest_username);
  350. }
  351. if (p_user == 0)
  352. {
  353. die2("",
  354. tunable_guest_username);
  355. }
  356. p_sess->guest_user_uid = vsf_sysutil_user_getuid(p_user);
  357. }
  358. if (tunable_chown_uploads)
  359. {
  360. const struct vsf_sysutil_user* p_user = 0;
  361. if (tunable_chown_username)
  362. {
  363. p_user = vsf_sysutil_getpwnam(tunable_chown_username);
  364. }
  365. if (p_user == 0)
  366. {
  367. die2("",
  368. tunable_chown_username);
  369. }
  370. p_sess->anon_upload_chown_uid = vsf_sysutil_user_getuid(p_user);
  371. }
  372. }