JavaScript is required to for searching.
ナビゲーションリンクをスキップ
印刷ビューの終了
Oracle Solaris 11 セキュリティーサービス開発ガイド     Oracle Solaris 11 Information Library (日本語)
search filter icon
search icon

ドキュメントの情報

はじめに

1.  Oracle Solaris の開発者向けセキュリティー機能 (概要)

2.  特権付きアプリケーションの開発

3.  PAM アプリケーションおよび PAM サービスの記述

PAM フレームワークの概要

PAM サービスモジュール

PAM ライブラリ

PAM 認証プロセス

PAM コンシューマの要件

PAM 構成

PAM サービスを使用するアプリケーションの記述

単純な PAM コンシューマ例

その他の有用な PAM 関数

対話関数の記述

PAM サービスを提供するモジュールの記述

PAM サービスプロバイダの要件

PAM プロバイダサービスモジュールの例

4.  GSS-API を使用するアプリケーションの記述

5.  GSS-API クライアント例

6.  GSS-API サーバー例

7.  SASL を使用するアプリケーションの記述

8.  Oracle Solaris 暗号化フレームワークの紹介

9.  ユーザーレベルの暗号化アプリケーションとプロバイダの記述

10.  Oracle Solaris 鍵管理フレームワークの紹介

A.  C ベース の GSS-API プログラム例

B.  GSS-API リファレンス

C.  OID の指定

D.  SASL ソースコード例

E.  SASL リファレンス

用語集

索引

PAM サービスを提供するモジュールの記述

ここでは、PAM サービスモジュールの記述方法を説明します。

PAM サービスプロバイダの要件

PAM サービスモジュールは、pam_get_item(3PAM)pam_set_item(3PAM) を使ってアプリケーションとの通信を行います。 サービスモジュール同士の通信には、pam_get_data(3PAM)pam_set_data(3PAM) が使用されます。 同一プロジェクト内のサービスモジュール間でデータを交換する必要がある場合、そのプロジェクト内で一意に決まるデータ名が確立されます。 その後、サービスモジュールは、関数 pam_get_data()pam_set_data() を使ってそのデータを共有できます。

サービスモジュールは、次の 3 種類の PAM 戻りコードのいずれかを返す必要があります。

1 つのサービスモジュール内に複数の機能が含まれている場合、それらの機能はそれぞれ個別のモジュールに分割することをお勧めします。 そうすることで、システム管理者は、ポリシー設定時によりきめ細かい制御を行えるようになります。

新しいサービスモジュールを作成した場合、対応するマニュアルページを提供する必要があります。 マニュアルページには、次の情報を含める必要があります。

サービスモジュールは、メッセージを抑制するための PAM_SILENT フラグを尊重することが求められます。 デバッグ情報を syslog に記録するには、debug 引数を指定することをお勧めします。 デバッグ情報を記録するには、syslog(3C) 使用時に LOG_AUTH と LOG_DEBUG を指定します。 その他のメッセージは、LOG_AUTH と適切な優先度を指定して syslog() に送るべきです。openlog(3C)closelog(3C)、および setlogmask(3C) という 3 つの関数はアプリケーションの設定に悪影響を与えるので、決して使用しないでください。

PAM プロバイダサービスモジュールの例

ここでは、PAM サービスモジュールの例を示します。 この例では、ユーザーがこのサービスへのアクセスが許可されているグループのメンバーかどうかを確認します。 プロバイダは、成功の場合にアクセスを許可し、失敗の場合にエラーメッセージをログに記録します。

この例では、次の手順を実行します。

  1. /etc/pam.conf の構成行からこのモジュールに渡されたオプションを解析します。

    このモジュールは、nowarn オプションおよび debug オプション、さらに固有のオプション group を受け入れます。 group オプションを使用する場合、デフォルトで使用されるグループ root 以外の特定のグループに対してアクセスを許可するようにモジュールを構成できます。 この例については、ソースコードの DEFAULT_GROUP の定義を参照してください。 たとえば、グループ staff に属するユーザーによる telnet(1) アクセスを許可するには、/etc/pam.conftelnet スタックにある次の行を使用できます。

    telnet  account  required  pam_members_only.so.1 group=staff
  2. ユーザー名、サービス名、およびホスト名を取得します。

    ユーザー名は、現在のユーザー名を PAM ハンドルから取り出す、pam_get_user(3PAM) の呼び出しによって取得されます。 ユーザー名が設定されていない場合、アクセスは拒否されます。 サービス名とホスト名は、pam_get_item(3PAM) の呼び出しによって取得されます。

  3. 有効にする情報を検証します。

    ユーザー名が設定されていない場合、アクセスは拒否されます。 有効にするグループが定義されていない場合、アクセスは拒否されます。

  4. 現在のユーザーが、このホストへのアクセスが許可されている特殊グループのメンバーであることを確認し、アクセスを許可します。

    固有のグループが定義されていてもメンバーが 1 つも含まれていない場合は、このモジュールがどのアカウント検証プロセスにも参加しないことを示す、PAM_IGNORE が返されます。 決定は、スタック上のほかのモジュールに委ねられます。

  5. ユーザーが特殊グループのメンバーではない場合は、アクセスが拒否されたことをユーザーに知らせるメッセージを表示します。

    メッセージをログに記録してこのイベントを記録します。

