summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/ssh/auth-rhosts.c27
-rw-r--r--usr.bin/ssh/auth.h7
-rw-r--r--usr.bin/ssh/auth2.c161
-rw-r--r--usr.bin/ssh/buffer.c11
-rw-r--r--usr.bin/ssh/canohost.c57
-rw-r--r--usr.bin/ssh/canohost.h4
-rw-r--r--usr.bin/ssh/compat.c6
-rw-r--r--usr.bin/ssh/compat.h3
-rw-r--r--usr.bin/ssh/hostfile.c4
-rw-r--r--usr.bin/ssh/pathnames.h5
-rw-r--r--usr.bin/ssh/readconf.c16
-rw-r--r--usr.bin/ssh/readconf.h3
-rw-r--r--usr.bin/ssh/servconf.c21
-rw-r--r--usr.bin/ssh/servconf.h4
-rw-r--r--usr.bin/ssh/ssh.c42
-rw-r--r--usr.bin/ssh/sshconnect.c8
-rw-r--r--usr.bin/ssh/sshconnect.h38
-rw-r--r--usr.bin/ssh/sshconnect1.c20
-rw-r--r--usr.bin/ssh/sshconnect2.c111
-rw-r--r--usr.bin/ssh/sshd_config4
20 files changed, 454 insertions, 98 deletions
diff --git a/usr.bin/ssh/auth-rhosts.c b/usr.bin/ssh/auth-rhosts.c
index c71e9b55d04..324a0f92590 100644
--- a/usr.bin/ssh/auth-rhosts.c
+++ b/usr.bin/ssh/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/usr.bin/ssh/auth.h b/usr.bin/ssh/auth.h
index c727519037a..500b73a3f0f 100644
--- a/usr.bin/ssh/auth.h
+++ b/usr.bin/ssh/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/usr.bin/ssh/auth2.c b/usr.bin/ssh/auth2.c
index e5a266830b7..56c2be7e4fe 100644
--- a/usr.bin/ssh/auth2.c
+++ b/usr.bin/ssh/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;
@@ -72,8 +75,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);
@@ -81,6 +87,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[] = {
@@ -96,6 +103,9 @@ Authmethod authmethods[] = {
{"keyboard-interactive",
userauth_kbdint,
&options.kbd_interactive_authentication},
+ {"hostbased",
+ userauth_hostbased,
+ &options.hostbased_authentication},
{NULL, NULL, NULL}
};
@@ -201,7 +211,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;
}
@@ -461,6 +471,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*
@@ -638,3 +731,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/usr.bin/ssh/buffer.c b/usr.bin/ssh/buffer.c
index 377d0c09f40..044caafb5d7 100644
--- a/usr.bin/ssh/buffer.c
+++ b/usr.bin/ssh/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/usr.bin/ssh/canohost.c b/usr.bin/ssh/canohost.c
index 453c2c6a581..dceba268bd9 100644
--- a/usr.bin/ssh/canohost.c
+++ b/usr.bin/ssh/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"
@@ -180,30 +180,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/usr.bin/ssh/canohost.h b/usr.bin/ssh/canohost.h
index 89bd5c3b454..36fb345a122 100644
--- a/usr.bin/ssh/canohost.h
+++ b/usr.bin/ssh/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/usr.bin/ssh/compat.c b/usr.bin/ssh/compat.c
index 356a3f3e90d..f6b9a597646 100644
--- a/usr.bin/ssh/compat.c
+++ b/usr.bin/ssh/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 $");
#include <regex.h>
@@ -77,10 +77,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/usr.bin/ssh/compat.h b/usr.bin/ssh/compat.h
index 244cd1aa7f9..fc6f3344f5a 100644
--- a/usr.bin/ssh/compat.h
+++ b/usr.bin/ssh/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/usr.bin/ssh/hostfile.c b/usr.bin/ssh/hostfile.c
index 77aa8a899a0..d532bd6adbb 100644
--- a/usr.bin/ssh/hostfile.c
+++ b/usr.bin/ssh/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/usr.bin/ssh/pathnames.h b/usr.bin/ssh/pathnames.h
index 39edf315ca4..2f109b30ac4 100644
--- a/usr.bin/ssh/pathnames.h
+++ b/usr.bin/ssh/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>
@@ -26,10 +26,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"
#define _PATH_SSH_PROGRAM "/usr/bin/ssh"
diff --git a/usr.bin/ssh/readconf.c b/usr.bin/ssh/readconf.c
index f95940c1eb9..4cbcac68894 100644
--- a/usr.bin/ssh/readconf.c
+++ b/usr.bin/ssh/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 },
@@ -322,6 +323,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;
@@ -592,7 +597,7 @@ parse_int:
filename, linenum);
fwd_port = atoi(arg);
add_local_forward(options, fwd_port, "socks4", 0);
- break;
+ break;
case oHost:
*activep = 0;
@@ -710,6 +715,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;
@@ -787,6 +793,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/usr.bin/ssh/readconf.h b/usr.bin/ssh/readconf.h
index 55babe80ead..680068b0934 100644
--- a/usr.bin/ssh/readconf.h
+++ b/usr.bin/ssh/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/usr.bin/ssh/servconf.c b/usr.bin/ssh/servconf.c
index 4d5eb53ae85..8e876d1f12e 100644
--- a/usr.bin/ssh/servconf.c
+++ b/usr.bin/ssh/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/usr.bin/ssh/servconf.h b/usr.bin/ssh/servconf.h
index 57d4370f1c5..9b3a60f08f7 100644
--- a/usr.bin/ssh/servconf.h
+++ b/usr.bin/ssh/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/usr.bin/ssh/ssh.c b/usr.bin/ssh/ssh.c
index a2b67904829..2282eb5ae76 100644
--- a/usr.bin/ssh/ssh.c
+++ b/usr.bin/ssh/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>
@@ -122,8 +122,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;
@@ -625,9 +628,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
@@ -686,11 +698,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/usr.bin/ssh/sshconnect.c b/usr.bin/ssh/sshconnect.c
index d62b3aa90dc..31d06964bb0 100644
--- a/usr.bin/ssh/sshconnect.c
+++ b/usr.bin/ssh/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>
@@ -730,7 +730,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;
@@ -755,10 +755,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/usr.bin/ssh/sshconnect.h b/usr.bin/ssh/sshconnect.h
index 45caf739590..6610401858d 100644
--- a/usr.bin/ssh/sshconnect.h
+++ b/usr.bin/ssh/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/usr.bin/ssh/sshconnect1.c b/usr.bin/ssh/sshconnect1.c
index 3ec5ecc5140..865d04e8505 100644
--- a/usr.bin/ssh/sshconnect1.c
+++ b/usr.bin/ssh/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/usr.bin/ssh/sshconnect2.c b/usr.bin/ssh/sshconnect2.c
index da5b7147847..9a1d2576e1f 100644
--- a/usr.bin/ssh/sshconnect2.c
+++ b/usr.bin/ssh/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/usr.bin/ssh/sshd_config b/usr.bin/ssh/sshd_config
index 24e8f336ba5..f9a959edee7 100644
--- a/usr.bin/ssh/sshd_config
+++ b/usr.bin/ssh/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 is the sshd server system-wide configuration file. See sshd(8)
# for more information.
@@ -35,6 +35,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