2 RCSID("$Id: auth2-pam.c,v 1.14 2002/06/28 16:48:12 mouring Exp $");
3 RCSID("$FreeBSD: src/crypto/openssh/auth2-pam.c,v 1.4.2.2 2003/02/03 17:31:06 des Exp $");
4 RCSID("$DragonFly: src/crypto/openssh/Attic/auth2-pam.c,v 1.2 2003/06/17 04:24:36 dillon Exp $");
7 #include <security/pam_appl.h>
18 static int do_pam_conversation_kbd_int(int num_msg,
19 const struct pam_message **msg, struct pam_response **resp,
21 void input_userauth_info_response_pam(int type, u_int32_t seqnr, void *ctxt);
24 int finished, num_received, num_expected;
26 struct pam_response *responses;
27 } context_pam2 = {0, 0, 0, NULL};
29 static struct pam_conv conv2 = {
30 do_pam_conversation_kbd_int,
35 auth2_pam(Authctxt *authctxt)
39 if (authctxt->user == NULL)
40 fatal("auth2_pam: internal error: no user");
42 conv2.appdata_ptr = authctxt;
43 do_pam_set_conv(&conv2);
45 dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE,
46 &input_userauth_info_response_pam);
47 retval = (do_pam_authenticate(0) == PAM_SUCCESS);
48 dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL);
54 do_pam_conversation_kbd_int(int num_msg, const struct pam_message **msg,
55 struct pam_response **resp, void *appdata_ptr)
60 context_pam2.finished = 0;
61 context_pam2.num_received = 0;
62 context_pam2.num_expected = 0;
63 context_pam2.prompts = xmalloc(sizeof(int) * num_msg);
64 context_pam2.responses = xmalloc(sizeof(struct pam_response) * num_msg);
65 memset(context_pam2.responses, 0, sizeof(struct pam_response) * num_msg);
68 for (i = 0, context_pam2.num_expected = 0; i < num_msg; i++) {
69 int style = PAM_MSG_MEMBER(msg, i, msg_style);
71 case PAM_PROMPT_ECHO_ON:
72 case PAM_PROMPT_ECHO_OFF:
73 context_pam2.num_expected++;
78 /* Capture all these messages to be sent at once */
79 message_cat(&text, PAM_MSG_MEMBER(msg, i, msg));
84 if (context_pam2.num_expected == 0)
87 packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST);
88 packet_put_cstring(""); /* Name */
89 packet_put_cstring(""); /* Instructions */
90 packet_put_cstring(""); /* Language */
91 packet_put_int(context_pam2.num_expected);
93 for (i = 0, j = 0; i < num_msg; i++) {
94 int style = PAM_MSG_MEMBER(msg, i, msg_style);
96 /* Skip messages which don't need a reply */
97 if (style != PAM_PROMPT_ECHO_ON && style != PAM_PROMPT_ECHO_OFF)
100 context_pam2.prompts[j++] = i;
102 message_cat(&text, PAM_MSG_MEMBER(msg, i, msg));
103 packet_put_cstring(text);
106 packet_put_cstring(PAM_MSG_MEMBER(msg, i, msg));
107 packet_put_char(style == PAM_PROMPT_ECHO_ON);
113 * Grabbing control of execution and spinning until we get what
114 * we want is probably rude, but it seems to work properly, and
115 * the client *should* be in lock-step with us, so the loop should
116 * only be traversed once.
118 while(context_pam2.finished == 0) {
120 dispatch_run(DISPATCH_BLOCK, &done, appdata_ptr);
121 if (context_pam2.finished == 0)
122 debug("extra packet during conversation");
125 if (context_pam2.num_received == context_pam2.num_expected) {
126 *resp = context_pam2.responses;
133 input_userauth_info_response_pam(int type, u_int32_t seqnr, void *ctxt)
135 Authctxt *authctxt = ctxt;
136 unsigned int nresp = 0, rlen = 0, i = 0;
139 if (authctxt == NULL)
140 fatal("input_userauth_info_response_pam: no authentication context");
142 nresp = packet_get_int(); /* Number of responses. */
143 debug("got %d responses", nresp);
146 if (nresp != context_pam2.num_expected)
147 fatal("%s: Received incorrect number of responses "
148 "(expected %d, received %u)", __func__,
149 context_pam2.num_expected, nresp);
152 fatal("%s: too many replies", __func__);
154 for (i = 0; i < nresp; i++) {
155 int j = context_pam2.prompts[i];
157 resp = packet_get_string(&rlen);
158 context_pam2.responses[j].resp_retcode = PAM_SUCCESS;
159 context_pam2.responses[j].resp = xstrdup(resp);
161 context_pam2.num_received++;
164 context_pam2.finished = 1;