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

ドキュメントの情報

はじめに

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

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

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

PAM フレームワークの概要

PAM サービスモジュール

このリリースでの PAM への変更

PAM ライブラリ

PAM 認証プロセス

PAM コンシューマの要件

PAM 構成

/etc/pam.d を介した 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.  開発者のためのセキュアコーディングガイドライン

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

C.  GSS-API リファレンス

D.  OID の指定

E.  SASL ソースコード例

F.  SASL リファレンス

用語集

索引

ドキュメントの品質向上のためのご意見をください
簡潔すぎた
読みづらかった、または難し過ぎた
重要な情報が欠けていた
内容が間違っていた
翻訳版が必要
その他
Your rating has been updated
貴重なご意見を有り難うございました!

あなたの貴重なご意見はより良いドキュメント作成の手助けとなります 内容の品質向上と追加コメントのためのアンケートに参加されますか?

対話関数の記述

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

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

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

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


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


例 3-2 PAM 対話関数

/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates.
* All rights reserved.
 #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);

errno = 0; /* don't propogate possible EINTR */

    /* 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);
}