web-dev-qa-db-ja.com

mod_auth_shadowのApache2.4の置き換え?

私の雇用主は、RHEL6.xとApachehttpd2.2を長年実行しています。現在、RHEL7.1およびApachehttpd2.4を実行する新しいハードウェアへの移行を進めています。現在のWebサイトには、さまざまなクライアントのセット用にダウンロード可能な資料を含むさまざまな場所があります。クライアントはすべて、サーバーボックスにシステムアカウントを持っています。現在、クライアントユーザーのグループメンバーシップに基づいて場所へのアクセスを制御しています。

例えば:

_<Location /xyzzy/*>
    AuthName "xyzzy product support"
    AuthShadow on
    AuthType Basic
    require group xyzzy
    Options Includes ExecCGI Indexes FollowSymLinks MultiViews
</Location>
_

_mod_auth_shadow_を使用して、Apache2.2でこのアクセス制御を実装することに成功しました。ただし、モジュールがap_requires()を呼び出すため、このモジュールは2.4ではロードされないことがわかりました。これは、2.4では存在しません。

RHEL7がデフォルトで実行されることに気づきました

_/usr/sbin/saslauthd -m /run/saslauthd -a pam
_

そのため、mod_auth_shadowの代わりに_mod_authn_sasl_を介してPAMを使用することを検討してきました。私はこのApache構成で部分的に成功しました:

_<Location /xyzzy/*>
    AuthType Basic
    AuthName "xyzzy product support"
    AuthBasicProvider sasl
    AuthBasicAuthoritative On
    AuthSaslPwcheckMethod saslauthd
    Require valid-user
</Location>
_

この_/etc/pam.d/http_ファイルと組み合わせる:

_#%PAM-1.0
auth       include      password-auth
auth       include      pam_group
account    include      password-auth
_

この組み合わせでany有効なログイン資格情報を持つユーザーはxyzzyの場所にアクセスできます。これにより、Apache-> saslauthd-> PAM間の基本的な接続が機能していることが確認できると思います。しかし、それは私たちが求めている粒度のレベルではありません。

この代替httpd構成:

_<Location /xyzzy/*>
    AuthType Basic
    AuthName "xyzzy product support"
    AuthBasicProvider sasl
    AuthBasicAuthoritative On
    AuthSaslPwcheckMethod saslauthd
    Require group xyzzy
</Location>
_

httpdログに次のエラーを生成します。

_AH01664: No group file was specified in the configuration
_

これは、グループメンバーシップを検証するためにhttpdがnot saslauthdを通過していることを示しています。これまでのところ、ユーザー/パスワード認証のようにsaslを介してグループ認証を強制するhttpdディレクティブは見つかりませんでした。

(http用の個別のデータベースの代わりにシステムpasswd、shadow、およびgroupファイルを認証に使用するのはなぜですか?一部のクライアントは、httpではなくftp経由でサポートファイルをダウンロードすることを好みます。したがって、クライアントに比較的簡単に提供するためにシステムを使用します。 2つのプロトコル間の切り替え)

最後の手段として、2.4用にmod_auth_shadowを更新してみる準備ができています。しかし、私はApacheモジュールをコーディングまたはデバッグしたことがないため、そのアプローチには未知の学習曲線が含まれています。だから私は提案を完全に受け入れています!

3
Eric Chevalier

Unbelieverによって提案されたものを含むいくつかの代替案を検討した後、私は先に進んで、現在の認証/承認アーキテクチャと互換性があるように元のmod_auth_shadowを書き直してみることにしました。 mod_authnz_ldapモジュールをいくらかモデル化した非常に基本的な簡素化されたモジュールを作成しました。

/*
 * mod_auth_shadow.c
 *
 * An Apache module to authenticate using the /etc/shadow file.
 * This module interacts with another program "validate", which
 * is setuid root.  Thus the /etc/shadow file can remain 
 * root:root 0400.
 *
 * Author: Brian Duggan <[email protected]>
 * Some code was taken from the sample code supplied with
 * _Apache Modules_ by Stein and MacEachern.  Parts of this
 * were also influenced by mod_auth.c.
 *
 * Adapted for Apache2: Bernard du Breuil 
 *  <[email protected]>
 * I went back to mod_auth.c to see how it was converted.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 * 
 */

#include "apr_strings.h"
#include "ap_config.h"

#include "httpd.h"  
#include "http_config.h"  
#include "http_core.h"  
#include "http_log.h"  
#include "http_protocol.h"  
#include "http_request.h"  

#include "mod_auth.h"

#include <shadow.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pwd.h>
#include <grp.h>
#include "validate.h"


static const char module_name[] = "authnz_shadow_module";


static authn_status authn_shadow_check_password(request_rec *r, const char *user,
                                              const char *password)
{
    return AUTH_GRANTED;
}


static authz_status valid_user_check_authorization(request_rec *r,
                                              const char *require_args,
                                              const void *parsed_require_args)
{
    return AUTH_GRANTED;
}


static authz_status group_check_authorization(request_rec *r,
                                              const char *require_args,
                                              const void *parsed_require_args)
{
    return AUTH_GRANTED;
}




typedef struct
{
    int auth_shadow_flag; /* 1 for yes, 0 for no */
}
auth_shadow_config_rec;


