2007/05/25(金)FreeBSDはなぜ標準で APOP に対応していない?

FreeBSDでは比較的標準的に利用される pop デーモンである popa3d は、なぜか apop をサポートしていません。不思議に思ってつらつらと man を読んでいたら、次のように書かれていました。

POP3 transmits passwords in plaintext and thus, if you care about the security of your individual user accounts, should only be used either in trusted networks or tunneled over encrypted channels.

There exist extensions to the protocol that are supposed to fix this problem. popa3d does not support them yet, partly because this isn't going to fully fix the problem. In fact, APOP and the weaker defined SASL mechanisms such as CRAM-MD5 may potentially be even less secure than transmission of plaintext passwords because of the requirement that plaintext equivalents be stored on the server.

英語の練習がてら意訳してみますと、

POP3 はパスワードを平文で送ります。あなたのアカウントのセキュリティーが心配でならば、信頼されたネットワークか暗号化された通信経路を用いてください。

この問題を解決するためのプロトコルの拡張(注:APOP等のこと)が存在しますが、popa3d はサポートしていません。なぜなら、この拡張は問題を部分的に解決しますが完全な解決にはならないからです。実際、APOP や脆弱性のある SASL では CRAM-MD5 のような方式が使われおり、サーバに直接平文パスワードを記述する必要があるため、場合によっては平文パスワード認証よりもセキュリティーが劣ってしまいます。

つまりは、いくら通信路の安全を守るためとは言っても、サーバ上に大量のユーザーの平文パスワードを記述することはセキュリティ上問題ありませんかということですね。

調べてみると、apop自体に問題があるらしいですが。

結局popもftpもダメで、ssh(ssl) でトンネルしたもの以外は現状信用できないということになるんでしょうねぇ……。PAM の元に SMTP も POP も安全な形で統一してほしいのココロ。*1

*1 : ftpはsftpで問題なし

2007/05/08(火)fml + mhonarc による公開メーリングリストの構築

某所においてもともとfml4を使っていたのですが、www公開(html化)の際のデータが中途半端だったためfml8に移行しました。そこそこ綺麗に表示されたのですが、単一表示の状態から現在スレッドを辿ってメール表示することができないため、mhonarc に入れ替えました。その作業記録です。

MHonARC

MHonARCはメールをhtml化するプログラムです。ダウンロードはこの辺。FreeBSDのportsならば www/mhonarc にあります。fml のメールデータをhtml化する場合は例えば次のように行います。

mhonarc -add /var/spool/ml/xxx/spool -outdir /www/xxx

メールをhtml化した際のデータは DB ファイルに保管されていますので、すべて再生成したいときは次のようにします。

