Add if_broadcastaddr to struct ifnet to hold the link layer broadcast address.
[dragonfly.git] / crypto / openssh / auth2-pam.c
1 #include "includes.h"
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 $");
5
6 #ifdef USE_PAM
7 #include <security/pam_appl.h>
8
9 #include "ssh.h"
10 #include "ssh2.h"
11 #include "auth.h"
12 #include "auth-pam.h"
13 #include "packet.h"
14 #include "xmalloc.h"
15 #include "dispatch.h"
16 #include "log.h"
17
18 static int do_pam_conversation_kbd_int(int num_msg, 
19     const struct pam_message **msg, struct pam_response **resp, 
20     void *appdata_ptr);
21 void input_userauth_info_response_pam(int type, u_int32_t seqnr, void *ctxt);
22
23 struct {
24         int finished, num_received, num_expected;
25         int *prompts;
26         struct pam_response *responses;
27 } context_pam2 = {0, 0, 0, NULL};
28
29 static struct pam_conv conv2 = {
30         do_pam_conversation_kbd_int,
31         NULL,
32 };
33
34 int
35 auth2_pam(Authctxt *authctxt)
36 {
37         int retval = -1;
38
39         if (authctxt->user == NULL)
40                 fatal("auth2_pam: internal error: no user");
41
42         conv2.appdata_ptr = authctxt;
43         do_pam_set_conv(&conv2);
44
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);
49
50         return retval;
51 }
52
53 static int
54 do_pam_conversation_kbd_int(int num_msg, const struct pam_message **msg,
55     struct pam_response **resp, void *appdata_ptr)
56 {
57         int i, j, done;
58         char *text;
59
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);
66
67         text = NULL;
68         for (i = 0, context_pam2.num_expected = 0; i < num_msg; i++) {
69                 int style = PAM_MSG_MEMBER(msg, i, msg_style);
70                 switch (style) {
71                 case PAM_PROMPT_ECHO_ON:
72                 case PAM_PROMPT_ECHO_OFF:
73                         context_pam2.num_expected++;
74                         break;
75                 case PAM_TEXT_INFO:
76                 case PAM_ERROR_MSG:
77                 default:
78                         /* Capture all these messages to be sent at once */
79                         message_cat(&text, PAM_MSG_MEMBER(msg, i, msg));
80                         break;
81                 }
82         }
83
84         if (context_pam2.num_expected == 0)
85                 return PAM_SUCCESS;
86
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);
92         
93         for (i = 0, j = 0; i < num_msg; i++) {
94                 int style = PAM_MSG_MEMBER(msg, i, msg_style);
95                 
96                 /* Skip messages which don't need a reply */
97                 if (style != PAM_PROMPT_ECHO_ON && style != PAM_PROMPT_ECHO_OFF)
98                         continue;
99                 
100                 context_pam2.prompts[j++] = i;
101                 if (text) {
102                         message_cat(&text, PAM_MSG_MEMBER(msg, i, msg));
103                         packet_put_cstring(text);
104                         text = NULL;
105                 } else
106                         packet_put_cstring(PAM_MSG_MEMBER(msg, i, msg));
107                 packet_put_char(style == PAM_PROMPT_ECHO_ON);
108         }
109         packet_send();
110         packet_write_wait();
111
112         /*
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.
117          */
118         while(context_pam2.finished == 0) {
119                 done = 1;
120                 dispatch_run(DISPATCH_BLOCK, &done, appdata_ptr);
121                 if (context_pam2.finished == 0)
122                         debug("extra packet during conversation");
123         }
124
125         if (context_pam2.num_received == context_pam2.num_expected) {
126                 *resp = context_pam2.responses;
127                 return PAM_SUCCESS;
128         } else
129                 return PAM_CONV_ERR;
130 }
131
132 void
133 input_userauth_info_response_pam(int type, u_int32_t seqnr, void *ctxt)
134 {
135         Authctxt *authctxt = ctxt;
136         unsigned int nresp = 0, rlen = 0, i = 0;
137         char *resp;
138
139         if (authctxt == NULL)
140                 fatal("input_userauth_info_response_pam: no authentication context");
141
142         nresp = packet_get_int();       /* Number of responses. */
143         debug("got %d responses", nresp);
144
145
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);
150
151         if (nresp > 100)
152                 fatal("%s: too many replies", __func__);
153
154         for (i = 0; i < nresp; i++) {
155                 int j = context_pam2.prompts[i];
156
157                 resp = packet_get_string(&rlen);
158                 context_pam2.responses[j].resp_retcode = PAM_SUCCESS;
159                 context_pam2.responses[j].resp = xstrdup(resp);
160                 xfree(resp);
161                 context_pam2.num_received++;
162         }
163
164         context_pam2.finished = 1;
165
166         packet_check_eom();
167 }
168 #endif