FreeBSD portsでsuEXEC Apache自由自在

# suEXECに課される重い制約

最近、あるソフトウェアセキュリティーコンサルタントさんに「[suEXEC](http://httpd.apache.org/docs/2.4/ja/suexec.html)は必須だと思います」とアドバイスされました。suEXECというのは[Apache](http://httpd.apache.org/)でCGIの実効ユーザーを都合のいいユーザーに代えるための仕組みなわけですが、苦手な方多いんじゃないでしょうか？

「UIDが1000未満のユーザーはダメ(UID_MIN制約)」とか「suEXECで動かせるCGIは`/usr/local/www/`の中に置いたものしか認めない(DOC_ROOT制約)」などの重い制約が課されるうえに、`httpd.conf`等をいじって変えられるものでもありませんからね。

> UID_MINとかDOC_ROOTとか、自分で決めたい

と思っても、意外と大変だったりします。

## でもFreeBSD愛好家のアナタはツイている！

suEXECの設定はコンパイル時に固定されるので、バイナリパッケージでヌルく生きてる人はパッケージ制作者の決めたパラメーターに従うしかありません。でもFreeBSDユーザーなら問題なし！portsという強い味方がいるからです。

portsの強みは何といっても、その場でコンパイルしてくれるパッケージ管理ツールであること。それでいて、tarball持ってきて自力でconfigure make make-installするより遥かに簡単。素晴らしすぎます。

ただし、suEXECの設定に関してはちょっと知ってないと難しい。ということでこのTipsの出番です。

# UID_MINとかDOC_ROOTとか自分で決めてインストール

では、次の要件でsuEXEC版インストールすることにしてみましょう。

* UIDは500以上なら許可する(AP_UID_MIN=500)

* GIDも500以上なら許可する(AP_GID_MIN=500)

* CGIを動かしてよいディレクトリを`/home`以下にする(AP_DOC_ROOT=/home)

* 許可するPATHを`/usr/local/mycommand:/usr/local/bin:/usr/bin:/bin`にする(AP_SAFE_PATH=/usr/local/mycommand:/usr/local/bin:/usr/bin:/bin)

* suEXECログ出力先を`/var/log/httpd/suexec.log`にする(AP_LOG_EXEC=/var/log/httpd/suexec.log)

## a. make installの場合

`portupgrade`とかを使っておらず、`make install`で行う場合は次のように書けばOKです。

```sh:make-installで行く!
cd /usr/ports/www/apache24
make WITH_SUEXEC=yes SUEXEC_UIDMIN=500 SUEXEC_GIDMIN=500 SUEXEC_DOCROOT=/home SUEXEC_SAFEPATH=/usr/local/mycommand:/usr/local/bin:/usr/bin:/bin SUEXEC_LOGFILE=/var/log/httpd/suexec.log install
```

## b. portupgradeを使っている場合

`portupgrade`を使っている場合、`-M`オプションを使えば同等のことができます。

```sh:portupgradeで行く!
portupgrade -M 'WITH_SUEXEC=yes SUEXEC_UIDMIN=500 SUEXEC_GIDMIN=500 SUEXEC_DOCROOT=/home SUEXEC_SAFEPATH=/usr/local/mycommand:/usr/local/bin:/usr/bin:/bin SUEXEC_LOGFILE=/var/log/httpd/suexec.log' -N www/apache24
```

## c. portupgradeを使っている場合 その2(毎回書くのは面倒だ!)

アップグレードの度に`portupgrade`コマンドにこの長い記述を書くのは面倒ですし、ホストに入っているパッケージ全体を一気にアップグレードしようとすると、せっかくの設定がその時に失われてしまいます。

ではどうすればいいかというと、`/usr/local/etc/pkgtools.conf`のMAKE_ARGS変数内に書いておけば大丈夫です。

```rb:/usr/local/etc/pkgtools.confの中
  MAKE_ARGS = {
          #:
    'www/apache*' => [
      'WITH_SUEXEC=yes',
      'SUEXEC_UIDMIN=500',
      'SUEXEC_GIDMIN=500',
      'SUEXEC_DOCROOT=/home',
      'SUEXEC_SAFEPATH=/usr/local/mycommand:/usr/local/bin:/usr/bin:/bin',
      'SUEXEC_LOGFILE=/var/log/httpd/suexec.log',
    ],
          #:
  }
```

こうすればアップグレードの際、`portupgrade`は必ず適用してくれますので、あとは普通に`portupgrade`するだけです。

## ちゃんと反映されているかな？

確認するには`suexec`コマンドを`-V`オプション付で実行すればわかります。

```sh:確認する
# suexec -V
 -D AP_DOC_ROOT="/home"
 -D AP_GID_MIN=500
 -D AP_HTTPD_USER="www"
 -D AP_LOG_EXEC="/var/log/httpd/suexec.log"
 -D AP_SAFE_PATH="/usr/local/mycommand:/usr/local/bin:/usr/bin:/bin"
 -D AP_UID_MIN=500
 -D AP_USERDIR_SUFFIX="public_html"
```

# 他にどんなパラメーターが？

上記のように、suEXECには他にもいくつか設定できるパラメーターがあります。それらの一覧は次のようにすると調べることができます。

```sh:確認する
$ grep -R SUEXEC_DOCROOT /usr/ports/www
/usr/ports/www/apache22/Makefile.doc:##            SUEXEC_DOCROOT:     suEXEC root directory
```

`/usr/ports/www/apache22/Makefile.doc`の中にそれらしきヘルプが記述されていることがわかりますので、開いてみると……

```text:/usr/ports/www/apache22/Makefile.doc
                :
##      WITH_SUEXEC:              Enable suEXEC support
##            SUEXEC_DOCROOT:     suEXEC root directory
##            SUEXEC_USERDIR:     User subdirectory (default public_html)
##            SUEXEC_SAFEPATH:    Set the safepath
##            SUEXEC_LOGFILE:     Set log file for suEXEC (default: /var/log/httpd-suexec.log)
##            SUEXEC_UIDMIN:      Minimal allowed UID (default 1000)
##            SUEXEC_GIDMIN:      Minimal allowed GID (default 1000)
##            SUEXEC_CALLER:      User allowed to call suEXEC (default
##                                ${WWWOWN} (www))
##            SUEXEC_UMASK:       Defines umask for suEXEC'd process(default:
##                                unset)
                :
```

いやぁ、portsって……、本当にいいものですね。