static const authn_provider authn_shadow_provider =
{
    &authn_shadow_check_password,
    NULL,
};


static const authz_provider authz_valid_user_provider =
{
    &valid_user_check_authorization,
    NULL,
};


static const authz_provider authz_group_provider =
{
    &group_check_authorization,
    NULL,
};


static void register_hooks(apr_pool_t *p)
{
    /* Register authn provider */
    ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "shadow",
                              AUTHN_PROVIDER_VERSION,
                              &authn_shadow_provider, AP_AUTH_INTERNAL_PER_CONF);

    /* Register authz providers */
    ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "shadow-valid-user",
                              AUTHZ_PROVIDER_VERSION,
                              &authz_valid_user_provider,
                              AP_AUTH_INTERNAL_PER_CONF);
    ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "shadow-group",
                              AUTHZ_PROVIDER_VERSION,
                              &authz_group_provider,
                              AP_AUTH_INTERNAL_PER_CONF);
}


static void *create_auth_shadow_dir_config(apr_pool_t *p, char *d)
{
    auth_shadow_config_rec *sec =
    (auth_shadow_config_rec *) apr_palloc(p, sizeof(*sec));
    sec->auth_shadow_flag = 0;  
    return sec;
}


static const command_rec auth_shadow_cmds[] =
{
    AP_INIT_FLAG("AuthShadow", ap_set_flag_slot,
    (void *)APR_OFFSETOF(auth_shadow_config_rec, auth_shadow_flag),
        OR_AUTHCFG, "On or Off depending on whether to use /etc/shadow"),
    {NULL}
};


module AP_MODULE_DECLARE_DATA authnz_shadow_module = 
{
    STANDARD20_MODULE_STUFF, 
    create_auth_shadow_dir_config , /* dir config creator */
    NULL,                  /* merge  per-dir    config structures */
    NULL,                  /* create per-server config structures */
    NULL,                  /* merge  per-server config structures */
    auth_shadow_cmds,      /* [config file] command table */
    register_hooks     /* register hooks */
};

今、私は認証モジュールの全体的なロジックシーケンスを理解しようとしています。 Webサーバー上に次のように定義された安全なテストディレクトリを作成しました。

<Location /secure>
    AuthName SecureDocument
    AuthType Basic
    AuthBasicProvider shadow
    AuthShadow on
    Require shadow-valid-user
    Require shadow-group xyzzy
</Location>

そして、ここで私は非常に混乱します。テスト中に、valid_user_check_authorizationおよびgroup_check_authorizationルーチンがr->userをNULLに設定して呼び出されていることがわかりました。ただし、認証ルーチンauthn_shadow_check_password決して呼び出されません。

コード化されているように、mod_authnz_ldap.cモジュールは、認証および承認を単一のモジュールに組み合わせることができることを意味しているようです。ただし、認証関数が存在する場合は、承認関数の前に常に呼び出されると想定しています。さらに、ブラウザから提供された資格情報が認証機能に従って有効である場合、ユーザーIDは後続の認証機能に渡されると想定しています。しかし、私はそのトピックに関する決定的なドキュメントを何らかの方法で見つけていません。

私は私の仮定の提案、ヒント、修正を受け入れています!

1
Eric Chevalier

すでに1つのオプションを検討しているようですが、どちらも作業が必要になるようですが、さらにいくつかの可能性があります。

mod_auth_external: https://github.com/phokz/mod-auth-external
mod_auth_kerb: http://modauthkerb.sourceforge.net/

1
Unbeliever

また、このmod_authn_saslの制限に遭遇しました。ただし、ApacheレベルではなくPAMレベルでグループ制限を適用することにより、目的の効果を実現するのはかなり簡単です。

元の例では、valid-userのみを必要とするApache構成を残しますが、関連するPAMサービス構成/etc/pam.d/httpの目的のグループに制限を追加します。

#%PAM-1.0
auth       require      pam_succeed_if.so user ingroup xyzzy
auth       include      password-auth
auth       include      pam_group
account    include      password-auth

グループ/ユーザーのリストのいずれかに制限するには、最初のauth行を次のようにします。

auth       require      pam_listfile.so onerr=fail item=group sense=allow file=/path/to/allowed.groups

より多くの可能性が利用可能です。 man pam_succeed_ifおよびman pam_listfile ..を参照してください。

それぞれが異なる制限を必要とする複数の場所の場合、Apache構成のAuthSaslServiceNameを介して選択された個別のPAMサービスを作成します。例えば。上記の/etc/pam.d/httpの名前を/etc/pam.d/http-xyzzyに変更し、たとえばにコピーします。 /etc/pam.d/http-abcdそしてグループabcdに制限するように変更し、Apacheを次のように構成します。

<Location /abcd/*>
    AuthType Basic
    AuthName "abcd product support"
    AuthBasicProvider sasl
    AuthBasicAuthoritative On
    AuthSaslPwcheckMethod saslauthd
    AuthSaslServiceName http-abcd
    Require valid-user
</Location>
<Location /xyzzy/*>
    AuthType Basic
    AuthName "xyzzy product support"
    AuthBasicProvider sasl
    AuthBasicAuthoritative On
    AuthSaslPwcheckMethod saslauthd
    AuthSaslServiceName http-xyzzy
    Require valid-user
</Location>
0
Mad Alex