summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@zip.com.au>2008-07-02 22:56:09 +1000
committerDarren Tucker <dtucker@zip.com.au>2008-07-02 22:56:09 +1000
commit4230a5dc305d1b39bc118befcc1ccfe933281b75 (patch)
tree68bd413a4e590c6aae5ea8e0b90c76baf933a7e6
parent33c787f23c0267c679ad3e3f8bc4679c6ced5ea3 (diff)
- djm@cvs.openbsd.org 2008/07/02 12:36:39
[auth2-none.c auth2.c] 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--ChangeLog18
-rw-r--r--auth2-none.c72
-rw-r--r--auth2.c78
3 files changed, 94 insertions, 74 deletions
diff --git a/ChangeLog b/ChangeLog
index dc8048939..873e1459d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -33,6 +33,22 @@
33 Merge duplicate host key file checks, based in part on a patch from Rob 33 Merge duplicate host key file checks, based in part on a patch from Rob
34 Holland via bz #1348 . Also checks for non-regular files during protocol 34 Holland via bz #1348 . Also checks for non-regular files during protocol
35 1 RSA auth. ok djm@ 35 1 RSA auth. ok djm@
36 - djm@cvs.openbsd.org 2008/07/02 12:36:39
37 [auth2-none.c auth2.c]
38 Make protocol 2 MaxAuthTries behaviour a little more sensible:
39 Check whether client has exceeded MaxAuthTries before running
40 an authentication method and skip it if they have, previously it
41 would always allow one try (for "none" auth).
42 Preincrement failure count before post-auth test - previously this
43 checked and postincremented, also to allow one "none" try.
44 Together, these two changes always count the "none" auth method
45 which could be skipped by a malicious client (e.g. an SSH worm)
46 to get an extra attempt at a real auth method. They also make
47 MaxAuthTries=0 a useful way to block users entirely (esp. in a
48 sshd_config Match block).
49 Also, move sending of any preauth banner from "none" auth method
50 to the first call to input_userauth_request(), so worms that skip
51 the "none" method get to see it too.
36 52
3720080630 5320080630
38 - (djm) OpenBSD CVS Sync 54 - (djm) OpenBSD CVS Sync
@@ -4516,4 +4532,4 @@
4516 OpenServer 6 and add osr5bigcrypt support so when someone migrates 4532 OpenServer 6 and add osr5bigcrypt support so when someone migrates
4517 passwords between UnixWare and OpenServer they will still work. OK dtucker@ 4533 passwords between UnixWare and OpenServer they will still work. OK dtucker@
4518 4534
4519$Id: ChangeLog,v 1.5047 2008/07/02 12:37:30 dtucker Exp $ 4535$Id: ChangeLog,v 1.5048 2008/07/02 12:56:09 dtucker Exp $
diff --git a/auth2-none.c b/auth2-none.c
index 28e593e6c..10accfe55 100644
--- a/auth2-none.c
+++ b/auth2-none.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-none.c,v 1.14 2007/08/23 03:22:16 djm Exp $ */ 1/* $OpenBSD: auth2-none.c,v 1.15 2008/07/02 12:36:39 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -31,9 +31,10 @@
31 31
32#include <fcntl.h> 32#include <fcntl.h>
33#include <stdarg.h> 33#include <stdarg.h>
34#include <unistd.h>
35#include <string.h> 34#include <string.h>
35#include <unistd.h>
36 36
37#include "atomicio.h"
37#include "xmalloc.h" 38#include "xmalloc.h"
38#include "key.h" 39#include "key.h"
39#include "hostfile.h" 40#include "hostfile.h"
@@ -42,7 +43,6 @@
42#include "log.h" 43#include "log.h"
43#include "buffer.h" 44#include "buffer.h"
44#include "servconf.h" 45#include "servconf.h"
45#include "atomicio.h"
46#include "compat.h" 46#include "compat.h"
47#include "ssh2.h" 47#include "ssh2.h"
48#ifdef GSSAPI 48#ifdef GSSAPI
@@ -56,77 +56,11 @@ extern ServerOptions options;
56/* "none" is allowed only one time */ 56/* "none" is allowed only one time */
57static int none_enabled = 1; 57static int none_enabled = 1;
58 58
59char *
60auth2_read_banner(void)
61{
62 struct stat st;
63 char *banner = NULL;
64 size_t len, n;
65 int fd;
66
67 if ((fd = open(options.banner, O_RDONLY)) == -1)
68 return (NULL);
69 if (fstat(fd, &st) == -1) {
70 close(fd);
71 return (NULL);
72 }
73 if (st.st_size > 1*1024*1024) {
74 close(fd);
75 return (NULL);
76 }
77
78 len = (size_t)st.st_size; /* truncate */
79 banner = xmalloc(len + 1);
80 n = atomicio(read, fd, banner, len);
81 close(fd);
82
83 if (n != len) {
84 xfree(banner);
85 return (NULL);
86 }
87 banner[n] = '\0';
88
89 return (banner);
90}
91
92void
93userauth_send_banner(const char *msg)
94{
95 if (datafellows & SSH_BUG_BANNER)
96 return;
97
98 packet_start(SSH2_MSG_USERAUTH_BANNER);
99 packet_put_cstring(msg);
100 packet_put_cstring(""); /* language, unused */
101 packet_send();
102 debug("%s: sent", __func__);
103}
104
105static void
106userauth_banner(void)
107{
108 char *banner = NULL;
109
110 if (options.banner == NULL ||
111 strcasecmp(options.banner, "none") == 0 ||
112 (datafellows & SSH_BUG_BANNER) != 0)
113 return;
114
115 if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
116 goto done;
117 userauth_send_banner(banner);
118
119done:
120 if (banner)
121 xfree(banner);
122}
123
124static int 59static int
125userauth_none(Authctxt *authctxt) 60userauth_none(Authctxt *authctxt)
126{ 61{
127 none_enabled = 0; 62 none_enabled = 0;
128 packet_check_eom(); 63 packet_check_eom();
129 userauth_banner();
130#ifdef HAVE_CYGWIN 64#ifdef HAVE_CYGWIN
131 if (check_nt_auth(1, authctxt->pw) == 0) 65 if (check_nt_auth(1, authctxt->pw) == 0)
132 return (0); 66 return (0);
diff --git a/auth2.c b/auth2.c
index 03d7f09dc..31f01f9fb 100644
--- a/auth2.c
+++ b/auth2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2.c,v 1.116 2007/09/29 00:25:51 dtucker Exp $ */ 1/* $OpenBSD: auth2.c,v 1.117 2008/07/02 12:36:39 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -26,10 +26,14 @@
26#include "includes.h" 26#include "includes.h"
27 27
28#include <sys/types.h> 28#include <sys/types.h>
29#include <sys/stat.h>
30#include <sys/uio.h>
29 31
32#include <fcntl.h>
30#include <pwd.h> 33#include <pwd.h>
31#include <stdarg.h> 34#include <stdarg.h>
32#include <string.h> 35#include <string.h>
36#include <unistd.h>
33 37
34#include "xmalloc.h" 38#include "xmalloc.h"
35#include "ssh2.h" 39#include "ssh2.h"
@@ -88,10 +92,74 @@ static void input_userauth_request(int, u_int32_t, void *);
88static Authmethod *authmethod_lookup(const char *); 92static Authmethod *authmethod_lookup(const char *);
89static char *authmethods_get(void); 93static char *authmethods_get(void);
90 94
95char *
96auth2_read_banner(void)
97{
98 struct stat st;
99 char *banner = NULL;
100 size_t len, n;
101 int fd;
102
103 if ((fd = open(options.banner, O_RDONLY)) == -1)
104 return (NULL);
105 if (fstat(fd, &st) == -1) {
106 close(fd);
107 return (NULL);
108 }
109 if (st.st_size > 1*1024*1024) {
110 close(fd);
111 return (NULL);
112 }
113
114 len = (size_t)st.st_size; /* truncate */
115 banner = xmalloc(len + 1);
116 n = atomicio(read, fd, banner, len);
117 close(fd);
118
119 if (n != len) {
120 xfree(banner);
121 return (NULL);
122 }
123 banner[n] = '\0';
124
125 return (banner);
126}
127
128void
129userauth_send_banner(const char *msg)
130{
131 if (datafellows & SSH_BUG_BANNER)
132 return;
133
134 packet_start(SSH2_MSG_USERAUTH_BANNER);
135 packet_put_cstring(msg);
136 packet_put_cstring(""); /* language, unused */
137 packet_send();
138 debug("%s: sent", __func__);
139}
140
141static void
142userauth_banner(void)
143{
144 char *banner = NULL;
145
146 if (options.banner == NULL ||
147 strcasecmp(options.banner, "none") == 0 ||
148 (datafellows & SSH_BUG_BANNER) != 0)
149 return;
150
151 if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
152 goto done;
153 userauth_send_banner(banner);
154
155done:
156 if (banner)
157 xfree(banner);
158}
159
91/* 160/*
92 * loop until authctxt->success == TRUE 161 * loop until authctxt->success == TRUE
93 */ 162 */
94
95void 163void
96do_authentication2(Authctxt *authctxt) 164do_authentication2(Authctxt *authctxt)
97{ 165{
@@ -179,6 +247,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
179 authctxt->style = style ? xstrdup(style) : NULL; 247 authctxt->style = style ? xstrdup(style) : NULL;
180 if (use_privsep) 248 if (use_privsep)
181 mm_inform_authserv(service, style); 249 mm_inform_authserv(service, style);
250 userauth_banner();
182 } else if (strcmp(user, authctxt->user) != 0 || 251 } else if (strcmp(user, authctxt->user) != 0 ||
183 strcmp(service, authctxt->service) != 0) { 252 strcmp(service, authctxt->service) != 0) {
184 packet_disconnect("Change of username or service not allowed: " 253 packet_disconnect("Change of username or service not allowed: "
@@ -197,7 +266,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
197 266
198 /* try to authenticate user */ 267 /* try to authenticate user */
199 m = authmethod_lookup(method); 268 m = authmethod_lookup(method);
200 if (m != NULL) { 269 if (m != NULL && authctxt->failures < options.max_authtries) {
201 debug2("input_userauth_request: try method %s", method); 270 debug2("input_userauth_request: try method %s", method);
202 authenticated = m->userauth(authctxt); 271 authenticated = m->userauth(authctxt);
203 } 272 }
@@ -264,7 +333,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
264 /* now we can break out */ 333 /* now we can break out */
265 authctxt->success = 1; 334 authctxt->success = 1;
266 } else { 335 } else {
267 if (authctxt->failures++ > options.max_authtries) { 336 if (++authctxt->failures > options.max_authtries) {
268#ifdef SSH_AUDIT_EVENTS 337#ifdef SSH_AUDIT_EVENTS
269 PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); 338 PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
270#endif 339#endif
@@ -320,3 +389,4 @@ authmethod_lookup(const char *name)
320 name ? name : "NULL"); 389 name ? name : "NULL");
321 return NULL; 390 return NULL;
322} 391}
392