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

Ftp客户端

开发平台:

C/C++

  1. /*
  2.  * Part of Very Secure FTPd
  3.  * Licence: GPL v2
  4.  * Author: Chris Evans
  5.  *
  6.  * logging.c
  7.  */
  8. #include "logging.h"
  9. #include "tunables.h"
  10. #include "utility.h"
  11. #include "str.h"
  12. #include "sysutil.h"
  13. #include "sysstr.h"
  14. #include "session.h"
  15. /* File local functions */
  16. static int vsf_log_type_is_transfer(enum EVSFLogEntryType type);
  17. static void vsf_log_common(struct vsf_session* p_sess, int succeeded,
  18.                            enum EVSFLogEntryType what,
  19.                            const struct mystr* p_str);
  20. static void vsf_log_do_log_vsftpd_format(struct vsf_session* p_sess,
  21.                                          struct mystr* p_str, int succeeded,
  22.                                          enum EVSFLogEntryType what,
  23.                                          const struct mystr* p_log_str);
  24. static void vsf_log_do_log_wuftpd_format(struct vsf_session* p_sess,
  25.                                          struct mystr* p_str, int succeeded);
  26. static void vsf_log_do_log_to_file(int fd, struct mystr* p_str);
  27. void
  28. vsf_log_init(struct vsf_session* p_sess)
  29. {
  30.   int retval;
  31.   if (tunable_syslog_enable || tunable_tcp_wrappers)
  32.   {
  33.     vsf_sysutil_openlog(1);
  34.   }
  35.   if (!tunable_xferlog_enable && !tunable_dual_log_enable)
  36.   {
  37.     return;
  38.   }
  39.   if (tunable_dual_log_enable || tunable_xferlog_std_format)
  40.   {
  41.     retval = vsf_sysutil_create_or_open_file(tunable_xferlog_file, 0600);
  42.     if (vsf_sysutil_retval_is_error(retval))
  43.     {
  44.       die2("failed to open xferlog log file:", tunable_xferlog_file);
  45.     }
  46.     p_sess->xferlog_fd = retval;
  47.   }
  48.   if (tunable_dual_log_enable || !tunable_xferlog_std_format)
  49.   {
  50.     if (!tunable_syslog_enable)
  51.     {
  52.       retval = vsf_sysutil_create_or_open_file(tunable_vsftpd_log_file, 0600);
  53.       if (vsf_sysutil_retval_is_error(retval))
  54.       {
  55.         die2("failed to open vsftpd log file:", tunable_vsftpd_log_file);
  56.       }
  57.       p_sess->vsftpd_log_fd = retval;
  58.     }
  59.   }
  60. }
  61. static int
  62. vsf_log_type_is_transfer(enum EVSFLogEntryType type)
  63. {
  64.   return (type == kVSFLogEntryDownload || type == kVSFLogEntryUpload);
  65. }
  66. void
  67. vsf_log_start_entry(struct vsf_session* p_sess, enum EVSFLogEntryType what)
  68. {
  69.   if (p_sess->log_type != 0)
  70.   {
  71.     bug("non null log_type in vsf_log_start_entry");
  72.   }
  73.   p_sess->log_type = (unsigned long) what;
  74.   p_sess->log_start_sec = 0;
  75.   p_sess->log_start_usec = 0;
  76.   p_sess->transfer_size = 0;
  77.   str_empty(&p_sess->log_str);
  78.   if (vsf_log_type_is_transfer(what))
  79.   {
  80.     p_sess->log_start_sec = vsf_sysutil_get_time_sec();
  81.     p_sess->log_start_usec = vsf_sysutil_get_time_usec();
  82.   }
  83. }
  84. void
  85. vsf_log_line(struct vsf_session* p_sess, enum EVSFLogEntryType what,
  86.              struct mystr* p_str)
  87. {
  88.   vsf_log_common(p_sess, 1, what, p_str);
  89. }
  90. int
  91. vsf_log_entry_pending(struct vsf_session* p_sess)
  92. {
  93.   if (p_sess->log_type == 0)
  94.   {
  95.     return 0;
  96.   }
  97.   return 1;
  98. }
  99. void
  100. vsf_log_clear_entry(struct vsf_session* p_sess)
  101. {
  102.   p_sess->log_type = 0;
  103. }
  104. void
  105. vsf_log_do_log(struct vsf_session* p_sess, int succeeded)
  106. {
  107.   vsf_log_common(p_sess, succeeded, (enum EVSFLogEntryType) p_sess->log_type,
  108.                  &p_sess->log_str);
  109.   p_sess->log_type = 0;
  110. }
  111. static void
  112. vsf_log_common(struct vsf_session* p_sess, int succeeded,
  113.                enum EVSFLogEntryType what, const struct mystr* p_str)
  114. {
  115.   static struct mystr s_log_str;
  116.   /* Handle xferlog line if appropriate */
  117.   if (p_sess->xferlog_fd != -1 && vsf_log_type_is_transfer(what))
  118.   {
  119.     vsf_log_do_log_wuftpd_format(p_sess, &s_log_str, succeeded);
  120.     vsf_log_do_log_to_file(p_sess->xferlog_fd, &s_log_str);
  121.   }
  122.   /* Handle vsftpd.log line if appropriate */
  123.   if (p_sess->vsftpd_log_fd != -1)
  124.   {
  125.     vsf_log_do_log_vsftpd_format(p_sess, &s_log_str, succeeded, what, p_str);
  126.     vsf_log_do_log_to_file(p_sess->vsftpd_log_fd, &s_log_str);
  127.   }
  128.   /* Handle syslog() line if appropriate */
  129.   if (tunable_syslog_enable)
  130.   {
  131.     int severe = 0;
  132.     vsf_log_do_log_vsftpd_format(p_sess, &s_log_str, succeeded, what, p_str);
  133.     if (what == kVSFLogEntryLogin && !succeeded)
  134.     {
  135.       severe = 1;
  136.     }
  137.     str_syslog(&s_log_str, severe);
  138.   }
  139. }
  140. static void
  141. vsf_log_do_log_to_file(int fd, struct mystr* p_str)
  142. {
  143.   if (!tunable_no_log_lock)
  144.   {
  145.     int retval = vsf_sysutil_lock_file_write(fd);
  146.     if (vsf_sysutil_retval_is_error(retval))
  147.     {
  148.       return;
  149.     }
  150.   }
  151.   str_replace_unprintable(p_str, '?');
  152.   str_append_char(p_str, 'n');
  153.   /* Ignore write failure; maybe the disk filled etc. */
  154.   (void) str_write_loop(p_str, fd);
  155.   if (!tunable_no_log_lock)
  156.   {
  157.     vsf_sysutil_unlock_file(fd);
  158.   }
  159. }
  160. static void
  161. vsf_log_do_log_wuftpd_format(struct vsf_session* p_sess, struct mystr* p_str,
  162.                              int succeeded)
  163. {
  164.   static struct mystr s_filename_str;
  165.   long delta_sec;
  166.   enum EVSFLogEntryType what = (enum EVSFLogEntryType) p_sess->log_type;
  167.   /* Date - vsf_sysutil_get_current_date updates cached time */
  168.   str_alloc_text(p_str, vsf_sysutil_get_current_date());
  169.   str_append_char(p_str, ' ');
  170.   /* Transfer time (in seconds) */
  171.   delta_sec = vsf_sysutil_get_time_sec() - p_sess->log_start_sec;
  172.   if (delta_sec <= 0)
  173.   {
  174.     delta_sec = 1;
  175.   }
  176.   str_append_ulong(p_str, (unsigned long) delta_sec);
  177.   str_append_char(p_str, ' ');
  178.   /* Remote host name */
  179.   str_append_str(p_str, &p_sess->remote_ip_str);
  180.   str_append_char(p_str, ' ');
  181.   /* Bytes transferred */
  182.   str_append_filesize_t(p_str, p_sess->transfer_size);
  183.   str_append_char(p_str, ' ');
  184.   /* Filename */
  185.   str_copy(&s_filename_str, &p_sess->log_str);
  186.   str_replace_char(&s_filename_str, ' ', '_');
  187.   str_append_str(p_str, &s_filename_str);
  188.   str_append_char(p_str, ' ');
  189.   /* Transfer type (ascii/binary) */
  190.   if (p_sess->is_ascii)
  191.   {
  192.     str_append_text(p_str, "a ");
  193.   }
  194.   else
  195.   {
  196.     str_append_text(p_str, "b ");
  197.   }
  198.   /* Special action flag - tar, gzip etc. */
  199.   str_append_text(p_str, "_ ");
  200.   /* Direction of transfer */
  201.   if (what == kVSFLogEntryUpload)
  202.   {
  203.     str_append_text(p_str, "i ");
  204.   }
  205.   else
  206.   {
  207.     str_append_text(p_str, "o ");
  208.   }
  209.   /* Access mode: anonymous/real user, and identity */
  210.   if (p_sess->is_anonymous && !p_sess->is_guest)
  211.   {
  212.     str_append_text(p_str, "a ");
  213.     str_append_str(p_str, &p_sess->anon_pass_str);
  214.   }
  215.   else
  216.   {
  217.     if (p_sess->is_guest)
  218.     {
  219.       str_append_text(p_str, "g ");
  220.     } 
  221.     else
  222.     {
  223.       str_append_text(p_str, "r ");
  224.     }
  225.     str_append_str(p_str, &p_sess->user_str);
  226.   }
  227.   str_append_char(p_str, ' ');
  228.   /* Service name, authentication method, authentication user id */
  229.   str_append_text(p_str, "ftp 0 * ");
  230.   /* Completion status */
  231.   if (succeeded)
  232.   {
  233.     str_append_char(p_str, 'c');
  234.   }
  235.   else
  236.   {
  237.     str_append_char(p_str, 'i');
  238.   }
  239. }
  240. static void
  241. vsf_log_do_log_vsftpd_format(struct vsf_session* p_sess, struct mystr* p_str,
  242.                              int succeeded, enum EVSFLogEntryType what,
  243.                              const struct mystr* p_log_str)
  244. {
  245.   str_empty(p_str);
  246.   if (!tunable_syslog_enable)
  247.   {
  248.     /* Date - vsf_sysutil_get_current_date updates cached time */
  249.     str_append_text(p_str, vsf_sysutil_get_current_date());
  250.     /* Pid */
  251.     str_append_text(p_str, " [pid ");
  252.     str_append_ulong(p_str, vsf_sysutil_getpid());
  253.     str_append_text(p_str, "] ");
  254.   }
  255.   /* User */
  256.   if (!str_isempty(&p_sess->user_str))
  257.   {
  258.     str_append_char(p_str, '[');
  259.     str_append_str(p_str, &p_sess->user_str);
  260.     str_append_text(p_str, "] ");
  261.   }
  262.   /* And the action */
  263.   if (what != kVSFLogEntryFTPInput && what != kVSFLogEntryFTPOutput &&
  264.       what != kVSFLogEntryConnection && what != kVSFLogEntryDebug)
  265.   {
  266.     if (succeeded)
  267.     {
  268.       str_append_text(p_str, "OK ");
  269.     }
  270.     else
  271.     {
  272.       str_append_text(p_str, "FAIL ");
  273.     }
  274.   }
  275.   switch (what)
  276.   {
  277.     case kVSFLogEntryDownload:
  278.       str_append_text(p_str, "DOWNLOAD");
  279.       break;
  280.     case kVSFLogEntryUpload:
  281.       str_append_text(p_str, "UPLOAD");
  282.       break;
  283.     case kVSFLogEntryMkdir:
  284.       str_append_text(p_str, "MKDIR");
  285.       break;
  286.     case kVSFLogEntryLogin:
  287.       str_append_text(p_str, "LOGIN");
  288.       break;
  289.     case kVSFLogEntryFTPInput:
  290.       str_append_text(p_str, "FTP command");
  291.       break;
  292.     case kVSFLogEntryFTPOutput:
  293.       str_append_text(p_str, "FTP response");
  294.       break;
  295.     case kVSFLogEntryConnection:
  296.       str_append_text(p_str, "CONNECT");
  297.       break;
  298.     case kVSFLogEntryDelete:
  299.       str_append_text(p_str, "DELETE");
  300.       break;
  301.     case kVSFLogEntryRename:
  302.       str_append_text(p_str, "RENAME");
  303.       break;
  304.     case kVSFLogEntryRmdir:
  305.       str_append_text(p_str, "RMDIR");
  306.       break;
  307.     case kVSFLogEntryChmod:
  308.       str_append_text(p_str, "CHMOD");
  309.       break;
  310.     case kVSFLogEntryDebug:
  311.       str_append_text(p_str, "DEBUG");
  312.       break;
  313.     default:
  314.       bug("bad entry_type in vsf_log_do_log");
  315.       break;
  316.   }
  317.   str_append_text(p_str, ": Client "");
  318.   str_append_str(p_str, &p_sess->remote_ip_str);
  319.   str_append_char(p_str, '"');
  320.   if (what == kVSFLogEntryLogin && !str_isempty(&p_sess->anon_pass_str))
  321.   {
  322.     str_append_text(p_str, ", anon password "");
  323.     str_append_str(p_str, &p_sess->anon_pass_str);
  324.     str_append_char(p_str, '"');
  325.   }
  326.   if (!str_isempty(p_log_str))
  327.   {
  328.     str_append_text(p_str, ", "");
  329.     str_append_str(p_str, p_log_str);
  330.     str_append_char(p_str, '"');
  331.   }
  332.   if (what != kVSFLogEntryFTPInput && what != kVSFLogEntryFTPOutput &&
  333.       what != kVSFLogEntryDebug)
  334.   {
  335.     if (p_sess->transfer_size)
  336.     {
  337.       str_append_text(p_str, ", ");
  338.       str_append_filesize_t(p_str, p_sess->transfer_size);
  339.       str_append_text(p_str, " bytes");
  340.     }
  341.     if (vsf_log_type_is_transfer(what))
  342.     {
  343.       long delta_sec = vsf_sysutil_get_time_sec() - p_sess->log_start_sec;
  344.       long delta_usec = vsf_sysutil_get_time_usec() - p_sess->log_start_usec;
  345.       double time_delta = (double) delta_sec + ((double) delta_usec /
  346.                                                 (double) 1000000);
  347.       double kbyte_rate;
  348.       if (time_delta <= 0)
  349.       {
  350.         time_delta = 0.1;
  351.       }
  352.       kbyte_rate =
  353.         ((double) p_sess->transfer_size / time_delta) / (double) 1024;
  354.       str_append_text(p_str, ", ");
  355.       str_append_double(p_str, kbyte_rate);
  356.       str_append_text(p_str, "Kbyte/sec");
  357.     }
  358.   }
  359. }