summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rw-r--r--Makefile.in2
-rw-r--r--auth-chall.c61
-rw-r--r--auth-passwd.c36
-rw-r--r--auth.c96
-rw-r--r--auth.h15
-rw-r--r--auth1.c216
-rw-r--r--auth2-chall.c113
-rw-r--r--auth2-pam.c6
-rw-r--r--auth2.c124
-rw-r--r--log-client.c6
-rw-r--r--log-server.c10
-rw-r--r--log.c7
-rw-r--r--readconf.c4
-rw-r--r--servconf.c4
-rw-r--r--serverloop.c4
-rw-r--r--session.c11
-rw-r--r--session.h2
-rw-r--r--ssh.16
-rw-r--r--ssh.h4
-rw-r--r--sshconnect1.c5
-rw-r--r--sshd.86
-rw-r--r--sshd.c53
23 files changed, 468 insertions, 342 deletions
diff --git a/ChangeLog b/ChangeLog
index 35937150..8b5df6fd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,23 @@
20010119
- (djm) Update versions in RPM specfiles
-
+ - (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
+
20010118
- (bal) Super Sized OpenBSD Resync
- markus@cvs.openbsd.org 2001/01/11 22:14:20 GMT 2001 by markus
diff --git a/Makefile.in b/Makefile.in
index d56cd640..57449dcd 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -43,7 +43,7 @@ LIBOPENBSD_COMPAT_OBJS=bsd-arc4random.o bsd-base64.o bsd-bindresvport.o bsd-daem
SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o log-client.o readconf.o clientloop.o
-SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-skey.o auth2-skey.o auth-rhosts.o auth-options.o auth-krb4.o auth-pam.o auth2-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o dh.o pty.o log-server.o login.o loginrec.o servconf.o serverloop.o md5crypt.o session.o groupaccess.o
+SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-chall.o auth2-chall.o auth-rhosts.o auth-options.o auth-krb4.o auth-pam.o auth2-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o dh.o pty.o log-server.o login.o loginrec.o servconf.o serverloop.o md5crypt.o session.o groupaccess.o
TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8
CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh-keyscan.0 ssh.0 sshd.0 sftp-server.0
diff --git a/auth-chall.c b/auth-chall.c
new file mode 100644
index 00000000..e02e99d3
--- /dev/null
+++ b/auth-chall.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2001 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: auth-chall.c,v 1.1 2001/01/18 17:12:43 markus Exp $");
+
+#include "ssh.h"
+#include "auth.h"
+
+#ifdef SKEY
+char *
+get_challenge(Authctxt *authctxt, char *devs)
+{
+ static char challenge[1024];
+ struct skey skey;
+ if (skeychallenge(&skey, authctxt->user, challenge) == -1)
+ return NULL;
+ strlcat(challenge, "\nS/Key Password: ", sizeof challenge);
+ return challenge;
+}
+int
+verify_response(Authctxt *authctxt, char *response)
+{
+ return (authctxt->valid &&
+ skey_haskey(authctxt->pw->pw_name) == 0 &&
+ skey_passcheck(authctxt->pw->pw_name, response) != -1);
+}
+#else
+/* not available */
+char *
+get_challenge(Authctxt *authctxt, char *devs)
+{
+ return NULL;
+}
+int
+verify_response(Authctxt *authctxt, char *response)
+{
+ return 0;
+}
+#endif
diff --git a/auth-passwd.c b/auth-passwd.c
index 184ce154..8295ea17 100644
--- a/auth-passwd.c
+++ b/auth-passwd.c
@@ -11,30 +11,7 @@
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
- *
* Copyright (c) 1999 Dug Song. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -59,7 +36,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth-passwd.c,v 1.18 2000/10/03 18:03:03 markus Exp $");
+RCSID("$OpenBSD: auth-passwd.c,v 1.19 2001/01/18 16:59:59 markus Exp $");
#if !defined(USE_PAM) && !defined(HAVE_OSF_SIA)
@@ -68,6 +45,8 @@ RCSID("$OpenBSD: auth-passwd.c,v 1.18 2000/10/03 18:03:03 markus Exp $");
#include "servconf.h"
#include "xmalloc.h"
+#include "auth.h"
+
#ifdef WITH_AIXAUTHENTICATE
# include <login.h>
#endif
@@ -156,15 +135,6 @@ auth_password(struct passwd * pw, const char *password)
}
#endif
-#ifdef SKEY_VIA_PASSWD_IS_DISABLED
- if (options.skey_authentication == 1) {
- int ret = auth_skey_password(pw, password);
- if (ret == 1 || ret == 0)
- return ret;
- /* Fall back to ordinary passwd authentication. */
- }
-#endif
-
#ifdef WITH_AIXAUTHENTICATE
return (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0);
#endif
diff --git a/auth.c b/auth.c
index 59c95fe4..814506d7 100644
--- a/auth.c
+++ b/auth.c
@@ -1,14 +1,4 @@
/*
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- *
- *
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,19 +23,12 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth.c,v 1.12 2001/01/13 18:56:48 markus Exp $");
+RCSID("$OpenBSD: auth.c,v 1.13 2001/01/18 16:59:59 markus Exp $");
#include "xmalloc.h"
-#include "rsa.h"
#include "ssh.h"
-#include "pty.h"
-#include "packet.h"
-#include "buffer.h"
-#include "mpaux.h"
-#include "servconf.h"
-#include "compat.h"
-#include "channels.h"
#include "match.h"
+#include "servconf.h"
#include "groupaccess.h"
#ifdef HAVE_LOGIN_H
#include <login.h>
@@ -54,10 +37,8 @@ RCSID("$OpenBSD: auth.c,v 1.12 2001/01/13 18:56:48 markus Exp $");
#include <shadow.h>
#endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */
-#include "bufaux.h"
-#include "ssh2.h"
#include "auth.h"
-#include "session.h"
+#include "auth-options.h"
/* import */
extern ServerOptions options;
@@ -179,3 +160,74 @@ allowed_user(struct passwd * pw)
/* We found no reason not to let this user try to log on... */
return 1;
}
+
+Authctxt *
+authctxt_new(void)
+{
+ Authctxt *authctxt = xmalloc(sizeof(*authctxt));
+ memset(authctxt, 0, sizeof(*authctxt));
+ return authctxt;
+}
+
+struct passwd *
+pwcopy(struct passwd *pw)
+{
+ struct passwd *copy = xmalloc(sizeof(*copy));
+ memset(copy, 0, sizeof(*copy));
+ copy->pw_name = xstrdup(pw->pw_name);
+ copy->pw_passwd = xstrdup(pw->pw_passwd);
+ copy->pw_uid = pw->pw_uid;
+ copy->pw_gid = pw->pw_gid;
+#ifdef HAVE_PW_CLASS_IN_PASSWD
+ copy->pw_class = xstrdup(pw->pw_class);
+#endif
+ copy->pw_dir = xstrdup(pw->pw_dir);
+ copy->pw_shell = xstrdup(pw->pw_shell);
+ return copy;
+}
+
+void
+auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
+{
+ void (*authlog) (const char *fmt,...) = verbose;
+ char *authmsg;
+
+ /* Raise logging level */
+ if (authenticated == 1 ||
+ !authctxt->valid ||
+ authctxt->failures >= AUTH_FAIL_LOG ||
+ strcmp(method, "password") == 0)
+ authlog = log;
+
+ if (authctxt->postponed)
+ authmsg = "Postponed";
+ else
+ authmsg = authenticated ? "Accepted" : "Failed";
+
+ authlog("%s %s for %s%.100s from %.200s port %d%s",
+ authmsg,
+ method,
+ authctxt->valid ? "" : "illegal user ",
+ authctxt->valid && authctxt->pw->pw_uid == 0 ? "ROOT" : authctxt->user,
+ get_remote_ipaddr(),
+ get_remote_port(),
+ info);
+}
+
+/*
+ * Check if the user is logging in as root and root logins are disallowed.
+ * Note that root login is _allways_ allowed for forced commands.
+ */
+int
+auth_root_allowed(void)
+{
+ if (options.permit_root_login)
+ return 1;
+ if (forced_command) {
+ log("Root login accepted for forced command.");
+ return 1;
+ } else {
+ log("ROOT LOGIN REFUSED FROM %.200s", get_canonical_hostname());
+ return 0;
+ }
+}
diff --git a/auth.h b/auth.h
index 4b029f9c..bf4787b6 100644
--- a/auth.h
+++ b/auth.h
@@ -21,7 +21,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $OpenBSD: auth.h,v 1.8 2000/12/28 14:25:51 markus Exp $
+ * $OpenBSD: auth.h,v 1.9 2001/01/18 16:59:59 markus Exp $
*/
#ifndef AUTH_H
#define AUTH_H
@@ -29,12 +29,14 @@
typedef struct Authctxt Authctxt;
struct Authctxt {
int success;
+ int postponed;
int valid;
int attempt;
int failures;
char *user;
char *service;
struct passwd *pw;
+ char *style;
};
#include "auth-pam.h"
@@ -43,13 +45,20 @@ struct Authctxt {
void do_authentication(void);
void do_authentication2(void);
-void userauth_log(Authctxt *authctxt, int authenticated, char *method);
+Authctxt *authctxt_new(void);
+void auth_log(Authctxt *authctxt, int authenticated, char *method, char *info);
void userauth_reply(Authctxt *authctxt, int authenticated);
+int auth_root_allowed(void);
-int auth2_skey(Authctxt *authctxt);
+int auth2_challenge(Authctxt *authctxt, char *devs);
int allowed_user(struct passwd * pw);
+
+char *get_challenge(Authctxt *authctxt, char *devs);
+int verify_response(Authctxt *authctxt, char *response);
+
struct passwd * auth_get_user(void);
+struct passwd * pwcopy(struct passwd *pw);
#define AUTH_FAIL_MAX 6
#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
diff --git a/auth1.c b/auth1.c
index 51ed8f77..0f21c4c7 100644
--- a/auth1.c
+++ b/auth1.c
@@ -10,7 +10,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth1.c,v 1.10 2001/01/07 19:06:25 markus Exp $");
+RCSID("$OpenBSD: auth1.c,v 1.11 2001/01/18 16:59:59 markus Exp $");
#ifdef HAVE_OSF_SIA
# include <sia.h>
@@ -56,41 +56,53 @@ get_authname(int type)
return "rhosts-rsa";
case SSH_CMSG_AUTH_RHOSTS:
return "rhosts";
+ case SSH_CMSG_AUTH_TIS:
+ case SSH_CMSG_AUTH_TIS_RESPONSE:
+ return "challenge-response";
#ifdef KRB4
case SSH_CMSG_AUTH_KERBEROS:
return "kerberos";
#endif
-#ifdef SKEY
- case SSH_CMSG_AUTH_TIS_RESPONSE:
- return "s/key";
-#endif
}
snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
return buf;
}
/*
- * read packets and try to authenticate local user 'luser'.
- * return if authentication is successful. 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.
+ * read packets, try to authenticate the user and
+ * return only if authentication is successful
*/
void
-do_authloop(struct passwd * pw, char *luser)
+do_authloop(Authctxt *authctxt)
{
int authenticated = 0;
- int attempt = 0;
u_int bits;
RSA *client_host_key;
BIGNUM *n;
char *client_user, *password;
- char user[1024];
+ char info[1024];
u_int dlen;
int plen, nlen, elen;
u_int ulen;
int type = 0;
- void (*authlog) (const char *fmt,...) = verbose;
+ struct passwd *pw = authctxt->pw;
+
+ debug("Attempting authentication for %s%.100s.",
+ authctxt->valid ? "" : "illegal user ", authctxt->user);
+
+ /* If the user has no password, accept authentication immediately. */
+ if (options.password_authentication &&
+#ifdef KRB4
+ (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
+#endif
+#ifdef USE_PAM /* ISSUE: Right?? */
+ auth_pam_password(pw, password)) {
+#else
+ auth_password(pw, "")) {
+#endif
+ auth_log(authctxt, 1, "without authentication", "");
+ return;
+ }
/* Indicate that authentication is needed. */
packet_start(SSH_SMSG_FAILURE);
@@ -99,11 +111,11 @@ do_authloop(struct passwd * pw, char *luser)
client_user = NULL;
- for (attempt = 1;; attempt++) {
+ for (;;) {
/* default to fail */
authenticated = 0;
- strlcpy(user, "", sizeof user);
+ info[0] = '\0';
/* Get a packet from the client. */
type = packet_read(&plen);
@@ -120,7 +132,7 @@ do_authloop(struct passwd * pw, char *luser)
char *tgt = packet_get_string(&dlen);
packet_integrity_check(plen, 4 + dlen, type);
if (!auth_kerberos_tgt(pw, tgt))
- verbose("Kerberos tgt REFUSED for %.100s", luser);
+ verbose("Kerberos tgt REFUSED for %.100s", authctxt->user);
xfree(tgt);
}
continue;
@@ -134,7 +146,7 @@ do_authloop(struct passwd * pw, char *luser)
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 %.100s", luser);
+ verbose("AFS token REFUSED for %.100s", authctxt->user);
xfree(token_string);
}
continue;
@@ -142,7 +154,6 @@ do_authloop(struct passwd * pw, char *luser)
#ifdef KRB4
case SSH_CMSG_AUTH_KERBEROS:
if (!options.kerberos_authentication) {
- /* packet_get_all(); */
verbose("Kerberos authentication disabled.");
break;
} else {
@@ -152,17 +163,17 @@ do_authloop(struct passwd * pw, char *luser)
char *kdata = packet_get_string((u_int *) &auth.length);
packet_integrity_check(plen, 4 + auth.length, type);
- if (auth.length < MAX_KTXT_LEN)
- memcpy(auth.dat, kdata, auth.length);
- xfree(kdata);
-
- if (pw != NULL) {
+ if (authctxt->valid) {
+ if (auth.length < MAX_KTXT_LEN)
+ memcpy(auth.dat, kdata, auth.length);
authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
if (authenticated) {
- snprintf(user, sizeof user, " tktuser %s", tkt_user);
+ snprintf(info, sizeof info,
+ " tktuser %.100s", tkt_user);
xfree(tkt_user);
}
}
+ xfree(kdata);
}
break;
#endif /* KRB4 */
@@ -184,7 +195,7 @@ do_authloop(struct passwd * pw, char *luser)
/* Try to authenticate using /etc/hosts.equiv and .rhosts. */
authenticated = auth_rhosts(pw, client_user);
- snprintf(user, sizeof user, " ruser %s", client_user);
+ snprintf(info, sizeof info, " ruser %.100s", client_user);
break;
case SSH_CMSG_AUTH_RHOSTS_RSA:
@@ -219,7 +230,7 @@ do_authloop(struct passwd * pw, char *luser)
authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
RSA_free(client_host_key);
- snprintf(user, sizeof user, " ruser %s", client_user);
+ snprintf(info, sizeof info, " ruser %.100s", client_user);
break;
case SSH_CMSG_AUTH_RSA:
@@ -267,22 +278,19 @@ do_authloop(struct passwd * pw, char *luser)
xfree(password);
break;
-#ifdef SKEY
+#ifdef SKEY /* ISSUE: Is this right? we don't define
+ having skey_authentication in
+ servconf.h by default so I assume
+ we need to deal with this via #ifdef
+ in some reasonable way */
case SSH_CMSG_AUTH_TIS:
debug("rcvd SSH_CMSG_AUTH_TIS");
if (options.skey_authentication == 1) {
- char *skeyinfo = NULL;
- if (pw != NULL)
- skeyinfo = skey_keyinfo(pw->pw_name);
- if (skeyinfo == NULL) {
- 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);
+ char *challenge = get_challenge(authctxt, authctxt->style);
+ if (challenge != NULL) {
+ debug("sending challenge '%s'", challenge);
packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
- packet_put_cstring(skeyinfo);
+ packet_put_cstring(challenge);
packet_send();
packet_write_wait();
continue;
@@ -293,20 +301,14 @@ do_authloop(struct passwd * pw, char *luser)
debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
if (options.skey_authentication == 1) {
char *response = packet_get_string(&dlen);
- debug("skey response == '%s'", response);
+ debug("got response '%s'", response);
packet_integrity_check(plen, 4 + dlen, type);
- authenticated = (pw != NULL &&
- skey_haskey(pw->pw_name) == 0 &&
- skey_passcheck(pw->pw_name, response) != -1);
+ authenticated = verify_response(authctxt, response);
+ memset(response, 'r', dlen);
xfree(response);
}
break;
-#else
- case SSH_CMSG_AUTH_TIS:
- /* TIS Authentication is unsupported */
- log("TIS authentication unsupported.");
- break;
-#endif
+#endif /* ISSUE: End of wrong SKEY defines */
default:
/*
@@ -316,10 +318,11 @@ do_authloop(struct passwd * pw, char *luser)
log("Unknown message during authentication: type %d", type);
break;
}
- if (authenticated && pw == NULL)
- fatal("internal error: authenticated for pw == NULL");
+ if (!authctxt->valid && authenticated)
+ fatal("INTERNAL ERROR: authenticated invalid user %s",
+ authctxt->user);
-#ifdef HAVE_CYGWIN
+#ifdef HAVE_CYGWIN /* ISSUE: Right place? */
if (authenticated &&
!check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD,pw->pw_uid)) {
packet_disconnect("Authentication rejected for uid %d.",
@@ -328,41 +331,18 @@ do_authloop(struct passwd * pw, char *luser)
}
#endif
- /*
- * Check if the user is logging in as root and root logins
- * are disallowed.
- * Note that root login is allowed for forced commands.
- */
- if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
- if (forced_command) {
- log("Root login accepted for forced command.");
- } else {
- authenticated = 0;
- log("ROOT LOGIN REFUSED FROM %.200s",
- get_canonical_hostname());
- }
- }
-
- /* Raise logging level */
- if (authenticated ||
- attempt == AUTH_FAIL_LOG ||
- type == SSH_CMSG_AUTH_PASSWORD)
- authlog = log;
-
- authlog("%s %s for %s%.100s from %.200s port %d%s",
- authenticated ? "Accepted" : "Failed",
- get_authname(type),
- pw ? "" : "illegal user ",
- pw && pw->pw_uid == 0 ? "ROOT" : luser,
- get_remote_ipaddr(),
- get_remote_port(),
- user);
+ /* Special handling for root */
+ if (authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed())
+ authenticated = 0;
-#ifdef USE_PAM
+#ifdef USE_PAM /* ISSUE: Right place? */
if (authenticated && !do_pam_account(pw->pw_name, client_user))
authenticated = 0;
#endif
+ /* Log before sending the reply */
+ auth_log(authctxt, authenticated, get_authname(type), info);
+
if (client_user != NULL) {
xfree(client_user);
client_user = NULL;
@@ -371,14 +351,13 @@ do_authloop(struct passwd * pw, char *luser)
if (authenticated)
return;
- if (attempt > AUTH_FAIL_MAX) {
+ if (authctxt->failures++ > AUTH_FAIL_MAX) {
#ifdef WITH_AIXAUTHENTICATE
loginfailed(user,get_canonical_hostname(),"ssh");
#endif /* WITH_AIXAUTHENTICATE */
- packet_disconnect(AUTH_FAIL_MSG, luser);
+ packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
}
- /* Send a message indicating that the authentication attempt failed. */
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
@@ -392,10 +371,11 @@ do_authloop(struct passwd * pw, char *luser)
void
do_authentication()
{
- struct passwd *pw, pwcopy;
+ Authctxt *authctxt;
+ struct passwd *pw;
int plen;
u_int ulen;
- char *user;
+ char *user, *style = NULL;
/* Get the name of the user that we wish to log in as. */
packet_read_expect(&plen, SSH_CMSG_USER);
@@ -404,6 +384,13 @@ do_authentication()
user = packet_get_string(&ulen);
packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
+ if ((style = strchr(user, ':')) != NULL)
+ *style++ = 0;
+
+ authctxt = authctxt_new();
+ authctxt->user = user;
+ authctxt->style = style;
+
setproctitle("%s", user);
#ifdef AFS
@@ -417,21 +404,13 @@ do_authentication()
/* Verify that the user is a valid user. */
pw = getpwnam(user);
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);
-#endif
- pwcopy.pw_dir = xstrdup(pw->pw_dir);
- pwcopy.pw_shell = xstrdup(pw->pw_shell);
- pw = &pwcopy;
+ authctxt->valid = 1;
+ pw = pwcopy(pw);
} else {
+ debug("do_authentication: illegal user %s", user);
pw = NULL;
}
+ authctxt->pw = pw;
#ifdef USE_PAM
if (pw)
@@ -447,44 +426,25 @@ do_authentication()
packet_disconnect("Cannot change user when server not running as root.");
#endif
- debug("Attempting authentication for %s%.100s.", pw ? "" : "illegal user ", user);
-
- /* If the user has no password, accept authentication immediately. */
- if (options.password_authentication &&
-#ifdef KRB4
- (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
-#endif /* KRB4 */
-#ifdef USE_PAM
- 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)) {
-#else /* !HAVE_OSF_SIA && !USE_PAM */
- auth_password(pw, "")) {
-#endif /* USE_PAM */
- /* Authentication with empty password succeeded. */
- log("Login for user %s from %.100s, accepted without authentication.",
- user, get_remote_ipaddr());
- } else {
- /* Loop until the user has been authenticated or the
- connection is closed, do_authloop() returns only if
- authentication is successful */
- do_authloop(pw, user);
- }
- if (pw == NULL)
- fatal("internal error, authentication successful for user '%.100s'", user);
+ /*
+ * Loop until the user has been authenticated or the connection is
+ * closed, do_authloop() returns only if authentication is successful
+ */
+ do_authloop(authctxt);
/* 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)
+ if (loginsuccess(authctxt->user,get_canonical_hostname(),"ssh",&aixloginmsg) < 0)
aixloginmsg = NULL;
#endif /* WITH_AIXAUTHENTICATE */
- xfree(user);
+
+ xfree(authctxt->user);
+ xfree(authctxt);
/* Perform session preparation. */
do_authenticated(pw);
diff --git a/auth2-chall.c b/auth2-chall.c
new file mode 100644
index 00000000..77294f4b
--- /dev/null
+++ b/auth2-chall.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2001 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "includes.h"
+RCSID("$OpenBSD: auth2-chall.c,v 1.1 2001/01/18 17:12:43 markus Exp $");
+
+#include "ssh.h"
+#include "ssh2.h"
+#include "auth.h"
+#include "packet.h"
+#include "xmalloc.h"
+#include "dispatch.h"
+
+void send_userauth_into_request(Authctxt *authctxt, char *challenge, int echo);
+void input_userauth_info_response(int type, int plen, void *ctxt);
+
+/*
+ * try challenge-reponse, return -1 (= postponed) if we have to
+ * wait for the response.
+ */
+int
+auth2_challenge(Authctxt *authctxt, char *devs)
+{
+ char *challenge;
+
+ if (!authctxt->valid || authctxt->user == NULL)
+ return 0;
+ if ((challenge = get_challenge(authctxt, devs)) == NULL)
+ return 0;
+ send_userauth_into_request(authctxt, challenge, 0);
+ dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE,
+ &input_userauth_info_response);
+ authctxt->postponed = 1;
+ return 0;
+}
+
+void
+send_userauth_into_request(Authctxt *authctxt, char *challenge, int echo)
+{
+ int nprompts = 1;
+
+ packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST);
+ /* name, instruction and language are unused */
+ packet_put_cstring("");
+ packet_put_cstring("");
+ packet_put_cstring("");
+ packet_put_int(nprompts);
+ packet_put_cstring(challenge);
+ packet_put_char(echo);
+ packet_send();
+ packet_write_wait();
+}
+
+void
+input_userauth_info_response(int type, int plen, void *ctxt)
+{
+ Authctxt *authctxt = ctxt;
+ int authenticated = 0;
+ u_int nresp, rlen;
+ char *response, *method = "challenge-reponse";
+
+ if (authctxt == NULL)
+ fatal("input_userauth_info_response: no authctxt");
+
+ authctxt->postponed = 0; /* reset */
+ nresp = packet_get_int();
+ if (nresp == 1) {
+ response = packet_get_string(&rlen);
+ packet_done();
+ if (strlen(response) == 0) {
+ /*
+ * if we received an empty response, resend challenge
+ * with echo enabled
+ */
+ char *challenge = get_challenge(authctxt, NULL);
+ if (challenge != NULL) {
+ send_userauth_into_request(authctxt,
+ challenge, 1);
+ authctxt->postponed = 1;
+ }
+ } else if (authctxt->valid) {
+ authenticated = verify_response(authctxt, response);
+ memset(response, 'r', rlen);
+ }
+ xfree(response);
+ }
+ auth_log(authctxt, authenticated, method, " ssh2");
+ if (!authctxt->postponed) {
+ /* unregister callback and send reply */
+ dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL);
+ userauth_reply(authctxt,