Changeset 72 in openpam


Ignore:
Timestamp:
Feb 22, 2002, 8:35:00 PM (16 years ago)
Author:
Dag-Erling Smørgrav
Message:

Mask signals while prompting the user (except for SIGINT and SIGTSTP),
and add timeout functionality (defaults to off).

Sponsored by: DARPA, NAI Labs

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/openpam_ttyconv.c

    r63 r72  
    3838
    3939#include <ctype.h>
     40#include <setjmp.h>
     41#include <signal.h>
    4042#include <stdio.h>
    4143#include <stdlib.h>
    4244#include <string.h>
    4345#include <termios.h>
     46#include <unistd.h>
    4447
    4548#include <security/pam_appl.h>
    4649#include <security/openpam.h>
     50
     51int openpam_ttyconv_timeout = 0;
     52static jmp_buf jmpenv;
     53static int timed_out;
     54
     55static void
     56timeout(int sig)
     57{
     58        timed_out = 1;
     59        longjmp(jmpenv, sig);
     60}
     61
     62static char *
     63prompt(const char *msg)
     64{
     65        char buf[PAM_MAX_RESP_SIZE];
     66        struct sigaction action, saved_action;
     67        sigset_t saved_sigset, sigset;
     68        unsigned int saved_alarm;
     69        size_t len;
     70
     71        sigemptyset(&sigset);
     72        sigaddset(&sigset, SIGINT);
     73        sigaddset(&sigset, SIGTSTP);
     74        sigprocmask(SIG_SETMASK, &sigset, &saved_sigset);
     75        action.sa_handler = &timeout;
     76        action.sa_flags = 0;
     77        sigemptyset(&action.sa_mask);
     78        sigaction(SIGALRM, &action, &saved_action);
     79        fputs(msg, stderr);
     80        buf[0] = '\0';
     81        timed_out = 0;
     82        saved_alarm = alarm(openpam_ttyconv_timeout);
     83        if (setjmp(jmpenv) == 0)
     84                fgets(buf, sizeof buf, stdin);
     85        else
     86                fputs(" timeout!\n", stderr);
     87        alarm(0);
     88        sigaction(SIGALRM, &saved_action, NULL);
     89        sigprocmask(SIG_SETMASK, &saved_sigset, NULL);
     90        alarm(saved_alarm);
     91        if (timed_out || ferror(stdin))
     92                return (NULL);
     93        /* trim trailing whitespace */
     94        for (len = strlen(buf); len > 0; --len)
     95                if (!isspace(buf[len - 1]))
     96                        break;
     97        buf[len] = '\0';
     98        return (strdup(buf));
     99}
     100
     101static char *
     102prompt_echo_off(const char *msg)
     103{
     104        struct termios tattr;
     105        tcflag_t lflag;
     106        char *ret;
     107        int fd;
     108       
     109        fd = fileno(stdin);
     110        if (tcgetattr(fd, &tattr) != 0) {
     111                openpam_log(PAM_LOG_ERROR, "tcgetattr(): %m");
     112                return (NULL);
     113        }
     114        lflag = tattr.c_lflag;
     115        tattr.c_lflag &= ~ECHO;
     116        if (tcsetattr(fd, TCSAFLUSH, &tattr) != 0) {
     117                openpam_log(PAM_LOG_ERROR, "tcsetattr(): %m");
     118                return (NULL);
     119        }
     120        ret = prompt(msg);
     121        tattr.c_lflag = lflag;
     122        (void)tcsetattr(fd, TCSANOW, &tattr);
     123        if (ret != NULL)
     124                fputs("\n", stdout);
     125        return (ret);
     126}
    47127
    48128/*
     
    58138         void *data)
    59139{
    60         char buf[PAM_MAX_RESP_SIZE];
    61         struct termios tattr;
    62         tcflag_t lflag;
    63         int fd, err, i;
    64         size_t len;
     140        int i;
    65141
    66142        data = data;
     
    69145        if ((*resp = calloc(n, sizeof **resp)) == NULL)
    70146                return (PAM_BUF_ERR);
    71         fd = fileno(stdin);
    72147        for (i = 0; i < n; ++i) {
    73148                resp[i]->resp_retcode = 0;
     
    75150                switch (msg[i]->msg_style) {
    76151                case PAM_PROMPT_ECHO_OFF:
     152                        resp[i]->resp = prompt_echo_off(msg[i]->msg);
     153                        if (resp[i]->resp == NULL)
     154                                goto fail;
     155                        break;
    77156                case PAM_PROMPT_ECHO_ON:
    78                         if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF) {
    79                                 if (tcgetattr(fd, &tattr) != 0) {
    80                                         openpam_log(PAM_LOG_ERROR,
    81                                             "tcgetattr(): %m");
    82                                         err = PAM_CONV_ERR;
    83                                         goto fail;
    84                                 }
    85                                 lflag = tattr.c_lflag;
    86                                 tattr.c_lflag &= ~ECHO;
    87                                 if (tcsetattr(fd, TCSAFLUSH, &tattr) != 0) {
    88                                         openpam_log(PAM_LOG_ERROR,
    89                                             "tcsetattr(): %m");
    90                                         err = PAM_CONV_ERR;
    91                                         goto fail;
    92                                 }
    93                         }
    94                         fputs(msg[i]->msg, stderr);
    95                         buf[0] = '\0';
    96                         fgets(buf, sizeof buf, stdin);
    97                         if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF) {
    98                                 tattr.c_lflag = lflag;
    99                                 (void)tcsetattr(fd, TCSANOW, &tattr);
    100                                 fputs("\n", stderr);
    101                         }
    102                         if (ferror(stdin)) {
    103                                 err = PAM_CONV_ERR;
     157                        resp[i]->resp = prompt(msg[i]->msg);
     158                        if (resp[i]->resp == NULL)
    104159                                goto fail;
    105                         }
    106                         for (len = strlen(buf); len > 0; --len)
    107                                 if (!isspace(buf[len - 1]))
    108                                         break;
    109                         buf[len] = '\0';
    110                         if ((resp[i]->resp = strdup(buf)) == NULL) {
    111                                 err = PAM_BUF_ERR;
    112                                 goto fail;
    113                         }
    114160                        break;
    115161                case PAM_ERROR_MSG:
     
    120166                        break;
    121167                default:
    122                         err = PAM_BUF_ERR;
    123168                        goto fail;
    124169                }
     
    130175        free(*resp);
    131176        *resp = NULL;
    132         return (err);
     177        return (PAM_CONV_ERR);
    133178}
    134179
Note: See TracChangeset for help on using the changeset viewer.