2011/02/09
ファイル暗号化/復号化 wrapper スクリプト
openssl (1) を実行してファイルを暗号化/復号化する処理を
簡易実行するための簡単な
シェルスクリプトによる wrapper
を作成した。
暗号化/復号化は openssl (1) の enc コマンドに
暗号化アルゴリズムに aes-128-cbc を指定して実施している。
指定されたファイルの先頭 8 バイトを参照して
Salted__ の場合は暗号化されていると仮定し復号化、
それ以外は暗号化する処理をデフォルトで実行するが、
実行時オプション -d、-e を指定する事で
強制的に暗号化/復号化を指定する事も可能だ。
-p オプションでパスワードを指定してバッチ処理も実行できるが、
コマンド実行履歴等にパスワードが残るのでお勧めできない。
暗号化/復号化が成功した場合は元のファイルを置き換える。
例によって必要に迫られれて適当に作成したスクリプトなので このスクリプトを利用した事で生じるあらゆる損害に対して責は負えない。
2011/01/17
シェルスクリプトで疑似乱数を取得する
gnu bash には ${RANDOM} というシェル変数が用意されていて、 アクセスするたびに疑似乱数(風)の値が取得できる様だ。 しかし posix 準拠の機能ではなく bash 独自の機能なので拡張性がない。 そこで汎用的な疑似乱数取得の方法として awk (1) を利用した方法を使ってみる。
awk (1) には rand() という関数が組込まれているので
乱数生成ができる。
その際に利用される種(seed)は
srand() という関数で初期化できるので、
これらを利用する事でそこそこの精度の疑似乱数は取得できる。
たとえば 0 〜 m までの疑似乱数は
取得した値から m の剰余を取ることで取得できる。
ただし awk (1) の rand() は仕様として
0 〜 1 までの桁数不定の少数を返すので、
乱数として利用する場合には整数に変換する必要がでてくる。
整数にするために 10n を乗すればよいのだが、
小数点以下の桁数が不定のために小さすぎる n を乗すると
全ての桁が整数化されずに乱数の精度が低くなってしまい、
逆に大きすぎる n を乗すると値が xxx000 の様になってしまい
剰余を取得しても無意味になってしまう。
そこで awk (1) により疑似乱数を取得する場合は rand() で取得した値の前 2 文字 ("0.") を文字列として除外した値から m の剰余とする事で 0 〜 m までの乱数が取得できる。
1#!/bin/sh 2 3awk 'BEGIN{ 4 srand(); 5 print substr(rand(), 3) % '${1:-1}' 6}'
データの型が存在しない(文字列であり数字である) awk (1) ならではの裏技とも言えるだろう。
2011/01/06
htaccess で特定のファイルのみパスワードを要求しない
Web コンテンツを保護するために
.htaccess ファイルを用いて Basic 認証などを実施する場合は多い。
通常 .htaccess はディレクトリ単位で有効になってしまうのだが、
あるディレクトリのアクセスを Basic 認証でアクセス制御したいが
特定のファイルについては認証を要求しない設定を行いたい場合は
Files ディレクティブと
Satisfy ディレクティブで実現できる。
AuthType Basic AuthUserFile 認証用ファイル AuthName "Enter password" Require valid-user <Files "認証要求しないファイル"> Satisfy Any Allow from all </Files>
Satisfy ディレクティブは Allow ディレクティブと
Require ディレクティブがどちらも使われている場合の
アクセスポリシーを制御する。
Any が指定された場合は Allow か Require
のどちらかの条件を満たせばアクセスが許可されるので、
Files ディレクティブで指定したファイルに対しては
Allow 指定が有効になり認証なしでアクセスが許可される。
逆にある特定のファイルだけの Basic 認証によるアクセス制御は Files ディレクティブのみで可能である。
AuthType Basic AuthUserFile 認証用ファイル AuthName "Enter password" <Files "認証要求するファイル"> Require valid-user </Files>
どちらの場合も Files ディレクティブは以下の様に
~ を使う事でファイル名を正規表現で記述できる。
<Files ~ "\.(gif|jpe?g|png)$"> : </Files>apache では PCRE - Perl Compatible Regular Expressions を 利用しているので複雑な正規表現の記述ができる様だ。
2010/12/15
DHCP
先日購入した MacBook Air を自宅のネットワークに接続しようとした所、 何故か DHCP での IP アドレス取得に失敗してしまう現象が発生した。 Windows Xp や FreeBSD がインストールされた PC では正しく取得できるが、 MacOS X ではどうやっても IP アドレスが取得できない。 無線 LAN 接続のアクセスポイント(TimeCapsule)の設定を変更したり、 アクセス制御を解除してみても全然 IP アドレスが取得できず DHCP サーバの設定を何度も確認しても症状はいっこうに改善されない。
そこでネットワーク障害はパケットキャプチャが基本だと思い立ち、
IP アドレスが取得できない MacBook Air で tcpdump (1) を実行すると、
クライアントからの DHCP DISCOVER に対して
サーバは DHCP OFFER を応答しているのだが、
パケットの Source IP Address が
127.0.0.1 となっている事を発見した。
なぜ DHCP OFFER パケットの Source IP Address が
127.0.0.1 だったのか、
結論から言うと /usr/local/etc/dhcp.conf ファイル中の
option domain-name に設定した FQDN が
/etc/hosts に 127.0.0.1 で登録されていたため、
DHCP サーバがパケットを送信する際に
domain-name を逆引きした結果として 127.0.0.1 を
Source IP Address に設定してしまった様だ。
/etc/hosts から該当する FQDN のエントリーを削除して、
DHCP サーバを再起動した所 IP アドレスが取得できた。
FQDN を 127.0.0.1 で /etc/hosts に登録する事は
Linux の一部のディストリビューションなどでは普通に行われている様だが、
メイルが送信できない、DHCP が機能しないなどの障害発生の原因になるので
是非とも辞めて欲しい。
それにしてもこの MacOS X の DHCP クライアントは Source IP Address が 127.0.0.1 の DHCP OFFER を無視しちゃうのね。
2010/09/01
mh で画像を添付したマルチメディアメイルを送信する
最近の mh(1) は標準で画像等を添付した
MIMEマルチパート形式のメイルが送信できる。
mh(1) では mhn(1) コマンドを利用して
マルチメディアメッセージを操作するので、
マルチメディアメイルを送信するためには、
本文中にマルチメディアメイルである事を通知する行
(ここでは mhn 通知行 と呼ぶ)を記述した上で
mhn(1) コマンドを実行し、
添付ファイルを base64 エンコードしてマルチパート形式に変換すればよい。
mhn 通知行は本文の 1 カラム目から以下の形式で記述する。
#MIME タイプ; name="ファイル名" [ファイルの説明] ファイル名MIME タイプは jpeg 形式の画像であれば image/jpeg、 gif 形式の画像であれば image/gif などと指定する。
comp(1) や repl(1) を利用してメイル本文を編集する場合、 mhn 通知行を含む本文を作成した後で What now? プロンプトから edit mhn などとして mhn(1) コマンドを実行してから 送信すればマルチメディアメイルが送信できる。
最近の日本語パッチが適用された mh(1) は、
mhn(1) コマンドがメイル本文の文字コードを参照して
適切な charset を Content-Type: ヘッダに付加するので、
メイル送信前に必ず mhn(1) を実行しても良いだろう。
その場合は $HOME/.mh_profile に以下の行を記述しておくと
送信時に自動で mhn が実行されて便利。
automhnproc: mhn
ちなみに 1 カラム目が # な行は mhn 通知行 とみなされるので、 本文中で # が行頭になるメイルを作成する場合は ## とする必要がある。
この様に mh(1) で MIME マルチパート形式のメイルを送信するのは
最近の高機能な MUA に比較すると若干面倒なので、
多少なりとも簡単に送信するために
mhmime スクリプトを作成した。
このスクリプトを利用してマルチメディアメイルを作成するためには
メイル本文の 1 カラム目から以下の行を記述する。
#MIME ファイル名 ファイルの説明このスクリプトは記述されたファイル名から MIME タイプを推測して mhn 指示行 を生成し、 #MIME 以外で 1 カラム目が # の場合は ## に置換した上でmhn(1) コマンドを実行する。
メイル本文を作成した後で What now? プロンプトから
edit mhmime などとしてこのスクリプトを実行した上で
送信すればマルチメディアメイルが送信できる。
$HOME/.mh_profile の automhnproc: に指定しておけば、
送信時に自動で実行されるので多少は便利になるかもしれない。
しかし、今時 mh を素で利用している人は果たしてどれほどいるのだろうか?
2010/08/17
SwiftPoint
Swiftpointが発売した
超小型のモバイルマウスが到着したので、
早速開封して MacBook に接続してみる。
自然に曲げた人差し指が丁度触れる位置に通常の左クリックボタン、
その手前に右クリックボタンがあるので、
特に右クリックボタンは最初のうちは意識しないと押し辛い気がする。
左クリックボタンの外側に設置されたスクロールホイールは、
指先で回転させても、本体を少し傾けて本体を上下させる
サイドスクロールでもなかなか使い易いので良いアイデアではないだろうか。
ペンを握る時の様な自然な持ち方で利用するので 細かな操作も可能という触れ込みなのだが、 一般のマウスとは若干異なる操作感なので慣れるまでには多少時間が必要そうだ。
2010/06/02
みずほ銀行
みずほ銀行のオンラインバンキングで振り込みをする場合に必要な
第2暗証番号から指定された4桁の番号を見つけ出すためのスクリプト。
awk (1) だけで書いたのでどんな環境でも動作する筈。
引数で番号を指定するか端末から入力すると、
対応する数字が表示されます。
こんなピンポイントでしか役立たないスクリプトを
利用する人がいるかどうか不明なのだが、
折角なので公開だけはしてみる。
あまり問題はないと思うのだが、
第2暗証番号を平文で保存するので
ご利用はくれぐれも自己責任で。
1#!/bin/sh 2# 3# $Id: mizuho,v 1.1 2010/01/06 07:15:54 mitz Exp $ 4# 5awk ' 6 BEGIN{ 7 base="第2暗証番号" 8 if("'$1'") 9 num = "'$1'" 10 11 if(!match(num, /^[0-9]{4}$/)){ 12 printf "Input number: " 13 getline num < "/dev/tty" 14 } 15 split(num, nums, ""); 16 for(i=1; i<=4; i++) 17 print substr(base, nums[i], 1) 18 print 19 } 20' < /dev/null
2010/05/13
ファイルの逆順出力
ファイルを逆順に出力したい事がたまにある。
FreeBSD の tail (1) には -r オプションがあって
ファイルを行単位で逆順に出力できるが、
これは POSIX.2 にはない拡張仕様なので汎用的ではない。
Linux では tac (1) (多分逆順に出力する cat だから tac)
というコマンドがインストールされている事もあるが、
これも POSIX.2 には存在せず
Linux でも標準ではインストールされていない場合がある。
ファイルの逆順を出力するなら ex (1) を利用して、
$ ex -s ファイル <<-FOF > g/^/mo0 > %p >EOFとするのが汎用的で良いと思う。
簡単に解説すると「行の先頭 (^) を 0 行目に移動(mo0)して、
全行を表示する(%p)」というコマンドを実行している。
行の先頭は全ての行に存在するので全ての行が処理対象になる。
各行を順番に 0 行目(1 行目の前の行なので先頭行)に移動するので、
結果としてファイルの内容が逆順に表示される。
2010/03/27
mnews
随分と長い間 mnews というソフトウェアを愛用している。
名前の通り、元々は Net News Reader として開発されたのだが、
MUA としての機能も備わっていて割と使いやすいので、
随分と以前より(1990年代の中盤頃から)愛用している。
最近はあまりメンテナンスもされていない様なのだが、
たまにネットで公開されている機能拡張用のパッチを適用したり、
自分でも簡単な改造をしながら長年愛用してきた。
今ではオリジナルにはない mime マルチパートメイルの送受信機能なども加わり、
今時の MUA としては最低限の機能は備える程度には機能が充実している。
最近は UNICODE で送られてくるメイルも増えて来たので、
UNICODE メイルを表示するためのパッチを適用し、
ついでに html メイルを lynx などのテキストベイスのブラウザで
表示する機能を追加した。
これで現状必要と思われる機能はほぼ網羅したと思われ、
届くメイルのほぼ全てを閲覧する事が出来るようになった(多分)。
まだまだ mnews を愛用できそうで嬉しい限りだ。
2010/03/18
GtkTwitter
FreeBSD 上で動作する twitter クライアントの GtkTwitter は 起動するたびにアカウント情報を入力する必要があり面倒だったので、 アカウント情報をファイルに保存して再利用するためのパッチを作成してみた。
自分が使う事だけを考えて適当に作ったので、
パスワードの暗号化すらしておらず、
シンタックスもセマンティックスもチェックしていない。
ただ単にアカウント情報を保存して再利用するだけの機能のみ。
ホームディレクトリに .gtktwitter があれば
保存されたアカウント情報を利用する。
$HOME/.gtktwitter がなければ
従来通りアカウント情報の入力ダイアログを表示し、
入力されたアカウント情報は $HOME/.gtktwitter に保存される。
$HOME/.gtktwitter は以下の書式なので、
アカウント情報は vi (1) を利用して入力する事も可能である。
勿論 cat (1) や echo (1) でも可。
ファイル中のスペースは文字そのものとして解釈されるので注意する事。
mail=ID pass=パスワード
diff -rc gtktwitter-0.0.4.orig/gtktwitter.c gtktwitter-0.0.4/gtktwitter.c *** gtktwitter-0.0.4.orig/gtktwitter.c 2007-05-10 00:50:02.000000000 +0900 --- gtktwitter-0.0.4/gtktwitter.c 2010-03-18 20:15:01.000000000 +0900 *************** *** 724,729 **** --- 724,783 ---- return FALSE; } + #define CONFIG_FILE ".gtktwitter" + + static gboolean getconfig(GtkWidget *window) + { + + gchar *config; + char buff[1024], + *m = NULL, + *p = NULL; + FILE *fp; + gboolean ret = FALSE; + + if((config = g_strdup_printf("%s/%s", getenv("HOME"), CONFIG_FILE))){ + if((fp = fopen(config, "r"))){ + while(fgets(buff, sizeof(buff), fp)) + if(!strncmp(buff, "mail=", 5)) + m = strdup(buff+5); + else if(!strncmp(buff, "pass=", 5)) + p = strdup(buff+5); + fclose(fp); + } + g_free(config); + + if(m && p){ + g_object_set_data(G_OBJECT(window), "mail", m); + g_object_set_data(G_OBJECT(window), "pass", p); + ret = TRUE; + } + } + + return (ret); + + } + + static void putconfig(const char *m, const char *p) + { + + gchar *config; + FILE *fp; + + if((config = g_strdup_printf("%s/%s", getenv("HOME"), CONFIG_FILE))){ + if((fp = fopen(config, "w"))){ + fprintf(fp, "mail=%s\n", m); + fprintf(fp, "pass=%s\n", p); + fclose(fp); + } + g_free(config); + + } + + return; + + } + /** * login dialog func */ *************** *** 735,740 **** --- 789,798 ---- GtkWidget* pass = NULL; gboolean ret = FALSE; + if(getconfig(window)){ + ret = TRUE; + } + else{ /* login dialog */ dialog = gtk_dialog_new(); gtk_dialog_add_buttons(GTK_DIALOG(dialog), *************** *** 804,812 **** --- 862,873 ---- char* pass_text = (char*)gtk_entry_get_text(GTK_ENTRY(pass)); g_object_set_data(G_OBJECT(window), "mail", strdup(mail_text)); g_object_set_data(G_OBJECT(window), "pass", strdup(pass_text)); + putconfig(mail_text, pass_text); ret = TRUE; } + } + if(dialog) gtk_widget_destroy(dialog); return ret; }