CentOS 7のduplicity (paramiko)でホスト鍵検証が通らない

サーバを入れ替えてホスト名に対するホスト鍵が変わったサーバ。事前にknown_hostsを編集して新サーバの鍵を追加してあり、OpenSSHのsshsftpでは正常に接続できる。
また前提としてpython2-paramiko-1.16.1-2.el7 時点ではECDSA鍵は使えないっぽいのでRSA鍵になる。
duplicityでsftp経由でバックアップしようとするとエラーが出る。

BackendException: ssh connection to target.server failed: ('target.server', , )

検索するとホスト鍵の検証を無効化する対処法が出てくるがセキュリティを完全に損なうので言うまでもなく実環境で真似してはいけない。


挙動を見たところ*1、OpenSSHの実装ではドキュメントの通りに一致する鍵が見つかるまでknown_hostsの各行の検証を続けるが、Paramikoでは最初に一致するホスト名しか検証していない雰囲気だった。
今回の場合、旧サーバを落とすまでの一時的な状態として複数の鍵が同じホスト名に対応する状態になっていた。

[target.server],[old.server],[10.0.0.1] ssh_rsa ...
[target.server],[new.server],[10.0.0.2] ssh_rsa ...

target.serverを名前解決すると10.0.0.2(new.server)になりそちらに接続するのだが、old.server側の鍵と比較して不一致のためエラーになっていたようだ。
new.serverという名前で接続するようにしたところ、エラーは出なくなり動作した。

*1:詳細は調べていない

CentOS 7のduplicity-0.7.11-1.el7 の--encrypt-keyが動作しない

GPGがエラーを起こす。

GPGError: GPG Failed, see log below:
===== Begin GnuPG log =====
gpg: invalid option "--pinentry-mode=loopback"
===== End GnuPG log =====

とりあえずオプション指定を外して対応した。
/usr/lib64/python2.7/site-packages/duplicity/gpg.pyの以下をコメントアウト

        elif profile.gpg_major == 2:
            # This forces gpg2 to ignore the agent.
            # Necessary to enforce truly non-interactive operation.
            if platform.platform().startswith('Linux'):
                gnupg.options.extra_args.append('--pinentry-mode=loopback')

バグレポートされていたので次の更新で直ると期待。

Adventure Land

Adventure LandというMORPG風のゲームがある。数か月前くらいにできて、まだプロトタイプだそうだが、cursors.io, agar.io, diep.ioのようにHTML5ベースのゲームだ。

HTML5ということはJavaScriptで動いているわけで、クライアントサイドでごにょごにょやる層も出てくるわけだが、他と違うのはその仕組みがもともとゲームに備わっていることだ。

試しにスクリプト機能をいろいろといじってみた。ただしプロトタイプ版のため、現時点とは仕様が変わる可能性がある。

続きを読む

diff -Wの関数名長制限をなくす

diffには差分文脈の関数を表示する機能があり、-W (--show-function-line)で関数とするパターンをカスタマイズできる。ただ関数名の長さに40字の制限があって長いと途中で途切れてしまう。
unix diff --show-function-line truncates outputfunction is truncated to 40 charactersによると文字数はハードコードされているらしい。入れているMSYSですんなりコンパイルできるか不明なのでバイナリをいじってみた。
ソースに当たるまでもなく、上記情報によると、print_context_functionでputc(' ', out);した後のfor (j = i; j < i + 40 && function[j] != '\n'; j++)が問題の箇所。関数冒頭でputc(' '...しているところを探す。

PUSH EBP
PUSH EDI
MOV EBP,EDX
PUSH ESI
PUSH EBX
MOV EDI,EAX
XOR ESI,ESI
SUB ESP,1C
MOV DWORD PTR SS:[LOCAL.9],EAX
MOV DWORD PTR SS:[LOCAL.10],20
CALL <JMP.&msys-2_0.putc_unlocked>       ; Jump to msys-2_0._putc_unlocked
MOV EDX,EBP
 MOVZX ECX,BYTE PTR DS:[EDX]
 MOV EAX,EDX
 LEA EBX,[ECX-9]
 CMP BL,4
 JBE SHORT _00402B00
 CMP CL,20
 JE SHORT _00402B00
 LEA EDX,[ESI+27]              ; 8D56 27
 MOV ECX,ESI                   ; 89F1
  ADD ECX,1                    ; 83C1 01
  CMP ECX,EDX                  ; 39D1
  JG SHORT _00402AB4           ; 7F 07
  CMP BYTE PTR SS:[ECX+EBP],0A ; 807C0D 00 0A
  JNE SHORT _00402AA6          ; 75 F2
 CMP ESI,ECX

あった。条件分岐JG SHORT _00402AB4NOPにする(1EABの7F 07を90 90とする)と、長さ制限が消えた。

WindowsのStrawberry Perlで最新のSQLiteを使う

SQLiteで新しいバージョンを使いたくなった。CPANで入れてみても9か月前のバージョンしか入らない。

cpanm -n DBD::SQLite
perl -MDBD::SQLite -e "print $DBD::SQLite::sqlite_version"
# 3.10.2

インターフェイスをどうこうする必要はないのでSQLiteのソースだけ入れ替えればいいはずと思ってやってみた。
先ほどインストールしたDBD::SQLiteのソースをローカルから拾ってきて展開。
またSQLiteのダウンロードページでamalgamationソースを持ってきて、sqlite3.c, sqlite3.h, sqlite3ext.hを置き換える。
あとはcpanmのローカルディレクトリインストール機能を使う。

bash
tar xf /C/path/to/strawberry/data/.cpanm/work/*/DBD-SQLite-1.50.tar.gz
cd DBD-SQLite-1.50
wget https://www.sqlite.org/2016/sqlite-amalgamation-3150000.zip
unzip sqlite-amalgamation-3150000.zip
mv sqlite-amalgamation-3150000/sqlite3* .
exit
cpanm -n .

バージョンアップできた。

perl -MDBD::SQLite -e "print $DBD::SQLite::sqlite_version"
# 3.15.0