Monday, March 29, 2010

vsftpd的文件名编码

问题的来由

前几天, 朋友被这一个需求烦着:希望freeBSD下的vsftpd不把用户(windows环境)上传的文件名保存为UTF-8,即希望是GBK编码。
在vsftpd的配置文件里, 没有提到这样的配置项。
于是,兴趣一上, 自己就去看vsftpd的代码了。 都是找了一圈,根本没有找到vsftpd是如何转编码的代码。(linux下的软件不都是使用libc的iconv函数的吗?)
于是想了一下,这种编码转换不是由vsftpd处理的, 而是由用户端软件处理的, 也就是说ftp协议本身有这样的定义。

理由:
1. server端根本不知道client系统是使用什么编码的
2. 在vsftpd的代码没有看到一点编码转换的代码。

在这两种情况下, 只能在通信中指定编码的类型。协议中应该有这样的定义。

查到的文档

于是, 去查看RFC文档: http://filezilla-project.org/specs/rfc2640.txt

FTP对FEAT命令的要求:
3.3 Clients compliance
   - Clients MUST support the FEAT command and recognize the "UTF8"
     feature (defined in 3.2 above) to determine if a server supports
     UTF-8 encoding.
* 注意其中的MUST单词。
* client端是一定可以知道服务端是否支持UTF-8的

上面可以看到: client端是一定可以知道服务端是否支持UTF-8的

使用wireshark分析

监听网络是最方便判断这个问题的方法。
如果是client传送了UTF-8字节流, 在client发出的通信数据中, 一定是UTF-8的.如下是使用wireshark监听到的client請求:
7    18.059426    192.168.0.102    192.168.0.102    FTP    Request: MKD \346\226\260\346\226\207\344\273\266\345\244\271 (7)
看到得到一串bytes, 这串bytes就是UTF-8数据:
print(unicode("\346\226\260\346\226\207\344\273\266\345\244\271","utf-8"))
新文件夹

测试FEAT和OPTS命令

关系feat和opts命令, 可以从这里得到信息:http://www.networksorcery.com/enp/rfc/rfc2389.txt
The File Transfer Protocol is, from time to time, extended with new
commands, or facilities. Implementations of the FTP protocol cannot
be assumed to all immediately implement all newly defined mechanisms.
This document provides a mechanism by which clients of the FTP
protocol can discover which new features are supported by a
particular FTP server.


feat和opts不是user interface, 它是FTP协议的命令, 就如HTTP中的session和host一样
所以使用客户端是无法看到的, 比如lftp或者ftp
好在ftp协议是本文协议, 可以使用telnet看清楚。
$ telnet 192.168.0.102 21
Trying 192.168.0.102...
Connected to 192.168.0.102.
Escape character is '^]'.
220 (vsFTPd 2.2.2)
user jessinio
331 Please specify the password.
password
530 Please login with USER and PASS.
feat
211-Features:
 EPRT
 EPSV
 MDTM
 PASV
 REST STREAM
 SIZE
 TVFS
 UTF8
211 End

可以看到支持UTF-8功能。

opts命令是为实现ftp日益增加的命令而存在的。下面测试opts命令:
$ telnet 192.168.0.102 21
Trying 192.168.0.102...
Connected to 192.168.0.102.
Escape character is '^]'.
220 (vsFTPd 2.2.2)
user jessinio
331 Please specify the password.
ivwsydfku
530 Please login with USER and PASS.
opts utf on
501 Option not understood.
opts utf8 on
200 Always in UTF8 mode.


手工禁止vsftpd的功能

现在把vsftpd代码里的feat命令和对opts命令返回信息做一下修改.

把features.c文件中的
vsf_cmdio_write_raw(p_sess, " UTF8\r\n");
去掉
把opts.c文件的handle_opts函数修改成如下:
 14 void
 15 handle_opts(struct vsf_session* p_sess)
 16 {
 17   str_upper(&p_sess->ftp_arg_str);
 18   //if (str_equal_text(&p_sess->ftp_arg_str, "UTF8 ON"))
 19   //{
 20   //  vsf_cmdio_write(p_sess, FTP_OPTSOK, "Always in UTF8 mode.");
 21   //}
 22   //else
 23   //{
 24     vsf_cmdio_write(p_sess, FTP_BADOPTS, "Option not understood.");
 25   //}
 26 }


No comments:

Post a Comment

Note: Only a member of this blog may post a comment.