$ rm -f /www/xxx/*.html /www/xxx/.mhonarc.db

rcfile

MHonARCの設定ファイルをrcfileと言います。mhonarc は実行時に引数としてパラメーターを渡す方法とrcfileに書く方法、環境変数の3種類で動作指定ができます。ここでは rcfile を利用することにしました。

UTF8を使用することにしますので、サンプルである examples/utf-8.mrc をコピーします。公開アーカイブを置く /www/xxx にコピーしてしまいましょう。MHonArc Reference Manual から rcfileの設定項目 を参照して設定を書き換えます。

設定ポリシーとしては

  • メールアドレスは秘匿する(SPAM対策)
  • 余計なヘッダを出力しない

です。

<NoPrintXComments>
<SpamMode>
<IDXSIZE>
100
</IDXSIZE>
<MultiPG>
<NoMailTo>
<Reverse>
<Modtime>
<EXCS>
To
Subject
List-
Reply-to
In-reply-to
References
Domainkey-signature
Dkim-signature
</EXCS>
<LiTemplate>
<li><strong>$SUBJECT$</strong>, <em>$FROMNAME$</em></li>
</LiTemplate>

の設定項目を追加しました。

  • NoPrintXComments …… X-XXXX という形式でヘッダを出力する機能をオフにする
  • SpamMode …… Spam対策用のメールアドレス秘匿機能を on にする
  • IDXSIZE …… 100件ごとに index ファイルを分ける
  • NoMailTo …… MailTo をリンクしない
  • Reverse …… 逆順でソートする(新しいメールをページ先頭に)
  • EXCS …… 出力しないヘッダを指定する(先頭一致)
  • LiTemplate …… メール一覧ページで、1メール=1行で表示するための設定

mhonarc の自動更新設定

aliases ファイルを用いて mhonarc を自動的に更新します。

/var/spool/ml/xxx/mhonarc.include
"| /var/spool/ml/xxx/mhonarc.sh"
/var/spool/ml/xxx/mhonarc.sh
#!/bin/sh
/usr/local/bin/mhonarc \
        -rcfile /www/xxx/utf-8.mrc \
        -outdir /www/xxx \
        -add /var/spool/ml/xxx/spool

というファイルをまず用意します。sh ファイルには実行権限を付けておきましょう。

メーラーの aliases に次の1行を追加します(メーラーにより場所が変わります)。

mhonarc-xxx: :include:/var/spool/ml/xxx/mhonarc.include

sendmail ならば newaliases コマンドが必要でしょう。aliases ファイルから直接コマンドを実行しないのは、include ファイルを一度経由させることで、includeしたファイルの所有者権限でコマンドを実行できるからです。

ここまでの設定で、mhonarc-xxx@domain.nameにメールが届くたびにメーリングリストの公開wwwが更新されます。ですから、メーリングリストの受信者として mhonarc-xxx@domain.name を登録すれば設定完了です。

fmlならば /var/spool/ml/xxx/actives が受信者のリストですので、次のようにしましょう。

$ makefml add2actives ml-name mhonarc-xxx@domain.name

fml8メモ(無関係)

fml8の設定メモです。特に関係はありません。

article_subject_tag     = [$ml_name %05d]
article_header_rewrite_rules += rewrite_article_subject_tag
article_header_rewrite_rules += rewrite_reply_to_enforce_article_post_address

use_html_archive = no
html_archive_dir        = /xxxx/$ml_name/

2007/04/16(月)Debian 4.0(amd64) で Firefox が固まる問題

iceweasel ですが、about(iceweaselについて)を開くだけでも、ブラウザが固まってしまうという状況でまったく使いものになりませんでした。

原因は標準の日本語入力フロントエンドを削除して SCIM+Anthy をいれていたせいで、SCIMが固まりアプリが落ちたのが原因。

SCIMのフロントエンド設定から「全てのアプリケーションで同一入力メソッドを使用」のチェックを外すことで解決しました。本来、about などでは日本語入力がオフになっているようで、このチェックをいれておくと無理矢理 Anthy が起動しようとして不整合が起こっていたようです。

2007/04/05(木)PL2303X + Linuxで高速通信はできるか

FT232RLはとりあえず諦めて、PL-2303Xのドライバの動作を検討しました。

パッチを当ててインストール

Linuxソースの drivers/usb/serial/pl2303.c がデバイスドライバです。カーネルを再構築するのは大変なので、FT232のデバイスドライバから Makefile と Rules.make を拝借し、適当に書き換えてカーネルモジュールを作り増した。

1Mbpsは対応していませんので、ドライバをごにょごにょと書き換えます。

baud = 0;
switch (cflag & CBAUD) {
	case B0:	baud = 0;	break;
	case B75:	baud = 75;	break;
	case B150:	baud = 150;	break;
	case B300:	baud = 300;	break;
	case B600:	baud = 600;	break;
	case B1200:	baud = 1200;	break;
	case B1800:	baud = 1800;	break;
	case B2400:	baud = 2400;	break;
	case B4800:	baud = 4800;	break;
	case B9600:	baud = 9600;	break;
	case B19200:	baud = 19200;	break;
	case B38400:	baud = 38400;	break;
	case B57600:	baud = 57600;	break;
	case B115200:	baud = 115200;	break;
	case B230400:	baud = 230400;	break;
	case B460800:	baud = 460800;	break;
	default:
		err ("pl2303 driver does not support the baudrate requested (fix it)");
		break;
}
baud = 1000000;
dbg("%s - baud = %d", __FUNCTION__, baud);
if (baud) {
	buf[0] = baud & 0xff;
	buf[1] = (baud >> 8) & 0xff;
	buf[2] = (baud >> 16) & 0xff;
	buf[3] = (baud >> 24) & 0xff;
}
<中略>
i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
		     SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, 
		     0, 0, buf, 7, 100);

ソースをみれば分かりますが、このデバイスはかなり変わっていて、通信速度(Baud rate)を直接デバイスに送る(設定する)仕組みになっています(普通は分周カウンタの値を送る)。

さてこれで通信……としてみたものの、データがすべて化けてしまって全くだめでした。100Kbpsでもダメでした。これは通信速度が合っていないときに起こる症状です。どうやら、うまく分周されていないようなのですが、データシートには 6Mbps まで対応と書かれています。

原因

ここでみつけたPL-2303の資料(PDF)(Xなし)によれば(表3の少し手前)、

The programmable baud rate generator supports baud rates up to 1.2M bps

とのことで、どうやらドライバが PL-2303X に対応しておらず、PL-2303互換デバイスとして使用しているためではないかと思うのですが。つまり、PL-2303Xのデバイスドライバをみつければよいのではないかと……。

訂正。PL-2303X資料(pdf)によれば、高速な baud として設定可能な値は

921600, 1228800, 2457600, 3000000, 6000000

だそうです。微妙に使えない PL-2303X。

2007/04/02(月)FT232RL を Linux kernel 2.4.17 で認識させる

FTDI製FT232RL(FT232R)とは、3Mbpsまでの速度に対応した高速USBシリアルチップ(Serial Conveter)です。USBに接続するだけで、TTLレベルで高速シリアル通信が実現できます。

デバイスドライバの組み込み

ドライバ配布サイトでWindows用、Mac用、Linux用のドライバが配布されています。Linux kernel 2.4.20以降には標準でドライバが組み込まれていますが、2.4.17には組み込まれていません。

実験中ドライバの利用

Kernel 2.4.17にはFTDI USB Serialのドライバが実験中として組み込まれています。

USB support
 -> USB Serial Converter support
   -> <*> USB FTDI Single Port Serial Driver (EXPERIMENTAL)
usbserial.c: FTDI 8U232AM converter detected
usbserial.c: FTDI 8U232AM converter now attached to ttyUSB0 (or usb/tts/0 for devfs)

カーネルにこれを組み込むことで一応認識はするのですが、次の問題が起きました。

  • 9600, 19200, 38400, 78600……921600(最大)といった系列しか指定できない。*1
  • 試しに460800に設定したところ、使用したマシンが非力なのかKernelごと落ちた(応答しなくなった)

公式配布ドライバの使用

配布されているドライバソース ftdi_sio.tar.gz を展開し make します。make するためにはカーネルのソース(の一部、ヘッダ類)が必要です。

kernelソースを展開し適切にパスを設定後 make してみると、コンパイルエラーが発生しました。どうやらkernelが古いせいか

	.owner =		THIS_MODULE,

という項目が存在しない*2のが原因のようです。これらの行をすべて削除(またはコメントアウト)することでコンパイルできるようになります。make が無事成功すると、ftdi_sio.oというファイルができます。これがドライバ本体(カーネルモジュール)です。

このドライバをカーネルに組み込むためには root で次のようにコマンドを実行します。

組み込み
# insmod ftdi_sio.o
Kernelから削除
# rmmod ftdi_sio.o
組み込み済カーネルモジュールの確認
# lsmod

組み込んでみたのですが、エラーが出てしまい、ドライバが動作しません。

ftdi_sio.c: v1.3.5r1:USB FTDI Serial Converters Driver
hub.c: USB new device connect on bus1/1, assigned device number 3
usbserial.c: descriptors matched, but endpoints did not
usb.c: USB device 3 (vend/prod 0x403/0x6001) is not claimed by any active driver.

0x403/0x6001は、FTDIの8U232AMを示し、ドライバソースには実際その記述があるのですが、「but endpoints did not」と出て認識しません。endpoints とは何であるかということですが、調べてみるとUSBデバイスがホスト側と通信する際に利用するバッファのことのようです。

要するにエンドポイントの設定がおかしいと言っているのですが、ドライバのソースにはきちんと記述されています。

static struct usb_serial_device_type ftdi_8U232AM_device = {
/*	.owner =		THIS_MODULE, */
	.name =			"FTDI 8U232AM Compatible",
	.id_table =		id_table_8U232AM,
	.num_interrupt_in =	0,
	.num_bulk_in =		1,
	.num_bulk_out =		1,

