summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2008-07-02 12:36:40 +0000
committerDamien Miller <djm@cvs.openbsd.org>2008-07-02 12:36:40 +0000
commitd252894a690953ef3714f49033556452d3778c48 (patch)
treece9a7ffb6fbf64e6bc599a500bdbee8590cec681
parentae7b4334d1743f117574eb58d42aba362ca45078 (diff)
Make protocol 2 MaxAuthTries behaviour a little more sensible:
Check whether client has exceeded MaxAuthTries before running an authentication method and skip it if they have, previously it would always allow one try (for "none" auth). Preincrement failure count before post-auth test - previously this checked and postincremented, also to allow one "none" try. Together, these two changes always count the "none" auth method which could be skipped by a malicious client (e.g. an SSH worm) to get an extra attempt at a real auth method. They also make MaxAuthTries=0 a useful way to block users entirely (esp. in a sshd_config Match block). Also, move sending of any preauth banner from "none" auth method to the first call to input_userauth_request(), so worms that skip the "none" method get to see it too.
-rw-r--r--usr.bin/ssh/auth2-none.c66
-rw-r--r--usr.bin/ssh/auth2.c70
2 files changed, 67 insertions, 69 deletions
diff --git a/usr.bin/ssh/auth2-none.c b/usr.bin/ssh/auth2-none.c
index fb463c64040..9ce38457a52 100644
--- a/usr.bin/ssh/auth2-none.c
+++ b/usr.bin/ssh/auth2-none.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-none.c,v 1.14 2007/08/23 03:22:16 djm Exp $ */
+/* $OpenBSD: auth2-none.c,v 1.15 2008/07/02 12:36:39 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -24,12 +24,6 @@
*/
#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/uio.h>
-
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
#include "xmalloc.h"
#include "key.h"
@@ -39,7 +33,6 @@
#include "log.h"
#include "buffer.h"
#include "servconf.h"
-#include "atomicio.h"
#include "compat.h"
#include "ssh2.h"
#ifdef GSSAPI
@@ -53,68 +46,11 @@ extern ServerOptions options;
/* "none" is allowed only one time */
static int none_enabled = 1;
-char *
-auth2_read_banner(void)
-{
- struct stat st;
- char *banner = NULL;
- size_t len, n;
- int fd;
-
- if ((fd = open(options.banner, O_RDONLY)) == -1)
- return (NULL);
- if (fstat(fd, &st) == -1) {
- close(fd);
- return (NULL);
- }
- if (st.st_size > 1*1024*1024) {
- close(fd);
- return (NULL);
- }
-
- len = (size_t)st.st_size; /* truncate */
- banner = xmalloc(len + 1);
- n = atomicio(read, fd, banner, len);
- close(fd);
-
- if (n != len) {
- xfree(banner);
- return (NULL);
- }
- banner[n] = '\0';
-
- return (banner);
-}
-
-static void
-userauth_banner(void)
-{
- char *banner = NULL;
-
- if (options.banner == NULL ||
- strcasecmp(options.banner, "none") == 0 ||
- (datafellows & SSH_BUG_BANNER) != 0)
- return;
-
- if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
- goto done;
-
- packet_start(SSH2_MSG_USERAUTH_BANNER);
- packet_put_cstring(banner);
- packet_put_cstring(""); /* language, unused */
- packet_send();
- debug("userauth_banner: sent");
-done:
- if (banner)
- xfree(banner);
-}
-
static int
userauth_none(Authctxt *authctxt)
{
none_enabled = 0;
packet_check_eom();
- userauth_banner();
if (options.password_authentication)
return (PRIVSEP(auth_password(authctxt, "")));
return (0);
diff --git a/usr.bin/ssh/auth2.c b/usr.bin/ssh/auth2.c
index 33a4ced5016..d3bbd22b73f 100644
--- a/usr.bin/ssh/auth2.c
+++ b/usr.bin/ssh/auth2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2.c,v 1.116 2007/09/29 00:25:51 dtucker Exp $ */
+/* $OpenBSD: auth2.c,v 1.117 2008/07/02 12:36:39 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -25,11 +25,16 @@
#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <fcntl.h>
#include <pwd.h>
#include <string.h>
#include <stdarg.h>
+#include <unistd.h>
+#include "atomicio.h"
#include "xmalloc.h"
#include "ssh2.h"
#include "packet.h"
@@ -84,10 +89,65 @@ static void input_userauth_request(int, u_int32_t, void *);
static Authmethod *authmethod_lookup(const char *);
static char *authmethods_get(void);
+char *
+auth2_read_banner(void)
+{
+ struct stat st;
+ char *banner = NULL;
+ size_t len, n;
+ int fd;
+
+ if ((fd = open(options.banner, O_RDONLY)) == -1)
+ return (NULL);
+ if (fstat(fd, &st) == -1) {
+ close(fd);
+ return (NULL);
+ }
+ if (st.st_size > 1*1024*1024) {
+ close(fd);
+ return (NULL);
+ }
+
+ len = (size_t)st.st_size; /* truncate */
+ banner = xmalloc(len + 1);
+ n = atomicio(read, fd, banner, len);
+ close(fd);
+
+ if (n != len) {
+ xfree(banner);
+ return (NULL);
+ }
+ banner[n] = '\0';
+
+ return (banner);
+}
+
+static void
+userauth_banner(void)
+{
+ char *banner = NULL;
+
+ if (options.banner == NULL ||
+ strcasecmp(options.banner, "none") == 0 ||
+ (datafellows & SSH_BUG_BANNER) != 0)
+ return;
+
+ if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
+ goto done;
+
+ packet_start(SSH2_MSG_USERAUTH_BANNER);
+ packet_put_cstring(banner);
+ packet_put_cstring(""); /* language, unused */
+ packet_send();
+ debug("userauth_banner: sent");
+done:
+ if (banner)
+ xfree(banner);
+}
+
/*
* loop until authctxt->success == TRUE
*/
-
void
do_authentication2(Authctxt *authctxt)
{
@@ -168,6 +228,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
authctxt->style = style ? xstrdup(style) : NULL;
if (use_privsep)
mm_inform_authserv(service, style);
+ userauth_banner();
} else if (strcmp(user, authctxt->user) != 0 ||
strcmp(service, authctxt->service) != 0) {
packet_disconnect("Change of username or service not allowed: "
@@ -186,7 +247,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
/* try to authenticate user */
m = authmethod_lookup(method);
- if (m != NULL) {
+ if (m != NULL && authctxt->failures < options.max_authtries) {
debug2("input_userauth_request: try method %s", method);
authenticated = m->userauth(authctxt);
}
@@ -227,7 +288,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
/* now we can break out */
authctxt->success = 1;
} else {
- if (authctxt->failures++ > options.max_authtries)
+ if (++authctxt->failures > options.max_authtries)
packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
methods = authmethods_get();
packet_start(SSH2_MSG_USERAUTH_FAILURE);
@@ -279,3 +340,4 @@ authmethod_lookup(const char *name)
name ? name : "NULL");
return NULL;
}
+