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