ssh接続で 'Too many authentication failures'

久々の更新です。ちょっと焦ったことがあったのでメモ。

サーバーを移転中で、今日ベンダーさんから設置完了の連絡があり ssh で接続しようとした所こんなエラーが...

Received disconnect from XXX.XXX.XXX.XXX: 2: Too many authentication failures for hoge

なんか怪しいエラーです(^^;

今回のサーバーは、sshVPN経由のみの接続ということで passwd認証ありで構築されている様子。
ヘルプを見ると -o で色々とオプションを指定できるということでこんな感じ。

$ ssh -2 -o PreferredAuthentications=password hoge@XXX.XXX.XXX.XXX

無事接続できました!

最近は、Objective-Cと戯れる毎日です。来月くらいには、iPhoneアプリを公開できるとおもいます。
無事公開したら報告したいと思います〜。

openssl-1.0.0 + mod_ssl-2.8.31

ずいぶん昔に制作したサーバーの移転準備をしています。
openssl-1.0.0がでていたので使おうとしたら、apacheのコンパイル時に以下の様なエラーがでました。

gcc -c -I../../os/unix -I../../include -DLINUX=22 -DHAVE_SET_DUMPABLE -I/usr/include/gdbm -DMOD_SSL=208131 -DUSE_HSREGEX -DEAPI -DUSE_EXPAT -I../../lib/expat-lite `../../apaci` -fpic -DSHARED_MODULE -DSSL_COMPAT -DSSL_USE_SDBM -I/usr/local/include -DMOD_SSL_VERSION=\"2.8.31\" ssl_util_ssl.c && mv ssl_util_ssl.o ssl_util_ssl.lo
ssl_util_ssl.c: In function ‘SSL_X509_isSGC’:
ssl_util_ssl.c:327: error: ‘STACK’ undeclared (first use in this function)
ssl_util_ssl.c:327: error: (Each undeclared identifier is reported only once
ssl_util_ssl.c:327: error: for each function it appears in.)
ssl_util_ssl.c:327: error: ‘sk’ undeclared (first use in this function)
ssl_util_ssl.c:336: error: expected expression before ‘)’ token
make[4]: *** [ssl_util_ssl.lo] エラー 1
make[3]: *** [all] エラー 1
make[2]: *** [subdirs] エラー 1
make[2]: ディレクトリ `/usr/local/src/apache_1.3.41/src' から出ます
make[1]: *** [build-std] エラー 2
make[1]: ディレクトリ `/usr/local/src/apache_1.3.41' から出ます
make: *** [build] エラー 2

調べてみたところ、openssl-1.0.0で、STACK構造体が _STACK に変更になった様です。

// openssl-0.9.8n/include/openssl/stack.h 66-74
typedef struct stack_st
        {
        int num;
        char **data;
        int sorted;

        int num_alloc;
        int (*comp)(const char * const *, const char * const *);
        } STACK;

// openssl-1.0.0/include/openssl/stack.h 66-74
typedef struct stack_st
        {
        int num;
        char **data; 
        int sorted; 

        int num_alloc;
        int (*comp)(const void *, const void *);
        } _STACK;  /* Use STACK_OF(...) instead */

構造的な変更は無い様なので、mod_sslに以下の様なpatchをあてて対応しました。

