diff options
author | Colin Watson <cjwatson@debian.org> | 2019-06-05 06:41:44 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2019-06-05 06:41:44 +0100 |
commit | 102062f825fb26a74295a1c089c00c4c4c76b68a (patch) | |
tree | 3db66bc8c8483cce66516dff36f6ef56065143d9 /auth2.c | |
parent | 3d246f10429fc9a37b98eabef94fe8dc7c61002b (diff) | |
parent | fd0fa130ecf06d7d092932adcd5d77f1549bfc8d (diff) |
Import openssh_8.0p1.orig.tar.gz
Diffstat (limited to 'auth2.c')
-rw-r--r-- | auth2.c | 131 |
1 files changed, 79 insertions, 52 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth2.c,v 1.149 2018/07/11 18:53:29 markus Exp $ */ | 1 | /* $OpenBSD: auth2.c,v 1.155 2019/03/25 22:34:52 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -35,6 +35,7 @@ | |||
35 | #include <stdarg.h> | 35 | #include <stdarg.h> |
36 | #include <string.h> | 36 | #include <string.h> |
37 | #include <unistd.h> | 37 | #include <unistd.h> |
38 | #include <time.h> | ||
38 | 39 | ||
39 | #include "atomicio.h" | 40 | #include "atomicio.h" |
40 | #include "xmalloc.h" | 41 | #include "xmalloc.h" |
@@ -137,18 +138,21 @@ auth2_read_banner(void) | |||
137 | return (banner); | 138 | return (banner); |
138 | } | 139 | } |
139 | 140 | ||
140 | void | 141 | static void |
141 | userauth_send_banner(const char *msg) | 142 | userauth_send_banner(struct ssh *ssh, const char *msg) |
142 | { | 143 | { |
143 | packet_start(SSH2_MSG_USERAUTH_BANNER); | 144 | int r; |
144 | packet_put_cstring(msg); | 145 | |
145 | packet_put_cstring(""); /* language, unused */ | 146 | if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_BANNER)) != 0 || |
146 | packet_send(); | 147 | (r = sshpkt_put_cstring(ssh, msg)) != 0 || |
148 | (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language, unused */ | ||
149 | (r = sshpkt_send(ssh)) != 0) | ||
150 | fatal("%s: %s", __func__, ssh_err(r)); | ||
147 | debug("%s: sent", __func__); | 151 | debug("%s: sent", __func__); |
148 | } | 152 | } |
149 | 153 | ||
150 | static void | 154 | static void |
151 | userauth_banner(void) | 155 | userauth_banner(struct ssh *ssh) |
152 | { | 156 | { |
153 | char *banner = NULL; | 157 | char *banner = NULL; |
154 | 158 | ||
@@ -157,7 +161,7 @@ userauth_banner(void) | |||
157 | 161 | ||
158 | if ((banner = PRIVSEP(auth2_read_banner())) == NULL) | 162 | if ((banner = PRIVSEP(auth2_read_banner())) == NULL) |
159 | goto done; | 163 | goto done; |
160 | userauth_send_banner(banner); | 164 | userauth_send_banner(ssh, banner); |
161 | 165 | ||
162 | done: | 166 | done: |
163 | free(banner); | 167 | free(banner); |
@@ -167,10 +171,10 @@ done: | |||
167 | * loop until authctxt->success == TRUE | 171 | * loop until authctxt->success == TRUE |
168 | */ | 172 | */ |
169 | void | 173 | void |
170 | do_authentication2(Authctxt *authctxt) | 174 | do_authentication2(struct ssh *ssh) |
171 | { | 175 | { |
172 | struct ssh *ssh = active_state; /* XXX */ | 176 | Authctxt *authctxt = ssh->authctxt; |
173 | ssh->authctxt = authctxt; /* XXX move to caller */ | 177 | |
174 | ssh_dispatch_init(ssh, &dispatch_protocol_error); | 178 | ssh_dispatch_init(ssh, &dispatch_protocol_error); |
175 | ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_REQUEST, &input_service_request); | 179 | ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_REQUEST, &input_service_request); |
176 | ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt->success); | 180 | ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt->success); |
@@ -182,10 +186,12 @@ static int | |||
182 | input_service_request(int type, u_int32_t seq, struct ssh *ssh) | 186 | input_service_request(int type, u_int32_t seq, struct ssh *ssh) |
183 | { | 187 | { |
184 | Authctxt *authctxt = ssh->authctxt; | 188 | Authctxt *authctxt = ssh->authctxt; |
185 | u_int len; | 189 | char *service = NULL; |
186 | int acceptit = 0; | 190 | int r, acceptit = 0; |
187 | char *service = packet_get_cstring(&len); | 191 | |
188 | packet_check_eom(); | 192 | if ((r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 || |
193 | (r = sshpkt_get_end(ssh)) != 0) | ||
194 | goto out; | ||
189 | 195 | ||
190 | if (authctxt == NULL) | 196 | if (authctxt == NULL) |
191 | fatal("input_service_request: no authctxt"); | 197 | fatal("input_service_request: no authctxt"); |
@@ -194,20 +200,24 @@ input_service_request(int type, u_int32_t seq, struct ssh *ssh) | |||
194 | if (!authctxt->success) { | 200 | if (!authctxt->success) { |
195 | acceptit = 1; | 201 | acceptit = 1; |
196 | /* now we can handle user-auth requests */ | 202 | /* now we can handle user-auth requests */ |
197 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); | 203 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, |
204 | &input_userauth_request); | ||
198 | } | 205 | } |
199 | } | 206 | } |
200 | /* XXX all other service requests are denied */ | 207 | /* XXX all other service requests are denied */ |
201 | 208 | ||
202 | if (acceptit) { | 209 | if (acceptit) { |
203 | packet_start(SSH2_MSG_SERVICE_ACCEPT); | 210 | if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_ACCEPT)) != 0 || |
204 | packet_put_cstring(service); | 211 | (r = sshpkt_put_cstring(ssh, service)) != 0 || |
205 | packet_send(); | 212 | (r = sshpkt_send(ssh)) != 0 || |
206 | packet_write_wait(); | 213 | (r = ssh_packet_write_wait(ssh)) != 0) |
214 | goto out; | ||
207 | } else { | 215 | } else { |
208 | debug("bad service request %s", service); | 216 | debug("bad service request %s", service); |
209 | packet_disconnect("bad service request %s", service); | 217 | ssh_packet_disconnect(ssh, "bad service request %s", service); |
210 | } | 218 | } |
219 | r = 0; | ||
220 | out: | ||
211 | free(service); | 221 | free(service); |
212 | return 0; | 222 | return 0; |
213 | } | 223 | } |
@@ -255,16 +265,17 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) | |||
255 | { | 265 | { |
256 | Authctxt *authctxt = ssh->authctxt; | 266 | Authctxt *authctxt = ssh->authctxt; |
257 | Authmethod *m = NULL; | 267 | Authmethod *m = NULL; |
258 | char *user, *service, *method, *style = NULL; | 268 | char *user = NULL, *service = NULL, *method = NULL, *style = NULL; |
259 | int authenticated = 0; | 269 | int r, authenticated = 0; |
260 | double tstart = monotime_double(); | 270 | double tstart = monotime_double(); |
261 | 271 | ||
262 | if (authctxt == NULL) | 272 | if (authctxt == NULL) |
263 | fatal("input_userauth_request: no authctxt"); | 273 | fatal("input_userauth_request: no authctxt"); |
264 | 274 | ||
265 | user = packet_get_cstring(NULL); | 275 | if ((r = sshpkt_get_cstring(ssh, &user, NULL)) != 0 || |
266 | service = packet_get_cstring(NULL); | 276 | (r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 || |
267 | method = packet_get_cstring(NULL); | 277 | (r = sshpkt_get_cstring(ssh, &method, NULL)) != 0) |
278 | goto out; | ||
268 | debug("userauth-request for user %s service %s method %s", user, service, method); | 279 | debug("userauth-request for user %s service %s method %s", user, service, method); |
269 | debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); | 280 | debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); |
270 | 281 | ||
@@ -273,7 +284,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) | |||
273 | 284 | ||
274 | if (authctxt->attempt++ == 0) { | 285 | if (authctxt->attempt++ == 0) { |
275 | /* setup auth context */ | 286 | /* setup auth context */ |
276 | authctxt->pw = PRIVSEP(getpwnamallow(user)); | 287 | authctxt->pw = PRIVSEP(getpwnamallow(ssh, user)); |
277 | authctxt->user = xstrdup(user); | 288 | authctxt->user = xstrdup(user); |
278 | if (authctxt->pw && strcmp(service, "ssh-connection")==0) { | 289 | if (authctxt->pw && strcmp(service, "ssh-connection")==0) { |
279 | authctxt->valid = 1; | 290 | authctxt->valid = 1; |
@@ -283,12 +294,12 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) | |||
283 | /* Invalid user, fake password information */ | 294 | /* Invalid user, fake password information */ |
284 | authctxt->pw = fakepw(); | 295 | authctxt->pw = fakepw(); |
285 | #ifdef SSH_AUDIT_EVENTS | 296 | #ifdef SSH_AUDIT_EVENTS |
286 | PRIVSEP(audit_event(SSH_INVALID_USER)); | 297 | PRIVSEP(audit_event(ssh, SSH_INVALID_USER)); |
287 | #endif | 298 | #endif |
288 | } | 299 | } |
289 | #ifdef USE_PAM | 300 | #ifdef USE_PAM |
290 | if (options.use_pam) | 301 | if (options.use_pam) |
291 | PRIVSEP(start_pam(authctxt)); | 302 | PRIVSEP(start_pam(ssh)); |
292 | #endif | 303 | #endif |
293 | ssh_packet_set_log_preamble(ssh, "%suser %s", | 304 | ssh_packet_set_log_preamble(ssh, "%suser %s", |
294 | authctxt->valid ? "authenticating " : "invalid ", user); | 305 | authctxt->valid ? "authenticating " : "invalid ", user); |
@@ -298,13 +309,14 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) | |||
298 | authctxt->style = style ? xstrdup(style) : NULL; | 309 | authctxt->style = style ? xstrdup(style) : NULL; |
299 | if (use_privsep) | 310 | if (use_privsep) |
300 | mm_inform_authserv(service, style); | 311 | mm_inform_authserv(service, style); |
301 | userauth_banner(); | 312 | userauth_banner(ssh); |
302 | if (auth2_setup_methods_lists(authctxt) != 0) | 313 | if (auth2_setup_methods_lists(authctxt) != 0) |
303 | packet_disconnect("no authentication methods enabled"); | 314 | ssh_packet_disconnect(ssh, |
315 | "no authentication methods enabled"); | ||
304 | } else if (strcmp(user, authctxt->user) != 0 || | 316 | } else if (strcmp(user, authctxt->user) != 0 || |
305 | strcmp(service, authctxt->service) != 0) { | 317 | strcmp(service, authctxt->service) != 0) { |
306 | packet_disconnect("Change of username or service not allowed: " | 318 | ssh_packet_disconnect(ssh, "Change of username or service " |
307 | "(%s,%s) -> (%s,%s)", | 319 | "not allowed: (%s,%s) -> (%s,%s)", |
308 | authctxt->user, authctxt->service, user, service); | 320 | authctxt->user, authctxt->service, user, service); |
309 | } | 321 | } |
310 | /* reset state */ | 322 | /* reset state */ |
@@ -330,11 +342,12 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) | |||
330 | ensure_minimum_time_since(tstart, | 342 | ensure_minimum_time_since(tstart, |
331 | user_specific_delay(authctxt->user)); | 343 | user_specific_delay(authctxt->user)); |
332 | userauth_finish(ssh, authenticated, method, NULL); | 344 | userauth_finish(ssh, authenticated, method, NULL); |
333 | 345 | r = 0; | |
346 | out: | ||
334 | free(service); | 347 | free(service); |
335 | free(user); | 348 | free(user); |
336 | free(method); | 349 | free(method); |
337 | return 0; | 350 | return r; |
338 | } | 351 | } |
339 | 352 | ||
340 | void | 353 | void |
@@ -343,7 +356,7 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, | |||
343 | { | 356 | { |
344 | Authctxt *authctxt = ssh->authctxt; | 357 | Authctxt *authctxt = ssh->authctxt; |
345 | char *methods; | 358 | char *methods; |
346 | int partial = 0; | 359 | int r, partial = 0; |
347 | 360 | ||
348 | if (!authctxt->valid && authenticated) | 361 | if (!authctxt->valid && authenticated) |
349 | fatal("INTERNAL ERROR: authenticated invalid user %s", | 362 | fatal("INTERNAL ERROR: authenticated invalid user %s", |
@@ -356,7 +369,7 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, | |||
356 | !auth_root_allowed(ssh, method)) { | 369 | !auth_root_allowed(ssh, method)) { |
357 | authenticated = 0; | 370 | authenticated = 0; |
358 | #ifdef SSH_AUDIT_EVENTS | 371 | #ifdef SSH_AUDIT_EVENTS |
359 | PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED)); | 372 | PRIVSEP(audit_event(ssh, SSH_LOGIN_ROOT_DENIED)); |
360 | #endif | 373 | #endif |
361 | } | 374 | } |
362 | 375 | ||
@@ -368,7 +381,7 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, | |||
368 | } | 381 | } |
369 | 382 | ||
370 | /* Log before sending the reply */ | 383 | /* Log before sending the reply */ |
371 | auth_log(authctxt, authenticated, partial, method, submethod); | 384 | auth_log(ssh, authenticated, partial, method, submethod); |
372 | 385 | ||
373 | /* Update information exposed to session */ | 386 | /* Update information exposed to session */ |
374 | if (authenticated || partial) | 387 | if (authenticated || partial) |
@@ -387,8 +400,11 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, | |||
387 | if ((r = sshbuf_put(loginmsg, "\0", 1)) != 0) | 400 | if ((r = sshbuf_put(loginmsg, "\0", 1)) != 0) |
388 | fatal("%s: buffer error: %s", | 401 | fatal("%s: buffer error: %s", |
389 | __func__, ssh_err(r)); | 402 | __func__, ssh_err(r)); |
390 | userauth_send_banner(sshbuf_ptr(loginmsg)); | 403 | userauth_send_banner(ssh, sshbuf_ptr(loginmsg)); |
391 | packet_write_wait(); | 404 | if ((r = ssh_packet_write_wait(ssh)) != 0) { |
405 | sshpkt_fatal(ssh, r, | ||
406 | "%s: send PAM banner", __func__); | ||
407 | } | ||
392 | } | 408 | } |
393 | fatal("Access denied for user %s by PAM account " | 409 | fatal("Access denied for user %s by PAM account " |
394 | "configuration", authctxt->user); | 410 | "configuration", authctxt->user); |
@@ -398,10 +414,12 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, | |||
398 | 414 | ||
399 | if (authenticated == 1) { | 415 | if (authenticated == 1) { |
400 | /* turn off userauth */ | 416 | /* turn off userauth */ |
401 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); | 417 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, |
402 | packet_start(SSH2_MSG_USERAUTH_SUCCESS); | 418 | &dispatch_protocol_ignore); |
403 | packet_send(); | 419 | if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_SUCCESS)) != 0 || |
404 | packet_write_wait(); | 420 | (r = sshpkt_send(ssh)) != 0 || |
421 | (r = ssh_packet_write_wait(ssh)) != 0) | ||
422 | fatal("%s: %s", __func__, ssh_err(r)); | ||
405 | /* now we can break out */ | 423 | /* now we can break out */ |
406 | authctxt->success = 1; | 424 | authctxt->success = 1; |
407 | ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); | 425 | ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); |
@@ -412,18 +430,19 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, | |||
412 | authctxt->failures++; | 430 | authctxt->failures++; |
413 | if (authctxt->failures >= options.max_authtries) { | 431 | if (authctxt->failures >= options.max_authtries) { |
414 | #ifdef SSH_AUDIT_EVENTS | 432 | #ifdef SSH_AUDIT_EVENTS |
415 | PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); | 433 | PRIVSEP(audit_event(ssh, SSH_LOGIN_EXCEED_MAXTRIES)); |
416 | #endif | 434 | #endif |
417 | auth_maxtries_exceeded(authctxt); | 435 | auth_maxtries_exceeded(ssh); |
418 | } | 436 | } |
419 | methods = authmethods_get(authctxt); | 437 | methods = authmethods_get(authctxt); |
420 | debug3("%s: failure partial=%d next methods=\"%s\"", __func__, | 438 | debug3("%s: failure partial=%d next methods=\"%s\"", __func__, |
421 | partial, methods); | 439 | partial, methods); |
422 | packet_start(SSH2_MSG_USERAUTH_FAILURE); | 440 | if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_FAILURE)) != 0 || |
423 | packet_put_cstring(methods); | 441 | (r = sshpkt_put_cstring(ssh, methods)) != 0 || |
424 | packet_put_char(partial); | 442 | (r = sshpkt_put_u8(ssh, partial)) != 0 || |
425 | packet_send(); | 443 | (r = sshpkt_send(ssh)) != 0 || |
426 | packet_write_wait(); | 444 | (r = ssh_packet_write_wait(ssh)) != 0) |
445 | fatal("%s: %s", __func__, ssh_err(r)); | ||
427 | free(methods); | 446 | free(methods); |
428 | } | 447 | } |
429 | } | 448 | } |
@@ -558,6 +577,14 @@ auth2_setup_methods_lists(Authctxt *authctxt) | |||
558 | { | 577 | { |
559 | u_int i; | 578 | u_int i; |
560 | 579 | ||
580 | /* First, normalise away the "any" pseudo-method */ | ||
581 | if (options.num_auth_methods == 1 && | ||
582 | strcmp(options.auth_methods[0], "any") == 0) { | ||
583 | free(options.auth_methods[0]); | ||
584 | options.auth_methods[0] = NULL; | ||
585 | options.num_auth_methods = 0; | ||
586 | } | ||
587 | |||
561 | if (options.num_auth_methods == 0) | 588 | if (options.num_auth_methods == 0) |
562 | return 0; | 589 | return 0; |
563 | debug3("%s: checking methods", __func__); | 590 | debug3("%s: checking methods", __func__); |