モジュール

標準構成でユーザ認証をするためには,auth.so, auth_db.so, mysql.soと言ったモジュールが必要で,マニュアルによると,auth.so, auth_db.soを使うためにはmysql.soが必要だと書いてあります.ところが実際に試してみたところ,auth.soをはmysql.soを必要としませんでした.そこで,設定ファイルの認証部分,

  if (!www_authorize("iptel.org", "subscriber")) {
    www_challenge("iptel.org", "0");
    break;
  };
  save("location");
  break;

で使っている関数のうち,www_authorizeはauth_db.soをwww_challengeはauth.soを使っていたので,この部分を,

  if(!exec_msg("/usr/local/sbin/ser_acc.pl")){
    www_challenge("iptel.org", "0");
    break;
  };
  save("location");
  break;
};

と変更して認証できることを確認しました.このとき使ったser_scc.plスクリプトは以下のようになります.

#!/bin/perl 
# ser_acc.pl

use Digest::MD5 qw(md5_hex);
use strict;

my ($auth, $userid, $realm, $nonce, $uri, $response);
my $pass;
my ($a1, $a2, $digest);

$auth = $ENV{SIP_HF_AUTHORIZATION};
$pass = "def"  # テスト用

exit 1 unless ($auth);

if($auth =~ m{userid=\"([0-9a-zA-Z]+)\"}){
	$userid = $1;
}
if($auth =~ m{realm=\"([0-9a-zA-Z.]+)\"}){
	$realm = $1;
}
if($auth =~ m{nonce=\"([0-9a-zA-Z]+)\"}){
	$nonce = $1;
}
if($auth =~ m{uri=\"([0-9a-zA-Z.:]+)\"}){
	$uri = $1;
}
if($auth =~ m{response=\"([0-9a-zA-Z]+)\"}){
	$response = $1;
}

exit 1 unless ($userid && $realm && $nonce && $uri && $response);

$a1 = md5_hex( $userid . ':' . $realm . ':' . $pass );
$a2 = md5_hex( 'REGISTER' . ':' . $uri );
$digest = md5_hex ($a1 . ':' . $nonce . ':' . $a2 ); 

exit 1 if ($response ne $digest);
}

このスクリプトはREGISTERパケットのヘッダからAUTHORIZATIONフィールドを抜き出し,ダイジェスト認証を使って認証を行います.正常であればexit 0 を問題があればexit 1を最終的に実行します.exitしたときの値がexec_msgの返値になるので,これを使えばwww_authorizeの代わりになるというわけです.

このときのser.cfgは以下のようになります.

#
#   SER config script
#

# ----------- global configuration parameters ------------------------

check_via=no
dns=no
rev_dns=no
fifo="/tmp/ser_fifo"

# ------------------ module loading ----------------------------------

loadmodule "/usr/local/lib/ser/modules/sl.so"
loadmodule "/usr/local/lib/ser/modules/tm.so"
loadmodule "/usr/local/lib/ser/modules/rr.so"
loadmodule "/usr/local/lib/ser/modules/maxfwd.so"
loadmodule "/usr/local/lib/ser/modules/usrloc.so"
loadmodule "/usr/local/lib/ser/modules/registrar.so"
loadmodule "/usr/local/lib/ser/modules/exec.so"
loadmodule "/usr/local/lib/ser/modules/auth.so"

# ----------------- setting module-specific parameters ---------------

# -- usrloc params --
modparam("usrloc", "db_mode",   0)

# -- rr params --
modparam("rr", "enable_full_lr", 1)

# -------------------------  request routing logic -------------------

# main routing logic

route{
  if (!mf_process_maxfwd_header("10")) {
    sl_send_reply("483","Too Many Hops");
    break;
  };
  if ( msg:len > max_len ) {
    sl_send_reply("513", "Message too big");
    break;
  };

  record_route();	
  if (loose_route()) {
    t_relay();
    break;
  };

  if (uri==myself) {
    if (method=="REGISTER") {
      if(!exec_msg("/usr/local/sbin/ser_acc.pl")){
        www_challenge("iptel.org", "0");
        break;
      };

      save("location");
      break;
    };
    if (!lookup("location")) {
      sl_send_reply("404", "Not Found");
      break;
    };
  };
  if (!t_relay()) {
    sl_reply_error();
  };
}

これを使って何か面白いことできないかな. (^^;