Sambaで共有しているディレクトリをWebから参照出来るようにするツール「SSLBridge」

と、こういうツールを探していたらSSLBridgeなるものを発見。
[Sambaウォッチ]第4回 社外から社内ファイル・サーバーへアクセス可能に,WebツールSSLBridge | 日経 xTECH(クロステック)

しかし、はまった。このSSLBridge、LinuxACL機能を使うことが考慮されていなかったっぽい。ここでいうACLとはPOSIX ACLといって、Unixで通常使われるファイルやディレクトリのパーミッションをもっと細かく設定できるもの。今回使ったSambaはこの機能もあわせて使ってるため、Windowsからディレクトリごとに参照できるユーザを追加したりすることが出来る。(ACLについては、以下のサイトとか参考になります。)
ITmedia エンタープライズ:特集:Linuxカーネル2.6で実現するACL (1/5)
Samba とACL機能:ミラクル・リナックス
はまった内容は手順の中に書いていきます。まず、

環境
OS CentOS 5.0
Samba 3.0.29c-2
Apache 2.2.3
PHP 5.1.6-23.2
SSLBridge 1.5(日本語版)

※ SSLBridge1.5(日本語版)ダウンロード(http://www.osstech.co.jp/techinfo/sslbridge)

SSLBridgeのインストール

まず、ApachePHPのインストールを行う。(Samabaについてはインストール済み。ちなみにApacheもすでに入っていたけど、インストールは以下のようになるはず。)

# yum install httpd
# yum install php
# yum install php-mbstring

次にSSLBridgeのインストール。基本的にはソースを持ってきてDocumento Rootの下にもって行きApacheが参照きるようにオーナ、グループを変更するのみ。

# mkdir sslbridge
# cd sslbridge
# wget http://www.osstech.co.jp/_media/techinfo/sslbridge-1.5-20090119.el5.tar.gz
# tar xvzf sslbridge-1.5-20090119.el5.tar.gz
# mv sslbridge-1.5-20090119.el5 /var/www/html/sslbridge
# chown -R apache:apache /var/www/html/sslbridge

そして、Apacheを起動して、http://ホスト名/sslbridgeにアクセスしてみる

# /etc/init.d/httpd start

すると、↓こんな画面が表示されるはず。

そして、ここからはブラウザからインストール作業を行っていく。この手順については、以下のURLを参考にした。
[Sambaウォッチ]第4回 社外から社内ファイル・サーバーへアクセス可能に,WebツールSSLBridge | 日経 xTECH(クロステック)
まず、上記の画面で「Start Install」を押し次の画面へ。
次の画面も「Next」を押して次へ進む。

Step1.

ここでは、デフォルトのまま設定した。Windowsドメインコントローラを指定するらしいんだけど、ドメインコントローラってなんじゃろ。

Step2.

ここでは、SSLBridgeをインストールした場所に、config.phpが出来たよといっている。(ちなみにGoogle Chromeでやっていたらこのソースが表示されなかったので、その後Firefoxで作業を進めた。なんでだろう)

Step3.

ここで、おそらく2つのファイルがエラーになる。これはmount.cifsにsetuidが設定されていないためなので、以下のように設定しておく。

# chmod 4755 /sbin/mount.cifs
# chmod 4755 /sbin/umount.cifs

(参考にしたサイトではこの2つのコマンドはそれぞれsmbmntとsmbumountだった。Sambaのバージョンの違いだと思われる。最近のSambaはCIFSというファイル共有プロトコル?を使っているようなので、mount.cifsとumount.cifsを使っているらしい)

setuidを設定できたら上記画面を更新する。すべてグリーンになればOK。

インストール完了

完了したら以下のようにログインページが現れるので、Sambaに登録されているユーザ&パスワードを入力してログインする。

SSLBridgeをACLに対応させる

ここまで、出来たらブラウザの画面から各ディレクトリの参照を行えるはず。でも、ACL機能を使っている場合、ダウロード・アップロード・削除が行えないはず。

ダウンロード

まず、ダウンロード出来るようにしよう。ダウンロードするときや、アップロードするときSSLBridgeは内部でmount.cifsコマンドを使って共有フォルダをマウントする。
まず、smbCommon.phpのmakeMount関数を見てみる。(以下出てくるphpファイルはすべて、インストールした時の/var/www/html/sslbridgeの中にあるはず)

<?//省略・・・
function makeMount($whereTo, $whereFrom, $workgroup, $username, $password){
    // 省略
    // 217行目辺り
    $cmd = "/sbin/mount.cifs $whereFrom $whereTo -o username='$username',password='$password',ip=$ip,domain=$workgroup";

217行目辺りで、いったんログインしたユーザの権限でマウントしている。そして、Apacheapacheユーザで動作していてマウントもapacheユーザが行うことになる。どうやらこのとき、$usernameで指定しされたユーザと一致しないので読み込めないらしい。
そこでマウントするときに「noperm」というオプションをつけてやる。こんな風に。

<?//省略・・・
function makeMount($whereTo, $whereFrom, $workgroup, $username, $password){
    // 省略
    // 217行目辺り
    $cmd = "/sbin/mount.cifs $whereFrom $whereTo -o username='$username',password='$password',ip=$ip,domain=$workgroup,noperm";

nopermとは、

クライアントはパーミッション検査を行わない。これは、ローカル クライアントシステム上の他のユーザによりアクセスするためにこのマウント上でファイルを さらすことが出来る。これは、サーバがCIFS Unix Extensionsをサポートしているが、 クライアントとサーバシステム上のUID/GIDがユーザのマウント操作によってアクセス するために密接になっているのに一致していない時にのみ通常必要である。 サーバソフトウェア(マウント時に提供されるユーザ名に対するACL)によってターゲット マシンで通常のACL検査を行うことへの影響はないことに注意。

http://www.samba.gr.jp/project/translation/3.2/htmldocs/manpages-3/mount.cifs.8.html

うーん。おそらくここで言っているのがmount.cifsでマウントしたときのユーザとアクセスしようとしているユーザ(ここではapache)のUID/GIDが一致していなくてもいいよってことになるんだろう。(と勝手に解釈)
ま、とにかくこれでファイルのダウンロードは行うことが出来るようになった。

アップロード

権限の問題はこれで解決。しかし、アップロードはまた別の問題があった。SSLBridgeはまず、アップロードの前に書き込み権限があるかチェックするため「/smb_test_save.txt」というファイルを作ろうとする。が、現在のバージョンでは、共有されているトップのディレクトリにそのファイルを作ろうとして必ずエラーになってしまう。(今回トップディレクトリはroot以外誰にも書き込み権限を与えていないので。もし誰でも書き込めるなら問題なかったのかも知れないけど、今回の場合それはそれでおかしい。)
その部分が、smbb.phpの以下の部分

<?//省略・・・
function triggerUpload_PHP($username, $password, $workgroup, $myLoc, $myDir){
   // 省略・・・
   // 972行目辺り
   $test = @fopen($source.'/smb_test_save.txt', "a");
   @fclose($test);

   $json = new Services_JSON();
   if($test == false){
   $sendIt = array();
   $sendIt['error'] = 'error';
   $sendIt['msg'] = 'You do not have permission to upload a file to this directory.';
        } else {
                $cmd = 'rm '.$source.'/smb_test_save.txt'; // 981行目辺り ここでは、作成したファイルを削除している。
                $result = `$cmd`;
   // 省略・・・

$sourceには共有されているディレクトリのトップのパスが入ってるが、これを、アップロードしようとしているディレクトリまで指定してやる。

<?//省略・・・
function triggerUpload_PHP($username, $password, $workgroup, $myLoc, $myDir){
   // 省略・・・
   // 972行目辺り
   //$test = @fopen($source.'/smb_test_save.txt', "a");
   $test = @fopen($source.$myDir.'/smb_test_save.txt', "a"); // 追加
   @fclose($test);

   $json = new Services_JSON();
   if($test == false){
   $sendIt = array();
   $sendIt['error'] = 'error';
   $sendIt['msg'] = 'You do not have permission to upload a file to this directory.';
        } else {
                //$cmd = 'rm '.$source.'/smb_test_save.txt'; // 981行目辺り ここでは、作成したファイルを削除している。
                $cmd = 'rm '.$source.$myDir.'/smb_test_save.txt'; // 追加
                $result = `$cmd`;
   // 省略・・・

$myDirって変数にブラウザで選択したディレクトリの相対パスが入っているので$sourceと結合してやる。
と、これだけでなく、このソースの少し上で、文字コードの対応の必要があった。

<?//省略・・・
     $path = $myLoc;
     if($myDir != '') {
             $path .= $myDir;
             // 970行目 あたりに以下の行を追加
             $myDir = ucs2_to_utf8(trim($myDir));
     }

$myDirには日本語が入る可能性があるのでここでUTF8に変換しておく。(これはソースのほかの部分を参照。)
ここまで出来ると、ブラウザからファイルアップロード画面を表示できるようになる。しかし、この画面でファイルを選択してアップロードすると、まだエラーが発生。実際にアップロードをする部分も同じようなチェックが入っているので修正する。
uploadFile.php

<?//省略・・・
    // 省略 126行目辺り・・・
                //$test = fopen($source.'/smb_test_save.txt', "a");
                $test = fopen($uploadDir.'/smb_test_save.txt', "a");
                fclose($test);
                $uploadFile = $uploadDir .'/'. $_FILES['userfile']['name'];
        }
        if($test != false){
                //$cmd = 'rm '.$source.'/smb_test_save.txt';
                $cmd = 'rm '.$uploadDir.'/smb_test_save.txt';
    // 省略・・・

ここでは、$uploadDirの中にアップロードするディレクトリパスが入っているのでこれを指定する。

完成

ここまでで、ファイルのダウンロードとアップロードが出来るようになる。まだ、完全にはテストしていないけど今のところ動いている。ただ、ファイルの削除が時々ダメだったりするので、同じような処理が必要なのかな。うーん。疲れた今日はここまで。

追記

PHPのインストールの部分で以下のモジュールも一緒に必要なので本文に追記した。

# yum install php-mbstring

IEの場合のダウンロードするファイルをUTF-8からCP932に変換している部分で「mb_convert_encoding」を使っているため(getDL.php内。他にもあるのかも)。