summaryrefslogtreecommitdiff
path: root/usr.bin/ssh
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>1999-10-07 21:45:04 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>1999-10-07 21:45:04 +0000
commit6e7e05417a32dd36ddfb2755a30aaef99f727d97 (patch)
tree1627a5eea59bd10356b842f5b7ed0346717a98a4 /usr.bin/ssh
parent3420dc17a77c97696c3c678a6b8725d22c9d6a73 (diff)
add skey to sshd:
1) pass *pw to auth_password() not user_name, do_authentication already keeps private copy of struct passwd for current user. 2) limit authentication attemps to 5, otherwise ssh -o 'NumberOfPasswordPrompts 100000' host lets you enter 100000 passwds 3) make s/key a run-time option in /etc/sshd_config 4) generate fake skeys, for s/key for nonexisting users, too limit auth-tries for nonexisting users, too. Note that % ssh -l nonexisting-user -o 'NumberOfPasswordPrompts 100000' host has NO limits in ssh-1.2.27
Diffstat (limited to 'usr.bin/ssh')
-rw-r--r--usr.bin/ssh/Makefile.inc2
-rw-r--r--usr.bin/ssh/auth-passwd.c66
-rw-r--r--usr.bin/ssh/auth-skey.c148
-rw-r--r--usr.bin/ssh/servconf.c23
-rw-r--r--usr.bin/ssh/servconf.h5
-rw-r--r--usr.bin/ssh/ssh.h9
-rw-r--r--usr.bin/ssh/sshd.857
-rw-r--r--usr.bin/ssh/sshd.c35
-rw-r--r--usr.bin/ssh/sshd/Makefile10
-rw-r--r--usr.bin/ssh/sshd_config2
10 files changed, 300 insertions, 57 deletions
diff --git a/usr.bin/ssh/Makefile.inc b/usr.bin/ssh/Makefile.inc
index 0be2a7ac5d7..b6d0347f032 100644
--- a/usr.bin/ssh/Makefile.inc
+++ b/usr.bin/ssh/Makefile.inc
@@ -1 +1 @@
-CFLAGS+= -I${.OBJDIR} -I${.CURDIR}/..
+CFLAGS+= -I${.CURDIR}/..
diff --git a/usr.bin/ssh/auth-passwd.c b/usr.bin/ssh/auth-passwd.c
index b4873f7f085..1143c85a0c7 100644
--- a/usr.bin/ssh/auth-passwd.c
+++ b/usr.bin/ssh/auth-passwd.c
@@ -15,7 +15,7 @@ the password is valid for the user.
*/
#include "includes.h"
-RCSID("$Id: auth-passwd.c,v 1.5 1999/09/30 04:30:03 deraadt Exp $");
+RCSID("$Id: auth-passwd.c,v 1.6 1999/10/07 21:45:02 markus Exp $");
#include "packet.h"
#include "ssh.h"
@@ -29,14 +29,10 @@ extern char *ticket;
/* Tries to authenticate the user using password. Returns true if
authentication succeeds. */
-int auth_password(const char *server_user, const char *password)
+int auth_password(struct passwd *pw, const char *password)
{
extern ServerOptions options;
- extern char *crypt(const char *key, const char *salt);
- struct passwd *pw;
char *encrypted_password;
- char correct_passwd[200];
- char *saved_pw_name, *saved_pw_passwd;
if (*password == '\0' && options.permit_empty_passwd == 0)
{
@@ -44,14 +40,32 @@ int auth_password(const char *server_user, const char *password)
return 0;
}
- /* Get the encrypted password for the user. */
- pw = getpwnam(server_user);
- if (!pw)
+ /* deny if no user. */
+ if (pw == NULL)
return 0;
- saved_pw_name = xstrdup(pw->pw_name);
- saved_pw_passwd = xstrdup(pw->pw_passwd);
-
+#ifdef SKEY
+ if (options.skey_authentication == 1) {
+ if (strncasecmp(password, "s/key", 5) == 0) {
+ char *skeyinfo = skey_keyinfo(pw->pw_name);
+ if(skeyinfo == NULL){
+ debug("generating fake skeyinfo for %.100s.", pw->pw_name);
+ skeyinfo = skey_fake_keyinfo(pw->pw_name);
+ }
+ if(skeyinfo != NULL)
+ packet_send_debug(skeyinfo);
+ /* Try again. */
+ return 0;
+ }
+ else if (skey_haskey(pw->pw_name) == 0 &&
+ skey_passcheck(pw->pw_name, (char *)password) != -1) {
+ /* Authentication succeeded. */
+ return 1;
+ }
+ /* Fall back to ordinary passwd authentication. */
+ }
+#endif
+
#if defined(KRB4)
/* Support for Kerberos v4 authentication - Dug Song <dugsong@UMICH.EDU> */
if (options.kerberos_authentication)
@@ -72,15 +86,15 @@ int auth_password(const char *server_user, const char *password)
/* Set up our ticket file. */
if (!ssh_tf_init(pw->pw_uid)) {
log("Couldn't initialize Kerberos ticket file for %s!",
- server_user);
+ pw->pw_name);
goto kerberos_auth_failure;
}
/* Try to get TGT using our password. */
- r = krb_get_pw_in_tkt((char *)server_user, "", realm, "krbtgt", realm,
+ r = krb_get_pw_in_tkt((char *)pw->pw_name, "", realm, "krbtgt", realm,
DEFAULT_TKT_LIFE, (char *)password);
if (r != INTK_OK) {
packet_send_debug("Kerberos V4 password authentication for %s "
- "failed: %s", server_user, krb_err_txt[r]);
+ "failed: %s", pw->pw_name, krb_err_txt[r]);
goto kerberos_auth_failure;
}
/* Successful authentication. */
@@ -105,7 +119,7 @@ int auth_password(const char *server_user, const char *password)
if (r == RD_AP_UNDEC) {
/* Probably didn't have a srvtab on localhost. Allow login. */
log("Kerberos V4 TGT for %s unverifiable, no srvtab installed? "
- "krb_rd_req: %s", server_user, krb_err_txt[r]);
+ "krb_rd_req: %s", pw->pw_name, krb_err_txt[r]);
}
else if (r != KSUCCESS) {
log("Kerberos V4 %s ticket unverifiable: %s",
@@ -116,13 +130,13 @@ int auth_password(const char *server_user, const char *password)
else if (r == KDC_PR_UNKNOWN) {
/* Allow login if no rcmd service exists, but log the error. */
log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s "
- "not registered, or srvtab is wrong?", server_user,
+ "not registered, or srvtab is wrong?", pw->pw_name,
krb_err_txt[r], KRB4_SERVICE_NAME, phost);
}
else {
/* TGT is bad, forget it. Possibly spoofed! */
packet_send_debug("WARNING: Kerberos V4 TGT possibly spoofed for"
- "%s: %s", server_user, krb_err_txt[r]);
+ "%s: %s", pw->pw_name, krb_err_txt[r]);
goto kerberos_auth_failure;
}
@@ -142,25 +156,19 @@ int auth_password(const char *server_user, const char *password)
/* Fall back to ordinary passwd authentication. */
}
#endif /* KRB4 */
-
- /* Save the encrypted password. */
- strlcpy(correct_passwd, saved_pw_passwd, sizeof(correct_passwd));
-
+
/* Check for users with no password. */
- if (strcmp(password, "") == 0 && strcmp(correct_passwd, "") == 0)
+ if (strcmp(password, "") == 0 && strcmp(pw->pw_passwd, "") == 0)
{
packet_send_debug("Login permitted without a password because the account has no password.");
return 1; /* The user has no password and an empty password was tried. */
}
- xfree(saved_pw_name);
- xfree(saved_pw_passwd);
-
/* Encrypt the candidate password using the proper salt. */
encrypted_password = crypt(password,
- (correct_passwd[0] && correct_passwd[1]) ?
- correct_passwd : "xx");
+ (pw->pw_passwd[0] && pw->pw_passwd[1]) ?
+ pw->pw_passwd : "xx");
/* Authentication is accepted if the encrypted passwords are identical. */
- return (strcmp(encrypted_password, correct_passwd) == 0);
+ return (strcmp(encrypted_password, pw->pw_passwd) == 0);
}
diff --git a/usr.bin/ssh/auth-skey.c b/usr.bin/ssh/auth-skey.c
new file mode 100644
index 00000000000..fe3103bd352
--- /dev/null
+++ b/usr.bin/ssh/auth-skey.c
@@ -0,0 +1,148 @@
+#include "includes.h"
+RCSID("$Id: auth-skey.c,v 1.1 1999/10/07 21:45:02 markus Exp $");
+
+#include "ssh.h"
+#include <sha1.h>
+
+/* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
+
+
+#define ROUND(x) (((x)[0] << 24) + (((x)[1]) << 16) + (((x)[2]) << 8) + \
+ ((x)[3]))
+
+/*
+ * hash_collapse()
+ */
+static u_int32_t
+hash_collapse(s)
+ u_char *s;
+{
+ int len, target;
+ u_int32_t i;
+
+ if ((strlen(s) % sizeof(u_int32_t)) == 0)
+ target = strlen(s); /* Multiple of 4 */
+ else
+ target = strlen(s) - (strlen(s) % sizeof(u_int32_t));
+
+ for (i = 0, len = 0; len < target; len += 4)
+ i ^= ROUND(s + len);
+
+ return i;
+}
+char *
+skey_fake_keyinfo(char *username)
+{
+ int i;
+ u_int ptr;
+ u_char hseed[SKEY_MAX_SEED_LEN], flg = 1, *up;
+ char pbuf[SKEY_MAX_PW_LEN+1];
+ static char skeyprompt[SKEY_MAX_CHALLENGE+1];
+ char *secret = NULL;
+ size_t secretlen = 0;
+ SHA1_CTX ctx;
+ char *p, *u;
+
+ /*
+ * Base first 4 chars of seed on hostname.
+ * Add some filler for short hostnames if necessary.
+ */
+ if (gethostname(pbuf, sizeof(pbuf)) == -1)
+ *(p = pbuf) = '.';
+ else
+ for (p = pbuf; *p && isalnum(*p); p++)
+ if (isalpha(*p) && isupper(*p))
+ *p = tolower(*p);
+ if (*p && pbuf - p < 4)
+ (void)strncpy(p, "asjd", 4 - (pbuf - p));
+ pbuf[4] = '\0';
+
+ /* Hash the username if possible */
+ if ((up = SHA1Data(username, strlen(username), NULL)) != NULL) {
+ struct stat sb;
+ time_t t;
+ int fd;
+
+ /* Collapse the hash */
+ ptr = hash_collapse(up);
+ memset(up, 0, strlen(up));
+
+ /* See if the random file's there, else use ctime */
+ if ((fd = open(_SKEY_RAND_FILE_PATH_, O_RDONLY)) != -1
+ && fstat(fd, &sb) == 0 &&
+ sb.st_size > (off_t)SKEY_MAX_SEED_LEN &&
+ lseek(fd, ptr % (sb.st_size - SKEY_MAX_SEED_LEN),
+ SEEK_SET) != -1 && read(fd, hseed,
+ SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) {
+ close(fd);
+ secret = hseed;
+ secretlen = SKEY_MAX_SEED_LEN;
+ flg = 0;
+ } else if (!stat(_PATH_MEM, &sb) || !stat("/", &sb)) {
+ t = sb.st_ctime;
+ secret = ctime(&t);
+ secretlen = strlen(secret);
+ flg = 0;
+ }
+ }
+
+ /* Put that in your pipe and smoke it */
+ if (flg == 0) {
+ /* Hash secret value with username */
+ SHA1Init(&ctx);
+ SHA1Update(&ctx, secret, secretlen);
+ SHA1Update(&ctx, username, strlen(username));
+ SHA1End(&ctx, up);
+
+ /* Zero out */
+ memset(secret, 0, secretlen);
+
+ /* Now hash the hash */
+ SHA1Init(&ctx);
+ SHA1Update(&ctx, up, strlen(up));
+ SHA1End(&ctx, up);
+
+ ptr = hash_collapse(up + 4);
+
+ for (i = 4; i < 9; i++) {
+ pbuf[i] = (ptr % 10) + '0';
+ ptr /= 10;
+ }
+ pbuf[i] = '\0';
+
+ /* Sequence number */
+ ptr = ((up[2] + up[3]) % 99) + 1;
+
+ memset(up, 0, 20); /* SHA1 specific */
+ free(up);
+
+ (void)sprintf(skeyprompt,
+ "otp-%.*s %d %.*s",
+ SKEY_MAX_HASHNAME_LEN,
+ skey_get_algorithm(),
+ ptr, SKEY_MAX_SEED_LEN,
+ pbuf);
+ } else {
+ /* Base last 8 chars of seed on username */
+ u = username;
+ i = 8;
+ p = &pbuf[4];
+ do {
+ if (*u == 0) {
+ /* Pad remainder with zeros */
+ while (--i >= 0)
+ *p++ = '0';
+ break;
+ }
+
+ *p++ = (*u++ % 10) + '0';
+ } while (--i != 0);
+ pbuf[12] = '\0';
+
+ (void)sprintf(skeyprompt, "otp-%.*s %d %.*s",
+ SKEY_MAX_HASHNAME_LEN,
+ skey_get_algorithm(),
+ 99, SKEY_MAX_SEED_LEN, pbuf);
+ }
+ return skeyprompt;
+}
diff --git a/usr.bin/ssh/servconf.c b/usr.bin/ssh/servconf.c
index f68ecb10ab3..ab8cac6d2ea 100644
--- a/usr.bin/ssh/servconf.c
+++ b/usr.bin/ssh/servconf.c
@@ -12,7 +12,7 @@ Created: Mon Aug 21 15:48:58 1995 ylo
*/
#include "includes.h"
-RCSID("$Id: servconf.c,v 1.9 1999/10/02 19:18:22 deraadt Exp $");
+RCSID("$Id: servconf.c,v 1.10 1999/10/07 21:45:02 markus Exp $");
#include "ssh.h"
#include "servconf.h"
@@ -52,6 +52,9 @@ void initialize_server_options(ServerOptions *options)
options->afs_token_passing = -1;
#endif
options->password_authentication = -1;
+#ifdef SKEY
+ options->skey_authentication = -1;
+#endif
options->permit_empty_passwd = -1;
options->num_allow_hosts = 0;
options->num_deny_hosts = 0;
@@ -120,8 +123,12 @@ void fill_default_server_options(ServerOptions *options)
#endif /* AFS */
if (options->password_authentication == -1)
options->password_authentication = 1;
+#ifdef SKEY
+ if (options->skey_authentication == -1)
+ options->skey_authentication = 1;
+#endif
if (options->permit_empty_passwd == -1)
- options->permit_empty_passwd = 1;
+ options->permit_empty_passwd = 1;
}
#define WHITESPACE " \t\r\n"
@@ -138,6 +145,9 @@ typedef enum
#ifdef AFS
sKerberosTgtPassing, sAFSTokenPassing,
#endif
+#ifdef SKEY
+ sSkeyAuthentication,
+#endif
sPasswordAuthentication, sAllowHosts, sDenyHosts, sListenAddress,
sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives
@@ -172,6 +182,9 @@ static struct
{ "afstokenpassing", sAFSTokenPassing },
#endif
{ "passwordauthentication", sPasswordAuthentication },
+#ifdef SKEY
+ { "skeyauthentication", sSkeyAuthentication },
+#endif
{ "allowhosts", sAllowHosts },
{ "denyhosts", sDenyHosts },
{ "listenaddress", sListenAddress },
@@ -392,6 +405,12 @@ void read_server_config(ServerOptions *options, const char *filename)
intptr = &options->password_authentication;
goto parse_flag;
+#ifdef SKEY
+ case sSkeyAuthentication:
+ intptr = &options->skey_authentication;
+ goto parse_flag;
+#endif
+
case sPrintMotd:
intptr = &options->print_motd;
goto parse_flag;
diff --git a/usr.bin/ssh/servconf.h b/usr.bin/ssh/servconf.h
index d87b83c965d..8a838011594 100644
--- a/usr.bin/ssh/servconf.h
+++ b/usr.bin/ssh/servconf.h
@@ -13,7 +13,7 @@ Definitions for server configuration data and for the functions reading it.
*/
-/* RCSID("$Id: servconf.h,v 1.4 1999/10/01 02:38:09 provos Exp $"); */
+/* RCSID("$Id: servconf.h,v 1.5 1999/10/07 21:45:02 markus Exp $"); */
#ifndef SERVCONF_H
#define SERVCONF_H
@@ -54,6 +54,9 @@ typedef struct
int afs_token_passing; /* If true, permit AFS token passing. */
#endif
int password_authentication; /* If true, permit password authentication. */
+#ifdef SKEY
+ int skey_authentication; /* If true, permit s/key authentication. */
+#endif
int permit_empty_passwd; /* If false, do not permit empty passwords. */
unsigned int num_allow_hosts;
char *allow_hosts[MAX_ALLOW_HOSTS];
diff --git a/usr.bin/ssh/ssh.h b/usr.bin/ssh/ssh.h
index 1586ace8b22..756a795b8bc 100644
--- a/usr.bin/ssh/ssh.h
+++ b/usr.bin/ssh/ssh.h
@@ -13,7 +13,7 @@ Generic header file for ssh.
*/
-/* RCSID("$Id: ssh.h,v 1.8 1999/10/05 22:18:52 markus Exp $"); */
+/* RCSID("$Id: ssh.h,v 1.9 1999/10/07 21:45:02 markus Exp $"); */
#ifndef SSH_H
#define SSH_H
@@ -260,7 +260,7 @@ int auth_rhosts_rsa(struct passwd *pw, const char *client_user,
/* Tries to authenticate the user using password. Returns true if
authentication succeeds. */
-int auth_password(const char *server_user, const char *password);
+int auth_password(struct passwd *pw, const char *password);
/* Performs the RSA authentication dialog with the client. This returns
0 if the client could not be authenticated, and 1 if authentication was
@@ -583,4 +583,9 @@ int radix_to_creds(const char *buf, CREDENTIALS *creds);
#endif /* KRB4 */
+#ifdef SKEY
+#include <skey.h>
+char *skey_fake_keyinfo(char *username);
+#endif /* SKEY */
+
#endif /* SSH_H */
diff --git a/usr.bin/ssh/sshd.8 b/usr.bin/ssh/sshd.8
index e32a9ae89ee..d088b62105f 100644
--- a/usr.bin/ssh/sshd.8
+++ b/usr.bin/ssh/sshd.8
@@ -9,7 +9,7 @@
.\"
.\" Created: Sat Apr 22 21:55:14 1995 ylo
.\"
-.\" $Id: sshd.8,v 1.6 1999/10/03 18:46:12 aaron Exp $
+.\" $Id: sshd.8,v 1.7 1999/10/07 21:45:02 markus Exp $
.\"
.Dd September 25, 1999
.Dt SSHD 8
@@ -126,14 +126,22 @@ indicates no limit.
.It Fl h Ar host_key_file
Specifies the file from which the host key is read (default
.Pa /etc/ssh_host_key ) .
-This option must be given if sshd is not run as root (as the normal
+This option must be given if
+.Nm
+is not run as root (as the normal
host file is normally not readable by anyone but root).
.It Fl i
-Specifies that sshd is being run from inetd. Sshd is normally not run
+Specifies that
+.Nm
+is being run from inetd.
+.Nm
+is normally not run
from inetd because it needs to generate the server key before it can
respond to the client, and this may take tens of seconds. Clients
would have to wait too long if the key was regenerated every time.
-However, with small key sizes (e.g. 512) using sshd from inetd may
+However, with small key sizes (e.g. 512) using
+.Nm
+from inetd may
be feasible.
.It Fl k Ar key_gen_time
Specifies how often the server key is regenerated (default 3600
@@ -182,7 +190,7 @@ are allowed to connect.
Note that
.Nm
can also be configured to use tcp_wrappers using the
-.Fl LIBWARP
+.Sy LIBWARP
compile-time option.
.It Cm DenyHosts
This keyword can be followed by any number of host name patterns,
@@ -228,7 +236,8 @@ To disable keepalives, the value should be set to
in both the server and the client configuration files.
.It Cm KerberosAuthentication
Specifies whether Kerberos authentication is allowed. This can
-be in the form of a Kerberos ticket, or if PasswordAuthentication
+be in the form of a Kerberos ticket, or if
+.Cm PasswordAuthentication
is yes, the password provided by the user will be validated through
the Kerberos KDC. Default is
.Dq yes .
@@ -245,8 +254,8 @@ Default is
.Dq no ,
as this only works when the Kerberos KDC is actually an AFS kaserver.
.It Cm KerberosTicketCleanup
-Specifies whether to automatically destroy the user's
-ticket cache file on logout. Default is
+Specifies whether to automatically destroy the user's ticket cache
+file on logout. Default is
.Dq yes .
.It Cm KeyRegenerationInterval
The server key is automatically regenerated after this many seconds
@@ -255,6 +264,11 @@ decrypting captured sessions by later breaking into the machine and
stealing the keys. The key is never stored anywhere. If the value is
0, the key is never regenerated. The default is 3600
(seconds).
+.It Cm ListenAddress
+Specifies what local address
+.Nm
+should listen on.
+The default is to listen to all local addresses.
.It Cm LoginGraceTime
The server disconnects after this time if the user has not
successfully logged in. If the value is 0, there is no time limit.
@@ -304,7 +318,9 @@ Obsolete. Random number generation uses other techniques.
.It Cm RhostsAuthentication
Specifies whether authentication using rhosts or /etc/hosts.equiv
files is sufficient. Normally, this method should not be permitted
-because it is insecure. RhostsRSAAuthentication should be used
+because it is insecure.
+.Cm RhostsRSAAuthentication
+should be used
instead, because it performs RSA-based host authentication in addition
to normal rhosts or /etc/hosts.equiv authentication.
The default is
@@ -319,11 +335,20 @@ Specifies whether pure RSA authentication is allowed. The default is
.It Cm ServerKeyBits
Defines the number of bits in the server key. The minimum value is
512, and the default is 768.
+.It Cm SkeyAuthentication
+Specifies whether
+.Xr skey 1
+authentication is allowed. The default is
+.Dq yes .
+Note that s/key authentication is enabled only if
+.Cm PasswordAuthentication
+is allowed, too.
.It Cm StrictModes
Specifies whether SSH should check file modes and ownership of the
user's home directory and rhosts files before accepting login. This
is normally desirable because novices sometimes accidentally leave their
-directory or files world-writable. The default is "yes".
+directory or files world-writable. The default is
+.Dq yes .
.It Cm SyslogFacility
Gives the facility code that is used when logging messages from
.Nm sshd .
@@ -516,19 +541,17 @@ Contains configuration data for
This file should be writable by root only, but it is recommended
(though not necessary) that it be world-readable.
.It Pa /etc/ssh_host_key
-Contains the private part of the host key. This file is normally
-created automatically by "make install", but can also be created
-manually using
-.Xr ssh-keygen 1 .
+Contains the private part of the host key.
This file should only be owned by root, readable only by root, and not
accessible to others.
.It Pa /etc/ssh_host_key.pub
-Contains the public part of the host key. This file is normally
-created automatically by "make install", but can also be created
-manually. This file should be world-readable but writable only by
+Contains the public part of the host key.
+This file should be world-readable but writable only by
root. Its contents should match the private part. This file is not
really used for anything; it is only provided for the convenience of
the user so its contents can be copied to known hosts files.
+These two files are created using
+.Xr ssh-keygen 1 .
.It Pa /var/run/sshd.pid
Contains the process ID of the
.Nm
diff --git a/usr.bin/ssh/sshd.c b/usr.bin/ssh/sshd.c
index 166c9256a9e..5c5317eec34 100644
--- a/usr.bin/ssh/sshd.c
+++ b/usr.bin/ssh/sshd.c
@@ -18,7 +18,7 @@ agent connections.
*/
#include "includes.h"
-RCSID("$Id: sshd.c,v 1.23 1999/10/07 04:40:03 deraadt Exp $");
+RCSID("$Id: sshd.c,v 1.24 1999/10/07 21:45:02 markus Exp $");
#include "xmalloc.h"
#include "rsa.h"
@@ -938,11 +938,14 @@ void do_connection(int privileged_port)
in as (received from the clinet). Privileged_port is true if the
connection comes from a privileged port (used for .rhosts authentication).*/
+#define MAX_AUTH_FAILURES 5
+
void
do_authentication(char *user, int privileged_port)
{
int type;
int authenticated = 0;
+ int authentication_failures = 0;
char *password;
struct passwd *pw, pwcopy;
char *client_user;
@@ -972,13 +975,30 @@ do_authentication(char *user, int privileged_port)
{
/* Read a packet. This will not return if the client disconnects. */
int plen;
- (void) packet_read(&plen);
-
+ int type = packet_read(&plen);
+#ifdef SKEY
+ int passw_len;
+ char *password, *skeyinfo;
+ if (options.password_authentication &&
+ options.skey_authentication == 1 &&
+ type == SSH_CMSG_AUTH_PASSWORD &&
+ (password = packet_get_string(&passw_len)) != NULL &&
+ passw_len == 5 &&
+ strncasecmp(password, "s/key", 5) == 0 &&
+ (skeyinfo = skey_fake_keyinfo(user)) != NULL ){
+ /* Send a fake s/key challenge. */
+ packet_send_debug(skeyinfo);
+ }
+#endif
/* Send failure. This should be indistinguishable from a failed
authentication. */
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
+ if (++authentication_failures >= MAX_AUTH_FAILURES) {
+ packet_disconnect("To many authentication failures for %.100s from %.200s",
+ user, get_canonical_hostname());
+ }
}
/*NOTREACHED*/
abort();
@@ -1006,7 +1026,7 @@ do_authentication(char *user, int privileged_port)
#ifdef KRB4
options.kerberos_or_local_passwd &&
#endif /* KRB4 */
- auth_password(user, ""))
+ auth_password(pw, ""))
{
/* Authentication with empty password succeeded. */
debug("Login for user %.100s accepted without authentication.", user);
@@ -1243,7 +1263,7 @@ do_authentication(char *user, int privileged_port)
}
/* Try authentication with the password. */
- if (auth_password(user, password))
+ if (auth_password(pw, password))
{
/* Successful authentication. */
/* Clear the password from memory. */
@@ -1272,6 +1292,11 @@ do_authentication(char *user, int privileged_port)
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
+
+ if (++authentication_failures >= MAX_AUTH_FAILURES) {
+ packet_disconnect("To many authentication failures for %.100s from %.200s",
+ pw->pw_name, get_canonical_hostname());
+ }
}
/* Check if the user is logging in as root and root logins are disallowed. */
diff --git a/usr.bin/ssh/sshd/Makefile b/usr.bin/ssh/sshd/Makefile
index db22b53ed29..f2d01164527 100644
--- a/usr.bin/ssh/sshd/Makefile
+++ b/usr.bin/ssh/sshd/Makefile
@@ -27,6 +27,10 @@ DPADD+= ${LIBKRBAFS}
.endif # AFS
.endif # KERBEROS
+.if (${SKEY} == "yes")
+SRCS+= auth-skey.c
+.endif
+
.include <bsd.prog.mk>
LDADD+= -lcrypto -lutil -lz
@@ -37,3 +41,9 @@ CFLAGS+= -DLIBWRAP
LDADD+= -lwrap
DPADD+= ${LIBWRAP}
.endif
+
+.if (${SKEY} == "yes")
+CFLAGS+= -DSKEY
+LDADD+= -lskey
+DPADD+= ${SKEY}
+.endif
diff --git a/usr.bin/ssh/sshd_config b/usr.bin/ssh/sshd_config
index 3c5e41879fa..5f30462b301 100644
--- a/usr.bin/ssh/sshd_config
+++ b/usr.bin/ssh/sshd_config
@@ -29,6 +29,8 @@ RSAAuthentication yes
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication yes
PermitEmptyPasswords no
+# Uncomment to disable s/key passwords
+#SkeyAuthentication no
# To change Kerberos options
#KerberosAuthentication no