日向夏特殊応援部隊

俺様向けメモ

ワイルド過ぎる realm のワイルドカードを何とかしたい - 前編 -

openid.realm の値が例えば、

  • *.org
  • *.co.jp

みたいなケース。これだと大多数のドメインを許可する事になってしまうので、これを避けたいと言う話。

その前にワイルド過ぎる realm の定義を決めてみる (ドメイン縛りで)

ワイルドカードを指定する事によって所有者の異なるドメインまで指定できてしまうようなケースを指す事にします。

どうすれば良いか

ではサンプルとして、openid.example.co.jp を取り上げて考えて見ましょう。

ドメイン部ですけど、カンマ区切りで右端にある物を TLD (top level domain) と言います。例えば .jp だとか .org だとか。

Top-level domain - Wikipedia によれば、主要なTLDとして

と言った物が挙げられます。*1

でちょっと脇道にそれてしまったけども、まずドメインの右端が TLD にマッチする事が必須条件。ここでは .jp がそれに当たるので残りは openid.example.co となります。

ここで次の右端である .co ですが SLD (second level domain) と言います。www.example.org ならば example がそれに当たります。

SLD までで、特定の所有者に紐づくのかそうでないかでワイルドな realm なのか、そうでないのかを判断して良いかと思います。なので、

  • *.co.jp は複数の所有者が考えられるので NG
  • *.example.org は特定の所有者だと考えられるので OK

って事になります。SLD でも ccTLD に紐づく SLD の事を ccSLD (country code SLD) と言うようです。

さて、wikipedia (en) の当該ページにあるリンクには MozillaWiki へのリンクがあります。

ただこれはどの程度、メンテナンスされてる情報かがイマイチ分からないのですよねぇ。とか思ってググってたら Mozilla がちゃんとメンテナンスしている事が分かりました。

nsIEffectiveTLDService ってのがあるらしく、元データは effective_tld_names.dat と言うファイルに集約されているみたいです。ここに ccSLD も含めた有効なドメインのパターンが存在し、結構ちゃんとメンテナンスされているみたいです。
ただ最近話題になっていた .me と言う ccTLD なんかはまだ無いみたい。Mozilla++ ですね。

さて Perl で書いてみよう

まず TLD ですが、Net::Domain::TLD と言うモジュールがありまして、ここから TLD のリストを得る事が出来ます。

#!/usr/bin/perl

use strict;
use warnings;

use Perl6::Say;
use Data::Dump qw(dump);
use Net::Domain::TLD qw(tlds tld_exists);

say '[tld types] ' . join(', ', Net::Domain::TLD::TLD_TYPES);
say '-' x 50;
say '[' . $_ . '] ' . join(', ', tlds($_)) for (Net::Domain::TLD::TLD_TYPES);

TLD の種別の出力と、TLD の種別ごとに TLD 一覧を出力します。

  • new_open
  • new_restricted
  • gtld_open
  • gtld_restricted
  • cc

と言うのが種別になります。

tld_exists は、

  • TLD と思しき文字列が
  • 指定されていればその種別にそのTLDが含まれているか
  • 指定されてなければそれが何らかの種別のTLDかどうか

と言うのを調べられます。

#!/usr/bin/perl

use strict;
use warnings;

use Perl6::Say;
use Data::Dump qw(dump);
use Net::Domain::TLD qw(tlds tld_exists);

say dump(tld_exists('org')); # org は TLD かどうか -> 1
say dump(tld_exists('hoge')); # hoge は TLD かどうか -> 0
say dump(tld_exists('jp', 'cc')); # jp は ccTLD かどうか -> 1
say dump(tld_exists('com', 'cc')); # com は ccTLD かどうか -> 0

TLD は調べられますが、SLD まではどうにもならないので、effective_tld_names.dat を利用してみます。

Gecko:Effective TLD Service - MozillaWiki によるとこのファイルの記述ルールは、

  • 行単位で読んでいく
  • // 以下はコメント
  • 何も無い行は無視
  • . はサブドメインの区切り文字
  • ! から始まるルールは直前のワイルドカードの除外パターンとして例外的に扱う

と言うルールのようです。

まずこれらのルールを考慮して TLD がどれだけ網羅されているか、Net::Domain::TLD と比較してみます。

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dump qw(dump);
use LWP::UserAgent;
use Net::Domain::TLD qw(tlds);
use Perl6::Say;

my $tld_names = 'http://mxr.mozilla.org/mozilla/source//netwerk/dns/src/effective_tld_names.dat?raw=1';
my $ua = LWP::UserAgent->new;
my $res = $ua->get($tld_names);

unless ($res->is_success) {
    die;
}

my %tlds = ();

for (split "\n" => $res->content) {
    s|(//.*)||g;
    s|\s+||g;
    next if (/^\n*$/);
    my $tld = ((split(/\./, $_))[-1]);
    $tlds{$tld}++;
}

say dump(scalar keys %tlds);
say dump(scalar (my @tlds = tlds));

say "-" x 50;

say dump(grep { !exists $tlds{$_} } @tlds);

結果は、

256
272
--------------------------------------------------
(
  "sj",
  "bv",
  "gb",
  "wf",
  "um",
  "me",
  "pm",
  "rs",
  "mf",
  "eh",
  "tp",
  "yt",
  "kp",
  "so",
  "bl",
  "tel",
)

なるほどなるほど。16個の TLDMozilla のリストからは漏れてるみたいです。

この未調査の TLD の事は別途何とかするかするとして、このデータを上手く使えば、ccSLD まで考慮に入れて realm の検証が出来そうです。

という訳で

次回、ccSLD も考慮に入れたモジュールを作ってみちゃったりする予定です。

*1:他は .arpa とか .nato とか