自動的にパスワードがハッシュ化される。

CouchDBのFutonへのアクセスは、http://localhost:5984/_utils/でできるわけだが、外に公開するサーバだと勝手に更新されるのはいかがなものかなぁと思い、/etc/couchdb/local.iniを調べてみたら 1 、認証かけられそうな設定があった。 2

; To create an admin account uncomment the '[admins]' section below and add a
; line in the format 'username = password'. When you next start CouchDB, it
; will change the password to a hash (so that your passwords don't linger
; around in plain-text files). You can add more admin accounts with more
; 'username = password' lines. Don't forget to restart CouchDB after
; changing this.
[admins]
;admin = mysecretpassword

む、

When you next start CouchDB, it will change the password to a hash (so that your passwords don’t linger around in plain-text files).

とな。実際にやってみる。

# git diff
diff --git a/local.ini b/local.ini
index 0a11877..eec1be3 100755
--- a/local.ini
+++ b/local.ini
@@ -9,7 +9,7 @@

 [httpd]
 ;port = 5984
-;bind_address = 127.0.0.1
+bind_address = 0.0.0.0

 [log]
 ;level = debug
@@ -28,4 +28,4 @@
 ; 'username = password' lines. Don't forget to restart CouchDB after
 ; changing this.
 [admins]
-;admin = mysecretpassword
+admin = hogehoge

とパスワードとしてCouchDBを再起動してみる。

$ sudo /opt/couchdb/etc/init.d/couchdb restart

再度、diffってみる。

diff --git a/local.ini b/local.ini
index 0a11877..eec1be3 100755
--- a/local.ini
+++ b/local.ini
@@ -9,7 +9,7 @@

 [httpd]
 ;port = 5984
-;bind_address = 127.0.0.1
+bind_address = 0.0.0.0

 [log]
 ;level = debug
@@ -28,4 +28,4 @@
 ; 'username = password' lines. Don't forget to restart CouchDB after
 ; changing this.
 [admins]
-;admin = mysecretpassword
+admin = -hashed-9b0a0bcd7318df5d0ef874a504dc2765f5165003,7478a0d6aad0771ad7211c

と、まぁ勝手に書き換えてくれる 3 。これは便利だ。

Erlangで書き換えている部分

実際のソースコード中ではこんな処理になってる。

src/couchdb/couch_server.erl

82 is_admin(User, ClearPwd) ->
83     case couch_config:get("admins", User) of
84     "-hashed-" ++ HashedPwdAndSalt ->
85         [HashedPwd, Salt] = string:tokens(HashedPwdAndSalt, ","),
86         couch_util:to_hex(crypto:sha(ClearPwd ++ Salt)) == HashedPwd;
87     _Else ->
88         false
89     end.

平文だったら、”-hashed-“という接頭辞をつけて、ハッシュ化したパスワードで書き換えるわけですな。ハッシュ化されたパスワードの途中に”,”があるが、最初これもランダムで書き換えられた文字列かと思っていたが、そうではないみたいだ。上記の85行目に

string:tokens(HashedPwdAndSalt, ","),

とあるので、stringモジュールのtokens(String, SeparatorList) -> Tokensで、”,”で文字列をHashedPwdとSaltに分割していたわけだ。パスワードのハッシュ化とSalt自体の生成は以下で行われている。

100 hash_admin_passwords(Persist) ->
101     lists:foreach(
102         fun({_User, "-hashed-" ++ _}) ->
103             ok; % already hashed
104         ({User, ClearPassword}) ->
105             Salt = ?b2l(couch_uuids:random()),
106             Hashed = couch_util:to_hex(crypto:sha(ClearPassword ++ Salt)        ),
107             couch_config:set("admins",
108                 User, "-hashed-" ++ Hashed ++ "," ++ Salt, Persist)
109         end, couch_config:get("admins")).

couch_uuids:random()は、src/couchdb/couch_uuids.erlの

32 random() ->
33     list_to_binary(couch_util:to_hex(crypto:rand_bytes(16))).

と。local.iniで上書きされたハッシュ化されたパスワードの中のカンマが気になってたのですっきりした。

それにしてもすんげぇ脱線だ。(わら

Footnotes

1

パスを変更しているので実際のパスは/opt/couchdb/etc/couchdb/local.iniである。

2

ああ、そういや最初のCouchDBの勉強会の時に、Erlangから追っかけるCouchDBで見た気もする。

3

gitのハッシュもハッシュ化されたパスワードも実際の元とはちゃうよ。