1 /*
2 * Packet protocol layer for the server side of the SSH-2 userauth
3 * protocol (RFC 4252).
4 */
5
6 #include <assert.h>
7
8 #include "putty.h"
9 #include "ssh.h"
10 #include "sshbpp.h"
11 #include "sshppl.h"
12 #include "sshcr.h"
13 #include "sshserver.h"
14
15 #ifndef NO_GSSAPI
16 #include "sshgssc.h"
17 #include "sshgss.h"
18 #endif
19
20 struct ssh2_userauth_server_state {
21 int crState;
22
23 PacketProtocolLayer *transport_layer, *successor_layer;
24 ptrlen session_id;
25
26 AuthPolicy *authpolicy;
27 const SshServerConfig *ssc;
28
29 ptrlen username, service, method;
30 unsigned methods, this_method;
31 bool partial_success;
32
33 AuthKbdInt *aki;
34
35 PacketProtocolLayer ppl;
36 };
37
38 static void ssh2_userauth_server_free(PacketProtocolLayer *);
39 static void ssh2_userauth_server_process_queue(PacketProtocolLayer *);
40
41 static const PacketProtocolLayerVtable ssh2_userauth_server_vtable = {
42 .free = ssh2_userauth_server_free,
43 .process_queue = ssh2_userauth_server_process_queue,
44 .queued_data_size = ssh_ppl_default_queued_data_size,
45 .name = "ssh-userauth",
46 /* other methods are NULL */
47 };
48
free_auth_kbdint(AuthKbdInt * aki)49 static void free_auth_kbdint(AuthKbdInt *aki)
50 {
51 int i;
52
53 if (!aki)
54 return;
55
56 sfree(aki->title);
57 sfree(aki->instruction);
58 for (i = 0; i < aki->nprompts; i++)
59 sfree(aki->prompts[i].prompt);
60 sfree(aki->prompts);
61 sfree(aki);
62 }
63
ssh2_userauth_server_new(PacketProtocolLayer * successor_layer,AuthPolicy * authpolicy,const SshServerConfig * ssc)64 PacketProtocolLayer *ssh2_userauth_server_new(
65 PacketProtocolLayer *successor_layer, AuthPolicy *authpolicy,
66 const SshServerConfig *ssc)
67 {
68 struct ssh2_userauth_server_state *s =
69 snew(struct ssh2_userauth_server_state);
70 memset(s, 0, sizeof(*s));
71 s->ppl.vt = &ssh2_userauth_server_vtable;
72
73 s->successor_layer = successor_layer;
74 s->authpolicy = authpolicy;
75 s->ssc = ssc;
76
77 return &s->ppl;
78 }
79
ssh2_userauth_server_set_transport_layer(PacketProtocolLayer * userauth,PacketProtocolLayer * transport)80 void ssh2_userauth_server_set_transport_layer(PacketProtocolLayer *userauth,
81 PacketProtocolLayer *transport)
82 {
83 struct ssh2_userauth_server_state *s =
84 container_of(userauth, struct ssh2_userauth_server_state, ppl);
85 s->transport_layer = transport;
86 }
87
ssh2_userauth_server_free(PacketProtocolLayer * ppl)88 static void ssh2_userauth_server_free(PacketProtocolLayer *ppl)
89 {
90 struct ssh2_userauth_server_state *s =
91 container_of(ppl, struct ssh2_userauth_server_state, ppl);
92
93 if (s->successor_layer)
94 ssh_ppl_free(s->successor_layer);
95
96 free_auth_kbdint(s->aki);
97
98 sfree(s);
99 }
100
ssh2_userauth_server_pop(struct ssh2_userauth_server_state * s)101 static PktIn *ssh2_userauth_server_pop(struct ssh2_userauth_server_state *s)
102 {
103 return pq_pop(s->ppl.in_pq);
104 }
105
ssh2_userauth_server_add_session_id(struct ssh2_userauth_server_state * s,strbuf * sigdata)106 static void ssh2_userauth_server_add_session_id(
107 struct ssh2_userauth_server_state *s, strbuf *sigdata)
108 {
109 if (s->ppl.remote_bugs & BUG_SSH2_PK_SESSIONID) {
110 put_datapl(sigdata, s->session_id);
111 } else {
112 put_stringpl(sigdata, s->session_id);
113 }
114 }
115
ssh2_userauth_server_process_queue(PacketProtocolLayer * ppl)116 static void ssh2_userauth_server_process_queue(PacketProtocolLayer *ppl)
117 {
118 struct ssh2_userauth_server_state *s =
119 container_of(ppl, struct ssh2_userauth_server_state, ppl);
120 PktIn *pktin;
121 PktOut *pktout;
122
123 crBegin(s->crState);
124
125 s->session_id = ssh2_transport_get_session_id(s->transport_layer);
126
127 if (s->ssc->banner.ptr) {
128 pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_USERAUTH_BANNER);
129 put_stringpl(pktout, s->ssc->banner);
130 put_stringz(pktout, ""); /* language tag */
131 pq_push(s->ppl.out_pq, pktout);
132 }
133
134 while (1) {
135 crMaybeWaitUntilV((pktin = ssh2_userauth_server_pop(s)) != NULL);
136 if (pktin->type != SSH2_MSG_USERAUTH_REQUEST) {
137 ssh_proto_error(s->ppl.ssh, "Received unexpected packet when "
138 "expecting USERAUTH_REQUEST, type %d (%s)",
139 pktin->type,
140 ssh2_pkt_type(s->ppl.bpp->pls->kctx,
141 s->ppl.bpp->pls->actx, pktin->type));
142 return;
143 }
144
145 s->username = get_string(pktin);
146 s->service = get_string(pktin);
147 s->method = get_string(pktin);
148
149 if (!ptrlen_eq_string(s->service, s->successor_layer->vt->name)) {
150 /*
151 * Unconditionally reject authentication for any service
152 * other than the one we're going to hand over to.
153 */
154 pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_USERAUTH_FAILURE);
155 put_stringz(pktout, "");
156 put_bool(pktout, false);
157 pq_push(s->ppl.out_pq, pktout);
158 continue;
159 }
160
161 s->methods = auth_methods(s->authpolicy);
162 s->partial_success = false;
163
164 if (ptrlen_eq_string(s->method, "none")) {
165 s->this_method = AUTHMETHOD_NONE;
166 if (!(s->methods & s->this_method))
167 goto failure;
168
169 if (!auth_none(s->authpolicy, s->username))
170 goto failure;
171 } else if (ptrlen_eq_string(s->method, "password")) {
172 bool changing;
173 ptrlen password, new_password, *new_password_ptr;
174
175 s->this_method = AUTHMETHOD_PASSWORD;
176 if (!(s->methods & s->this_method))
177 goto failure;
178
179 changing = get_bool(pktin);
180 password = get_string(pktin);
181
182 if (changing) {
183 new_password = get_string(pktin);
184 new_password_ptr = &new_password;
185 } else {
186 new_password_ptr = NULL;
187 }
188
189 int result = auth_password(s->authpolicy, s->username,
190 password, new_password_ptr);
191 if (result == 2) {
192 pktout = ssh_bpp_new_pktout(
193 s->ppl.bpp, SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ);
194 put_stringz(pktout, "Please change your password");
195 put_stringz(pktout, ""); /* language tag */
196 pq_push(s->ppl.out_pq, pktout);
197 continue; /* skip USERAUTH_{SUCCESS,FAILURE} epilogue */
198 } else if (result != 1) {
199 goto failure;
200 }
201 } else if (ptrlen_eq_string(s->method, "publickey")) {
202 bool has_signature, success, send_pk_ok, key_really_ok;
203 ptrlen algorithm, blob, signature;
204 const ssh_keyalg *keyalg;
205 ssh_key *key;
206 strbuf *sigdata;
207
208 s->this_method = AUTHMETHOD_PUBLICKEY;
209 if (!(s->methods & s->this_method))
210 goto failure;
211
212 has_signature = get_bool(pktin);
213 algorithm = get_string(pktin);
214 blob = get_string(pktin);
215
216 key_really_ok = auth_publickey(s->authpolicy, s->username, blob);
217 send_pk_ok = key_really_ok ||
218 s->ssc->stunt_pretend_to_accept_any_pubkey;
219
220 if (!has_signature) {
221 if (!send_pk_ok)
222 goto failure;
223
224 pktout = ssh_bpp_new_pktout(
225 s->ppl.bpp, SSH2_MSG_USERAUTH_PK_OK);
226 put_stringpl(pktout, algorithm);
227 put_stringpl(pktout, blob);
228 pq_push(s->ppl.out_pq, pktout);
229 continue; /* skip USERAUTH_{SUCCESS,FAILURE} epilogue */
230 }
231
232 if (!key_really_ok)
233 goto failure;
234
235 keyalg = find_pubkey_alg_len(algorithm);
236 if (!keyalg)
237 goto failure;
238 key = ssh_key_new_pub(keyalg, blob);
239 if (!key)
240 goto failure;
241
242 sigdata = strbuf_new();
243 ssh2_userauth_server_add_session_id(s, sigdata);
244 put_byte(sigdata, SSH2_MSG_USERAUTH_REQUEST);
245 put_stringpl(sigdata, s->username);
246 put_stringpl(sigdata, s->service);
247 put_stringpl(sigdata, s->method);
248 put_bool(sigdata, has_signature);
249 put_stringpl(sigdata, algorithm);
250 put_stringpl(sigdata, blob);
251
252 signature = get_string(pktin);
253 success = ssh_key_verify(key, signature,
254 ptrlen_from_strbuf(sigdata));
255 ssh_key_free(key);
256 strbuf_free(sigdata);
257
258 if (!success)
259 goto failure;
260 } else if (ptrlen_eq_string(s->method, "keyboard-interactive")) {
261 int i, ok;
262 unsigned n;
263
264 s->this_method = AUTHMETHOD_KBDINT;
265 if (!(s->methods & s->this_method))
266 goto failure;
267
268 do {
269 s->aki = auth_kbdint_prompts(s->authpolicy, s->username);
270 if (!s->aki)
271 goto failure;
272
273 pktout = ssh_bpp_new_pktout(
274 s->ppl.bpp, SSH2_MSG_USERAUTH_INFO_REQUEST);
275 put_stringz(pktout, s->aki->title);
276 put_stringz(pktout, s->aki->instruction);
277 put_stringz(pktout, ""); /* language tag */
278 put_uint32(pktout, s->aki->nprompts);
279 for (i = 0; i < s->aki->nprompts; i++) {
280 put_stringz(pktout, s->aki->prompts[i].prompt);
281 put_bool(pktout, s->aki->prompts[i].echo);
282 }
283 pq_push(s->ppl.out_pq, pktout);
284
285 crMaybeWaitUntilV(
286 (pktin = ssh2_userauth_server_pop(s)) != NULL);
287 if (pktin->type != SSH2_MSG_USERAUTH_INFO_RESPONSE) {
288 ssh_proto_error(
289 s->ppl.ssh, "Received unexpected packet when "
290 "expecting USERAUTH_INFO_RESPONSE, type %d (%s)",
291 pktin->type,
292 ssh2_pkt_type(s->ppl.bpp->pls->kctx,
293 s->ppl.bpp->pls->actx, pktin->type));
294 return;
295 }
296
297 n = get_uint32(pktin);
298 if (n != s->aki->nprompts) {
299 ssh_proto_error(
300 s->ppl.ssh, "Received %u keyboard-interactive "
301 "responses after sending %u prompts",
302 n, s->aki->nprompts);
303 return;
304 }
305
306 {
307 ptrlen *responses = snewn(s->aki->nprompts, ptrlen);
308 for (i = 0; i < s->aki->nprompts; i++)
309 responses[i] = get_string(pktin);
310 ok = auth_kbdint_responses(s->authpolicy, responses);
311 sfree(responses);
312 }
313
314 free_auth_kbdint(s->aki);
315 s->aki = NULL;
316 } while (ok == 0);
317
318 if (ok <= 0)
319 goto failure;
320 } else {
321 goto failure;
322 }
323
324 /*
325 * If we get here, we've successfully completed this
326 * authentication step.
327 */
328 if (auth_successful(s->authpolicy, s->username, s->this_method)) {
329 /*
330 * ... and it was the last one, so we're completely done.
331 */
332 pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_USERAUTH_SUCCESS);
333 pq_push(s->ppl.out_pq, pktout);
334 break;
335 } else {
336 /*
337 * ... but another is required, so fall through to
338 * generation of USERAUTH_FAILURE, having first refreshed
339 * the bit mask of available methods.
340 */
341 s->methods = auth_methods(s->authpolicy);
342 }
343 s->partial_success = true;
344
345 failure:
346 pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_USERAUTH_FAILURE);
347 {
348 strbuf *list = strbuf_new();
349 if (s->methods & AUTHMETHOD_NONE)
350 add_to_commasep(list, "none");
351 if (s->methods & AUTHMETHOD_PASSWORD)
352 add_to_commasep(list, "password");
353 if (s->methods & AUTHMETHOD_PUBLICKEY)
354 add_to_commasep(list, "publickey");
355 if (s->methods & AUTHMETHOD_KBDINT)
356 add_to_commasep(list, "keyboard-interactive");
357 put_stringsb(pktout, list);
358 }
359 put_bool(pktout, s->partial_success);
360 pq_push(s->ppl.out_pq, pktout);
361 }
362
363 /*
364 * Finally, hand over to our successor layer, and return
365 * immediately without reaching the crFinishV: ssh_ppl_replace
366 * will have freed us, so crFinishV's zeroing-out of crState would
367 * be a use-after-free bug.
368 */
369 {
370 PacketProtocolLayer *successor = s->successor_layer;
371 s->successor_layer = NULL; /* avoid freeing it ourself */
372 ssh_ppl_replace(&s->ppl, successor);
373 return; /* we've just freed s, so avoid even touching s->crState */
374 }
375
376 crFinishV;
377 }
378