拡張子によってApacheモジュールの処理を適応するか判断するpatch(mod_ruid2版)

ブログはかなり久々。

会社での実装でいいものが生まれたりするのが、なかなかそれを社外に公開するわけにはいかず、あまり技術的な創作物をブログに書くことができなかった。今は、会社2割大学8割のような比率で研究しているので、最近作ったpatchでも紹介する。

実装対象は、DSO版PHPなどでもsuEXECのようなアクセス制御が行えるmod_ruid2に対してpatchを書いてみた。

mod_ruid2は実装上、モジュールとしてApacheに読み込んだ場合、すべての動的コンテンツ実行時にサーバプロセスをsetuid、setgidしてしまう。しかし、ある特定の環境下では、任意の拡張子(.phpや.py)においてのみモジュールの処理を実行させたい場合がある。Filesディレクティブ等を用いて、ファイルを指定するやり方もあるが、mod_ruid2等ではそういう設定記述は禁止されている。

そこで、mod_ruid2に2つの機能を実装した。

  • RExAll [On/Off]

mod_ruid2はモジュールをロードしてしまうと、すべてのサーバプロセスでset[u,g]id機能が動作してしまう。そこで、そもそも機能を動作させるかどうかをOnとOffで切り替えられるようにした。また、DefaultはOffにしているので、モジュールをロードしただけでは、mod_ruid2の機能が勝手に動作してしまわないようにした。

  • RExtensions [.php .pl .py ……..]

RExALLがOffの場合、ある任意の拡張子のみmod_ruid2を動作させるようにできるようにした。例えば、下記のように

RExtensions .php .pl

と設定すると、.phpと.plの実行時のみ該当のサーバプロセスをset[u,g]idさせて、その他のファイルは動作しない。これによって、.cgiは別のアクセス制御モジュールを使い、.plはmod_ruid2を使うなどの設定が可能となる。

以上が今回のpatchである。ソースは以下。

--- mod_ruid2.c.orig    2011-02-24 23:25:28.000000000 +0900
+++ mod_ruid2.c 2011-10-12 17:45:59.000000000 +0900
@@ -64,6 +64,10 @@
 #define UNSET                  -1
 #define SET                    1

+#define RU_MAXEXTENSIONS        16
+#define ON                      1
+#define OFF                     0
+

 typedef struct
 {
@@ -78,6 +82,7 @@

 typedef struct
 {
+    int all_ext_enable;
        uid_t default_uid;
        gid_t default_gid;
        uid_t min_uid;
@@ -85,6 +90,7 @@
        int8_t stat_used;
        const char *chroot_dir;
        const char *document_root;
+    apr_array_header_t *extensions;
 } ruid_config_t;

@@ -150,6 +156,8 @@
        conf->stat_used=UNSET;
        conf->chroot_dir=NULL;
        conf->document_root=NULL;
+    conf->extensions=apr_array_make(p, RU_MAXEXTENSIONS, sizeof(char *));
+    conf->all_ext_enable = OFF;

        return conf;
 }
@@ -260,6 +268,32 @@

        return NULL;
 }
+
+static const char * set_extensions(cmd_parms *cmd, void *mconfig, const char *arg)
+{
+    ruid_config_t *conf = ap_get_module_config (cmd->server->module_config, &ruid2_module);
+    const char *err = ap_check_cmd_context (cmd, NOT_IN_FILES | NOT_IN_LIMIT);
+
+    if (err != NULL)
+        return err;
+
+    *(const char **)apr_array_push(conf->extensions) = arg;
+
+    return NULL;
+}
+
+static const char * set_all_ext(cmd_parms *cmd, void *mconfig, int flag)
+{
+    ruid_config_t *conf = ap_get_module_config (cmd->server->module_config, &ruid2_module);
+    const char *err = ap_check_cmd_context (cmd, NOT_IN_FILES | NOT_IN_LIMIT);
+
+    if (err != NULL)
+        return err;
+
+    conf->all_ext_enable = flag;
+
+    return NULL;
+}

 /* configure options in httpd.conf */
@@ -271,6 +305,8 @@
        AP_INIT_TAKE2 ("RDefaultUidGid", set_defuidgid, NULL, RSRC_CONF, "If uid or gid is < than RMinUidGid set[ug]id to this uid gid"),
        AP_INIT_TAKE2 ("RUidGid", set_uidgid, NULL, RSRC_CONF | ACCESS_CONF, "Minimal uid or gid file/dir, else set[ug]id to default (User,Group)"),
        AP_INIT_TAKE2 ("RDocumentChRoot", set_documentchroot, NULL, RSRC_CONF, "Set chroot directory and the document root inside"),
+    AP_INIT_ITERATE("RExtensions", set_extensions, NULL, ACCESS_CONF | RSRC_CONF, "Set Enable Extensions."),
+    AP_INIT_FLAG("RExAll", set_all_ext, NULL, ACCESS_CONF | RSRC_CONF, "Set Enable All Extensions On / Off. (default Off)"),
        {NULL}
 };

@@ -445,6 +481,25 @@
        cap_t cap;
        cap_value_t capval[4];

+    const char *extension;
+
+    int enable      = 0;
+    int name_len    = 0;
+
+    if (conf->all_ext_enable) {
+        enable = ON;
+    } else {
+        for (i = 0; i < conf->extensions->nelts; i++) {
+            extension = ((char **)conf->extensions->elts)[i];
+            name_len = strlen(r->filename) - strlen(extension);
+            if (name_len >= 0 && strcmp(&r->filename[name_len], extension) == 0)
+                enable = ON;
+        }
+    }
+
+    if (!enable)
+        return DECLINED;
+
        cap=cap_get_proc();
        capval[0]=CAP_SETUID;
        capval[1]=CAP_SETGID;

「拡張子によってApacheモジュールの処理を適応するか判断するpatch(mod_ruid2版)」への1件のフィードバック

コメントは受け付けていません。