--- ssl_util_ssl.orig.c 2010-04-17 13:11:24.000000000 +0900
+++ ssl_util_ssl.c      2010-04-17 13:12:05.000000000 +0900
@@ -324,7 +324,7 @@
 {
     X509_EXTENSION *ext;
     int ext_nid;
-    STACK *sk;
+    _STACK *sk;
     BOOL is_sgc;
     int idx;
     int i;
@@ -333,7 +333,7 @@
     idx = X509_get_ext_by_NID(cert, NID_ext_key_usage, -1);
     if (idx >= 0) {
         ext = X509_get_ext(cert, idx);
-        if ((sk = (STACK *)X509V3_EXT_d2i(ext)) != NULL) {
+        if ((sk = (_STACK *)X509V3_EXT_d2i(ext)) != NULL) {
             for (i = 0; i < sk_num(sk); i++) {
                 ext_nid = OBJ_obj2nid((ASN1_OBJECT *)sk_value(sk, i));
                 if (ext_nid == NID_ms_sgc || ext_nid == NID_ns_sgc) {

2010.5.20 追記
http://dsas.blog.klab.org/archives/51719714.html
こんな情報もあるようなので、1.0.0の使用は注意が必要な感じですね。

2010.5.20 追記2
http://slashdot.jp/security/comments.pl?sid=490412&cid=1742785
makeのオプションにOPTIM=-DSTACK=_STACKを指定するとソースは修正せずに対応できるようです。

独自namedパラメータを使って逆ルーティング

結構な忙しさなのですが、id:cakephperさんのTweetをみて妙に納得してしまったので、昨日はまってた事をまとめました。

CakePHP 1.2.5で開発中です。

namedパラメータはなかなかに便利なのですが、独自のnamedパラメータを使っているURLの逆ルーティングではまったのでちょっと調べてみました。

通常の以下の様なルーティングであれば、独自のnamedパラメータも問題なく使えます。

<?php
Router::connect('/:controller/:action/*');

$url = Router::url(array('controller' => 'posts', 'action' => 'index', 'mode' => 'test')) ;
// 正しく変換できます
// $url = "/posts/index/mode:test"

ところがprefix routingを使ったりすると状況が変わります。例えば、以下の様に携帯対応のためにprefix routingとURLにセッションキーを埋め込むような場合ですね。

<?php
Router::connect('/m/:session/:controller/:action/*', 
  array('prefix' => 'mobile', 'mobile' => true), 
  array('session' => '[a-zA-Z0-9]{32}')
);

$url = Router::url(array('controller' => 'posts', 'action' => 'index', 
  'mobile' => true, 'page' => 1, 'session' => '11111111112222222222333333333344')) ;
// page等のCakePHPで標準的に使われているnamedパラメータは問題なし
// $url = "/m/11111111112222222222333333333344/posts/view/page:1"

$url = Router::url(array('controller' => 'posts', 'action' => 'index', 
  'mobile' => true, 'mode' => 'test', 'session' => '11111111112222222222333333333344')) ;
// 独自のnamedパラメータを使うとこんな感じになってしまいます
// $url = "/posts/view/mobile:1/mode:test/session:11111111112222222222333333333344"

色々と調べた結果、namedパラメータとして使用する変数名を登録することができるようです。

Routerクラスに定義されている、connectNamedを使うことで使用可能なnamedパラメータをカスタマイズすることができます。
例えば上記の例の場合には、以下のように指定すると正常に変換できるようになります。

<?php
// 'default'=>true を指定しないとCakePHP標準のnamedパラメータを上書きしてしまうので注意!
Router::connectNamed(array('mode'), array('default'=>true)) ;

connectNamedメソッドのコメントを見ると適用するコントローラやアクションを指定出来そうなのですが、私が試した範囲では制限をかけられませんでした。(アプリすべてのコントローラに適用されます)
追いかけきれていないので、時間ができたらもう少し調べてみたいと思います。

参考

  • ルーティングの設定に失敗するとハマる事がおおいので、しっかりテストも書きましょう!ということで、ルーティングのテストについては以下の新原さんの記事がとても参考になります!

csv_sourceにfind,paginate対応を追加しました

先日のPHP勉強会の発表で取り上げた、csv Datasourceはcsvが非常に馴染み深いフォーマットなので Datasourceの挙動を理解するのにはとても良い教材だと思います。しかし、findやpaginateには対応していない簡易なものなので発表した勢いで簡単なfindとpaginateの対応を追加してみました。

http://github.com/kaz29/datasources/tree/csv

当初ベタっと(^^; 実装していたのですが、id:hiromi2424 さんのtweetをみて Set::matches を使う方法に変更しました。Set::matchesでサポートしている演算子であれば正常に動作すると思います。

実際のfindは、DBOを扱うときと同様な以下の形式に対応しています。

" => 10,
"status" => 1
);

$conditions = array(
"or" => array(
"id <=" => 10,
"status" => 1
)
);

paginateを実現するために一回のfindですべての行を2回走査します。
あまり大きなcsvファイルを扱う用途には不向きだと思いますが、Datasourceを理解する参考になればうれしいです。

# 時間見つけてテスト書かないとね...。

第49回PHP勉強会@関東で発表してきました

第49回PHP勉強会@関東で、久々の参加&発表してきました。

第49回PHP勉強会@関東
http://events.php.gr.jp/events/show/88

発表資料

サンプルコードはこちらから

発表は相変わらず...でしたが、なんとかDatasourceの面白さは伝えられたかなぁと思います。

lithiumは、とても刺激的ですね。私も2,3日ほど前に落として色々中を見ていますが、PHP5.3を今まで全く使っていないので苦戦していたので、安藤さんの発表はとても良いヒントになりました!

Schema ShellでDB設定を切り替える方法

忘れそうなのでメモ。

今開発中の案件では、DBのスキーマ情報をCakeSchemaで管理しています。
本番環境に反映時する際、DB設定の切り替え方がわからなかったので調べてみました。

connectionというパラメータを指定すると切り替えられます。以下の例だと「production」というのがdatabase.phpで設定された設定名になります。

php cake/console/cake.php schema run create -connection production

CakeLogをスマートにカスタマイズする方法

CakePHPのログ出力処理は結構簡易なもので今ひとつ使いにくいです。また、「内部的に flock してるからアクセスが多いと遅いので実運用では使わない方が良いよ!」という話も聞いていたので、うちではカスタマイズしたものを使っています。

ROOT/cake/libs/cake_log.phpを書き換えてしまえばそれでも良いのですが、COREのコードを書き換えずにカスタマイズする方法を見つけたのでまとめました。

ログ出力処理は、objectクラスのメソッドとして実装されていて実際のコードは以下のようになっています。

<?php
// cake/libs/cake_log.php
...
	function log($msg, $type = LOG_ERROR) {
		if (!class_exists('CakeLog')) {
			uses('cake_log');
		}
		if (is_null($this->_log)) {
			$this->_log = new CakeLog();
		}
		if (!is_string($msg)) {
			$msg = print_r($msg, true);
		}
		return $this->_log->write($type, $msg);
	}
...

上記のコードの通り、このコードが実行される前に CakeLog というクラスを定義してしまえば差し替えが出来そうです。

で、どこにその設定を書けば良いか探るために起動時にどんな順番で処理が遷移するか主なファイルにログを仕込んでみました。
取得した結果は以下のとおり。

1. ROOT/cake/bootstrap.php
2. ROOT/app/config/core.php
3. ROOT/cake/libs/cake_log.php
4. ROOT/cake/config/config.php
5. ROOT/app/config/bootstrap.php
6. ROOT/cake/dispatcher.php

ということで、cake_log.php より前に呼ばれているAPP側のファイルは core.phpだけなのでここになにか仕込めば良さそうです。

実際のログ出力は、LOG4PHPを使うなりsyslogを使うなり適宜実装し、APP/app_log.phpに以下のように CakeLogクラスを定義します。

# LOG4PHPを使う方法は以下がとでも参考になりました。

<?php
// app/app_log.php
class CakeLog {
  function CakeLog() {
    $args = func_get_args();
    if (method_exists($this, '__destruct')) {
      register_shutdown_function (array(&$this, '__destruct'));
    }
  }
  
  function __destruct() {
...
  }
  
  function write($type, $msg) {
...
  }

で、APP/config/core.phpの一番頭に以下のように記述すれば、上記クラスが使用されます。

<?php
require_once(dirname(dirname(__FILE__)).DS.'app_log.php') ;
...

COREに手を入れずにカスタマイズできてなかなか良いのではないかと思います。一度試してみてはいかがでしょうか?