usbserial.c をみてみると

/* verify that we found all of the endpoints that we need */
if (!((interrupt_pipe & type->needs_interrupt_in) &&
      (bulk_in_pipe & type->needs_bulk_in) &&
      (bulk_out_pipe & type->needs_bulk_out))) {
	/* nope, they don't match what we expected */
	info("descriptors matched, but endpoints did not");
	return NULL;
}

ということで、この項目が設定されてないことが原因のようです。

公式配布ドライバへのパッチ

ftdi_sio.c の中に記述されているすべてのデバイス情報(8U232AM, FT232BM等々)について、次のような書き換えを行います。

static struct usb_serial_device_type ftdi_8U232AM_device = {
/*	.owner =		THIS_MODULE,	*/
	.name =			"FTDI 8U232AM Compatible",
	.id_table =		id_table_8U232AM,
	.needs_interrupt_in =	DONT_CARE,
	.needs_bulk_in =	MUST_HAVE,
	.needs_bulk_out =	MUST_HAVE,
	.num_interrupt_in =	0,

色が変わっているところが追加部分です。これをコンパイルしてカーネルモジュールを作成しインストールすると、

usbserial.c: FTDI FT232BM converter detected
usbserial.c: FTDI FT232BM converter now attached to ttyUSB0 (or usb/tts/0 for devfs)

として認識されます。

FT232RLと表示されませんが仕様です。コンピューターデバイスではよくあることで、デバイスとして異なってもソフトウェア的に同一の場合は、同じプロダクトIDを持つことがあります。また1つのデバイスで仮想的に(ソフト的に)複数のデバイスが存在するということもあるため、デバイスの型とソフト的に見える型の不一致などが頻繁に起きます。

*1 : あたらしいドライバならば任意の速度が設定出来ることはソースより確認済

*2 : struct usb_serial_device_type

ターミナルによる通信 2007/04/03

シリアルポートの設定を変更したり、任意の速度で通信するためにはターミナルや設定ソフトが必要ですが、minicom や stty などはお節介なことに"9600, 19200……"系列しか指定できません。kermit もダメでした。

いろいろ調べたところ、cu というコマンドで指定できました。cu コマンドは uucp と一緒に配布されています(リンク先、左下のソースから uucp_1.07.orig.tar.gz をダウンロード)。

# tar zxvf uucp_1.07.orig.tar.gz
# cd uucp-1.07
# ./configure
# make
# make install
# mkdir /usr/spool
# mkdir /usr/spool/uucp
# chown uucp /usr/spool/uucp

利用方法は次のようになります。

# cu -l /dev/ttyUSB0 -s 38400

1Mbps通信はできるか?

早速

# cu -l /dev/ttyUSB0 -s 1000000 -d
cu: fconn_open: Opening port /dev/ttyUSB0 (speed 1000000)
cu: fconn_set: Changing setting to 1, 2, 2

と設定してみます(-d はデバッグフラグです)。ところが、公式ドライバでも、2.4.17付属ドライバでも通信速度が変更できないようです。ドライバソースを改造してデバッグメッセージを出力させてみると、

ftdi_sio.c: Set to 9600

などと出てしまいます。カーネルの段階(tty?)で通信速度が書き換えられている模様です(詳細不明)。

仕方がないので、ドライバのソース(ftdi_sio.c)を書き換えて、無理矢理 1Mbps 通信をさせてみました。

