1 /*
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that the following conditions
4 * are met:
5 * 1. Redistributions of source code must retain the above copyright
6 * notice, and the entire permission notice in its entirety,
7 * including the disclaimer of warranties.
8 * 2. Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * 3. The name of the author may not be used to endorse or promote
12 * products derived from this software without specific prior
13 * written permission.
14 *
15 * ALTERNATIVELY, this product may be distributed under the terms of
16 * the GNU Public License, in which case the provisions of the GPL are
17 * required INSTEAD OF the above restrictions. (This clause is
18 * necessary due to a potential bad interaction between the GPL and
19 * the restrictions contained in a BSD-style copyright.)
20 *
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include "config.h"
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <stdarg.h>
40 #include <errno.h>
41
42 #include <security/pam_modules.h>
43 #include <security/pam_ext.h>
44
45 #include "pam_private.h"
46 #include "pam_inline.h"
47
48 int
49 pam_vprompt (pam_handle_t *pamh, int style, char **response,
50 const char *fmt, va_list args)
51 {
52 struct pam_message msg;
53 struct pam_response *pam_resp = NULL;
54 const struct pam_message *pmsg;
55 const struct pam_conv *conv;
56 const void *convp;
57 char *msgbuf;
58 int retval;
59
60 if (response)
61 *response = NULL;
62
63 retval = pam_get_item (pamh, PAM_CONV, &convp);
64 if (retval != PAM_SUCCESS)
65 return retval;
66 conv = convp;
67 if (conv == NULL || conv->conv == NULL)
68 {
69 pam_syslog (pamh, LOG_ERR, "no conversation function");
70 return PAM_SYSTEM_ERR;
71 }
72
73 if (vasprintf (&msgbuf, fmt, args) < 0)
74 {
75 pam_syslog (pamh, LOG_ERR, "vasprintf: %m");
76 return PAM_BUF_ERR;
77 }
78
79 msg.msg_style = style;
80 msg.msg = msgbuf;
81 pmsg = &msg;
82
83 retval = conv->conv (1, &pmsg, &pam_resp, conv->appdata_ptr);
84 if (retval != PAM_SUCCESS && pam_resp != NULL)
85 pam_syslog(pamh, LOG_WARNING,
86 "unexpected response from failed conversation function");
87 if (response)
88 *response = pam_resp == NULL ? NULL : pam_resp->resp;
89 else if (pam_resp && pam_resp->resp)
90 {
91 pam_overwrite_string (pam_resp->resp);
92 _pam_drop (pam_resp->resp);
93 }
94 pam_overwrite_string (msgbuf);
95 _pam_drop (pam_resp);
96 free (msgbuf);
97 if (retval != PAM_SUCCESS)
98 pam_syslog (pamh, LOG_ERR, "conversation failed");
99
100 return retval;
101 }
102
103 int
104 pam_prompt (pam_handle_t *pamh, int style, char **response,
105 const char *fmt, ...)
106 {
107 va_list args;
108 int retval;
109
110 va_start (args, fmt);
111 retval = pam_vprompt (pamh, style, response, fmt, args);
112 va_end (args);
113
114 return retval;
115 }