source: openpam/trunk/lib/openpam_ttyconv.c @ 232

Last change on this file since 232 was 232, checked in by des, 12 years ago

With one single exception (where the pointer is obviously being
immediately overwritten), replace all use of free(3) with a macro
that clears the pointer after freeing the memory it pointed to.

Suggested by: Dmitry V. Levin <ldv@…>

File size: 5.4 KB
Line 
1/*-
2 * Copyright (c) 2002,2003 Networks Associates Technology, Inc.
3 * All rights reserved.
4 *
5 * This software was developed for the FreeBSD Project by ThinkSec AS and
6 * Network Associates Laboratories, the Security Research Division of
7 * Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
8 * ("CBOSS"), as part of the DARPA CHATS research program.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote
19 *    products derived from this software without specific prior written
20 *    permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * $P4: //depot/projects/openpam/lib/openpam_ttyconv.c#18 $
35 */
36
37#include <sys/types.h>
38
39#include <ctype.h>
40#include <setjmp.h>
41#include <signal.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <termios.h>
46#include <unistd.h>
47
48#include <security/pam_appl.h>
49
50#include "openpam_impl.h"
51
52int openpam_ttyconv_timeout = 0;
53static jmp_buf jmpenv;
54static int timed_out;
55
56static void
57timeout(int sig)
58{
59        timed_out = 1;
60        longjmp(jmpenv, sig);
61}
62
63static char *
64prompt(const char *msg)
65{
66        char buf[PAM_MAX_RESP_SIZE];
67        struct sigaction action, saved_action;
68        sigset_t saved_sigset, sigset;
69        unsigned int saved_alarm;
70        size_t len;
71
72        sigemptyset(&sigset);
73        sigaddset(&sigset, SIGINT);
74        sigaddset(&sigset, SIGTSTP);
75        sigprocmask(SIG_SETMASK, &sigset, &saved_sigset);
76        action.sa_handler = &timeout;
77        action.sa_flags = 0;
78        sigemptyset(&action.sa_mask);
79        sigaction(SIGALRM, &action, &saved_action);
80        fputs(msg, stdout);
81        buf[0] = '\0';
82        timed_out = 0;
83        saved_alarm = alarm(openpam_ttyconv_timeout);
84        if (setjmp(jmpenv) == 0)
85                fgets(buf, sizeof buf, stdin);
86        else
87                fputs(" timeout!\n", stderr);
88        alarm(0);
89        sigaction(SIGALRM, &saved_action, NULL);
90        sigprocmask(SIG_SETMASK, &saved_sigset, NULL);
91        alarm(saved_alarm);
92        if (timed_out || ferror(stdin) || feof(stdin))
93                return (NULL);
94        /* trim trailing whitespace */
95        for (len = strlen(buf); len > 0; --len)
96                if (!isspace(buf[len - 1]))
97                        break;
98        buf[len] = '\0';
99        return (strdup(buf));
100}
101
102static char *
103prompt_echo_off(const char *msg)
104{
105        struct termios tattr;
106        tcflag_t lflag;
107        char *ret;
108        int fd;
109
110        fd = fileno(stdin);
111        if (tcgetattr(fd, &tattr) != 0) {
112                openpam_log(PAM_LOG_ERROR, "tcgetattr(): %m");
113                return (NULL);
114        }
115        lflag = tattr.c_lflag;
116        tattr.c_lflag &= ~ECHO;
117        if (tcsetattr(fd, TCSAFLUSH, &tattr) != 0) {
118                openpam_log(PAM_LOG_ERROR, "tcsetattr(): %m");
119                return (NULL);
120        }
121        ret = prompt(msg);
122        tattr.c_lflag = lflag;
123        (void)tcsetattr(fd, TCSANOW, &tattr);
124        if (ret != NULL)
125                fputs("\n", stdout);
126        return (ret);
127}
128
129/*
130 * OpenPAM extension
131 *
132 * Simple tty-based conversation function
133 */
134
135int
136openpam_ttyconv(int n,
137         const struct pam_message **msg,
138         struct pam_response **resp,
139         void *data)
140{
141        int i;
142
143        ENTER();
144        (void)data;
145        if (n <= 0 || n > PAM_MAX_NUM_MSG)
146                RETURNC(PAM_CONV_ERR);
147        if ((*resp = calloc(n, sizeof **resp)) == NULL)
148                RETURNC(PAM_BUF_ERR);
149        for (i = 0; i < n; ++i) {
150                resp[i]->resp_retcode = 0;
151                resp[i]->resp = NULL;
152                switch (msg[i]->msg_style) {
153                case PAM_PROMPT_ECHO_OFF:
154                        resp[i]->resp = prompt_echo_off(msg[i]->msg);
155                        if (resp[i]->resp == NULL)
156                                goto fail;
157                        break;
158                case PAM_PROMPT_ECHO_ON:
159                        resp[i]->resp = prompt(msg[i]->msg);
160                        if (resp[i]->resp == NULL)
161                                goto fail;
162                        break;
163                case PAM_ERROR_MSG:
164                        fputs(msg[i]->msg, stderr);
165                        if (strlen(msg[i]->msg) > 0 &&
166                            msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
167                                fputc('\n', stderr);
168                        break;
169                case PAM_TEXT_INFO:
170                        fputs(msg[i]->msg, stdout);
171                        if (strlen(msg[i]->msg) > 0 &&
172                            msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
173                                fputc('\n', stdout);
174                        break;
175                default:
176                        goto fail;
177                }
178        }
179        RETURNC(PAM_SUCCESS);
180 fail:
181        while (i)
182                FREE(resp[--i]);
183        FREE(*resp);
184        *resp = NULL;
185        RETURNC(PAM_CONV_ERR);
186}
187
188/*
189 * Error codes:
190 *
191 *      PAM_SYSTEM_ERR
192 *      PAM_BUF_ERR
193 *      PAM_CONV_ERR
194 */
195
196/**
197 * The =openpam_ttyconv function is a standard conversation function
198 * suitable for use on TTY devices.  It should be adequate for the needs
199 * of most text-based interactive programs.
200 *
201 * The =openpam_ttyconv function allows the application to specify a
202 * timeout for user input by setting the global integer variable
203 * :openpam_ttyconv_timeout to the length of the timeout in seconds.
204 *
205 * >openpam_nullconv
206 * >pam_prompt
207 * >pam_vprompt
208 */
Note: See TracBrowser for help on using the repository browser.