  • Linux 2.4.17付属ドライバ …… 99%程度取りこぼし、使い物にならない
  • 公式配布ドライバ …… 通信速度の設定によらず、1byteも受信できない

以上うまく通信できませんでした。Linux 2.4.17のドライバは未成熟である可能性は捨てきれず、逆に公式配布ドライバはカーネルが古すぎるために(非互換により)通信すら行えていない可能性が高いと思います。

Linux 2.4.17のドライバを改変し受信したデータ

00001,00001,00001,00001,00001,00001,00001,00001,00001,00001

00002,00002,00002,00002,00002,00002,00002,00002,00002,00002

00003,00003,00003,00003,00003,00003,00003,00003,00003,00003

00004,00004,00004,00004,00004,00004,00004,00004,00004,00004

00005,00005,00005,00005,00005,00005,00005,00005,00005,00005

00006,00006,00006,00006,00006,00006,00006,00006,00006,00006

00007,0000720,359205921,35921,35921,35921,35921,35921,35921,35921

35922,35922,35935922,35922

35923,35923,35923,35923,35923,35923,35923,35923,3535924,35924,35924,35924,35924,35924

35925,35925,35925,35925,35

35926,35926,35926,35926,35926,35926,35926,359

FT232Rとして認識しない原因 2007/04/04

ftdi_sio.h では

#define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */

となっていて、いくつかの製品で同じプロダクトID(PID)を持っています。複数の製品をどうやって見分けているのかなと思ったのですが、productversion という2バイトの値で識別しているようです。

USB_DEVICE_VER (vendorId, productId, lo, hi)
	... like USB_DEVICE with lo <= productversion <= hi
<略>
static struct usb_device_id id_table_8U232AM [] = {
	{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0, 0x3ff) },
	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) },
