JavaScript is required to for searching.
跳过导航链接
退出打印视图
Oracle Solaris 10 开发者安全性指南     Oracle Solaris 10 1/13 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 提供者服务模块样例

4.  编写使用 GSS-API 的应用程序

5.  GSS-API 客户机示例

6.  GSS-API 服务器示例

7.  编写使用 SASL 的应用程序

8.  Oracle Solaris 加密框架介绍

9.  编写用户级加密应用程序和提供者

10.  使用智能卡框架

A.  基于 C 的 GSS-API 样例程序

B.  GSS-API 参考

C.  指定 OID

D.  SASL 示例的源代码

E.  SASL 参考表

F.  打包和签署加密提供者

词汇表

索引

编写提供 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() 函数共享此数据。

服务模块必须返回以下三类 PAM 返回码之一:

如果服务模块执行多个函数,则应将这些函数分成单独的模块。使用此方法,系统管理员可对策略配置进行更为精细的控制。

应该为任何新的服务模块提供手册页。手册页应该包括以下各项:

服务模块必须支持 PAM_SILENT 标志,以防止显示消息。建议使用 debug 参数将调试信息记录到 syslog 中。请将 syslog(3C) 与 LOG_AUTH 和 LOG_DEBUG 结合使用来记录调试。其他消息应发送到具有 LOG_AUTH 和相应优先级的 syslog()。决不能使用 openlog(3C)closelog(3C)setlogmask(3C),因为这些函数会干扰应用程序设置。

PAM 提供者服务模块样例

以下是一个 PAM 服务模块样例。此示例将查看用户是否是允许访问此服务的组中的成员。如果成功,则提供者随后将授予访问权限,如果失败则记录错误消息。此示例执行以下步骤:

  1. 解析从 /etc/pam.conf 中的配置行传递到此模块的选项。

    此模块可接受 nowarndebug 选项以及特定的选项 group。使用 group 选项可以配置模块,允许其访问除缺省情况下使用的 root 组以外的特定组。有关示例,请参见源代码中 DEFAULT_GROUP 的定义。例如,要允许属于组 staff 的用户访问 telnet(1),用户可以使用以下行(位于 /etc/pam.conf 中的 telnet 栈中):

    telnet  account  required  pam_members_only.so.1 group=staff
  2. 获取用户名、服务名和主机名。

    用户名通过调用 pam_get_user(3PAM)(用于从 PAM 句柄中检索当前用户名)获取。如果未设置用户名,则会拒绝访问。可通过调用 pam_get_item(3PAM) 来获取服务名和主机名。

  3. 验证要使用的信息。

    如果未设置用户名,则拒绝访问。如果未定义要使用的组,则拒绝访问。

  4. 检验当前用户是否是允许访问此主机并且授予访问权限的特殊组的成员。

    如果该特殊组已定义但根本不包含任何成员,则将返回 PAM_IGNORE,表示此模块不参与任何帐户验证过程。该决策将留给栈中的其他模块。

  5. 如果用户不是特殊组的成员,则会显示一条消息,通知用户访问被拒绝。

    记录消息以记录此事件。

以下示例给出了 PAM 提供者样例的源代码。

示例 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);
}