Mercurial > dropbear
comparison svr-auth.c @ 511:582cb38e4eb5 insecure-nocrypto
propagate from branch 'au.asn.ucc.matt.dropbear' (head cdcc3c729e29544e8b98a408e2dc60e4483dfd2a)
to branch 'au.asn.ucc.matt.dropbear.insecure-nocrypto' (head 0ca38a1cf349f7426ac9de34ebe4c3e3735effab)
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 06 Nov 2008 13:16:55 +0000 |
parents | d58c478bd399 |
children | d3ea8b9672f0 |
comparison
equal
deleted
inserted
replaced
361:461c4b1fb35f | 511:582cb38e4eb5 |
---|---|
40 | 40 |
41 /* initialise the first time for a session, resetting all parameters */ | 41 /* initialise the first time for a session, resetting all parameters */ |
42 void svr_authinitialise() { | 42 void svr_authinitialise() { |
43 | 43 |
44 ses.authstate.failcount = 0; | 44 ses.authstate.failcount = 0; |
45 ses.authstate.pw_name = NULL; | |
46 ses.authstate.pw_dir = NULL; | |
47 ses.authstate.pw_shell = NULL; | |
48 ses.authstate.pw_passwd = NULL; | |
45 authclear(); | 49 authclear(); |
46 | 50 |
47 } | 51 } |
48 | 52 |
49 /* Reset the auth state, but don't reset the failcount. This is for if the | 53 /* Reset the auth state, but don't reset the failcount. This is for if the |
58 #if defined(ENABLE_SVR_PASSWORD_AUTH) || defined(ENABLE_SVR_PAM_AUTH) | 62 #if defined(ENABLE_SVR_PASSWORD_AUTH) || defined(ENABLE_SVR_PAM_AUTH) |
59 if (!svr_opts.noauthpass) { | 63 if (!svr_opts.noauthpass) { |
60 ses.authstate.authtypes |= AUTH_TYPE_PASSWORD; | 64 ses.authstate.authtypes |= AUTH_TYPE_PASSWORD; |
61 } | 65 } |
62 #endif | 66 #endif |
63 | 67 if (ses.authstate.pw_name) { |
68 m_free(ses.authstate.pw_name); | |
69 } | |
70 if (ses.authstate.pw_shell) { | |
71 m_free(ses.authstate.pw_shell); | |
72 } | |
73 if (ses.authstate.pw_dir) { | |
74 m_free(ses.authstate.pw_dir); | |
75 } | |
76 if (ses.authstate.pw_passwd) { | |
77 m_free(ses.authstate.pw_passwd); | |
78 } | |
79 | |
64 } | 80 } |
65 | 81 |
66 /* 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 |
67 * ignore this, but possibly serves as a legal "no trespassing" sign */ | 83 * ignore this, but possibly serves as a legal "no trespassing" sign */ |
68 static void send_msg_userauth_banner() { | 84 static void send_msg_userauth_banner() { |
141 goto out; | 157 goto out; |
142 } | 158 } |
143 | 159 |
144 #ifdef ENABLE_SVR_PASSWORD_AUTH | 160 #ifdef ENABLE_SVR_PASSWORD_AUTH |
145 if (!svr_opts.noauthpass && | 161 if (!svr_opts.noauthpass && |
146 !(svr_opts.norootpass && ses.authstate.pw->pw_uid == 0) ) { | 162 !(svr_opts.norootpass && ses.authstate.pw_uid == 0) ) { |
147 /* user wants to try password auth */ | 163 /* user wants to try password auth */ |
148 if (methodlen == AUTH_METHOD_PASSWORD_LEN && | 164 if (methodlen == AUTH_METHOD_PASSWORD_LEN && |
149 strncmp(methodname, AUTH_METHOD_PASSWORD, | 165 strncmp(methodname, AUTH_METHOD_PASSWORD, |
150 AUTH_METHOD_PASSWORD_LEN) == 0) { | 166 AUTH_METHOD_PASSWORD_LEN) == 0) { |
151 svr_auth_password(); | 167 svr_auth_password(); |
154 } | 170 } |
155 #endif | 171 #endif |
156 | 172 |
157 #ifdef ENABLE_SVR_PAM_AUTH | 173 #ifdef ENABLE_SVR_PAM_AUTH |
158 if (!svr_opts.noauthpass && | 174 if (!svr_opts.noauthpass && |
159 !(svr_opts.norootpass && ses.authstate.pw->pw_uid == 0) ) { | 175 !(svr_opts.norootpass && ses.authstate.pw_uid == 0) ) { |
160 /* user wants to try password auth */ | 176 /* user wants to try password auth */ |
161 if (methodlen == AUTH_METHOD_PASSWORD_LEN && | 177 if (methodlen == AUTH_METHOD_PASSWORD_LEN && |
162 strncmp(methodname, AUTH_METHOD_PASSWORD, | 178 strncmp(methodname, AUTH_METHOD_PASSWORD, |
163 AUTH_METHOD_PASSWORD_LEN) == 0) { | 179 AUTH_METHOD_PASSWORD_LEN) == 0) { |
164 svr_auth_pam(); | 180 svr_auth_pam(); |
185 m_free(username); | 201 m_free(username); |
186 m_free(servicename); | 202 m_free(servicename); |
187 m_free(methodname); | 203 m_free(methodname); |
188 } | 204 } |
189 | 205 |
206 | |
190 /* Check that the username exists, has a non-empty password, and has a valid | 207 /* Check that the username exists, has a non-empty password, and has a valid |
191 * shell. | 208 * shell. |
192 * returns DROPBEAR_SUCCESS on valid username, DROPBEAR_FAILURE on failure */ | 209 * returns DROPBEAR_SUCCESS on valid username, DROPBEAR_FAILURE on failure */ |
193 static int checkusername(unsigned char *username, unsigned int userlen) { | 210 static int checkusername(unsigned char *username, unsigned int userlen) { |
194 | 211 |
195 char* listshell = NULL; | 212 char* listshell = NULL; |
196 char* usershell = NULL; | 213 char* usershell = NULL; |
197 | |
198 TRACE(("enter checkusername")) | 214 TRACE(("enter checkusername")) |
199 if (userlen > MAX_USERNAME_LEN) { | 215 if (userlen > MAX_USERNAME_LEN) { |
200 return DROPBEAR_FAILURE; | 216 return DROPBEAR_FAILURE; |
201 } | 217 } |
202 | 218 |
208 dropbear_log(LOG_WARNING, "client trying multiple usernames from %s", | 224 dropbear_log(LOG_WARNING, "client trying multiple usernames from %s", |
209 svr_ses.addrstring); | 225 svr_ses.addrstring); |
210 m_free(ses.authstate.username); | 226 m_free(ses.authstate.username); |
211 } | 227 } |
212 authclear(); | 228 authclear(); |
213 ses.authstate.pw = getpwnam((char*)username); | 229 fill_passwd(username); |
214 ses.authstate.username = m_strdup(username); | 230 ses.authstate.username = m_strdup(username); |
215 m_free(ses.authstate.printableuser); | |
216 } | 231 } |
217 | 232 |
218 /* check that user exists */ | 233 /* check that user exists */ |
219 if (ses.authstate.pw == NULL) { | 234 if (!ses.authstate.pw_name) { |
220 TRACE(("leave checkusername: user '%s' doesn't exist", username)) | 235 TRACE(("leave checkusername: user '%s' doesn't exist", username)) |
221 dropbear_log(LOG_WARNING, | 236 dropbear_log(LOG_WARNING, |
222 "login attempt for nonexistent user from %s", | 237 "login attempt for nonexistent user from %s", |
223 svr_ses.addrstring); | 238 svr_ses.addrstring); |
224 send_msg_userauth_failure(0, 1); | 239 send_msg_userauth_failure(0, 1); |
225 return DROPBEAR_FAILURE; | 240 return DROPBEAR_FAILURE; |
226 } | 241 } |
227 | 242 |
228 /* We can set it once we know its a real user */ | |
229 ses.authstate.printableuser = m_strdup(ses.authstate.pw->pw_name); | |
230 | |
231 /* check for non-root if desired */ | 243 /* check for non-root if desired */ |
232 if (svr_opts.norootlogin && ses.authstate.pw->pw_uid == 0) { | 244 if (svr_opts.norootlogin && ses.authstate.pw_uid == 0) { |
233 TRACE(("leave checkusername: root login disabled")) | 245 TRACE(("leave checkusername: root login disabled")) |
234 dropbear_log(LOG_WARNING, "root login rejected"); | 246 dropbear_log(LOG_WARNING, "root login rejected"); |
235 send_msg_userauth_failure(0, 1); | 247 send_msg_userauth_failure(0, 1); |
236 return DROPBEAR_FAILURE; | 248 return DROPBEAR_FAILURE; |
237 } | 249 } |
238 | 250 |
239 /* check for an empty password */ | 251 /* check for an empty password */ |
240 if (ses.authstate.pw->pw_passwd[0] == '\0') { | 252 if (ses.authstate.pw_passwd[0] == '\0') { |
241 TRACE(("leave checkusername: empty pword")) | 253 TRACE(("leave checkusername: empty pword")) |
242 dropbear_log(LOG_WARNING, "user '%s' has blank password, rejected", | 254 dropbear_log(LOG_WARNING, "user '%s' has blank password, rejected", |
243 ses.authstate.printableuser); | 255 ses.authstate.pw_name); |
244 send_msg_userauth_failure(0, 1); | 256 send_msg_userauth_failure(0, 1); |
245 return DROPBEAR_FAILURE; | 257 return DROPBEAR_FAILURE; |
246 } | 258 } |
247 | 259 |
248 TRACE(("shell is %s", ses.authstate.pw->pw_shell)) | 260 TRACE(("shell is %s", ses.authstate.pw_shell)) |
249 | 261 |
250 /* check that the shell is set */ | 262 /* check that the shell is set */ |
251 usershell = ses.authstate.pw->pw_shell; | 263 usershell = ses.authstate.pw_shell; |
252 if (usershell[0] == '\0') { | 264 if (usershell[0] == '\0') { |
253 /* empty shell in /etc/passwd means /bin/sh according to passwd(5) */ | 265 /* empty shell in /etc/passwd means /bin/sh according to passwd(5) */ |
254 usershell = "/bin/sh"; | 266 usershell = "/bin/sh"; |
255 } | 267 } |
256 | 268 |
267 } | 279 } |
268 /* no matching shell */ | 280 /* no matching shell */ |
269 endusershell(); | 281 endusershell(); |
270 TRACE(("no matching shell")) | 282 TRACE(("no matching shell")) |
271 dropbear_log(LOG_WARNING, "user '%s' has invalid shell, rejected", | 283 dropbear_log(LOG_WARNING, "user '%s' has invalid shell, rejected", |
272 ses.authstate.printableuser); | 284 ses.authstate.pw_name); |
273 send_msg_userauth_failure(0, 1); | 285 send_msg_userauth_failure(0, 1); |
274 return DROPBEAR_FAILURE; | 286 return DROPBEAR_FAILURE; |
275 | 287 |
276 goodshell: | 288 goodshell: |
277 endusershell(); | 289 endusershell(); |
278 TRACE(("matching shell")) | 290 TRACE(("matching shell")) |
279 | 291 |
280 TRACE(("uid = %d", ses.authstate.pw->pw_uid)) | 292 TRACE(("uid = %d", ses.authstate.pw_uid)) |
281 TRACE(("leave checkusername")) | 293 TRACE(("leave checkusername")) |
282 return DROPBEAR_SUCCESS; | 294 return DROPBEAR_SUCCESS; |
283 | 295 |
284 } | 296 } |
285 | 297 |
313 } | 325 } |
314 | 326 |
315 buf_setpos(typebuf, 0); | 327 buf_setpos(typebuf, 0); |
316 buf_putstring(ses.writepayload, buf_getptr(typebuf, typebuf->len), | 328 buf_putstring(ses.writepayload, buf_getptr(typebuf, typebuf->len), |
317 typebuf->len); | 329 typebuf->len); |
330 | |
331 TRACE(("auth fail: methods %d, '%s'", ses.authstate.authtypes, | |
332 buf_getptr(typebuf, typebuf->len))); | |
333 | |
318 buf_free(typebuf); | 334 buf_free(typebuf); |
319 | 335 |
320 buf_putbyte(ses.writepayload, partial ? 1 : 0); | 336 buf_putbyte(ses.writepayload, partial ? 1 : 0); |
321 encrypt_packet(); | 337 encrypt_packet(); |
322 | |
323 TRACE(("auth fail: methods %d, '%s'", ses.authstate.authtypes, | |
324 buf_getptr(typebuf, typebuf->len))); | |
325 | 338 |
326 if (incrfail) { | 339 if (incrfail) { |
327 usleep(300000); /* XXX improve this */ | 340 usleep(300000); /* XXX improve this */ |
328 ses.authstate.failcount++; | 341 ses.authstate.failcount++; |
329 } | 342 } |
331 if (ses.authstate.failcount >= MAX_AUTH_TRIES) { | 344 if (ses.authstate.failcount >= MAX_AUTH_TRIES) { |
332 char * userstr; | 345 char * userstr; |
333 /* XXX - send disconnect ? */ | 346 /* XXX - send disconnect ? */ |
334 TRACE(("Max auth tries reached, exiting")) | 347 TRACE(("Max auth tries reached, exiting")) |
335 | 348 |
336 if (ses.authstate.printableuser == NULL) { | 349 if (ses.authstate.pw_name == NULL) { |
337 userstr = "is invalid"; | 350 userstr = "is invalid"; |
338 } else { | 351 } else { |
339 userstr = ses.authstate.printableuser; | 352 userstr = ses.authstate.pw_name; |
340 } | 353 } |
341 dropbear_exit("Max auth tries reached - user '%s' from %s", | 354 dropbear_exit("Max auth tries reached - user '%s' from %s", |
342 userstr, svr_ses.addrstring); | 355 userstr, svr_ses.addrstring); |
343 } | 356 } |
344 | 357 |
353 CHECKCLEARTOWRITE(); | 366 CHECKCLEARTOWRITE(); |
354 | 367 |
355 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_SUCCESS); | 368 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_SUCCESS); |
356 encrypt_packet(); | 369 encrypt_packet(); |
357 | 370 |
371 /* authdone must be set after encrypt_packet() for | |
372 * delayed-zlib mode */ | |
358 ses.authstate.authdone = 1; | 373 ses.authstate.authdone = 1; |
359 ses.connecttimeout = 0; | 374 ses.connect_time = 0; |
360 | 375 |
361 | 376 |
362 if (ses.authstate.pw->pw_uid == 0) { | 377 if (ses.authstate.pw_uid == 0) { |
363 ses.allowprivport = 1; | 378 ses.allowprivport = 1; |
364 } | 379 } |
365 | 380 |
366 /* Remove from the list of pre-auth sockets. Should be m_close(), since if | 381 /* Remove from the list of pre-auth sockets. Should be m_close(), since if |
367 * we fail, we might end up leaking connection slots, and disallow new | 382 * we fail, we might end up leaking connection slots, and disallow new |