2011年6月15日水曜日

Net-SNMP viewの設定

snmpd.conf の view 設定として、下記が "全て公開" になるというサンプルがありますが、なぜそうなるのか分からなかった(特にMASK部分)ので、調べてみました。
##           incl/excl  subtree                     mask
view all    included   .1                             80

まずは 'man snmpd.conf'。mask の指定は16進数ということは分かったけれど、まだハッキリしない。
view VNAME TYPE OID [MASK]
...
  MASK is a list of hex octets (optionally separated by '.' or ':') 
  with the set bits indicating which   subidentifiers in the view 
  OID to match against.

ここのメーリングリストの説明を見て、やっと分かった!












つまり、ビットが立っている部分は固定(指定したOIDそのまま)で、立っていない部分はワイルドカードの扱いになると。実際に確認してみよう。

たとえば、このようなインターフェース構成のサーバで、"全て公開"の設定にしていると、全てのインターフェースの情報が見える(当然ですね!)
# snmpwalk -v 2c -c private localhost .1.3.6.1.2.1.2.2.1.2
IF-MIB::ifDescr.1 = STRING: lo
IF-MIB::ifDescr.2 = STRING: eth0
IF-MIB::ifDescr.3 = STRING: eth1
IF-MIB::ifDescr.4 = STRING: eth2

(「受信した総バイト数」を表示)
# snmpwalk -v 2c -c private localhost .1.3.6.1.2.1.2.2.1.10
IF-MIB::ifInOctets.1 = Counter32: 1270274
IF-MIB::ifInOctets.2 = Counter32: 165686032
IF-MIB::ifInOctets.3 = Counter32: 9656051
IF-MIB::ifInOctets.4 = Counter32: 635738

(「送信した総バイト数」を表示)
# snmpwalk -v 2c -c private localhost .1.3.6.1.2.1.2.2.1.16
IF-MIB::ifOutOctets.1 = Counter32: 1270274
IF-MIB::ifOutOctets.2 = Counter32: 19914854
IF-MIB::ifOutOctets.3 = Counter32: 805032
IF-MIB::ifOutOctets.4 = Counter32: 8933886

ここで、このように設定を変更すると、
view ifRow4 included .1.3.6.1.2.1.2.2.1.0.4  0xff:a0
4番目のインターフェース(eth2)の情報しか見えなくなる。
# snmpwalk -v 2c -c private localhost .1.3.6.1.2.1.2.2.1.10
IF-MIB::ifInOctets.4 = Counter32: 635738

# snmpwalk -v 2c -c private localhost .1.3.6.1.2.1.2.2.1.16
IF-MIB::ifOutOctets.4 = Counter32: 8933886
公開する情報を、特定のインターフェースに制限しつつ、様々な IfEntry を取得したい時などに便利そうですね。

まとめると、下記の設定はMIBのオブジェクトツリーのトップ('iso(1)')にのみビットが立っているので、配下のオブジェクトは任意 = 全て公開 ということになるんですね。
.1
 1 0 0 0 0 0 0 0   = 0x80

2011年6月1日水曜日

Python の hash関数

Google Code University に Gruyere というデモサイトを使って、Webアプリケーションの脆弱性と対策を説明しているガイドがあります。

少しずつ読み進めているのですが、cookie処理の部分について少し調べてみました。

gruyere.py (601行目)
def _CreateCookie(self, cookie_name, uid):
    ....
    h_data = str(hash(cookie_secret + c_data) & 0x7FFFFFF)

発行するcookieにハッシュ値を付与している部分ですが、「Pythonのhash関数はセキュアでないため、"違う文字列で同じハッシュ値" を短い時間で発見できる」と説明されています。

そうすると cookie_secret を知らなくても、cookieの改ざんができてしまうため、この用途にhash関数は向いていないとのこと。対策として「セキュアなhash関数を使用する」とあるので、hashlib などを使用するべきなのかな。

そもそも、Pythonのhash関数は dict での使用に適するようにされていて、ランダムよりも(末尾の文字がインクリメントされるような)よく似たケースにおいて規則的な変化をする性質を重視していると dictobject.c のコメントに書かれているんですね。

python/Objects/dictobject.c
/*
Major subtleties ahead:  Most hash schemes depend on
having a "good" hash function, in the sense of simulating
randomness.  Python doesn't:  its most important hash
functions (for strings and ints) are very regular in
common cases:
'''
>>> map(hash, (0, 1, 2, 3))
[0, 1, 2, 3]
>>> map(hash, ("namea", "nameb", "namec", "named"))
[-1658398457, -1658398460, -1658398459, -1658398462]

また、Pythonのhash関数はFNVというアルゴリズムに近いものだそうだ。

FNV-1 hash algorithm
hash = FNV_offset_basis
for each octet_of_data to be hashed
    hash = hash  FNV_prime
    hash = hash XOR octet_of_data

python/Objects/stringobject.c
string_hash(PyStringObject *a)
{
    ...
    x = *p << 7;
    while (--len >= 0)
        x = (1000003*x) ^ *p++;

この辺りがそうなのかな。
きちんと理解できるように、がんばらねば。