summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--auth-rhosts.c27
-rw-r--r--auth.h7
-rw-r--r--auth2.c161
-rw-r--r--buffer.c11
-rw-r--r--canohost.c57
-rw-r--r--canohost.h4
-rw-r--r--compat.c6
-rw-r--r--compat.h3
-rw-r--r--hostfile.c4
-rw-r--r--pathnames.h5
-rw-r--r--readconf.c16
-rw-r--r--readconf.h3
-rw-r--r--servconf.c21
-rw-r--r--servconf.h4
-rw-r--r--ssh.c42
-rw-r--r--sshconnect.c8
-rw-r--r--sshconnect.h38
-rw-r--r--sshconnect1.c20
-rw-r--r--sshconnect2.c111
-rw-r--r--sshd_config4
21 files changed, 464 insertions, 99 deletions
diff --git a/ChangeLog b/ChangeLog
index 98dbed58..708e5991 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,15 @@
[ssh.c]
show debug output during option processing, report from
pekkas@netcore.fi
+ - OpenBSD CVS Sync
+ - markus@cvs.openbsd.org 2001/04/12 19:15:26
+ [auth-rhosts.c auth.h auth2.c buffer.c canohost.c canohost.h
+ compat.c compat.h hostfile.c pathnames.h readconf.c readconf.h
+ servconf.c servconf.h ssh.c sshconnect.c sshconnect.h sshconnect1.c
+ sshconnect2.c sshd_config]
+ implement HostbasedAuthentication (= RhostRSAAuthentication for ssh v2)
+ similar to RhostRSAAuthentication unless you enable (the experimental)
+ HostbasedUsesNameFromPacketOnly option. please test. :)
- (bal) Added openbsd-compat/inet_ntop.[ch] since HP/UX (and others)
lack it.
@@ -5026,4 +5035,4 @@
- Wrote replacements for strlcpy and mkdtemp
- Released 1.0pre1
-$Id: ChangeLog,v 1.1102 2001/04/12 21:35:52 mouring Exp $
+$Id: ChangeLog,v 1.1103 2001/04/12 23:34:34 mouring Exp $
diff --git a/auth-rhosts.c b/auth-rhosts.c
index c71e9b55..324a0f92 100644
--- a/auth-rhosts.c
+++ b/auth-rhosts.c
@@ -14,7 +14,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth-rhosts.c,v 1.22 2001/04/06 21:00:06 markus Exp $");
+RCSID("$OpenBSD: auth-rhosts.c,v 1.23 2001/04/12 19:15:24 markus Exp $");
#include "packet.h"
#include "xmalloc.h"
@@ -25,6 +25,9 @@ RCSID("$OpenBSD: auth-rhosts.c,v 1.22 2001/04/06 21:00:06 markus Exp $");
#include "canohost.h"
#include "auth.h"
+/* import */
+extern ServerOptions options;
+
/*
* This function processes an rhosts-style file (.rhosts, .shosts, or
* /etc/hosts.equiv). This returns true if authentication can be granted
@@ -150,16 +153,31 @@ check_rhosts_file(const char *filename, const char *hostname,
int
auth_rhosts(struct passwd *pw, const char *client_user)
{
- extern ServerOptions options;
- char buf[1024];
const char *hostname, *ipaddr;
+ int ret;
+
+ hostname = get_canonical_hostname(options.reverse_mapping_check);
+ ipaddr = get_remote_ipaddr();
+ ret = auth_rhosts2(pw, client_user, hostname, ipaddr);
+ return ret;
+}
+
+int
+auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
+ const char *ipaddr)
+{
+ char buf[1024];
struct stat st;
static const char *rhosts_files[] = {".shosts", ".rhosts", NULL};
u_int rhosts_file_index;
+ debug2("auth_rhosts2: clientuser %s hostname %s ipaddr %s",
+ client_user, hostname, ipaddr);
+
/* no user given */
if (pw == NULL)
return 0;
+
/* Switch to the user's uid. */
temporarily_use_uid(pw);
/*
@@ -184,9 +202,6 @@ auth_rhosts(struct passwd *pw, const char *client_user)
stat(_PATH_SSH_HOSTS_EQUIV, &st) < 0)
return 0;
- hostname = get_canonical_hostname(options.reverse_mapping_check);
- ipaddr = get_remote_ipaddr();
-
/* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */
if (pw->pw_uid != 0) {
if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr, client_user,
diff --git a/auth.h b/auth.h
index 50375226..1e02923c 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.14 2001/03/28 22:43:31 markus Exp $
+ * $OpenBSD: auth.h,v 1.15 2001/04/12 19:15:24 markus Exp $
*/
#ifndef AUTH_H
#define AUTH_H
@@ -58,6 +58,11 @@ struct Authctxt {
*/
int auth_rhosts(struct passwd * pw, const char *client_user);
+/* extended interface similar to auth_rhosts() */
+int
+auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
+ const char *ipaddr);
+
/*
* Tries to authenticate the user using the .rhosts file and the host using
* its host key. Returns true if authentication succeeds.
diff --git a/auth2.c b/auth2.c
index d676270b..cd6b2768 100644
--- a/auth2.c
+++ b/auth2.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth2.c,v 1.51 2001/04/06 21:00:08 markus Exp $");
+RCSID("$OpenBSD: auth2.c,v 1.52 2001/04/12 19:15:24 markus Exp $");
#include <openssl/evp.h>
@@ -48,6 +48,9 @@ RCSID("$OpenBSD: auth2.c,v 1.51 2001/04/06 21:00:08 markus Exp $");
#include "uidswap.h"
#include "auth-options.h"
#include "misc.h"
+#include "hostfile.h"
+#include "canohost.h"
+#include "tildexpand.h"
/* import */
extern ServerOptions options;
@@ -76,8 +79,11 @@ void protocol_error(int type, int plen, void *ctxt);
/* helper */
Authmethod *authmethod_lookup(const char *name);
-int user_key_allowed(struct passwd *pw, Key *key);
char *authmethods_get(void);
+int user_key_allowed(struct passwd *pw, Key *key);
+int
+hostbased_key_allowed(struct passwd *pw, const char *cuser, const char *chost,
+ Key *key);
/* auth */
void userauth_banner(void);
@@ -85,6 +91,7 @@ void userauth_reply(Authctxt *authctxt, int authenticated);
int userauth_none(Authctxt *authctxt);
int userauth_passwd(Authctxt *authctxt);
int userauth_pubkey(Authctxt *authctxt);
+int userauth_hostbased(Authctxt *authctxt);
int userauth_kbdint(Authctxt *authctxt);
Authmethod authmethods[] = {
@@ -100,6 +107,9 @@ Authmethod authmethods[] = {
{"keyboard-interactive",
userauth_kbdint,
&options.kbd_interactive_authentication},
+ {"hostbased",
+ userauth_hostbased,
+ &options.hostbased_authentication},
{NULL, NULL, NULL}
};
@@ -211,7 +221,7 @@ input_userauth_request(int type, int plen, void *ctxt)
} else if (authctxt->valid) {
if (strcmp(user, authctxt->user) != 0 ||
strcmp(service, authctxt->service) != 0) {
- log("input_userauth_request: missmatch: (%s,%s)!=(%s,%s)",
+ log("input_userauth_request: mismatch: (%s,%s)!=(%s,%s)",
user, service, authctxt->user, authctxt->service);
authctxt->valid = 0;
}
@@ -519,6 +529,89 @@ userauth_pubkey(Authctxt *authctxt)
return authenticated;
}
+int
+userauth_hostbased(Authctxt *authctxt)
+{
+ Buffer b;
+ Key *key;
+ char *pkalg, *pkblob, *sig;
+ char *cuser, *chost;
+ u_int alen, blen, slen;
+ int pktype;
+ int authenticated = 0;
+
+ if (!authctxt->valid) {
+ debug2("userauth_hostbased: disabled because of invalid user");
+ return 0;
+ }
+ pkalg = packet_get_string(&alen);
+ pkblob = packet_get_string(&blen);
+ chost = packet_get_string(NULL);
+ cuser = packet_get_string(NULL);
+ sig = packet_get_string(&slen);
+
+ debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
+ cuser, chost, pkalg, slen);
+#ifdef DEBUG_PK
+ debug("signature:");
+ buffer_init(&b);
+ buffer_append(&b, sig, slen);
+ buffer_dump(&b);
+ buffer_free(&b);
+#endif
+ pktype = key_type_from_name(pkalg);
+ if (pktype == KEY_UNSPEC) {
+ /* this is perfectly legal */
+ log("userauth_hostbased: unsupported "
+ "public key algorithm: %s", pkalg);
+ goto done;
+ }
+ key = key_from_blob(pkblob, blen);
+ if (key == NULL) {
+ debug("userauth_hostbased: cannot decode key: %s", pkalg);
+ goto done;
+ }
+ buffer_init(&b);
+ if (datafellows & SSH_OLD_SESSIONID) {
+ buffer_append(&b, session_id2, session_id2_len);
+ } else {
+ buffer_put_string(&b, session_id2, session_id2_len);
+ }
+ if (datafellows & SSH_BUG_HBSERVICE)
+ debug("SSH_BUG_HBSERVICE");
+ /* reconstruct packet */
+ buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+ buffer_put_cstring(&b, authctxt->user);
+ buffer_put_cstring(&b,
+ datafellows & SSH_BUG_HBSERVICE ?
+ "ssh-userauth" :
+ authctxt->service);
+ buffer_put_cstring(&b, "hostbased");
+ buffer_put_string(&b, pkalg, alen);
+ buffer_put_string(&b, pkblob, blen);
+ buffer_put_cstring(&b, chost);
+ buffer_put_cstring(&b, cuser);
+#ifdef DEBUG_PK
+ buffer_dump(&b);
+#endif
+ /* test for allowed key and correct signature */
+ if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) &&
+ key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
+ authenticated = 1;
+
+ buffer_clear(&b);
+ key_free(key);
+
+done:
+ debug2("userauth_hostbased: authenticated %d", authenticated);
+ xfree(pkalg);
+ xfree(pkblob);
+ xfree(cuser);
+ xfree(chost);
+ xfree(sig);
+ return authenticated;
+}
+
/* get current user */
struct passwd*
@@ -696,3 +789,65 @@ user_key_allowed(struct passwd *pw, Key *key)
debug2("key not found");
return found_key;
}
+
+/* return 1 if given hostkey is allowed */
+int
+hostbased_key_allowed(struct passwd *pw, const char *cuser, const char *chost,
+ Key *key)
+{
+ Key *found;
+ const char *resolvedname, *ipaddr, *lookup;
+ struct stat st;
+ char *user_hostfile;
+ int host_status;
+
+ resolvedname = get_canonical_hostname(options.reverse_mapping_check);
+ ipaddr = get_remote_ipaddr();
+
+ debug2("userauth_hostbased: resolvedname %s ipaddr %s",
+ resolvedname, ipaddr);
+
+ if (options.hostbased_uses_name_from_packet_only) {
+ if (auth_rhosts2(pw, cuser, chost, chost) == 0)
+ return 0;
+ lookup = chost;
+ } else {
+ if (strcasecmp(resolvedname, chost) != 0)
+ log("userauth_hostbased mismatch: "
+ "client sends %s, but we resolve %s to %s",
+ chost, ipaddr, resolvedname);
+ if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
+ return 0;
+ lookup = resolvedname;
+ }
+ debug2("userauth_hostbased: access allowed by auth_rhosts2");
+
+ /* XXX this is copied from auth-rh-rsa.c and should be shared */
+ found = key_new(key->type);
+ host_status = check_host_in_hostfile(_PATH_SSH_SYSTEM_HOSTFILE2, lookup,
+ key, found, NULL);
+
+ if (host_status != HOST_OK && !options.ignore_user_known_hosts) {
+ user_hostfile = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE2,
+ pw->pw_uid);
+ if (options.strict_modes &&
+ (stat(user_hostfile, &st) == 0) &&
+ ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
+ (st.st_mode & 022) != 0)) {
+ log("Hostbased authentication refused for %.100s: "
+ "bad owner or modes for %.200s",
+ pw->pw_name, user_hostfile);
+ } else {
+ temporarily_use_uid(pw);
+ host_status = check_host_in_hostfile(user_hostfile,
+ lookup, key, found, NULL);
+ restore_uid();
+ }
+ xfree(user_hostfile);
+ }
+ key_free(found);
+
+ debug2("userauth_hostbased: key %s for %s", host_status == HOST_OK ?
+ "ok" : "not found", lookup);
+ return (host_status == HOST_OK);
+}
diff --git a/buffer.c b/buffer.c
index 377d0c09..044caafb 100644
--- a/buffer.c
+++ b/buffer.c
@@ -12,7 +12,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: buffer.c,v 1.12 2001/04/07 08:55:15 markus Exp $");
+RCSID("$OpenBSD: buffer.c,v 1.13 2001/04/12 19:15:24 markus Exp $");
#include "xmalloc.h"
#include "buffer.h"
@@ -154,7 +154,12 @@ buffer_dump(Buffer *buffer)
int i;
u_char *ucp = (u_char *) buffer->buf;
- for (i = buffer->offset; i < buffer->end; i++)
- fprintf(stderr, " %02x", ucp[i]);
+ for (i = buffer->offset; i < buffer->end; i++) {
+ fprintf(stderr, "%02x", ucp[i]);
+ if ((i-buffer->offset)%16==15)
+ fprintf(stderr, "\r\n");
+ else if ((i-buffer->offset)%2==1)
+ fprintf(stderr, " ");
+ }
fprintf(stderr, "\r\n");
}
diff --git a/canohost.c b/canohost.c
index 927508f5..823545d4 100644
--- a/canohost.c
+++ b/canohost.c
@@ -12,7 +12,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: canohost.c,v 1.24 2001/04/05 15:48:19 stevesk Exp $");
+RCSID("$OpenBSD: canohost.c,v 1.25 2001/04/12 19:15:24 markus Exp $");
#include "packet.h"
#include "xmalloc.h"
@@ -202,30 +202,59 @@ get_canonical_hostname(int reverse_mapping_check)
* Returns the remote IP-address of socket as a string. The returned
* string must be freed.
*/
-
char *
-get_peer_ipaddr(int socket)
+get_socket_address(int socket, int remote, int flags)
{
- struct sockaddr_storage from;
- socklen_t fromlen;
+ struct sockaddr_storage addr;
+ socklen_t addrlen;
char ntop[NI_MAXHOST];
/* Get IP address of client. */
- fromlen = sizeof(from);
- memset(&from, 0, sizeof(from));
- if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
- debug("get_peer_ipaddr: getpeername failed: %.100s", strerror(errno));
- return NULL;
+ addrlen = sizeof(addr);
+ memset(&addr, 0, sizeof(addr));
+
+ if (remote) {
+ if (getpeername(socket, (struct sockaddr *)&addr, &addrlen)
+ < 0) {
+ debug("get_socket_ipaddr: getpeername failed: %.100s",
+ strerror(errno));
+ return NULL;
+ }
+ } else {
+ if (getsockname(socket, (struct sockaddr *)&addr, &addrlen)
+ < 0) {
+ debug("get_socket_ipaddr: getsockname failed: %.100s",
+ strerror(errno));
+ return NULL;
+ }
}
- /* Get the IP address in ascii. */
- if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
- NULL, 0, NI_NUMERICHOST) != 0) {
- error("get_peer_ipaddr: getnameinfo NI_NUMERICHOST failed");
+ /* Get the address in ascii. */
+ if (getnameinfo((struct sockaddr *)&addr, addrlen, ntop, sizeof(ntop),
+ NULL, 0, flags) != 0) {
+ error("get_socket_ipaddr: getnameinfo %d failed", flags);
return NULL;
}
return xstrdup(ntop);
}
+char *
+get_peer_ipaddr(int socket)
+{
+ return get_socket_address(socket, 1, NI_NUMERICHOST);
+}
+
+char *
+get_local_ipaddr(int socket)
+{
+ return get_socket_address(socket, 0, NI_NUMERICHOST);
+}
+
+char *
+get_local_name(int socket)
+{
+ return get_socket_address(socket, 0, NI_NAMEREQD);
+}
+
/*
* Returns the IP-address of the remote host as a string. The returned
* string must not be freed.
diff --git a/canohost.h b/canohost.h
index 89bd5c3b..36fb345a 100644
--- a/canohost.h
+++ b/canohost.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: canohost.h,v 1.5 2001/04/05 15:48:19 stevesk Exp $ */
+/* $OpenBSD: canohost.h,v 1.6 2001/04/12 19:15:24 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -30,6 +30,8 @@ const char *get_remote_name_or_ip(u_int utmp_len, int reverse_mapping_check);
/* Returns the ipaddr/port number of the peer of the socket. */
char * get_peer_ipaddr(int socket);
int get_peer_port(int sock);
+char * get_local_ipaddr(int socket);
+char * get_local_name(int socket);
/* Returns the port number of the remote/local host. */
int get_remote_port(void);
diff --git a/compat.c b/compat.c
index f96a6c63..4bdc6c6b 100644
--- a/compat.c
+++ b/compat.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: compat.c,v 1.45 2001/04/05 11:09:16 markus Exp $");
+RCSID("$OpenBSD: compat.c,v 1.46 2001/04/12 19:15:24 markus Exp $");
#ifdef HAVE_LIBPCRE
# include <pcreposix.h>
@@ -85,10 +85,10 @@ compat_datafellows(const char *version)
{ "MindTerm", 0 },
{ "^2\\.1\\.0", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
- SSH_BUG_RSASIGMD5 },
+ SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE },
{ "^2\\.1 ", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
- SSH_BUG_RSASIGMD5 },
+ SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE },
{ "^2\\.0\\.1[3-9]", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
SSH_BUG_PKSERVICE|SSH_BUG_X11FWD|
diff --git a/compat.h b/compat.h
index 244cd1aa..fc6f3344 100644
--- a/compat.h
+++ b/compat.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.
*/
-/* RCSID("$OpenBSD: compat.h,v 1.22 2001/04/05 11:09:17 markus Exp $"); */
+/* RCSID("$OpenBSD: compat.h,v 1.23 2001/04/12 19:15:24 markus Exp $"); */
#ifndef COMPAT_H
#define COMPAT_H
@@ -47,6 +47,7 @@
#define SSH_BUG_RSASIGMD5 0x2000
#define SSH_OLD_DHGEX 0x4000
#define SSH_BUG_NOREKEY 0x8000
+#define SSH_BUG_HBSERVICE 0x10000
void enable_compat13(void);
void enable_compat20(void);
diff --git a/hostfile.c b/hostfile.c
index 77aa8a89..d532bd6a 100644
--- a/hostfile.c
+++ b/hostfile.c
@@ -36,7 +36,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: hostfile.c,v 1.25 2001/04/06 22:12:47 stevesk Exp $");
+RCSID("$OpenBSD: hostfile.c,v 1.26 2001/04/12 19:15:24 markus Exp $");
#include "packet.h"
#include "match.h"
@@ -115,6 +115,7 @@ check_host_in_hostfile(const char *filename, const char *host, Key *key,
char *cp, *cp2;
HostStatus end_return;
+ debug3("check_host_in_hostfile: filename %s", filename);
if (key == NULL)
fatal("no key to look up");
/* Open the file containing the list of known hosts. */
@@ -166,6 +167,7 @@ check_host_in_hostfile(const char *filename, const char *host, Key *key,
/* Check if the current key is the same as the given key. */
if (key_equal(key, found)) {
/* Ok, they match. */
+ debug3("check_host_in_hostfile: match line %d", linenum);
fclose(f);
return HOST_OK;
}
diff --git a/pathnames.h b/pathnames.h
index 75415f3a..2f09820b 100644
--- a/pathnames.h
+++ b/pathnames.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pathnames.h,v 1.4 2001/02/08 22:28:07 stevesk Exp $ */
+/* $OpenBSD: pathnames.h,v 1.5 2001/04/12 19:15:24 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -31,10 +31,11 @@
* Of these, ssh_host_key must be readable only by root, whereas ssh_config
* should be world-readable.
*/
-#define _PATH_HOST_KEY_FILE ETCDIR "/ssh_host_key"
#define _PATH_SERVER_CONFIG_FILE ETCDIR "/sshd_config"
#define _PATH_HOST_CONFIG_FILE ETCDIR "/ssh_config"
+#define _PATH_HOST_KEY_FILE ETCDIR "/ssh_host_key"
#define _PATH_HOST_DSA_KEY_FILE ETCDIR "/ssh_host_dsa_key"
+#define _PATH_HOST_RSA_KEY_FILE ETCDIR "/ssh_host_rsa_key"
#define _PATH_DH_PRIMES ETCDIR "/primes"
#ifndef _PATH_SSH_PROGRAM
diff --git a/readconf.c b/readconf.c
index 007056d4..12b431d5 100644
--- a/readconf.c
+++ b/readconf.c
@@ -12,7 +12,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: readconf.c,v 1.71 2001/04/07 08:55:17 markus Exp $");
+RCSID("$OpenBSD: readconf.c,v 1.72 2001/04/12 19:15:25 markus Exp $");
#include "ssh.h"
#include "xmalloc.h"
@@ -110,7 +110,7 @@ typedef enum {
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
- oDynamicForward, oPreferredAuthentications
+ oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication
} OpCodes;
/* Textual representations of the tokens. */
@@ -131,6 +131,8 @@ static struct {
{ "rsaauthentication", oRSAAuthentication },
{ "pubkeyauthentication", oPubkeyAuthentication },
{ "dsaauthentication", oPubkeyAuthentication }, /* alias */
+ { "rhostsrsaauthentication", oRhostsRSAAuthentication },
+ { "hostbaedauthentication", oHostbasedAuthentication },
{ "challengeresponseauthentication", oChallengeResponseAuthentication },
{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
{ "tisauthentication", oChallengeResponseAuthentication }, /* alias */
@@ -158,7 +160,6 @@ static struct {
{ "user", oUser },
{ "host", oHost },
{ "escapechar", oEscapeChar },
- { "rhostsrsaauthentication", oRhostsRSAAuthentication },
{ "globalknownhostsfile", oGlobalKnownHostsFile },
{ "userknownhostsfile", oUserKnownHostsFile },
{ "globalknownhostsfile2", oGlobalKnownHostsFile2 },
@@ -324,6 +325,10 @@ parse_flag:
intptr = &options->rhosts_rsa_authentication;
goto parse_flag;
+ case oHostbasedAuthentication:
+ intptr = &options->hostbased_authentication;
+ goto parse_flag;
+
case oChallengeResponseAuthentication:
intptr = &options->challenge_reponse_authentication;
goto parse_flag;
@@ -594,7 +599,7 @@ parse_int:
filename, linenum);
fwd_port = atoi(arg);
add_local_forward(options, fwd_port, "socks4", 0);
- break;
+ break;
case oHost:
*activep = 0;
@@ -712,6 +717,7 @@ initialize_options(Options * options)
options->kbd_interactive_authentication = -1;
options->kbd_interactive_devices = NULL;
options->rhosts_rsa_authentication = -1;
+ options->hostbased_authentication = -1;
options->fallback_to_rsh = -1;
options->use_rsh = -1;
options->batch_mode = -1;
@@ -789,6 +795,8 @@ fill_default_options(Options * options)
options->kbd_interactive_authentication = 1;
if (options->rhosts_rsa_authentication == -1)
options->rhosts_rsa_authentication = 1;
+ if (options->hostbased_authentication == -1)
+ options->hostbased_authentication = 0;
if (options->fallback_to_rsh == -1)
options->fallback_to_rsh = 0;
if (options->use_rsh == -1)
diff --git a/readconf.h b/readconf.h
index 55babe80..680068b0 100644
--- a/readconf.h
+++ b/readconf.h
@@ -11,7 +11,7 @@
* called by a name other than "ssh" or "Secure Shell".
*/
-/* RCSID("$OpenBSD: readconf.h,v 1.28 2001/03/10 17:51:04 markus Exp $"); */
+/* RCSID("$OpenBSD: readconf.h,v 1.29 2001/04/12 19:15:25 markus Exp $"); */
#ifndef READCONF_H
#define READCONF_H
@@ -38,6 +38,7 @@ typedef struct {
* authentication. */
int rsa_authentication; /* Try RSA authentication. */
int pubkey_authentication; /* Try ssh2 pubkey authentication. */
+ int hostbased_authentication; /* ssh2's rhosts_rsa */
int challenge_reponse_authentication;
/* Try S/Key or TIS, authentication. */
#ifdef KRB4
diff --git a/servconf.c b/servconf.c
index 4d5eb53a..8e876d1f 100644
--- a/servconf.c
+++ b/servconf.c
@@ -10,7 +10,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: servconf.c,v 1.74 2001/04/06 22:25:25 stevesk Exp $");
+RCSID("$OpenBSD: servconf.c,v 1.75 2001/04/12 19:15:25 markus Exp $");
#ifdef KRB4
#include <krb.h>
@@ -67,6 +67,8 @@ initialize_server_options(ServerOptions *options)
options->log_level = (LogLevel) - 1;
options->rhosts_authentication = -1;
options->rhosts_rsa_authentication = -1;
+ options->hostbased_authentication = -1;
+ options->hostbased_uses_name_from_packet_only = -1;
options->rsa_authentication = -1;
options->pubkey_authentication = -1;
#ifdef KRB4
@@ -156,6 +158,10 @@ fill_default_server_options(ServerOptions *options)
options->rhosts_authentication = 0;
if (options->rhosts_rsa_authentication == -1)
options->rhosts_rsa_authentication = 0;
+ if (options->hostbased_authentication == -1)
+ options->hostbased_authentication = 0;
+ if (options->hostbased_uses_name_from_packet_only == -1)
+ options->hostbased_uses_name_from_packet_only = 0;
if (options->rsa_authentication == -1)
options->rsa_authentication = 1;
if (options->pubkey_authentication == -1)
@@ -219,7 +225,8 @@ typedef enum {
sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
- sBanner, sReverseMappingCheck
+ sBanner, sReverseMappingCheck, sHostbasedAuthentication,
+ sHostbasedUsesNameFromPacketOnly
} ServerOpCodes;
/* Textual representation of the tokens. */
@@ -239,6 +246,8 @@ static struct {
{ "loglevel", sLogLevel },
{ "rhostsauthentication", sRhostsAuthentication },
{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
+ { "hostbasedauthentication", sHostbasedAuthentication },
+ { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly },
{ "rsaauthentication", sRSAAuthentication },
{ "pubkeyauthentication", sPubkeyAuthentication },
{ "dsaauthentication", sPubkeyAuthentication }, /* alias */
@@ -537,6 +546,14 @@ parse_flag:
intptr = &options->rhosts_rsa_authentication;
goto parse_flag;
+ case sHostbasedAuthentication:
+ intptr = &options->hostbased_authentication;
+ goto parse_flag;
+
+ case sHostbasedUsesNameFromPacketOnly:
+ intptr = &options->hostbased_uses_name_from_packet_only;
+ goto parse_flag;
+
case sRSAAuthentication:
intptr = &options->rsa_authentication;
goto parse_flag;
diff --git a/servconf.h b/servconf.h
index 57d4370f..9b3a60f0 100644
--- a/servconf.h
+++ b/servconf.h
@@ -11,7 +11,7 @@
* called by a name other than "ssh" or "Secure Shell".
*/
-/* RCSID("$OpenBSD: servconf.h,v 1.39 2001/03/25 13:16:10 stevesk Exp $"); */
+/* RCSID("$OpenBSD: servconf.h,v 1.40 2001/04/12 19:15:25 markus Exp $"); */
#ifndef SERVCONF_H
#define SERVCONF_H
@@ -69,6 +69,8 @@ typedef struct {
* authentication. */
int rhosts_rsa_authentication; /* If true, permit rhosts RSA
* authentication. */
+ int hostbased_authentication; /* If true, permit ssh2 hostbased auth */
+ int hostbased_uses_name_from_packet_only; /* experimental */
int rsa_authentication; /* If true, permit RSA authentication. */
int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */
#ifdef KRB4
diff --git a/ssh.c b/ssh.c
index 5c08de82..f14fbac2 100644
--- a/ssh.c
+++ b/ssh.c
@@ -39,7 +39,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: ssh.c,v 1.111 2001/04/12 14:29:09 markus Exp $");
+RCSID("$OpenBSD: ssh.c,v 1.112 2001/04/12 19:15:25 markus Exp $");
#include <openssl/evp.h>
#include <openssl/err.h>
@@ -130,8 +130,11 @@ struct sockaddr_storage hostaddr;
*/
volatile int received_window_change_signal = 0;
-/* Host private key. */
-Key *host_private_key = NULL;
+/* Private host keys. */
+struct {
+ Key **keys;
+ int nkeys;
+} sensitive_data;
/* Original real UID. */
uid_t original_real_uid;
@@ -646,9 +649,18 @@ main(int ac, char **av)
* authentication. This must be done before releasing extra
* privileges, because the file is only readable by root.
*/
- if (ok && (options.protocol & SSH_PROTO_1)) {
- host_private_key = key_load_private_type(KEY_RSA1,
+ sensitive_data.nkeys = 0;
+ sensitive_data.keys = NULL;
+ if (ok && (options.rhosts_rsa_authentication ||
+ options.hostbased_authentication)) {
+ sensitive_data.nkeys = 3;
+ sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key));
+ sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
_PATH_HOST_KEY_FILE, "", NULL);
+ sensitive_data.keys[1] = key_load_private_type(KEY_DSA,
+ _PATH_HOST_DSA_KEY_FILE, "", NULL);
+ sensitive_data.keys[2] = key_load_private_type(KEY_RSA,
+ _PATH_HOST_RSA_KEY_FILE, "", NULL);
}
/*
* Get rid of any extra privileges that we may have. We will no
@@ -707,11 +719,21 @@ main(int ac, char **av)
tilde_expand_filename(options.user_hostfile2, original_real_uid);
/* Log into the remote system. This never returns if the login fails. */
- ssh_login(host_private_key, host, (struct sockaddr *)&hostaddr, pw);
-
- /* We no longer need the host private key. Clear it now. */
- if (host_private_key != NULL)
- key_free(host_private_key); /* Destroys contents safely */
+ ssh_login(sensitive_data.keys, sensitive_data.nkeys,
+ host, (struct sockaddr *)&hostaddr, pw);
+
+ /* We no longer need the private host keys. Clear them now. */
+ if (sensitive_data.nkeys != 0) {
+ for (i = 0; i < sensitive_data.nkeys; i++) {
+ if (sensitive_data.keys[i] != NULL) {
+ /* Destroys contents safely */
+ debug3("clear hostkey %d", i);
+ key_free(sensitive_data.keys[i]);
+ sensitive_data.keys[i] = NULL;
+ }
+ }
+ xfree(sensitive_data.keys);
+ }
exit_status = compat20 ? ssh_session2() : ssh_session();
packet_close();
diff --git a/sshconnect.c b/sshconnect.c
index 85427b44..60b16a24 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -13,7 +13,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect.c,v 1.103 2001/04/06 21:00:14 markus Exp $");
+RCSID("$OpenBSD: sshconnect.c,v 1.104 2001/04/12 19:15:25 markus Exp $");
#include <openssl/bn.h>
@@ -738,7 +738,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
* This function does not require super-user privileges.
*/
void
-ssh_login(Key *own_host_key, const char *orighost,
+ssh_login(Key **keys, int nkeys, const char *orighost,
struct sockaddr *hostaddr, struct passwd *pw)
{
char *host, *cp;
@@ -763,10 +763,10 @@ ssh_login(Key *own_host_key, const char *orighost,
/* authenticate user */
if (compat20) {
ssh_kex2(host, hostaddr);
- ssh_userauth2(server_user, host);
+ ssh_userauth2(local_user, server_user, host, keys, nkeys);
} else {
ssh_kex(host, hostaddr);
- ssh_userauth(local_user, server_user, host, own_host_key);
+ ssh_userauth1(local_user, server_user, host, keys, nkeys);
}
}
diff --git a/sshconnect.h b/sshconnect.h
index 45caf739..66104018 100644
--- a/sshconnect.h
+++ b/sshconnect.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect.h,v 1.8 2001/04/06 21:00:15 markus Exp $ */
+/* $OpenBSD: sshconnect.h,v 1.9 2001/04/12 19:15:25 markus Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -25,46 +25,30 @@
*/
#ifndef SSHCONNECT_H
#define SSHCONNECT_H
-/*
- * Opens a TCP/IP connection to the remote server on the given host. If port
- * is 0, the default port will be used. If anonymous is zero, a privileged
- * port will be allocated to make the connection. This requires super-user
- * privileges if anonymous is false. Connection_attempts specifies the
- * maximum number of tries, one per second. This returns true on success,
- * and zero on failure. If the connection is successful, this calls
- * packet_set_connection for the connection.
- */
+
int
ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
u_short port, int connection_attempts,
int anonymous, struct passwd *pw,
const char *proxy_command);
-/*
- * Starts a dialog with the server, and authenticates the current user on the
- * server. This does not need any extra privileges. The basic connection to
- * the server must already have been established before this is called. If
- * login fails, this function prints an error and never returns. This
- * initializes the random state, and leaves it initialized (it will also have
- * references from the packet module).
- */
-
void
-ssh_login(Key *host_key, const char *host,
- struct sockaddr * hostaddr, struct passwd *pw);
-
+ssh_login(Key **keys, int nkeys, const char *orighost,
+ struct sockaddr *hostaddr, struct passwd *pw);
void
check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
const char *user_hostfile, const char *system_hostfile);
void ssh_kex(char *host, struct sockaddr *hostaddr);
-void
-ssh_userauth(const char * local_user, const char * server_user, char *host,
- Key *own_host_key);
-
void ssh_kex2(char *host, struct sockaddr *hostaddr);
-void ssh_userauth2(const char *server_user, char *host);
+
+void
+ssh_userauth1(const char *local_user, const char *server_user, char *host,
+ Key **keys, int nkeys);
+void
+ssh_userauth2(const char *local_user, const char *server_user, char *host,
+ Key **keys, int nkeys);
void ssh_put_password(char *password);
diff --git a/sshconnect1.c b/sshconnect1.c
index 3ec5ecc5..865d04e8 100644
--- a/sshconnect1.c
+++ b/sshconnect1.c
@@ -13,7 +13,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect1.c,v 1.29 2001/03/26 08:07:09 markus Exp $");
+RCSID("$OpenBSD: sshconnect1.c,v 1.30 2001/04/12 19:15:25 markus Exp $");
#include <openssl/bn.h>
#include <openssl/evp.h>
@@ -911,17 +911,14 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
* Authenticate user
*/
void
-ssh_userauth(
- const char *local_user,
- const char *server_user,
- char *host,
- Key *own_host_key)
+ssh_userauth1(const char *local_user, const char *server_user, char *host,
+ Key **keys, int nkeys)
{
int i, type;
int payload_len;
if (supported_authentications == 0)
- fatal("ssh_userauth: server supports no auth methods");
+ fatal("ssh_userauth1: server supports no auth methods");
/* Send the name of the user to log in as on the server. */
packet_start(SSH_CMSG_USER);
@@ -1000,9 +997,12 @@ ssh_userauth(
* authentication.
*/
if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&
- options.rhosts_rsa_authentication && own_host_key != NULL) {
- if (try_rhosts_rsa_authentication(local_user, own_host_key))
- return;
+ options.rhosts_rsa_authentication) {
+ for (i = 0; i < nkeys; i++) {
+ if (keys[i]->type == KEY_RSA1 &&
+ try_rhosts_rsa_authentication(local_user, keys[i]))
+ return;
+ }
}
/* Try RSA authentication if the server supports it. */
if ((supported_authentications & (1 << SSH_AUTH_RSA)) &&
diff --git a/sshconnect2.c b/sshconnect2.c
index da5b7147..9a1d2576 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect2.c,v 1.67 2001/04/05 10:42:56 markus Exp $");
+RCSID("$OpenBSD: sshconnect2.c,v 1.68 2001/04/12 19:15:25 markus Exp $");
#include <openssl/bn.h>
#include <openssl/md5.h>
@@ -53,6 +53,7 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.67 2001/04/05 10:42:56 markus Exp $");
#include "readpass.h"
#include "match.h"
#include "dispatch.h"
+#include "canohost.h"
/* import */
extern char *client_version_string;
@@ -147,15 +148,20 @@ typedef int sign_cb_fn(
struct Authctxt {
const char *server_user;
+ const char *local_user;
const char *host;
const char *service;
- AuthenticationConnection *agent;
Authmethod *method;
int success;
char *authlist;
+ /* pubkey */
Key *last_key;
sign_cb_fn *last_key_sign;
int last_key_hint;
+ AuthenticationConnection *agent;
+ /* hostbased */
+ Key **keys;
+ int nkeys;
};
struct Authmethod {
char *name; /* string to compare against server's list */
@@ -175,6 +181,7 @@ int userauth_none(Authctxt *authctxt);
int userauth_pubkey(Authctxt *authctxt);
int userauth_passwd(Authctxt *authctxt);
int userauth_kbdint(Authctxt *authctxt);
+int userauth_hostbased(Authctxt *authctxt);
void userauth(Authctxt *authctxt, char *authlist);
@@ -200,6 +207,10 @@ Authmethod authmethods[] = {
userauth_kbdint,
&options.kbd_interactive_authentication,
&options.batch_mode},
+ {"hostbased",
+ userauth_hostbased,
+ &options.hostbased_authentication,
+ NULL},
{"none",
userauth_none,
NULL,
@@ -208,7 +219,8 @@ Authmethod authmethods[] = {
};
void
-ssh_userauth2(const char *server_user, char *host)
+ssh_userauth2(const char *local_user, const char *server_user, char *host,
+ Key **keys, int nkeys)
{
Authctxt authctxt;
int type;
@@ -242,11 +254,14 @@ ssh_userauth2(const char *server_user, char *host)
/* setup authentication context */
authctxt.agent = ssh_get_authentication_connection();
authctxt.server_user = server_user;
+ authctxt.local_user = local_user;
authctxt.host = host;
authctxt.service = "ssh-connection"; /* service name */
authctxt.success = 0;
authctxt.method = authmethod_lookup("none");
authctxt.authlist = NULL;
+ authctxt.keys = keys;
+ authctxt.nkeys = nkeys;
if (authctxt.method == NULL)
fatal("ssh_userauth2: internal error: cannot send userauth none request");
@@ -786,6 +801,96 @@ input_userauth_info_req(int type, int plen, void *ctxt)
packet_send();
}
+/*
+ * this will be move to an external program (ssh-keysign) ASAP. ssh-keysign
+ * will be setuid-root and the sbit can be removed from /usr/bin/ssh.
+ */
+int
+userauth_hostbased(Authctxt *authctxt)
+{
+ Key *private = NULL;
+ Buffer b;
+ u_char *signature, *blob;
+ char *chost, *pkalg, *p;
+ u_int blen, slen;
+ int ok, i, found = 0;
+
+ p = get_local_name(packet_get_connection_in());
+ if (p == NULL) {
+ error("userauth_hostbased: cannot get local ipaddr/name");
+ return 0;
+ }
+ chost = xstrdup(p);
+ debug2("userauth_hostbased: chost %s", chost);
+ /* check for a useful key */
+ for (i = 0; i < authctxt->nkeys; i++) {
+ private = authctxt->keys[i];
+ if (private && private->type != KEY_RSA1) {
+ found = 1;
+ /* we take and free the key */
+ authctxt->keys[i] = NULL;
+ break;
+ }
+ }
+ if (!found) {
+ xfree(chost);
+ return 0;
+ }
+ if (key_to_blob(private, &blob, &blen) == 0) {
+ key_free(private);
+ xfree(chost);
+ return 0;
+ }
+ pkalg = xstrdup(key_ssh_name(private));
+ buffer_init(&b);
+ if (datafellows & SSH_OLD_SESSIONID) {
+ buffer_append(&b, session_id2, session_id2_len);
+ } else {
+ buffer_put_string(&b, session_id2, session_id2_len);
+ }
+ /* construct data */
+ buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+ buffer_put_cstring(&b, authctxt->server_user);
+ buffer_put_cstring(&b,
+ datafellows & SSH_BUG_HBSERVICE ?
+ "ssh-userauth" :
+ authctxt->service);
+ buffer_put_cstring(&b, authctxt->method->name);
+ buffer_put_cstring(&b, pkalg);
+ buffer_put_string(&b, blob, blen);
+ buffer_put_cstring(&b, chost);
+ buffer_put_cstring(&b, authctxt->local_user);
+#ifdef DEBUG_PK
+ buffer_dump(&b);
+#endif
+ debug2("xxx: chost %s", chost);
+ ok = key_sign(private, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
+ key_free(private);
+ buffer_free(&b);
+ if (ok != 0) {
+ error("key_sign failed");
+ xfree(chost);
+ xfree(pkalg);
+ return 0;
+ }
+ packet_start(SSH2_MSG_USERAUTH_REQUEST);
+ packet_put_cstring(authctxt->server_user);
+ packet_put_cstring(authctxt->service);
+ packet_put_cstring(authctxt->method->name);
+ packet_put_cstring(pkalg);
+ packet_put_string(blob, blen);
+ packet_put_cstring(chost);
+ packet_put_cstring(authctxt->local_user);
+ packet_put_string(signature, slen);
+ memset(signature, 's', slen);
+ xfree(signature);
+ xfree(chost);
+ xfree(pkalg);
+
+ packet_send();
+ return 1;
+}
+
/* find auth method */
/*
diff --git a/sshd_config b/sshd_config
index 3ef9b929..c131a586 100644
--- a/sshd_config
+++ b/sshd_config
@@ -1,4 +1,4 @@
-# $OpenBSD: sshd_config,v 1.35 2001/03/25 13:16:11 stevesk Exp $
+# $OpenBSD: sshd_config,v 1.36 2001/04/12 19:15:26 markus Exp $
# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
@@ -37,6 +37,8 @@ RhostsAuthentication no
#
# For this to work you will also need host keys in /etc/ssh_known_hosts
RhostsRSAAuthentication no
+# similar for protocol version 2
+HostbasedAuthentication no
#
RSAAuthentication yes