summaryrefslogtreecommitdiff
path: root/auth1.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2000-10-14 16:23:11 +1100
committerDamien Miller <djm@mindrot.org>2000-10-14 16:23:11 +1100
commit874d77bb134a21a5cf625956b60173376a993ba8 (patch)
tree93dd73b2ff1fbf0ad5f3978a2c4e0d8438a0bf7c /auth1.c
parent89d9796fbedef4eed6956a2c095c7cc25330c28d (diff)
- (djm) Big OpenBSD sync:
- markus@cvs.openbsd.org 2000/09/30 10:27:44 [log.c] allow loglevel debug - markus@cvs.openbsd.org 2000/10/03 11:59:57 [packet.c] hmac->mac - markus@cvs.openbsd.org 2000/10/03 12:03:03 [auth-krb4.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth1.c] move fake-auth from auth1.c to individual auth methods, disables s/key in debug-msg - markus@cvs.openbsd.org 2000/10/03 12:16:48 ssh.c do not resolve canonname, i have no idea why this was added oin ossh - markus@cvs.openbsd.org 2000/10/09 15:30:44 ssh-keygen.1 ssh-keygen.c -X now reads private ssh.com DSA keys, too. - markus@cvs.openbsd.org 2000/10/09 15:32:34 auth-options.c clear options on every call. - markus@cvs.openbsd.org 2000/10/09 15:51:00 authfd.c authfd.h interop with ssh-agent2, from <res@shore.net> - markus@cvs.openbsd.org 2000/10/10 14:20:45 compat.c use rexexp for version string matching - provos@cvs.openbsd.org 2000/10/10 22:02:18 [kex.c kex.h myproposal.h ssh.h ssh2.h sshconnect2.c sshd.c dh.c dh.h] First rough implementation of the diffie-hellman group exchange. The client can ask the server for bigger groups to perform the diffie-hellman in, thus increasing the attack complexity when using ciphers with longer keys. University of Windsor provided network, T the company. - markus@cvs.openbsd.org 2000/10/11 13:59:52 [auth-rsa.c auth2.c] clear auth options unless auth sucessfull - markus@cvs.openbsd.org 2000/10/11 14:00:27 [auth-options.h] clear auth options unless auth sucessfull - markus@cvs.openbsd.org 2000/10/11 14:03:27 [scp.1 scp.c] support 'scp -o' with help from mouring@pconline.com - markus@cvs.openbsd.org 2000/10/11 14:11:35 [dh.c] Wall - markus@cvs.openbsd.org 2000/10/11 14:14:40 [auth.h auth2.c readconf.c readconf.h readpass.c servconf.c servconf.h] [ssh.h sshconnect2.c sshd_config auth2-skey.c cli.c cli.h] add support for s/key (kbd-interactive) to ssh2, based on work by mkiernan@avantgo.com and me - markus@cvs.openbsd.org 2000/10/11 14:27:24 [auth.c auth1.c auth2.c authfile.c cipher.c cipher.h kex.c kex.h] [myproposal.h packet.c readconf.c session.c ssh.c ssh.h sshconnect1.c] [sshconnect2.c sshd.c] new cipher framework - markus@cvs.openbsd.org 2000/10/11 14:45:21 [cipher.c] remove DES - markus@cvs.openbsd.org 2000/10/12 03:59:20 [cipher.c cipher.h sshconnect1.c sshconnect2.c sshd.c] enable DES in SSH-1 clients only - markus@cvs.openbsd.org 2000/10/12 08:21:13 [kex.h packet.c] remove unused - markus@cvs.openbsd.org 2000/10/13 12:34:46 [sshd.c] Kludge for F-Secure Macintosh < 1.0.2; appro@fy.chalmers.se - markus@cvs.openbsd.org 2000/10/13 12:59:15 [cipher.c cipher.h myproposal.h rijndael.c rijndael.h] rijndael/aes support - markus@cvs.openbsd.org 2000/10/13 13:10:54 [sshd.8] more info about -V - markus@cvs.openbsd.org 2000/10/13 13:12:02 [myproposal.h] prefer no compression
Diffstat (limited to 'auth1.c')
-rw-r--r--auth1.c246
1 files changed, 90 insertions, 156 deletions
diff --git a/auth1.c b/auth1.c
index 99639b59..520da640 100644
--- a/auth1.c
+++ b/auth1.c
@@ -10,28 +10,31 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth1.c,v 1.4 2000/09/07 20:27:49 deraadt Exp $");
+RCSID("$OpenBSD: auth1.c,v 1.6 2000/10/11 20:27:23 markus Exp $");
+
+#ifdef HAVE_OSF_SIA
+# include <sia.h>
+# include <siad.h>
+#endif
#include "xmalloc.h"
#include "rsa.h"
#include "ssh.h"
#include "packet.h"
#include "buffer.h"
-#include "cipher.h"
#include "mpaux.h"
#include "servconf.h"
#include "compat.h"
#include "auth.h"
#include "session.h"
-#ifdef HAVE_OSF_SIA
-# include <sia.h>
-# include <siad.h>
-#endif
-
/* import */
extern ServerOptions options;
extern char *forced_command;
+
+#ifdef WITH_AIXAUTHENTICATE
+extern char *aixloginmsg;
+#endif /* WITH_AIXAUTHENTICATE */
#ifdef HAVE_OSF_SIA
extern int saved_argc;
extern char **saved_argv;
@@ -67,89 +70,21 @@ get_authname(int type)
}
/*
- * The user does not exist or access is denied,
- * but fake indication that authentication is needed.
+ * read packets and try to authenticate local user 'luser'.
+ * return if authentication is successfull. not that pw == NULL
+ * if the user does not exists or is not allowed to login.
+ * each auth method has to 'fake' authentication for nonexisting
+ * users.
*/
void
-do_fake_authloop1(char *user)
-{
- int attempt = 0;
-
- log("Faking authloop for illegal user %.200s from %.200s port %d",
- user,
- get_remote_ipaddr(),
- get_remote_port());
-
-#ifdef WITH_AIXAUTHENTICATE
- loginfailed(user,get_canonical_hostname(),"ssh");
-#endif /* WITH_AIXAUTHENTICATE */
-
- /* Indicate that authentication is needed. */
- packet_start(SSH_SMSG_FAILURE);
- packet_send();
- packet_write_wait();
-
- /*
- * Keep reading packets, and always respond with a failure. This is
- * to avoid disclosing whether such a user really exists.
- */
- for (attempt = 1;; attempt++) {
- /* Read a packet. This will not return if the client disconnects. */
- int plen;
-#ifndef SKEY
- (void)packet_read(&plen);
-#else /* SKEY */
- int type = packet_read(&plen);
- unsigned int dlen;
- char *password, *skeyinfo;
- password = NULL;
- /* Try to send a fake s/key challenge. */
- if (options.skey_authentication == 1 &&
- (skeyinfo = skey_fake_keyinfo(user)) != NULL) {
- if (type == SSH_CMSG_AUTH_TIS) {
- packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
- packet_put_string(skeyinfo, strlen(skeyinfo));
- packet_send();
- packet_write_wait();
- continue;
- } else if (type == SSH_CMSG_AUTH_PASSWORD &&
- options.password_authentication &&
- (password = packet_get_string(&dlen)) != NULL &&
- dlen == 5 &&
- strncasecmp(password, "s/key", 5) == 0 ) {
- packet_send_debug(skeyinfo);
- }
- }
- if (password != NULL)
- xfree(password);
-#endif
- if (attempt > AUTH_FAIL_MAX)
- packet_disconnect(AUTH_FAIL_MSG, user);
-
- /*
- * Send failure. This should be indistinguishable from a
- * failed authentication.
- */
- packet_start(SSH_SMSG_FAILURE);
- packet_send();
- packet_write_wait();
- }
- /* NOTREACHED */
- abort();
-}
-
-/*
- * read packets and try to authenticate local user *pw.
- * return if authentication is successfull
- */
-void
-do_authloop(struct passwd * pw)
+do_authloop(struct passwd * pw, char *luser)
{
+ int authenticated = 0;
int attempt = 0;
unsigned int bits;
RSA *client_host_key;
BIGNUM *n;
- char *client_user = NULL, *password = NULL;
+ char *client_user, *password;
char user[1024];
unsigned int dlen;
int plen, nlen, elen;
@@ -162,8 +97,12 @@ do_authloop(struct passwd * pw)
packet_send();
packet_write_wait();
+ client_user = NULL;
+
for (attempt = 1;; attempt++) {
- int authenticated = 0;
+ /* default to fail */
+ authenticated = 0;
+
strlcpy(user, "", sizeof user);
/* Get a packet from the client. */
@@ -174,7 +113,6 @@ do_authloop(struct passwd * pw)
#ifdef AFS
case SSH_CMSG_HAVE_KERBEROS_TGT:
if (!options.kerberos_tgt_passing) {
- /* packet_get_all(); */
verbose("Kerberos tgt passing disabled.");
break;
} else {
@@ -182,14 +120,13 @@ do_authloop(struct passwd * pw)
char *tgt = packet_get_string(&dlen);
packet_integrity_check(plen, 4 + dlen, type);
if (!auth_kerberos_tgt(pw, tgt))
- verbose("Kerberos tgt REFUSED for %s", pw->pw_name);
+ verbose("Kerberos tgt REFUSED for %.100s", luser);
xfree(tgt);
}
continue;
case SSH_CMSG_HAVE_AFS_TOKEN:
if (!options.afs_token_passing || !k_hasafs()) {
- /* packet_get_all(); */
verbose("AFS token passing disabled.");
break;
} else {
@@ -197,7 +134,7 @@ do_authloop(struct passwd * pw)
char *token_string = packet_get_string(&dlen);
packet_integrity_check(plen, 4 + dlen, type);
if (!auth_afs_token(pw, token_string))
- verbose("AFS token REFUSED for %s", pw->pw_name);
+ verbose("AFS token REFUSED for %.100s", luser);
xfree(token_string);
}
continue;
@@ -219,11 +156,12 @@ do_authloop(struct passwd * pw)
memcpy(auth.dat, kdata, auth.length);
xfree(kdata);
- authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
-
- if (authenticated) {
- snprintf(user, sizeof user, " tktuser %s", tkt_user);
- xfree(tkt_user);
+ if (pw != NULL) {
+ authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
+ if (authenticated) {
+ snprintf(user, sizeof user, " tktuser %s", tkt_user);
+ xfree(tkt_user);
+ }
}
}
break;
@@ -243,8 +181,7 @@ do_authloop(struct passwd * pw)
client_user = packet_get_string(&ulen);
packet_integrity_check(plen, 4 + ulen, type);
- /* Try to authenticate using /etc/hosts.equiv and
- .rhosts. */
+ /* Try to authenticate using /etc/hosts.equiv and .rhosts. */
authenticated = auth_rhosts(pw, client_user);
snprintf(user, sizeof user, " ruser %s", client_user);
@@ -275,7 +212,7 @@ do_authloop(struct passwd * pw)
packet_get_bignum(client_host_key->n, &nlen);
if (bits != BN_num_bits(client_host_key->n))
- log("Warning: keysize mismatch for client_host_key: "
+ verbose("Warning: keysize mismatch for client_host_key: "
"actual %d, announced %d", BN_num_bits(client_host_key->n), bits);
packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
@@ -322,7 +259,7 @@ do_authloop(struct passwd * pw)
authenticated = 1;
}
#else /* !USE_PAM && !HAVE_OSF_SIA */
- /* Try authentication with the password. */
+ /* Try authentication with the password. */
authenticated = auth_password(pw, password);
#endif /* USE_PAM */
@@ -334,16 +271,18 @@ do_authloop(struct passwd * pw)
case SSH_CMSG_AUTH_TIS:
debug("rcvd SSH_CMSG_AUTH_TIS");
if (options.skey_authentication == 1) {
- char *skeyinfo = skey_keyinfo(pw->pw_name);
+ char *skeyinfo = NULL;
+ if (pw != NULL)
+ skey_keyinfo(pw->pw_name);
if (skeyinfo == NULL) {
- debug("generating fake skeyinfo for %.100s.", pw->pw_name);
- skeyinfo = skey_fake_keyinfo(pw->pw_name);
+ debug("generating fake skeyinfo for %.100s.", luser);
+ skeyinfo = skey_fake_keyinfo(luser);
}
if (skeyinfo != NULL) {
/* we send our s/key- in tis-challenge messages */
debug("sending challenge '%s'", skeyinfo);
packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
- packet_put_string(skeyinfo, strlen(skeyinfo));
+ packet_put_cstring(skeyinfo);
packet_send();
packet_write_wait();
continue;
@@ -356,8 +295,9 @@ do_authloop(struct passwd * pw)
char *response = packet_get_string(&dlen);
debug("skey response == '%s'", response);
packet_integrity_check(plen, 4 + dlen, type);
- authenticated = (skey_haskey(pw->pw_name) == 0 &&
- skey_passcheck(pw->pw_name, response) != -1);
+ authenticated = (pw != NULL &&
+ skey_haskey(pw->pw_name) == 0 &&
+ skey_passcheck(pw->pw_name, response) != -1);
xfree(response);
}
break;
@@ -376,12 +316,14 @@ do_authloop(struct passwd * pw)
log("Unknown message during authentication: type %d", type);
break;
}
+ if (authenticated && pw == NULL)
+ fatal("internal error: authenticated for pw == NULL");
#ifdef HAVE_CYGWIN
- if (authenticated &&
+ if (authenticated &&
!check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD,pw->pw_uid)) {
packet_disconnect("Authentication rejected for uid %d.",
- (int) pw->pw_uid);
+ (int)pw->pw_uid);
authenticated = 0;
}
#endif
@@ -391,7 +333,7 @@ do_authloop(struct passwd * pw)
* are disallowed.
* Note that root login is allowed for forced commands.
*/
- if (authenticated && pw->pw_uid == 0 && !options.permit_root_login) {
+ if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
if (forced_command) {
log("Root login accepted for forced command.");
} else {
@@ -407,41 +349,33 @@ do_authloop(struct passwd * pw)
type == SSH_CMSG_AUTH_PASSWORD)
authlog = log;
- authlog("%s %s for %.200s from %.200s port %d%s",
+ authlog("%s %s for %s%.100s from %.200s port %d%s",
authenticated ? "Accepted" : "Failed",
get_authname(type),
- pw->pw_uid == 0 ? "ROOT" : pw->pw_name,
+ pw ? "" : "illegal user ",
+ pw && pw->pw_uid == 0 ? "ROOT" : luser,
get_remote_ipaddr(),
get_remote_port(),
user);
#ifdef USE_PAM
- if (authenticated) {
- if (!do_pam_account(pw->pw_name, client_user)) {
- if (client_user != NULL) {
- xfree(client_user);
- client_user = NULL;
- }
- do_fake_authloop1(pw->pw_name);
- }
- return;
- }
-#else /* USE_PAM */
- if (authenticated) {
- return;
- }
-#endif /* USE_PAM */
+ if (authenticated && !do_pam_account(pw->pw_name, client_user))
+ authenticated = 0;
+#endif
if (client_user != NULL) {
xfree(client_user);
client_user = NULL;
}
+ if (authenticated)
+ return;
+
if (attempt > AUTH_FAIL_MAX) {
#ifdef WITH_AIXAUTHENTICATE
- loginfailed(pw->pw_name,get_canonical_hostname(),"ssh");
+ loginfailed(user,get_canonical_hostname(),"ssh");
#endif /* WITH_AIXAUTHENTICATE */
- packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
+ packet_disconnect(AUTH_FAIL_MSG, luser);
}
/* Send a message indicating that the authentication attempt failed. */
@@ -462,9 +396,6 @@ do_authentication()
int plen;
unsigned int ulen;
char *user;
-#ifdef WITH_AIXAUTHENTICATE
- extern char *aixloginmsg;
-#endif /* WITH_AIXAUTHENTICATE */
/* Get the name of the user that we wish to log in as. */
packet_read_expect(&plen, SSH_CMSG_USER);
@@ -485,38 +416,38 @@ do_authentication()
/* Verify that the user is a valid user. */
pw = getpwnam(user);
- if (!pw || !allowed_user(pw))
- do_fake_authloop1(user);
- xfree(user);
-
- /* Take a copy of the returned structure. */
- memset(&pwcopy, 0, sizeof(pwcopy));
- pwcopy.pw_name = xstrdup(pw->pw_name);
- pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
- pwcopy.pw_uid = pw->pw_uid;
- pwcopy.pw_gid = pw->pw_gid;
+ if (pw && allowed_user(pw)) {
+ /* Take a copy of the returned structure. */
+ memset(&pwcopy, 0, sizeof(pwcopy));
+ pwcopy.pw_name = xstrdup(pw->pw_name);
+ pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
+ pwcopy.pw_uid = pw->pw_uid;
+ pwcopy.pw_gid = pw->pw_gid;
#ifdef HAVE_PW_CLASS_IN_PASSWD
- pwcopy.pw_class = xstrdup(pw->pw_class);
+ pwcopy.pw_class = xstrdup(pw->pw_class);
#endif
- pwcopy.pw_dir = xstrdup(pw->pw_dir);
- pwcopy.pw_shell = xstrdup(pw->pw_shell);
- pw = &pwcopy;
+ pwcopy.pw_dir = xstrdup(pw->pw_dir);
+ pwcopy.pw_shell = xstrdup(pw->pw_shell);
+ pw = &pwcopy;
+ } else {
+ pw = NULL;
+ }
#ifdef USE_PAM
- start_pam(pw);
+ if (pw)
+ start_pam(pw);
#endif
-#ifndef HAVE_CYGWIN
/*
* If we are not running as root, the user must have the same uid as
- * the server.
- * Rule not valid on Windows systems.
+ * the server. (Unless you are running Windows)
*/
- if (getuid() != 0 && pw->pw_uid != getuid())
+#ifndef HAVE_CYGWIN
+ if (getuid() != 0 && pw && pw->pw_uid != getuid())
packet_disconnect("Cannot change user when server not running as root.");
#endif
- debug("Attempting authentication for %.100s.", pw->pw_name);
+ debug("Attempting authentication for %s%.100s.", pw ? "" : "illegal user ", user);
/* If the user has no password, accept authentication immediately. */
if (options.password_authentication &&
@@ -527,30 +458,33 @@ do_authentication()
auth_pam_password(pw, "")) {
#elif defined(HAVE_OSF_SIA)
(sia_validate_user(NULL, saved_argc, saved_argv,
- get_canonical_hostname(), pw->pw_name, NULL, 0, NULL,
- "") == SIASUCCESS)) {
+ get_canonical_hostname(), pw->pw_name, NULL, 0,
+ NULL, "") == SIASUCCESS)) {
#else /* !HAVE_OSF_SIA && !USE_PAM */
- auth_password(pw, "")) {
+ auth_password(pw, "")) {
#endif /* USE_PAM */
/* Authentication with empty password succeeded. */
log("Login for user %s from %.100s, accepted without authentication.",
- pw->pw_name, get_remote_ipaddr());
+ user, get_remote_ipaddr());
} else {
/* Loop until the user has been authenticated or the
connection is closed, do_authloop() returns only if
authentication is successfull */
- do_authloop(pw);
+ do_authloop(pw, user);
}
+ if (pw == NULL)
+ fatal("internal error, authentication successfull for user '%.100s'", user);
/* The user has been authenticated and accepted. */
+ packet_start(SSH_SMSG_SUCCESS);
+ packet_send();
+ packet_write_wait();
+
#ifdef WITH_AIXAUTHENTICATE
/* We don't have a pty yet, so just label the line as "ssh" */
if (loginsuccess(user,get_canonical_hostname(),"ssh",&aixloginmsg) < 0)
aixloginmsg = NULL;
#endif /* WITH_AIXAUTHENTICATE */
- packet_start(SSH_SMSG_SUCCESS);
- packet_send();
- packet_write_wait();
/* Perform session preparation. */
do_authenticated(pw);