Oracle Solaris セキュリティーサービス開発ガイド

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 プロバイダ例のソースコードです。


注 –

このソースコード例は、Sun ダウンロードセンターからダウンロードすることも可能です。http://www.sun.com/download/products.xml?id=41912db5 を参照してください。



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

/*
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#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);
}