1f3b0ac34SDag-Erling Smørgrav /*-
2*49e56509SDag-Erling Smørgrav * Copyright (c) 2015-2017 Dag-Erling Smørgrav
3f3b0ac34SDag-Erling Smørgrav * All rights reserved.
4f3b0ac34SDag-Erling Smørgrav *
5f3b0ac34SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without
6f3b0ac34SDag-Erling Smørgrav * modification, are permitted provided that the following conditions
7f3b0ac34SDag-Erling Smørgrav * are met:
8f3b0ac34SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright
9f3b0ac34SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer.
10f3b0ac34SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright
11f3b0ac34SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the
12f3b0ac34SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution.
13f3b0ac34SDag-Erling Smørgrav * 3. The name of the author may not be used to endorse or promote
14f3b0ac34SDag-Erling Smørgrav * products derived from this software without specific prior written
15f3b0ac34SDag-Erling Smørgrav * permission.
16f3b0ac34SDag-Erling Smørgrav *
17f3b0ac34SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18f3b0ac34SDag-Erling Smørgrav * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19f3b0ac34SDag-Erling Smørgrav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20f3b0ac34SDag-Erling Smørgrav * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21f3b0ac34SDag-Erling Smørgrav * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22f3b0ac34SDag-Erling Smørgrav * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23f3b0ac34SDag-Erling Smørgrav * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24f3b0ac34SDag-Erling Smørgrav * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25f3b0ac34SDag-Erling Smørgrav * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26f3b0ac34SDag-Erling Smørgrav * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27f3b0ac34SDag-Erling Smørgrav * SUCH DAMAGE.
28f3b0ac34SDag-Erling Smørgrav */
29f3b0ac34SDag-Erling Smørgrav
30f3b0ac34SDag-Erling Smørgrav #ifdef HAVE_CONFIG_H
31f3b0ac34SDag-Erling Smørgrav # include "config.h"
32f3b0ac34SDag-Erling Smørgrav #endif
33f3b0ac34SDag-Erling Smørgrav
34f3b0ac34SDag-Erling Smørgrav #include <err.h>
35f3b0ac34SDag-Erling Smørgrav #include <errno.h>
36f3b0ac34SDag-Erling Smørgrav #include <stdint.h>
37f3b0ac34SDag-Erling Smørgrav #include <stdio.h>
38f3b0ac34SDag-Erling Smørgrav #include <stdlib.h>
39f3b0ac34SDag-Erling Smørgrav #include <string.h>
40f3b0ac34SDag-Erling Smørgrav
41f3b0ac34SDag-Erling Smørgrav #include <cryb/test.h>
42f3b0ac34SDag-Erling Smørgrav
43f3b0ac34SDag-Erling Smørgrav #include <security/pam_appl.h>
44f3b0ac34SDag-Erling Smørgrav #include <security/openpam.h>
45f3b0ac34SDag-Erling Smørgrav
46f3b0ac34SDag-Erling Smørgrav #include "openpam_impl.h"
47f3b0ac34SDag-Erling Smørgrav #include "openpam_asprintf.h"
48f3b0ac34SDag-Erling Smørgrav
49f3b0ac34SDag-Erling Smørgrav #include "t_pam_conv.h"
50f3b0ac34SDag-Erling Smørgrav
51f3b0ac34SDag-Erling Smørgrav /*
52f3b0ac34SDag-Erling Smørgrav * Conversation function
53f3b0ac34SDag-Erling Smørgrav *
54f3b0ac34SDag-Erling Smørgrav * The appdata argument points to a struct t_pam_conv_script which
55f3b0ac34SDag-Erling Smørgrav * contains both the expected messages and the desired responses. If
56f3b0ac34SDag-Erling Smørgrav * script.responses is NULL, t_pam_conv() will return PAM_CONV_ERR. If an
57f3b0ac34SDag-Erling Smørgrav * error occurs (incorrect number of messages, messages don't match script
58f3b0ac34SDag-Erling Smørgrav * etc.), script.comment will be set to point to a malloc()ed string
59f3b0ac34SDag-Erling Smørgrav * describing the error. Otherwise, t_pam_conv() will return to its
60f3b0ac34SDag-Erling Smørgrav * caller a malloc()ed copy of script.responses.
61f3b0ac34SDag-Erling Smørgrav */
62f3b0ac34SDag-Erling Smørgrav int
t_pam_conv(int nm,const struct pam_message ** msgs,struct pam_response ** respsp,void * ad)63f3b0ac34SDag-Erling Smørgrav t_pam_conv(int nm, const struct pam_message **msgs,
64f3b0ac34SDag-Erling Smørgrav struct pam_response **respsp, void *ad)
65f3b0ac34SDag-Erling Smørgrav {
66f3b0ac34SDag-Erling Smørgrav struct t_pam_conv_script *s = ad;
67f3b0ac34SDag-Erling Smørgrav struct pam_response *resps;
68f3b0ac34SDag-Erling Smørgrav int i;
69f3b0ac34SDag-Erling Smørgrav
70f3b0ac34SDag-Erling Smørgrav /* check message count */
71f3b0ac34SDag-Erling Smørgrav if (nm != s->nmsg) {
72f3b0ac34SDag-Erling Smørgrav asprintf(&s->comment, "expected %d messages, got %d",
73f3b0ac34SDag-Erling Smørgrav s->nmsg, nm);
74f3b0ac34SDag-Erling Smørgrav return (PAM_CONV_ERR);
75f3b0ac34SDag-Erling Smørgrav }
76f3b0ac34SDag-Erling Smørgrav if (nm <= 0 || nm > PAM_MAX_NUM_MSG) {
77f3b0ac34SDag-Erling Smørgrav /* since the previous test passed, this is intentional! */
78f3b0ac34SDag-Erling Smørgrav s->comment = NULL;
79f3b0ac34SDag-Erling Smørgrav return (PAM_CONV_ERR);
80f3b0ac34SDag-Erling Smørgrav }
81f3b0ac34SDag-Erling Smørgrav
82f3b0ac34SDag-Erling Smørgrav /* check each message and provide the sed answer */
83f3b0ac34SDag-Erling Smørgrav if ((resps = calloc(nm, sizeof *resps)) == NULL)
84f3b0ac34SDag-Erling Smørgrav goto enomem;
85f3b0ac34SDag-Erling Smørgrav for (i = 0; i < nm; ++i) {
86f3b0ac34SDag-Erling Smørgrav if (msgs[i]->msg_style != s->msgs[i].msg_style) {
87f3b0ac34SDag-Erling Smørgrav asprintf(&s->comment,
88f3b0ac34SDag-Erling Smørgrav "message %d expected style %d got %d", i,
89f3b0ac34SDag-Erling Smørgrav s->msgs[i].msg_style, msgs[i]->msg_style);
90f3b0ac34SDag-Erling Smørgrav goto fail;
91f3b0ac34SDag-Erling Smørgrav }
92f3b0ac34SDag-Erling Smørgrav if (strcmp(msgs[i]->msg, s->msgs[i].msg) != 0) {
93f3b0ac34SDag-Erling Smørgrav asprintf(&s->comment,
94f3b0ac34SDag-Erling Smørgrav "message %d expected \"%s\" got \"%s\"", i,
95f3b0ac34SDag-Erling Smørgrav s->msgs[i].msg, msgs[i]->msg);
96f3b0ac34SDag-Erling Smørgrav goto fail;
97f3b0ac34SDag-Erling Smørgrav }
98f3b0ac34SDag-Erling Smørgrav switch (msgs[i]->msg_style) {
99f3b0ac34SDag-Erling Smørgrav case PAM_PROMPT_ECHO_OFF:
100*49e56509SDag-Erling Smørgrav t_printv("[PAM_PROMPT_ECHO_OFF] %s\n", msgs[i]->msg);
101f3b0ac34SDag-Erling Smørgrav break;
102f3b0ac34SDag-Erling Smørgrav case PAM_PROMPT_ECHO_ON:
103*49e56509SDag-Erling Smørgrav t_printv("[PAM_PROMPT_ECHO_ON] %s\n", msgs[i]->msg);
104f3b0ac34SDag-Erling Smørgrav break;
105f3b0ac34SDag-Erling Smørgrav case PAM_ERROR_MSG:
106*49e56509SDag-Erling Smørgrav t_printv("[PAM_ERROR_MSG] %s\n", msgs[i]->msg);
107f3b0ac34SDag-Erling Smørgrav break;
108f3b0ac34SDag-Erling Smørgrav case PAM_TEXT_INFO:
109*49e56509SDag-Erling Smørgrav t_printv("[PAM_TEXT_INFO] %s\n", msgs[i]->msg);
110f3b0ac34SDag-Erling Smørgrav break;
111f3b0ac34SDag-Erling Smørgrav default:
112f3b0ac34SDag-Erling Smørgrav asprintf(&s->comment, "invalid message style %d",
113f3b0ac34SDag-Erling Smørgrav msgs[i]->msg_style);
114f3b0ac34SDag-Erling Smørgrav goto fail;
115f3b0ac34SDag-Erling Smørgrav }
116f3b0ac34SDag-Erling Smørgrav /* copy the response, if there is one */
117f3b0ac34SDag-Erling Smørgrav if (s->resps[i].resp != NULL &&
118f3b0ac34SDag-Erling Smørgrav (resps[i].resp = strdup(s->resps[i].resp)) == NULL)
119f3b0ac34SDag-Erling Smørgrav goto enomem;
120f3b0ac34SDag-Erling Smørgrav resps[i].resp_retcode = s->resps[i].resp_retcode;
121f3b0ac34SDag-Erling Smørgrav }
122f3b0ac34SDag-Erling Smørgrav s->comment = NULL;
123f3b0ac34SDag-Erling Smørgrav *respsp = resps;
124f3b0ac34SDag-Erling Smørgrav return (PAM_SUCCESS);
125f3b0ac34SDag-Erling Smørgrav enomem:
126f3b0ac34SDag-Erling Smørgrav asprintf(&s->comment, "%s", strerror(ENOMEM));
127f3b0ac34SDag-Erling Smørgrav fail:
128f3b0ac34SDag-Erling Smørgrav for (i = 0; i < nm; ++i)
129f3b0ac34SDag-Erling Smørgrav free(resps[i].resp);
130f3b0ac34SDag-Erling Smørgrav free(resps);
131f3b0ac34SDag-Erling Smørgrav return (PAM_CONV_ERR);
132f3b0ac34SDag-Erling Smørgrav }
133