summaryrefslogtreecommitdiff
path: root/auth1.c
diff options
context:
space:
mode:
authorBen Lindstrom <mouring@eviladmin.org>2001-01-19 04:26:52 +0000
committerBen Lindstrom <mouring@eviladmin.org>2001-01-19 04:26:52 +0000
commitdb65e8fdedadaf79df2d8393a4d43e9094c80649 (patch)
treee5902db5ee2b69f9f3c2fa0dbdeb7f4fc20c68b4 /auth1.c
parent5aa80596f76ce36dee4623a00a55548834c3328d (diff)
Please grep through the source and look for 'ISSUE' comments and verify
that I was able to get all the portable bits in the right location. As for the SKEY comment there is an email out to Markus as to how it should be resolved. Until then I just #ifdef SKEY/#endif out the whole block. - (bal) OpenBSD Resync - markus@cvs.openbsd.org 2001/01/18 16:20:21 [log-client.c log-server.c log.c readconf.c servconf.c ssh.1 ssh.h sshd.8 sshd.c] log() is at pri=LOG_INFO, since LOG_NOTICE goes to /dev/console on many systems - markus@cvs.openbsd.org 2001/01/18 16:59:59 [auth-passwd.c auth.c auth.h auth1.c auth2.c serverloop.c session.c session.h sshconnect1.c] 1) removes fake skey from sshd, since this will be much harder with /usr/libexec/auth/login_XXX 2) share/unify code used in ssh-1 and ssh-2 authentication (server side) 3) make addition of BSD_AUTH and other challenge reponse methods easier. - markus@cvs.openbsd.org 2001/01/18 17:12:43 [auth-chall.c auth2-chall.c] rename *-skey.c *-chall.c since the files are not skey specific
Diffstat (limited to 'auth1.c')
-rw-r--r--auth1.c216
1 files changed, 88 insertions, 128 deletions
diff --git a/auth1.c b/auth1.c
index 51ed8f773..0f21c4c7c 100644
--- a/auth1.c
+++ b/auth1.c
@@ -10,7 +10,7 @@
10 */ 10 */
11 11
12#include "includes.h" 12#include "includes.h"
13RCSID("$OpenBSD: auth1.c,v 1.10 2001/01/07 19:06:25 markus Exp $"); 13RCSID("$OpenBSD: auth1.c,v 1.11 2001/01/18 16:59:59 markus Exp $");
14 14
15#ifdef HAVE_OSF_SIA 15#ifdef HAVE_OSF_SIA
16# include <sia.h> 16# include <sia.h>
@@ -56,41 +56,53 @@ get_authname(int type)
56 return "rhosts-rsa"; 56 return "rhosts-rsa";
57 case SSH_CMSG_AUTH_RHOSTS: 57 case SSH_CMSG_AUTH_RHOSTS:
58 return "rhosts"; 58 return "rhosts";
59 case SSH_CMSG_AUTH_TIS:
60 case SSH_CMSG_AUTH_TIS_RESPONSE:
61 return "challenge-response";
59#ifdef KRB4 62#ifdef KRB4
60 case SSH_CMSG_AUTH_KERBEROS: 63 case SSH_CMSG_AUTH_KERBEROS:
61 return "kerberos"; 64 return "kerberos";
62#endif 65#endif
63#ifdef SKEY
64 case SSH_CMSG_AUTH_TIS_RESPONSE:
65 return "s/key";
66#endif
67 } 66 }
68 snprintf(buf, sizeof buf, "bad-auth-msg-%d", type); 67 snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
69 return buf; 68 return buf;
70} 69}
71 70
72/* 71/*
73 * read packets and try to authenticate local user 'luser'. 72 * read packets, try to authenticate the user and
74 * return if authentication is successful. not that pw == NULL 73 * return only if authentication is successful
75 * if the user does not exists or is not allowed to login.
76 * each auth method has to 'fake' authentication for nonexisting
77 * users.
78 */ 74 */
79void 75void
80do_authloop(struct passwd * pw, char *luser) 76do_authloop(Authctxt *authctxt)
81{ 77{
82 int authenticated = 0; 78 int authenticated = 0;
83 int attempt = 0;
84 u_int bits; 79 u_int bits;
85 RSA *client_host_key; 80 RSA *client_host_key;
86 BIGNUM *n; 81 BIGNUM *n;
87 char *client_user, *password; 82 char *client_user, *password;
88 char user[1024]; 83 char info[1024];
89 u_int dlen; 84 u_int dlen;
90 int plen, nlen, elen; 85 int plen, nlen, elen;
91 u_int ulen; 86 u_int ulen;
92 int type = 0; 87 int type = 0;
93 void (*authlog) (const char *fmt,...) = verbose; 88 struct passwd *pw = authctxt->pw;
89
90 debug("Attempting authentication for %s%.100s.",
91 authctxt->valid ? "" : "illegal user ", authctxt->user);
92
93 /* If the user has no password, accept authentication immediately. */
94 if (options.password_authentication &&
95#ifdef KRB4
96 (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
97#endif
98#ifdef USE_PAM /* ISSUE: Right?? */
99 auth_pam_password(pw, password)) {
100#else
101 auth_password(pw, "")) {
102#endif
103 auth_log(authctxt, 1, "without authentication", "");
104 return;
105 }
94 106
95 /* Indicate that authentication is needed. */ 107 /* Indicate that authentication is needed. */
96 packet_start(SSH_SMSG_FAILURE); 108 packet_start(SSH_SMSG_FAILURE);
@@ -99,11 +111,11 @@ do_authloop(struct passwd * pw, char *luser)
99 111
100 client_user = NULL; 112 client_user = NULL;
101 113
102 for (attempt = 1;; attempt++) { 114 for (;;) {
103 /* default to fail */ 115 /* default to fail */
104 authenticated = 0; 116 authenticated = 0;
105 117
106 strlcpy(user, "", sizeof user); 118 info[0] = '\0';
107 119
108 /* Get a packet from the client. */ 120 /* Get a packet from the client. */
109 type = packet_read(&plen); 121 type = packet_read(&plen);
@@ -120,7 +132,7 @@ do_authloop(struct passwd * pw, char *luser)
120 char *tgt = packet_get_string(&dlen); 132 char *tgt = packet_get_string(&dlen);
121 packet_integrity_check(plen, 4 + dlen, type); 133 packet_integrity_check(plen, 4 + dlen, type);
122 if (!auth_kerberos_tgt(pw, tgt)) 134 if (!auth_kerberos_tgt(pw, tgt))
123 verbose("Kerberos tgt REFUSED for %.100s", luser); 135 verbose("Kerberos tgt REFUSED for %.100s", authctxt->user);
124 xfree(tgt); 136 xfree(tgt);
125 } 137 }
126 continue; 138 continue;
@@ -134,7 +146,7 @@ do_authloop(struct passwd * pw, char *luser)
134 char *token_string = packet_get_string(&dlen); 146 char *token_string = packet_get_string(&dlen);
135 packet_integrity_check(plen, 4 + dlen, type); 147 packet_integrity_check(plen, 4 + dlen, type);
136 if (!auth_afs_token(pw, token_string)) 148 if (!auth_afs_token(pw, token_string))
137 verbose("AFS token REFUSED for %.100s", luser); 149 verbose("AFS token REFUSED for %.100s", authctxt->user);
138 xfree(token_string); 150 xfree(token_string);
139 } 151 }
140 continue; 152 continue;
@@ -142,7 +154,6 @@ do_authloop(struct passwd * pw, char *luser)
142#ifdef KRB4 154#ifdef KRB4
143 case SSH_CMSG_AUTH_KERBEROS: 155 case SSH_CMSG_AUTH_KERBEROS:
144 if (!options.kerberos_authentication) { 156 if (!options.kerberos_authentication) {
145 /* packet_get_all(); */
146 verbose("Kerberos authentication disabled."); 157 verbose("Kerberos authentication disabled.");
147 break; 158 break;
148 } else { 159 } else {
@@ -152,17 +163,17 @@ do_authloop(struct passwd * pw, char *luser)
152 char *kdata = packet_get_string((u_int *) &auth.length); 163 char *kdata = packet_get_string((u_int *) &auth.length);
153 packet_integrity_check(plen, 4 + auth.length, type); 164 packet_integrity_check(plen, 4 + auth.length, type);
154 165
155 if (auth.length < MAX_KTXT_LEN) 166 if (authctxt->valid) {
156 memcpy(auth.dat, kdata, auth.length); 167 if (auth.length < MAX_KTXT_LEN)
157 xfree(kdata); 168 memcpy(auth.dat, kdata, auth.length);
158
159 if (pw != NULL) {
160 authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user); 169 authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
161 if (authenticated) { 170 if (authenticated) {
162 snprintf(user, sizeof user, " tktuser %s", tkt_user); 171 snprintf(info, sizeof info,
172 " tktuser %.100s", tkt_user);
163 xfree(tkt_user); 173 xfree(tkt_user);
164 } 174 }
165 } 175 }
176 xfree(kdata);
166 } 177 }
167 break; 178 break;
168#endif /* KRB4 */ 179#endif /* KRB4 */
@@ -184,7 +195,7 @@ do_authloop(struct passwd * pw, char *luser)
184 /* Try to authenticate using /etc/hosts.equiv and .rhosts. */ 195 /* Try to authenticate using /etc/hosts.equiv and .rhosts. */
185 authenticated = auth_rhosts(pw, client_user); 196 authenticated = auth_rhosts(pw, client_user);
186 197
187 snprintf(user, sizeof user, " ruser %s", client_user); 198 snprintf(info, sizeof info, " ruser %.100s", client_user);
188 break; 199 break;
189 200
190 case SSH_CMSG_AUTH_RHOSTS_RSA: 201 case SSH_CMSG_AUTH_RHOSTS_RSA:
@@ -219,7 +230,7 @@ do_authloop(struct passwd * pw, char *luser)
219 authenticated = auth_rhosts_rsa(pw, client_user, client_host_key); 230 authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
220 RSA_free(client_host_key); 231 RSA_free(client_host_key);
221 232
222 snprintf(user, sizeof user, " ruser %s", client_user); 233 snprintf(info, sizeof info, " ruser %.100s", client_user);
223 break; 234 break;
224 235
225 case SSH_CMSG_AUTH_RSA: 236 case SSH_CMSG_AUTH_RSA:
@@ -267,22 +278,19 @@ do_authloop(struct passwd * pw, char *luser)
267 xfree(password); 278 xfree(password);
268 break; 279 break;
269 280
270#ifdef SKEY 281#ifdef SKEY /* ISSUE: Is this right? we don't define
282 having skey_authentication in
283 servconf.h by default so I assume
284 we need to deal with this via #ifdef
285 in some reasonable way */
271 case SSH_CMSG_AUTH_TIS: 286 case SSH_CMSG_AUTH_TIS:
272 debug("rcvd SSH_CMSG_AUTH_TIS"); 287 debug("rcvd SSH_CMSG_AUTH_TIS");
273 if (options.skey_authentication == 1) { 288 if (options.skey_authentication == 1) {
274 char *skeyinfo = NULL; 289 char *challenge = get_challenge(authctxt, authctxt->style);
275 if (pw != NULL) 290 if (challenge != NULL) {
276 skeyinfo = skey_keyinfo(pw->pw_name); 291 debug("sending challenge '%s'", challenge);
277 if (skeyinfo == NULL) {
278 debug("generating fake skeyinfo for %.100s.", luser);
279 skeyinfo = skey_fake_keyinfo(luser);
280 }
281 if (skeyinfo != NULL) {
282 /* we send our s/key- in tis-challenge messages */
283 debug("sending challenge '%s'", skeyinfo);
284 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE); 292 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
285 packet_put_cstring(skeyinfo); 293 packet_put_cstring(challenge);
286 packet_send(); 294 packet_send();
287 packet_write_wait(); 295 packet_write_wait();
288 continue; 296 continue;
@@ -293,20 +301,14 @@ do_authloop(struct passwd * pw, char *luser)
293 debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE"); 301 debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
294 if (options.skey_authentication == 1) { 302 if (options.skey_authentication == 1) {
295 char *response = packet_get_string(&dlen); 303 char *response = packet_get_string(&dlen);
296 debug("skey response == '%s'", response); 304 debug("got response '%s'", response);
297 packet_integrity_check(plen, 4 + dlen, type); 305 packet_integrity_check(plen, 4 + dlen, type);
298 authenticated = (pw != NULL && 306 authenticated = verify_response(authctxt, response);
299 skey_haskey(pw->pw_name) == 0 && 307 memset(response, 'r', dlen);
300 skey_passcheck(pw->pw_name, response) != -1);
301 xfree(response); 308 xfree(response);
302 } 309 }
303 break; 310 break;
304#else 311#endif /* ISSUE: End of wrong SKEY defines */
305 case SSH_CMSG_AUTH_TIS:
306 /* TIS Authentication is unsupported */
307 log("TIS authentication unsupported.");
308 break;
309#endif
310 312
311 default: 313 default:
312 /* 314 /*
@@ -316,10 +318,11 @@ do_authloop(struct passwd * pw, char *luser)
316 log("Unknown message during authentication: type %d", type); 318 log("Unknown message during authentication: type %d", type);
317 break; 319 break;
318 } 320 }
319 if (authenticated && pw == NULL) 321 if (!authctxt->valid && authenticated)
320 fatal("internal error: authenticated for pw == NULL"); 322 fatal("INTERNAL ERROR: authenticated invalid user %s",
323 authctxt->user);
321 324
322#ifdef HAVE_CYGWIN 325#ifdef HAVE_CYGWIN /* ISSUE: Right place? */
323 if (authenticated && 326 if (authenticated &&
324 !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD,pw->pw_uid)) { 327 !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD,pw->pw_uid)) {
325 packet_disconnect("Authentication rejected for uid %d.", 328 packet_disconnect("Authentication rejected for uid %d.",
@@ -328,41 +331,18 @@ do_authloop(struct passwd * pw, char *luser)
328 } 331 }
329#endif 332#endif
330 333
331 /* 334 /* Special handling for root */
332 * Check if the user is logging in as root and root logins 335 if (authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed())
333 * are disallowed. 336 authenticated = 0;
334 * Note that root login is allowed for forced commands.
335 */
336 if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
337 if (forced_command) {
338 log("Root login accepted for forced command.");
339 } else {
340 authenticated = 0;
341 log("ROOT LOGIN REFUSED FROM %.200s",
342 get_canonical_hostname());
343 }
344 }
345
346 /* Raise logging level */
347 if (authenticated ||
348 attempt == AUTH_FAIL_LOG ||
349 type == SSH_CMSG_AUTH_PASSWORD)
350 authlog = log;
351
352 authlog("%s %s for %s%.100s from %.200s port %d%s",
353 authenticated ? "Accepted" : "Failed",
354 get_authname(type),
355 pw ? "" : "illegal user ",
356 pw && pw->pw_uid == 0 ? "ROOT" : luser,
357 get_remote_ipaddr(),
358 get_remote_port(),
359 user);
360 337
361#ifdef USE_PAM 338#ifdef USE_PAM /* ISSUE: Right place? */
362 if (authenticated && !do_pam_account(pw->pw_name, client_user)) 339 if (authenticated && !do_pam_account(pw->pw_name, client_user))
363 authenticated = 0; 340 authenticated = 0;
364#endif 341#endif
365 342
343 /* Log before sending the reply */
344 auth_log(authctxt, authenticated, get_authname(type), info);
345
366 if (client_user != NULL) { 346 if (client_user != NULL) {
367 xfree(client_user); 347 xfree(client_user);
368 client_user = NULL; 348 client_user = NULL;
@@ -371,14 +351,13 @@ do_authloop(struct passwd * pw, char *luser)
371 if (authenticated) 351 if (authenticated)
372 return; 352 return;
373 353
374 if (attempt > AUTH_FAIL_MAX) { 354 if (authctxt->failures++ > AUTH_FAIL_MAX) {
375#ifdef WITH_AIXAUTHENTICATE 355#ifdef WITH_AIXAUTHENTICATE
376 loginfailed(user,get_canonical_hostname(),"ssh"); 356 loginfailed(user,get_canonical_hostname(),"ssh");
377#endif /* WITH_AIXAUTHENTICATE */ 357#endif /* WITH_AIXAUTHENTICATE */
378 packet_disconnect(AUTH_FAIL_MSG, luser); 358 packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
379 } 359 }
380 360
381 /* Send a message indicating that the authentication attempt failed. */
382 packet_start(SSH_SMSG_FAILURE); 361 packet_start(SSH_SMSG_FAILURE);
383 packet_send(); 362 packet_send();
384 packet_write_wait(); 363 packet_write_wait();
@@ -392,10 +371,11 @@ do_authloop(struct passwd * pw, char *luser)
392void 371void
393do_authentication() 372do_authentication()
394{ 373{
395 struct passwd *pw, pwcopy; 374 Authctxt *authctxt;
375 struct passwd *pw;
396 int plen; 376 int plen;
397 u_int ulen; 377 u_int ulen;
398 char *user; 378 char *user, *style = NULL;
399 379
400 /* Get the name of the user that we wish to log in as. */ 380 /* Get the name of the user that we wish to log in as. */
401 packet_read_expect(&plen, SSH_CMSG_USER); 381 packet_read_expect(&plen, SSH_CMSG_USER);
@@ -404,6 +384,13 @@ do_authentication()
404 user = packet_get_string(&ulen); 384 user = packet_get_string(&ulen);
405 packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER); 385 packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
406 386
387 if ((style = strchr(user, ':')) != NULL)
388 *style++ = 0;
389
390 authctxt = authctxt_new();
391 authctxt->user = user;
392 authctxt->style = style;
393
407 setproctitle("%s", user); 394 setproctitle("%s", user);
408 395
409#ifdef AFS 396#ifdef AFS
@@ -417,21 +404,13 @@ do_authentication()
417 /* Verify that the user is a valid user. */ 404 /* Verify that the user is a valid user. */
418 pw = getpwnam(user); 405 pw = getpwnam(user);
419 if (pw && allowed_user(pw)) { 406 if (pw && allowed_user(pw)) {
420 /* Take a copy of the returned structure. */ 407 authctxt->valid = 1;
421 memset(&pwcopy, 0, sizeof(pwcopy)); 408 pw = pwcopy(pw);
422 pwcopy.pw_name = xstrdup(pw->pw_name);
423 pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
424 pwcopy.pw_uid = pw->pw_uid;
425 pwcopy.pw_gid = pw->pw_gid;
426#ifdef HAVE_PW_CLASS_IN_PASSWD
427 pwcopy.pw_class = xstrdup(pw->pw_class);
428#endif
429 pwcopy.pw_dir = xstrdup(pw->pw_dir);
430 pwcopy.pw_shell = xstrdup(pw->pw_shell);
431 pw = &pwcopy;
432 } else { 409 } else {
410 debug("do_authentication: illegal user %s", user);
433 pw = NULL; 411 pw = NULL;
434 } 412 }
413 authctxt->pw = pw;
435 414
436#ifdef USE_PAM 415#ifdef USE_PAM
437 if (pw) 416 if (pw)
@@ -447,44 +426,25 @@ do_authentication()
447 packet_disconnect("Cannot change user when server not running as root."); 426 packet_disconnect("Cannot change user when server not running as root.");
448#endif 427#endif
449 428
450 debug("Attempting authentication for %s%.100s.", pw ? "" : "illegal user ", user); 429 /*
451 430 * Loop until the user has been authenticated or the connection is
452 /* If the user has no password, accept authentication immediately. */ 431 * closed, do_authloop() returns only if authentication is successful
453 if (options.password_authentication && 432 */
454#ifdef KRB4 433 do_authloop(authctxt);
455 (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
456#endif /* KRB4 */
457#ifdef USE_PAM
458 auth_pam_password(pw, "")) {
459#elif defined(HAVE_OSF_SIA)
460 (sia_validate_user(NULL, saved_argc, saved_argv,
461 get_canonical_hostname(), pw->pw_name, NULL, 0,
462 NULL, "") == SIASUCCESS)) {
463#else /* !HAVE_OSF_SIA && !USE_PAM */
464 auth_password(pw, "")) {
465#endif /* USE_PAM */
466 /* Authentication with empty password succeeded. */
467 log("Login for user %s from %.100s, accepted without authentication.",
468 user, get_remote_ipaddr());
469 } else {
470 /* Loop until the user has been authenticated or the
471 connection is closed, do_authloop() returns only if
472 authentication is successful */
473 do_authloop(pw, user);
474 }
475 if (pw == NULL)
476 fatal("internal error, authentication successful for user '%.100s'", user);
477 434
478 /* The user has been authenticated and accepted. */ 435 /* The user has been authenticated and accepted. */
479 packet_start(SSH_SMSG_SUCCESS); 436 packet_start(SSH_SMSG_SUCCESS);
480 packet_send(); 437 packet_send();
481 packet_write_wait(); 438 packet_write_wait();
439
482#ifdef WITH_AIXAUTHENTICATE 440#ifdef WITH_AIXAUTHENTICATE
483 /* We don't have a pty yet, so just label the line as "ssh" */ 441 /* We don't have a pty yet, so just label the line as "ssh" */
484 if (loginsuccess(user,get_canonical_hostname(),"ssh",&aixloginmsg) < 0) 442 if (loginsuccess(authctxt->user,get_canonical_hostname(),"ssh",&aixloginmsg) < 0)
485 aixloginmsg = NULL; 443 aixloginmsg = NULL;
486#endif /* WITH_AIXAUTHENTICATE */ 444#endif /* WITH_AIXAUTHENTICATE */
487 xfree(user); 445
446 xfree(authctxt->user);
447 xfree(authctxt);
488 448
489 /* Perform session preparation. */ 449 /* Perform session preparation. */
490 do_authenticated(pw); 450 do_authenticated(pw);