ApacheのphpからSambaユーザーを追加したかったのにハマったのでメモ
Sambaユーザーの追加はsmbpasswdコマンドで行えるが、 ワンライナーなコマンドがなく、対話式でパスワードを入力する事でしか作成ができない。 またsmbpasswdはrootユーザーでなければ実行できないので Apacheのphpから実行する場合はパーミッションエラーとなる。
[code]
smbpasswd -a hogehoge
New SMB password: Retype new SMB password: Added user hogehoge. [/code]
sudoを導入
まずはApacheユーザーがroot権限でsmbpasswdコマンドを実行できるようにsudoを導入する。 [code] apt-get install sudo [/code] 今回、Apacheはdaemonというユーザーで動かしていたのでdaemonがsudoコマンドでroot権限で操作できるよう設定する [code] visudo 以下の一文を追加 daemon ALL=(ALL) NOPASSWD: ALL [/code] ※今回は完全にローカルなサーバーなのでこのように設定していますがセキュリティ的には非常にまずいので特定のスクリプトのみにsudo権限を与える等、慎重に行って下さい。
上記作業でdaemonユーザーはコマンド前にsudoを付ける事でroot権限で実行する事が可能になりました。
expectの導入
上記の作業でApacheのphpから「sudo smbpasswd -a hogehoge」といったコマンドをexecするだけでroot権限で実行が可能となりました。 しかしsmbpasswdは対話式のコマンドである為、普通に実行すれば 「New SMB password:」と聞かれて止まってしまいます。
そこで対話式をサポートするexpectというプログラムを導入します。 [code] apt-get install expect [/code]
expectはシェルスクリプトから呼び出し可能なので以下のようなシェルスクリプトを作成し、ワンライナーでsambaユーザーが作成できるようにします。
[code] vi smbpasswd.sh [/code] 以下のように作成 [code]
!/bin/bash
usage | ./smbpasswd.sh username passwd
if [ $# -ne 2 ]; then echo "error" exit 1 fi
expect smbpasswd
expect -c " set timeout 10 spawn smbpasswd -a $1 expect \"New SMB password:\" send \"$2\n\" expect \"Retype new SMB password:\" send \"$2\n\" interact " [/code] 実行権限を与える [code] chmod 755 smbpasswd.sh [/code]
これで以下のように実行すればsambaユーザーが作成できるようになりました。 以下の例ではhogehogeユーザーがパスワード123123として作成されます。 [code]
./smbpasswd.sh hogehoge 123123
New SMB password: Retype new SMB password: Added user hogehoge. [/code]
Apacheのphpから実行するとうまくいかない
上記のシェルスクリプトをApacheのphpから実行してみます。
test.php [code] <?php exec("sudo ./smbpasswd.sh hogehoge 123123",$str); foreach($str as $v){ echo $v . "<br />"; } ?> [/code]
ブラウザから接続してみるも、どうもexpectがうまくいっていないようで 「Retype new SMB password:」部分で止まっている事がわかりました。
以下のようにすると解決
シェル上からの実行だとうまくいくのにApacheのphpから実行するとうまくいかない、、、 すごく頭を悩ませましたが、expectの文を以下のように編集するとうまくいくようになりました。
[code] vi smbpasswd.sh [/code] 以下のように作成 [code]
expect smbpasswd
expect -c " set timeout 10 spawn smbpasswd -a $1 expect \"New SMB password:\" send \"$2\n\" expect \"Retype new SMB password:\" send \"$2\n\" interact "
↓以下のように編集
expect smbpasswd
expect -c " set timeout 10 spawn smbpasswd -a $1 expect \"New SMB password:\" send \"$2\n\" expect \"Retype new SMB password:\" send \"$2\n\" expect \"x\" send \"\n\" interact " [/code]
追加したのは expect \"x\" send \"\n\" という文章で、どうやらApacheから実行した場合は上記のように適当なexpect文を入れておかなければ最後の行で止まってしまうようでした。 この原因は未だによくわかってないですが、上記のようにする事で動かす事ができるようになりました。