From 54fd7cf2db5327f304825e0f9aaf9af5a490a75f Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Mon, 17 Sep 2007 12:04:08 +1000 Subject: - djm@cvs.openbsd.org 2007/09/04 03:21:03 [clientloop.c monitor.c monitor_fdpass.c monitor_fdpass.h] [monitor_wrap.c ssh.c] make file descriptor passing code return an error rather than call fatal() when it encounters problems, and use this to make session multiplexing masters survive slaves failing to pass all stdio FDs; ok markus@ --- monitor.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'monitor.c') diff --git a/monitor.c b/monitor.c index 08c7ea3cb..1fe1fb56f 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.91 2007/05/17 20:52:13 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.92 2007/09/04 03:21:03 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1314,8 +1314,9 @@ mm_answer_pty(int sock, Buffer *m) mm_request_send(sock, MONITOR_ANS_PTY, m); - mm_send_fd(sock, s->ptyfd); - mm_send_fd(sock, s->ttyfd); + if (mm_send_fd(sock, s->ptyfd) == -1 || + mm_send_fd(sock, s->ttyfd) == -1) + fatal("%s: send fds failed", __func__); /* make sure nothing uses fd 0 */ if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0) -- cgit v1.2.3 From 733124b5dd735cdd12be7dd7002a22f5d3896e29 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 26 Oct 2007 14:25:12 +1000 Subject: - djm@cvs.openbsd.org 2007/09/21 08:15:29 [auth-bsdauth.c auth-passwd.c auth.c auth.h auth1.c auth2-chall.c] [monitor.c monitor_wrap.c] unifdef -DBSD_AUTH unifdef -USKEY These options have been in use for some years; ok markus@ "no objection" millert@ (NB. RCD ID sync only for portable) --- ChangeLog | 10 +++++++++- auth-bsdauth.c | 2 +- auth-passwd.c | 2 +- auth.c | 2 +- auth.h | 2 +- auth1.c | 2 +- auth2-chall.c | 2 +- monitor.c | 2 +- monitor_wrap.c | 2 +- 9 files changed, 17 insertions(+), 9 deletions(-) (limited to 'monitor.c') diff --git a/ChangeLog b/ChangeLog index cd781c264..46729e70a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,14 @@ [ssh_config.5] document KbdInteractiveAuthentication in ssh_config.5; patch from dkg AT fifthhorseman.net + - djm@cvs.openbsd.org 2007/09/21 08:15:29 + [auth-bsdauth.c auth-passwd.c auth.c auth.h auth1.c auth2-chall.c] + [monitor.c monitor_wrap.c] + unifdef -DBSD_AUTH + unifdef -USKEY + These options have been in use for some years; + ok markus@ "no objection" millert@ + (NB. RCD ID sync only for portable) 20070927 - (dtucker) [configure.ac atomicio.c] Fall back to including if @@ -3279,4 +3287,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4762 2007/10/26 04:24:48 djm Exp $ +$Id: ChangeLog,v 1.4763 2007/10/26 04:25:12 djm Exp $ diff --git a/auth-bsdauth.c b/auth-bsdauth.c index 37d527d11..0b3262b49 100644 --- a/auth-bsdauth.c +++ b/auth-bsdauth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-bsdauth.c,v 1.10 2006/08/03 03:34:41 deraadt Exp $ */ +/* $OpenBSD: auth-bsdauth.c,v 1.11 2007/09/21 08:15:29 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * diff --git a/auth-passwd.c b/auth-passwd.c index 6b67a131b..bdfced023 100644 --- a/auth-passwd.c +++ b/auth-passwd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-passwd.c,v 1.42 2007/08/23 02:55:51 djm Exp $ */ +/* $OpenBSD: auth-passwd.c,v 1.43 2007/09/21 08:15:29 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland diff --git a/auth.c b/auth.c index 6823330a3..f94c7d1d5 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.77 2007/08/23 02:55:51 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.78 2007/09/21 08:15:29 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * diff --git a/auth.h b/auth.h index 1816eaaae..f752c1220 100644 --- a/auth.h +++ b/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.59 2007/08/23 03:06:10 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.60 2007/09/21 08:15:29 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. diff --git a/auth1.c b/auth1.c index b9d6b1115..c17cc9133 100644 --- a/auth1.c +++ b/auth1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth1.c,v 1.70 2006/08/03 03:34:41 deraadt Exp $ */ +/* $OpenBSD: auth1.c,v 1.71 2007/09/21 08:15:29 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved diff --git a/auth2-chall.c b/auth2-chall.c index 51059c2bd..d816578c6 100644 --- a/auth2-chall.c +++ b/auth2-chall.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-chall.c,v 1.32 2007/01/03 03:01:40 stevesk Exp $ */ +/* $OpenBSD: auth2-chall.c,v 1.33 2007/09/21 08:15:29 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Per Allansson. All rights reserved. diff --git a/monitor.c b/monitor.c index 1fe1fb56f..7996d5a14 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.92 2007/09/04 03:21:03 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.93 2007/09/21 08:15:29 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl diff --git a/monitor_wrap.c b/monitor_wrap.c index 36154be4d..7ac845296 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.58 2007/09/04 03:21:03 djm Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.59 2007/09/21 08:15:29 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl -- cgit v1.2.3 From 2f8b3d9855be2cd6a43d32d7b1799ca415f19f1c Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Sun, 2 Dec 2007 23:02:15 +1100 Subject: - dtucker@cvs.openbsd.org 2007/10/29 04:08:08 [monitor_wrap.c monitor.c] Send config block back to slave for invalid users too so options set by a Match block (eg Banner) behave the same for non-existent users. Found by and ok djm@ --- ChangeLog | 7 ++++++- monitor.c | 6 +++--- monitor_wrap.c | 7 ++++--- 3 files changed, 13 insertions(+), 7 deletions(-) (limited to 'monitor.c') diff --git a/ChangeLog b/ChangeLog index aff32e50e..31ffeaec5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,11 @@ [ssh.c] Plug tiny mem leaks in ControlPath and ProxyCommand option processing; ok djm@ + - dtucker@cvs.openbsd.org 2007/10/29 04:08:08 + [monitor_wrap.c monitor.c] + Send config block back to slave for invalid users too so options + set by a Match block (eg Banner) behave the same for non-existent + users. Found by and ok djm@ 20071030 - (djm) OpenBSD CVS Sync @@ -3429,4 +3434,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4798 2007/12/02 12:01:03 dtucker Exp $ +$Id: ChangeLog,v 1.4799 2007/12/02 12:02:15 dtucker Exp $ diff --git a/monitor.c b/monitor.c index 7996d5a14..2f23669cd 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.93 2007/09/21 08:15:29 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.94 2007/10/29 04:08:08 dtucker Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -643,11 +643,11 @@ mm_answer_pwnamallow(int sock, Buffer *m) #endif buffer_put_cstring(m, pwent->pw_dir); buffer_put_cstring(m, pwent->pw_shell); + + out: buffer_put_string(m, &options, sizeof(options)); if (options.banner != NULL) buffer_put_cstring(m, options.banner); - - out: debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); mm_request_send(sock, MONITOR_ANS_PWNAM, m); diff --git a/monitor_wrap.c b/monitor_wrap.c index 7ac845296..e895f1924 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.59 2007/09/21 08:15:29 djm Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.60 2007/10/29 04:08:08 dtucker Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -222,8 +222,8 @@ mm_getpwnamallow(const char *username) mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m); if (buffer_get_char(&m) == 0) { - buffer_free(&m); - return (NULL); + pw = NULL; + goto out; } pw = buffer_get_string(&m, &len); if (len != sizeof(struct passwd)) @@ -237,6 +237,7 @@ mm_getpwnamallow(const char *username) pw->pw_dir = buffer_get_string(&m, NULL); pw->pw_shell = buffer_get_string(&m, NULL); +out: /* copy options block as a Match directive may have changed some */ newopts = buffer_get_string(&m, &len); if (len != sizeof(*newopts)) -- cgit v1.2.3 From 52358d6df32d9ae923572c43a58159d84b673631 Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Tue, 11 Mar 2008 22:58:25 +1100 Subject: - (dtucker) [auth-pam.c monitor.c session.c sshd.c] Bug #926: Move pam_open_session and pam_close_session into the privsep monitor, which will ensure that pam_session_close is called as root. Patch from Tomas Mraz. --- ChangeLog | 8 +++++++- auth-pam.c | 6 ++++-- monitor.c | 5 +++++ session.c | 29 ----------------------------- sshd.c | 14 ++++++++++++++ 5 files changed, 30 insertions(+), 32 deletions(-) (limited to 'monitor.c') diff --git a/ChangeLog b/ChangeLog index 3057c2be5..4bb82cd29 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +20080312 + - (dtucker) [auth-pam.c monitor.c session.c sshd.c] Bug #926: Move + pam_open_session and pam_close_session into the privsep monitor, which + will ensure that pam_session_close is called as root. Patch from Tomas + Mraz. + 20080309 - (dtucker) [configure.ac] It turns out gcc's -fstack-protector-all doesn't always work for all platforms and versions, so test what we can and @@ -3712,4 +3718,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4864 2008/03/09 11:50:50 dtucker Exp $ +$Id: ChangeLog,v 1.4865 2008/03/11 11:58:25 dtucker Exp $ diff --git a/auth-pam.c b/auth-pam.c index a07f1fe77..ccdb9937e 100644 --- a/auth-pam.c +++ b/auth-pam.c @@ -598,15 +598,17 @@ static struct pam_conv store_conv = { sshpam_store_conv, NULL }; void sshpam_cleanup(void) { - debug("PAM: cleanup"); - if (sshpam_handle == NULL) + if (sshpam_handle == NULL || (use_privsep && !mm_is_monitor())) return; + debug("PAM: cleanup"); pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv); if (sshpam_cred_established) { + debug("PAM: deleting credentials"); pam_setcred(sshpam_handle, PAM_DELETE_CRED); sshpam_cred_established = 0; } if (sshpam_session_open) { + debug("PAM: closing session"); pam_close_session(sshpam_handle, PAM_SILENT); sshpam_session_open = 0; } diff --git a/monitor.c b/monitor.c index 2f23669cd..cc0e0fcac 100644 --- a/monitor.c +++ b/monitor.c @@ -1547,6 +1547,11 @@ mm_answer_term(int sock, Buffer *req) /* The child is terminating */ session_destroy_all(&mm_session_close); +#ifdef USE_PAM + if (options.use_pam) + sshpam_cleanup(); +#endif + while (waitpid(pmonitor->m_pid, &status, 0) == -1) if (errno != EINTR) exit(1); diff --git a/session.c b/session.c index 3eba513de..f5eaa815c 100644 --- a/session.c +++ b/session.c @@ -428,11 +428,6 @@ do_exec_no_pty(Session *s, const char *command) session_proctitle(s); -#if defined(USE_PAM) - if (options.use_pam && !use_privsep) - do_pam_setcred(1); -#endif /* USE_PAM */ - /* Fork the child. */ if ((pid = fork()) == 0) { is_child = 1; @@ -563,14 +558,6 @@ do_exec_pty(Session *s, const char *command) ptyfd = s->ptyfd; ttyfd = s->ttyfd; -#if defined(USE_PAM) - if (options.use_pam) { - do_pam_set_tty(s->tty); - if (!use_privsep) - do_pam_setcred(1); - } -#endif - /* Fork the child. */ if ((pid = fork()) == 0) { is_child = 1; @@ -1373,16 +1360,8 @@ do_setusercontext(struct passwd *pw) # ifdef __bsdi__ setpgid(0, 0); # endif -#ifdef GSSAPI - if (options.gss_authentication) { - temporarily_use_uid(pw); - ssh_gssapi_storecreds(); - restore_uid(); - } -#endif # ifdef USE_PAM if (options.use_pam) { - do_pam_session(); do_pam_setcred(use_privsep); } # endif /* USE_PAM */ @@ -1410,13 +1389,6 @@ do_setusercontext(struct passwd *pw) exit(1); } endgrent(); -# ifdef GSSAPI - if (options.gss_authentication) { - temporarily_use_uid(pw); - ssh_gssapi_storecreds(); - restore_uid(); - } -# endif # ifdef USE_PAM /* * PAM credentials may take the form of supplementary groups. @@ -1424,7 +1396,6 @@ do_setusercontext(struct passwd *pw) * Reestablish them here. */ if (options.use_pam) { - do_pam_session(); do_pam_setcred(use_privsep); } # endif /* USE_PAM */ diff --git a/sshd.c b/sshd.c index 5ea87f0f9..5dfc2b185 100644 --- a/sshd.c +++ b/sshd.c @@ -1847,6 +1847,20 @@ main(int ac, char **av) audit_event(SSH_AUTH_SUCCESS); #endif +#ifdef GSSAPI + if (options.gss_authentication) { + temporarily_use_uid(authctxt->pw); + ssh_gssapi_storecreds(); + restore_uid(); + } +#endif +#ifdef USE_PAM + if (options.use_pam) { + do_pam_setcred(1); + do_pam_session(); + } +#endif + /* * In privilege separation, we fork another child and prepare * file descriptor passing. -- cgit v1.2.3 From b84886ba3e362f54b70aefcbe1aa10606309b7d7 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Mon, 19 May 2008 15:05:07 +1000 Subject: - djm@cvs.openbsd.org 2008/05/08 12:02:23 [auth-options.c auth1.c channels.c channels.h clientloop.c gss-serv.c] [monitor.c monitor_wrap.c nchan.c servconf.c serverloop.c session.c] [ssh.c sshd.c] Implement a channel success/failure status confirmation callback mechanism. Each channel maintains a queue of callbacks, which will be drained in order (RFC4253 guarantees confirm messages are not reordered within an channel). Also includes a abandonment callback to clean up if a channel is closed without sending confirmation messages. This probably shouldn't happen in compliant implementations, but it could be abused to leak memory. ok markus@ (as part of a larger diff) --- ChangeLog | 15 +++++++++++- auth-options.c | 3 ++- auth1.c | 3 ++- channels.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- channels.h | 26 +++++++++++++++++---- clientloop.c | 10 +++++--- gss-serv.c | 3 ++- monitor.c | 3 ++- monitor_wrap.c | 3 ++- nchan.c | 3 ++- servconf.c | 3 ++- serverloop.c | 6 +++-- session.c | 3 ++- ssh.c | 6 +++-- sshd.c | 3 ++- 15 files changed, 132 insertions(+), 31 deletions(-) (limited to 'monitor.c') diff --git a/ChangeLog b/ChangeLog index e7fd87ba8..567222e96 100644 --- a/ChangeLog +++ b/ChangeLog @@ -62,6 +62,19 @@ [bufaux.c buffer.h channels.c packet.c packet.h] avoid extra malloc/copy/free when receiving data over the net; ~10% speedup for localhost-scp; ok djm@ + - djm@cvs.openbsd.org 2008/05/08 12:02:23 + [auth-options.c auth1.c channels.c channels.h clientloop.c gss-serv.c] + [monitor.c monitor_wrap.c nchan.c servconf.c serverloop.c session.c] + [ssh.c sshd.c] + Implement a channel success/failure status confirmation callback + mechanism. Each channel maintains a queue of callbacks, which will + be drained in order (RFC4253 guarantees confirm messages are not + reordered within an channel). + Also includes a abandonment callback to clean up if a channel is + closed without sending confirmation messages. This probably + shouldn't happen in compliant implementations, but it could be + abused to leak memory. + ok markus@ (as part of a larger diff) 20080403 - (djm) [openbsd-compat/bsd-poll.c] Include stdlib.h to avoid compile- @@ -3922,4 +3935,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4919 2008/05/19 04:59:37 djm Exp $ +$Id: ChangeLog,v 1.4920 2008/05/19 05:05:07 djm Exp $ diff --git a/auth-options.c b/auth-options.c index 6e2256961..3a6c3c0f3 100644 --- a/auth-options.c +++ b/auth-options.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.c,v 1.41 2008/03/26 21:28:14 djm Exp $ */ +/* $OpenBSD: auth-options.c,v 1.42 2008/05/08 12:02:23 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -20,6 +20,7 @@ #include #include +#include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "match.h" #include "log.h" diff --git a/auth1.c b/auth1.c index c17cc9133..b5798f634 100644 --- a/auth1.c +++ b/auth1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth1.c,v 1.71 2007/09/21 08:15:29 djm Exp $ */ +/* $OpenBSD: auth1.c,v 1.72 2008/05/08 12:02:23 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -20,6 +20,7 @@ #include #include +#include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "rsa.h" #include "ssh1.h" diff --git a/channels.c b/channels.c index 05c23e59c..b5e28dabf 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.274 2008/05/08 06:59:01 markus Exp $ */ +/* $OpenBSD: channels.c,v 1.275 2008/05/08 12:02:23 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -61,6 +61,7 @@ #include #include +#include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "ssh1.h" @@ -319,10 +320,11 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, c->single_connection = 0; c->detach_user = NULL; c->detach_close = 0; - c->confirm = NULL; - c->confirm_ctx = NULL; + c->open_confirm = NULL; + c->open_confirm_ctx = NULL; c->input_filter = NULL; c->output_filter = NULL; + TAILQ_INIT(&c->status_confirms); debug("channel %d: new [%s]", found, remote_name); return c; } @@ -379,6 +381,7 @@ channel_free(Channel *c) { char *s; u_int i, n; + struct channel_confirm *cc; for (n = 0, i = 0; i < channels_alloc; i++) if (channels[i]) @@ -402,6 +405,13 @@ channel_free(Channel *c) xfree(c->remote_name); c->remote_name = NULL; } + while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) { + if (cc->abandon_cb != NULL) + cc->abandon_cb(c, cc->ctx); + TAILQ_REMOVE(&c->status_confirms, cc, entry); + bzero(cc, sizeof(*cc)); + xfree(cc); + } channels[c->self] = NULL; xfree(c); } @@ -660,16 +670,33 @@ channel_request_start(int id, char *service, int wantconfirm) } void -channel_register_confirm(int id, channel_callback_fn *fn, void *ctx) +channel_register_status_confirm(int id, channel_confirm_cb *cb, + channel_confirm_abandon_cb *abandon_cb, void *ctx) +{ + struct channel_confirm *cc; + Channel *c; + + if ((c = channel_lookup(id)) == NULL) + fatal("channel_register_expect: %d: bad id", id); + + cc = xmalloc(sizeof(*cc)); + cc->cb = cb; + cc->abandon_cb = abandon_cb; + cc->ctx = ctx; + TAILQ_INSERT_TAIL(&c->status_confirms, cc, entry); +} + +void +channel_register_open_confirm(int id, channel_callback_fn *fn, void *ctx) { Channel *c = channel_lookup(id); if (c == NULL) { - logit("channel_register_comfirm: %d: bad id", id); + logit("channel_register_open_comfirm: %d: bad id", id); return; } - c->confirm = fn; - c->confirm_ctx = ctx; + c->open_confirm = fn; + c->open_confirm_ctx = ctx; } void @@ -2209,9 +2236,9 @@ channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt) if (compat20) { c->remote_window = packet_get_int(); c->remote_maxpacket = packet_get_int(); - if (c->confirm) { + if (c->open_confirm) { debug2("callback start"); - c->confirm(c->self, c->confirm_ctx); + c->open_confirm(c->self, c->open_confirm_ctx); debug2("callback done"); } debug2("channel %d: open confirm rwindow %u rmax %u", c->self, @@ -2328,6 +2355,34 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt) xfree(host); } +/* ARGSUSED */ +void +channel_input_status_confirm(int type, u_int32_t seq, void *ctxt) +{ + Channel *c; + struct channel_confirm *cc; + int remote_id; + + /* Reset keepalive timeout */ + keep_alive_timeouts = 0; + + remote_id = packet_get_int(); + packet_check_eom(); + + debug2("channel_input_confirm: type %d id %d", type, remote_id); + + if ((c = channel_lookup(remote_id)) == NULL) { + logit("channel_input_success_failure: %d: unknown", remote_id); + return; + } + ; + if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL) + return; + cc->cb(type, c, cc->ctx); + TAILQ_REMOVE(&c->status_confirms, cc, entry); + bzero(cc, sizeof(*cc)); + xfree(cc); +} /* -- tcp forwarding */ diff --git a/channels.h b/channels.h index b632a86af..46cde0309 100644 --- a/channels.h +++ b/channels.h @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.h,v 1.89 2007/06/11 09:14:00 markus Exp $ */ +/* $OpenBSD: channels.h,v 1.90 2008/05/08 12:02:23 djm Exp $ */ /* * Author: Tatu Ylonen @@ -64,6 +64,17 @@ typedef void channel_callback_fn(int, void *); typedef int channel_infilter_fn(struct Channel *, char *, int); typedef u_char *channel_outfilter_fn(struct Channel *, u_char **, u_int *); +/* Channel success/failure callbacks */ +typedef void channel_confirm_cb(int, struct Channel *, void *); +typedef void channel_confirm_abandon_cb(struct Channel *, void *); +struct channel_confirm { + TAILQ_ENTRY(channel_confirm) entry; + channel_confirm_cb *cb; + channel_confirm_abandon_cb *abandon_cb; + void *ctx; +}; +TAILQ_HEAD(channel_confirms, channel_confirm); + struct Channel { int type; /* channel type/state */ int self; /* my own channel identifier */ @@ -104,10 +115,11 @@ struct Channel { char *ctype; /* type */ /* callback */ - channel_callback_fn *confirm; - void *confirm_ctx; + channel_callback_fn *open_confirm; + void *open_confirm_ctx; channel_callback_fn *detach_user; int detach_close; + struct channel_confirms status_confirms; /* filter */ channel_infilter_fn *input_filter; @@ -170,8 +182,11 @@ void channel_stop_listening(void); void channel_send_open(int); void channel_request_start(int, char *, int); void channel_register_cleanup(int, channel_callback_fn *, int); -void channel_register_confirm(int, channel_callback_fn *, void *); -void channel_register_filter(int, channel_infilter_fn *, channel_outfilter_fn *); +void channel_register_open_confirm(int, channel_callback_fn *, void *); +void channel_register_filter(int, channel_infilter_fn *, + channel_outfilter_fn *); +void channel_register_status_confirm(int, channel_confirm_cb *, + channel_confirm_abandon_cb *, void *); void channel_cancel_cleanup(int); int channel_close_fd(int *); void channel_send_window_changes(void); @@ -188,6 +203,7 @@ void channel_input_open_confirmation(int, u_int32_t, void *); void channel_input_open_failure(int, u_int32_t, void *); void channel_input_port_open(int, u_int32_t, void *); void channel_input_window_adjust(int, u_int32_t, void *); +void channel_input_status_confirm(int, u_int32_t, void *); /* file descriptor handling (read/write) */ diff --git a/clientloop.c b/clientloop.c index 8a40bc71e..edd801440 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.188 2008/02/22 20:44:02 dtucker Exp $ */ +/* $OpenBSD: clientloop.c,v 1.189 2008/05/08 12:02:23 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -86,6 +86,7 @@ #include #include +#include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "ssh1.h" @@ -700,7 +701,7 @@ client_extra_session2_setup(int id, void *arg) cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env, client_subsystem_reply); - c->confirm_ctx = NULL; + c->open_confirm_ctx = NULL; buffer_free(&cctx->cmd); xfree(cctx->term); if (cctx->env != NULL) { @@ -940,7 +941,8 @@ client_process_control(fd_set *readset) debug3("%s: channel_new: %d", __func__, c->self); channel_send_open(c->self); - channel_register_confirm(c->self, client_extra_session2_setup, cctx); + channel_register_open_confirm(c->self, + client_extra_session2_setup, cctx); } static void @@ -2068,6 +2070,8 @@ client_init_dispatch_20(void) dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req); dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); + dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm); + dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm); dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request); /* rekeying */ diff --git a/gss-serv.c b/gss-serv.c index bc498fd47..2ec7ea19c 100644 --- a/gss-serv.c +++ b/gss-serv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gss-serv.c,v 1.21 2007/06/12 08:20:00 djm Exp $ */ +/* $OpenBSD: gss-serv.c,v 1.22 2008/05/08 12:02:23 djm Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. @@ -35,6 +35,7 @@ #include #include +#include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "buffer.h" #include "key.h" diff --git a/monitor.c b/monitor.c index cc0e0fcac..04f6924b6 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.94 2007/10/29 04:08:08 dtucker Exp $ */ +/* $OpenBSD: monitor.c,v 1.95 2008/05/08 12:02:23 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -51,6 +51,7 @@ #include +#include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "key.h" diff --git a/monitor_wrap.c b/monitor_wrap.c index e895f1924..72fd5c83c 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.60 2007/10/29 04:08:08 dtucker Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.61 2008/05/08 12:02:23 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -41,6 +41,7 @@ #include #include +#include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "dh.h" diff --git a/nchan.c b/nchan.c index ad461f4af..0d0faddb3 100644 --- a/nchan.c +++ b/nchan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nchan.c,v 1.57 2006/08/03 03:34:42 deraadt Exp $ */ +/* $OpenBSD: nchan.c,v 1.58 2008/05/08 12:02:23 djm Exp $ */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * @@ -32,6 +32,7 @@ #include #include +#include "openbsd-compat/sys-queue.h" #include "ssh1.h" #include "ssh2.h" #include "buffer.h" diff --git a/servconf.c b/servconf.c index e6d49099b..b8a968aa3 100644 --- a/servconf.c +++ b/servconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.c,v 1.178 2008/05/07 05:49:37 pyr Exp $ */ +/* $OpenBSD: servconf.c,v 1.179 2008/05/08 12:02:23 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -24,6 +24,7 @@ #include #include +#include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "log.h" diff --git a/serverloop.c b/serverloop.c index bf3f9c9f0..20991c3ce 100644 --- a/serverloop.c +++ b/serverloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.c,v 1.148 2008/02/22 20:44:02 dtucker Exp $ */ +/* $OpenBSD: serverloop.c,v 1.149 2008/05/08 12:02:23 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -56,6 +56,7 @@ #include #include +#include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "packet.h" #include "buffer.h" @@ -1188,8 +1189,9 @@ server_init_dispatch_20(void) dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req); dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request); + dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm); + dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm); /* client_alive */ - dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive); dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive); dispatch_set(SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive); /* rekeying */ diff --git a/session.c b/session.c index 16e455588..ca04a4532 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.235 2008/05/07 05:49:37 pyr Exp $ */ +/* $OpenBSD: session.c,v 1.236 2008/05/08 12:02:23 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -59,6 +59,7 @@ #include #include +#include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "ssh1.h" diff --git a/ssh.c b/ssh.c index 2ed76c9a1..b144a7130 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.309 2008/01/19 20:51:26 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.310 2008/05/08 12:02:23 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -73,6 +73,7 @@ #include #include #include "openbsd-compat/openssl-compat.h" +#include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" @@ -1195,7 +1196,8 @@ ssh_session2_open(void) channel_send_open(c->self); if (!no_shell_flag) - channel_register_confirm(c->self, ssh_session2_setup, NULL); + channel_register_open_confirm(c->self, + ssh_session2_setup, NULL); return c->self; } diff --git a/sshd.c b/sshd.c index 796310b03..aefbaaa42 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.356 2008/04/13 00:22:17 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.357 2008/05/08 12:02:23 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -54,6 +54,7 @@ # include #endif #include "openbsd-compat/sys-tree.h" +#include "openbsd-compat/sys-queue.h" #include #include -- cgit v1.2.3 From 7207f64a23a49a719aad3083c068f50e5034ccb8 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Mon, 19 May 2008 15:34:50 +1000 Subject: - djm@cvs.openbsd.org 2008/05/08 12:21:16 [monitor.c monitor_wrap.c session.h servconf.c servconf.h session.c] [sshd_config sshd_config.5] Make the maximum number of sessions run-time controllable via a sshd_config MaxSessions knob. This is useful for disabling login/shell/subsystem access while leaving port-forwarding working (MaxSessions 0), disabling connection multiplexing (MaxSessions 1) or simply increasing the number of allows multiplexed sessions. Because some bozos are sure to configure MaxSessions in excess of the number of available file descriptors in sshd (which, at peak, might be as many as 9*MaxSessions), audit sshd to ensure that it doesn't leak fds on error paths, and make it fail gracefully on out-of-fd conditions - sending channel errors instead of than exiting with fatal(). bz#1090; MaxSessions config bits and manpage from junyer AT gmail.com ok markus@ --- ChangeLog | 17 ++- monitor.c | 4 +- monitor_wrap.c | 22 +++- servconf.c | 21 +++- servconf.h | 4 +- session.c | 382 +++++++++++++++++++++++++++++++++++++++------------------ session.h | 4 +- sshd_config | 3 +- sshd_config.5 | 7 +- 9 files changed, 326 insertions(+), 138 deletions(-) (limited to 'monitor.c') diff --git a/ChangeLog b/ChangeLog index 99dbdaf78..5ea4afcac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -77,6 +77,21 @@ shouldn't happen in compliant implementations, but it could be abused to leak memory. ok markus@ (as part of a larger diff) + - djm@cvs.openbsd.org 2008/05/08 12:21:16 + [monitor.c monitor_wrap.c session.h servconf.c servconf.h session.c] + [sshd_config sshd_config.5] + Make the maximum number of sessions run-time controllable via + a sshd_config MaxSessions knob. This is useful for disabling + login/shell/subsystem access while leaving port-forwarding working + (MaxSessions 0), disabling connection multiplexing (MaxSessions 1) or + simply increasing the number of allows multiplexed sessions. + Because some bozos are sure to configure MaxSessions in excess of the + number of available file descriptors in sshd (which, at peak, might be + as many as 9*MaxSessions), audit sshd to ensure that it doesn't leak fds + on error paths, and make it fail gracefully on out-of-fd conditions - + sending channel errors instead of than exiting with fatal(). + bz#1090; MaxSessions config bits and manpage from junyer AT gmail.com + ok markus@ 20080403 - (djm) [openbsd-compat/bsd-poll.c] Include stdlib.h to avoid compile- @@ -3937,4 +3952,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4922 2008/05/19 05:28:35 djm Exp $ +$Id: ChangeLog,v 1.4923 2008/05/19 05:34:50 djm Exp $ diff --git a/monitor.c b/monitor.c index 04f6924b6..f872edbb5 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.95 2008/05/08 12:02:23 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.96 2008/05/08 12:21:16 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1273,7 +1273,7 @@ mm_session_close(Session *s) debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); session_pty_cleanup2(s); } - s->used = 0; + session_unused(s->self); } int diff --git a/monitor_wrap.c b/monitor_wrap.c index 72fd5c83c..e65fb1279 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.61 2008/05/08 12:02:23 djm Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.62 2008/05/08 12:21:16 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -666,7 +666,20 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen) { Buffer m; char *p, *msg; - int success = 0; + int success = 0, tmp1 = -1, tmp2 = -1; + + /* Kludge: ensure there are fds free to receive the pty/tty */ + if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 || + (tmp2 = dup(pmonitor->m_recvfd)) == -1) { + error("%s: cannot allocate fds for pty", __func__); + if (tmp1 > 0) + close(tmp1); + if (tmp2 > 0) + close(tmp2); + return 0; + } + close(tmp1); + close(tmp2); buffer_init(&m); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m); @@ -711,8 +724,9 @@ mm_session_pty_cleanup2(Session *s) buffer_free(&m); /* closed dup'ed master */ - if (close(s->ptymaster) < 0) - error("close(s->ptymaster): %s", strerror(errno)); + if (s->ptymaster != -1 && close(s->ptymaster) < 0) + error("close(s->ptymaster/%d): %s", + s->ptymaster, strerror(errno)); /* unlink pty from session */ s->ttyfd = -1; diff --git a/servconf.c b/servconf.c index b8a968aa3..94dff1fd6 100644 --- a/servconf.c +++ b/servconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.c,v 1.179 2008/05/08 12:02:23 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.180 2008/05/08 12:21:16 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -114,6 +114,7 @@ initialize_server_options(ServerOptions *options) options->max_startups_rate = -1; options->max_startups = -1; options->max_authtries = -1; + options->max_sessions = -1; options->banner = NULL; options->use_dns = -1; options->client_alive_interval = -1; @@ -237,6 +238,8 @@ fill_default_server_options(ServerOptions *options) options->max_startups_begin = options->max_startups; if (options->max_authtries == -1) options->max_authtries = DEFAULT_AUTH_FAIL_MAX; + if (options->max_sessions == -1) + options->max_sessions = DEFAULT_SESSIONS_MAX; if (options->use_dns == -1) options->use_dns = 1; if (options->client_alive_interval == -1) @@ -291,7 +294,7 @@ typedef enum { sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, - sMaxStartups, sMaxAuthTries, + sMaxStartups, sMaxAuthTries, sMaxSessions, sBanner, sUseDNS, sHostbasedAuthentication, sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, @@ -395,6 +398,7 @@ static struct { { "subsystem", sSubsystem, SSHCFG_GLOBAL }, { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, { "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL }, + { "maxsessions", sMaxSessions, SSHCFG_ALL }, { "banner", sBanner, SSHCFG_ALL }, { "usedns", sUseDNS, SSHCFG_GLOBAL }, { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, @@ -695,7 +699,7 @@ process_server_config_line(ServerOptions *options, char *line, case sServerKeyBits: intptr = &options->server_key_bits; -parse_int: + parse_int: arg = strdelim(&cp); if (!arg || *arg == '\0') fatal("%s line %d: missing integer value.", @@ -707,7 +711,7 @@ parse_int: case sLoginGraceTime: intptr = &options->login_grace_time; -parse_time: + parse_time: arg = strdelim(&cp); if (!arg || *arg == '\0') fatal("%s line %d: missing time value.", @@ -776,7 +780,7 @@ parse_time: fatal("%s line %d: too many host keys specified (max %d).", filename, linenum, MAX_HOSTKEYS); charptr = &options->host_key_files[*intptr]; -parse_filename: + parse_filename: arg = strdelim(&cp); if (!arg || *arg == '\0') fatal("%s line %d: missing file name.", @@ -819,7 +823,7 @@ parse_filename: case sIgnoreRhosts: intptr = &options->ignore_rhosts; -parse_flag: + parse_flag: arg = strdelim(&cp); if (!arg || *arg == '\0') fatal("%s line %d: missing yes/no argument.", @@ -1155,6 +1159,10 @@ parse_flag: intptr = &options->max_authtries; goto parse_int; + case sMaxSessions: + intptr = &options->max_sessions; + goto parse_int; + case sBanner: charptr = &options->banner; goto parse_filename; @@ -1382,6 +1390,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) M_CP_INTOPT(x11_display_offset); M_CP_INTOPT(x11_forwarding); M_CP_INTOPT(x11_use_localhost); + M_CP_INTOPT(max_sessions); M_CP_STROPT(banner); if (preauth) diff --git a/servconf.h b/servconf.h index aaf87cd18..819a028c8 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.83 2008/05/07 05:49:37 pyr Exp $ */ +/* $OpenBSD: servconf.h,v 1.84 2008/05/08 12:21:16 djm Exp $ */ /* * Author: Tatu Ylonen @@ -35,6 +35,7 @@ #define PERMIT_YES 3 #define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ +#define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */ /* Magic name for internal sftp-server */ #define INTERNAL_SFTP_NAME "internal-sftp" @@ -123,6 +124,7 @@ typedef struct { int max_startups_rate; int max_startups; int max_authtries; + int max_sessions; char *banner; /* SSH-2 banner message */ int use_dns; int client_alive_interval; /* diff --git a/session.c b/session.c index ca04a4532..c8ed25234 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.236 2008/05/08 12:02:23 djm Exp $ */ +/* $OpenBSD: session.c,v 1.237 2008/05/08 12:21:16 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -102,9 +102,9 @@ void session_set_fds(Session *, int, int, int); void session_pty_cleanup(Session *); void session_proctitle(Session *); int session_setup_x11fwd(Session *); -void do_exec_pty(Session *, const char *); -void do_exec_no_pty(Session *, const char *); -void do_exec(Session *, const char *); +int do_exec_pty(Session *, const char *); +int do_exec_no_pty(Session *, const char *); +int do_exec(Session *, const char *); void do_login(Session *, const char *); #ifdef LOGIN_NEEDS_UTMPX static void do_pre_login(Session *s); @@ -132,8 +132,9 @@ extern Buffer loginmsg; const char *original_command = NULL; /* data */ -#define MAX_SESSIONS 20 -Session sessions[MAX_SESSIONS]; +static int sessions_first_unused = -1; +static int sessions_nalloc = 0; +static Session *sessions = NULL; #define SUBSYSTEM_NONE 0 #define SUBSYSTEM_EXT 1 @@ -167,7 +168,7 @@ static int auth_input_request_forwarding(struct passwd * pw) { Channel *nc; - int sock; + int sock = -1; struct sockaddr_un sunaddr; if (auth_sock_name != NULL) { @@ -179,43 +180,48 @@ auth_input_request_forwarding(struct passwd * pw) temporarily_use_uid(pw); /* Allocate a buffer for the socket name, and format the name. */ - auth_sock_name = xmalloc(MAXPATHLEN); - auth_sock_dir = xmalloc(MAXPATHLEN); - strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN); + auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX"); /* Create private directory for socket */ if (mkdtemp(auth_sock_dir) == NULL) { packet_send_debug("Agent forwarding disabled: " "mkdtemp() failed: %.100s", strerror(errno)); restore_uid(); - xfree(auth_sock_name); xfree(auth_sock_dir); - auth_sock_name = NULL; auth_sock_dir = NULL; - return 0; + goto authsock_err; } - snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld", - auth_sock_dir, (long) getpid()); + + xasprintf(&auth_sock_name, "%s/agent.%ld", + auth_sock_dir, (long) getpid()); /* Create the socket. */ sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - packet_disconnect("socket: %.100s", strerror(errno)); + if (sock < 0) { + error("socket: %.100s", strerror(errno)); + restore_uid(); + goto authsock_err; + } /* Bind it to the name. */ memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_UNIX; strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path)); - if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) - packet_disconnect("bind: %.100s", strerror(errno)); + if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { + error("bind: %.100s", strerror(errno)); + restore_uid(); + goto authsock_err; + } /* Restore the privileged uid. */ restore_uid(); /* Start listening on the socket. */ - if (listen(sock, SSH_LISTEN_BACKLOG) < 0) - packet_disconnect("listen: %.100s", strerror(errno)); + if (listen(sock, SSH_LISTEN_BACKLOG) < 0) { + error("listen: %.100s", strerror(errno)); + goto authsock_err; + } /* Allocate a channel for the authentication agent socket. */ nc = channel_new("auth socket", @@ -224,6 +230,19 @@ auth_input_request_forwarding(struct passwd * pw) 0, "auth socket", 1); strlcpy(nc->path, auth_sock_name, sizeof(nc->path)); return 1; + + authsock_err: + if (auth_sock_name != NULL) + xfree(auth_sock_name); + if (auth_sock_dir != NULL) { + rmdir(auth_sock_dir); + xfree(auth_sock_dir); + } + if (sock != -1) + close(sock); + auth_sock_name = NULL; + auth_sock_dir = NULL; + return 0; } static void @@ -373,10 +392,14 @@ do_authenticated1(Authctxt *authctxt) if (type == SSH_CMSG_EXEC_CMD) { command = packet_get_string(&dlen); debug("Exec command '%.500s'", command); - do_exec(s, command); + if (do_exec(s, command) != 0) + packet_disconnect( + "command execution failed"); xfree(command); } else { - do_exec(s, NULL); + if (do_exec(s, NULL) != 0) + packet_disconnect( + "shell execution failed"); } packet_check_eom(); session_close(s); @@ -401,41 +424,84 @@ do_authenticated1(Authctxt *authctxt) } } +#define USE_PIPES /* * This is called to fork and execute a command when we have no tty. This * will call do_child from the child, and server_loop from the parent after * setting up file descriptors and such. */ -void +int do_exec_no_pty(Session *s, const char *command) { pid_t pid; #ifdef USE_PIPES int pin[2], pout[2], perr[2]; + /* Allocate pipes for communicating with the program. */ - if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0) - packet_disconnect("Could not create pipes: %.100s", - strerror(errno)); -#else /* USE_PIPES */ + if (pipe(pin) < 0) { + error("%s: pipe in: %.100s", __func__, strerror(errno)); + return -1; + } + if (pipe(pout) < 0) { + error("%s: pipe out: %.100s", __func__, strerror(errno)); + close(pin[0]); + close(pin[1]); + return -1; + } + if (pipe(perr) < 0) { + error("%s: pipe err: %.100s", __func__, strerror(errno)); + close(pin[0]); + close(pin[1]); + close(pout[0]); + close(pout[1]); + return -1; + } +#else int inout[2], err[2]; + /* Uses socket pairs to communicate with the program. */ - if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 || - socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) - packet_disconnect("Could not create socket pairs: %.100s", - strerror(errno)); -#endif /* USE_PIPES */ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) { + error("%s: socketpair #1: %.100s", __func__, strerror(errno)); + return -1; + } + if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) { + error("%s: socketpair #2: %.100s", __func__, strerror(errno)); + close(inout[0]); + close(inout[1]); + return -1; + } +#endif + if (s == NULL) fatal("do_exec_no_pty: no session"); session_proctitle(s); /* Fork the child. */ - if ((pid = fork()) == 0) { + switch ((pid = fork())) { + case -1: + error("%s: fork: %.100s", __func__, strerror(errno)); +#ifdef USE_PIPES + close(pin[0]); + close(pin[1]); + close(pout[0]); + close(pout[1]); + close(perr[0]); + close(perr[1]); +#else + close(inout[0]); + close(inout[1]); + close(err[0]); + close(err[1]); +#endif + return -1; + case 0: is_child = 1; /* Child. Reinitialize the log since the pid has changed. */ - log_init(__progname, options.log_level, options.log_facility, log_stderr); + log_init(__progname, options.log_level, + options.log_facility, log_stderr); /* * Create a new session and process group since the 4.4BSD @@ -465,7 +531,7 @@ do_exec_no_pty(Session *s, const char *command) if (dup2(perr[1], 2) < 0) perror("dup2 stderr"); close(perr[1]); -#else /* USE_PIPES */ +#else /* * Redirect stdin, stdout, and stderr. Stdin and stdout will * use the same socket, as some programs (particularly rdist) @@ -475,11 +541,14 @@ do_exec_no_pty(Session *s, const char *command) close(err[1]); if (dup2(inout[0], 0) < 0) /* stdin */ perror("dup2 stdin"); - if (dup2(inout[0], 1) < 0) /* stdout. Note: same socket as stdin. */ + if (dup2(inout[0], 1) < 0) /* stdout (same as stdin) */ perror("dup2 stdout"); + close(inout[0]); if (dup2(err[0], 2) < 0) /* stderr */ perror("dup2 stderr"); -#endif /* USE_PIPES */ + close(err[0]); +#endif + #ifdef _UNICOS cray_init_job(s->pw); /* set up cray jid and tmpdir */ @@ -488,7 +557,10 @@ do_exec_no_pty(Session *s, const char *command) /* Do processing for the child (exec command etc). */ do_child(s, command); /* NOTREACHED */ + default: + break; } + #ifdef _UNICOS signal(WJSIGNAL, cray_job_termination_handler); #endif /* _UNICOS */ @@ -496,11 +568,18 @@ do_exec_no_pty(Session *s, const char *command) if (is_winnt) cygwin_set_impersonation_token(INVALID_HANDLE_VALUE); #endif - if (pid < 0) - packet_disconnect("fork failed: %.100s", strerror(errno)); + s->pid = pid; /* Set interactive/non-interactive mode. */ packet_set_interactive(s->display != NULL); + + /* + * Clear loginmsg, since it's the child's responsibility to display + * it to the user, otherwise multiple sessions may accumulate + * multiple copies of the login messages. + */ + buffer_clear(&loginmsg); + #ifdef USE_PIPES /* We are the parent. Close the child sides of the pipes. */ close(pin[0]); @@ -518,29 +597,26 @@ do_exec_no_pty(Session *s, const char *command) server_loop(pid, pin[1], pout[0], perr[0]); /* server_loop has closed pin[1], pout[0], and perr[0]. */ } -#else /* USE_PIPES */ +#else /* We are the parent. Close the child sides of the socket pairs. */ close(inout[0]); close(err[0]); - /* - * Clear loginmsg, since it's the child's responsibility to display - * it to the user, otherwise multiple sessions may accumulate - * multiple copies of the login messages. - */ - buffer_clear(&loginmsg); - /* * Enter the interactive session. Note: server_loop must be able to * handle the case that fdin and fdout are the same. */ if (compat20) { - session_set_fds(s, inout[1], inout[1], s->is_subsystem ? -1 : err[1]); + session_set_fds(s, inout[1], inout[1], + s->is_subsystem ? -1 : err[1]); + if (s->is_subsystem) + close(err[1]); } else { server_loop(pid, inout[1], inout[1], err[1]); /* server_loop has closed inout[1] and err[1]. */ } -#endif /* USE_PIPES */ +#endif + return 0; } /* @@ -549,7 +625,7 @@ do_exec_no_pty(Session *s, const char *command) * setting up file descriptors, controlling tty, updating wtmp, utmp, * lastlog, and other such operations. */ -void +int do_exec_pty(Session *s, const char *command) { int fdout, ptyfd, ttyfd, ptymaster; @@ -560,12 +636,46 @@ do_exec_pty(Session *s, const char *command) ptyfd = s->ptyfd; ttyfd = s->ttyfd; + /* + * Create another descriptor of the pty master side for use as the + * standard input. We could use the original descriptor, but this + * simplifies code in server_loop. The descriptor is bidirectional. + * Do this before forking (and cleanup in the child) so as to + * detect and gracefully fail out-of-fd conditions. + */ + if ((fdout = dup(ptyfd)) < 0) { + error("%s: dup #1: %s", __func__, strerror(errno)); + close(ttyfd); + close(ptyfd); + return -1; + } + /* we keep a reference to the pty master */ + if ((ptymaster = dup(ptyfd)) < 0) { + error("%s: dup #2: %s", __func__, strerror(errno)); + close(ttyfd); + close(ptyfd); + close(fdout); + return -1; + } + /* Fork the child. */ - if ((pid = fork()) == 0) { + switch ((pid = fork())) { + case -1: + error("%s: fork: %.100s", __func__, strerror(errno)); + close(fdout); + close(ptymaster); + close(ttyfd); + close(ptyfd); + return -1; + case 0: is_child = 1; + close(fdout); + close(ptymaster); + /* Child. Reinitialize the log because the pid has changed. */ - log_init(__progname, options.log_level, options.log_facility, log_stderr); + log_init(__progname, options.log_level, + options.log_facility, log_stderr); /* Close the master side of the pseudo tty. */ close(ptyfd); @@ -596,11 +706,16 @@ do_exec_pty(Session *s, const char *command) do_pre_login(s); # endif #endif - - /* Do common processing for the child, such as execing the command. */ - do_child(s, command); - /* NOTREACHED */ + /* + * Do common processing for the child, such as execing + * the command. + */ + do_child(s, command); + /* NOTREACHED */ + default: + break; } + #ifdef _UNICOS signal(WJSIGNAL, cray_job_termination_handler); #endif /* _UNICOS */ @@ -608,29 +723,14 @@ do_exec_pty(Session *s, const char *command) if (is_winnt) cygwin_set_impersonation_token(INVALID_HANDLE_VALUE); #endif - if (pid < 0) - packet_disconnect("fork failed: %.100s", strerror(errno)); + s->pid = pid; /* Parent. Close the slave side of the pseudo tty. */ close(ttyfd); - /* - * Create another descriptor of the pty master side for use as the - * standard input. We could use the original descriptor, but this - * simplifies code in server_loop. The descriptor is bidirectional. - */ - fdout = dup(ptyfd); - if (fdout < 0) - packet_disconnect("dup #1 failed: %.100s", strerror(errno)); - - /* we keep a reference to the pty master */ - ptymaster = dup(ptyfd); - if (ptymaster < 0) - packet_disconnect("dup #2 failed: %.100s", strerror(errno)); - s->ptymaster = ptymaster; - /* Enter interactive session. */ + s->ptymaster = ptymaster; packet_set_interactive(1); if (compat20) { session_set_fds(s, ptyfd, fdout, -1); @@ -638,6 +738,7 @@ do_exec_pty(Session *s, const char *command) server_loop(pid, ptyfd, fdout, -1); /* server_loop _has_ closed ptyfd and fdout. */ } + return 0; } #ifdef LOGIN_NEEDS_UTMPX @@ -672,9 +773,11 @@ do_pre_login(Session *s) * This is called to fork and execute a command. If another command is * to be forced, execute that instead. */ -void +int do_exec(Session *s, const char *command) { + int ret; + if (options.adm_forced_command) { original_command = command; command = options.adm_forced_command; @@ -705,9 +808,9 @@ do_exec(Session *s, const char *command) } #endif if (s->ttyfd != -1) - do_exec_pty(s, command); + ret = do_exec_pty(s, command); else - do_exec_no_pty(s, command); + ret = do_exec_no_pty(s, command); original_command = NULL; @@ -717,6 +820,8 @@ do_exec(Session *s, const char *command) * multiple copies of the login messages. */ buffer_clear(&loginmsg); + + return ret; } /* administrative, login(1)-like work */ @@ -1740,43 +1845,79 @@ do_child(Session *s, const char *command) exit(1); } +void +session_unused(int id) +{ + debug3("%s: session id %d unused", __func__, id); + if (id >= options.max_sessions || + id >= sessions_nalloc) { + fatal("%s: insane session id %d (max %d nalloc %d)", + __func__, id, options.max_sessions, sessions_nalloc); + } + bzero(&sessions[id], sizeof(*sessions)); + sessions[id].self = id; + sessions[id].used = 0; + sessions[id].chanid = -1; + sessions[id].ptyfd = -1; + sessions[id].ttyfd = -1; + sessions[id].ptymaster = -1; + sessions[id].x11_chanids = NULL; + sessions[id].next_unused = sessions_first_unused; + sessions_first_unused = id; +} + Session * session_new(void) { - int i; - static int did_init = 0; - if (!did_init) { - debug("session_new: init"); - for (i = 0; i < MAX_SESSIONS; i++) { - sessions[i].used = 0; + Session *s, *tmp; + + if (sessions_first_unused == -1) { + if (sessions_nalloc >= options.max_sessions) + return NULL; + debug2("%s: allocate (allocated %d max %d)", + __func__, sessions_nalloc, options.max_sessions); + tmp = xrealloc(sessions, sessions_nalloc + 1, + sizeof(*sessions)); + if (tmp == NULL) { + error("%s: cannot allocate %d sessions", + __func__, sessions_nalloc + 1); + return NULL; } - did_init = 1; + sessions = tmp; + session_unused(sessions_nalloc++); } - for (i = 0; i < MAX_SESSIONS; i++) { - Session *s = &sessions[i]; - if (! s->used) { - memset(s, 0, sizeof(*s)); - s->chanid = -1; - s->ptyfd = -1; - s->ttyfd = -1; - s->used = 1; - s->self = i; - s->x11_chanids = NULL; - debug("session_new: session %d", i); - return s; - } + + if (sessions_first_unused >= sessions_nalloc || + sessions_first_unused < 0) { + fatal("%s: insane first_unused %d max %d nalloc %d", + __func__, sessions_first_unused, options.max_sessions, + sessions_nalloc); } - return NULL; + + s = &sessions[sessions_first_unused]; + if (s->used) { + fatal("%s: session %d already used", + __func__, sessions_first_unused); + } + sessions_first_unused = s->next_unused; + s->used = 1; + s->next_unused = -1; + debug("session_new: session %d", s->self); + + return s; } static void session_dump(void) { int i; - for (i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; - debug("dump: used %d session %d %p channel %d pid %ld", + + debug("dump: used %d next_unused %d session %d %p " + "channel %d pid %ld", s->used, + s->next_unused, s->self, s, s->chanid, @@ -1806,7 +1947,7 @@ Session * session_by_tty(char *tty) { int i; - for (i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) { debug("session_by_tty: session %d tty %s", i, tty); @@ -1822,10 +1963,11 @@ static Session * session_by_channel(int id) { int i; - for (i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; if (s->used && s->chanid == id) { - debug("session_by_channel: session %d channel %d", i, id); + debug("session_by_channel: session %d channel %d", + i, id); return s; } } @@ -1839,7 +1981,7 @@ session_by_x11_channel(int id) { int i, j; - for (i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; if (s->x11_chanids == NULL || !s->used) @@ -1862,7 +2004,7 @@ session_by_pid(pid_t pid) { int i; debug("session_by_pid: pid %ld", (long)pid); - for (i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; if (s->used && s->pid == pid) return s; @@ -1918,7 +2060,8 @@ session_pty_req(Session *s) /* Allocate a pty and open it. */ debug("Allocating pty."); - if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) { + if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, + sizeof(s->tty)))) { if (s->term) xfree(s->term); s->term = NULL; @@ -1971,8 +2114,7 @@ session_subsystem_req(Session *s) s->is_subsystem = SUBSYSTEM_EXT; } debug("subsystem: exec() %s", cmd); - do_exec(s, cmd); - success = 1; + success = do_exec(s, cmd) == 0; break; } } @@ -2015,19 +2157,19 @@ static int session_shell_req(Session *s) { packet_check_eom(); - do_exec(s, NULL); - return 1; + return do_exec(s, NULL) == 0; } static int session_exec_req(Session *s) { - u_int len; + u_int len, success; + char *command = packet_get_string(&len); packet_check_eom(); - do_exec(s, command); + success = do_exec(s, command) == 0; xfree(command); - return 1; + return success; } static int @@ -2037,8 +2179,7 @@ session_break_req(Session *s) packet_get_int(); /* ignored */ packet_check_eom(); - if (s->ttyfd == -1 || - tcsendbreak(s->ttyfd, 0) < 0) + if (s->ttyfd == -1 || tcsendbreak(s->ttyfd, 0) < 0) return 0; return 1; } @@ -2185,8 +2326,9 @@ session_pty_cleanup2(Session *s) * the pty cleanup, so that another process doesn't get this pty * while we're still cleaning up. */ - if (close(s->ptymaster) < 0) - error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno)); + if (s->ptymaster != -1 && close(s->ptymaster) < 0) + error("close(s->ptymaster/%d): %s", + s->ptymaster, strerror(errno)); /* unlink pty from session */ s->ttyfd = -1; @@ -2346,7 +2488,6 @@ session_close(Session *s) xfree(s->auth_data); if (s->auth_proto) xfree(s->auth_proto); - s->used = 0; if (s->env != NULL) { for (i = 0; i < s->num_env; i++) { xfree(s->env[i].name); @@ -2355,6 +2496,7 @@ session_close(Session *s) xfree(s->env); } session_proctitle(s); + session_unused(s->self); } void @@ -2418,7 +2560,7 @@ void session_destroy_all(void (*closefunc)(Session *)) { int i; - for (i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; if (s->used) { if (closefunc != NULL) @@ -2437,7 +2579,7 @@ session_tty_list(void) char *cp; buf[0] = '\0'; - for (i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; if (s->used && s->ttyfd != -1) { diff --git a/session.h b/session.h index ee9338e4f..cbb8e3a32 100644 --- a/session.h +++ b/session.h @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.29 2006/08/03 03:34:42 deraadt Exp $ */ +/* $OpenBSD: session.h,v 1.30 2008/05/08 12:21:16 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -31,6 +31,7 @@ typedef struct Session Session; struct Session { int used; int self; + int next_unused; struct passwd *pw; Authctxt *authctxt; pid_t pid; @@ -65,6 +66,7 @@ void do_authenticated(Authctxt *); void do_cleanup(Authctxt *); int session_open(Authctxt *, int); +void session_unused(int); int session_input_channel_req(Channel *, const char *); void session_close_by_pid(pid_t, int); void session_close_by_channel(int, void *); diff --git a/sshd_config b/sshd_config index 1f97a9dcc..c5ee7c8a4 100644 --- a/sshd_config +++ b/sshd_config @@ -1,4 +1,4 @@ -# $OpenBSD: sshd_config,v 1.78 2008/05/07 06:43:35 pyr Exp $ +# $OpenBSD: sshd_config,v 1.79 2008/05/08 12:21:16 djm Exp $ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. @@ -41,6 +41,7 @@ Protocol 2 #PermitRootLogin yes #StrictModes yes #MaxAuthTries 6 +#MaxSessions 10 #RSAAuthentication yes #PubkeyAuthentication yes diff --git a/sshd_config.5 b/sshd_config.5 index 99b5621e7..0d8c140bf 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -34,8 +34,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.89 2008/05/07 08:00:14 jmc Exp $ -.Dd $Mdocdate: May 19 2008 $ +.\" $OpenBSD: sshd_config.5,v 1.90 2008/05/08 12:21:16 djm Exp $ +.Dd $Mdocdate: May 8 2008 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -594,6 +594,9 @@ connection. Once the number of failures reaches half this value, additional failures are logged. The default is 6. +.It Cm MaxSessions +Specifies the maximum number of open sessions permitted per network connection. +The default is 10. .It Cm MaxStartups Specifies the maximum number of concurrent unauthenticated connections to the SSH daemon. -- cgit v1.2.3 From f2c16d30b456c3b149999e91d16bf28f82197d3f Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Sat, 14 Jun 2008 08:59:49 +1000 Subject: - dtucker@cvs.openbsd.org 2008/06/13 13:56:59 [monitor.c] Clear key options in the monitor on failed authentication, prevents applying additional restrictions to non-pubkey authentications in the case where pubkey fails but another method subsequently succeeds. bz #1472, found by Colin Watson, ok markus@ djm --- ChangeLog | 8 +++++++- monitor.c | 6 +++++- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'monitor.c') diff --git a/ChangeLog b/ChangeLog index 81c36752c..362febe67 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,12 @@ - deraadt@cvs.openbsd.org 2008/06/13 09:44:36 [packet.c] compile on older gcc; no decl after code + - dtucker@cvs.openbsd.org 2008/06/13 13:56:59 + [monitor.c] + Clear key options in the monitor on failed authentication, prevents + applying additional restrictions to non-pubkey authentications in + the case where pubkey fails but another method subsequently succeeds. + bz #1472, found by Colin Watson, ok markus@ djm@ 20080612 - (dtucker) OpenBSD CVS Sync @@ -4341,4 +4347,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.5004 2008/06/13 12:02:50 dtucker Exp $ +$Id: ChangeLog,v 1.5005 2008/06/13 22:59:49 dtucker Exp $ diff --git a/monitor.c b/monitor.c index f872edbb5..8a9ea7849 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.96 2008/05/08 12:21:16 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.97 2008/06/13 13:56:59 dtucker Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1015,6 +1015,8 @@ mm_answer_keyallowed(int sock, Buffer *m) allowed = options.pubkey_authentication && user_key_allowed(authctxt->pw, key); auth_method = "publickey"; + if (options.pubkey_authentication && allowed != 1) + auth_clear_options(); break; case MM_HOSTKEY: allowed = options.hostbased_authentication && @@ -1027,6 +1029,8 @@ mm_answer_keyallowed(int sock, Buffer *m) allowed = options.rhosts_rsa_authentication && auth_rhosts_rsa_key_allowed(authctxt->pw, cuser, chost, key); + if (options.rhosts_rsa_authentication && allowed != 1) + auth_clear_options(); auth_method = "rsa"; break; default: -- cgit v1.2.3 From 2784f1fcc3b6c41cdeb8e7d850044c5ee61cbbcd Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Fri, 4 Jul 2008 13:51:45 +1000 Subject: - dtucker@cvs.openbsd.org 2008/07/04 03:47:02 [monitor.c] Make debug a little clearer. ok djm@ --- ChangeLog | 5 ++++- monitor.c | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'monitor.c') diff --git a/ChangeLog b/ChangeLog index 56ee5d46e..b86b5e498 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,9 @@ - djm@cvs.openbsd.org 2008/07/04 03:44:59 [servconf.c groupaccess.h groupaccess.c] support negation of groups in "Match group" block (bz#1315); ok dtucker@ + - dtucker@cvs.openbsd.org 2008/07/04 03:47:02 + [monitor.c] + Make debug a little clearer. ok djm@ 20080702 - (dtucker) OpenBSD CVS Sync @@ -4550,4 +4553,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.5052 2008/07/04 03:51:12 dtucker Exp $ +$Id: ChangeLog,v 1.5053 2008/07/04 03:51:45 dtucker Exp $ diff --git a/monitor.c b/monitor.c index 8a9ea7849..b7074cfb4 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.97 2008/06/13 13:56:59 dtucker Exp $ */ +/* $OpenBSD: monitor.c,v 1.98 2008/07/04 03:47:02 dtucker Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1060,7 +1060,7 @@ mm_answer_keyallowed(int sock, Buffer *m) } debug3("%s: key %p is %s", - __func__, key, allowed ? "allowed" : "disallowed"); + __func__, key, allowed ? "allowed" : "not allowed"); buffer_clear(m); buffer_put_int(m, allowed); -- cgit v1.2.3 From b61f3fc31ff6eb1693431e21fb1086c33eb66549 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 11 Jul 2008 17:36:48 +1000 Subject: - markus@cvs.openbsd.org 2008/07/10 18:08:11 [clientloop.c monitor.c monitor_wrap.c packet.c packet.h sshd.c] sync v1 and v2 traffic accounting; add it to sshd, too; ok djm@, dtucker@ --- ChangeLog | 6 +++++- clientloop.c | 24 ++++++++---------------- monitor.c | 10 ++++++---- monitor_wrap.c | 10 ++++++---- packet.c | 29 ++++++++++++++++++++++------- packet.h | 6 +++--- sshd.c | 11 ++++++++--- 7 files changed, 58 insertions(+), 38 deletions(-) (limited to 'monitor.c') diff --git a/ChangeLog b/ChangeLog index 40b939018..b3263e909 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,10 @@ - markus@cvs.openbsd.org 2008/07/10 18:05:58 [channels.c] missing bzero; from mickey; ok djm@ + - markus@cvs.openbsd.org 2008/07/10 18:08:11 + [clientloop.c monitor.c monitor_wrap.c packet.c packet.h sshd.c] + sync v1 and v2 traffic accounting; add it to sshd, too; + ok djm@, dtucker@ 20080709 - (djm) [Makefile.in] Print "all tests passed" when all regress tests pass @@ -4618,4 +4622,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.5072 2008/07/11 07:35:37 djm Exp $ +$Id: ChangeLog,v 1.5073 2008/07/11 07:36:48 djm Exp $ diff --git a/clientloop.c b/clientloop.c index ba2f0b79e..5a8727eb9 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.199 2008/06/12 21:06:25 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.200 2008/07/10 18:08:11 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -152,7 +152,6 @@ static int stdin_eof; /* EOF has been encountered on stderr. */ static Buffer stdin_buffer; /* Buffer for stdin data. */ static Buffer stdout_buffer; /* Buffer for stdout data. */ static Buffer stderr_buffer; /* Buffer for stderr data. */ -static u_long stdin_bytes, stdout_bytes, stderr_bytes; static u_int buffer_high;/* Soft max buffer size. */ static int connection_in; /* Connection to server (input). */ static int connection_out; /* Connection to server (output). */ @@ -437,7 +436,6 @@ client_make_packets_from_stdin_data(void) packet_put_string(buffer_ptr(&stdin_buffer), len); packet_send(); buffer_consume(&stdin_buffer, len); - stdin_bytes += len; /* If we have a pending EOF, send it now. */ if (stdin_eof && buffer_len(&stdin_buffer) == 0) { packet_start(SSH_CMSG_EOF); @@ -1205,7 +1203,6 @@ client_process_output(fd_set *writeset) } /* Consume printed data from the buffer. */ buffer_consume(&stdout_buffer, len); - stdout_bytes += len; } /* Write buffered output to stderr. */ if (FD_ISSET(fileno(stderr), writeset)) { @@ -1227,7 +1224,6 @@ client_process_output(fd_set *writeset) } /* Consume printed characters from the buffer. */ buffer_consume(&stderr_buffer, len); - stderr_bytes += len; } } @@ -1302,6 +1298,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) fd_set *readset = NULL, *writeset = NULL; double start_time, total_time; int max_fd = 0, max_fd2 = 0, len, rekeying = 0; + u_int64_t ibytes, obytes; u_int nalloc = 0; char buf[100]; @@ -1333,9 +1330,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) max_fd = MAX(max_fd, fileno(stdout)); max_fd = MAX(max_fd, fileno(stderr)); } - stdin_bytes = 0; - stdout_bytes = 0; - stderr_bytes = 0; quit_pending = 0; escape_char1 = escape_char_arg; @@ -1521,7 +1515,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) break; } buffer_consume(&stdout_buffer, len); - stdout_bytes += len; } /* Output any buffered data for stderr. */ @@ -1533,7 +1526,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) break; } buffer_consume(&stderr_buffer, len); - stderr_bytes += len; } /* Clear and free any buffers. */ @@ -1544,13 +1536,13 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) /* Report bytes transferred, and transfer rates. */ total_time = get_current_time() - start_time; - debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f " - "seconds", stdin_bytes, stdout_bytes, stderr_bytes, total_time); + packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes); + packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes); + verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds", + obytes, ibytes, total_time); if (total_time > 0) - debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f", - stdin_bytes / total_time, stdout_bytes / total_time, - stderr_bytes / total_time); - + verbose("Bytes per second: sent %.1f, received %.1f", + obytes / total_time, ibytes / total_time); /* Return the exit status of the program. */ debug("Exit status %d", exit_status); return exit_status; diff --git a/monitor.c b/monitor.c index b7074cfb4..73cf6bc9b 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.98 2008/07/04 03:47:02 dtucker Exp $ */ +/* $OpenBSD: monitor.c,v 1.99 2008/07/10 18:08:11 markus Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1705,7 +1705,7 @@ mm_get_keystate(struct monitor *pmonitor) u_char *blob, *p; u_int bloblen, plen; u_int32_t seqnr, packets; - u_int64_t blocks; + u_int64_t blocks, bytes; debug3("%s: Waiting for new keys", __func__); @@ -1738,11 +1738,13 @@ mm_get_keystate(struct monitor *pmonitor) seqnr = buffer_get_int(&m); blocks = buffer_get_int64(&m); packets = buffer_get_int(&m); - packet_set_state(MODE_OUT, seqnr, blocks, packets); + bytes = buffer_get_int64(&m); + packet_set_state(MODE_OUT, seqnr, blocks, packets, bytes); seqnr = buffer_get_int(&m); blocks = buffer_get_int64(&m); packets = buffer_get_int(&m); - packet_set_state(MODE_IN, seqnr, blocks, packets); + bytes = buffer_get_int64(&m); + packet_set_state(MODE_IN, seqnr, blocks, packets, bytes); skip: /* Get the key context */ diff --git a/monitor_wrap.c b/monitor_wrap.c index e65fb1279..40463d078 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.62 2008/05/08 12:21:16 djm Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.63 2008/07/10 18:08:11 markus Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -573,7 +573,7 @@ mm_send_keystate(struct monitor *monitor) u_char *blob, *p; u_int bloblen, plen; u_int32_t seqnr, packets; - u_int64_t blocks; + u_int64_t blocks, bytes; buffer_init(&m); @@ -622,14 +622,16 @@ mm_send_keystate(struct monitor *monitor) buffer_put_string(&m, blob, bloblen); xfree(blob); - packet_get_state(MODE_OUT, &seqnr, &blocks, &packets); + packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes); buffer_put_int(&m, seqnr); buffer_put_int64(&m, blocks); buffer_put_int(&m, packets); - packet_get_state(MODE_IN, &seqnr, &blocks, &packets); + buffer_put_int64(&m, bytes); + packet_get_state(MODE_IN, &seqnr, &blocks, &packets, &bytes); buffer_put_int(&m, seqnr); buffer_put_int64(&m, blocks); buffer_put_int(&m, packets); + buffer_put_int64(&m, bytes); debug3("%s: New keys have been sent", __func__); skip: diff --git a/packet.c b/packet.c index 1dda4a294..8abd43eb4 100644 --- a/packet.c +++ b/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.156 2008/07/04 23:08:25 djm Exp $ */ +/* $OpenBSD: packet.c,v 1.157 2008/07/10 18:08:11 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -147,6 +147,7 @@ static struct packet_state { u_int32_t seqnr; u_int32_t packets; u_int64_t blocks; + u_int64_t bytes; } p_read, p_send; static u_int64_t max_blocks_in, max_blocks_out; @@ -191,6 +192,7 @@ packet_set_connection(int fd_in, int fd_out) buffer_init(&outgoing_packet); buffer_init(&incoming_packet); TAILQ_INIT(&outgoing); + p_send.packets = p_read.packets = 0; } } @@ -311,18 +313,25 @@ packet_get_ssh1_cipher(void) } void -packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets) +packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets, + u_int64_t *bytes) { struct packet_state *state; state = (mode == MODE_IN) ? &p_read : &p_send; - *seqnr = state->seqnr; - *blocks = state->blocks; - *packets = state->packets; + if (seqnr) + *seqnr = state->seqnr; + if (blocks) + *blocks = state->blocks; + if (packets) + *packets = state->packets; + if (bytes) + *bytes = state->bytes; } void -packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets) +packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets, + u_int64_t bytes) { struct packet_state *state; @@ -330,6 +339,7 @@ packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets) state->seqnr = seqnr; state->blocks = blocks; state->packets = packets; + state->bytes = bytes; } /* returns 1 if connection is via ipv4 */ @@ -608,7 +618,8 @@ packet_send1(void) fprintf(stderr, "encrypted: "); buffer_dump(&output); #endif - + p_send.packets++; + p_send.bytes += len + buffer_len(&outgoing_packet); buffer_clear(&outgoing_packet); /* @@ -834,6 +845,7 @@ packet_send2_wrapped(void) if (!(datafellows & SSH_BUG_NOREKEY)) fatal("XXX too many packets with same key"); p_send.blocks += (packet_length + 4) / block_size; + p_send.bytes += packet_length + 4; buffer_clear(&outgoing_packet); if (type == SSH2_MSG_NEWKEYS) @@ -1096,6 +1108,8 @@ packet_read_poll1(void) buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), buffer_len(&compression_buffer)); } + p_read.packets++; + p_read.bytes += padded_len + 4; type = buffer_get_char(&incoming_packet); if (type < SSH_MSG_MIN || type > SSH_MSG_MAX) packet_disconnect("Invalid ssh1 packet type: %d", type); @@ -1184,6 +1198,7 @@ packet_read_poll2(u_int32_t *seqnr_p) if (!(datafellows & SSH_BUG_NOREKEY)) fatal("XXX too many packets with same key"); p_read.blocks += (packet_length + 4) / block_size; + p_read.bytes += packet_length + 4; /* get padlen */ cp = buffer_ptr(&incoming_packet); diff --git a/packet.h b/packet.h index fd4e1ac7a..03bb87c9b 100644 --- a/packet.h +++ b/packet.h @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.h,v 1.48 2008/06/12 20:38:28 dtucker Exp $ */ +/* $OpenBSD: packet.h,v 1.49 2008/07/10 18:08:11 markus Exp $ */ /* * Author: Tatu Ylonen @@ -68,8 +68,8 @@ int packet_get_keyiv_len(int); void packet_get_keyiv(int, u_char *, u_int); int packet_get_keycontext(int, u_char *); void packet_set_keycontext(int, u_char *); -void packet_get_state(int, u_int32_t *, u_int64_t *, u_int32_t *); -void packet_set_state(int, u_int32_t, u_int64_t, u_int32_t); +void packet_get_state(int, u_int32_t *, u_int64_t *, u_int32_t *, u_int64_t *); +void packet_set_state(int, u_int32_t, u_int64_t, u_int32_t, u_int64_t); int packet_get_ssh1_cipher(void); void packet_set_iv(int, u_char *); diff --git a/sshd.c b/sshd.c index a6620a05a..6e5bb5476 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.363 2008/07/01 07:24:22 dtucker Exp $ */ +/* $OpenBSD: sshd.c,v 1.364 2008/07/10 18:08:11 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -677,7 +677,7 @@ privsep_postauth(Authctxt *authctxt) if (pmonitor->m_pid == -1) fatal("fork of unprivileged child failed"); else if (pmonitor->m_pid != 0) { - debug2("User child is on pid %ld", (long)pmonitor->m_pid); + verbose("User child is on pid %ld", (long)pmonitor->m_pid); close(pmonitor->m_recvfd); buffer_clear(&loginmsg); monitor_child_postauth(pmonitor); @@ -1248,6 +1248,7 @@ main(int ac, char **av) int remote_port; char *line, *p, *cp; int config_s[2] = { -1 , -1 }; + u_int64_t ibytes, obytes; mode_t new_umask; Key *key; Authctxt *authctxt; @@ -1919,7 +1920,11 @@ main(int ac, char **av) do_authenticated(authctxt); /* The connection has been terminated. */ - verbose("Closing connection to %.100s", remote_ip); + packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes); + packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes); + verbose("Transferred: sent %llu, received %llu bytes", obytes, ibytes); + + verbose("Closing connection to %.500s port %d", remote_ip, remote_port); #ifdef USE_PAM if (options.use_pam) -- cgit v1.2.3