diff options
Diffstat (limited to 'auth2.c')
-rw-r--r-- | auth2.c | 88 |
1 files changed, 81 insertions, 7 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth2.c,v 1.115 2007/04/14 22:01:58 stevesk Exp $ */ | 1 | /* $OpenBSD: auth2.c,v 1.119 2008/07/04 23:30:16 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,12 +26,17 @@ | |||
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" |
39 | #include "atomicio.h" | ||
35 | #include "ssh2.h" | 40 | #include "ssh2.h" |
36 | #include "packet.h" | 41 | #include "packet.h" |
37 | #include "log.h" | 42 | #include "log.h" |
@@ -89,12 +94,75 @@ static void input_userauth_request(int, u_int32_t, void *); | |||
89 | /* helper */ | 94 | /* helper */ |
90 | static Authmethod *authmethod_lookup(const char *); | 95 | static Authmethod *authmethod_lookup(const char *); |
91 | static char *authmethods_get(void); | 96 | static char *authmethods_get(void); |
92 | int user_key_allowed(struct passwd *, Key *); | 97 | |
98 | char * | ||
99 | auth2_read_banner(void) | ||
100 | { | ||
101 | struct stat st; | ||
102 | char *banner = NULL; | ||
103 | size_t len, n; | ||
104 | int fd; | ||
105 | |||
106 | if ((fd = open(options.banner, O_RDONLY)) == -1) | ||
107 | return (NULL); | ||
108 | if (fstat(fd, &st) == -1) { | ||
109 | close(fd); | ||
110 | return (NULL); | ||
111 | } | ||
112 | if (st.st_size > 1*1024*1024) { | ||
113 | close(fd); | ||
114 | return (NULL); | ||
115 | } | ||
116 | |||
117 | len = (size_t)st.st_size; /* truncate */ | ||
118 | banner = xmalloc(len + 1); | ||
119 | n = atomicio(read, fd, banner, len); | ||
120 | close(fd); | ||
121 | |||
122 | if (n != len) { | ||
123 | xfree(banner); | ||
124 | return (NULL); | ||
125 | } | ||
126 | banner[n] = '\0'; | ||
127 | |||
128 | return (banner); | ||
129 | } | ||
130 | |||
131 | void | ||
132 | userauth_send_banner(const char *msg) | ||
133 | { | ||
134 | if (datafellows & SSH_BUG_BANNER) | ||
135 | return; | ||
136 | |||
137 | packet_start(SSH2_MSG_USERAUTH_BANNER); | ||
138 | packet_put_cstring(msg); | ||
139 | packet_put_cstring(""); /* language, unused */ | ||
140 | packet_send(); | ||
141 | debug("%s: sent", __func__); | ||
142 | } | ||
143 | |||
144 | static void | ||
145 | userauth_banner(void) | ||
146 | { | ||
147 | char *banner = NULL; | ||
148 | |||
149 | if (options.banner == NULL || | ||
150 | strcasecmp(options.banner, "none") == 0 || | ||
151 | (datafellows & SSH_BUG_BANNER) != 0) | ||
152 | return; | ||
153 | |||
154 | if ((banner = PRIVSEP(auth2_read_banner())) == NULL) | ||
155 | goto done; | ||
156 | userauth_send_banner(banner); | ||
157 | |||
158 | done: | ||
159 | if (banner) | ||
160 | xfree(banner); | ||
161 | } | ||
93 | 162 | ||
94 | /* | 163 | /* |
95 | * loop until authctxt->success == TRUE | 164 | * loop until authctxt->success == TRUE |
96 | */ | 165 | */ |
97 | |||
98 | void | 166 | void |
99 | do_authentication2(Authctxt *authctxt) | 167 | do_authentication2(Authctxt *authctxt) |
100 | { | 168 | { |
@@ -188,6 +256,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) | |||
188 | authctxt->role = role ? xstrdup(role) : NULL; | 256 | authctxt->role = role ? xstrdup(role) : NULL; |
189 | if (use_privsep) | 257 | if (use_privsep) |
190 | mm_inform_authserv(service, style, role); | 258 | mm_inform_authserv(service, style, role); |
259 | userauth_banner(); | ||
191 | } else if (strcmp(user, authctxt->user) != 0 || | 260 | } else if (strcmp(user, authctxt->user) != 0 || |
192 | strcmp(service, authctxt->service) != 0) { | 261 | strcmp(service, authctxt->service) != 0) { |
193 | packet_disconnect("Change of username or service not allowed: " | 262 | packet_disconnect("Change of username or service not allowed: " |
@@ -207,7 +276,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) | |||
207 | 276 | ||
208 | /* try to authenticate user */ | 277 | /* try to authenticate user */ |
209 | m = authmethod_lookup(method); | 278 | m = authmethod_lookup(method); |
210 | if (m != NULL) { | 279 | if (m != NULL && authctxt->failures < options.max_authtries) { |
211 | debug2("input_userauth_request: try method %s", method); | 280 | debug2("input_userauth_request: try method %s", method); |
212 | authenticated = m->userauth(authctxt); | 281 | authenticated = m->userauth(authctxt); |
213 | } | 282 | } |
@@ -274,9 +343,13 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method) | |||
274 | /* now we can break out */ | 343 | /* now we can break out */ |
275 | authctxt->success = 1; | 344 | authctxt->success = 1; |
276 | } else { | 345 | } else { |
277 | /* Dont count server configuration issues against the client */ | 346 | |
278 | if (!authctxt->server_caused_failure && | 347 | /* Allow initial try of "none" auth without failure penalty */ |
279 | authctxt->failures++ > options.max_authtries) { | 348 | /* Don't count server configuration issues against the client */ |
349 | if (!authctxt->server_caused_failure && | ||
350 | (authctxt->attempt > 1 || strcmp(method, "none") != 0)) | ||
351 | authctxt->failures++; | ||
352 | if (authctxt->failures >= options.max_authtries) { | ||
280 | #ifdef SSH_AUDIT_EVENTS | 353 | #ifdef SSH_AUDIT_EVENTS |
281 | PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); | 354 | PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); |
282 | #endif | 355 | #endif |
@@ -332,3 +405,4 @@ authmethod_lookup(const char *name) | |||
332 | name ? name : "NULL"); | 405 | name ? name : "NULL"); |
333 | return NULL; | 406 | return NULL; |
334 | } | 407 | } |
408 | |||