次の例は、PAM プロバイダ例のソースコードです。


注 - このソースコード例は、Oracle ダウンロードセンターからダウンロードすることも可能です。 http://www.oracle.com/technetwork/indexes/downloads/sdlc-decommission-333274.html を参照してください。


例 3-3 PAM サービスモジュール例

/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
 */

#include <stdio.h>
#include <stdlib.h>
#include <grp.h>
#include <string.h>
#include <syslog.h>
#include <libintl.h>
#include <security/pam_appl.h>

/*
 * by default, only users who are a member of group "root" are allowed access
 */
#define    DEFAULT_GROUP "root"

static char *NOMSG =
    "Sorry, you are not on the access list for this host - access denied.";

int
pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, int argc, const char **argv)
{
    char *user = NULL;
    char *host = NULL;
    char *service = NULL;
    const char *allowed_grp = DEFAULT_GROUP;
    char grp_buf[4096];
    struct group grp;
    struct pam_conv *conversation;
    struct pam_message message;
    struct pam_message *pmessage = &message;
    struct pam_response *res = NULL;
    int i;
    int nowarn = 0;
    int debug = 0;

    /* Set flags to display warnings if in debug mode. */
    for (i = 0; i < argc; i++) {
        if (strcasecmp(argv[i], "nowarn") == 0)
            nowarn = 1;
        else if (strcasecmp(argv[i], "debug") == 0)
            debug = 1;
        else if (strncmp(argv[i], "group=", 6) == 0)
            allowed_grp = &argv[i][6];
    }
    if (flags & PAM_SILENT)
        nowarn = 1;

    /* Get user name,service name, and host name. */
    (void) pam_get_user(pamh, &user, NULL);
    (void) pam_get_item(pamh, PAM_SERVICE, (void **) &service);
    (void) pam_get_item(pamh, PAM_RHOST, (void **) &host);

    /* Deny access if user is NULL. */
    if (user == NULL) {
        syslog(LOG_AUTH|LOG_DEBUG,
            "%s: members_only: user not set", service);
        return (PAM_USER_UNKNOWN);
    }

    if (host == NULL)
        host = "unknown";

    /*
     * Deny access if vuser group is required and user is not in vuser
     * group
     */
    if (getgrnam_r(allowed_grp, &grp, grp_buf, sizeof (grp_buf)) == NULL) {
        syslog(LOG_NOTICE|LOG_AUTH,
            "%s: members_only: group \"%s\" not defined",
            service, allowed_grp);
        return (PAM_SYSTEM_ERR);
    }

    /* Ignore this module if group contains no members. */
    if (grp.gr_mem[0] == 0) {
        if (debug)
            syslog(LOG_AUTH|LOG_DEBUG,
                "%s: members_only: group %s empty: "
                "all users allowed.", service, grp.gr_name);
        return (PAM_IGNORE);
    }

    /* Check to see if user is in group. If so, return SUCCESS. */
    for (; grp.gr_mem[0]; grp.gr_mem++) {
        if (strcmp(grp.gr_mem[0], user) == 0) {
            if (debug)
                syslog(LOG_AUTH|LOG_DEBUG,
                    "%s: user %s is member of group %s. "
                    "Access allowed.",
                    service, user, grp.gr_name);
            return (PAM_SUCCESS);
        }
    }

    /*
     * User is not a member of the group.
     * Set message style to error and specify denial message.
     */
    message.msg_style = PAM_ERROR_MSG;
    message.msg = gettext(NOMSG);

    /* Use conversation function to display denial message to user. */
    (void) pam_get_item(pamh, PAM_CONV, (void **) &conversation);
    if (nowarn == 0 && conversation != NULL) {
        int err;
        err = conversation->conv(1, &pmessage, &res,
            conversation->appdata_ptr);
        if (debug && err != PAM_SUCCESS)
            syslog(LOG_AUTH|LOG_DEBUG,
                "%s: members_only: conversation returned "
                "error %d (%s).", service, err,
                pam_strerror(pamh, err));

        /* free response (if any) */
        if (res != NULL) {
            if (res->resp)
                free(res->resp);
            free(res);
        }
    }

    /* Report denial to system log and return error to caller. */
    syslog(LOG_NOTICE | LOG_AUTH, "%s: members_only: "
        "Connection for %s not allowed from %s", service, user, host);

    return (PAM_PERM_DENIED);
}