<略>
static struct usb_device_id id_table_FT232BM [] = {
	{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0x400, 0xffff) },
	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) },
<略>
static struct usb_device_id id_table_FT232R[] = {
	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x600, 0xffff) },

0xffff0x5ff に書き換えることで、FT232R と認識しますが、特に挙動は変わりませんでした。usb_serial_device_type をみても表示文字列以外、内部処理に特に違いはないようです。

その後の検討とまとめ

  • 公式ドライバの ftdi_read_bulk_callback() 内の "port->open_count" の条件文を無効化(常に真)することでデータ通信はできましたが、Linux 2.4.17ドライバ同様に99%取りこぼしでした。
  • 試しに usbserial.c を別バージョンのカーネルから引っ張ってきましたが、案の定コンパイルすらできませんでした。
  • Linux 2.4.17で 100kbps で受信させてみましたが、それでも多少取りこぼしが発生しました。
  • Linux 2.6.17カーネルで試したところ、何の問題*3もなく動作しました。
    Linux version 2.6.17
    [17179838.796000] usb 1-1: configuration #1 chosen from 1 choice
    [17179838.800000] ftdi_sio 1-1:1.0: FTDI USB Serial Device converter detected
    [17179838.800000] drivers/usb/serial/ftdi_sio.c: Detected FT232BM
    [17179838.800000] usb 1-1: FTDI USB Serial Device converter now attached to ttyUSB0
    
    # stty -F /dev/ttyUSB0 1000000
    # cat /dev/ttyUSB0
    

Linux 2.4.17時代にはおそらく高速シリアル通信は考えられておらず、そのためまともに通信できないのではないかと思います。

もっとも、使用したマシンが非力すぎるという可能性も捨てきれない面はありますが、PowerPCベース200MHz程度あれば、いくら何でも100KB/sぐらい受信してよさそうですので(LANは3Mbps以上でてますし)。

残された道

  • Linux 2.4.17カーネルのドライバを適当に最新カーネルのものに入れ替える。
  • Linux 2.4.17カーネルのドライバを元に地道にパッチを当てる。
  • Linux 2.4.34等の最新カーネルをベースに、特殊ハード(組み込み)向けの改造を加える。
  • VCPドライバではなく、D2XXドライバの利用を検討する。x86バイナリのみの提供のため利用不可。

*3 : 取りこぼしもおそらくなし