JavaScript is required to for searching.
ナビゲーションリンクをスキップ
印刷ビューの終了
Oracle Solaris セキュリティーサービス開発ガイド     Oracle Solaris 10 8/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.  スマートカードフレームワークの使用

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

B.  GSS-API リファレンス

C.  OID の指定

D.  SASL ソースコード例

E.  SASL リファレンス

F.  暗号化プロバイダのパッケージ化と署名

用語集

索引

対話関数の記述

PAM モジュール (アプリケーション) はいくつかの方法でユーザーと通信できます。 たとえば、コマンド行を使用する方法や、ダイアログボックスを使用する方法などです。その結果、ユーザーと通信する PAM コンシューマの設計者は、「対話関数」と呼ばれるものを記述する必要があります。対話関数は、特定の通信手段に依存することなしに、ユーザーとモジュール間でメッセージの受け渡しを行います。対話関数は、対話関数コールバック関数の pam_message パラメータ内の msg_style パラメータから、メッセージタイプを得ます。pam_start(3PAM) のマニュアルページを参照してください。

開発者は、PAM とユーザー間の通信手段について、何らかの仮定を行なってはいけません。むしろ、アプリケーションは、処理が完了するまでユーザーとメッセージを交換し続ける必要があります。アプリケーションは、対話関数のメッセージ文字列を、解釈または変更することなしに表示します。個々のメッセージには、複数の行を含めることができるほか、制御文字や余分な空白も含めることができます。対話関数に送信する文字列を各言語対応にすることは、サービスモジュールの責任であることに注意してください。

対話関数の例 pam_tty_conv() を、次に示します。pam_tty_conv() の引数は次のとおりです。

この関数例は、stdin からユーザー入力を取得します。応答バッファーに対するメモリーの割り当ては、このルーチンが行う必要があります。最大値 PAM_MAX_NUM_MSG を設定すれば、メッセージの数を制限できます。対話関数がエラーを返す場合、対話関数は応答に割り当てられていたすべてのメモリーを消去および解放する役割を担います。さらに、対話関数は応答ポインタを NULL に設定する必要があります。メモリーの消去は、ゼロ埋めアプローチを使用して完了されるべきです。対話関数の呼び出し側には、呼び出し側に返されたすべての応答を解放する責任があります。対話を実現するために、この関数は、ユーザーアプリケーションからのメッセージをループ処理します。有効なメッセージは stdout に書き込まれ、エラーメッセージは stderr に書き込まれます。


注 - このソースコード例は、ダウンロードセンターからダウンロードすることも可能です。https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_SMI-Site/en_US/-/USD/ViewProductDetail-Start?ProductRef=Security_code-Dev1.1-G-F@CDS-CDS_SMI を参照してください。


例 3-2 PAM 対話関数

/* 
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved. 
 * Use is subject to license terms. 
 */
 
#pragma ident    "@(#)pam_tty_conv.c    1.4    05/02/12 SMI"  

#define    __EXTENSIONS__    /* to expose flockfile and friends in stdio.h */ 
#include <errno.h>
#include <libgen.h>
#include <malloc.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <stropts.h>
#include <unistd.h>
#include <termio.h>
#include <security/pam_appl.h>

static int ctl_c;    /* was the conversation interrupted? */

/* ARGSUSED 1 */
static void
interrupt(int x)
{
    ctl_c = 1;
}

/* getinput -- read user input from stdin abort on ^C
 *    Entry    noecho == TRUE, don't echo input.
 *    Exit    User's input.
 *        If interrupted, send SIGINT to caller for processing.
 */
static char *
getinput(int noecho)
{
    struct termio tty;
    unsigned short tty_flags;
    char input[PAM_MAX_RESP_SIZE];
    int c;
    int i = 0;
    void (*sig)(int);

    ctl_c = 0;
    sig = signal(SIGINT, interrupt);
    if (noecho) {
        (void) ioctl(fileno(stdin), TCGETA, &tty);
        tty_flags = tty.c_lflag;
        tty.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
        (void) ioctl(fileno(stdin), TCSETAF, &tty);
    }

    /* go to end, but don't overflow PAM_MAX_RESP_SIZE */
    flockfile(stdin);
    while (ctl_c == 0 &&
        (c = getchar_unlocked()) != '\n' &&
        c != '\r' &&
        c != EOF) {
        if (i < PAM_MAX_RESP_SIZE) {
            input[i++] = (char)c;
        }
    }
    funlockfile(stdin);
    input[i] = '\0';
    if (noecho) {
        tty.c_lflag = tty_flags;
        (void) ioctl(fileno(stdin), TCSETAW, &tty);
        (void) fputc('\n', stdout);
    }
    (void) signal(SIGINT, sig);
    if (ctl_c == 1)
        (void) kill(getpid(), SIGINT);

    return (strdup(input));
}

/* Service modules do not clean up responses if an error is returned.
 * Free responses here.
 */
static void
free_resp(int num_msg, struct pam_response *pr)
{
    int i;
    struct pam_response *r = pr;

    if (pr == NULL)
        return;

    for (i = 0; i < num_msg; i++, r++) {

        if (r->resp) {
            /* clear before freeing -- may be a password */
            bzero(r->resp, strlen(r->resp));
            free(r->resp);
            r->resp = NULL;
        }
    }
    free(pr);
}

/* ARGSUSED */
int
pam_tty_conv(int num_msg, struct pam_message **mess,
    struct pam_response **resp, void *my_data)
{
    struct pam_message *m = *mess;
    struct pam_response *r;
    int i;

    if (num_msg <= 0 || num_msg >= PAM_MAX_NUM_MSG) {
        (void) fprintf(stderr, "bad number of messages %d "
            "<= 0 || >= %d\n",
            num_msg, PAM_MAX_NUM_MSG);
        *resp = NULL;
        return (PAM_CONV_ERR);
    }
    if ((*resp = r = calloc(num_msg,
        sizeof (struct pam_response))) == NULL)
        return (PAM_BUF_ERR);

    /* Loop through messages */
    for (i = 0; i < num_msg; i++) {
        int echo_off;

        /* bad message from service module */
        if (m->msg == NULL) {
            (void) fprintf(stderr, "message[%d]: %d/NULL\n",
                i, m->msg_style);
            goto err;
        }

        /*
         * fix up final newline:
         *     removed for prompts
         *     added back for messages
         */
        if (m->msg[strlen(m->msg)] == '\n')
            m->msg[strlen(m->msg)] = '\0';

        r->resp = NULL;
        r->resp_retcode = 0;
        echo_off = 0;
        switch (m->msg_style) {

        case PAM_PROMPT_ECHO_OFF:
            echo_off = 1;
            /*FALLTHROUGH*/

        case PAM_PROMPT_ECHO_ON:
            (void) fputs(m->msg, stdout);

            r->resp = getinput(echo_off);
            break;

        case PAM_ERROR_MSG:
            (void) fputs(m->msg, stderr);
            (void) fputc('\n', stderr);
            break;

        case PAM_TEXT_INFO:
            (void) fputs(m->msg, stdout);
            (void) fputc('\n', stdout);
            break;

        default:
            (void) fprintf(stderr, "message[%d]: unknown type "
                "%d/val=\"%s\"\n",
                i, m->msg_style, m->msg);
            /* error, service module won't clean up */
            goto err;
        }
        if (errno == EINTR)
            goto err;

        /* next message/response */
        m++;
        r++;
    }
    return (PAM_SUCCESS);

err:
    free_resp(i, r);
    *resp = NULL;
    return (PAM_CONV_ERR);
}