logging.c 10 KB

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