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/23(水)UDPをTCPにクローンするプログラム

UDPを受信してTCPにクローンするプログラム(複数クライアント対応)。本当はマルチスレッドで書いてあげるべきなのですが、そこまですると(実現する処理に対して)高級するぎる気がしたのでポーリングにしました。

というのも、TCPの通信エラーとかが出たときに(ブロックしないはずの)ソケットへの書き込み(データの送信)がバッファ一杯になるとストールして(止まって)しまうんですよね。もちろんソケットや書き込み時の関数はノンブロッキングに設定しておいても、です。C ではまだ確認していませんが、Perlで書いたときはそうでした。

TCP/IPはただ通信するだけなら簡単ですが、この手のエラー処理を考えはじめると非常に頭を使います。

プログラム

メイン部のみ。適当に main ルーチンを書けば Windows でも Unix系 でも動きます。

int	max_connections=100;
char	buffer[0x10000];
int	connection_pool[max_connections];

int accept_client(int listen_sock) {
	int sock, len;
	struct sockaddr_in sin;

	// accept
	len = sizeof(sin);
	sock = accept(listen_sock, (struct sockaddr *)&sin, &len);
	if (sock<0) error_return("client accept error");

	// 接続者情報
	printf("[%02d] Connection from %s\n", sock, inet_ntoa(sin.sin_addr));
	// ソケットの設定
	set_non_blocking(sock);
	return sock;
}

//////////////////////////////////////////////////////////////////////////////
// server main
//////////////////////////////////////////////////////////////////////////////
int udp2tcp_server_main(int udp_sock, int tcp_sock) {
	int i;
	char buf[1024];
	// select用の設定
	fd_set fdbits;
	fd_set fdbits_org;
	FD_ZERO(&fdbits_org);
	FD_SET(udp_sock, &fdbits_org);
	FD_SET(tcp_sock, &fdbits_org);

	while(1) {
		// Select
		memcpy(&fdbits, &fdbits_org, sizeof(fdbits_org));
		select(FD_SETSIZE, &fdbits, NULL, NULL, NULL);

		// New connection from TCP
		if ( FD_ISSET(tcp_sock, &fdbits) ) {
			int newsock = accept_client(tcp_sock);
			if (newsock>0) {
				// search for free connection pool point
				for(i=0; i<max_connections; i++)
					if (!connection_pool[i]) break;

				if (i<max_connections) {	// ソケット番号をセーブ
					FD_SET(newsock, &fdbits_org);
					connection_pool[i] = newsock;
					dbg("[%02d] save to connection_pool[%d]\n", newsock, i);
				} else {		// 接続を切る
					printf("Connections max\n");
					close(newsock);
				}
			}
		}

		// Recieved from UDP
		int size = 0;
		if ( FD_ISSET(udp_sock, &fdbits) ) {
			size = recv(udp_sock, buffer, BUF_SIZE, MSG_DONTWAIT);
			if (size<0) error_exit2("UDP recv error(%d)", size);
			dbg("[%02d] Recieved UDP %d bytes\n", udp_sock, size);
		}

		// TCP接続クライアントにデータを送信
		for(i=0; i<max_connections; i++) {
			int sock = connection_pool[i];
			if (!sock) continue;
			// socket からデータ受信
			if ( FD_ISSET(sock, &fdbits) ) {
				int s = recv(sock, buf, 1024, MSG_DONTWAIT);
				if (s<0) {
					FD_CLR(sock, &fdbits_org);
					connection_pool[i] = 0;
					dbg("[%02d] clear to connection_pool[%d]\n", sock, i);
					printf("[%02d] Connection close\n", sock);
					close(sock);
					continue;
				}
			}
			// データ送信
			if (size>0) {
				//int s = write(sock, buf, size);
				int s = send(sock, buf, size, MSG_DONTWAIT);
				dbg("[%02d] write TCP %d bytes\n", sock, s);
			}
		}
	}
}

2007/05/14(月)Borland C++ Builder 5をユーザー権限で使う

BDE5 は、管理者権限(Adminstrator)でインストール後、実ユーザー(一般ユーザー権限)で使用しようとすると、コンポーネント(ボタンなど)が一切表示されず(エラーになり)使い物になりません。

これは、BDEインストーラーが、ソフトウェアの設定をユーザー個人のレジストリに保存するためです。これを解消するには次のようにします。

  1. インストールーしたユーザーのレジストリを開き、HKEY_CURRENT_USER\Software\Borland 以下をすべて保存する。
  2. BDEを使用したいユーザーでログインし、保存したレジストリを挿入する

2007/05/09(水)PCスピーカーが調子悪い

例の改造PCスピーカーここも)の調子が悪い。

ガリしかない半固定抵抗がオープンになっているのに気付かず、Rチャンネルを長時間に渡って発振状態にしてしまってからダメですね。発振させると、ものの数秒で手で触れないぐらい TA8217P(パワーアンプIC)が熱くなりますから、それで損傷してしまったと思われます。

高域が入るとバリバリと寄生発振して、そのうち保護回路が働いて(?)右チャンネルだけ音が小さくなります。コンデンサが劣化したのか、ICが劣化したのか。ICだと同じ型のICは入手できないから、回路(実体配線)を変更する必要が出て面倒なんだよなぁ……

いじっているうちに 2007/05/09

いじっているうちに治った(汗)。考えられる説。

  • コンデンサ劣化 → いじっているうちにやや回復
  • ICか接点故障 → いじっているうちに接点回復

調子悪かったころから、あやしい半固定抵抗(フィードバック抵抗)の代わりに、カーボン抵抗突っ込んであります。しばらく様子見。どちらにしろ再現しないことには原因不明です(汗)