ftpcmdio.c
上传用户:ig0539
上传日期:2022-05-21
资源大小:181k
文件大小:6k
源码类别:

Ftp客户端

开发平台:

C/C++

  1. /*
  2.  * Part of Very Secure FTPd
  3.  * Licence: GPL v2
  4.  * Author: Chris Evans
  5.  * ftpcmdio.c
  6.  *
  7.  * Routines applicable to reading and writing the FTP command stream.
  8.  */
  9. #include "ftpcmdio.h"
  10. #include "ftpcodes.h"
  11. #include "str.h"
  12. #include "netstr.h"
  13. #include "sysutil.h"
  14. #include "tunables.h"
  15. #include "defs.h"
  16. #include "secbuf.h"
  17. #include "utility.h"
  18. #include "logging.h"
  19. #include "session.h"
  20. #include "readwrite.h"
  21. /* Internal functions */
  22. static void control_getline(struct mystr* p_str, struct vsf_session* p_sess);
  23. static void ftp_write_text_common(struct vsf_session* p_sess, int status,
  24.                                   const char* p_text, int noblock, char sep);
  25. static void ftp_write_str_common(struct vsf_session* p_sess, int status,
  26.                                  char sep, const struct mystr* p_str,
  27.                                  int noblock);
  28. static void handle_alarm_timeout(void* p_private);
  29. void
  30. vsf_cmdio_sock_setup(void)
  31. {
  32.   vsf_sysutil_activate_keepalive(VSFTP_COMMAND_FD);
  33.   vsf_sysutil_set_nodelay(VSFTP_COMMAND_FD);
  34.   vsf_sysutil_activate_oobinline(VSFTP_COMMAND_FD);
  35. }
  36. static void
  37. handle_alarm_timeout(void* p_private)
  38. {
  39.   struct vsf_session* p_sess = (struct vsf_session*) p_private;
  40.   vsf_cmdio_write_exit(p_sess, FTP_IDLE_TIMEOUT, "Timeout.");
  41. }
  42. void
  43. vsf_cmdio_write(struct vsf_session* p_sess, int status, const char* p_text)
  44. {
  45.   ftp_write_text_common(p_sess, status, p_text, 0, ' ');
  46. }
  47. void
  48. vsf_cmdio_write_hyphen(struct vsf_session* p_sess, int status,
  49.                        const char* p_text)
  50. {
  51.   ftp_write_text_common(p_sess, status, p_text, 0, '-');
  52. }
  53. void
  54. vsf_cmdio_write_raw(struct vsf_session* p_sess, const char* p_text)
  55. {
  56.   static struct mystr s_the_str;
  57.   int retval;
  58.   str_alloc_text(&s_the_str, p_text);
  59.   if (tunable_log_ftp_protocol)
  60.   {
  61.     vsf_log_line(p_sess, kVSFLogEntryFTPOutput, &s_the_str);
  62.   }
  63.   retval = ftp_write_str(p_sess, &s_the_str, kVSFRWControl);
  64.   if (retval != 0)
  65.   {
  66.     die("ftp_write_str");
  67.   }
  68. }
  69. void
  70. vsf_cmdio_write_exit(struct vsf_session* p_sess, int status, const char* p_text)
  71. {
  72.   /* Unblock any readers on the dying control channel. This is needed for SSL
  73.    * connections, where the SSL control channel slave is in a separate
  74.    * process.
  75.    */
  76.   vsf_sysutil_shutdown_read_failok(VSFTP_COMMAND_FD);
  77.   ftp_write_text_common(p_sess, status, p_text, 1, ' ');
  78.   vsf_sysutil_shutdown_failok(VSFTP_COMMAND_FD);
  79.   vsf_sysutil_exit(0);
  80. }
  81. static void
  82. ftp_write_text_common(struct vsf_session* p_sess, int status,
  83.                       const char* p_text, int noblock, char sep)
  84. {
  85.   /* XXX - could optimize */
  86.   static struct mystr s_the_str;
  87.   str_alloc_text(&s_the_str, p_text);
  88.   ftp_write_str_common(p_sess, status, sep, &s_the_str, noblock);
  89. }
  90. void
  91. vsf_cmdio_write_str_hyphen(struct vsf_session* p_sess, int status,
  92.                            const struct mystr* p_str)
  93. {
  94.   ftp_write_str_common(p_sess, status, '-', p_str, 0);
  95. }
  96. void
  97. vsf_cmdio_write_str(struct vsf_session* p_sess, int status,
  98.                     const struct mystr* p_str)
  99. {
  100.   ftp_write_str_common(p_sess, status, ' ', p_str, 0);
  101. }
  102. static void
  103. ftp_write_str_common(struct vsf_session* p_sess, int status, char sep,
  104.                      const struct mystr* p_str, int noblock)
  105. {
  106.   static struct mystr s_write_buf_str;
  107.   static struct mystr s_text_mangle_str;
  108.   int retval;
  109.   if (tunable_log_ftp_protocol)
  110.   {
  111.     str_alloc_ulong(&s_write_buf_str, (unsigned long) status);
  112.     str_append_char(&s_write_buf_str, sep);
  113.     str_append_str(&s_write_buf_str, p_str);
  114.     vsf_log_line(p_sess, kVSFLogEntryFTPOutput, &s_write_buf_str);
  115.   }
  116.   str_copy(&s_text_mangle_str, p_str);
  117.   /* Process the output response according to the specifications.. */
  118.   /* Escape telnet characters properly */
  119.   str_replace_text(&s_text_mangle_str, "377", "377377");
  120.   /* Change n for  in response */
  121.   str_replace_char(&s_text_mangle_str, 'n', '');
  122.   /* Build string to squirt down network */
  123.   str_alloc_ulong(&s_write_buf_str, (unsigned long) status);
  124.   str_append_char(&s_write_buf_str, sep);
  125.   str_append_str(&s_write_buf_str, &s_text_mangle_str);
  126.   str_append_text(&s_write_buf_str, "rn");
  127.   if (noblock)
  128.   {
  129.     vsf_sysutil_activate_noblock(VSFTP_COMMAND_FD);
  130.   }
  131.   retval = ftp_write_str(p_sess, &s_write_buf_str, kVSFRWControl);
  132.   if (retval != 0 && !noblock)
  133.   {
  134.     die("ftp_write");
  135.   }
  136.   if (noblock)
  137.   {
  138.     vsf_sysutil_deactivate_noblock(VSFTP_COMMAND_FD);
  139.   }
  140. }
  141. void
  142. vsf_cmdio_set_alarm(struct vsf_session* p_sess)
  143. {
  144.   if (tunable_idle_session_timeout > 0)
  145.   {
  146.     vsf_sysutil_install_sighandler(kVSFSysUtilSigALRM,
  147.                                    handle_alarm_timeout,
  148.                                    p_sess,
  149.                                    1);
  150.     vsf_sysutil_set_alarm(tunable_idle_session_timeout);
  151.   }
  152. }
  153. void
  154. vsf_cmdio_get_cmd_and_arg(struct vsf_session* p_sess, struct mystr* p_cmd_str,
  155.                           struct mystr* p_arg_str, int set_alarm)
  156. {
  157.   /* Prepare an alarm to timeout the session.. */
  158.   if (set_alarm)
  159.   {
  160.     vsf_cmdio_set_alarm(p_sess);
  161.   }
  162.   /* Blocks */
  163.   control_getline(p_cmd_str, p_sess);
  164.   /* View a single space as a command of " ", which although a useless command,
  165.    * permits the caller to distinguish input of "" from " ".
  166.    */
  167.   if (str_getlen(p_cmd_str) == 1 && str_get_char_at(p_cmd_str, 0) == ' ')
  168.   {
  169.     str_empty(p_arg_str);
  170.   }
  171.   else
  172.   {
  173.     str_split_char(p_cmd_str, p_arg_str, ' ');
  174.   }
  175.   str_upper(p_cmd_str);
  176.   if (tunable_log_ftp_protocol)
  177.   {
  178.     static struct mystr s_log_str;
  179.     if (str_equal_text(p_cmd_str, "PASS"))
  180.     {
  181.       str_alloc_text(&s_log_str, "PASS <password>");
  182.     }
  183.     else
  184.     {
  185.       str_copy(&s_log_str, p_cmd_str);
  186.       if (!str_isempty(p_arg_str))
  187.       {
  188.         str_append_char(&s_log_str, ' ');
  189.         str_append_str(&s_log_str, p_arg_str);
  190.       }
  191.     }
  192.     vsf_log_line(p_sess, kVSFLogEntryFTPInput, &s_log_str);
  193.   }
  194. }
  195. static void
  196. control_getline(struct mystr* p_str, struct vsf_session* p_sess)
  197. {
  198.   int ret;
  199.   if (p_sess->p_control_line_buf == 0)
  200.   {
  201.     vsf_secbuf_alloc(&p_sess->p_control_line_buf, VSFTP_MAX_COMMAND_LINE);
  202.   }
  203.   ret = ftp_getline(p_sess, p_str, p_sess->p_control_line_buf);
  204.   if (ret < 0)
  205.   {
  206.     vsf_cmdio_write_exit(p_sess, FTP_BADCMD, "Input line too long.");
  207.   }
  208.   /* As mandated by the FTP specifications.. */
  209.   str_replace_char(p_str, '', 'n');
  210.   /* If the last character is a r, strip it */
  211.   {
  212.     unsigned int len = str_getlen(p_str);
  213.     while (len > 0 && str_get_char_at(p_str, len - 1) == 'r')
  214.     {
  215.       str_trunc(p_str, len - 1);
  216.       --len;
  217.     }
  218.   }
  219. }