vsftpd 的日志不支持中文日文等字符, 在日志文件中所有的中文文件名都会显示为一连串的问号.
在 vsftpd 的源文件中可以看到为什么会是这样(示例源代码为 Ubuntu 8.04 系统仓库中的源代码.):
先看一看日志记录文件, file logging.c, line 152 - 171:
static void
vsf_log_do_log_to_file(int fd, struct mystr* p_str)
{
if (!tunable_no_log_lock)
{
int retval = vsf_sysutil_lock_file_write(fd);
if (vsf_sysutil_retval_is_error(retval))
{
return;
}
}
str_replace_unprintable(p_str, '?');
str_append_char(p_str, '\n');
/* Ignore write failure; maybe the disk filled etc. */
(void) str_write_loop(p_str, fd);
if (!tunable_no_log_lock)
{
vsf_sysutil_unlock_file(fd);
}
}
可以看到函数调用 str_replace_unprintable(p_str, '?'), 会把所有无法打印的字符全部替换为问号.
再看一看 str_replace_unprintable 函数, file str.c, line 656 - 668:
void
str_replace_unprintable(struct mystr* p_str, char new_char)
{
unsigned int i;
for (i=0; i < p_str->len; i++)
{
if (!vsf_sysutil_isprint(p_str->p_buf[i]))
{
p_str->p_buf[i] = new_char;
}
}
}
这样我们就有追踪到了函数 vsf_sysutil_isprint, file sysutil.c, line 883 - 903:
int
vsf_sysutil_isprint(int the_char)
{
/* From Solar - we know better than some libc's! Don't let any potential
* control chars through
*/
unsigned char uc = (unsigned char) the_char;
if (uc <= 31)
{
return 0;
}
if (uc == 177)
{
return 0;
}
if (uc >= 128 && uc <= 159)
{
return 0;
}
return isprint(the_char);
}
在这个文件中, 我们可以看到有那些字符是"可打印"的, 也可以看到为什么日志中的中文文件名会变成一连串的问号.
对此, 作者注释出了这样做的原因: "Don't let any potential control chars through".
这样尽可能的提高了安全性, 但是对于非拉丁语系的语言却造成了一些不便.
解决这个问题, 有两种方法:
1.注释掉 logging.c 文件中的 static void vsf_log_do_log_to_file(int fd, struct mystr* p_str) 函数中的
str_replace_unprintable(p_str, '?');
这一行. 这样在 UTF-8 的 locale 环境下就可以记录中文文件名了. 但是这样做会在一定程度上降低系统的安全性, 有可能会使一些攻击行为能够得逞.
2. 配置 vsftpd 通过 syslog 些日志: syslog_enable=YES
具体请参考:man vsftpd.conf
Be First to Comment