4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * This file has all of the PAM related code for sys-suspend. It is
28 * part of it's own file, as these could be part of some bigger item
29 * that can handle generic PAM facilities (certainly the getinput()
30 * function could be in a common library). However, as that does not
31 * yet exist, we replicate it here so we can get the job done.
34 #define __EXTENSIONS__ /* to expose flockfile and friends in stdio.h */
46 #include <security/pam_appl.h>
48 static int ctl_c
; /* was the conversation interrupted? */
58 * getinput -- read user input from stdin abort on ^C
60 * Entry noecho == TRUE, don't echo input.
63 * If interrupted, send SIGINT to caller for processing.
69 unsigned short tty_flags
= 0;
70 char input
[PAM_MAX_RESP_SIZE
+ 1];
76 sig
= signal(SIGINT
, interrupt
);
78 (void) ioctl(fileno(stdin
), TCGETA
, &tty
);
79 tty_flags
= tty
.c_lflag
;
80 tty
.c_lflag
&= ~(ECHO
| ECHOE
| ECHOK
| ECHONL
);
81 (void) ioctl(fileno(stdin
), TCSETAF
, &tty
);
83 /* go to end, but don't overflow PAM_MAX_RESP_SIZE */
86 (c
= getchar_unlocked()) != '\n' &&
89 if (i
< PAM_MAX_RESP_SIZE
) {
96 tty
.c_lflag
= tty_flags
;
97 (void) ioctl(fileno(stdin
), TCSETAW
, &tty
);
98 (void) fputc('\n', stdout
);
100 (void) signal(SIGINT
, sig
);
102 (void) kill(getpid(), SIGINT
);
104 return (strdup(input
));
108 * Service modules don't clean up responses if an error is returned.
109 * Free responses here.
112 free_resp(int num_msg
, struct pam_response
*pr
)
115 struct pam_response
*r
= pr
;
120 for (i
= 0; i
< num_msg
; i
++, r
++) {
123 /* clear before freeing -- may be a password */
124 bzero(r
->resp
, strlen(r
->resp
));
134 pam_tty_conv(int num_msg
, struct pam_message
**mess
,
135 struct pam_response
**resp
, void *my_data
)
137 struct pam_message
*m
= *mess
;
138 struct pam_response
*r
= calloc(num_msg
, sizeof (struct pam_response
));
141 if (num_msg
>= PAM_MAX_NUM_MSG
) {
142 (void) fprintf(stderr
, "too many messages %d >= %d\n",
143 num_msg
, PAM_MAX_NUM_MSG
);
146 return (PAM_CONV_ERR
);
151 for (i
= 0; i
< num_msg
; i
++) {
154 /* bad message from service module */
155 if (m
->msg
== NULL
) {
156 (void) fprintf(stderr
, "message[%d]: %d/NULL\n",
162 * fix up final newline:
163 * removed for prompts
164 * added back for messages
166 if (m
->msg
[strlen(m
->msg
)] == '\n')
167 m
->msg
[strlen(m
->msg
)] = '\0';
172 switch (m
->msg_style
) {
174 case PAM_PROMPT_ECHO_OFF
:
178 case PAM_PROMPT_ECHO_ON
:
179 (void) fputs(m
->msg
, stdout
);
181 r
->resp
= getinput(echo_off
);
185 (void) fputs(m
->msg
, stderr
);
186 (void) fputc('\n', stderr
);
190 (void) fputs(m
->msg
, stdout
);
191 (void) fputc('\n', stdout
);
195 (void) fprintf(stderr
, "message[%d]: unknown type "
197 i
, m
->msg_style
, m
->msg
);
198 /* error, service module won't clean up */
204 /* next message/response */
208 return (PAM_SUCCESS
);
213 return (PAM_CONV_ERR
);