comparison svr-auth.c @ 835:4095b6d7c9fc ecc

Merge in changes from the past couple of releases
author Matt Johnston <matt@ucc.asn.au>
date Fri, 18 Oct 2013 21:38:01 +0800
parents 7dcb46da72d9 8fe36617bf4e
children 7540c0822374
comparison
equal deleted inserted replaced
807:75509065db53 835:4095b6d7c9fc
35 #include "runopts.h" 35 #include "runopts.h"
36 #include "random.h" 36 #include "random.h"
37 37
38 static void authclear(); 38 static void authclear();
39 static int checkusername(unsigned char *username, unsigned int userlen); 39 static int checkusername(unsigned char *username, unsigned int userlen);
40 static void send_msg_userauth_banner();
41 40
42 /* initialise the first time for a session, resetting all parameters */ 41 /* initialise the first time for a session, resetting all parameters */
43 void svr_authinitialise() { 42 void svr_authinitialise() {
44 43
45 ses.authstate.failcount = 0; 44 ses.authstate.failcount = 0;
80 79
81 } 80 }
82 81
83 /* Send a banner message if specified to the client. The client might 82 /* Send a banner message if specified to the client. The client might
84 * ignore this, but possibly serves as a legal "no trespassing" sign */ 83 * ignore this, but possibly serves as a legal "no trespassing" sign */
85 static void send_msg_userauth_banner() { 84 void send_msg_userauth_banner(buffer *banner) {
86 85
87 TRACE(("enter send_msg_userauth_banner")) 86 TRACE(("enter send_msg_userauth_banner"))
88 if (svr_opts.banner == NULL) {
89 TRACE(("leave send_msg_userauth_banner: banner is NULL"))
90 return;
91 }
92 87
93 CHECKCLEARTOWRITE(); 88 CHECKCLEARTOWRITE();
94 89
95 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_BANNER); 90 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_BANNER);
96 buf_putbufstring(ses.writepayload, svr_opts.banner); 91 buf_putbufstring(ses.writepayload, banner);
97 buf_putstring(ses.writepayload, "en", 2); 92 buf_putstring(ses.writepayload, "en", 2);
98 93
99 encrypt_packet(); 94 encrypt_packet();
100 buf_free(svr_opts.banner);
101 svr_opts.banner = NULL;
102 95
103 TRACE(("leave send_msg_userauth_banner")) 96 TRACE(("leave send_msg_userauth_banner"))
104 } 97 }
105 98
106 /* handle a userauth request, check validity, pass to password or pubkey 99 /* handle a userauth request, check validity, pass to password or pubkey
107 * checking, and handle success or failure */ 100 * checking, and handle success or failure */
108 void recv_msg_userauth_request() { 101 void recv_msg_userauth_request() {
109 102
110 unsigned char *username = NULL, *servicename = NULL, *methodname = NULL; 103 unsigned char *username = NULL, *servicename = NULL, *methodname = NULL;
111 unsigned int userlen, servicelen, methodlen; 104 unsigned int userlen, servicelen, methodlen;
105 int valid_user = 0;
112 106
113 TRACE(("enter recv_msg_userauth_request")) 107 TRACE(("enter recv_msg_userauth_request"))
114 108
115 /* ignore packets if auth is already done */ 109 /* ignore packets if auth is already done */
116 if (ses.authstate.authdone == 1) { 110 if (ses.authstate.authdone == 1) {
118 return; 112 return;
119 } 113 }
120 114
121 /* send the banner if it exists, it will only exist once */ 115 /* send the banner if it exists, it will only exist once */
122 if (svr_opts.banner) { 116 if (svr_opts.banner) {
123 send_msg_userauth_banner(); 117 send_msg_userauth_banner(svr_opts.banner);
124 } 118 buf_free(svr_opts.banner);
125 119 svr_opts.banner = NULL;
126 120 }
121
127 username = buf_getstring(ses.payload, &userlen); 122 username = buf_getstring(ses.payload, &userlen);
128 servicename = buf_getstring(ses.payload, &servicelen); 123 servicename = buf_getstring(ses.payload, &servicelen);
129 methodname = buf_getstring(ses.payload, &methodlen); 124 methodname = buf_getstring(ses.payload, &methodlen);
130 125
131 /* only handle 'ssh-connection' currently */ 126 /* only handle 'ssh-connection' currently */
138 m_free(servicename); 133 m_free(servicename);
139 m_free(methodname); 134 m_free(methodname);
140 dropbear_exit("unknown service in auth"); 135 dropbear_exit("unknown service in auth");
141 } 136 }
142 137
143 /* check username is good before continuing */ 138 /* check username is good before continuing.
144 if (checkusername(username, userlen) == DROPBEAR_FAILURE) { 139 * the 'incrfail' varies depending on the auth method to
145 /* username is invalid/no shell/etc - send failure */ 140 * avoid giving away which users exist on the system through
146 TRACE(("sending checkusername failure")) 141 * the time delay. */
147 send_msg_userauth_failure(0, 1); 142 if (checkusername(username, userlen) == DROPBEAR_SUCCESS) {
148 goto out; 143 valid_user = 1;
149 } 144 }
150 145
151 /* user wants to know what methods are supported */ 146 /* user wants to know what methods are supported */
152 if (methodlen == AUTH_METHOD_NONE_LEN && 147 if (methodlen == AUTH_METHOD_NONE_LEN &&
153 strncmp(methodname, AUTH_METHOD_NONE, 148 strncmp(methodname, AUTH_METHOD_NONE,
154 AUTH_METHOD_NONE_LEN) == 0) { 149 AUTH_METHOD_NONE_LEN) == 0) {
155 TRACE(("recv_msg_userauth_request: 'none' request")) 150 TRACE(("recv_msg_userauth_request: 'none' request"))
156 if (svr_opts.allowblankpass 151 if (valid_user
152 && svr_opts.allowblankpass
157 && !svr_opts.noauthpass 153 && !svr_opts.noauthpass
158 && !(svr_opts.norootpass && ses.authstate.pw_uid == 0) 154 && !(svr_opts.norootpass && ses.authstate.pw_uid == 0)
159 && ses.authstate.pw_passwd[0] == '\0') 155 && ses.authstate.pw_passwd[0] == '\0')
160 { 156 {
161 dropbear_log(LOG_NOTICE, 157 dropbear_log(LOG_NOTICE,
165 send_msg_userauth_success(); 161 send_msg_userauth_success();
166 goto out; 162 goto out;
167 } 163 }
168 else 164 else
169 { 165 {
166 /* 'none' has no failure delay */
170 send_msg_userauth_failure(0, 0); 167 send_msg_userauth_failure(0, 0);
171 goto out; 168 goto out;
172 } 169 }
173 } 170 }
174 171
177 !(svr_opts.norootpass && ses.authstate.pw_uid == 0) ) { 174 !(svr_opts.norootpass && ses.authstate.pw_uid == 0) ) {
178 /* user wants to try password auth */ 175 /* user wants to try password auth */
179 if (methodlen == AUTH_METHOD_PASSWORD_LEN && 176 if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
180 strncmp(methodname, AUTH_METHOD_PASSWORD, 177 strncmp(methodname, AUTH_METHOD_PASSWORD,
181 AUTH_METHOD_PASSWORD_LEN) == 0) { 178 AUTH_METHOD_PASSWORD_LEN) == 0) {
182 svr_auth_password(); 179 if (valid_user) {
183 goto out; 180 svr_auth_password();
181 goto out;
182 }
184 } 183 }
185 } 184 }
186 #endif 185 #endif
187 186
188 #ifdef ENABLE_SVR_PAM_AUTH 187 #ifdef ENABLE_SVR_PAM_AUTH
190 !(svr_opts.norootpass && ses.authstate.pw_uid == 0) ) { 189 !(svr_opts.norootpass && ses.authstate.pw_uid == 0) ) {
191 /* user wants to try password auth */ 190 /* user wants to try password auth */
192 if (methodlen == AUTH_METHOD_PASSWORD_LEN && 191 if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
193 strncmp(methodname, AUTH_METHOD_PASSWORD, 192 strncmp(methodname, AUTH_METHOD_PASSWORD,
194 AUTH_METHOD_PASSWORD_LEN) == 0) { 193 AUTH_METHOD_PASSWORD_LEN) == 0) {
195 svr_auth_pam(); 194 if (valid_user) {
196 goto out; 195 svr_auth_pam();
196 goto out;
197 }
197 } 198 }
198 } 199 }
199 #endif 200 #endif
200 201
201 #ifdef ENABLE_SVR_PUBKEY_AUTH 202 #ifdef ENABLE_SVR_PUBKEY_AUTH
202 /* user wants to try pubkey auth */ 203 /* user wants to try pubkey auth */
203 if (methodlen == AUTH_METHOD_PUBKEY_LEN && 204 if (methodlen == AUTH_METHOD_PUBKEY_LEN &&
204 strncmp(methodname, AUTH_METHOD_PUBKEY, 205 strncmp(methodname, AUTH_METHOD_PUBKEY,
205 AUTH_METHOD_PUBKEY_LEN) == 0) { 206 AUTH_METHOD_PUBKEY_LEN) == 0) {
206 svr_auth_pubkey(); 207 if (valid_user) {
208 svr_auth_pubkey();
209 } else {
210 /* pubkey has no failure delay */
211 send_msg_userauth_failure(0, 0);
212 }
207 goto out; 213 goto out;
208 } 214 }
209 #endif 215 #endif
210 216
211 /* nothing matched, we just fail */ 217 /* nothing matched, we just fail with a delay */
212 send_msg_userauth_failure(0, 1); 218 send_msg_userauth_failure(0, 1);
213 219
214 out: 220 out:
215 221
216 m_free(username); 222 m_free(username);
249 if (!ses.authstate.pw_name) { 255 if (!ses.authstate.pw_name) {
250 TRACE(("leave checkusername: user '%s' doesn't exist", username)) 256 TRACE(("leave checkusername: user '%s' doesn't exist", username))
251 dropbear_log(LOG_WARNING, 257 dropbear_log(LOG_WARNING,
252 "Login attempt for nonexistent user from %s", 258 "Login attempt for nonexistent user from %s",
253 svr_ses.addrstring); 259 svr_ses.addrstring);
254 send_msg_userauth_failure(0, 1);
255 return DROPBEAR_FAILURE; 260 return DROPBEAR_FAILURE;
256 } 261 }
257 262
258 /* check if we are running as non-root, and login user is different from the server */ 263 /* check if we are running as non-root, and login user is different from the server */
259 uid = geteuid(); 264 uid = geteuid();
261 TRACE(("running as nonroot, only server uid is allowed")) 266 TRACE(("running as nonroot, only server uid is allowed"))
262 dropbear_log(LOG_WARNING, 267 dropbear_log(LOG_WARNING,
263 "Login attempt with wrong user %s from %s", 268 "Login attempt with wrong user %s from %s",
264 ses.authstate.pw_name, 269 ses.authstate.pw_name,
265 svr_ses.addrstring); 270 svr_ses.addrstring);
266 send_msg_userauth_failure(0, 1);
267 return DROPBEAR_FAILURE; 271 return DROPBEAR_FAILURE;
268 } 272 }
269 273
270 /* check for non-root if desired */ 274 /* check for non-root if desired */
271 if (svr_opts.norootlogin && ses.authstate.pw_uid == 0) { 275 if (svr_opts.norootlogin && ses.authstate.pw_uid == 0) {
272 TRACE(("leave checkusername: root login disabled")) 276 TRACE(("leave checkusername: root login disabled"))
273 dropbear_log(LOG_WARNING, "root login rejected"); 277 dropbear_log(LOG_WARNING, "root login rejected");
274 send_msg_userauth_failure(0, 1);
275 return DROPBEAR_FAILURE; 278 return DROPBEAR_FAILURE;
276 } 279 }
277 280
278 TRACE(("shell is %s", ses.authstate.pw_shell)) 281 TRACE(("shell is %s", ses.authstate.pw_shell))
279 282
298 /* no matching shell */ 301 /* no matching shell */
299 endusershell(); 302 endusershell();
300 TRACE(("no matching shell")) 303 TRACE(("no matching shell"))
301 dropbear_log(LOG_WARNING, "User '%s' has invalid shell, rejected", 304 dropbear_log(LOG_WARNING, "User '%s' has invalid shell, rejected",
302 ses.authstate.pw_name); 305 ses.authstate.pw_name);
303 send_msg_userauth_failure(0, 1);
304 return DROPBEAR_FAILURE; 306 return DROPBEAR_FAILURE;
305 307
306 goodshell: 308 goodshell:
307 endusershell(); 309 endusershell();
308 TRACE(("matching shell")) 310 TRACE(("matching shell"))
309 311
310 TRACE(("uid = %d", ses.authstate.pw_uid)) 312 TRACE(("uid = %d", ses.authstate.pw_uid))
311 TRACE(("leave checkusername")) 313 TRACE(("leave checkusername"))
312 return DROPBEAR_SUCCESS; 314 return DROPBEAR_SUCCESS;
313
314 } 315 }
315 316
316 /* Send a failure message to the client, in responds to a userauth_request. 317 /* Send a failure message to the client, in responds to a userauth_request.
317 * Partial indicates whether to set the "partial success" flag, 318 * Partial indicates whether to set the "partial success" flag,
318 * incrfail is whether to count this failure in the failure count (which 319 * incrfail is whether to count this failure in the failure count (which
353 encrypt_packet(); 354 encrypt_packet();
354 355
355 if (incrfail) { 356 if (incrfail) {
356 unsigned int delay; 357 unsigned int delay;
357 genrandom((unsigned char*)&delay, sizeof(delay)); 358 genrandom((unsigned char*)&delay, sizeof(delay));
358 /* We delay for 300ms +- 50ms, 0.1ms granularity */ 359 /* We delay for 300ms +- 50ms */
359 delay = 250000 + (delay % 1000)*100; 360 delay = 250000 + (delay % 100000);
360 usleep(delay); 361 usleep(delay);
361 ses.authstate.failcount++; 362 ses.authstate.failcount++;
362 } 363 }
363 364
364 if (ses.authstate.failcount >= MAX_AUTH_TRIES) { 365 if (ses.authstate.failcount >= MAX_AUTH_TRIES) {