summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/openssh/LICENCE2
-rw-r--r--crypto/openssh/Makefile4
-rw-r--r--crypto/openssh/README.smartcard66
-rw-r--r--crypto/openssh/auth-bsdauth.c21
-rw-r--r--crypto/openssh/auth-krb4.c7
-rw-r--r--crypto/openssh/auth-krb5.c27
-rw-r--r--crypto/openssh/auth-options.c42
-rw-r--r--crypto/openssh/auth-passwd.c23
-rw-r--r--crypto/openssh/auth-rh-rsa.c59
-rw-r--r--crypto/openssh/auth-rhosts.c68
-rw-r--r--crypto/openssh/auth-rsa.c209
-rw-r--r--crypto/openssh/auth-skey.c25
-rw-r--r--crypto/openssh/auth.c94
-rw-r--r--crypto/openssh/auth.h47
-rw-r--r--crypto/openssh/auth1.c43
-rw-r--r--crypto/openssh/auth2-chall.c23
-rw-r--r--crypto/openssh/auth2-hostbased.c182
-rw-r--r--crypto/openssh/auth2-kbdint.c61
-rw-r--r--crypto/openssh/auth2-none.c106
-rw-r--r--crypto/openssh/auth2-passwd.c62
-rw-r--r--crypto/openssh/auth2-pubkey.c279
-rw-r--r--crypto/openssh/auth2.c554
-rw-r--r--crypto/openssh/authfd.c56
-rw-r--r--crypto/openssh/authfd.h34
-rw-r--r--crypto/openssh/authfile.c4
-rw-r--r--crypto/openssh/authfile.h3
-rw-r--r--crypto/openssh/bufaux.c28
-rw-r--r--crypto/openssh/bufaux.h8
-rw-r--r--crypto/openssh/canohost.c7
-rw-r--r--crypto/openssh/channels.c134
-rw-r--r--crypto/openssh/channels.h17
-rw-r--r--crypto/openssh/cipher.c192
-rw-r--r--crypto/openssh/cipher.h9
-rw-r--r--crypto/openssh/clientloop.c74
-rw-r--r--crypto/openssh/clientloop.h3
-rw-r--r--crypto/openssh/compat.c30
-rw-r--r--crypto/openssh/compat.h4
-rw-r--r--crypto/openssh/compress.c14
-rw-r--r--crypto/openssh/kex.c36
-rw-r--r--crypto/openssh/kex.h5
-rw-r--r--crypto/openssh/kexdh.c5
-rw-r--r--crypto/openssh/kexgex.c11
-rw-r--r--crypto/openssh/key.c49
-rw-r--r--crypto/openssh/key.h3
-rw-r--r--crypto/openssh/lib/Makefile16
-rw-r--r--crypto/openssh/log.h6
-rw-r--r--crypto/openssh/mac.c4
-rw-r--r--crypto/openssh/misc.h8
-rw-r--r--crypto/openssh/monitor.c1498
-rw-r--r--crypto/openssh/monitor.h81
-rw-r--r--crypto/openssh/monitor_fdpass.c96
-rw-r--r--crypto/openssh/monitor_fdpass.h34
-rw-r--r--crypto/openssh/monitor_mm.c330
-rw-r--r--crypto/openssh/monitor_mm.h66
-rw-r--r--crypto/openssh/monitor_wrap.c920
-rw-r--r--crypto/openssh/monitor_wrap.h88
-rw-r--r--crypto/openssh/msg.c73
-rw-r--r--crypto/openssh/msg.h31
-rw-r--r--crypto/openssh/myproposal.h4
-rw-r--r--crypto/openssh/nchan.c60
-rw-r--r--crypto/openssh/packet.c145
-rw-r--r--crypto/openssh/packet.h13
-rw-r--r--crypto/openssh/pathnames.h8
-rw-r--r--crypto/openssh/radix.c245
-rw-r--r--crypto/openssh/readconf.c40
-rw-r--r--crypto/openssh/readconf.h4
-rw-r--r--crypto/openssh/readpass.c7
-rw-r--r--crypto/openssh/readpass.h3
-rw-r--r--crypto/openssh/scard.c305
-rw-r--r--crypto/openssh/scard.h10
-rw-r--r--crypto/openssh/scard/Ssh.bin.uu27
-rw-r--r--crypto/openssh/scard/Ssh.java59
-rw-r--r--crypto/openssh/scp.19
-rw-r--r--crypto/openssh/scp.c29
-rw-r--r--crypto/openssh/servconf.c31
-rw-r--r--crypto/openssh/servconf.h4
-rw-r--r--crypto/openssh/serverloop.c25
-rw-r--r--crypto/openssh/session.c276
-rw-r--r--crypto/openssh/session.h38
-rw-r--r--crypto/openssh/sftp-client.c64
-rw-r--r--crypto/openssh/sftp-glob.h4
-rw-r--r--crypto/openssh/sftp-int.c9
-rw-r--r--crypto/openssh/sftp-server.c20
-rw-r--r--crypto/openssh/sftp.117
-rw-r--r--crypto/openssh/sftp.c21
-rw-r--r--crypto/openssh/ssh-add.119
-rw-r--r--crypto/openssh/ssh-add.c83
-rw-r--r--crypto/openssh/ssh-agent.111
-rw-r--r--crypto/openssh/ssh-agent.c356
-rw-r--r--crypto/openssh/ssh-keygen.14
-rw-r--r--crypto/openssh/ssh-keygen.c149
-rw-r--r--crypto/openssh/ssh-keyscan.c8
-rw-r--r--crypto/openssh/ssh-keysign.867
-rw-r--r--crypto/openssh/ssh-keysign.c208
-rw-r--r--crypto/openssh/ssh-keysign/Makefile18
-rw-r--r--crypto/openssh/ssh-rsa.c34
-rw-r--r--crypto/openssh/ssh.1634
-rw-r--r--crypto/openssh/ssh.c216
-rw-r--r--crypto/openssh/ssh.h14
-rw-r--r--crypto/openssh/ssh/Makefile12
-rw-r--r--crypto/openssh/ssh_config16
-rw-r--r--crypto/openssh/ssh_config.5621
-rw-r--r--crypto/openssh/sshconnect.c75
-rw-r--r--crypto/openssh/sshconnect.h33
-rw-r--r--crypto/openssh/sshconnect1.c16
-rw-r--r--crypto/openssh/sshconnect2.c186
-rw-r--r--crypto/openssh/sshd.8671
-rw-r--r--crypto/openssh/sshd.c358
-rw-r--r--crypto/openssh/sshd/Makefile16
-rw-r--r--crypto/openssh/sshd_config14
-rw-r--r--crypto/openssh/sshd_config.5707
-rw-r--r--crypto/openssh/ttymodes.c20
-rw-r--r--crypto/openssh/uidswap.c21
-rw-r--r--crypto/openssh/version.h4
-rw-r--r--crypto/openssh/xmalloc.h4
115 files changed, 8750 insertions, 3303 deletions
diff --git a/crypto/openssh/LICENCE b/crypto/openssh/LICENCE
index 1c98a1d..19d4c74 100644
--- a/crypto/openssh/LICENCE
+++ b/crypto/openssh/LICENCE
@@ -190,6 +190,8 @@ OpenSSH contains no GPL code.
Aaron Campbell
Damien Miller
Kevin Steves
+ Daniel Kouril
+ Per Allansson
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/crypto/openssh/Makefile b/crypto/openssh/Makefile
index f1f871e..0b9c668 100644
--- a/crypto/openssh/Makefile
+++ b/crypto/openssh/Makefile
@@ -1,9 +1,9 @@
-# $OpenBSD: Makefile,v 1.10 2002/02/09 17:37:34 deraadt Exp $
+# $OpenBSD: Makefile,v 1.11 2002/05/23 19:24:30 markus Exp $
.include <bsd.own.mk>
SUBDIR= lib ssh sshd ssh-add ssh-keygen ssh-agent scp sftp-server \
- ssh-keyscan sftp scard
+ ssh-keysign ssh-keyscan sftp scard
distribution:
install -C -o root -g wheel -m 0644 ${.CURDIR}/ssh_config \
diff --git a/crypto/openssh/README.smartcard b/crypto/openssh/README.smartcard
index 499dc8e..4112e12 100644
--- a/crypto/openssh/README.smartcard
+++ b/crypto/openssh/README.smartcard
@@ -4,52 +4,33 @@ OpenSSH contains experimental support for authentication using
Cyberflex smartcards and TODOS card readers. To enable this you
need to:
-(1) install sectok
-
- $ cd /usr/src/lib/libsectok
- $ make obj depend all install includes
- $ cd /usr/src/usr.bin/sectok
- $ make obj depend all install
-
-(2) enable SMARTCARD support in OpenSSH:
+(1) enable SMARTCARD support in OpenSSH:
$ vi /usr/src/usr.bin/ssh/Makefile.inc
and uncomment
CFLAGS+= -DSMARTCARD
LDADD+= -lsectok
-(3) load the Java Cardlet to the Cyberflex card:
+(2) If you have used a previous version of ssh with your card, you
+ must remove the old applet and keys.
$ sectok
sectok> login -d
- sectok> jload /usr/libdata/ssh/Ssh.bin
+ sectok> junload Ssh.bin
+ sectok> delete 0012
+ sectok> delete sh
sectok> quit
-(4) load a RSA key to the card:
-
- please don't use your production RSA keys, since
- with the current version of sectok/ssh-keygen
- the private key file is still readable
-
- $ ssh-keygen -f /path/to/rsakey -U 1
- (where 1 is the reader number, you can also try 0)
-
- In spite of the name, this does not generate a key.
- It just loads an already existing key on to the card.
-
-(5) optional:
-
- Change the card password so that only you can
- read the private key:
+(3) load the Java Cardlet to the Cyberflex card and set card passphrase:
$ sectok
sectok> login -d
+ sectok> jload /usr/libdata/ssh/Ssh.bin
sectok> setpass
+ Enter new AUT0 passphrase:
+ Re-enter passphrase:
sectok> quit
- This prevents reading the key but not use of the
- key by the card applet.
-
Do not forget the passphrase. There is no way to
recover if you do.
@@ -57,13 +38,36 @@ need to:
wrong passphrase three times in a row, you will
destroy your card.
-(6) tell the ssh client to use the card reader:
+(4) load a RSA key to the card:
+
+ $ ssh-keygen -f /path/to/rsakey -U 1
+ (where 1 is the reader number, you can also try 0)
+
+ In spite of the name, this does not generate a key.
+ It just loads an already existing key on to the card.
+
+(5) tell the ssh client to use the card reader:
$ ssh -I 1 otherhost
-(7) or tell the agent (don't forget to restart) to use the smartcard:
+(6) or tell the agent (don't forget to restart) to use the smartcard:
$ ssh-add -s 1
+(7) Optional: If you don't want to use a card passphrase, change the
+ acl on the private key file:
+
+ $ sectok
+ sectok> login -d
+ sectok> acl 0012 world: w
+ world: w
+ AUT0: w inval
+ sectok> quit
+
+ If you do this, anyone who has access to your card
+ can assume your identity. This is not recommended.
+
-markus,
Tue Jul 17 23:54:51 CEST 2001
+
+$OpenBSD: README.smartcard,v 1.8 2002/03/26 18:56:23 rees Exp $
diff --git a/crypto/openssh/auth-bsdauth.c b/crypto/openssh/auth-bsdauth.c
index b70d48f..4f1b452 100644
--- a/crypto/openssh/auth-bsdauth.c
+++ b/crypto/openssh/auth-bsdauth.c
@@ -22,12 +22,13 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
-RCSID("$OpenBSD: auth-bsdauth.c,v 1.2 2001/12/19 07:18:56 deraadt Exp $");
+RCSID("$OpenBSD: auth-bsdauth.c,v 1.4 2002/06/19 00:27:55 deraadt Exp $");
#ifdef BSD_AUTH
#include "xmalloc.h"
#include "auth.h"
#include "log.h"
+#include "monitor_wrap.h"
static void *
bsdauth_init_ctx(Authctxt *authctxt)
@@ -35,7 +36,7 @@ bsdauth_init_ctx(Authctxt *authctxt)
return authctxt;
}
-static int
+int
bsdauth_query(void *ctx, char **name, char **infotxt,
u_int *numprompts, char ***prompts, u_int **echo_on)
{
@@ -56,7 +57,7 @@ bsdauth_query(void *ctx, char **name, char **infotxt,
debug3("bsdauth_query: style %s",
authctxt->style ? authctxt->style : "<default>");
authctxt->as = auth_userchallenge(authctxt->user,
- authctxt->style, "auth-ssh", &challenge);
+ authctxt->style, "auth-ssh", &challenge);
if (authctxt->as == NULL)
challenge = NULL;
debug2("bsdauth_query: <%s>", challenge ? challenge : "empty");
@@ -65,8 +66,8 @@ bsdauth_query(void *ctx, char **name, char **infotxt,
if (challenge == NULL)
return -1;
- *name = xstrdup("");
- *infotxt = xstrdup("");
+ *name = xstrdup("");
+ *infotxt = xstrdup("");
*numprompts = 1;
*prompts = xmalloc(*numprompts * sizeof(char*));
*echo_on = xmalloc(*numprompts * sizeof(u_int));
@@ -76,7 +77,7 @@ bsdauth_query(void *ctx, char **name, char **infotxt,
return 0;
}
-static int
+int
bsdauth_respond(void *ctx, u_int numresponses, char **responses)
{
Authctxt *authctxt = ctx;
@@ -113,4 +114,12 @@ KbdintDevice bsdauth_device = {
bsdauth_respond,
bsdauth_free_ctx
};
+
+KbdintDevice mm_bsdauth_device = {
+ "bsdauth",
+ bsdauth_init_ctx,
+ mm_bsdauth_query,
+ mm_bsdauth_respond,
+ bsdauth_free_ctx
+};
#endif
diff --git a/crypto/openssh/auth-krb4.c b/crypto/openssh/auth-krb4.c
index f7a144f..1cc528a 100644
--- a/crypto/openssh/auth-krb4.c
+++ b/crypto/openssh/auth-krb4.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth-krb4.c,v 1.25 2001/12/19 07:18:56 deraadt Exp $");
+RCSID("$OpenBSD: auth-krb4.c,v 1.27 2002/06/11 05:46:20 mpech Exp $");
#include "ssh.h"
#include "ssh1.h"
@@ -57,8 +57,8 @@ krb4_init(void *context)
if (lstat("/ticket", &st) != -1)
tkt_root = "/ticket/";
#endif /* AFS */
- snprintf(authctxt->krb4_ticket_file, MAXPATHLEN, "%s%u_%d",
- tkt_root, authctxt->pw->pw_uid, getpid());
+ snprintf(authctxt->krb4_ticket_file, MAXPATHLEN, "%s%u_%ld",
+ tkt_root, authctxt->pw->pw_uid, (long)getpid());
krb_set_tkt_string(authctxt->krb4_ticket_file);
}
/* Register ticket cleanup in case of fatal error. */
@@ -253,6 +253,7 @@ auth_krb4(Authctxt *authctxt, KTEXT auth, char **client)
log("Kerberos v4 .klogin authorization failed for %s to "
"account %s", *client, authctxt->user);
xfree(*client);
+ *client = NULL;
return (0);
}
/* Increment the checksum, and return it encrypted with the
diff --git a/crypto/openssh/auth-krb5.c b/crypto/openssh/auth-krb5.c
index 0f64567..6a61b1c 100644
--- a/crypto/openssh/auth-krb5.c
+++ b/crypto/openssh/auth-krb5.c
@@ -1,11 +1,34 @@
/*
* Kerberos v5 authentication and ticket-passing routines.
- *
+ *
* $FreeBSD$
*/
+/*
+ * Copyright (c) 2002 Daniel Kouril. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
#include "includes.h"
-RCSID("$OpenBSD: auth-krb5.c,v 1.6 2002/03/04 17:27:39 stevesk Exp $");
+RCSID("$OpenBSD: auth-krb5.c,v 1.8 2002/03/19 10:49:35 markus Exp $");
#include "ssh.h"
#include "ssh1.h"
diff --git a/crypto/openssh/auth-options.c b/crypto/openssh/auth-options.c
index 8df6a6d..2787d29 100644
--- a/crypto/openssh/auth-options.c
+++ b/crypto/openssh/auth-options.c
@@ -10,7 +10,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth-options.c,v 1.21 2002/01/29 14:32:03 markus Exp $");
+RCSID("$OpenBSD: auth-options.c,v 1.24 2002/05/13 20:44:58 markus Exp $");
#include "packet.h"
#include "xmalloc.h"
@@ -20,7 +20,10 @@ RCSID("$OpenBSD: auth-options.c,v 1.21 2002/01/29 14:32:03 markus Exp $");
#include "channels.h"
#include "auth-options.h"
#include "servconf.h"
+#include "bufaux.h"
#include "misc.h"
+#include "monitor_wrap.h"
+#include "auth.h"
/* Flags set authorized_keys flags */
int no_port_forwarding_flag = 0;
@@ -54,6 +57,7 @@ auth_clear_options(void)
forced_command = NULL;
}
channel_clear_permitted_opens();
+ auth_debug_reset();
}
/*
@@ -75,28 +79,28 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
while (*opts && *opts != ' ' && *opts != '\t') {
cp = "no-port-forwarding";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
- packet_send_debug("Port forwarding disabled.");
+ auth_debug_add("Port forwarding disabled.");
no_port_forwarding_flag = 1;
opts += strlen(cp);
goto next_option;
}
cp = "no-agent-forwarding";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
- packet_send_debug("Agent forwarding disabled.");
+ auth_debug_add("Agent forwarding disabled.");
no_agent_forwarding_flag = 1;
opts += strlen(cp);
goto next_option;
}
cp = "no-X11-forwarding";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
- packet_send_debug("X11 forwarding disabled.");
+ auth_debug_add("X11 forwarding disabled.");
no_x11_forwarding_flag = 1;
opts += strlen(cp);
goto next_option;
}
cp = "no-pty";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
- packet_send_debug("Pty allocation disabled.");
+ auth_debug_add("Pty allocation disabled.");
no_pty_flag = 1;
opts += strlen(cp);
goto next_option;
@@ -119,14 +123,14 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
- packet_send_debug("%.100s, line %lu: missing end quote",
+ auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
xfree(forced_command);
forced_command = NULL;
goto bad_option;
}
forced_command[i] = 0;
- packet_send_debug("Forced command: %.900s", forced_command);
+ auth_debug_add("Forced command: %.900s", forced_command);
opts++;
goto next_option;
}
@@ -151,13 +155,13 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
- packet_send_debug("%.100s, line %lu: missing end quote",
+ auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
xfree(s);
goto bad_option;
}
s[i] = 0;
- packet_send_debug("Adding to environment: %.900s", s);
+ auth_debug_add("Adding to environment: %.900s", s);
debug("Adding to environment: %.900s", s);
opts++;
new_envstring = xmalloc(sizeof(struct envstring));
@@ -188,7 +192,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
- packet_send_debug("%.100s, line %lu: missing end quote",
+ auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
xfree(patterns);
goto bad_option;
@@ -202,7 +206,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
"correct key but not from a permitted "
"host (host=%.200s, ip=%.200s).",
pw->pw_name, remote_host, remote_ip);
- packet_send_debug("Your host '%.200s' is not "
+ auth_debug_add("Your host '%.200s' is not "
"permitted to use this key for login.",
remote_host);
/* deny access */
@@ -233,7 +237,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
- packet_send_debug("%.100s, line %lu: missing end quote",
+ auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
xfree(patterns);
goto bad_option;
@@ -244,7 +248,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
sscanf(patterns, "%255[^/]/%5[0-9]", host, sport) != 2) {
debug("%.100s, line %lu: Bad permitopen specification "
"<%.100s>", file, linenum, patterns);
- packet_send_debug("%.100s, line %lu: "
+ auth_debug_add("%.100s, line %lu: "
"Bad permitopen specification", file, linenum);
xfree(patterns);
goto bad_option;
@@ -252,7 +256,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
if ((port = a2port(sport)) == 0) {
debug("%.100s, line %lu: Bad permitopen port <%.100s>",
file, linenum, sport);
- packet_send_debug("%.100s, line %lu: "
+ auth_debug_add("%.100s, line %lu: "
"Bad permitopen port", file, linenum);
xfree(patterns);
goto bad_option;
@@ -276,14 +280,22 @@ next_option:
opts++;
/* Process the next option. */
}
+
+ if (!use_privsep)
+ auth_debug_send();
+
/* grant access */
return 1;
bad_option:
log("Bad options in %.100s file, line %lu: %.50s",
file, linenum, opts);
- packet_send_debug("Bad options in %.100s file, line %lu: %.50s",
+ auth_debug_add("Bad options in %.100s file, line %lu: %.50s",
file, linenum, opts);
+
+ if (!use_privsep)
+ auth_debug_send();
+
/* deny access */
return 0;
}
diff --git a/crypto/openssh/auth-passwd.c b/crypto/openssh/auth-passwd.c
index 915991f..d0295fb 100644
--- a/crypto/openssh/auth-passwd.c
+++ b/crypto/openssh/auth-passwd.c
@@ -36,7 +36,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth-passwd.c,v 1.24 2002/03/04 12:43:06 markus Exp $");
+RCSID("$OpenBSD: auth-passwd.c,v 1.27 2002/05/24 16:45:16 stevesk Exp $");
#include "packet.h"
#include "log.h"
@@ -54,7 +54,6 @@ int
auth_password(Authctxt *authctxt, const char *password)
{
struct passwd * pw = authctxt->pw;
- char *encrypted_password;
/* deny if no user. */
if (pw == NULL)
@@ -85,14 +84,20 @@ auth_password(Authctxt *authctxt, const char *password)
return 0;
else
return 1;
-#endif
+#else
/* Check for users with no password. */
if (strcmp(password, "") == 0 && strcmp(pw->pw_passwd, "") == 0)
return 1;
- /* Encrypt the candidate password using the proper salt. */
- encrypted_password = crypt(password,
- (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, pw->pw_passwd) == 0);
+ else {
+ /* Encrypt the candidate password using the proper salt. */
+ char *encrypted_password = crypt(password,
+ (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, pw->pw_passwd) == 0);
+ }
+#endif
}
diff --git a/crypto/openssh/auth-rh-rsa.c b/crypto/openssh/auth-rh-rsa.c
index d1b7ae9..d7848d0 100644
--- a/crypto/openssh/auth-rh-rsa.c
+++ b/crypto/openssh/auth-rh-rsa.c
@@ -13,7 +13,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth-rh-rsa.c,v 1.29 2002/03/04 12:43:06 markus Exp $");
+RCSID("$OpenBSD: auth-rh-rsa.c,v 1.34 2002/03/25 09:25:06 markus Exp $");
#include "packet.h"
#include "uidswap.h"
@@ -25,37 +25,48 @@ RCSID("$OpenBSD: auth-rh-rsa.c,v 1.29 2002/03/04 12:43:06 markus Exp $");
#include "auth.h"
#include "canohost.h"
-/*
- * Tries to authenticate the user using the .rhosts file and the host using
- * its host key. Returns true if authentication succeeds.
- */
+#include "monitor_wrap.h"
+
+/* import */
+extern ServerOptions options;
int
-auth_rhosts_rsa(struct passwd *pw, const char *client_user, Key *client_host_key)
+auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
+ Key *client_host_key)
{
- extern ServerOptions options;
- const char *canonical_hostname;
HostStatus host_status;
- debug("Trying rhosts with RSA host authentication for client user %.100s", client_user);
-
- if (pw == NULL || client_host_key == NULL || client_host_key->rsa == NULL)
- return 0;
-
/* Check if we would accept it using rhosts authentication. */
- if (!auth_rhosts(pw, client_user))
+ if (!auth_rhosts(pw, cuser))
return 0;
- canonical_hostname = get_canonical_hostname(
- options.verify_reverse_mapping);
-
- debug("Rhosts RSA authentication: canonical host %.900s", canonical_hostname);
-
host_status = check_key_in_hostfiles(pw, client_host_key,
- canonical_hostname, _PATH_SSH_SYSTEM_HOSTFILE,
+ chost, _PATH_SSH_SYSTEM_HOSTFILE,
options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
- if (host_status != HOST_OK) {
+ return (host_status == HOST_OK);
+}
+
+/*
+ * Tries to authenticate the user using the .rhosts file and the host using
+ * its host key. Returns true if authentication succeeds.
+ */
+int
+auth_rhosts_rsa(struct passwd *pw, char *cuser, Key *client_host_key)
+{
+ char *chost;
+
+ debug("Trying rhosts with RSA host authentication for client user %.100s",
+ cuser);
+
+ if (pw == NULL || client_host_key == NULL ||
+ client_host_key->rsa == NULL)
+ return 0;
+
+ chost = (char *)get_canonical_hostname(options.verify_reverse_mapping);
+ debug("Rhosts RSA authentication: canonical host %.900s", chost);
+
+ if (!PRIVSEP(auth_rhosts_rsa_key_allowed(pw, cuser, chost, client_host_key))) {
debug("Rhosts with RSA host authentication denied: unknown or invalid host key");
packet_send_debug("Your host key cannot be verified: unknown or invalid host key.");
return 0;
@@ -63,9 +74,9 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, Key *client_host_key
/* A matching host key was found and is known. */
/* Perform the challenge-response dialog with the client for the host key. */
- if (!auth_rsa_challenge_dialog(client_host_key->rsa)) {
+ if (!auth_rsa_challenge_dialog(client_host_key)) {
log("Client on %.800s failed to respond correctly to host authentication.",
- canonical_hostname);
+ chost);
return 0;
}
/*
@@ -74,7 +85,7 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, Key *client_host_key
*/
verbose("Rhosts with RSA host authentication accepted for %.100s, %.100s on %.700s.",
- pw->pw_name, client_user, canonical_hostname);
+ pw->pw_name, cuser, chost);
packet_send_debug("Rhosts with RSA host authentication accepted.");
return 1;
}
diff --git a/crypto/openssh/auth-rhosts.c b/crypto/openssh/auth-rhosts.c
index bd15261..afca1f7 100644
--- a/crypto/openssh/auth-rhosts.c
+++ b/crypto/openssh/auth-rhosts.c
@@ -14,7 +14,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth-rhosts.c,v 1.27 2002/03/04 12:43:06 markus Exp $");
+RCSID("$OpenBSD: auth-rhosts.c,v 1.28 2002/05/13 21:26:49 markus Exp $");
#include "packet.h"
#include "uidswap.h"
@@ -26,6 +26,7 @@ RCSID("$OpenBSD: auth-rhosts.c,v 1.27 2002/03/04 12:43:06 markus Exp $");
/* import */
extern ServerOptions options;
+extern int use_privsep;
/*
* This function processes an rhosts-style file (.rhosts, .shosts, or
@@ -69,7 +70,7 @@ check_rhosts_file(const char *filename, const char *hostname,
*/
switch (sscanf(buf, "%s %s %s", hostbuf, userbuf, dummy)) {
case 0:
- packet_send_debug("Found empty line in %.100s.", filename);
+ auth_debug_add("Found empty line in %.100s.", filename);
continue;
case 1:
/* Host name only. */
@@ -79,7 +80,7 @@ check_rhosts_file(const char *filename, const char *hostname,
/* Got both host and user name. */
break;
case 3:
- packet_send_debug("Found garbage in %.100s.", filename);
+ auth_debug_add("Found garbage in %.100s.", filename);
continue;
default:
/* Weird... */
@@ -106,8 +107,8 @@ check_rhosts_file(const char *filename, const char *hostname,
/* Check for empty host/user names (particularly '+'). */
if (!host[0] || !user[0]) {
/* We come here if either was '+' or '-'. */
- packet_send_debug("Ignoring wild host/user names in %.100s.",
- filename);
+ auth_debug_add("Ignoring wild host/user names in %.100s.",
+ filename);
continue;
}
/* Verify that host name matches. */
@@ -130,8 +131,8 @@ check_rhosts_file(const char *filename, const char *hostname,
/* If the entry was negated, deny access. */
if (negated) {
- packet_send_debug("Matched negative entry in %.100s.",
- filename);
+ auth_debug_add("Matched negative entry in %.100s.",
+ filename);
return 0;
}
/* Accept authentication. */
@@ -153,16 +154,14 @@ int
auth_rhosts(struct passwd *pw, const char *client_user)
{
const char *hostname, *ipaddr;
- int ret;
hostname = get_canonical_hostname(options.verify_reverse_mapping);
ipaddr = get_remote_ipaddr();
- ret = auth_rhosts2(pw, client_user, hostname, ipaddr);
- return ret;
+ return auth_rhosts2(pw, client_user, hostname, ipaddr);
}
-int
-auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
+static int
+auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostname,
const char *ipaddr)
{
char buf[1024];
@@ -205,13 +204,13 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
if (pw->pw_uid != 0) {
if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr,
client_user, pw->pw_name)) {
- packet_send_debug("Accepted for %.100s [%.100s] by /etc/hosts.equiv.",
+ auth_debug_add("Accepted for %.100s [%.100s] by /etc/hosts.equiv.",
hostname, ipaddr);
return 1;
}
if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr,
client_user, pw->pw_name)) {
- packet_send_debug("Accepted for %.100s [%.100s] by %.100s.",
+ auth_debug_add("Accepted for %.100s [%.100s] by %.100s.",
hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV);
return 1;
}
@@ -221,19 +220,19 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
* not group or world writable.
*/
if (stat(pw->pw_dir, &st) < 0) {
- log("Rhosts authentication refused for %.100s: no home directory %.200s",
- pw->pw_name, pw->pw_dir);
- packet_send_debug("Rhosts authentication refused for %.100s: no home directory %.200s",
- pw->pw_name, pw->pw_dir);
+ log("Rhosts authentication refused for %.100s: "
+ "no home directory %.200s", pw->pw_name, pw->pw_dir);
+ auth_debug_add("Rhosts authentication refused for %.100s: "
+ "no home directory %.200s", pw->pw_name, pw->pw_dir);
return 0;
}
if (options.strict_modes &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0)) {
- log("Rhosts authentication refused for %.100s: bad ownership or modes for home directory.",
- pw->pw_name);
- packet_send_debug("Rhosts authentication refused for %.100s: bad ownership or modes for home directory.",
- pw->pw_name);
+ log("Rhosts authentication refused for %.100s: "
+ "bad ownership or modes for home directory.", pw->pw_name);
+ auth_debug_add("Rhosts authentication refused for %.100s: "
+ "bad ownership or modes for home directory.", pw->pw_name);
return 0;
}
/* Temporarily use the user's uid. */
@@ -259,21 +258,23 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
(st.st_mode & 022) != 0)) {
log("Rhosts authentication refused for %.100s: bad modes for %.200s",
pw->pw_name, buf);
- packet_send_debug("Bad file modes for %.200s", buf);
+ auth_debug_add("Bad file modes for %.200s", buf);
continue;
}
/* Check if we have been configured to ignore .rhosts and .shosts files. */
if (options.ignore_rhosts) {
- packet_send_debug("Server has been configured to ignore %.100s.",
- rhosts_files[rhosts_file_index]);
+ auth_debug_add("Server has been configured to ignore %.100s.",
+ rhosts_files[rhosts_file_index]);
continue;
}
/* Check if authentication is permitted by the file. */
if (check_rhosts_file(buf, hostname, ipaddr, client_user, pw->pw_name)) {
- packet_send_debug("Accepted by %.100s.",
- rhosts_files[rhosts_file_index]);
+ auth_debug_add("Accepted by %.100s.",
+ rhosts_files[rhosts_file_index]);
/* Restore the privileged uid. */
restore_uid();
+ auth_debug_add("Accepted host %s ip %s client_user %s server_user %s",
+ hostname, ipaddr, client_user, pw->pw_name);
return 1;
}
}
@@ -282,3 +283,16 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
restore_uid();
return 0;
}
+
+int
+auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
+ const char *ipaddr)
+{
+ int ret;
+
+ auth_debug_reset();
+ ret = auth_rhosts2_raw(pw, client_user, hostname, ipaddr);
+ if (!use_privsep)
+ auth_debug_send();
+ return ret;
+}
diff --git a/crypto/openssh/auth-rsa.c b/crypto/openssh/auth-rsa.c
index f7ae03c..92f6277 100644
--- a/crypto/openssh/auth-rsa.c
+++ b/crypto/openssh/auth-rsa.c
@@ -14,7 +14,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth-rsa.c,v 1.50 2001/12/28 14:50:54 markus Exp $");
+RCSID("$OpenBSD: auth-rsa.c,v 1.56 2002/06/10 16:53:06 stevesk Exp $");
#include <openssl/rsa.h>
#include <openssl/md5.h>
@@ -32,6 +32,8 @@ RCSID("$OpenBSD: auth-rsa.c,v 1.50 2001/12/28 14:50:54 markus Exp $");
#include "servconf.h"
#include "auth.h"
#include "hostfile.h"
+#include "monitor_wrap.h"
+#include "ssh.h"
/* import */
extern ServerOptions options;
@@ -52,6 +54,58 @@ extern u_char session_id[16];
* description of the options.
*/
+BIGNUM *
+auth_rsa_generate_challenge(Key *key)
+{
+ BIGNUM *challenge;
+ BN_CTX *ctx;
+
+ if ((challenge = BN_new()) == NULL)
+ fatal("auth_rsa_generate_challenge: BN_new() failed");
+ /* Generate a random challenge. */
+ BN_rand(challenge, 256, 0, 0);
+ if ((ctx = BN_CTX_new()) == NULL)
+ fatal("auth_rsa_generate_challenge: BN_CTX_new() failed");
+ BN_mod(challenge, challenge, key->rsa->n, ctx);
+ BN_CTX_free(ctx);
+
+ return challenge;
+}
+
+int
+auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
+{
+ u_char buf[32], mdbuf[16];
+ MD5_CTX md;
+ int len;
+
+ /* don't allow short keys */
+ if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
+ error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits",
+ BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
+ return (0);
+ }
+
+ /* The response is MD5 of decrypted challenge plus session id. */
+ len = BN_num_bytes(challenge);
+ if (len <= 0 || len > 32)
+ fatal("auth_rsa_verify_response: bad challenge length %d", len);
+ memset(buf, 0, 32);
+ BN_bn2bin(challenge, buf + 32 - len);
+ MD5_Init(&md);
+ MD5_Update(&md, buf, 32);
+ MD5_Update(&md, session_id, 16);
+ MD5_Final(mdbuf, &md);
+
+ /* Verify that the response is the original challenge. */
+ if (memcmp(response, mdbuf, 16) != 0) {
+ /* Wrong answer. */
+ return (0);
+ }
+ /* Correct answer. */
+ return (1);
+}
+
/*
* Performs the RSA authentication challenge-response dialog with the client,
* and returns true (non-zero) if the client gave the correct answer to
@@ -59,29 +113,19 @@ extern u_char session_id[16];
*/
int
-auth_rsa_challenge_dialog(RSA *pk)
+auth_rsa_challenge_dialog(Key *key)
{
BIGNUM *challenge, *encrypted_challenge;
- BN_CTX *ctx;
- u_char buf[32], mdbuf[16], response[16];
- MD5_CTX md;
- u_int i;
- int len;
+ u_char response[16];
+ int i, success;
if ((encrypted_challenge = BN_new()) == NULL)
fatal("auth_rsa_challenge_dialog: BN_new() failed");
- if ((challenge = BN_new()) == NULL)
- fatal("auth_rsa_challenge_dialog: BN_new() failed");
- /* Generate a random challenge. */
- BN_rand(challenge, 256, 0, 0);
- if ((ctx = BN_CTX_new()) == NULL)
- fatal("auth_rsa_challenge_dialog: BN_CTX_new() failed");
- BN_mod(challenge, challenge, pk->n, ctx);
- BN_CTX_free(ctx);
+ challenge = PRIVSEP(auth_rsa_generate_challenge(key));
/* Encrypt the challenge with the public key. */
- rsa_public_encrypt(encrypted_challenge, challenge, pk);
+ rsa_public_encrypt(encrypted_challenge, challenge, key->rsa);
/* Send the encrypted challenge to the client. */
packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
@@ -96,48 +140,26 @@ auth_rsa_challenge_dialog(RSA *pk)
response[i] = packet_get_char();
packet_check_eom();
- /* The response is MD5 of decrypted challenge plus session id. */
- len = BN_num_bytes(challenge);
- if (len <= 0 || len > 32)
- fatal("auth_rsa_challenge_dialog: bad challenge length %d", len);
- memset(buf, 0, 32);
- BN_bn2bin(challenge, buf + 32 - len);
- MD5_Init(&md);
- MD5_Update(&md, buf, 32);
- MD5_Update(&md, session_id, 16);
- MD5_Final(mdbuf, &md);
+ success = PRIVSEP(auth_rsa_verify_response(key, challenge, response));
BN_clear_free(challenge);
-
- /* Verify that the response is the original challenge. */
- if (memcmp(response, mdbuf, 16) != 0) {
- /* Wrong answer. */
- return 0;
- }
- /* Correct answer. */
- return 1;
+ return (success);
}
/*
- * Performs the RSA authentication dialog with the client. This returns
- * 0 if the client could not be authenticated, and 1 if authentication was
- * successful. This may exit if there is a serious protocol violation.
+ * check if there's user key matching client_n,
+ * return key if login is allowed, NULL otherwise
*/
int
-auth_rsa(struct passwd *pw, BIGNUM *client_n)
+auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
{
char line[8192], *file;
- int authenticated;
+ int allowed = 0;
u_int bits;
FILE *f;
u_long linenum = 0;
struct stat st;
Key *key;
- char *fp;
-
- /* no user given */
- if (pw == NULL)
- return 0;
/* Temporarily use the user's uid. */
temporarily_use_uid(pw);
@@ -151,29 +173,27 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
/* Restore the privileged uid. */
restore_uid();
xfree(file);
- return 0;
+ return (0);
}
/* Open the file containing the authorized keys. */
f = fopen(file, "r");
if (!f) {
/* Restore the privileged uid. */
restore_uid();
- packet_send_debug("Could not open %.900s for reading.", file);
- packet_send_debug("If your home is on an NFS volume, it may need to be world-readable.");
xfree(file);
- return 0;
+ return (0);
}
if (options.strict_modes &&
secure_filename(f, file, pw, line, sizeof(line)) != 0) {
xfree(file);
fclose(f);
log("Authentication refused: %s", line);
- packet_send_debug("Authentication refused: %s", line);
restore_uid();
- return 0;
+ return (0);
}
- /* Flag indicating whether authentication has succeeded. */
- authenticated = 0;
+
+ /* Flag indicating whether the key is allowed. */
+ allowed = 0;
key = key_new(KEY_RSA1);
@@ -238,32 +258,8 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
if (!auth_parse_options(pw, options, file, linenum))
continue;
- /* Perform the challenge-response dialog for this key. */
- if (!auth_rsa_challenge_dialog(key->rsa)) {
- /* Wrong response. */
- verbose("Wrong response to RSA authentication challenge.");
- packet_send_debug("Wrong response to RSA authentication challenge.");
- /*
- * Break out of the loop. Otherwise we might send
- * another challenge and break the protocol.
- */
- break;
- }
- /*
- * Correct response. The client has been successfully
- * authenticated. Note that we have not yet processed the
- * options; this will be reset if the options cause the
- * authentication to be rejected.
- * Break out of the loop if authentication was successful;
- * otherwise continue searching.
- */
- authenticated = 1;
-
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
- verbose("Found matching %s key: %s",
- key_type(key), fp);
- xfree(fp);
-
+ /* break out, this key is allowed */
+ allowed = 1;
break;
}
@@ -274,13 +270,58 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
xfree(file);
fclose(f);
- key_free(key);
-
- if (authenticated)
- packet_send_debug("RSA authentication accepted.");
+ /* return key if allowed */
+ if (allowed && rkey != NULL)
+ *rkey = key;
else
+ key_free(key);
+ return (allowed);
+}
+
+/*
+ * Performs the RSA authentication dialog with the client. This returns
+ * 0 if the client could not be authenticated, and 1 if authentication was
+ * successful. This may exit if there is a serious protocol violation.
+ */
+int
+auth_rsa(struct passwd *pw, BIGNUM *client_n)
+{
+ Key *key;
+ char *fp;
+
+ /* no user given */
+ if (pw == NULL)
+ return 0;
+
+ if (!PRIVSEP(auth_rsa_key_allowed(pw, client_n, &key))) {
auth_clear_options();
+ return (0);
+ }
+
+ /* Perform the challenge-response dialog for this key. */
+ if (!auth_rsa_challenge_dialog(key)) {
+ /* Wrong response. */
+ verbose("Wrong response to RSA authentication challenge.");
+ packet_send_debug("Wrong response to RSA authentication challenge.");
+ /*
+ * Break out of the loop. Otherwise we might send
+ * another challenge and break the protocol.
+ */
+ key_free(key);
+ return (0);
+ }
+ /*
+ * Correct response. The client has been successfully
+ * authenticated. Note that we have not yet processed the
+ * options; this will be reset if the options cause the
+ * authentication to be rejected.
+ */
+ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ verbose("Found matching %s key: %s",
+ key_type(key), fp);
+ xfree(fp);
+ key_free(key);
- /* Return authentication result. */
- return authenticated;
+ packet_send_debug("RSA authentication accepted.");
+ return (1);
}
diff --git a/crypto/openssh/auth-skey.c b/crypto/openssh/auth-skey.c
index df19f75..eb13c5c 100644
--- a/crypto/openssh/auth-skey.c
+++ b/crypto/openssh/auth-skey.c
@@ -22,7 +22,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
-RCSID("$OpenBSD: auth-skey.c,v 1.16 2002/01/12 13:10:29 markus Exp $");
+RCSID("$OpenBSD: auth-skey.c,v 1.19 2002/06/19 00:27:55 deraadt Exp $");
#ifdef SKEY
@@ -30,6 +30,7 @@ RCSID("$OpenBSD: auth-skey.c,v 1.16 2002/01/12 13:10:29 markus Exp $");
#include "xmalloc.h"
#include "auth.h"
+#include "monitor_wrap.h"
static void *
skey_init_ctx(Authctxt *authctxt)
@@ -37,9 +38,7 @@ skey_init_ctx(Authctxt *authctxt)
return authctxt;
}
-#define PROMPT "\nS/Key Password: "
-
-static int
+int
skey_query(void *ctx, char **name, char **infotxt,
u_int* numprompts, char ***prompts, u_int **echo_on)
{
@@ -51,23 +50,23 @@ skey_query(void *ctx, char **name, char **infotxt,
if (skeychallenge(&skey, authctxt->user, challenge) == -1)
return -1;
- *name = xstrdup("");
- *infotxt = xstrdup("");
+ *name = xstrdup("");
+ *infotxt = xstrdup("");
*numprompts = 1;
*prompts = xmalloc(*numprompts * sizeof(char*));
*echo_on = xmalloc(*numprompts * sizeof(u_int));
(*echo_on)[0] = 0;
- len = strlen(challenge) + strlen(PROMPT) + 1;
+ len = strlen(challenge) + strlen(SKEY_PROMPT) + 1;
p = xmalloc(len);
strlcpy(p, challenge, len);
- strlcat(p, PROMPT, len);
+ strlcat(p, SKEY_PROMPT, len);
(*prompts)[0] = p;
return 0;
}
-static int
+int
skey_respond(void *ctx, u_int numresponses, char **responses)
{
Authctxt *authctxt = ctx;
@@ -93,4 +92,12 @@ KbdintDevice skey_device = {
skey_respond,
skey_free_ctx
};
+
+KbdintDevice mm_skey_device = {
+ "skey",
+ skey_init_ctx,
+ mm_skey_query,
+ mm_skey_respond,
+ skey_free_ctx
+};
#endif /* SKEY */
diff --git a/crypto/openssh/auth.c b/crypto/openssh/auth.c
index 6e29d66..59e76bc 100644
--- a/crypto/openssh/auth.c
+++ b/crypto/openssh/auth.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth.c,v 1.35 2002/03/01 13:12:10 markus Exp $");
+RCSID("$OpenBSD: auth.c,v 1.43 2002/05/17 14:27:55 millert Exp $");
#include <libgen.h>
@@ -39,10 +39,17 @@ RCSID("$OpenBSD: auth.c,v 1.35 2002/03/01 13:12:10 markus Exp $");
#include "bufaux.h"
#include "uidswap.h"
#include "tildexpand.h"
+#include "misc.h"
+#include "bufaux.h"
+#include "packet.h"
/* import */
extern ServerOptions options;
+/* Debugging messages */
+Buffer auth_debug;
+int auth_debug_init;
+
/*
* Check if the user is allowed to log in via ssh. If user is listed
* in DenyUsers or one of user's groups is listed in DenyGroups, false
@@ -76,7 +83,8 @@ allowed_user(struct passwd * pw)
pw->pw_name, shell);
return 0;
}
- if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)))) {
+ if (S_ISREG(st.st_mode) == 0 ||
+ (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
log("User %.100s not allowed because shell %.100s is not executable",
pw->pw_name, shell);
return 0;
@@ -90,17 +98,17 @@ allowed_user(struct passwd * pw)
/* Return false if user is listed in DenyUsers */
if (options.num_deny_users > 0) {
for (i = 0; i < options.num_deny_users; i++)
- if (match_user(pw->pw_name, hostname, ipaddr,
+ if (match_user(pw->pw_name, hostname, ipaddr,
options.deny_users[i])) {
- log("User %.100s not allowed because listed in DenyUsers",
- pw->pw_name);
+ log("User %.100s not allowed because listed in DenyUsers",
+ pw->pw_name);
return 0;
}
}
/* Return false if AllowUsers isn't empty and user isn't listed there */
if (options.num_allow_users > 0) {
for (i = 0; i < options.num_allow_users; i++)
- if (match_user(pw->pw_name, hostname, ipaddr,
+ if (match_user(pw->pw_name, hostname, ipaddr,
options.allow_users[i]))
break;
/* i < options.num_allow_users iff we break for loop */
@@ -386,3 +394,77 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
}
return 0;
}
+
+struct passwd *
+getpwnamallow(const char *user)
+{
+#ifdef HAVE_LOGIN_CAP
+ extern login_cap_t *lc;
+#ifdef BSD_AUTH
+ auth_session_t *as;
+#endif
+#endif
+ struct passwd *pw;
+
+ pw = getpwnam(user);
+ if (pw == NULL || !allowed_user(pw))
+ return (NULL);
+#ifdef HAVE_LOGIN_CAP
+ if ((lc = login_getclass(pw->pw_class)) == NULL) {
+ debug("unable to get login class: %s", user);
+ return (NULL);
+ }
+#ifdef BSD_AUTH
+ if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 ||
+ auth_approval(as, lc, pw->pw_name, "ssh") <= 0) {
+ debug("Approval failure for %s", user);
+ pw = NULL;
+ }
+ if (as != NULL)
+ auth_close(as);
+#endif
+#endif
+ if (pw != NULL)
+ return (pwcopy(pw));
+ return (NULL);
+}
+
+void
+auth_debug_add(const char *fmt,...)
+{
+ char buf[1024];
+ va_list args;
+
+ if (!auth_debug_init)
+ return;
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ buffer_put_cstring(&auth_debug, buf);
+}
+
+void
+auth_debug_send(void)
+{
+ char *msg;
+
+ if (!auth_debug_init)
+ return;
+ while (buffer_len(&auth_debug)) {
+ msg = buffer_get_string(&auth_debug, NULL);
+ packet_send_debug("%s", msg);
+ xfree(msg);
+ }
+}
+
+void
+auth_debug_reset(void)
+{
+ if (auth_debug_init)
+ buffer_clear(&auth_debug);
+ else {
+ buffer_init(&auth_debug);
+ auth_debug_init = 1;
+ }
+}
diff --git a/crypto/openssh/auth.h b/crypto/openssh/auth.h
index 56ef2de..ea5354c 100644
--- a/crypto/openssh/auth.h
+++ b/crypto/openssh/auth.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.h,v 1.29 2002/03/04 17:27:39 stevesk Exp $ */
+/* $OpenBSD: auth.h,v 1.39 2002/05/31 11:35:15 markus Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -43,6 +43,7 @@
#endif
typedef struct Authctxt Authctxt;
+typedef struct Authmethod Authmethod;
typedef struct KbdintDevice KbdintDevice;
struct Authctxt {
@@ -71,6 +72,12 @@ struct Authctxt {
#endif
};
+struct Authmethod {
+ char *name;
+ int (*userauth)(Authctxt *authctxt);
+ int *enabled;
+};
+
/*
* Keyboard interactive device:
* init_ctx returns: non NULL upon success
@@ -88,14 +95,21 @@ struct KbdintDevice
void (*free_ctx)(void *ctx);
};
-int auth_rhosts(struct passwd *, const char *);
+int auth_rhosts(struct passwd *, const char *);
int
auth_rhosts2(struct passwd *, const char *, const char *, const char *);
-int auth_rhosts_rsa(struct passwd *, const char *, Key *);
+int auth_rhosts_rsa(struct passwd *, char *, Key *);
int auth_password(Authctxt *, const char *);
int auth_rsa(struct passwd *, BIGNUM *);
-int auth_rsa_challenge_dialog(RSA *);
+int auth_rsa_challenge_dialog(Key *);
+BIGNUM *auth_rsa_generate_challenge(Key *);
+int auth_rsa_verify_response(Key *, BIGNUM *, u_char[]);
+int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
+
+int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
+int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
+int user_key_allowed(struct passwd *, Key *);
#ifdef KRB4
#include <krb.h>
@@ -118,18 +132,27 @@ int auth_krb5_password(Authctxt *authctxt, const char *password);
void krb5_cleanup_proc(void *authctxt);
#endif /* KRB5 */
-void do_authentication(void);
-void do_authentication2(void);
+Authctxt *do_authentication(void);
+Authctxt *do_authentication2(void);
Authctxt *authctxt_new(void);
void auth_log(Authctxt *, int, char *, char *);
void userauth_finish(Authctxt *, int, char *);
int auth_root_allowed(char *);
+char *auth2_read_banner(void);
+
+void privsep_challenge_enable(void);
+
int auth2_challenge(Authctxt *, char *);
void auth2_challenge_stop(Authctxt *);
+int bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
+int bsdauth_respond(void *, u_int, char **);
+int skey_query(void *, char **, char **, u_int *, char ***, u_int **);
+int skey_respond(void *, u_int, char **);
int allowed_user(struct passwd *);
+struct passwd * getpwnamallow(const char *user);
char *get_challenge(Authctxt *);
int verify_response(Authctxt *, const char *);
@@ -147,8 +170,20 @@ HostStatus
check_key_in_hostfiles(struct passwd *, Key *, const char *,
const char *, const char *);
+/* hostkey handling */
+Key *get_hostkey_by_index(int);
+Key *get_hostkey_by_type(int);
+int get_hostkey_index(Key *);
+int ssh1_session_key(BIGNUM *);
+
+/* debug messages during authentication */
+void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
+void auth_debug_send(void);
+void auth_debug_reset(void);
+
#define AUTH_FAIL_MAX 6
#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
+#define SKEY_PROMPT "\nS/Key Password: "
#endif
diff --git a/crypto/openssh/auth1.c b/crypto/openssh/auth1.c
index 7460b6f..4858aae 100644
--- a/crypto/openssh/auth1.c
+++ b/crypto/openssh/auth1.c
@@ -10,7 +10,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth1.c,v 1.35 2002/02/03 17:53:25 markus Exp $");
+RCSID("$OpenBSD: auth1.c,v 1.41 2002/06/19 00:27:55 deraadt Exp $");
#include "xmalloc.h"
#include "rsa.h"
@@ -24,8 +24,8 @@ RCSID("$OpenBSD: auth1.c,v 1.35 2002/02/03 17:53:25 markus Exp $");
#include "auth.h"
#include "channels.h"
#include "session.h"
-#include "misc.h"
#include "uidswap.h"
+#include "monitor_wrap.h"
/* import */
extern ServerOptions options;
@@ -84,7 +84,7 @@ do_authloop(Authctxt *authctxt)
#if defined(KRB4) || defined(KRB5)
(!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif
- auth_password(authctxt, "")) {
+ PRIVSEP(auth_password(authctxt, ""))) {
auth_log(authctxt, 1, "without authentication", "");
return;
}
@@ -204,7 +204,7 @@ do_authloop(Authctxt *authctxt)
if (bits != BN_num_bits(client_host_key->rsa->n))
verbose("Warning: keysize mismatch for client_host_key: "
"actual %d, announced %d",
- BN_num_bits(client_host_key->rsa->n), bits);
+ BN_num_bits(client_host_key->rsa->n), bits);
packet_check_eom();
authenticated = auth_rhosts_rsa(pw, client_user,
@@ -243,7 +243,7 @@ do_authloop(Authctxt *authctxt)
packet_check_eom();
/* Try authentication with the password. */
- authenticated = auth_password(authctxt, password);
+ authenticated = PRIVSEP(auth_password(authctxt, password));
memset(password, 0, strlen(password));
xfree(password);
@@ -318,13 +318,12 @@ do_authloop(Authctxt *authctxt)
* Performs authentication of an incoming connection. Session key has already
* been exchanged and encryption is enabled.
*/
-void
+Authctxt *
do_authentication(void)
{
Authctxt *authctxt;
- struct passwd *pw;
u_int ulen;
- char *p, *user, *style = NULL;
+ char *user, *style = NULL;
/* Get the name of the user that we wish to log in as. */
packet_read_expect(SSH_CMSG_USER);
@@ -336,32 +335,35 @@ do_authentication(void)
if ((style = strchr(user, ':')) != NULL)
*style++ = '\0';
+#ifdef KRB5
/* XXX - SSH.com Kerberos v5 braindeath. */
- if ((p = strchr(user, '@')) != NULL)
- *p = '\0';
+ if ((datafellows & SSH_BUG_K5USER) &&
+ options.kerberos_authentication) {
+ char *p;
+ if ((p = strchr(user, '@')) != NULL)
+ *p = '\0';
+ }
+#endif
authctxt = authctxt_new();
authctxt->user = user;
authctxt->style = style;
/* Verify that the user is a valid user. */
- pw = getpwnam(user);
- if (pw && allowed_user(pw)) {
+ if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
authctxt->valid = 1;
- pw = pwcopy(pw);
- } else {
+ else
debug("do_authentication: illegal user %s", user);
- pw = NULL;
- }
- authctxt->pw = pw;
- setproctitle("%s", pw ? user : "unknown");
+ setproctitle("%s%s", authctxt->pw ? user : "unknown",
+ use_privsep ? " [net]" : "");
/*
* If we are not running as root, the user must have the same uid as
* the server.
*/
- if (getuid() != 0 && pw && pw->pw_uid != getuid())
+ if (!use_privsep && getuid() != 0 && authctxt->pw &&
+ authctxt->pw->pw_uid != getuid())
packet_disconnect("Cannot change user when server not running as root.");
/*
@@ -375,6 +377,5 @@ do_authentication(void)
packet_send();
packet_write_wait();
- /* Perform session preparation. */
- do_authenticated(authctxt);
+ return (authctxt);
}
diff --git a/crypto/openssh/auth2-chall.c b/crypto/openssh/auth2-chall.c
index 9f1d932..f35bfb2 100644
--- a/crypto/openssh/auth2-chall.c
+++ b/crypto/openssh/auth2-chall.c
@@ -23,7 +23,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
-RCSID("$OpenBSD: auth2-chall.c,v 1.16 2002/01/13 17:57:37 markus Exp $");
+RCSID("$OpenBSD: auth2-chall.c,v 1.18 2002/06/19 00:27:55 deraadt Exp $");
#include "ssh2.h"
#include "auth.h"
@@ -219,7 +219,7 @@ send_userauth_info_request(Authctxt *authctxt)
packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST);
packet_put_cstring(name);
packet_put_cstring(instr);
- packet_put_cstring(""); /* language not used */
+ packet_put_cstring(""); /* language not used */
packet_put_int(numprompts);
for (i = 0; i < numprompts; i++) {
packet_put_cstring(prompts[i]);
@@ -310,3 +310,22 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
userauth_finish(authctxt, authenticated, method);
xfree(method);
}
+
+void
+privsep_challenge_enable(void)
+{
+#ifdef BSD_AUTH
+ extern KbdintDevice mm_bsdauth_device;
+#endif
+#ifdef SKEY
+ extern KbdintDevice mm_skey_device;
+#endif
+ /* As long as SSHv1 has devices[0] hard coded this is fine */
+#ifdef BSD_AUTH
+ devices[0] = &mm_bsdauth_device;
+#else
+#ifdef SKEY
+ devices[0] = &mm_skey_device;
+#endif
+#endif
+}
diff --git a/crypto/openssh/auth2-hostbased.c b/crypto/openssh/auth2-hostbased.c
new file mode 100644
index 0000000..2bde7bb
--- /dev/null
+++ b/crypto/openssh/auth2-hostbased.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: auth2-hostbased.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
+
+#include "ssh2.h"
+#include "xmalloc.h"
+#include "packet.h"
+#include "buffer.h"
+#include "log.h"
+#include "servconf.h"
+#include "compat.h"
+#include "bufaux.h"
+#include "auth.h"
+#include "key.h"
+#include "canohost.h"
+#include "monitor_wrap.h"
+#include "pathnames.h"
+
+/* import */
+extern ServerOptions options;
+extern u_char *session_id2;
+extern int session_id2_len;
+
+static int
+userauth_hostbased(Authctxt *authctxt)
+{
+ Buffer b;
+ Key *key = NULL;
+ char *pkalg, *cuser, *chost, *service;
+ u_char *pkblob, *sig;
+ 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) {
+ error("userauth_hostbased: cannot decode key: %s", pkalg);
+ goto done;
+ }
+ if (key->type != pktype) {
+ error("userauth_hostbased: type mismatch for decoded key "
+ "(received %d, expected %d)", key->type, pktype);
+ goto done;
+ }
+ service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
+ authctxt->service;
+ buffer_init(&b);
+ buffer_put_string(&b, session_id2, session_id2_len);
+ /* reconstruct packet */
+ buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+ buffer_put_cstring(&b, authctxt->user);
+ buffer_put_cstring(&b, 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 */
+ authenticated = 0;
+ if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
+ PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
+ buffer_len(&b))) == 1)
+ authenticated = 1;
+
+ buffer_clear(&b);
+done:
+ debug2("userauth_hostbased: authenticated %d", authenticated);
+ if (key != NULL)
+ key_free(key);
+ xfree(pkalg);
+ xfree(pkblob);
+ xfree(cuser);
+ xfree(chost);
+ xfree(sig);
+ return authenticated;
+}
+
+/* return 1 if given hostkey is allowed */
+int
+hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
+ Key *key)
+{
+ const char *resolvedname, *ipaddr, *lookup;
+ HostStatus host_status;
+ int len;
+
+ resolvedname = get_canonical_hostname(options.verify_reverse_mapping);
+ ipaddr = get_remote_ipaddr();
+
+ debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
+ chost, resolvedname, ipaddr);
+
+ if (options.hostbased_uses_name_from_packet_only) {
+ if (auth_rhosts2(pw, cuser, chost, chost) == 0)
+ return 0;
+ lookup = chost;
+ } else {
+ if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
+ debug2("stripping trailing dot from chost %s", chost);
+ chost[len - 1] = '\0';
+ }
+ 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");
+
+ host_status = check_key_in_hostfiles(pw, key, lookup,
+ _PATH_SSH_SYSTEM_HOSTFILE,
+ options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
+
+ /* backward compat if no key has been found. */
+ if (host_status == HOST_NEW)
+ host_status = check_key_in_hostfiles(pw, key, lookup,
+ _PATH_SSH_SYSTEM_HOSTFILE2,
+ options.ignore_user_known_hosts ? NULL :
+ _PATH_SSH_USER_HOSTFILE2);
+
+ return (host_status == HOST_OK);
+}
+
+Authmethod method_hostbased = {
+ "hostbased",
+ userauth_hostbased,
+ &options.hostbased_authentication
+};
diff --git a/crypto/openssh/auth2-kbdint.c b/crypto/openssh/auth2-kbdint.c
new file mode 100644
index 0000000..cae051e
--- /dev/null
+++ b/crypto/openssh/auth2-kbdint.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: auth2-kbdint.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
+
+#include "packet.h"
+#include "auth.h"
+#include "log.h"
+#include "servconf.h"
+#include "xmalloc.h"
+
+/* import */
+extern ServerOptions options;
+
+static int
+userauth_kbdint(Authctxt *authctxt)
+{
+ int authenticated = 0;
+ char *lang, *devs;
+
+ lang = packet_get_string(NULL);
+ devs = packet_get_string(NULL);
+ packet_check_eom();
+
+ debug("keyboard-interactive devs %s", devs);
+
+ if (options.challenge_response_authentication)
+ authenticated = auth2_challenge(authctxt, devs);
+
+ xfree(devs);
+ xfree(lang);
+ return authenticated;
+}
+
+Authmethod method_kbdint = {
+ "keyboard-interactive",
+ userauth_kbdint,
+ &options.kbd_interactive_authentication
+};
diff --git a/crypto/openssh/auth2-none.c b/crypto/openssh/auth2-none.c
new file mode 100644
index 0000000..0afbc4f
--- /dev/null
+++ b/crypto/openssh/auth2-none.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: auth2-none.c,v 1.3 2002/06/19 00:27:55 deraadt Exp $");
+
+#include "auth.h"
+#include "xmalloc.h"
+#include "packet.h"
+#include "log.h"
+#include "servconf.h"
+#include "atomicio.h"
+#include "compat.h"
+#include "ssh2.h"
+#include "monitor_wrap.h"
+
+/* import */
+extern ServerOptions options;
+
+/* "none" is allowed only one time */
+static int none_enabled = 1;
+
+char *
+auth2_read_banner(void)
+{
+ struct stat st;
+ char *banner = NULL;
+ off_t len, n;
+ int fd;
+
+ if ((fd = open(options.banner, O_RDONLY)) == -1)
+ return (NULL);
+ if (fstat(fd, &st) == -1) {
+ close(fd);
+ return (NULL);
+ }
+ len = st.st_size;
+ banner = xmalloc(len + 1);
+ n = atomicio(read, fd, banner, len);
+ close(fd);
+
+ if (n != len) {
+ free(banner);
+ return (NULL);
+ }
+ banner[n] = '\0';
+
+ return (banner);
+}
+
+static void
+userauth_banner(void)
+{
+ char *banner = NULL;
+
+ if (options.banner == NULL || (datafellows & SSH_BUG_BANNER))
+ return;
+
+ if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
+ goto done;
+
+ packet_start(SSH2_MSG_USERAUTH_BANNER);
+ packet_put_cstring(banner);
+ packet_put_cstring(""); /* language, unused */
+ packet_send();
+ debug("userauth_banner: sent");
+done:
+ if (banner)
+ xfree(banner);
+}
+
+static int
+userauth_none(Authctxt *authctxt)
+{
+ none_enabled = 0;
+ packet_check_eom();
+ userauth_banner();
+ return (authctxt->valid ? PRIVSEP(auth_password(authctxt, "")) : 0);
+}
+
+Authmethod method_none = {
+ "none",
+ userauth_none,
+ &none_enabled
+};
diff --git a/crypto/openssh/auth2-passwd.c b/crypto/openssh/auth2-passwd.c
new file mode 100644
index 0000000..bfd7aeb
--- /dev/null
+++ b/crypto/openssh/auth2-passwd.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: auth2-passwd.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
+
+#include "xmalloc.h"
+#include "packet.h"
+#include "log.h"
+#include "auth.h"
+#include "monitor_wrap.h"
+#include "servconf.h"
+
+/* import */
+extern ServerOptions options;
+
+static int
+userauth_passwd(Authctxt *authctxt)
+{
+ char *password;
+ int authenticated = 0;
+ int change;
+ u_int len;
+ change = packet_get_char();
+ if (change)
+ log("password change not supported");
+ password = packet_get_string(&len);
+ packet_check_eom();
+ if (authctxt->valid &&
+ PRIVSEP(auth_password(authctxt, password)) == 1)
+ authenticated = 1;
+ memset(password, 0, len);
+ xfree(password);
+ return authenticated;
+}
+
+Authmethod method_passwd = {
+ "password",
+ userauth_passwd,
+ &options.password_authentication
+};
diff --git a/crypto/openssh/auth2-pubkey.c b/crypto/openssh/auth2-pubkey.c
new file mode 100644
index 0000000..3d164ea
--- /dev/null
+++ b/crypto/openssh/auth2-pubkey.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: auth2-pubkey.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
+
+#include "ssh2.h"
+#include "xmalloc.h"
+#include "packet.h"
+#include "buffer.h"
+#include "log.h"
+#include "servconf.h"
+#include "compat.h"
+#include "bufaux.h"
+#include "auth.h"
+#include "key.h"
+#include "pathnames.h"
+#include "uidswap.h"
+#include "auth-options.h"
+#include "canohost.h"
+#include "monitor_wrap.h"
+
+/* import */
+extern ServerOptions options;
+extern u_char *session_id2;
+extern int session_id2_len;
+
+static int
+userauth_pubkey(Authctxt *authctxt)
+{
+ Buffer b;
+ Key *key = NULL;
+ char *pkalg;
+ u_char *pkblob, *sig;
+ u_int alen, blen, slen;
+ int have_sig, pktype;
+ int authenticated = 0;
+
+ if (!authctxt->valid) {
+ debug2("userauth_pubkey: disabled because of invalid user");
+ return 0;
+ }
+ have_sig = packet_get_char();
+ if (datafellows & SSH_BUG_PKAUTH) {
+ debug2("userauth_pubkey: SSH_BUG_PKAUTH");
+ /* no explicit pkalg given */
+ pkblob = packet_get_string(&blen);
+ buffer_init(&b);
+ buffer_append(&b, pkblob, blen);
+ /* so we have to extract the pkalg from the pkblob */
+ pkalg = buffer_get_string(&b, &alen);
+ buffer_free(&b);
+ } else {
+ pkalg = packet_get_string(&alen);
+ pkblob = packet_get_string(&blen);
+ }
+ pktype = key_type_from_name(pkalg);
+ if (pktype == KEY_UNSPEC) {
+ /* this is perfectly legal */
+ log("userauth_pubkey: unsupported public key algorithm: %s",
+ pkalg);
+ goto done;
+ }
+ key = key_from_blob(pkblob, blen);
+ if (key == NULL) {
+ error("userauth_pubkey: cannot decode key: %s", pkalg);
+ goto done;
+ }
+ if (key->type != pktype) {
+ error("userauth_pubkey: type mismatch for decoded key "
+ "(received %d, expected %d)", key->type, pktype);
+ goto done;
+ }
+ if (have_sig) {
+ sig = packet_get_string(&slen);
+ packet_check_eom();
+ 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);
+ }
+ /* reconstruct packet */
+ buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+ buffer_put_cstring(&b, authctxt->user);
+ buffer_put_cstring(&b,
+ datafellows & SSH_BUG_PKSERVICE ?
+ "ssh-userauth" :
+ authctxt->service);
+ if (datafellows & SSH_BUG_PKAUTH) {
+ buffer_put_char(&b, have_sig);
+ } else {
+ buffer_put_cstring(&b, "publickey");
+ buffer_put_char(&b, have_sig);
+ buffer_put_cstring(&b, pkalg);
+ }
+ buffer_put_string(&b, pkblob, blen);
+#ifdef DEBUG_PK
+ buffer_dump(&b);
+#endif
+ /* test for correct signature */
+ authenticated = 0;
+ if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
+ PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
+ buffer_len(&b))) == 1)
+ authenticated = 1;
+ buffer_clear(&b);
+ xfree(sig);
+ } else {
+ debug("test whether pkalg/pkblob are acceptable");
+ packet_check_eom();
+
+ /* XXX fake reply and always send PK_OK ? */
+ /*
+ * XXX this allows testing whether a user is allowed
+ * to login: if you happen to have a valid pubkey this
+ * message is sent. the message is NEVER sent at all
+ * if a user is not allowed to login. is this an
+ * issue? -markus
+ */
+ if (PRIVSEP(user_key_allowed(authctxt->pw, key))) {
+ packet_start(SSH2_MSG_USERAUTH_PK_OK);
+ packet_put_string(pkalg, alen);
+ packet_put_string(pkblob, blen);
+ packet_send();
+ packet_write_wait();
+ authctxt->postponed = 1;
+ }
+ }
+ if (authenticated != 1)
+ auth_clear_options();
+done:
+ debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
+ if (key != NULL)
+ key_free(key);
+ xfree(pkalg);
+ xfree(pkblob);
+ return authenticated;
+}
+
+/* return 1 if user allows given key */
+static int
+user_key_allowed2(struct passwd *pw, Key *key, char *file)
+{
+ char line[8192];
+ int found_key = 0;
+ FILE *f;
+ u_long linenum = 0;
+ struct stat st;
+ Key *found;
+ char *fp;
+
+ if (pw == NULL)
+ return 0;
+
+ /* Temporarily use the user's uid. */
+ temporarily_use_uid(pw);
+
+ debug("trying public key file %s", file);
+
+ /* Fail quietly if file does not exist */
+ if (stat(file, &st) < 0) {
+ /* Restore the privileged uid. */
+ restore_uid();
+ return 0;
+ }
+ /* Open the file containing the authorized keys. */
+ f = fopen(file, "r");
+ if (!f) {
+ /* Restore the privileged uid. */
+ restore_uid();
+ return 0;
+ }
+ if (options.strict_modes &&
+ secure_filename(f, file, pw, line, sizeof(line)) != 0) {
+ fclose(f);
+ log("Authentication refused: %s", line);
+ restore_uid();
+ return 0;
+ }
+
+ found_key = 0;
+ found = key_new(key->type);
+
+ while (fgets(line, sizeof(line), f)) {
+ char *cp, *options = NULL;
+ linenum++;
+ /* Skip leading whitespace, empty and comment lines. */
+ for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+ if (!*cp || *cp == '\n' || *cp == '#')
+ continue;
+
+ if (key_read(found, &cp) != 1) {
+ /* no key? check if there are options for this key */
+ int quoted = 0;
+ debug2("user_key_allowed: check options: '%s'", cp);
+ options = cp;
+ for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
+ if (*cp == '\\' && cp[1] == '"')
+ cp++; /* Skip both */
+ else if (*cp == '"')
+ quoted = !quoted;
+ }
+ /* Skip remaining whitespace. */
+ for (; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+ if (key_read(found, &cp) != 1) {
+ debug2("user_key_allowed: advance: '%s'", cp);
+ /* still no key? advance to next line*/
+ continue;
+ }
+ }
+ if (key_equal(found, key) &&
+ auth_parse_options(pw, options, file, linenum) == 1) {
+ found_key = 1;
+ debug("matching key found: file %s, line %lu",
+ file, linenum);
+ fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
+ verbose("Found matching %s key: %s",
+ key_type(found), fp);
+ xfree(fp);
+ break;
+ }
+ }
+ restore_uid();
+ fclose(f);
+ key_free(found);
+ if (!found_key)
+ debug2("key not found");
+ return found_key;
+}
+
+/* check whether given key is in .ssh/authorized_keys* */
+int
+user_key_allowed(struct passwd *pw, Key *key)
+{
+ int success;
+ char *file;
+
+ file = authorized_keys_file(pw);
+ success = user_key_allowed2(pw, key, file);
+ xfree(file);
+ if (success)
+ return success;
+
+ /* try suffix "2" for backward compat, too */
+ file = authorized_keys_file2(pw);
+ success = user_key_allowed2(pw, key, file);
+ xfree(file);
+ return success;
+}
+
+Authmethod method_pubkey = {
+ "publickey",
+ userauth_pubkey,
+ &options.pubkey_authentication
+};
diff --git a/crypto/openssh/auth2.c b/crypto/openssh/auth2.c
index 21f46a3..c6ba227 100644
--- a/crypto/openssh/auth2.c
+++ b/crypto/openssh/auth2.c
@@ -23,48 +23,41 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth2.c,v 1.85 2002/02/24 19:14:59 markus Exp $");
-
-#include <openssl/evp.h>
+RCSID("$OpenBSD: auth2.c,v 1.93 2002/05/31 11:35:15 markus Exp $");
#include "ssh2.h"
#include "xmalloc.h"
-#include "rsa.h"
-#include "sshpty.h"
#include "packet.h"
-#include "buffer.h"
#include "log.h"
#include "servconf.h"
#include "compat.h"
-#include "channels.h"
-#include "bufaux.h"
#include "auth.h"
-#include "session.h"
#include "dispatch.h"
-#include "key.h"
-#include "cipher.h"
-#include "kex.h"
#include "pathnames.h"
-#include "uidswap.h"
-#include "auth-options.h"
-#include "misc.h"
-#include "hostfile.h"
-#include "canohost.h"
-#include "match.h"
+#include "monitor_wrap.h"
/* import */
extern ServerOptions options;
extern u_char *session_id2;
extern int session_id2_len;
-static Authctxt *x_authctxt = NULL;
-static int one = 1;
+Authctxt *x_authctxt = NULL;
+
+/* methods */
+
+extern Authmethod method_none;
+extern Authmethod method_pubkey;
+extern Authmethod method_passwd;
+extern Authmethod method_kbdint;
+extern Authmethod method_hostbased;
-typedef struct Authmethod Authmethod;
-struct Authmethod {
- char *name;
- int (*userauth)(Authctxt *authctxt);
- int *enabled;
+Authmethod *authmethods[] = {
+ &method_none,
+ &method_pubkey,
+ &method_passwd,
+ &method_kbdint,
+ &method_hostbased,
+ NULL
};
/* protocol */
@@ -75,41 +68,14 @@ static void input_userauth_request(int, u_int32_t, void *);
/* helper */
static Authmethod *authmethod_lookup(const char *);
static char *authmethods_get(void);
-static int user_key_allowed(struct passwd *, Key *);
-static int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
-
-/* auth */
-static void userauth_banner(void);
-static int userauth_none(Authctxt *);
-static int userauth_passwd(Authctxt *);
-static int userauth_pubkey(Authctxt *);
-static int userauth_hostbased(Authctxt *);
-static int userauth_kbdint(Authctxt *);
-
-Authmethod authmethods[] = {
- {"none",
- userauth_none,
- &one},
- {"publickey",
- userauth_pubkey,
- &options.pubkey_authentication},
- {"password",
- userauth_passwd,
- &options.password_authentication},
- {"keyboard-interactive",
- userauth_kbdint,
- &options.kbd_interactive_authentication},
- {"hostbased",
- userauth_hostbased,
- &options.hostbased_authentication},
- {NULL, NULL, NULL}
-};
+int user_key_allowed(struct passwd *, Key *);
+int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
/*
* loop until authctxt->success == TRUE
*/
-void
+Authctxt *
do_authentication2(void)
{
Authctxt *authctxt = authctxt_new();
@@ -123,7 +89,8 @@ do_authentication2(void)
dispatch_init(&dispatch_protocol_error);
dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
- do_authenticated(authctxt);
+
+ return (authctxt);
}
static void
@@ -181,19 +148,20 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
if (authctxt->attempt++ == 0) {
/* setup auth context */
- struct passwd *pw = NULL;
- pw = getpwnam(user);
- if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) {
- authctxt->pw = pwcopy(pw);
+ authctxt->pw = PRIVSEP(getpwnamallow(user));
+ if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
authctxt->valid = 1;
debug2("input_userauth_request: setting up authctxt for %s", user);
} else {
log("input_userauth_request: illegal user %s", user);
}
- setproctitle("%s", pw ? user : "unknown");
+ setproctitle("%s%s", authctxt->pw ? user : "unknown",
+ use_privsep ? " [net]" : "");
authctxt->user = xstrdup(user);
authctxt->service = xstrdup(service);
authctxt->style = style ? xstrdup(style) : NULL;
+ if (use_privsep)
+ mm_inform_authserv(service, style);
} else if (strcmp(user, authctxt->user) != 0 ||
strcmp(service, authctxt->service) != 0) {
packet_disconnect("Change of username or service not allowed: "
@@ -259,281 +227,6 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
}
}
-static void
-userauth_banner(void)
-{
- struct stat st;
- char *banner = NULL;
- off_t len, n;
- int fd;
-
- if (options.banner == NULL || (datafellows & SSH_BUG_BANNER))
- return;
- if ((fd = open(options.banner, O_RDONLY)) < 0)
- return;
- if (fstat(fd, &st) < 0)
- goto done;
- len = st.st_size;
- banner = xmalloc(len + 1);
- if ((n = read(fd, banner, len)) < 0)
- goto done;
- banner[n] = '\0';
- packet_start(SSH2_MSG_USERAUTH_BANNER);
- packet_put_cstring(banner);
- packet_put_cstring(""); /* language, unused */
- packet_send();
- debug("userauth_banner: sent");
-done:
- if (banner)
- xfree(banner);
- close(fd);
- return;
-}
-
-static int
-userauth_none(Authctxt *authctxt)
-{
- /* disable method "none", only allowed one time */
- Authmethod *m = authmethod_lookup("none");
- if (m != NULL)
- m->enabled = NULL;
- packet_check_eom();
- userauth_banner();
- return authctxt->valid ? auth_password(authctxt, "") : 0;
-}
-
-static int
-userauth_passwd(Authctxt *authctxt)
-{
- char *password;
- int authenticated = 0;
- int change;
- u_int len;
- change = packet_get_char();
- if (change)
- log("password change not supported");
- password = packet_get_string(&len);
- packet_check_eom();
- if (authctxt->valid &&
- auth_password(authctxt, password) == 1)
- authenticated = 1;
- memset(password, 0, len);
- xfree(password);
- return authenticated;
-}
-
-static int
-userauth_kbdint(Authctxt *authctxt)
-{
- int authenticated = 0;
- char *lang, *devs;
-
- lang = packet_get_string(NULL);
- devs = packet_get_string(NULL);
- packet_check_eom();
-
- debug("keyboard-interactive devs %s", devs);
-
- if (options.challenge_response_authentication)
- authenticated = auth2_challenge(authctxt, devs);
-
- xfree(devs);
- xfree(lang);
- return authenticated;
-}
-
-static int
-userauth_pubkey(Authctxt *authctxt)
-{
- Buffer b;
- Key *key = NULL;
- char *pkalg;
- u_char *pkblob, *sig;
- u_int alen, blen, slen;
- int have_sig, pktype;
- int authenticated = 0;
-
- if (!authctxt->valid) {
- debug2("userauth_pubkey: disabled because of invalid user");
- return 0;
- }
- have_sig = packet_get_char();
- if (datafellows & SSH_BUG_PKAUTH) {
- debug2("userauth_pubkey: SSH_BUG_PKAUTH");
- /* no explicit pkalg given */
- pkblob = packet_get_string(&blen);
- buffer_init(&b);
- buffer_append(&b, pkblob, blen);
- /* so we have to extract the pkalg from the pkblob */
- pkalg = buffer_get_string(&b, &alen);
- buffer_free(&b);
- } else {
- pkalg = packet_get_string(&alen);
- pkblob = packet_get_string(&blen);
- }
- pktype = key_type_from_name(pkalg);
- if (pktype == KEY_UNSPEC) {
- /* this is perfectly legal */
- log("userauth_pubkey: unsupported public key algorithm: %s",
- pkalg);
- goto done;
- }
- key = key_from_blob(pkblob, blen);
- if (key == NULL) {
- error("userauth_pubkey: cannot decode key: %s", pkalg);
- goto done;
- }
- if (key->type != pktype) {
- error("userauth_pubkey: type mismatch for decoded key "
- "(received %d, expected %d)", key->type, pktype);
- goto done;
- }
- if (have_sig) {
- sig = packet_get_string(&slen);
- packet_check_eom();
- 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);
- }
- /* reconstruct packet */
- buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
- buffer_put_cstring(&b, authctxt->user);
- buffer_put_cstring(&b,
- datafellows & SSH_BUG_PKSERVICE ?
- "ssh-userauth" :
- authctxt->service);
- if (datafellows & SSH_BUG_PKAUTH) {
- buffer_put_char(&b, have_sig);
- } else {
- buffer_put_cstring(&b, "publickey");
- buffer_put_char(&b, have_sig);
- buffer_put_cstring(&b, pkalg);
- }
- buffer_put_string(&b, pkblob, blen);
-#ifdef DEBUG_PK
- buffer_dump(&b);
-#endif
- /* test for correct signature */
- if (user_key_allowed(authctxt->pw, key) &&
- key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
- authenticated = 1;
- buffer_clear(&b);
- xfree(sig);
- } else {
- debug("test whether pkalg/pkblob are acceptable");
- packet_check_eom();
-
- /* XXX fake reply and always send PK_OK ? */
- /*
- * XXX this allows testing whether a user is allowed
- * to login: if you happen to have a valid pubkey this
- * message is sent. the message is NEVER sent at all
- * if a user is not allowed to login. is this an
- * issue? -markus
- */
- if (user_key_allowed(authctxt->pw, key)) {
- packet_start(SSH2_MSG_USERAUTH_PK_OK);
- packet_put_string(pkalg, alen);
- packet_put_string(pkblob, blen);
- packet_send();
- packet_write_wait();
- authctxt->postponed = 1;
- }
- }
- if (authenticated != 1)
- auth_clear_options();
-done:
- debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
- if (key != NULL)
- key_free(key);
- xfree(pkalg);
- xfree(pkblob);
- return authenticated;
-}
-
-static int
-userauth_hostbased(Authctxt *authctxt)
-{
- Buffer b;
- Key *key = NULL;
- char *pkalg, *cuser, *chost, *service;
- u_char *pkblob, *sig;
- 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) {
- error("userauth_hostbased: cannot decode key: %s", pkalg);
- goto done;
- }
- if (key->type != pktype) {
- error("userauth_hostbased: type mismatch for decoded key "
- "(received %d, expected %d)", key->type, pktype);
- goto done;
- }
- service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
- authctxt->service;
- buffer_init(&b);
- buffer_put_string(&b, session_id2, session_id2_len);
- /* reconstruct packet */
- buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
- buffer_put_cstring(&b, authctxt->user);
- buffer_put_cstring(&b, 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);
-done:
- debug2("userauth_hostbased: authenticated %d", authenticated);
- if (key != NULL)
- key_free(key);
- xfree(pkalg);
- xfree(pkblob);
- xfree(cuser);
- xfree(chost);
- xfree(sig);
- return authenticated;
-}
-
/* get current user */
struct passwd*
@@ -547,18 +240,20 @@ auth_get_user(void)
static char *
authmethods_get(void)
{
- Authmethod *method = NULL;
Buffer b;
char *list;
+ int i;
buffer_init(&b);
- for (method = authmethods; method->name != NULL; method++) {
- if (strcmp(method->name, "none") == 0)
+ for (i = 0; authmethods[i] != NULL; i++) {
+ if (strcmp(authmethods[i]->name, "none") == 0)
continue;
- if (method->enabled != NULL && *(method->enabled) != 0) {
+ if (authmethods[i]->enabled != NULL &&
+ *(authmethods[i]->enabled) != 0) {
if (buffer_len(&b) > 0)
buffer_append(&b, ",", 1);
- buffer_append(&b, method->name, strlen(method->name));
+ buffer_append(&b, authmethods[i]->name,
+ strlen(authmethods[i]->name));
}
}
buffer_append(&b, "\0", 1);
@@ -570,174 +265,15 @@ authmethods_get(void)
static Authmethod *
authmethod_lookup(const char *name)
{
- Authmethod *method = NULL;
+ int i;
+
if (name != NULL)
- for (method = authmethods; method->name != NULL; method++)
- if (method->enabled != NULL &&
- *(method->enabled) != 0 &&
- strcmp(name, method->name) == 0)
- return method;
- debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
+ for (i = 0; authmethods[i] != NULL; i++)
+ if (authmethods[i]->enabled != NULL &&
+ *(authmethods[i]->enabled) != 0 &&
+ strcmp(name, authmethods[i]->name) == 0)
+ return authmethods[i];
+ debug2("Unrecognized authentication method name: %s",
+ name ? name : "NULL");
return NULL;
}
-
-/* return 1 if user allows given key */
-static int
-user_key_allowed2(struct passwd *pw, Key *key, char *file)
-{
- char line[8192];
- int found_key = 0;
- FILE *f;
- u_long linenum = 0;
- struct stat st;
- Key *found;
- char *fp;
-
- if (pw == NULL)
- return 0;
-
- /* Temporarily use the user's uid. */
- temporarily_use_uid(pw);
-
- debug("trying public key file %s", file);
-
- /* Fail quietly if file does not exist */
- if (stat(file, &st) < 0) {
- /* Restore the privileged uid. */
- restore_uid();
- return 0;
- }
- /* Open the file containing the authorized keys. */
- f = fopen(file, "r");
- if (!f) {
- /* Restore the privileged uid. */
- restore_uid();
- return 0;
- }
- if (options.strict_modes &&
- secure_filename(f, file, pw, line, sizeof(line)) != 0) {
- fclose(f);
- log("Authentication refused: %s", line);
- restore_uid();
- return 0;
- }
-
- found_key = 0;
- found = key_new(key->type);
-
- while (fgets(line, sizeof(line), f)) {
- char *cp, *options = NULL;
- linenum++;
- /* Skip leading whitespace, empty and comment lines. */
- for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
- ;
- if (!*cp || *cp == '\n' || *cp == '#')
- continue;
-
- if (key_read(found, &cp) != 1) {
- /* no key? check if there are options for this key */
- int quoted = 0;
- debug2("user_key_allowed: check options: '%s'", cp);
- options = cp;
- for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
- if (*cp == '\\' && cp[1] == '"')
- cp++; /* Skip both */
- else if (*cp == '"')
- quoted = !quoted;
- }
- /* Skip remaining whitespace. */
- for (; *cp == ' ' || *cp == '\t'; cp++)
- ;
- if (key_read(found, &cp) != 1) {
- debug2("user_key_allowed: advance: '%s'", cp);
- /* still no key? advance to next line*/
- continue;
- }
- }
- if (key_equal(found, key) &&
- auth_parse_options(pw, options, file, linenum) == 1) {
- found_key = 1;
- debug("matching key found: file %s, line %lu",
- file, linenum);
- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
- verbose("Found matching %s key: %s",
- key_type(found), fp);
- xfree(fp);
- break;
- }
- }
- restore_uid();
- fclose(f);
- key_free(found);
- if (!found_key)
- debug2("key not found");
- return found_key;
-}
-
-/* check whether given key is in .ssh/authorized_keys* */
-static int
-user_key_allowed(struct passwd *pw, Key *key)
-{
- int success;
- char *file;
-
- file = authorized_keys_file(pw);
- success = user_key_allowed2(pw, key, file);
- xfree(file);
- if (success)
- return success;
-
- /* try suffix "2" for backward compat, too */
- file = authorized_keys_file2(pw);
- success = user_key_allowed2(pw, key, file);
- xfree(file);
- return success;
-}
-
-/* return 1 if given hostkey is allowed */
-static int
-hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
- Key *key)
-{
- const char *resolvedname, *ipaddr, *lookup;
- HostStatus host_status;
- int len;
-
- resolvedname = get_canonical_hostname(options.verify_reverse_mapping);
- ipaddr = get_remote_ipaddr();
-
- debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
- chost, resolvedname, ipaddr);
-
- if (options.hostbased_uses_name_from_packet_only) {
- if (auth_rhosts2(pw, cuser, chost, chost) == 0)
- return 0;
- lookup = chost;
- } else {
- if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
- debug2("stripping trailing dot from chost %s", chost);
- chost[len - 1] = '\0';
- }
- 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");
-
- host_status = check_key_in_hostfiles(pw, key, lookup,
- _PATH_SSH_SYSTEM_HOSTFILE,
- options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
-
- /* backward compat if no key has been found. */
- if (host_status == HOST_NEW)
- host_status = check_key_in_hostfiles(pw, key, lookup,
- _PATH_SSH_SYSTEM_HOSTFILE2,
- options.ignore_user_known_hosts ? NULL :
- _PATH_SSH_USER_HOSTFILE2);
-
- return (host_status == HOST_OK);
-}
diff --git a/crypto/openssh/authfd.c b/crypto/openssh/authfd.c
index fa76435..a452a79 100644
--- a/crypto/openssh/authfd.c
+++ b/crypto/openssh/authfd.c
@@ -35,7 +35,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: authfd.c,v 1.48 2002/02/24 19:14:59 markus Exp $");
+RCSID("$OpenBSD: authfd.c,v 1.55 2002/06/19 00:27:55 deraadt Exp $");
#include <openssl/evp.h>
@@ -59,7 +59,7 @@ int decode_reply(int type);
/* macro to check for "agent failure" message */
#define agent_failed(x) \
((x == SSH_AGENT_FAILURE) || (x == SSH_COM_AGENT2_FAILURE) || \
- (x == SSH2_AGENT_FAILURE))
+ (x == SSH2_AGENT_FAILURE))
/* Returns the number of the authentication fd, or -1 if there is none. */
@@ -207,6 +207,26 @@ ssh_close_authentication_connection(AuthenticationConnection *auth)
xfree(auth);
}
+/* Lock/unlock agent */
+int
+ssh_lock_agent(AuthenticationConnection *auth, int lock, const char *password)
+{
+ int type;
+ Buffer msg;
+
+ buffer_init(&msg);
+ buffer_put_char(&msg, lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK);
+ buffer_put_cstring(&msg, password);
+
+ if (ssh_request_reply(auth, &msg, &msg) == 0) {
+ buffer_free(&msg);
+ return 0;
+ }
+ type = buffer_get_char(&msg);
+ buffer_free(&msg);
+ return decode_reply(type);
+}
+
/*
* Returns the first authentication identity held by the agent.
*/
@@ -419,8 +439,6 @@ ssh_agent_sign(AuthenticationConnection *auth,
static void
ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
{
- buffer_clear(b);
- buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY);
buffer_put_int(b, BN_num_bits(key->n));
buffer_put_bignum(b, key->n);
buffer_put_bignum(b, key->e);
@@ -435,8 +453,6 @@ ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
static void
ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
{
- buffer_clear(b);
- buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY);
buffer_put_cstring(b, key_ssh_name(key));
switch (key->type) {
case KEY_RSA:
@@ -464,19 +480,28 @@ ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
*/
int
-ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
+ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
+ const char *comment, u_int life)
{
Buffer msg;
- int type;
+ int type, constrained = (life != 0);
buffer_init(&msg);
switch (key->type) {
case KEY_RSA1:
+ type = constrained ?
+ SSH_AGENTC_ADD_RSA_ID_CONSTRAINED :
+ SSH_AGENTC_ADD_RSA_IDENTITY;
+ buffer_put_char(&msg, type);
ssh_encode_identity_rsa1(&msg, key->rsa, comment);
break;
case KEY_RSA:
case KEY_DSA:
+ type = constrained ?
+ SSH2_AGENTC_ADD_ID_CONSTRAINED :
+ SSH2_AGENTC_ADD_IDENTITY;
+ buffer_put_char(&msg, type);
ssh_encode_identity_ssh2(&msg, key, comment);
break;
default:
@@ -484,6 +509,12 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
return 0;
break;
}
+ if (constrained) {
+ if (life != 0) {
+ buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME);
+ buffer_put_int(&msg, life);
+ }
+ }
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return 0;
@@ -493,6 +524,12 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
return decode_reply(type);
}
+int
+ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
+{
+ return ssh_add_identity_constrained(auth, key, comment, 0);
+}
+
/*
* Removes an identity from the authentication server. This call is not
* meant to be used by normal applications.
@@ -532,7 +569,7 @@ ssh_remove_identity(AuthenticationConnection *auth, Key *key)
}
int
-ssh_update_card(AuthenticationConnection *auth, int add, const char *reader_id)
+ssh_update_card(AuthenticationConnection *auth, int add, const char *reader_id, const char *pin)
{
Buffer msg;
int type;
@@ -541,6 +578,7 @@ ssh_update_card(AuthenticationConnection *auth, int add, const char *reader_id)
buffer_put_char(&msg, add ? SSH_AGENTC_ADD_SMARTCARD_KEY :
SSH_AGENTC_REMOVE_SMARTCARD_KEY);
buffer_put_cstring(&msg, reader_id);
+ buffer_put_cstring(&msg, pin);
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return 0;
diff --git a/crypto/openssh/authfd.h b/crypto/openssh/authfd.h
index 0f2ca7a..b2767e5 100644
--- a/crypto/openssh/authfd.h
+++ b/crypto/openssh/authfd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfd.h,v 1.23 2002/03/04 17:27:39 stevesk Exp $ */
+/* $OpenBSD: authfd.h,v 1.30 2002/06/19 00:27:55 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -40,34 +40,46 @@
/* smartcard */
#define SSH_AGENTC_ADD_SMARTCARD_KEY 20
-#define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
+#define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
+
+/* lock/unlock the agent */
+#define SSH_AGENTC_LOCK 22
+#define SSH_AGENTC_UNLOCK 23
+
+/* add key with constraints */
+#define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24
+#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25
+
+#define SSH_AGENT_CONSTRAIN_LIFETIME 1
/* extended failure messages */
#define SSH2_AGENT_FAILURE 30
/* additional error code for ssh.com's ssh-agent2 */
-#define SSH_COM_AGENT2_FAILURE 102
+#define SSH_COM_AGENT2_FAILURE 102
#define SSH_AGENT_OLD_SIGNATURE 0x01
typedef struct {
- int fd;
- Buffer identities;
- int howmany;
-} AuthenticationConnection;
+ int fd;
+ Buffer identities;
+ int howmany;
+} AuthenticationConnection;
-int ssh_get_authentication_socket(void);
-void ssh_close_authentication_socket(int);
+int ssh_get_authentication_socket(void);
+void ssh_close_authentication_socket(int);
AuthenticationConnection *ssh_get_authentication_connection(void);
-void ssh_close_authentication_connection(AuthenticationConnection *);
+void ssh_close_authentication_connection(AuthenticationConnection *);
int ssh_get_num_identities(AuthenticationConnection *, int);
Key *ssh_get_first_identity(AuthenticationConnection *, char **, int);
Key *ssh_get_next_identity(AuthenticationConnection *, char **, int);
int ssh_add_identity(AuthenticationConnection *, Key *, const char *);
+int ssh_add_identity_constrained(AuthenticationConnection *, Key *, const char *, u_int);
int ssh_remove_identity(AuthenticationConnection *, Key *);
int ssh_remove_all_identities(AuthenticationConnection *, int);
-int ssh_update_card(AuthenticationConnection *, int, const char *);
+int ssh_lock_agent(AuthenticationConnection *, int, const char *);
+int ssh_update_card(AuthenticationConnection *, int, const char *, const char *);
int
ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16],
diff --git a/crypto/openssh/authfile.c b/crypto/openssh/authfile.c
index 337da59..f22a3d1 100644
--- a/crypto/openssh/authfile.c
+++ b/crypto/openssh/authfile.c
@@ -36,7 +36,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: authfile.c,v 1.48 2002/02/28 15:46:33 markus Exp $");
+RCSID("$OpenBSD: authfile.c,v 1.49 2002/05/23 19:24:30 markus Exp $");
#include <openssl/err.h>
#include <openssl/evp.h>
@@ -421,7 +421,7 @@ fail:
return NULL;
}
-static Key *
+Key *
key_load_private_pem(int fd, int type, const char *passphrase,
char **commentp)
{
diff --git a/crypto/openssh/authfile.h b/crypto/openssh/authfile.h
index c614ca1..7f92701 100644
--- a/crypto/openssh/authfile.h
+++ b/crypto/openssh/authfile.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfile.h,v 1.9 2002/03/04 17:27:39 stevesk Exp $ */
+/* $OpenBSD: authfile.h,v 1.10 2002/05/23 19:24:30 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -20,5 +20,6 @@ Key *key_load_public(const char *, char **);
Key *key_load_public_type(int, const char *, char **);
Key *key_load_private(const char *, const char *, char **);
Key *key_load_private_type(int, const char *, const char *, char **);
+Key *key_load_private_pem(int, int, const char *, char **);
#endif
diff --git a/crypto/openssh/bufaux.c b/crypto/openssh/bufaux.c
index 0c92ed9..f4c5c94 100644
--- a/crypto/openssh/bufaux.c
+++ b/crypto/openssh/bufaux.c
@@ -37,7 +37,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: bufaux.c,v 1.22 2002/01/18 18:14:17 stevesk Exp $");
+RCSID("$OpenBSD: bufaux.c,v 1.25 2002/04/20 09:14:58 markus Exp $");
#include <openssl/bn.h>
#include "bufaux.h"
@@ -137,10 +137,18 @@ buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
BN_bin2bn(bin, len, value);
xfree(bin);
}
-
/*
- * Returns an integer from the buffer (4 bytes, msb first).
+ * Returns integers from the buffer (msb first).
*/
+
+u_short
+buffer_get_short(Buffer *buffer)
+{
+ u_char buf[2];
+ buffer_get(buffer, (char *) buf, 2);
+ return GET_16BIT(buf);
+}
+
u_int
buffer_get_int(Buffer *buffer)
{
@@ -158,9 +166,17 @@ buffer_get_int64(Buffer *buffer)
}
/*
- * Stores an integer in the buffer in 4 bytes, msb first.
+ * Stores integers in the buffer, msb first.
*/
void
+buffer_put_short(Buffer *buffer, u_short value)
+{
+ char buf[2];
+ PUT_16BIT(buf, value);
+ buffer_append(buffer, buf, 2);
+}
+
+void
buffer_put_int(Buffer *buffer, u_int value)
{
char buf[4];
@@ -192,7 +208,7 @@ buffer_get_string(Buffer *buffer, u_int *length_ptr)
/* Get the length. */
len = buffer_get_int(buffer);
if (len > 256 * 1024)
- fatal("Received packet with bad string length %d", len);
+ fatal("buffer_get_string: bad string length %d", len);
/* Allocate space for the string. Add one byte for a null character. */
value = xmalloc(len + 1);
/* Get the string. */
@@ -217,6 +233,8 @@ buffer_put_string(Buffer *buffer, const void *buf, u_int len)
void
buffer_put_cstring(Buffer *buffer, const char *s)
{
+ if (s == NULL)
+ fatal("buffer_put_cstring: s == NULL");
buffer_put_string(buffer, s, strlen(s));
}
diff --git a/crypto/openssh/bufaux.h b/crypto/openssh/bufaux.h
index fda41ca..9355535 100644
--- a/crypto/openssh/bufaux.h
+++ b/crypto/openssh/bufaux.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bufaux.h,v 1.16 2002/03/04 17:27:39 stevesk Exp $ */
+/* $OpenBSD: bufaux.h,v 1.18 2002/04/20 09:14:58 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -23,6 +23,9 @@ void buffer_put_bignum2(Buffer *, BIGNUM *);
void buffer_get_bignum(Buffer *, BIGNUM *);
void buffer_get_bignum2(Buffer *, BIGNUM *);
+u_short buffer_get_short(Buffer *);
+void buffer_put_short(Buffer *, u_short);
+
u_int buffer_get_int(Buffer *);
void buffer_put_int(Buffer *, u_int);
@@ -36,4 +39,7 @@ void *buffer_get_string(Buffer *, u_int *);
void buffer_put_string(Buffer *, const void *, u_int);
void buffer_put_cstring(Buffer *, const char *);
+#define buffer_skip_string(b) \
+ do { u_int l = buffer_get_int(b); buffer_consume(b, l); } while(0)
+
#endif /* BUFAUX_H */
diff --git a/crypto/openssh/canohost.c b/crypto/openssh/canohost.c
index 65342e9..81a47f2 100644
--- a/crypto/openssh/canohost.c
+++ b/crypto/openssh/canohost.c
@@ -12,7 +12,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: canohost.c,v 1.31 2002/02/27 21:23:13 stevesk Exp $");
+RCSID("$OpenBSD: canohost.c,v 1.32 2002/06/11 08:11:45 itojun Exp $");
#include "packet.h"
#include "xmalloc.h"
@@ -42,13 +42,14 @@ get_remote_hostname(int socket, int verify_reverse_mapping)
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
- if (from.ss_family == AF_INET)
- check_ip_options(socket, ntop);
if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
NULL, 0, NI_NUMERICHOST) != 0)
fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
+ if (from.ss_family == AF_INET)
+ check_ip_options(socket, ntop);
+
debug3("Trying to reverse map address %.100s.", ntop);
/* Map the IP address to a host name. */
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
diff --git a/crypto/openssh/channels.c b/crypto/openssh/channels.c
index 841a899..a1b2305 100644
--- a/crypto/openssh/channels.c
+++ b/crypto/openssh/channels.c
@@ -39,14 +39,13 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: channels.c,v 1.171 2002/03/04 19:37:58 markus Exp $");
+RCSID("$OpenBSD: channels.c,v 1.175 2002/06/10 22:28:41 markus Exp $");
#include "ssh.h"
#include "ssh1.h"
#include "ssh2.h"
#include "packet.h"
#include "xmalloc.h"
-#include "uidswap.h"
#include "log.h"
#include "misc.h"
#include "channels.h"
@@ -129,10 +128,6 @@ static u_int x11_fake_data_len;
#define NUM_SOCKS 10
-/* Name and directory of socket for authentication agent forwarding. */
-static char *auth_sock_name = NULL;
-static char *auth_sock_dir = NULL;
-
/* AF_UNSPEC or AF_INET or AF_INET6 */
static int IPv4or6 = AF_UNSPEC;
@@ -706,7 +701,11 @@ channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset)
if (buffer_len(&c->output) > 0) {
FD_SET(c->wfd, writeset);
} else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
- chan_obuf_empty(c);
+ if (CHANNEL_EFD_OUTPUT_ACTIVE(c))
+ debug2("channel %d: obuf_empty delayed efd %d/(%d)",
+ c->self, c->efd, buffer_len(&c->extended));
+ else
+ chan_obuf_empty(c);
}
}
/** XXX check close conditions, too */
@@ -714,7 +713,8 @@ channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset)
if (c->extended_usage == CHAN_EXTENDED_WRITE &&
buffer_len(&c->extended) > 0)
FD_SET(c->efd, writeset);
- else if (c->extended_usage == CHAN_EXTENDED_READ &&
+ else if (!(c->flags & CHAN_EOF_SENT) &&
+ c->extended_usage == CHAN_EXTENDED_READ &&
buffer_len(&c->extended) < c->remote_window)
FD_SET(c->efd, readset);
}
@@ -1632,12 +1632,18 @@ channel_output_poll(void)
fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3");
/*
* input-buffer is empty and read-socket shutdown:
- * tell peer, that we will not send more data: send IEOF
+ * tell peer, that we will not send more data: send IEOF.
+ * hack for extended data: delay EOF if EFD still in use.
*/
- chan_ibuf_empty(c);
+ if (CHANNEL_EFD_INPUT_ACTIVE(c))
+ debug2("channel %d: ibuf_empty delayed efd %d/(%d)",
+ c->self, c->efd, buffer_len(&c->extended));
+ else
+ chan_ibuf_empty(c);
}
/* Send extended data, i.e. stderr */
if (compat20 &&
+ !(c->flags & CHAN_EOF_SENT) &&
c->remote_window > 0 &&
(len = buffer_len(&c->extended)) > 0 &&
c->extended_usage == CHAN_EXTENDED_READ) {
@@ -1726,6 +1732,13 @@ channel_input_extended_data(int type, u_int32_t seq, void *ctxt)
log("channel %d: ext data for non open", id);
return;
}
+ if (c->flags & CHAN_EOF_RCVD) {
+ if (datafellows & SSH_BUG_EXTEOF)
+ debug("channel %d: accepting ext data after eof", id);
+ else
+ packet_disconnect("Received extended_data after EOF "
+ "on channel %d.", id);
+ }
tcode = packet_get_int();
if (c->efd == -1 ||
c->extended_usage != CHAN_EXTENDED_WRITE ||
@@ -2108,7 +2121,7 @@ channel_request_remote_forwarding(u_short listen_port,
const char *address_to_bind = "0.0.0.0";
packet_start(SSH2_MSG_GLOBAL_REQUEST);
packet_put_cstring("tcpip-forward");
- packet_put_char(0); /* boolean: want reply */
+ packet_put_char(1); /* boolean: want reply */
packet_put_cstring(address_to_bind);
packet_put_int(listen_port);
packet_send();
@@ -2654,105 +2667,6 @@ auth_request_forwarding(void)
packet_write_wait();
}
-/*
- * Returns the name of the forwarded authentication socket. Returns NULL if
- * there is no forwarded authentication socket. The returned value points to
- * a static buffer.
- */
-
-char *
-auth_get_socket_name(void)
-{
- return auth_sock_name;
-}
-
-/* removes the agent forwarding socket */
-
-void
-auth_sock_cleanup_proc(void *_pw)
-{
- struct passwd *pw = _pw;
-
- if (auth_sock_name) {
- temporarily_use_uid(pw);
- unlink(auth_sock_name);
- rmdir(auth_sock_dir);
- auth_sock_name = NULL;
- restore_uid();
- }
-}
-
-/*
- * This is called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server.
- * This starts forwarding authentication requests.
- */
-
-int
-auth_input_request_forwarding(struct passwd * pw)
-{
- Channel *nc;
- int sock;
- struct sockaddr_un sunaddr;
-
- if (auth_get_socket_name() != NULL) {
- error("authentication forwarding requested twice.");
- return 0;
- }
-
- /* Temporarily drop privileged uid for mkdir/bind. */
- temporarily_use_uid(pw);
-
- /* Allocate a buffer for the socket name, and format the name. */
- auth_sock_name = xmalloc(MAXPATHLEN);
- auth_sock_dir = xmalloc(MAXPATHLEN);
- strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
-
- /* Create private directory for socket */
- if (mkdtemp(auth_sock_dir) == NULL) {
- packet_send_debug("Agent forwarding disabled: "
- "mkdtemp() failed: %.100s", strerror(errno));
- restore_uid();
- xfree(auth_sock_name);
- xfree(auth_sock_dir);
- auth_sock_name = NULL;
- auth_sock_dir = NULL;
- return 0;
- }
- snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%d",
- auth_sock_dir, (int) getpid());
-
- /* delete agent socket on fatal() */
- fatal_add_cleanup(auth_sock_cleanup_proc, pw);
-
- /* Create the socket. */
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock < 0)
- packet_disconnect("socket: %.100s", strerror(errno));
-
- /* Bind it to the name. */
- memset(&sunaddr, 0, sizeof(sunaddr));
- sunaddr.sun_family = AF_UNIX;
- strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
-
- if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0)
- packet_disconnect("bind: %.100s", strerror(errno));
-
- /* Restore the privileged uid. */
- restore_uid();
-
- /* Start listening on the socket. */
- if (listen(sock, 5) < 0)
- packet_disconnect("listen: %.100s", strerror(errno));
-
- /* Allocate a channel for the authentication agent socket. */
- nc = channel_new("auth socket",
- SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
- CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
- 0, xstrdup("auth socket"), 1);
- strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
- return 1;
-}
-
/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
void
diff --git a/crypto/openssh/channels.h b/crypto/openssh/channels.h
index 707d9a9..9ceff3e 100644
--- a/crypto/openssh/channels.h
+++ b/crypto/openssh/channels.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.h,v 1.65 2002/03/04 17:27:39 stevesk Exp $ */
+/* $OpenBSD: channels.h,v 1.68 2002/06/10 22:28:41 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -135,6 +135,18 @@ struct Channel {
#define CHAN_CLOSE_SENT 0x01
#define CHAN_CLOSE_RCVD 0x02
+#define CHAN_EOF_SENT 0x04
+#define CHAN_EOF_RCVD 0x08
+
+/* check whether 'efd' is still in use */
+#define CHANNEL_EFD_INPUT_ACTIVE(c) \
+ (compat20 && c->extended_usage == CHAN_EXTENDED_READ && \
+ (c->efd != -1 || \
+ buffer_len(&c->extended) > 0))
+#define CHANNEL_EFD_OUTPUT_ACTIVE(c) \
+ (compat20 && c->extended_usage == CHAN_EXTENDED_WRITE && \
+ ((c->efd != -1 && !(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD))) || \
+ buffer_len(&c->extended) > 0))
/* channel management */
@@ -201,9 +213,6 @@ void deny_input_open(int, u_int32_t, void *);
/* agent forwarding */
void auth_request_forwarding(void);
-char *auth_get_socket_name(void);
-void auth_sock_cleanup_proc(void *);
-int auth_input_request_forwarding(struct passwd *);
void auth_input_open_request(int, u_int32_t, void *);
/* channel close */
diff --git a/crypto/openssh/cipher.c b/crypto/openssh/cipher.c
index ce3f6f3..36d616a 100644
--- a/crypto/openssh/cipher.c
+++ b/crypto/openssh/cipher.c
@@ -35,25 +35,27 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: cipher.c,v 1.52 2002/02/18 13:05:32 markus Exp $");
+RCSID("$OpenBSD: cipher.c,v 1.59 2002/06/19 18:01:00 markus Exp $");
#include "xmalloc.h"
#include "log.h"
#include "cipher.h"
#include <openssl/md5.h>
-#include "rijndael.h"
-static EVP_CIPHER *evp_ssh1_3des(void);
-static EVP_CIPHER *evp_ssh1_bf(void);
-static EVP_CIPHER *evp_rijndael(void);
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+#include "rijndael.h"
+static const EVP_CIPHER *evp_rijndael(void);
+#endif
+static const EVP_CIPHER *evp_ssh1_3des(void);
+static const EVP_CIPHER *evp_ssh1_bf(void);
struct Cipher {
char *name;
int number; /* for ssh1 only */
u_int block_size;
u_int key_len;
- EVP_CIPHER *(*evptype)(void);
+ const EVP_CIPHER *(*evptype)(void);
} ciphers[] = {
{ "none", SSH_CIPHER_NONE, 8, 0, EVP_enc_null },
{ "des", SSH_CIPHER_DES, 8, 8, EVP_des_cbc },
@@ -64,25 +66,40 @@ struct Cipher {
{ "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_bf_cbc },
{ "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_cast5_cbc },
{ "arcfour", SSH_CIPHER_SSH2, 8, 16, EVP_rc4 },
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
{ "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, evp_rijndael },
{ "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, evp_rijndael },
{ "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, evp_rijndael },
+ { "rijndael-cbc@lysator.liu.se",
+ SSH_CIPHER_SSH2, 16, 32, evp_rijndael },
+#else
+ { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, EVP_aes_128_cbc },
+ { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, EVP_aes_192_cbc },
+ { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc },
+ { "rijndael-cbc@lysator.liu.se",
+ SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc },
+#endif
{ NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL }
};
/*--*/
-u_int
+u_int
cipher_blocksize(Cipher *c)
{
return (c->block_size);
}
-u_int
+u_int
cipher_keylen(Cipher *c)
{
return (c->key_len);
}
+u_int
+cipher_get_number(Cipher *c)
+{
+ return (c->number);
+}
u_int
cipher_mask_ssh1(int client)
@@ -333,7 +350,7 @@ ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
}
return (1);
}
-static EVP_CIPHER *
+static const EVP_CIPHER *
evp_ssh1_3des(void)
{
static EVP_CIPHER ssh1_3des;
@@ -383,7 +400,7 @@ bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len)
swap_bytes(out, out, len);
return (ret);
}
-static EVP_CIPHER *
+static const EVP_CIPHER *
evp_ssh1_bf(void)
{
static EVP_CIPHER ssh1_bf;
@@ -396,6 +413,7 @@ evp_ssh1_bf(void)
return (&ssh1_bf);
}
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
/* RIJNDAEL */
#define RIJNDAEL_BLOCKSIZE 16
struct ssh_rijndael_ctx
@@ -481,7 +499,7 @@ ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
}
return (1);
}
-static EVP_CIPHER *
+static const EVP_CIPHER *
evp_rijndael(void)
{
static EVP_CIPHER rijndal_cbc;
@@ -498,3 +516,155 @@ evp_rijndael(void)
EVP_CIPH_ALWAYS_CALL_INIT;
return (&rijndal_cbc);
}
+#endif
+
+/*
+ * Exports an IV from the CipherContext required to export the key
+ * state back from the unprivileged child to the privileged parent
+ * process.
+ */
+
+int
+cipher_get_keyiv_len(CipherContext *cc)
+{
+ Cipher *c = cc->cipher;
+ int ivlen;
+
+ if (c->number == SSH_CIPHER_3DES)
+ ivlen = 24;
+ else
+ ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
+ return (ivlen);
+}
+
+void
+cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
+{
+ Cipher *c = cc->cipher;
+ u_char *civ = NULL;
+ int evplen;
+
+ switch (c->number) {
+ case SSH_CIPHER_SSH2:
+ case SSH_CIPHER_DES:
+ case SSH_CIPHER_BLOWFISH:
+ evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
+ if (evplen == 0)
+ return;
+ if (evplen != len)
+ fatal("%s: wrong iv length %d != %d", __func__,
+ evplen, len);
+
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+ if (c->evptype == evp_rijndael) {
+ struct ssh_rijndael_ctx *aesc;
+
+ aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
+ if (aesc == NULL)
+ fatal("%s: no rijndael context", __func__);
+ civ = aesc->r_iv;
+ } else
+#endif
+ {
+ civ = cc->evp.iv;
+ }
+ break;
+ case SSH_CIPHER_3DES: {
+ struct ssh1_3des_ctx *desc;
+ if (len != 24)
+ fatal("%s: bad 3des iv length: %d", __func__, len);
+ desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
+ if (desc == NULL)
+ fatal("%s: no 3des context", __func__);
+ debug3("%s: Copying 3DES IV", __func__);
+ memcpy(iv, desc->k1.iv, 8);
+ memcpy(iv + 8, desc->k2.iv, 8);
+ memcpy(iv + 16, desc->k3.iv, 8);
+ return;
+ }
+ default:
+ fatal("%s: bad cipher %d", __func__, c->number);
+ }
+ memcpy(iv, civ, len);
+}
+
+void
+cipher_set_keyiv(CipherContext *cc, u_char *iv)
+{
+ Cipher *c = cc->cipher;
+ u_char *div = NULL;
+ int evplen = 0;
+
+ switch (c->number) {
+ case SSH_CIPHER_SSH2:
+ case SSH_CIPHER_DES:
+ case SSH_CIPHER_BLOWFISH:
+ evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
+ if (evplen == 0)
+ return;
+
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+ if (c->evptype == evp_rijndael) {
+ struct ssh_rijndael_ctx *aesc;
+
+ aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
+ if (aesc == NULL)
+ fatal("%s: no rijndael context", __func__);
+ div = aesc->r_iv;
+ } else
+#endif
+ {
+ div = cc->evp.iv;
+ }
+ break;
+ case SSH_CIPHER_3DES: {
+ struct ssh1_3des_ctx *desc;
+ desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
+ if (desc == NULL)
+ fatal("%s: no 3des context", __func__);
+ debug3("%s: Installed 3DES IV", __func__);
+ memcpy(desc->k1.iv, iv, 8);
+ memcpy(desc->k2.iv, iv + 8, 8);
+ memcpy(desc->k3.iv, iv + 16, 8);
+ return;
+ }
+ default:
+ fatal("%s: bad cipher %d", __func__, c->number);
+ }
+ memcpy(div, iv, evplen);
+}
+
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+#define EVP_X_STATE(evp) &(evp).c
+#define EVP_X_STATE_LEN(evp) sizeof((evp).c)
+#else
+#define EVP_X_STATE(evp) (evp).cipher_data
+#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size
+#endif
+
+int
+cipher_get_keycontext(CipherContext *cc, u_char *dat)
+{
+ Cipher *c = cc->cipher;
+ int plen = 0;
+
+ if (c->evptype == EVP_rc4) {
+ plen = EVP_X_STATE_LEN(cc->evp);
+ if (dat == NULL)
+ return (plen);
+ memcpy(dat, EVP_X_STATE(cc->evp), plen);
+ }
+ return (plen);
+}
+
+void
+cipher_set_keycontext(CipherContext *cc, u_char *dat)
+{
+ Cipher *c = cc->cipher;
+ int plen;
+
+ if (c->evptype == EVP_rc4) {
+ plen = EVP_X_STATE_LEN(cc->evp);
+ memcpy(EVP_X_STATE(cc->evp), dat, plen);
+ }
+}
diff --git a/crypto/openssh/cipher.h b/crypto/openssh/cipher.h
index b3b0303..fc7f6dd 100644
--- a/crypto/openssh/cipher.h
+++ b/crypto/openssh/cipher.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cipher.h,v 1.32 2002/03/04 17:27:39 stevesk Exp $ */
+/* $OpenBSD: cipher.h,v 1.33 2002/03/18 17:13:15 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -81,4 +81,11 @@ void cipher_cleanup(CipherContext *);
void cipher_set_key_string(CipherContext *, Cipher *, const char *, int);
u_int cipher_blocksize(Cipher *);
u_int cipher_keylen(Cipher *);
+
+u_int cipher_get_number(Cipher *);
+void cipher_get_keyiv(CipherContext *, u_char *, u_int);
+void cipher_set_keyiv(CipherContext *, u_char *);
+int cipher_get_keyiv_len(CipherContext *);
+int cipher_get_keycontext(CipherContext *, u_char *);
+void cipher_set_keycontext(CipherContext *, u_char *);
#endif /* CIPHER_H */
diff --git a/crypto/openssh/clientloop.c b/crypto/openssh/clientloop.c
index 65a6682..75d24ac 100644
--- a/crypto/openssh/clientloop.c
+++ b/crypto/openssh/clientloop.c
@@ -59,7 +59,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: clientloop.c,v 1.96 2002/02/06 14:55:15 markus Exp $");
+RCSID("$OpenBSD: clientloop.c,v 1.101 2002/06/09 13:32:01 markus Exp $");
#include "ssh.h"
#include "ssh1.h"
@@ -81,6 +81,7 @@ RCSID("$OpenBSD: clientloop.c,v 1.96 2002/02/06 14:55:15 markus Exp $");
#include "atomicio.h"
#include "sshtty.h"
#include "misc.h"
+#include "readpass.h"
/* import options */
extern Options options;
@@ -470,6 +471,67 @@ client_process_net_input(fd_set * readset)
}
}
+static void
+process_cmdline(void)
+{
+ void (*handler)(int);
+ char *s, *cmd;
+ u_short fwd_port, fwd_host_port;
+ char buf[1024], sfwd_port[6], sfwd_host_port[6];
+ int local = 0;
+
+ leave_raw_mode();
+ handler = signal(SIGINT, SIG_IGN);
+ cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
+ if (s == NULL)
+ goto out;
+ while (*s && isspace(*s))
+ s++;
+ if (*s == 0)
+ goto out;
+ if (strlen(s) < 2 || s[0] != '-' || !(s[1] == 'L' || s[1] == 'R')) {
+ log("Invalid command.");
+ goto out;
+ }
+ if (s[1] == 'L')
+ local = 1;
+ if (!local && !compat20) {
+ log("Not supported for SSH protocol version 1.");
+ goto out;
+ }
+ s += 2;
+ while (*s && isspace(*s))
+ s++;
+
+ if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]",
+ sfwd_port, buf, sfwd_host_port) != 3 &&
+ sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]",
+ sfwd_port, buf, sfwd_host_port) != 3) {
+ log("Bad forwarding specification.");
+ goto out;
+ }
+ if ((fwd_port = a2port(sfwd_port)) == 0 ||
+ (fwd_host_port = a2port(sfwd_host_port)) == 0) {
+ log("Bad forwarding port(s).");
+ goto out;
+ }
+ if (local) {
+ if (channel_setup_local_fwd_listener(fwd_port, buf,
+ fwd_host_port, options.gateway_ports) < 0) {
+ log("Port forwarding failed.");
+ goto out;
+ }
+ } else
+ channel_request_remote_forwarding(fwd_port, buf,
+ fwd_host_port);
+ log("Forwarding port.");
+out:
+ signal(SIGINT, handler);
+ enter_raw_mode();
+ if (cmd)
+ xfree(cmd);
+}
+
/* process the characters one by one */
static int
process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
@@ -574,6 +636,7 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
"%c?\r\n\
Supported escape sequences:\r\n\
~. - terminate connection\r\n\
+~C - open a command line\r\n\
~R - Request rekey (SSH protocol 2 only)\r\n\
~^Z - suspend ssh\r\n\
~# - list forwarded connections\r\n\
@@ -593,6 +656,10 @@ Supported escape sequences:\r\n\
xfree(s);
continue;
+ case 'C':
+ process_cmdline();
+ continue;
+
default:
if (ch != escape_char) {
buffer_put_char(bin, escape_char);
@@ -1247,6 +1314,7 @@ static void
client_init_dispatch_20(void)
{
dispatch_init(&dispatch_protocol_error);
+
dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
@@ -1260,6 +1328,10 @@ client_init_dispatch_20(void)
/* rekeying */
dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
+
+ /* global request reply messages */
+ dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply);
+ dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
}
static void
client_init_dispatch_13(void)
diff --git a/crypto/openssh/clientloop.h b/crypto/openssh/clientloop.h
index 1bc9a95..8056a40 100644
--- a/crypto/openssh/clientloop.h
+++ b/crypto/openssh/clientloop.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.h,v 1.6 2001/06/26 17:27:23 markus Exp $ */
+/* $OpenBSD: clientloop.h,v 1.7 2002/04/22 21:04:52 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -37,3 +37,4 @@
/* Client side main loop for the interactive session. */
int client_loop(int, int, int);
+void client_global_request_reply(int type, u_int32_t seq, void *ctxt);
diff --git a/crypto/openssh/compat.c b/crypto/openssh/compat.c
index 74d5ed8..406b47c 100644
--- a/crypto/openssh/compat.c
+++ b/crypto/openssh/compat.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: compat.c,v 1.61 2002/03/06 00:24:39 markus Exp $");
+RCSID("$OpenBSD: compat.c,v 1.63 2002/04/10 08:21:47 markus Exp $");
#include "buffer.h"
#include "packet.h"
@@ -61,20 +61,26 @@ compat_datafellows(const char *version)
"OpenSSH-2.1*,"
"OpenSSH_2.1*,"
"OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER|
- SSH_OLD_DHGEX|SSH_BUG_NOREKEY },
+ SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
+ SSH_BUG_EXTEOF},
{ "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES|
- SSH_OLD_DHGEX|SSH_BUG_NOREKEY},
+ SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
+ SSH_BUG_EXTEOF},
{ "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
- SSH_BUG_NOREKEY},
+ SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
{ "OpenSSH_2.5.0p1*,"
"OpenSSH_2.5.1p1*",
SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
- SSH_BUG_NOREKEY },
+ SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
{ "OpenSSH_2.5.0*,"
"OpenSSH_2.5.1*,"
- "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY },
- { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY },
- { "Sun_SSH_1.0*", SSH_BUG_NOREKEY },
+ "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
+ SSH_BUG_EXTEOF},
+ { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
+ { "OpenSSH_2.*,"
+ "OpenSSH_3.0*,"
+ "OpenSSH_3.1*", SSH_BUG_EXTEOF},
+ { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
{ "OpenSSH*", 0 },
{ "*MindTerm*", 0 },
{ "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
@@ -121,8 +127,12 @@ compat_datafellows(const char *version)
"1.2.19*,"
"1.2.20*,"
"1.2.21*,"
- "1.2.22*", SSH_BUG_IGNOREMSG },
- { "1.3.2*", SSH_BUG_IGNOREMSG }, /* f-secure */
+ "1.2.22*", SSH_BUG_IGNOREMSG|SSH_BUG_K5USER },
+ { "1.3.2*", /* F-Secure */
+ SSH_BUG_IGNOREMSG|SSH_BUG_K5USER },
+ { "1.2.1*,"
+ "1.2.2*,"
+ "1.2.3*", SSH_BUG_K5USER },
{ "*SSH Compatible Server*", /* Netscreen */
SSH_BUG_PASSWORDPAD },
{ "*OSU_0*,"
diff --git a/crypto/openssh/compat.h b/crypto/openssh/compat.h
index 0eeb782..7afca04 100644
--- a/crypto/openssh/compat.h
+++ b/crypto/openssh/compat.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: compat.h,v 1.30 2002/03/04 17:27:39 stevesk Exp $ */
+/* $OpenBSD: compat.h,v 1.32 2002/04/10 08:21:47 markus Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
@@ -52,6 +52,8 @@
#define SSH_BUG_OPENFAILURE 0x00020000
#define SSH_BUG_DERIVEKEY 0x00040000
#define SSH_BUG_DUMMYCHAN 0x00100000
+#define SSH_BUG_EXTEOF 0x00200000
+#define SSH_BUG_K5USER 0x00400000
void enable_compat13(void);
void enable_compat20(void);
diff --git a/crypto/openssh/compress.c b/crypto/openssh/compress.c
index 3badbf4..85a361d 100644
--- a/crypto/openssh/compress.c
+++ b/crypto/openssh/compress.c
@@ -12,17 +12,19 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: compress.c,v 1.17 2001/12/29 21:56:01 stevesk Exp $");
+RCSID("$OpenBSD: compress.c,v 1.19 2002/03/18 17:31:54 provos Exp $");
#include "log.h"
#include "buffer.h"
#include "zlib.h"
#include "compress.h"
-static z_stream incoming_stream;
-static z_stream outgoing_stream;
+z_stream incoming_stream;
+z_stream outgoing_stream;
static int compress_init_send_called = 0;
static int compress_init_recv_called = 0;
+static int inflate_failed = 0;
+static int deflate_failed = 0;
/*
* Initializes compression; level is compression level from 1 to 9
@@ -62,9 +64,9 @@ buffer_compress_uninit(void)
incoming_stream.total_out, incoming_stream.total_in,
incoming_stream.total_out == 0 ? 0.0 :
(double) incoming_stream.total_in / incoming_stream.total_out);
- if (compress_init_recv_called == 1)
+ if (compress_init_recv_called == 1 && inflate_failed == 0)
inflateEnd(&incoming_stream);
- if (compress_init_send_called == 1)
+ if (compress_init_send_called == 1 && deflate_failed == 0)
deflateEnd(&outgoing_stream);
}
@@ -106,6 +108,7 @@ buffer_compress(Buffer * input_buffer, Buffer * output_buffer)
sizeof(buf) - outgoing_stream.avail_out);
break;
default:
+ deflate_failed = 1;
fatal("buffer_compress: deflate returned %d", status);
/* NOTREACHED */
}
@@ -149,6 +152,7 @@ buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer)
*/
return;
default:
+ inflate_failed = 1;
fatal("buffer_uncompress: inflate returned %d", status);
/* NOTREACHED */
}
diff --git a/crypto/openssh/kex.c b/crypto/openssh/kex.c
index bf8fd95..d079ab0 100644
--- a/crypto/openssh/kex.c
+++ b/crypto/openssh/kex.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: kex.c,v 1.47 2002/02/28 15:46:33 markus Exp $");
+RCSID("$OpenBSD: kex.c,v 1.50 2002/05/15 15:47:49 mouring Exp $");
#include <openssl/crypto.h>
@@ -40,9 +40,15 @@ RCSID("$OpenBSD: kex.c,v 1.47 2002/02/28 15:46:33 markus Exp $");
#include "mac.h"
#include "match.h"
#include "dispatch.h"
+#include "monitor.h"
#define KEX_COOKIE_LEN 16
+/* Use privilege separation for sshd */
+int use_privsep;
+struct monitor *pmonitor;
+
+
/* prototype */
static void kex_kexinit_finish(Kex *);
static void kex_choose_conf(Kex *);
@@ -51,16 +57,15 @@ static void kex_choose_conf(Kex *);
static void
kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
{
- u_int32_t rand = 0;
int i;
buffer_clear(b);
- for (i = 0; i < KEX_COOKIE_LEN; i++) {
- if (i % 4 == 0)
- rand = arc4random();
- buffer_put_char(b, rand & 0xff);
- rand >>= 8;
- }
+ /*
+ * add a dummy cookie, the cookie will be overwritten by
+ * kex_send_kexinit(), each time a kexinit is set
+ */
+ for (i = 0; i < KEX_COOKIE_LEN; i++)
+ buffer_put_char(b, 0);
for (i = 0; i < PROPOSAL_MAX; i++)
buffer_put_cstring(b, proposal[i]);
buffer_put_char(b, 0); /* first_kex_packet_follows */
@@ -146,6 +151,10 @@ kex_finish(Kex *kex)
void
kex_send_kexinit(Kex *kex)
{
+ u_int32_t rand = 0;
+ u_char *cookie;
+ int i;
+
if (kex == NULL) {
error("kex_send_kexinit: no kex, cannot rekey");
return;
@@ -155,6 +164,17 @@ kex_send_kexinit(Kex *kex)
return;
}
kex->done = 0;
+
+ /* generate a random cookie */
+ if (buffer_len(&kex->my) < KEX_COOKIE_LEN)
+ fatal("kex_send_kexinit: kex proposal too short");
+ cookie = buffer_ptr(&kex->my);
+ for (i = 0; i < KEX_COOKIE_LEN; i++) {
+ if (i % 4 == 0)
+ rand = arc4random();
+ cookie[i] = rand;
+ rand >>= 8;
+ }
packet_start(SSH2_MSG_KEXINIT);
packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my));
packet_send();
diff --git a/crypto/openssh/kex.h b/crypto/openssh/kex.h
index 755bf33..12edcdc 100644
--- a/crypto/openssh/kex.h
+++ b/crypto/openssh/kex.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.h,v 1.29 2002/02/14 23:41:01 markus Exp $ */
+/* $OpenBSD: kex.h,v 1.31 2002/05/16 22:02:50 markus Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -79,7 +79,7 @@ struct Enc {
struct Mac {
char *name;
int enabled;
- EVP_MD *md;
+ const EVP_MD *md;
int mac_len;
u_char *key;
int key_len;
@@ -111,6 +111,7 @@ struct Kex {
char *server_version_string;
int (*verify_host_key)(Key *);
Key *(*load_host_key)(int);
+ int (*host_key_index)(Key *);
};
Kex *kex_setup(char *[PROPOSAL_MAX]);
diff --git a/crypto/openssh/kexdh.c b/crypto/openssh/kexdh.c
index eaf497c..1e91e25 100644
--- a/crypto/openssh/kexdh.c
+++ b/crypto/openssh/kexdh.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: kexdh.c,v 1.17 2002/02/28 15:46:33 markus Exp $");
+RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $");
#include <openssl/crypto.h>
#include <openssl/bn.h>
@@ -37,6 +37,7 @@ RCSID("$OpenBSD: kexdh.c,v 1.17 2002/02/28 15:46:33 markus Exp $");
#include "packet.h"
#include "dh.h"
#include "ssh2.h"
+#include "monitor_wrap.h"
static u_char *
kex_dh_hash(
@@ -275,7 +276,7 @@ kexdh_server(Kex *kex)
/* sign H */
/* XXX hashlen depends on KEX */
- key_sign(server_host_key, &signature, &slen, hash, 20);
+ PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20));
/* destroy_sensitive_data(); */
diff --git a/crypto/openssh/kexgex.c b/crypto/openssh/kexgex.c
index 61896e6..2d4a581 100644
--- a/crypto/openssh/kexgex.c
+++ b/crypto/openssh/kexgex.c
@@ -24,7 +24,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: kexgex.c,v 1.20 2002/02/28 15:46:33 markus Exp $");
+RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $");
#include <openssl/bn.h>
@@ -38,6 +38,7 @@ RCSID("$OpenBSD: kexgex.c,v 1.20 2002/02/28 15:46:33 markus Exp $");
#include "dh.h"
#include "ssh2.h"
#include "compat.h"
+#include "monitor_wrap.h"
static u_char *
kexgex_hash(
@@ -259,7 +260,7 @@ kexgex_server(Kex *kex)
{
BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
Key *server_host_key;
- DH *dh = dh;
+ DH *dh;
u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
u_int sbloblen, klen, kout, slen;
int min = -1, max = -1, nbits = -1, type;
@@ -296,7 +297,8 @@ kexgex_server(Kex *kex)
fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d",
min, nbits, max);
- dh = choose_dh(min, nbits, max);
+ /* Contact privileged parent */
+ dh = PRIVSEP(choose_dh(min, nbits, max));
if (dh == NULL)
packet_disconnect("Protocol error: no matching DH grp found");
@@ -379,7 +381,7 @@ kexgex_server(Kex *kex)
/* sign H */
/* XXX hashlen depends on KEX */
- key_sign(server_host_key, &signature, &slen, hash, 20);
+ PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20));
/* destroy_sensitive_data(); */
@@ -390,6 +392,7 @@ kexgex_server(Kex *kex)
packet_put_bignum2(dh->pub_key); /* f */
packet_put_string(signature, slen);
packet_send();
+
xfree(signature);
xfree(server_host_key_blob);
/* have keys, free DH */
diff --git a/crypto/openssh/key.c b/crypto/openssh/key.c
index cda9157..2d850c8 100644
--- a/crypto/openssh/key.c
+++ b/crypto/openssh/key.c
@@ -32,7 +32,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
-RCSID("$OpenBSD: key.c,v 1.41 2002/02/28 15:46:33 markus Exp $");
+RCSID("$OpenBSD: key.c,v 1.44 2002/05/31 13:16:48 markus Exp $");
#include <openssl/evp.h>
@@ -779,6 +779,10 @@ key_sign(
}
}
+/*
+ * key_verify returns 1 for a correct signature, 0 for an incorrect signature
+ * and -1 on error.
+ */
int
key_verify(
Key *key,
@@ -801,3 +805,46 @@ key_verify(
break;
}
}
+
+/* Converts a private to a public key */
+
+Key *
+key_demote(Key *k)
+{
+ Key *pk;
+
+ pk = xmalloc(sizeof(*pk));
+ pk->type = k->type;
+ pk->flags = k->flags;
+ pk->dsa = NULL;
+ pk->rsa = NULL;
+
+ switch (k->type) {
+ case KEY_RSA1:
+ case KEY_RSA:
+ if ((pk->rsa = RSA_new()) == NULL)
+ fatal("key_demote: RSA_new failed");
+ if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL)
+ fatal("key_demote: BN_dup failed");
+ if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
+ fatal("key_demote: BN_dup failed");
+ break;
+ case KEY_DSA:
+ if ((pk->dsa = DSA_new()) == NULL)
+ fatal("key_demote: DSA_new failed");
+ if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL)
+ fatal("key_demote: BN_dup failed");
+ if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL)
+ fatal("key_demote: BN_dup failed");
+ if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL)
+ fatal("key_demote: BN_dup failed");
+ if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL)
+ fatal("key_demote: BN_dup failed");
+ break;
+ default:
+ fatal("key_free: bad key type %d", k->type);
+ break;
+ }
+
+ return (pk);
+}
diff --git a/crypto/openssh/key.h b/crypto/openssh/key.h
index a225773..8d1fa41 100644
--- a/crypto/openssh/key.h
+++ b/crypto/openssh/key.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: key.h,v 1.18 2002/02/24 19:14:59 markus Exp $ */
+/* $OpenBSD: key.h,v 1.19 2002/03/18 17:23:31 markus Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -58,6 +58,7 @@ struct Key {
Key *key_new(int);
Key *key_new_private(int);
void key_free(Key *);
+Key *key_demote(Key *);
int key_equal(Key *, Key *);
char *key_fingerprint(Key *, enum fp_type, enum fp_rep);
char *key_type(Key *);
diff --git a/crypto/openssh/lib/Makefile b/crypto/openssh/lib/Makefile
index 369cf90..ac950a9 100644
--- a/crypto/openssh/lib/Makefile
+++ b/crypto/openssh/lib/Makefile
@@ -1,15 +1,15 @@
-# $OpenBSD: Makefile,v 1.31 2002/02/22 12:20:34 markus Exp $
+# $OpenBSD: Makefile,v 1.36 2002/06/11 15:23:29 hin Exp $
.PATH: ${.CURDIR}/..
LIB= ssh
-SRCS= authfd.c authfile.c bufaux.c buffer.c canohost.c channels.c \
+SRCS= authfd.c authfile.c bufaux.c buffer.c canohost.c channels.c \
cipher.c compat.c compress.c crc32.c deattack.c fatal.c \
hostfile.c log.c match.c mpaux.c nchan.c packet.c readpass.c \
- rsa.c tildexpand.c ttymodes.c uidswap.c xmalloc.c atomicio.c \
+ rsa.c tildexpand.c ttymodes.c xmalloc.c atomicio.c \
key.c dispatch.c kex.c mac.c uuencode.c misc.c \
rijndael.c ssh-dss.c ssh-rsa.c dh.c kexdh.c kexgex.c \
- scard.c
+ scard.c monitor_wrap.c monitor_fdpass.c msg.c
DEBUGLIBS= no
NOPROFILE= yes
@@ -20,6 +20,10 @@ install:
.include <bsd.own.mk>
+.if (${KERBEROS5:L} == "yes")
+CFLAGS+= -DKRB5 -I${DESTDIR}/usr/include/kerberosV
+.endif # KERBEROS5
+
.if (${KERBEROS:L} == "yes")
CFLAGS+= -DKRB4 -I${DESTDIR}/usr/include/kerberosIV
.if (${AFS:L} == "yes")
@@ -28,8 +32,4 @@ SRCS+= radix.c
.endif # AFS
.endif # KERBEROS
-.if (${KERBEROS5:L} == "yes")
-CFLAGS+= -DKRB5 -I${DESTDIR}/usr/include/kerberosV
-.endif # KERBEROS5
-
.include <bsd.lib.mk>
diff --git a/crypto/openssh/log.h b/crypto/openssh/log.h
index 276ba05..1c6a21c 100644
--- a/crypto/openssh/log.h
+++ b/crypto/openssh/log.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.h,v 1.6 2002/02/22 12:20:34 markus Exp $ */
+/* $OpenBSD: log.h,v 1.7 2002/05/19 20:54:52 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -28,7 +28,7 @@ typedef enum {
SYSLOG_FACILITY_LOCAL5,
SYSLOG_FACILITY_LOCAL6,
SYSLOG_FACILITY_LOCAL7,
- SYSLOG_FACILITY_NOT_SET = -1,
+ SYSLOG_FACILITY_NOT_SET = -1
} SyslogFacility;
typedef enum {
@@ -40,7 +40,7 @@ typedef enum {
SYSLOG_LEVEL_DEBUG1,
SYSLOG_LEVEL_DEBUG2,
SYSLOG_LEVEL_DEBUG3,
- SYSLOG_LEVEL_NOT_SET = -1,
+ SYSLOG_LEVEL_NOT_SET = -1
} LogLevel;
void log_init(char *, LogLevel, SyslogFacility, int);
diff --git a/crypto/openssh/mac.c b/crypto/openssh/mac.c
index b250af2..ab9a03d 100644
--- a/crypto/openssh/mac.c
+++ b/crypto/openssh/mac.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: mac.c,v 1.4 2002/01/25 22:07:40 markus Exp $");
+RCSID("$OpenBSD: mac.c,v 1.5 2002/05/16 22:02:50 markus Exp $");
#include <openssl/hmac.h>
@@ -36,7 +36,7 @@ RCSID("$OpenBSD: mac.c,v 1.4 2002/01/25 22:07:40 markus Exp $");
struct {
char *name;
- EVP_MD * (*mdfunc)(void);
+ const EVP_MD * (*mdfunc)(void);
int truncatebits; /* truncate digest if != 0 */
} macs[] = {
{ "hmac-sha1", EVP_sha1, 0, },
diff --git a/crypto/openssh/misc.h b/crypto/openssh/misc.h
index d28b865..6d2869b 100644
--- a/crypto/openssh/misc.h
+++ b/crypto/openssh/misc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.h,v 1.11 2002/01/24 21:09:25 stevesk Exp $ */
+/* $OpenBSD: misc.h,v 1.12 2002/03/19 10:49:35 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -26,8 +26,8 @@ struct passwd *pwcopy(struct passwd *);
typedef struct arglist arglist;
struct arglist {
- char **list;
- int num;
- int nalloc;
+ char **list;
+ int num;
+ int nalloc;
};
void addargs(arglist *, char *, ...) __attribute__((format(printf, 2, 3)));
diff --git a/crypto/openssh/monitor.c b/crypto/openssh/monitor.c
new file mode 100644
index 0000000..4957be9
--- /dev/null
+++ b/crypto/openssh/monitor.c
@@ -0,0 +1,1498 @@
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * Copyright 2002 Markus Friedl <markus@openbsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: monitor.c,v 1.16 2002/06/21 05:50:51 djm Exp $");
+
+#include <openssl/dh.h>
+
+#ifdef SKEY
+#include <skey.h>
+#endif
+
+#include "ssh.h"
+#include "auth.h"
+#include "kex.h"
+#include "dh.h"
+#include "zlib.h"
+#include "packet.h"
+#include "auth-options.h"
+#include "sshpty.h"
+#include "channels.h"
+#include "session.h"
+#include "sshlogin.h"
+#include "canohost.h"
+#include "log.h"
+#include "servconf.h"
+#include "monitor.h"
+#include "monitor_mm.h"
+#include "monitor_wrap.h"
+#include "monitor_fdpass.h"
+#include "xmalloc.h"
+#include "misc.h"
+#include "buffer.h"
+#include "bufaux.h"
+#include "compat.h"
+#include "ssh2.h"
+#include "mpaux.h"
+
+/* Imports */
+extern ServerOptions options;
+extern u_int utmp_len;
+extern Newkeys *current_keys[];
+extern z_stream incoming_stream;
+extern z_stream outgoing_stream;
+extern u_char session_id[];
+extern Buffer input, output;
+extern Buffer auth_debug;
+extern int auth_debug_init;
+
+/* State exported from the child */
+
+struct {
+ z_stream incoming;
+ z_stream outgoing;
+ u_char *keyin;
+ u_int keyinlen;
+ u_char *keyout;
+ u_int keyoutlen;
+ u_char *ivin;
+ u_int ivinlen;
+ u_char *ivout;
+ u_int ivoutlen;
+ u_char *ssh1key;
+ u_int ssh1keylen;
+ int ssh1cipher;
+ int ssh1protoflags;
+ u_char *input;
+ u_int ilen;
+ u_char *output;
+ u_int olen;
+} child_state;
+
+/* Functions on the montior that answer unprivileged requests */
+
+int mm_answer_moduli(int, Buffer *);
+int mm_answer_sign(int, Buffer *);
+int mm_answer_pwnamallow(int, Buffer *);
+int mm_answer_auth2_read_banner(int, Buffer *);
+int mm_answer_authserv(int, Buffer *);
+int mm_answer_authpassword(int, Buffer *);
+int mm_answer_bsdauthquery(int, Buffer *);
+int mm_answer_bsdauthrespond(int, Buffer *);
+int mm_answer_skeyquery(int, Buffer *);
+int mm_answer_skeyrespond(int, Buffer *);
+int mm_answer_keyallowed(int, Buffer *);
+int mm_answer_keyverify(int, Buffer *);
+int mm_answer_pty(int, Buffer *);
+int mm_answer_pty_cleanup(int, Buffer *);
+int mm_answer_term(int, Buffer *);
+int mm_answer_rsa_keyallowed(int, Buffer *);
+int mm_answer_rsa_challenge(int, Buffer *);
+int mm_answer_rsa_response(int, Buffer *);
+int mm_answer_sesskey(int, Buffer *);
+int mm_answer_sessid(int, Buffer *);
+
+static Authctxt *authctxt;
+static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */
+
+/* local state for key verify */
+static u_char *key_blob = NULL;
+static u_int key_bloblen = 0;
+static int key_blobtype = MM_NOKEY;
+static u_char *hostbased_cuser = NULL;
+static u_char *hostbased_chost = NULL;
+static char *auth_method = "unknown";
+static int session_id2_len = 0;
+static u_char *session_id2 = NULL;
+
+struct mon_table {
+ enum monitor_reqtype type;
+ int flags;
+ int (*f)(int, Buffer *);
+};
+
+#define MON_ISAUTH 0x0004 /* Required for Authentication */
+#define MON_AUTHDECIDE 0x0008 /* Decides Authentication */
+#define MON_ONCE 0x0010 /* Disable after calling */
+
+#define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE)
+
+#define MON_PERMIT 0x1000 /* Request is permitted */
+
+struct mon_table mon_dispatch_proto20[] = {
+ {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
+ {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
+ {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
+ {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
+ {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
+ {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
+#ifdef BSD_AUTH
+ {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
+ {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond},
+#endif
+#ifdef SKEY
+ {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
+ {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
+#endif
+ {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
+ {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
+ {0, 0, NULL}
+};
+
+struct mon_table mon_dispatch_postauth20[] = {
+ {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
+ {MONITOR_REQ_SIGN, 0, mm_answer_sign},
+ {MONITOR_REQ_PTY, 0, mm_answer_pty},
+ {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
+ {MONITOR_REQ_TERM, 0, mm_answer_term},
+ {0, 0, NULL}
+};
+
+struct mon_table mon_dispatch_proto15[] = {
+ {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
+ {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey},
+ {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid},
+ {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
+ {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH, mm_answer_rsa_keyallowed},
+ {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
+ {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge},
+ {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response},
+#ifdef BSD_AUTH
+ {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
+ {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond},
+#endif
+#ifdef SKEY
+ {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
+ {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
+#endif
+ {0, 0, NULL}
+};
+
+struct mon_table mon_dispatch_postauth15[] = {
+ {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
+ {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
+ {MONITOR_REQ_TERM, 0, mm_answer_term},
+ {0, 0, NULL}
+};
+
+struct mon_table *mon_dispatch;
+
+/* Specifies if a certain message is allowed at the moment */
+
+static void
+monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit)
+{
+ while (ent->f != NULL) {
+ if (ent->type == type) {
+ ent->flags &= ~MON_PERMIT;
+ ent->flags |= permit ? MON_PERMIT : 0;
+ return;
+ }
+ ent++;
+ }
+}
+
+static void
+monitor_permit_authentications(int permit)
+{
+ struct mon_table *ent = mon_dispatch;
+
+ while (ent->f != NULL) {
+ if (ent->flags & MON_AUTH) {
+ ent->flags &= ~MON_PERMIT;
+ ent->flags |= permit ? MON_PERMIT : 0;
+ }
+ ent++;
+ }
+}
+
+Authctxt *
+monitor_child_preauth(struct monitor *pmonitor)
+{
+ struct mon_table *ent;
+ int authenticated = 0;
+
+ debug3("preauth child monitor started");
+
+ if (compat20) {
+ mon_dispatch = mon_dispatch_proto20;
+
+ /* Permit requests for moduli and signatures */
+ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+ } else {
+ mon_dispatch = mon_dispatch_proto15;
+
+ monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
+ }
+
+ authctxt = authctxt_new();
+
+ /* The first few requests do not require asynchronous access */
+ while (!authenticated) {
+ authenticated = monitor_read(pmonitor, mon_dispatch, &ent);
+ if (authenticated) {
+ if (!(ent->flags & MON_AUTHDECIDE))
+ fatal("%s: unexpected authentication from %d",
+ __func__, ent->type);
+ if (authctxt->pw->pw_uid == 0 &&
+ !auth_root_allowed(auth_method))
+ authenticated = 0;
+ }
+
+ if (ent->flags & MON_AUTHDECIDE) {
+ auth_log(authctxt, authenticated, auth_method,
+ compat20 ? " ssh2" : "");
+ if (!authenticated)
+ authctxt->failures++;
+ }
+ }
+
+ if (!authctxt->valid)
+ fatal("%s: authenticated invalid user", __func__);
+
+ debug("%s: %s has been authenticated by privileged process",
+ __func__, authctxt->user);
+
+ mm_get_keystate(pmonitor);
+
+ return (authctxt);
+}
+
+void
+monitor_child_postauth(struct monitor *pmonitor)
+{
+ if (compat20) {
+ mon_dispatch = mon_dispatch_postauth20;
+
+ /* Permit requests for moduli and signatures */
+ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
+
+ } else {
+ mon_dispatch = mon_dispatch_postauth15;
+ monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
+ }
+ if (!no_pty_flag) {
+ monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
+ }
+
+ for (;;)
+ monitor_read(pmonitor, mon_dispatch, NULL);
+}
+
+void
+monitor_sync(struct monitor *pmonitor)
+{
+ if (options.compression) {
+ /* The member allocation is not visible, so sync it */
+ mm_share_sync(&pmonitor->m_zlib, &pmonitor->m_zback);
+ }
+}
+
+int
+monitor_read(struct monitor *pmonitor, struct mon_table *ent,
+ struct mon_table **pent)
+{
+ Buffer m;
+ int ret;
+ u_char type;
+
+ buffer_init(&m);
+
+ mm_request_receive(pmonitor->m_sendfd, &m);
+ type = buffer_get_char(&m);
+
+ debug3("%s: checking request %d", __func__, type);
+
+ while (ent->f != NULL) {
+ if (ent->type == type)
+ break;
+ ent++;
+ }
+
+ if (ent->f != NULL) {
+ if (!(ent->flags & MON_PERMIT))
+ fatal("%s: unpermitted request %d", __func__,
+ type);
+ ret = (*ent->f)(pmonitor->m_sendfd, &m);
+ buffer_free(&m);
+
+ /* The child may use this request only once, disable it */
+ if (ent->flags & MON_ONCE) {
+ debug2("%s: %d used once, disabling now", __func__,
+ type);
+ ent->flags &= ~MON_PERMIT;
+ }
+
+ if (pent != NULL)
+ *pent = ent;
+
+ return ret;
+ }
+
+ fatal("%s: unsupported request: %d", __func__, type);
+
+ /* NOTREACHED */
+ return (-1);
+}
+
+/* allowed key state */
+static int
+monitor_allowed_key(u_char *blob, u_int bloblen)
+{
+ /* make sure key is allowed */
+ if (key_blob == NULL || key_bloblen != bloblen ||
+ memcmp(key_blob, blob, key_bloblen))
+ return (0);
+ return (1);
+}
+
+static void
+monitor_reset_key_state(void)
+{
+ /* reset state */
+ if (key_blob != NULL)
+ xfree(key_blob);
+ if (hostbased_cuser != NULL)
+ xfree(hostbased_cuser);
+ if (hostbased_chost != NULL)
+ xfree(hostbased_chost);
+ key_blob = NULL;
+ key_bloblen = 0;
+ key_blobtype = MM_NOKEY;
+ hostbased_cuser = NULL;
+ hostbased_chost = NULL;
+}
+
+int
+mm_answer_moduli(int socket, Buffer *m)
+{
+ DH *dh;
+ int min, want, max;
+
+ min = buffer_get_int(m);
+ want = buffer_get_int(m);
+ max = buffer_get_int(m);
+
+ debug3("%s: got parameters: %d %d %d",
+ __func__, min, want, max);
+ /* We need to check here, too, in case the child got corrupted */
+ if (max < min || want < min || max < want)
+ fatal("%s: bad parameters: %d %d %d",
+ __func__, min, want, max);
+
+ buffer_clear(m);
+
+ dh = choose_dh(min, want, max);
+ if (dh == NULL) {
+ buffer_put_char(m, 0);
+ return (0);
+ } else {
+ /* Send first bignum */
+ buffer_put_char(m, 1);
+ buffer_put_bignum2(m, dh->p);
+ buffer_put_bignum2(m, dh->g);
+
+ DH_free(dh);
+ }
+ mm_request_send(socket, MONITOR_ANS_MODULI, m);
+ return (0);
+}
+
+int
+mm_answer_sign(int socket, Buffer *m)
+{
+ Key *key;
+ u_char *p;
+ u_char *signature;
+ u_int siglen, datlen;
+ int keyid;
+
+ debug3("%s", __func__);
+
+ keyid = buffer_get_int(m);
+ p = buffer_get_string(m, &datlen);
+
+ if (datlen != 20)
+ fatal("%s: data length incorrect: %d", __func__, datlen);
+
+ /* save session id, it will be passed on the first call */
+ if (session_id2_len == 0) {
+ session_id2_len = datlen;
+ session_id2 = xmalloc(session_id2_len);
+ memcpy(session_id2, p, session_id2_len);
+ }
+
+ if ((key = get_hostkey_by_index(keyid)) == NULL)
+ fatal("%s: no hostkey from index %d", __func__, keyid);
+ if (key_sign(key, &signature, &siglen, p, datlen) < 0)
+ fatal("%s: key_sign failed", __func__);
+
+ debug3("%s: signature %p(%d)", __func__, signature, siglen);
+
+ buffer_clear(m);
+ buffer_put_string(m, signature, siglen);
+
+ xfree(p);
+ xfree(signature);
+
+ mm_request_send(socket, MONITOR_ANS_SIGN, m);
+
+ /* Turn on permissions for getpwnam */
+ monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
+
+ return (0);
+}
+
+/* Retrieves the password entry and also checks if the user is permitted */
+
+int
+mm_answer_pwnamallow(int socket, Buffer *m)
+{
+ char *login;
+ struct passwd *pwent;
+ int allowed = 0;
+
+ debug3("%s", __func__);
+
+ if (authctxt->attempt++ != 0)
+ fatal("%s: multiple attempts for getpwnam", __func__);
+
+ login = buffer_get_string(m, NULL);
+
+ pwent = getpwnamallow(login);
+
+ authctxt->user = xstrdup(login);
+ setproctitle("%s [priv]", pwent ? login : "unknown");
+ xfree(login);
+
+ buffer_clear(m);
+
+ if (pwent == NULL) {
+ buffer_put_char(m, 0);
+ goto out;
+ }
+
+ allowed = 1;
+ authctxt->pw = pwent;
+ authctxt->valid = 1;
+
+ buffer_put_char(m, 1);
+ buffer_put_string(m, pwent, sizeof(struct passwd));
+ buffer_put_cstring(m, pwent->pw_name);
+ buffer_put_cstring(m, "*");
+ buffer_put_cstring(m, pwent->pw_gecos);
+ buffer_put_cstring(m, pwent->pw_class);
+ buffer_put_cstring(m, pwent->pw_dir);
+ buffer_put_cstring(m, pwent->pw_shell);
+
+ out:
+ debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
+ mm_request_send(socket, MONITOR_ANS_PWNAM, m);
+
+ /* For SSHv1 allow authentication now */
+ if (!compat20)
+ monitor_permit_authentications(1);
+ else {
+ /* Allow service/style information on the auth context */
+ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
+ }
+
+
+ return (0);
+}
+
+int mm_answer_auth2_read_banner(int socket, Buffer *m)
+{
+ char *banner;
+
+ buffer_clear(m);
+ banner = auth2_read_banner();
+ buffer_put_cstring(m, banner != NULL ? banner : "");
+ mm_request_send(socket, MONITOR_ANS_AUTH2_READ_BANNER, m);
+
+ if (banner != NULL)
+ free(banner);
+
+ return (0);
+}
+
+int
+mm_answer_authserv(int socket, Buffer *m)
+{
+ monitor_permit_authentications(1);
+
+ authctxt->service = buffer_get_string(m, NULL);
+ authctxt->style = buffer_get_string(m, NULL);
+ debug3("%s: service=%s, style=%s",
+ __func__, authctxt->service, authctxt->style);
+
+ if (strlen(authctxt->style) == 0) {
+ xfree(authctxt->style);
+ authctxt->style = NULL;
+ }
+
+ return (0);
+}
+
+int
+mm_answer_authpassword(int socket, Buffer *m)
+{
+ static int call_count;
+ char *passwd;
+ int authenticated, plen;
+
+ passwd = buffer_get_string(m, &plen);
+ /* Only authenticate if the context is valid */
+ authenticated = options.password_authentication &&
+ authctxt->valid && auth_password(authctxt, passwd);
+ memset(passwd, 0, strlen(passwd));
+ xfree(passwd);
+
+ buffer_clear(m);
+ buffer_put_int(m, authenticated);
+
+ debug3("%s: sending result %d", __func__, authenticated);
+ mm_request_send(socket, MONITOR_ANS_AUTHPASSWORD, m);
+
+ call_count++;
+ if (plen == 0 && call_count == 1)
+ auth_method = "none";
+ else
+ auth_method = "password";
+
+ /* Causes monitor loop to terminate if authenticated */
+ return (authenticated);
+}
+
+#ifdef BSD_AUTH
+int
+mm_answer_bsdauthquery(int socket, Buffer *m)
+{
+ char *name, *infotxt;
+ u_int numprompts;
+ u_int *echo_on;
+ char **prompts;
+ int res;
+
+ res = bsdauth_query(authctxt, &name, &infotxt, &numprompts,
+ &prompts, &echo_on);
+
+ buffer_clear(m);
+ buffer_put_int(m, res);
+ if (res != -1)
+ buffer_put_cstring(m, prompts[0]);
+
+ debug3("%s: sending challenge res: %d", __func__, res);
+ mm_request_send(socket, MONITOR_ANS_BSDAUTHQUERY, m);
+
+ if (res != -1) {
+ xfree(name);
+ xfree(infotxt);
+ xfree(prompts);
+ xfree(echo_on);
+ }
+
+ return (0);
+}
+
+int
+mm_answer_bsdauthrespond(int socket, Buffer *m)
+{
+ char *response;
+ int authok;
+
+ if (authctxt->as == 0)
+ fatal("%s: no bsd auth session", __func__);
+
+ response = buffer_get_string(m, NULL);
+ authok = options.challenge_response_authentication &&
+ auth_userresponse(authctxt->as, response, 0);
+ authctxt->as = NULL;
+ debug3("%s: <%s> = <%d>", __func__, response, authok);
+ xfree(response);
+
+ buffer_clear(m);
+ buffer_put_int(m, authok);
+
+ debug3("%s: sending authenticated: %d", __func__, authok);
+ mm_request_send(socket, MONITOR_ANS_BSDAUTHRESPOND, m);
+
+ auth_method = "bsdauth";
+
+ return (authok != 0);
+}
+#endif
+
+#ifdef SKEY
+int
+mm_answer_skeyquery(int socket, Buffer *m)
+{
+ struct skey skey;
+ char challenge[1024];
+ int res;
+
+ res = skeychallenge(&skey, authctxt->user, challenge);
+
+ buffer_clear(m);
+ buffer_put_int(m, res);
+ if (res != -1)
+ buffer_put_cstring(m, challenge);
+
+ debug3("%s: sending challenge res: %d", __func__, res);
+ mm_request_send(socket, MONITOR_ANS_SKEYQUERY, m);
+
+ return (0);
+}
+
+int
+mm_answer_skeyrespond(int socket, Buffer *m)
+{
+ char *response;
+ int authok;
+
+ response = buffer_get_string(m, NULL);
+
+ authok = (options.challenge_response_authentication &&
+ authctxt->valid &&
+ skey_haskey(authctxt->pw->pw_name) == 0 &&
+ skey_passcheck(authctxt->pw->pw_name, response) != -1);
+
+ xfree(response);
+
+ buffer_clear(m);
+ buffer_put_int(m, authok);
+
+ debug3("%s: sending authenticated: %d", __func__, authok);
+ mm_request_send(socket, MONITOR_ANS_SKEYRESPOND, m);
+
+ auth_method = "skey";
+
+ return (authok != 0);
+}
+#endif
+
+static void
+mm_append_debug(Buffer *m)
+{
+ if (auth_debug_init && buffer_len(&auth_debug)) {
+ debug3("%s: Appending debug messages for child", __func__);
+ buffer_append(m, buffer_ptr(&auth_debug),
+ buffer_len(&auth_debug));
+ buffer_clear(&auth_debug);
+ }
+}
+
+int
+mm_answer_keyallowed(int socket, Buffer *m)
+{
+ Key *key;
+ u_char *cuser, *chost, *blob;
+ u_int bloblen;
+ enum mm_keytype type = 0;
+ int allowed = 0;
+
+ debug3("%s entering", __func__);
+
+ type = buffer_get_int(m);
+ cuser = buffer_get_string(m, NULL);
+ chost = buffer_get_string(m, NULL);
+ blob = buffer_get_string(m, &bloblen);
+
+ key = key_from_blob(blob, bloblen);
+
+ if ((compat20 && type == MM_RSAHOSTKEY) ||
+ (!compat20 && type != MM_RSAHOSTKEY))
+ fatal("%s: key type and protocol mismatch", __func__);
+
+ debug3("%s: key_from_blob: %p", __func__, key);
+
+ if (key != NULL && authctxt->pw != NULL) {
+ switch(type) {
+ case MM_USERKEY:
+ allowed = options.pubkey_authentication &&
+ user_key_allowed(authctxt->pw, key);
+ break;
+ case MM_HOSTKEY:
+ allowed = options.hostbased_authentication &&
+ hostbased_key_allowed(authctxt->pw,
+ cuser, chost, key);
+ break;
+ case MM_RSAHOSTKEY:
+ key->type = KEY_RSA1; /* XXX */
+ allowed = options.rhosts_rsa_authentication &&
+ auth_rhosts_rsa_key_allowed(authctxt->pw,
+ cuser, chost, key);
+ break;
+ default:
+ fatal("%s: unknown key type %d", __func__, type);
+ break;
+ }
+ key_free(key);
+ }
+
+ /* clear temporarily storage (used by verify) */
+ monitor_reset_key_state();
+
+ if (allowed) {
+ /* Save temporarily for comparison in verify */
+ key_blob = blob;
+ key_bloblen = bloblen;
+ key_blobtype = type;
+ hostbased_cuser = cuser;
+ hostbased_chost = chost;
+ }
+
+ debug3("%s: key %p is %s",
+ __func__, key, allowed ? "allowed" : "disallowed");
+
+ buffer_clear(m);
+ buffer_put_int(m, allowed);
+
+ mm_append_debug(m);
+
+ mm_request_send(socket, MONITOR_ANS_KEYALLOWED, m);
+
+ if (type == MM_RSAHOSTKEY)
+ monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
+
+ return (0);
+}
+
+static int
+monitor_valid_userblob(u_char *data, u_int datalen)
+{
+ Buffer b;
+ u_char *p;
+ u_int len;
+ int fail = 0;
+
+ buffer_init(&b);
+ buffer_append(&b, data, datalen);
+
+ if (datafellows & SSH_OLD_SESSIONID) {
+ p = buffer_ptr(&b);
+ len = buffer_len(&b);
+ if ((session_id2 == NULL) ||
+ (len < session_id2_len) ||
+ (memcmp(p, session_id2, session_id2_len) != 0))
+ fail++;
+ buffer_consume(&b, session_id2_len);
+ } else {
+ p = buffer_get_string(&b, &len);
+ if ((session_id2 == NULL) ||
+ (len != session_id2_len) ||
+ (memcmp(p, session_id2, session_id2_len) != 0))
+ fail++;
+ xfree(p);
+ }
+ if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
+ fail++;
+ p = buffer_get_string(&b, NULL);
+ if (strcmp(authctxt->user, p) != 0) {
+ log("wrong user name passed to monitor: expected %s != %.100s",
+ authctxt->user, p);
+ fail++;
+ }
+ xfree(p);
+ buffer_skip_string(&b);
+ if (datafellows & SSH_BUG_PKAUTH) {
+ if (!buffer_get_char(&b))
+ fail++;
+ } else {
+ p = buffer_get_string(&b, NULL);
+ if (strcmp("publickey", p) != 0)
+ fail++;
+ xfree(p);
+ if (!buffer_get_char(&b))
+ fail++;
+ buffer_skip_string(&b);
+ }
+ buffer_skip_string(&b);
+ if (buffer_len(&b) != 0)
+ fail++;
+ buffer_free(&b);
+ return (fail == 0);
+}
+
+static int
+monitor_valid_hostbasedblob(u_char *data, u_int datalen, u_char *cuser,
+ u_char *chost)
+{
+ Buffer b;
+ u_char *p;
+ u_int len;
+ int fail = 0;
+
+ buffer_init(&b);
+ buffer_append(&b, data, datalen);
+
+ p = buffer_get_string(&b, &len);
+ if ((session_id2 == NULL) ||
+ (len != session_id2_len) ||
+ (memcmp(p, session_id2, session_id2_len) != 0))
+ fail++;
+ xfree(p);
+
+ if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
+ fail++;
+ p = buffer_get_string(&b, NULL);
+ if (strcmp(authctxt->user, p) != 0) {
+ log("wrong user name passed to monitor: expected %s != %.100s",
+ authctxt->user, p);
+ fail++;
+ }
+ xfree(p);
+ buffer_skip_string(&b); /* service */
+ p = buffer_get_string(&b, NULL);
+ if (strcmp(p, "hostbased") != 0)
+ fail++;
+ xfree(p);
+ buffer_skip_string(&b); /* pkalg */
+ buffer_skip_string(&b); /* pkblob */
+
+ /* verify client host, strip trailing dot if necessary */
+ p = buffer_get_string(&b, NULL);
+ if (((len = strlen(p)) > 0) && p[len - 1] == '.')
+ p[len - 1] = '\0';
+ if (strcmp(p, chost) != 0)
+ fail++;
+ xfree(p);
+
+ /* verify client user */
+ p = buffer_get_string(&b, NULL);
+ if (strcmp(p, cuser) != 0)
+ fail++;
+ xfree(p);
+
+ if (buffer_len(&b) != 0)
+ fail++;
+ buffer_free(&b);
+ return (fail == 0);
+}
+
+int
+mm_answer_keyverify(int socket, Buffer *m)
+{
+ Key *key;
+ u_char *signature, *data, *blob;
+ u_int signaturelen, datalen, bloblen;
+ int verified = 0;
+ int valid_data = 0;
+
+ blob = buffer_get_string(m, &bloblen);
+ signature = buffer_get_string(m, &signaturelen);
+ data = buffer_get_string(m, &datalen);
+
+ if (hostbased_cuser == NULL || hostbased_chost == NULL ||
+ !monitor_allowed_key(blob, bloblen))
+ fatal("%s: bad key, not previously allowed", __func__);
+
+ key = key_from_blob(blob, bloblen);
+ if (key == NULL)
+ fatal("%s: bad public key blob", __func__);
+
+ switch (key_blobtype) {
+ case MM_USERKEY:
+ valid_data = monitor_valid_userblob(data, datalen);
+ break;
+ case MM_HOSTKEY:
+ valid_data = monitor_valid_hostbasedblob(data, datalen,
+ hostbased_cuser, hostbased_chost);
+ break;
+ default:
+ valid_data = 0;
+ break;
+ }
+ if (!valid_data)
+ fatal("%s: bad signature data blob", __func__);
+
+ verified = key_verify(key, signature, signaturelen, data, datalen);
+ debug3("%s: key %p signature %s",
+ __func__, key, verified ? "verified" : "unverified");
+
+ key_free(key);
+ xfree(blob);
+ xfree(signature);
+ xfree(data);
+
+ monitor_reset_key_state();
+
+ buffer_clear(m);
+ buffer_put_int(m, verified);
+ mm_request_send(socket, MONITOR_ANS_KEYVERIFY, m);
+
+ auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased";
+
+ return (verified);
+}
+
+static void
+mm_record_login(Session *s, struct passwd *pw)
+{
+ socklen_t fromlen;
+ struct sockaddr_storage from;
+
+ /*
+ * Get IP address of client. If the connection is not a socket, let
+ * the address be 0.0.0.0.
+ */
+ memset(&from, 0, sizeof(from));
+ if (packet_connection_is_on_socket()) {
+ fromlen = sizeof(from);
+ if (getpeername(packet_get_connection_in(),
+ (struct sockaddr *) & from, &fromlen) < 0) {
+ debug("getpeername: %.100s", strerror(errno));
+ fatal_cleanup();
+ }
+ }
+ /* Record that there was a login on that tty from the remote host. */
+ record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid,
+ get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping),
+ (struct sockaddr *)&from);
+}
+
+static void
+mm_session_close(Session *s)
+{
+ debug3("%s: session %d pid %d", __func__, s->self, s->pid);
+ if (s->ttyfd != -1) {
+ debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd);
+ fatal_remove_cleanup(session_pty_cleanup2, (void *)s);
+ session_pty_cleanup2(s);
+ }
+ s->used = 0;
+}
+
+int
+mm_answer_pty(int socket, Buffer *m)
+{
+ extern struct monitor *pmonitor;
+ Session *s;
+ int res, fd0;
+
+ debug3("%s entering", __func__);
+
+ buffer_clear(m);
+ s = session_new();
+ if (s == NULL)
+ goto error;
+ s->authctxt = authctxt;
+ s->pw = authctxt->pw;
+ s->pid = pmonitor->m_pid;
+ res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
+ if (res == 0)
+ goto error;
+ fatal_add_cleanup(session_pty_cleanup2, (void *)s);
+ pty_setowner(authctxt->pw, s->tty);
+
+ buffer_put_int(m, 1);
+ buffer_put_cstring(m, s->tty);
+ mm_request_send(socket, MONITOR_ANS_PTY, m);
+
+ mm_send_fd(socket, s->ptyfd);
+ mm_send_fd(socket, s->ttyfd);
+
+ /* We need to trick ttyslot */
+ if (dup2(s->ttyfd, 0) == -1)
+ fatal("%s: dup2", __func__);
+
+ mm_record_login(s, authctxt->pw);
+
+ /* Now we can close the file descriptor again */
+ close(0);
+
+ /* make sure nothing uses fd 0 */
+ if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0)
+ fatal("%s: open(/dev/null): %s", __func__, strerror(errno));
+ if (fd0 != 0)
+ error("%s: fd0 %d != 0", __func__, fd0);
+
+ /* slave is not needed */
+ close(s->ttyfd);
+ s->ttyfd = s->ptyfd;
+ /* no need to dup() because nobody closes ptyfd */
+ s->ptymaster = s->ptyfd;
+
+ debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd);
+
+ return (0);
+
+ error:
+ if (s != NULL)
+ mm_session_close(s);
+ buffer_put_int(m, 0);
+ mm_request_send(socket, MONITOR_ANS_PTY, m);
+ return (0);
+}
+
+int
+mm_answer_pty_cleanup(int socket, Buffer *m)
+{
+ Session *s;
+ char *tty;
+
+ debug3("%s entering", __func__);
+
+ tty = buffer_get_string(m, NULL);
+ if ((s = session_by_tty(tty)) != NULL)
+ mm_session_close(s);
+ buffer_clear(m);
+ xfree(tty);
+ return (0);
+}
+
+int
+mm_answer_sesskey(int socket, Buffer *m)
+{
+ BIGNUM *p;
+ int rsafail;
+
+ /* Turn off permissions */
+ monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
+
+ if ((p = BN_new()) == NULL)
+ fatal("%s: BN_new", __func__);
+
+ buffer_get_bignum2(m, p);
+
+ rsafail = ssh1_session_key(p);
+
+ buffer_clear(m);
+ buffer_put_int(m, rsafail);
+ buffer_put_bignum2(m, p);
+
+ BN_clear_free(p);
+
+ mm_request_send(socket, MONITOR_ANS_SESSKEY, m);
+
+ /* Turn on permissions for sessid passing */
+ monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1);
+
+ return (0);
+}
+
+int
+mm_answer_sessid(int socket, Buffer *m)
+{
+ int i;
+
+ debug3("%s entering", __func__);
+
+ if (buffer_len(m) != 16)
+ fatal("%s: bad ssh1 session id", __func__);
+ for (i = 0; i < 16; i++)
+ session_id[i] = buffer_get_char(m);
+
+ /* Turn on permissions for getpwnam */
+ monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
+
+ return (0);
+}
+
+int
+mm_answer_rsa_keyallowed(int socket, Buffer *m)
+{
+ BIGNUM *client_n;
+ Key *key = NULL;
+ u_char *blob = NULL;
+ u_int blen = 0;
+ int allowed = 0;
+
+ debug3("%s entering", __func__);
+
+ if (options.rsa_authentication && authctxt->valid) {
+ if ((client_n = BN_new()) == NULL)
+ fatal("%s: BN_new", __func__);
+ buffer_get_bignum2(m, client_n);
+ allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key);
+ BN_clear_free(client_n);
+ }
+ buffer_clear(m);
+ buffer_put_int(m, allowed);
+
+ /* clear temporarily storage (used by generate challenge) */
+ monitor_reset_key_state();
+
+ if (allowed && key != NULL) {
+ key->type = KEY_RSA; /* cheat for key_to_blob */
+ if (key_to_blob(key, &blob, &blen) == 0)
+ fatal("%s: key_to_blob failed", __func__);
+ buffer_put_string(m, blob, blen);
+
+ /* Save temporarily for comparison in verify */
+ key_blob = blob;
+ key_bloblen = blen;
+ key_blobtype = MM_RSAUSERKEY;
+ key_free(key);
+ }
+
+ mm_append_debug(m);
+
+ mm_request_send(socket, MONITOR_ANS_RSAKEYALLOWED, m);
+
+ monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
+ monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0);
+ return (0);
+}
+
+int
+mm_answer_rsa_challenge(int socket, Buffer *m)
+{
+ Key *key = NULL;
+ u_char *blob;
+ u_int blen;
+
+ debug3("%s entering", __func__);
+
+ if (!authctxt->valid)
+ fatal("%s: authctxt not valid", __func__);
+ blob = buffer_get_string(m, &blen);
+ if (!monitor_allowed_key(blob, blen))
+ fatal("%s: bad key, not previously allowed", __func__);
+ if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
+ fatal("%s: key type mismatch", __func__);
+ if ((key = key_from_blob(blob, blen)) == NULL)
+ fatal("%s: received bad key", __func__);
+
+ if (ssh1_challenge)
+ BN_clear_free(ssh1_challenge);
+ ssh1_challenge = auth_rsa_generate_challenge(key);
+
+ buffer_clear(m);
+ buffer_put_bignum2(m, ssh1_challenge);
+
+ debug3("%s sending reply", __func__);
+ mm_request_send(socket, MONITOR_ANS_RSACHALLENGE, m);
+
+ monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1);
+ return (0);
+}
+
+int
+mm_answer_rsa_response(int socket, Buffer *m)
+{
+ Key *key = NULL;
+ u_char *blob, *response;
+ u_int blen, len;
+ int success;
+
+ debug3("%s entering", __func__);
+
+ if (!authctxt->valid)
+ fatal("%s: authctxt not valid", __func__);
+ if (ssh1_challenge == NULL)
+ fatal("%s: no ssh1_challenge", __func__);
+
+ blob = buffer_get_string(m, &blen);
+ if (!monitor_allowed_key(blob, blen))
+ fatal("%s: bad key, not previously allowed", __func__);
+ if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
+ fatal("%s: key type mismatch: %d", __func__, key_blobtype);
+ if ((key = key_from_blob(blob, blen)) == NULL)
+ fatal("%s: received bad key", __func__);
+ response = buffer_get_string(m, &len);
+ if (len != 16)
+ fatal("%s: received bad response to challenge", __func__);
+ success = auth_rsa_verify_response(key, ssh1_challenge, response);
+
+ key_free(key);
+ xfree(response);
+
+ auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa";
+
+ /* reset state */
+ BN_clear_free(ssh1_challenge);
+ ssh1_challenge = NULL;
+ monitor_reset_key_state();
+
+ buffer_clear(m);
+ buffer_put_int(m, success);
+ mm_request_send(socket, MONITOR_ANS_RSARESPONSE, m);
+
+ return (success);
+}
+
+int
+mm_answer_term(int socket, Buffer *req)
+{
+ extern struct monitor *pmonitor;
+ int res, status;
+
+ debug3("%s: tearing down sessions", __func__);
+
+ /* The child is terminating */
+ session_destroy_all(&mm_session_close);
+
+ while (waitpid(pmonitor->m_pid, &status, 0) == -1)
+ if (errno != EINTR)
+ exit(1);
+
+ res = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
+
+ /* Terminate process */
+ exit (res);
+}
+
+void
+monitor_apply_keystate(struct monitor *pmonitor)
+{
+ if (compat20) {
+ set_newkeys(MODE_IN);
+ set_newkeys(MODE_OUT);
+ } else {
+ packet_set_protocol_flags(child_state.ssh1protoflags);
+ packet_set_encryption_key(child_state.ssh1key,
+ child_state.ssh1keylen, child_state.ssh1cipher);
+ xfree(child_state.ssh1key);
+ }
+
+ /* for rc4 and other stateful ciphers */
+ packet_set_keycontext(MODE_OUT, child_state.keyout);
+ xfree(child_state.keyout);
+ packet_set_keycontext(MODE_IN, child_state.keyin);
+ xfree(child_state.keyin);
+
+ if (!compat20) {
+ packet_set_iv(MODE_OUT, child_state.ivout);
+ xfree(child_state.ivout);
+ packet_set_iv(MODE_IN, child_state.ivin);
+ xfree(child_state.ivin);
+ }
+
+ memcpy(&incoming_stream, &child_state.incoming,
+ sizeof(incoming_stream));
+ memcpy(&outgoing_stream, &child_state.outgoing,
+ sizeof(outgoing_stream));
+
+ /* Update with new address */
+ if (options.compression)
+ mm_init_compression(pmonitor->m_zlib);
+
+ /* Network I/O buffers */
+ /* XXX inefficient for large buffers, need: buffer_init_from_string */
+ buffer_clear(&input);
+ buffer_append(&input, child_state.input, child_state.ilen);
+ memset(child_state.input, 0, child_state.ilen);
+ xfree(child_state.input);
+
+ buffer_clear(&output);
+ buffer_append(&output, child_state.output, child_state.olen);
+ memset(child_state.output, 0, child_state.olen);
+ xfree(child_state.output);
+}
+
+static Kex *
+mm_get_kex(Buffer *m)
+{
+ Kex *kex;
+ void *blob;
+ u_int bloblen;
+
+ kex = xmalloc(sizeof(*kex));
+ memset(kex, 0, sizeof(*kex));
+ kex->session_id = buffer_get_string(m, &kex->session_id_len);
+ if ((session_id2 == NULL) ||
+ (kex->session_id_len != session_id2_len) ||
+ (memcmp(kex->session_id, session_id2, session_id2_len) != 0))
+ fatal("mm_get_get: internal error: bad session id");
+ kex->we_need = buffer_get_int(m);
+ kex->server = 1;
+ kex->hostkey_type = buffer_get_int(m);
+ kex->kex_type = buffer_get_int(m);
+ blob = buffer_get_string(m, &bloblen);
+ buffer_init(&kex->my);
+ buffer_append(&kex->my, blob, bloblen);
+ xfree(blob);
+ blob = buffer_get_string(m, &bloblen);
+ buffer_init(&kex->peer);
+ buffer_append(&kex->peer, blob, bloblen);
+ xfree(blob);
+ kex->done = 1;
+ kex->flags = buffer_get_int(m);
+ kex->client_version_string = buffer_get_string(m, NULL);
+ kex->server_version_string = buffer_get_string(m, NULL);
+ kex->load_host_key=&get_hostkey_by_type;
+ kex->host_key_index=&get_hostkey_index;
+
+ return (kex);
+}
+
+/* This function requries careful sanity checking */
+
+void
+mm_get_keystate(struct monitor *pmonitor)
+{
+ Buffer m;
+ u_char *blob, *p;
+ u_int bloblen, plen;
+
+ debug3("%s: Waiting for new keys", __func__);
+
+ buffer_init(&m);
+ mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m);
+ if (!compat20) {
+ child_state.ssh1protoflags = buffer_get_int(&m);
+ child_state.ssh1cipher = buffer_get_int(&m);
+ child_state.ssh1key = buffer_get_string(&m,
+ &child_state.ssh1keylen);
+ child_state.ivout = buffer_get_string(&m,
+ &child_state.ivoutlen);
+ child_state.ivin = buffer_get_string(&m, &child_state.ivinlen);
+ goto skip;
+ } else {
+ /* Get the Kex for rekeying */
+ *pmonitor->m_pkex = mm_get_kex(&m);
+ }
+
+ blob = buffer_get_string(&m, &bloblen);
+ current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);
+ xfree(blob);
+
+ debug3("%s: Waiting for second key", __func__);
+ blob = buffer_get_string(&m, &bloblen);
+ current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen);
+ xfree(blob);
+
+ /* Now get sequence numbers for the packets */
+ packet_set_seqnr(MODE_OUT, buffer_get_int(&m));
+ packet_set_seqnr(MODE_IN, buffer_get_int(&m));
+
+ skip:
+ /* Get the key context */
+ child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen);
+ child_state.keyin = buffer_get_string(&m, &child_state.keyinlen);
+
+ debug3("%s: Getting compression state", __func__);
+ /* Get compression state */
+ p = buffer_get_string(&m, &plen);
+ if (plen != sizeof(child_state.outgoing))
+ fatal("%s: bad request size", __func__);
+ memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing));
+ xfree(p);
+
+ p = buffer_get_string(&m, &plen);
+ if (plen != sizeof(child_state.incoming))
+ fatal("%s: bad request size", __func__);
+ memcpy(&child_state.incoming, p, sizeof(child_state.incoming));
+ xfree(p);
+
+ /* Network I/O buffers */
+ debug3("%s: Getting Network I/O buffers", __func__);
+ child_state.input = buffer_get_string(&m, &child_state.ilen);
+ child_state.output = buffer_get_string(&m, &child_state.olen);
+
+ buffer_free(&m);
+}
+
+
+/* Allocation functions for zlib */
+void *
+mm_zalloc(struct mm_master *mm, u_int ncount, u_int size)
+{
+ void *address;
+
+ address = mm_malloc(mm, size * ncount);
+
+ return (address);
+}
+
+void
+mm_zfree(struct mm_master *mm, void *address)
+{
+ mm_free(mm, address);
+}
+
+void
+mm_init_compression(struct mm_master *mm)
+{
+ outgoing_stream.zalloc = (alloc_func)mm_zalloc;
+ outgoing_stream.zfree = (free_func)mm_zfree;
+ outgoing_stream.opaque = mm;
+
+ incoming_stream.zalloc = (alloc_func)mm_zalloc;
+ incoming_stream.zfree = (free_func)mm_zfree;
+ incoming_stream.opaque = mm;
+}
+
+/* XXX */
+
+#define FD_CLOSEONEXEC(x) do { \
+ if (fcntl(x, F_SETFD, 1) == -1) \
+ fatal("fcntl(%d, F_SETFD)", x); \
+} while (0)
+
+static void
+monitor_socketpair(int *pair)
+{
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
+ fatal("%s: socketpair", __func__);
+ FD_CLOSEONEXEC(pair[0]);
+ FD_CLOSEONEXEC(pair[1]);
+}
+
+#define MM_MEMSIZE 65536
+
+struct monitor *
+monitor_init(void)
+{
+ struct monitor *mon;
+ int pair[2];
+
+ mon = xmalloc(sizeof(*mon));
+
+ monitor_socketpair(pair);
+
+ mon->m_recvfd = pair[0];
+ mon->m_sendfd = pair[1];
+
+ /* Used to share zlib space across processes */
+ if (options.compression) {
+ mon->m_zback = mm_create(NULL, MM_MEMSIZE);
+ mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE);
+
+ /* Compression needs to share state across borders */
+ mm_init_compression(mon->m_zlib);
+ }
+
+ return mon;
+}
+
+void
+monitor_reinit(struct monitor *mon)
+{
+ int pair[2];
+
+ monitor_socketpair(pair);
+
+ mon->m_recvfd = pair[0];
+ mon->m_sendfd = pair[1];
+}
diff --git a/crypto/openssh/monitor.h b/crypto/openssh/monitor.h
new file mode 100644
index 0000000..42d5237
--- /dev/null
+++ b/crypto/openssh/monitor.h
@@ -0,0 +1,81 @@
+/* $OpenBSD: monitor.h,v 1.6 2002/06/11 05:46:20 mpech Exp $ */
+
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MONITOR_H_
+#define _MONITOR_H_
+
+enum monitor_reqtype {
+ MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
+ MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
+ MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
+ MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
+ MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
+ MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD,
+ MONITOR_REQ_BSDAUTHQUERY, MONITOR_ANS_BSDAUTHQUERY,
+ MONITOR_REQ_BSDAUTHRESPOND, MONITOR_ANS_BSDAUTHRESPOND,
+ MONITOR_REQ_SKEYQUERY, MONITOR_ANS_SKEYQUERY,
+ MONITOR_REQ_SKEYRESPOND, MONITOR_ANS_SKEYRESPOND,
+ MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED,
+ MONITOR_REQ_KEYVERIFY, MONITOR_ANS_KEYVERIFY,
+ MONITOR_REQ_KEYEXPORT,
+ MONITOR_REQ_PTY, MONITOR_ANS_PTY,
+ MONITOR_REQ_PTYCLEANUP,
+ MONITOR_REQ_SESSKEY, MONITOR_ANS_SESSKEY,
+ MONITOR_REQ_SESSID,
+ MONITOR_REQ_RSAKEYALLOWED, MONITOR_ANS_RSAKEYALLOWED,
+ MONITOR_REQ_RSACHALLENGE, MONITOR_ANS_RSACHALLENGE,
+ MONITOR_REQ_RSARESPONSE, MONITOR_ANS_RSARESPONSE,
+ MONITOR_REQ_TERM
+};
+
+struct mm_master;
+struct monitor {
+ int m_recvfd;
+ int m_sendfd;
+ struct mm_master *m_zback;
+ struct mm_master *m_zlib;
+ struct Kex **m_pkex;
+ pid_t m_pid;
+};
+
+struct monitor *monitor_init(void);
+void monitor_reinit(struct monitor *);
+void monitor_sync(struct monitor *);
+
+struct Authctxt;
+struct Authctxt *monitor_child_preauth(struct monitor *);
+void monitor_child_postauth(struct monitor *);
+
+struct mon_table;
+int monitor_read(struct monitor*, struct mon_table *, struct mon_table **);
+
+/* Prototypes for request sending and receiving */
+void mm_request_send(int, enum monitor_reqtype, Buffer *);
+void mm_request_receive(int, Buffer *);
+void mm_request_receive_expect(int, enum monitor_reqtype, Buffer *);
+
+#endif /* _MONITOR_H_ */
diff --git a/crypto/openssh/monitor_fdpass.c b/crypto/openssh/monitor_fdpass.c
new file mode 100644
index 0000000..9696c86
--- /dev/null
+++ b/crypto/openssh/monitor_fdpass.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2001 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: monitor_fdpass.c,v 1.3 2002/06/04 23:05:49 markus Exp $");
+
+#include <sys/uio.h>
+
+#include "log.h"
+#include "monitor_fdpass.h"
+
+void
+mm_send_fd(int socket, int fd)
+{
+ struct msghdr msg;
+ char tmp[CMSG_SPACE(sizeof(int))];
+ struct cmsghdr *cmsg;
+ struct iovec vec;
+ char ch = '\0';
+ int n;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_control = (caddr_t)tmp;
+ msg.msg_controllen = CMSG_LEN(sizeof(int));
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ *(int *)CMSG_DATA(cmsg) = fd;
+
+ vec.iov_base = &ch;
+ vec.iov_len = 1;
+ msg.msg_iov = &vec;
+ msg.msg_iovlen = 1;
+
+ if ((n = sendmsg(socket, &msg, 0)) == -1)
+ fatal("%s: sendmsg(%d): %s", __func__, fd,
+ strerror(errno));
+ if (n != 1)
+ fatal("%s: sendmsg: expected sent 1 got %d",
+ __func__, n);
+}
+
+int
+mm_receive_fd(int socket)
+{
+ struct msghdr msg;
+ char tmp[CMSG_SPACE(sizeof(int))];
+ struct cmsghdr *cmsg;
+ struct iovec vec;
+ char ch;
+ int fd, n;
+
+ memset(&msg, 0, sizeof(msg));
+ vec.iov_base = &ch;
+ vec.iov_len = 1;
+ msg.msg_iov = &vec;
+ msg.msg_iovlen = 1;
+ msg.msg_control = tmp;
+ msg.msg_controllen = sizeof(tmp);
+
+ if ((n = recvmsg(socket, &msg, 0)) == -1)
+ fatal("%s: recvmsg: %s", __func__, strerror(errno));
+ if (n != 1)
+ fatal("%s: recvmsg: expected received 1 got %d",
+ __func__, n);
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ if (cmsg->cmsg_type != SCM_RIGHTS)
+ fatal("%s: expected type %d got %d", __func__,
+ SCM_RIGHTS, cmsg->cmsg_type);
+ fd = (*(int *)CMSG_DATA(cmsg));
+ return fd;
+}
diff --git a/crypto/openssh/monitor_fdpass.h b/crypto/openssh/monitor_fdpass.h
new file mode 100644
index 0000000..31d080e
--- /dev/null
+++ b/crypto/openssh/monitor_fdpass.h
@@ -0,0 +1,34 @@
+/* $OpenBSD: monitor_fdpass.h,v 1.2 2002/03/26 03:24:01 stevesk Exp $ */
+
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MM_FDPASS_H_
+#define _MM_FDPASS_H_
+
+void mm_send_fd(int, int);
+int mm_receive_fd(int);
+
+#endif /* _MM_FDPASS_H_ */
diff --git a/crypto/openssh/monitor_mm.c b/crypto/openssh/monitor_mm.c
new file mode 100644
index 0000000..c6ea208
--- /dev/null
+++ b/crypto/openssh/monitor_mm.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: monitor_mm.c,v 1.6 2002/06/04 23:05:49 markus Exp $");
+
+#include <sys/mman.h>
+
+#include "ssh.h"
+#include "xmalloc.h"
+#include "log.h"
+#include "monitor_mm.h"
+
+static int
+mm_compare(struct mm_share *a, struct mm_share *b)
+{
+ return ((char *)a->address - (char *)b->address);
+}
+
+RB_GENERATE(mmtree, mm_share, next, mm_compare)
+
+static struct mm_share *
+mm_make_entry(struct mm_master *mm, struct mmtree *head,
+ void *address, size_t size)
+{
+ struct mm_share *tmp, *tmp2;
+
+ if (mm->mmalloc == NULL)
+ tmp = xmalloc(sizeof(struct mm_share));
+ else
+ tmp = mm_xmalloc(mm->mmalloc, sizeof(struct mm_share));
+ tmp->address = address;
+ tmp->size = size;
+
+ tmp2 = RB_INSERT(mmtree, head, tmp);
+ if (tmp2 != NULL)
+ fatal("mm_make_entry(%p): double address %p->%p(%lu)",
+ mm, tmp2, address, (u_long)size);
+
+ return (tmp);
+}
+
+/* Creates a shared memory area of a certain size */
+
+struct mm_master *
+mm_create(struct mm_master *mmalloc, size_t size)
+{
+ void *address;
+ struct mm_master *mm;
+
+ if (mmalloc == NULL)
+ mm = xmalloc(sizeof(struct mm_master));
+ else
+ mm = mm_xmalloc(mmalloc, sizeof(struct mm_master));
+
+ /*
+ * If the memory map has a mm_master it can be completely
+ * shared including authentication between the child
+ * and the client.
+ */
+ mm->mmalloc = mmalloc;
+
+ address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_ANON|MAP_SHARED,
+ -1, 0);
+ if (address == MAP_FAILED)
+ fatal("mmap(%lu): %s", (u_long)size, strerror(errno));
+
+ mm->address = address;
+ mm->size = size;
+
+ RB_INIT(&mm->rb_free);
+ RB_INIT(&mm->rb_allocated);
+
+ mm_make_entry(mm, &mm->rb_free, address, size);
+
+ return (mm);
+}
+
+/* Frees either the allocated or the free list */
+
+static void
+mm_freelist(struct mm_master *mmalloc, struct mmtree *head)
+{
+ struct mm_share *mms, *next;
+
+ for (mms = RB_ROOT(head); mms; mms = next) {
+ next = RB_NEXT(mmtree, head, mms);
+ RB_REMOVE(mmtree, head, mms);
+ if (mmalloc == NULL)
+ xfree(mms);
+ else
+ mm_free(mmalloc, mms);
+ }
+}
+
+/* Destroys a memory mapped area */
+
+void
+mm_destroy(struct mm_master *mm)
+{
+ mm_freelist(mm->mmalloc, &mm->rb_free);
+ mm_freelist(mm->mmalloc, &mm->rb_allocated);
+
+ if (munmap(mm->address, mm->size) == -1)
+ fatal("munmap(%p, %lu): %s", mm->address, (u_long)mm->size,
+ strerror(errno));
+ if (mm->mmalloc == NULL)
+ xfree(mm);
+ else
+ mm_free(mm->mmalloc, mm);
+}
+
+void *
+mm_xmalloc(struct mm_master *mm, size_t size)
+{
+ void *address;
+
+ address = mm_malloc(mm, size);
+ if (address == NULL)
+ fatal("%s: mm_malloc(%lu)", __func__, (u_long)size);
+ return (address);
+}
+
+
+/* Allocates data from a memory mapped area */
+
+void *
+mm_malloc(struct mm_master *mm, size_t size)
+{
+ struct mm_share *mms, *tmp;
+
+ if (size == 0)
+ fatal("mm_malloc: try to allocate 0 space");
+
+ size = ((size + MM_MINSIZE - 1) / MM_MINSIZE) * MM_MINSIZE;
+
+ RB_FOREACH(mms, mmtree, &mm->rb_free) {
+ if (mms->size >= size)
+ break;
+ }
+
+ if (mms == NULL)
+ return (NULL);
+
+ /* Debug */
+ memset(mms->address, 0xd0, size);
+
+ tmp = mm_make_entry(mm, &mm->rb_allocated, mms->address, size);
+
+ /* Does not change order in RB tree */
+ mms->size -= size;
+ mms->address = (u_char *)mms->address + size;
+
+ if (mms->size == 0) {
+ RB_REMOVE(mmtree, &mm->rb_free, mms);
+ if (mm->mmalloc == NULL)
+ xfree(mms);
+ else
+ mm_free(mm->mmalloc, mms);
+ }
+
+ return (tmp->address);
+}
+
+/* Frees memory in a memory mapped area */
+
+void
+mm_free(struct mm_master *mm, void *address)
+{
+ struct mm_share *mms, *prev, tmp;
+
+ tmp.address = address;
+ mms = RB_FIND(mmtree, &mm->rb_allocated, &tmp);
+ if (mms == NULL)
+ fatal("mm_free(%p): can not find %p", mm, address);
+
+ /* Debug */
+ memset(mms->address, 0xd0, mms->size);
+
+ /* Remove from allocated list and insert in free list */
+ RB_REMOVE(mmtree, &mm->rb_allocated, mms);
+ if (RB_INSERT(mmtree, &mm->rb_free, mms) != NULL)
+ fatal("mm_free(%p): double address %p", mm, address);
+
+ /* Find previous entry */
+ prev = mms;
+ if (RB_LEFT(prev, next)) {
+ prev = RB_LEFT(prev, next);
+ while (RB_RIGHT(prev, next))
+ prev = RB_RIGHT(prev, next);
+ } else {
+ if (RB_PARENT(prev, next) &&
+ (prev == RB_RIGHT(RB_PARENT(prev, next), next)))
+ prev = RB_PARENT(prev, next);
+ else {
+ while (RB_PARENT(prev, next) &&
+ (prev == RB_LEFT(RB_PARENT(prev, next), next)))
+ prev = RB_PARENT(prev, next);
+ prev = RB_PARENT(prev, next);
+ }
+ }
+
+ /* Check if range does not overlap */
+ if (prev != NULL && MM_ADDRESS_END(prev) > address)
+ fatal("mm_free: memory corruption: %p(%lu) > %p",
+ prev->address, (u_long)prev->size, address);
+
+ /* See if we can merge backwards */
+ if (prev != NULL && MM_ADDRESS_END(prev) == address) {
+ prev->size += mms->size;
+ RB_REMOVE(mmtree, &mm->rb_free, mms);
+ if (mm->mmalloc == NULL)
+ xfree(mms);
+ else
+ mm_free(mm->mmalloc, mms);
+ } else
+ prev = mms;
+
+ if (prev == NULL)
+ return;
+
+ /* Check if we can merge forwards */
+ mms = RB_NEXT(mmtree, &mm->rb_free, prev);
+ if (mms == NULL)
+ return;
+
+ if (MM_ADDRESS_END(prev) > mms->address)
+ fatal("mm_free: memory corruption: %p < %p(%lu)",
+ mms->address, prev->address, (u_long)prev->size);
+ if (MM_ADDRESS_END(prev) != mms->address)
+ return;
+
+ prev->size += mms->size;
+ RB_REMOVE(mmtree, &mm->rb_free, mms);
+
+ if (mm->mmalloc == NULL)
+ xfree(mms);
+ else
+ mm_free(mm->mmalloc, mms);
+}
+
+static void
+mm_sync_list(struct mmtree *oldtree, struct mmtree *newtree,
+ struct mm_master *mm, struct mm_master *mmold)
+{
+ struct mm_master *mmalloc = mm->mmalloc;
+ struct mm_share *mms, *new;
+
+ /* Sync free list */
+ RB_FOREACH(mms, mmtree, oldtree) {
+ /* Check the values */
+ mm_memvalid(mmold, mms, sizeof(struct mm_share));
+ mm_memvalid(mm, mms->address, mms->size);
+
+ new = mm_xmalloc(mmalloc, sizeof(struct mm_share));
+ memcpy(new, mms, sizeof(struct mm_share));
+ RB_INSERT(mmtree, newtree, new);
+ }
+}
+
+void
+mm_share_sync(struct mm_master **pmm, struct mm_master **pmmalloc)
+{
+ struct mm_master *mm;
+ struct mm_master *mmalloc;
+ struct mm_master *mmold;
+ struct mmtree rb_free, rb_allocated;
+
+ debug3("%s: Share sync", __func__);
+
+ mm = *pmm;
+ mmold = mm->mmalloc;
+ mm_memvalid(mmold, mm, sizeof(*mm));
+
+ mmalloc = mm_create(NULL, mm->size);
+ mm = mm_xmalloc(mmalloc, sizeof(struct mm_master));
+ memcpy(mm, *pmm, sizeof(struct mm_master));
+ mm->mmalloc = mmalloc;
+
+ rb_free = mm->rb_free;
+ rb_allocated = mm->rb_allocated;
+
+ RB_INIT(&mm->rb_free);
+ RB_INIT(&mm->rb_allocated);
+
+ mm_sync_list(&rb_free, &mm->rb_free, mm, mmold);
+ mm_sync_list(&rb_allocated, &mm->rb_allocated, mm, mmold);
+
+ mm_destroy(mmold);
+
+ *pmm = mm;
+ *pmmalloc = mmalloc;
+
+ debug3("%s: Share sync end", __func__);
+}
+
+void
+mm_memvalid(struct mm_master *mm, void *address, size_t size)
+{
+ void *end = (u_char *)address + size;
+
+ if (address < mm->address)
+ fatal("mm_memvalid: address too small: %p", address);
+ if (end < address)
+ fatal("mm_memvalid: end < address: %p < %p", end, address);
+ if (end > (void *)((u_char *)mm->address + mm->size))
+ fatal("mm_memvalid: address too large: %p", address);
+}
diff --git a/crypto/openssh/monitor_mm.h b/crypto/openssh/monitor_mm.h
new file mode 100644
index 0000000..d8a5cdf
--- /dev/null
+++ b/crypto/openssh/monitor_mm.h
@@ -0,0 +1,66 @@
+/* $OpenBSD: monitor_mm.h,v 1.2 2002/03/26 03:24:01 stevesk Exp $ */
+
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MM_H_
+#define _MM_H_
+#include <sys/tree.h>
+
+struct mm_share {
+ RB_ENTRY(mm_share) next;
+ void *address;
+ size_t size;
+};
+
+struct mm_master {
+ RB_HEAD(mmtree, mm_share) rb_free;
+ struct mmtree rb_allocated;
+ void *address;
+ size_t size;
+
+ struct mm_master *mmalloc; /* Used to completely share */
+
+ int write; /* used to writing to other party */
+ int read; /* used for reading from other party */
+};
+
+RB_PROTOTYPE(mmtree, mm_share, next, mm_compare)
+
+#define MM_MINSIZE 128
+
+#define MM_ADDRESS_END(x) (void *)((u_char *)(x)->address + (x)->size)
+
+struct mm_master *mm_create(struct mm_master *, size_t);
+void mm_destroy(struct mm_master *);
+
+void mm_share_sync(struct mm_master **, struct mm_master **);
+
+void *mm_malloc(struct mm_master *, size_t);
+void *mm_xmalloc(struct mm_master *, size_t);
+void mm_free(struct mm_master *, void *);
+
+void mm_memvalid(struct mm_master *, void *, size_t);
+#endif /* _MM_H_ */
diff --git a/crypto/openssh/monitor_wrap.c b/crypto/openssh/monitor_wrap.c
new file mode 100644
index 0000000..faad6c2
--- /dev/null
+++ b/crypto/openssh/monitor_wrap.c
@@ -0,0 +1,920 @@
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * Copyright 2002 Markus Friedl <markus@openbsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: monitor_wrap.c,v 1.11 2002/06/19 18:01:00 markus Exp $");
+
+#include <openssl/bn.h>
+#include <openssl/dh.h>
+
+#include "ssh.h"
+#include "dh.h"
+#include "kex.h"
+#include "auth.h"
+#include "buffer.h"
+#include "bufaux.h"
+#include "packet.h"
+#include "mac.h"
+#include "log.h"
+#include "zlib.h"
+#include "monitor.h"
+#include "monitor_wrap.h"
+#include "xmalloc.h"
+#include "atomicio.h"
+#include "monitor_fdpass.h"
+#include "getput.h"
+
+#include "auth.h"
+#include "channels.h"
+#include "session.h"
+
+/* Imports */
+extern int compat20;
+extern Newkeys *newkeys[];
+extern z_stream incoming_stream;
+extern z_stream outgoing_stream;
+extern struct monitor *pmonitor;
+extern Buffer input, output;
+
+void
+mm_request_send(int socket, enum monitor_reqtype type, Buffer *m)
+{
+ u_char buf[5];
+ u_int mlen = buffer_len(m);
+
+ debug3("%s entering: type %d", __func__, type);
+
+ PUT_32BIT(buf, mlen + 1);
+ buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */
+ if (atomicio(write, socket, buf, sizeof(buf)) != sizeof(buf))
+ fatal("%s: write", __func__);
+ if (atomicio(write, socket, buffer_ptr(m), mlen) != mlen)
+ fatal("%s: write", __func__);
+}
+
+void
+mm_request_receive(int socket, Buffer *m)
+{
+ u_char buf[4];
+ ssize_t res;
+ u_int msg_len;
+
+ debug3("%s entering", __func__);
+
+ res = atomicio(read, socket, buf, sizeof(buf));
+ if (res != sizeof(buf)) {
+ if (res == 0)
+ fatal_cleanup();
+ fatal("%s: read: %ld", __func__, (long)res);
+ }
+ msg_len = GET_32BIT(buf);
+ if (msg_len > 256 * 1024)
+ fatal("%s: read: bad msg_len %d", __func__, msg_len);
+ buffer_clear(m);
+ buffer_append_space(m, msg_len);
+ res = atomicio(read, socket, buffer_ptr(m), msg_len);
+ if (res != msg_len)
+ fatal("%s: read: %ld != msg_len", __func__, (long)res);
+}
+
+void
+mm_request_receive_expect(int socket, enum monitor_reqtype type, Buffer *m)
+{
+ u_char rtype;
+
+ debug3("%s entering: type %d", __func__, type);
+
+ mm_request_receive(socket, m);
+ rtype = buffer_get_char(m);
+ if (rtype != type)
+ fatal("%s: read: rtype %d != type %d", __func__,
+ rtype, type);
+}
+
+DH *
+mm_choose_dh(int min, int nbits, int max)
+{
+ BIGNUM *p, *g;
+ int success = 0;
+ Buffer m;
+
+ buffer_init(&m);
+ buffer_put_int(&m, min);
+ buffer_put_int(&m, nbits);
+ buffer_put_int(&m, max);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m);
+
+ debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m);
+
+ success = buffer_get_char(&m);
+ if (success == 0)
+ fatal("%s: MONITOR_ANS_MODULI failed", __func__);
+
+ if ((p = BN_new()) == NULL)
+ fatal("%s: BN_new failed", __func__);
+ if ((g = BN_new()) == NULL)
+ fatal("%s: BN_new failed", __func__);
+ buffer_get_bignum2(&m, p);
+ buffer_get_bignum2(&m, g);
+
+ debug3("%s: remaining %d", __func__, buffer_len(&m));
+ buffer_free(&m);
+
+ return (dh_new_group(g, p));
+}
+
+int
+mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen)
+{
+ Kex *kex = *pmonitor->m_pkex;
+ Buffer m;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+ buffer_put_int(&m, kex->host_key_index(key));
+ buffer_put_string(&m, data, datalen);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);
+
+ debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m);
+ *sigp = buffer_get_string(&m, lenp);
+ buffer_free(&m);
+
+ return (0);
+}
+
+struct passwd *
+mm_getpwnamallow(const char *login)
+{
+ Buffer m;
+ struct passwd *pw;
+ u_int pwlen;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+ buffer_put_cstring(&m, login);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m);
+
+ debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m);
+
+ if (buffer_get_char(&m) == 0) {
+ buffer_free(&m);
+ return (NULL);
+ }
+ pw = buffer_get_string(&m, &pwlen);
+ if (pwlen != sizeof(struct passwd))
+ fatal("%s: struct passwd size mismatch", __func__);
+ pw->pw_name = buffer_get_string(&m, NULL);
+ pw->pw_passwd = buffer_get_string(&m, NULL);
+ pw->pw_gecos = buffer_get_string(&m, NULL);
+ pw->pw_class = buffer_get_string(&m, NULL);
+ pw->pw_dir = buffer_get_string(&m, NULL);
+ pw->pw_shell = buffer_get_string(&m, NULL);
+ buffer_free(&m);
+
+ return (pw);
+}
+
+char* mm_auth2_read_banner(void)
+{
+ Buffer m;
+ char *banner;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
+ buffer_clear(&m);
+
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTH2_READ_BANNER, &m);
+ banner = buffer_get_string(&m, NULL);
+ buffer_free(&m);
+
+ return (banner);
+}
+
+/* Inform the privileged process about service and style */
+
+void
+mm_inform_authserv(char *service, char *style)
+{
+ Buffer m;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+ buffer_put_cstring(&m, service);
+ buffer_put_cstring(&m, style ? style : "");
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
+
+ buffer_free(&m);
+}
+
+/* Do the password authentication */
+int
+mm_auth_password(Authctxt *authctxt, char *password)
+{
+ Buffer m;
+ int authenticated = 0;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+ buffer_put_cstring(&m, password);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
+
+ debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
+
+ authenticated = buffer_get_int(&m);
+
+ buffer_free(&m);
+
+ debug3("%s: user %sauthenticated",
+ __func__, authenticated ? "" : "not ");
+ return (authenticated);
+}
+
+int
+mm_user_key_allowed(struct passwd *pw, Key *key)
+{
+ return (mm_key_allowed(MM_USERKEY, NULL, NULL, key));
+}
+
+int
+mm_hostbased_key_allowed(struct passwd *pw, char *user, char *host,
+ Key *key)
+{
+ return (mm_key_allowed(MM_HOSTKEY, user, host, key));
+}
+
+int
+mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
+ char *host, Key *key)
+{
+ int ret;
+
+ key->type = KEY_RSA; /* XXX hack for key_to_blob */
+ ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key);
+ key->type = KEY_RSA1;
+ return (ret);
+}
+
+static void
+mm_send_debug(Buffer *m)
+{
+ char *msg;
+
+ while (buffer_len(m)) {
+ msg = buffer_get_string(m, NULL);
+ debug3("%s: Sending debug: %s", __func__, msg);
+ packet_send_debug("%s", msg);
+ xfree(msg);
+ }
+}
+
+int
+mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
+{
+ Buffer m;
+ u_char *blob;
+ u_int len;
+ int allowed = 0;
+
+ debug3("%s entering", __func__);
+
+ /* Convert the key to a blob and the pass it over */
+ if (!key_to_blob(key, &blob, &len))
+ return (0);
+
+ buffer_init(&m);
+ buffer_put_int(&m, type);
+ buffer_put_cstring(&m, user ? user : "");
+ buffer_put_cstring(&m, host ? host : "");
+ buffer_put_string(&m, blob, len);
+ xfree(blob);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
+
+ debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
+
+ allowed = buffer_get_int(&m);
+
+ /* Send potential debug messages */
+ mm_send_debug(&m);
+
+ buffer_free(&m);
+
+ return (allowed);
+}
+
+/*
+ * This key verify needs to send the key type along, because the
+ * privileged parent makes the decision if the key is allowed
+ * for authentication.
+ */
+
+int
+mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
+{
+ Buffer m;
+ u_char *blob;
+ u_int len;
+ int verified = 0;
+
+ debug3("%s entering", __func__);
+
+ /* Convert the key to a blob and the pass it over */
+ if (!key_to_blob(key, &blob, &len))
+ return (0);
+
+ buffer_init(&m);
+ buffer_put_string(&m, blob, len);
+ buffer_put_string(&m, sig, siglen);
+ buffer_put_string(&m, data, datalen);
+ xfree(blob);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
+
+ debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
+
+ verified = buffer_get_int(&m);
+
+ buffer_free(&m);
+
+ return (verified);
+}
+
+/* Export key state after authentication */
+Newkeys *
+mm_newkeys_from_blob(u_char *blob, int blen)
+{
+ Buffer b;
+ u_int len;
+ Newkeys *newkey = NULL;
+ Enc *enc;
+ Mac *mac;
+ Comp *comp;
+
+ debug3("%s: %p(%d)", __func__, blob, blen);
+#ifdef DEBUG_PK
+ dump_base64(stderr, blob, blen);
+#endif
+ buffer_init(&b);
+ buffer_append(&b, blob, blen);
+
+ newkey = xmalloc(sizeof(*newkey));
+ enc = &newkey->enc;
+ mac = &newkey->mac;
+ comp = &newkey->comp;
+
+ /* Enc structure */
+ enc->name = buffer_get_string(&b, NULL);
+ buffer_get(&b, &enc->cipher, sizeof(enc->cipher));
+ enc->enabled = buffer_get_int(&b);
+ enc->block_size = buffer_get_int(&b);
+ enc->key = buffer_get_string(&b, &enc->key_len);
+ enc->iv = buffer_get_string(&b, &len);
+ if (len != enc->block_size)
+ fatal("%s: bad ivlen: expected %d != %d", __func__,
+ enc->block_size, len);
+
+ if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher)
+ fatal("%s: bad cipher name %s or pointer %p", __func__,
+ enc->name, enc->cipher);
+
+ /* Mac structure */
+ mac->name = buffer_get_string(&b, NULL);
+ if (mac->name == NULL || mac_init(mac, mac->name) == -1)
+ fatal("%s: can not init mac %s", __func__, mac->name);
+ mac->enabled = buffer_get_int(&b);
+ mac->key = buffer_get_string(&b, &len);
+ if (len > mac->key_len)
+ fatal("%s: bad mac key length: %d > %d", __func__, len,
+ mac->key_len);
+ mac->key_len = len;
+
+ /* Comp structure */
+ comp->type = buffer_get_int(&b);
+ comp->enabled = buffer_get_int(&b);
+ comp->name = buffer_get_string(&b, NULL);
+
+ len = buffer_len(&b);
+ if (len != 0)
+ error("newkeys_from_blob: remaining bytes in blob %d", len);
+ buffer_free(&b);
+ return (newkey);
+}
+
+int
+mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
+{
+ Buffer b;
+ int len;
+ u_char *buf;
+ Enc *enc;
+ Mac *mac;
+ Comp *comp;
+ Newkeys *newkey = newkeys[mode];
+
+ debug3("%s: converting %p", __func__, newkey);
+
+ if (newkey == NULL) {
+ error("%s: newkey == NULL", __func__);
+ return 0;
+ }
+ enc = &newkey->enc;
+ mac = &newkey->mac;
+ comp = &newkey->comp;
+
+ buffer_init(&b);
+ /* Enc structure */
+ buffer_put_cstring(&b, enc->name);
+ /* The cipher struct is constant and shared, you export pointer */
+ buffer_append(&b, &enc->cipher, sizeof(enc->cipher));
+ buffer_put_int(&b, enc->enabled);
+ buffer_put_int(&b, enc->block_size);
+ buffer_put_string(&b, enc->key, enc->key_len);
+ packet_get_keyiv(mode, enc->iv, enc->block_size);
+ buffer_put_string(&b, enc->iv, enc->block_size);
+
+ /* Mac structure */
+ buffer_put_cstring(&b, mac->name);
+ buffer_put_int(&b, mac->enabled);
+ buffer_put_string(&b, mac->key, mac->key_len);
+
+ /* Comp structure */
+ buffer_put_int(&b, comp->type);
+ buffer_put_int(&b, comp->enabled);
+ buffer_put_cstring(&b, comp->name);
+
+ len = buffer_len(&b);
+ buf = xmalloc(len);
+ memcpy(buf, buffer_ptr(&b), len);
+ memset(buffer_ptr(&b), 0, len);
+ buffer_free(&b);
+ if (lenp != NULL)
+ *lenp = len;
+ if (blobp != NULL)
+ *blobp = buf;
+ return len;
+}
+
+static void
+mm_send_kex(Buffer *m, Kex *kex)
+{
+ buffer_put_string(m, kex->session_id, kex->session_id_len);
+ buffer_put_int(m, kex->we_need);
+ buffer_put_int(m, kex->hostkey_type);
+ buffer_put_int(m, kex->kex_type);
+ buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my));
+ buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer));
+ buffer_put_int(m, kex->flags);
+ buffer_put_cstring(m, kex->client_version_string);
+ buffer_put_cstring(m, kex->server_version_string);
+}
+
+void
+mm_send_keystate(struct monitor *pmonitor)
+{
+ Buffer m;
+ u_char *blob, *p;
+ u_int bloblen, plen;
+
+ buffer_init(&m);
+
+ if (!compat20) {
+ u_char iv[24];
+ u_char *key;
+ u_int ivlen, keylen;
+
+ buffer_put_int(&m, packet_get_protocol_flags());
+
+ buffer_put_int(&m, packet_get_ssh1_cipher());
+
+ debug3("%s: Sending ssh1 KEY+IV", __func__);
+ keylen = packet_get_encryption_key(NULL);
+ key = xmalloc(keylen+1); /* add 1 if keylen == 0 */
+ keylen = packet_get_encryption_key(key);
+ buffer_put_string(&m, key, keylen);
+ memset(key, 0, keylen);
+ xfree(key);
+
+ ivlen = packet_get_keyiv_len(MODE_OUT);
+ packet_get_keyiv(MODE_OUT, iv, ivlen);
+ buffer_put_string(&m, iv, ivlen);
+ ivlen = packet_get_keyiv_len(MODE_OUT);
+ packet_get_keyiv(MODE_IN, iv, ivlen);
+ buffer_put_string(&m, iv, ivlen);
+ goto skip;
+ } else {
+ /* Kex for rekeying */
+ mm_send_kex(&m, *pmonitor->m_pkex);
+ }
+
+ debug3("%s: Sending new keys: %p %p",
+ __func__, newkeys[MODE_OUT], newkeys[MODE_IN]);
+
+ /* Keys from Kex */
+ if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen))
+ fatal("%s: conversion of newkeys failed", __func__);
+
+ buffer_put_string(&m, blob, bloblen);
+ xfree(blob);
+
+ if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen))
+ fatal("%s: conversion of newkeys failed", __func__);
+
+ buffer_put_string(&m, blob, bloblen);
+ xfree(blob);
+
+ buffer_put_int(&m, packet_get_seqnr(MODE_OUT));
+ buffer_put_int(&m, packet_get_seqnr(MODE_IN));
+
+ debug3("%s: New keys have been sent", __func__);
+ skip:
+ /* More key context */
+ plen = packet_get_keycontext(MODE_OUT, NULL);
+ p = xmalloc(plen+1);
+ packet_get_keycontext(MODE_OUT, p);
+ buffer_put_string(&m, p, plen);
+ xfree(p);
+
+ plen = packet_get_keycontext(MODE_IN, NULL);
+ p = xmalloc(plen+1);
+ packet_get_keycontext(MODE_IN, p);
+ buffer_put_string(&m, p, plen);
+ xfree(p);
+
+ /* Compression state */
+ debug3("%s: Sending compression state", __func__);
+ buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream));
+ buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream));
+
+ /* Network I/O buffers */
+ buffer_put_string(&m, buffer_ptr(&input), buffer_len(&input));
+ buffer_put_string(&m, buffer_ptr(&output), buffer_len(&output));
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m);
+ debug3("%s: Finished sending state", __func__);
+
+ buffer_free(&m);
+}
+
+int
+mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
+{
+ Buffer m;
+ u_char *p;
+ int success = 0;
+
+ buffer_init(&m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
+
+ debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m);
+
+ success = buffer_get_int(&m);
+ if (success == 0) {
+ debug3("%s: pty alloc failed", __func__);
+ buffer_free(&m);
+ return (0);
+ }
+ p = buffer_get_string(&m, NULL);
+ buffer_free(&m);
+
+ strlcpy(namebuf, p, namebuflen); /* Possible truncation */
+ xfree(p);
+
+ *ptyfd = mm_receive_fd(pmonitor->m_recvfd);
+ *ttyfd = mm_receive_fd(pmonitor->m_recvfd);
+
+ /* Success */
+ return (1);
+}
+
+void
+mm_session_pty_cleanup2(void *session)
+{
+ Session *s = session;
+ Buffer m;
+
+ if (s->ttyfd == -1)
+ return;
+ buffer_init(&m);
+ buffer_put_cstring(&m, s->tty);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
+ buffer_free(&m);
+
+ /* closed dup'ed master */
+ if (close(s->ptymaster) < 0)
+ error("close(s->ptymaster): %s", strerror(errno));
+
+ /* unlink pty from session */
+ s->ttyfd = -1;
+}
+
+/* Request process termination */
+
+void
+mm_terminate(void)
+{
+ Buffer m;
+
+ buffer_init(&m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m);
+ buffer_free(&m);
+}
+
+int
+mm_ssh1_session_key(BIGNUM *num)
+{
+ int rsafail;
+ Buffer m;
+
+ buffer_init(&m);
+ buffer_put_bignum2(&m, num);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m);
+
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m);
+
+ rsafail = buffer_get_int(&m);
+ buffer_get_bignum2(&m, num);
+
+ buffer_free(&m);
+
+ return (rsafail);
+}
+
+static void
+mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
+ char ***prompts, u_int **echo_on)
+{
+ *name = xstrdup("");
+ *infotxt = xstrdup("");
+ *numprompts = 1;
+ *prompts = xmalloc(*numprompts * sizeof(char*));
+ *echo_on = xmalloc(*numprompts * sizeof(u_int));
+ (*echo_on)[0] = 0;
+}
+
+int
+mm_bsdauth_query(void *ctx, char **name, char **infotxt,
+ u_int *numprompts, char ***prompts, u_int **echo_on)
+{
+ Buffer m;
+ int res;
+ char *challenge;
+
+ debug3("%s: entering", __func__);
+
+ buffer_init(&m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m);
+
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY,
+ &m);
+ res = buffer_get_int(&m);
+ if (res == -1) {
+ debug3("%s: no challenge", __func__);
+ buffer_free(&m);
+ return (-1);
+ }
+
+ /* Get the challenge, and format the response */
+ challenge = buffer_get_string(&m, NULL);
+ buffer_free(&m);
+
+ mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
+ (*prompts)[0] = challenge;
+
+ debug3("%s: received challenge: %s", __func__, challenge);
+
+ return (0);
+}
+
+int
+mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
+{
+ Buffer m;
+ int authok;
+
+ debug3("%s: entering", __func__);
+ if (numresponses != 1)
+ return (-1);
+
+ buffer_init(&m);
+ buffer_put_cstring(&m, responses[0]);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m);
+
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_BSDAUTHRESPOND, &m);
+
+ authok = buffer_get_int(&m);
+ buffer_free(&m);
+
+ return ((authok == 0) ? -1 : 0);
+}
+
+int
+mm_skey_query(void *ctx, char **name, char **infotxt,
+ u_int *numprompts, char ***prompts, u_int **echo_on)
+{
+ Buffer m;
+ int len, res;
+ char *p, *challenge;
+
+ debug3("%s: entering", __func__);
+
+ buffer_init(&m);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m);
+
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY,
+ &m);
+ res = buffer_get_int(&m);
+ if (res == -1) {
+ debug3("%s: no challenge", __func__);
+ buffer_free(&m);
+ return (-1);
+ }
+
+ /* Get the challenge, and format the response */
+ challenge = buffer_get_string(&m, NULL);
+ buffer_free(&m);
+
+ debug3("%s: received challenge: %s", __func__, challenge);
+
+ mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
+
+ len = strlen(challenge) + strlen(SKEY_PROMPT) + 1;
+ p = xmalloc(len);
+ strlcpy(p, challenge, len);
+ strlcat(p, SKEY_PROMPT, len);
+ (*prompts)[0] = p;
+ xfree(challenge);
+
+ return (0);
+}
+
+int
+mm_skey_respond(void *ctx, u_int numresponses, char **responses)
+{
+ Buffer m;
+ int authok;
+
+ debug3("%s: entering", __func__);
+ if (numresponses != 1)
+ return (-1);
+
+ buffer_init(&m);
+ buffer_put_cstring(&m, responses[0]);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m);
+
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_SKEYRESPOND, &m);
+
+ authok = buffer_get_int(&m);
+ buffer_free(&m);
+
+ return ((authok == 0) ? -1 : 0);
+}
+
+void
+mm_ssh1_session_id(u_char session_id[16])
+{
+ Buffer m;
+ int i;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+ for (i = 0; i < 16; i++)
+ buffer_put_char(&m, session_id[i]);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m);
+ buffer_free(&m);
+}
+
+int
+mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
+{
+ Buffer m;
+ Key *key;
+ u_char *blob;
+ u_int blen;
+ int allowed = 0;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+ buffer_put_bignum2(&m, client_n);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);
+
+ allowed = buffer_get_int(&m);
+
+ if (allowed && rkey != NULL) {
+ blob = buffer_get_string(&m, &blen);
+ if ((key = key_from_blob(blob, blen)) == NULL)
+ fatal("%s: key_from_blob failed", __func__);
+ *rkey = key;
+ xfree(blob);
+ }
+ mm_send_debug(&m);
+ buffer_free(&m);
+
+ return (allowed);
+}
+
+BIGNUM *
+mm_auth_rsa_generate_challenge(Key *key)
+{
+ Buffer m;
+ BIGNUM *challenge;
+ u_char *blob;
+ u_int blen;
+
+ debug3("%s entering", __func__);
+
+ if ((challenge = BN_new()) == NULL)
+ fatal("%s: BN_new failed", __func__);
+
+ key->type = KEY_RSA; /* XXX cheat for key_to_blob */
+ if (key_to_blob(key, &blob, &blen) == 0)
+ fatal("%s: key_to_blob failed", __func__);
+ key->type = KEY_RSA1;
+
+ buffer_init(&m);
+ buffer_put_string(&m, blob, blen);
+ xfree(blob);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m);
+
+ buffer_get_bignum2(&m, challenge);
+ buffer_free(&m);
+
+ return (challenge);
+}
+
+int
+mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
+{
+ Buffer m;
+ u_char *blob;
+ u_int blen;
+ int success = 0;
+
+ debug3("%s entering", __func__);
+
+ key->type = KEY_RSA; /* XXX cheat for key_to_blob */
+ if (key_to_blob(key, &blob, &blen) == 0)
+ fatal("%s: key_to_blob failed", __func__);
+ key->type = KEY_RSA1;
+
+ buffer_init(&m);
+ buffer_put_string(&m, blob, blen);
+ buffer_put_string(&m, response, 16);
+ xfree(blob);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m);
+
+ success = buffer_get_int(&m);
+ buffer_free(&m);
+
+ return (success);
+}
diff --git a/crypto/openssh/monitor_wrap.h b/crypto/openssh/monitor_wrap.h
new file mode 100644
index 0000000..739b054
--- /dev/null
+++ b/crypto/openssh/monitor_wrap.h
@@ -0,0 +1,88 @@
+/* $OpenBSD: monitor_wrap.h,v 1.5 2002/05/12 23:53:45 djm Exp $ */
+
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MM_WRAP_H_
+#define _MM_WRAP_H_
+#include "key.h"
+#include "buffer.h"
+
+extern int use_privsep;
+#define PRIVSEP(x) (use_privsep ? mm_##x : x)
+
+enum mm_keytype {MM_NOKEY, MM_HOSTKEY, MM_USERKEY, MM_RSAHOSTKEY, MM_RSAUSERKEY};
+
+struct monitor;
+struct mm_master;
+struct passwd;
+struct Authctxt;
+
+DH *mm_choose_dh(int, int, int);
+int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int);
+void mm_inform_authserv(char *, char *);
+struct passwd *mm_getpwnamallow(const char *);
+char* mm_auth2_read_banner(void);
+int mm_auth_password(struct Authctxt *, char *);
+int mm_key_allowed(enum mm_keytype, char *, char *, Key *);
+int mm_user_key_allowed(struct passwd *, Key *);
+int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *);
+int mm_auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
+int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int);
+int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
+int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *);
+BIGNUM *mm_auth_rsa_generate_challenge(Key *);
+
+void mm_terminate(void);
+int mm_pty_allocate(int *, int *, char *, int);
+void mm_session_pty_cleanup2(void *);
+
+/* SSHv1 interfaces */
+void mm_ssh1_session_id(u_char *);
+int mm_ssh1_session_key(BIGNUM *);
+
+/* Key export functions */
+struct Newkeys *mm_newkeys_from_blob(u_char *, int);
+int mm_newkeys_to_blob(int, u_char **, u_int *);
+
+void monitor_apply_keystate(struct monitor *);
+void mm_get_keystate(struct monitor *);
+void mm_send_keystate(struct monitor*);
+
+/* bsdauth */
+int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
+int mm_bsdauth_respond(void *, u_int, char **);
+
+/* skey */
+int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
+int mm_skey_respond(void *, u_int, char **);
+
+/* zlib allocation hooks */
+
+void *mm_zalloc(struct mm_master *, u_int, u_int);
+void mm_zfree(struct mm_master *, void *);
+void mm_init_compression(struct mm_master *);
+
+#endif /* _MM_H_ */
diff --git a/crypto/openssh/msg.c b/crypto/openssh/msg.c
new file mode 100644
index 0000000..103aed2
--- /dev/null
+++ b/crypto/openssh/msg.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2002 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "includes.h"
+RCSID("$OpenBSD: msg.c,v 1.2 2002/06/19 00:27:55 deraadt Exp $");
+
+#include "buffer.h"
+#include "getput.h"
+#include "log.h"
+#include "atomicio.h"
+#include "msg.h"
+
+void
+msg_send(int fd, u_char type, Buffer *m)
+{
+ u_char buf[5];
+ u_int mlen = buffer_len(m);
+
+ debug3("msg_send: type %d", type);
+
+ PUT_32BIT(buf, mlen + 1);
+ buf[4] = type; /* 1st byte of payload is mesg-type */
+ if (atomicio(write, fd, buf, sizeof(buf)) != sizeof(buf))
+ fatal("msg_send: write");
+ if (atomicio(write, fd, buffer_ptr(m), mlen) != mlen)
+ fatal("msg_send: write");
+}
+
+int
+msg_recv(int fd, Buffer *m)
+{
+ u_char buf[4];
+ ssize_t res;
+ u_int msg_len;
+
+ debug3("msg_recv entering");
+
+ res = atomicio(read, fd, buf, sizeof(buf));
+ if (res != sizeof(buf)) {
+ if (res == 0)
+ return -1;
+ fatal("msg_recv: read: header %d", res);
+ }
+ msg_len = GET_32BIT(buf);
+ if (msg_len > 256 * 1024)
+ fatal("msg_recv: read: bad msg_len %d", msg_len);
+ buffer_clear(m);
+ buffer_append_space(m, msg_len);
+ res = atomicio(read, fd, buffer_ptr(m), msg_len);
+ if (res != msg_len)
+ fatal("msg_recv: read: %ld != msg_len", (long)res);
+ return 0;
+}
diff --git a/crypto/openssh/msg.h b/crypto/openssh/msg.h
new file mode 100644
index 0000000..13fa95b
--- /dev/null
+++ b/crypto/openssh/msg.h
@@ -0,0 +1,31 @@
+/* $OpenBSD: msg.h,v 1.1 2002/05/23 19:24:30 markus Exp $ */
+/*
+ * Copyright (c) 2002 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef SSH_MSG_H
+#define SSH_MSG_H
+
+void msg_send(int, u_char, Buffer *);
+int msg_recv(int, Buffer *);
+
+#endif
diff --git a/crypto/openssh/myproposal.h b/crypto/openssh/myproposal.h
index 1caf04a..62f5cfb 100644
--- a/crypto/openssh/myproposal.h
+++ b/crypto/openssh/myproposal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: myproposal.h,v 1.13 2002/01/21 22:30:12 markus Exp $ */
+/* $OpenBSD: myproposal.h,v 1.14 2002/04/03 09:26:11 markus Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -27,7 +27,7 @@
#define KEX_DEFAULT_PK_ALG "ssh-rsa,ssh-dss"
#define KEX_DEFAULT_ENCRYPT \
"aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour," \
- "aes192-cbc,aes256-cbc"
+ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se"
#define KEX_DEFAULT_MAC \
"hmac-md5,hmac-sha1,hmac-ripemd160," \
"hmac-ripemd160@openssh.com," \
diff --git a/crypto/openssh/nchan.c b/crypto/openssh/nchan.c
index 8153abb..b9b304d 100644
--- a/crypto/openssh/nchan.c
+++ b/crypto/openssh/nchan.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: nchan.c,v 1.44 2002/01/21 23:27:10 markus Exp $");
+RCSID("$OpenBSD: nchan.c,v 1.47 2002/06/19 00:27:55 deraadt Exp $");
#include "ssh1.h"
#include "ssh2.h"
@@ -302,6 +302,7 @@ static void
chan_rcvd_eof2(Channel *c)
{
debug("channel %d: rcvd eof", c->self);
+ c->flags |= CHAN_EOF_RCVD;
if (c->ostate == CHAN_OUTPUT_OPEN)
chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
}
@@ -330,6 +331,7 @@ chan_send_eof2(Channel *c)
packet_start(SSH2_MSG_CHANNEL_EOF);
packet_put_int(c->remote_id);
packet_send();
+ c->flags |= CHAN_EOF_SENT;
break;
default:
error("channel %d: cannot send eof for istate %d",
@@ -365,7 +367,8 @@ chan_rcvd_ieof(Channel *c)
else
chan_rcvd_ieof1(c);
if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
- buffer_len(&c->output) == 0)
+ buffer_len(&c->output) == 0 &&
+ !CHANNEL_EFD_OUTPUT_ACTIVE(c))
chan_obuf_empty(c);
}
void
@@ -404,39 +407,30 @@ chan_is_dead(Channel *c, int send)
debug("channel %d: is dead", c->self);
return 1;
}
- /*
- * we have to delay the close message if the efd (for stderr) is
- * still active
- */
- if (((c->extended_usage != CHAN_EXTENDED_IGNORE) &&
- buffer_len(&c->extended) > 0)
-#if 0
- || ((c->extended_usage == CHAN_EXTENDED_READ) &&
- c->efd != -1)
-#endif
- ) {
- debug2("channel %d: active efd: %d len %d type %s",
- c->self, c->efd, buffer_len(&c->extended),
- c->extended_usage==CHAN_EXTENDED_READ ?
- "read": "write");
- } else {
- if (!(c->flags & CHAN_CLOSE_SENT)) {
- if (send) {
- chan_send_close2(c);
- } else {
- /* channel would be dead if we sent a close */
- if (c->flags & CHAN_CLOSE_RCVD) {
- debug("channel %d: almost dead",
- c->self);
- return 1;
- }
+ if ((datafellows & SSH_BUG_EXTEOF) &&
+ c->extended_usage == CHAN_EXTENDED_WRITE &&
+ c->efd != -1 &&
+ buffer_len(&c->extended) > 0) {
+ debug2("channel %d: active efd: %d len %d",
+ c->self, c->efd, buffer_len(&c->extended));
+ return 0;
+ }
+ if (!(c->flags & CHAN_CLOSE_SENT)) {
+ if (send) {
+ chan_send_close2(c);
+ } else {
+ /* channel would be dead if we sent a close */
+ if (c->flags & CHAN_CLOSE_RCVD) {
+ debug("channel %d: almost dead",
+ c->self);
+ return 1;
}
}
- if ((c->flags & CHAN_CLOSE_SENT) &&
- (c->flags & CHAN_CLOSE_RCVD)) {
- debug("channel %d: is dead", c->self);
- return 1;
- }
+ }
+ if ((c->flags & CHAN_CLOSE_SENT) &&
+ (c->flags & CHAN_CLOSE_RCVD)) {
+ debug("channel %d: is dead", c->self);
+ return 1;
}
return 0;
}
diff --git a/crypto/openssh/packet.c b/crypto/openssh/packet.c
index b3e6d84..759361b 100644
--- a/crypto/openssh/packet.c
+++ b/crypto/openssh/packet.c
@@ -37,7 +37,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: packet.c,v 1.90 2002/02/27 21:23:13 stevesk Exp $");
+RCSID("$OpenBSD: packet.c,v 1.95 2002/06/19 18:01:00 markus Exp $");
#include "xmalloc.h"
#include "buffer.h"
@@ -60,6 +60,7 @@ RCSID("$OpenBSD: packet.c,v 1.90 2002/02/27 21:23:13 stevesk Exp $");
#include "log.h"
#include "canohost.h"
#include "misc.h"
+#include "ssh.h"
#ifdef PACKET_DEBUG
#define DBG(x) x
@@ -86,10 +87,10 @@ static CipherContext receive_context;
static CipherContext send_context;
/* Buffer for raw input data from the socket. */
-static Buffer input;
+Buffer input;
/* Buffer for raw output data going to the socket. */
-static Buffer output;
+Buffer output;
/* Buffer for the partial outgoing packet being constructed. */
static Buffer outgoing_packet;
@@ -115,6 +116,12 @@ static int interactive_mode = 0;
/* Session key information for Encryption and MAC */
Newkeys *newkeys[MODE_MAX];
+static u_int32_t read_seqnr = 0;
+static u_int32_t send_seqnr = 0;
+
+/* Session key for protocol v1 */
+static u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
+static u_int ssh1_keylen;
/* roundup current message to extra_pad bytes */
static u_char extra_pad = 0;
@@ -171,6 +178,99 @@ packet_connection_is_on_socket(void)
return 1;
}
+/*
+ * Exports an IV from the CipherContext required to export the key
+ * state back from the unprivileged child to the privileged parent
+ * process.
+ */
+
+void
+packet_get_keyiv(int mode, u_char *iv, u_int len)
+{
+ CipherContext *cc;
+
+ if (mode == MODE_OUT)
+ cc = &send_context;
+ else
+ cc = &receive_context;
+
+ cipher_get_keyiv(cc, iv, len);
+}
+
+int
+packet_get_keycontext(int mode, u_char *dat)
+{
+ CipherContext *cc;
+
+ if (mode == MODE_OUT)
+ cc = &send_context;
+ else
+ cc = &receive_context;
+
+ return (cipher_get_keycontext(cc, dat));
+}
+
+void
+packet_set_keycontext(int mode, u_char *dat)
+{
+ CipherContext *cc;
+
+ if (mode == MODE_OUT)
+ cc = &send_context;
+ else
+ cc = &receive_context;
+
+ cipher_set_keycontext(cc, dat);
+}
+
+int
+packet_get_keyiv_len(int mode)
+{
+ CipherContext *cc;
+
+ if (mode == MODE_OUT)
+ cc = &send_context;
+ else
+ cc = &receive_context;
+
+ return (cipher_get_keyiv_len(cc));
+}
+void
+packet_set_iv(int mode, u_char *dat)
+{
+ CipherContext *cc;
+
+ if (mode == MODE_OUT)
+ cc = &send_context;
+ else
+ cc = &receive_context;
+
+ cipher_set_keyiv(cc, dat);
+}
+int
+packet_get_ssh1_cipher()
+{
+ return (cipher_get_number(receive_context.cipher));
+}
+
+
+u_int32_t
+packet_get_seqnr(int mode)
+{
+ return (mode == MODE_IN ? read_seqnr : send_seqnr);
+}
+
+void
+packet_set_seqnr(int mode, u_int32_t seqnr)
+{
+ if (mode == MODE_IN)
+ read_seqnr = seqnr;
+ else if (mode == MODE_OUT)
+ send_seqnr = seqnr;
+ else
+ fatal("packet_set_seqnr: bad mode %d", mode);
+}
+
/* returns 1 if connection is via ipv4 */
int
@@ -291,6 +391,7 @@ packet_start_compression(int level)
* key is used for both sending and reception. However, both directions are
* encrypted independently of each other.
*/
+
void
packet_set_encryption_key(const u_char *key, u_int keylen,
int number)
@@ -300,10 +401,23 @@ packet_set_encryption_key(const u_char *key, u_int keylen,
fatal("packet_set_encryption_key: unknown cipher number %d", number);
if (keylen < 20)
fatal("packet_set_encryption_key: keylen too small: %d", keylen);
+ if (keylen > SSH_SESSION_KEY_LENGTH)
+ fatal("packet_set_encryption_key: keylen too big: %d", keylen);
+ memcpy(ssh1_key, key, keylen);
+ ssh1_keylen = keylen;
cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT);
cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT);
}
+u_int
+packet_get_encryption_key(u_char *key)
+{
+ if (key == NULL)
+ return (ssh1_keylen);
+ memcpy(key, ssh1_key, ssh1_keylen);
+ return (ssh1_keylen);
+}
+
/* Start constructing a packet to send. */
void
packet_start(u_char type)
@@ -433,7 +547,7 @@ packet_send1(void)
*/
}
-static void
+void
set_newkeys(int mode)
{
Enc *enc;
@@ -477,8 +591,9 @@ set_newkeys(int mode)
DBG(debug("cipher_init_context: %d", mode));
cipher_init(cc, enc->cipher, enc->key, enc->key_len,
enc->iv, enc->block_size, encrypt);
- memset(enc->iv, 0, enc->block_size);
- memset(enc->key, 0, enc->key_len);
+ /* Deleting the keys does not gain extra security */
+ /* memset(enc->iv, 0, enc->block_size);
+ memset(enc->key, 0, enc->key_len); */
if (comp->type != 0 && comp->enabled == 0) {
packet_init_compression();
if (mode == MODE_OUT)
@@ -495,7 +610,6 @@ set_newkeys(int mode)
static void
packet_send2(void)
{
- static u_int32_t seqnr = 0;
u_char type, *cp, *macbuf = NULL;
u_char padlen, pad;
u_int packet_length = 0;
@@ -549,7 +663,7 @@ packet_send2(void)
/* will wrap if extra_pad+padlen > 255 */
extra_pad = roundup(extra_pad, block_size);
pad = extra_pad - ((len + padlen) % extra_pad);
- debug("packet_send2: adding %d (len %d padlen %d extra_pad %d)",
+ debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)",
pad, len, padlen, extra_pad);
padlen += pad;
extra_pad = 0;
@@ -576,10 +690,10 @@ packet_send2(void)
/* compute MAC over seqnr and packet(length fields, payload, padding) */
if (mac && mac->enabled) {
- macbuf = mac_compute(mac, seqnr,
+ macbuf = mac_compute(mac, send_seqnr,
buffer_ptr(&outgoing_packet),
buffer_len(&outgoing_packet));
- DBG(debug("done calc MAC out #%d", seqnr));
+ DBG(debug("done calc MAC out #%d", send_seqnr));
}
/* encrypt packet and append to output buffer. */
cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
@@ -593,7 +707,7 @@ packet_send2(void)
buffer_dump(&output);
#endif
/* increment sequence number for outgoing packets */
- if (++seqnr == 0)
+ if (++send_seqnr == 0)
log("outgoing seqnr wraps around");
buffer_clear(&outgoing_packet);
@@ -783,7 +897,6 @@ packet_read_poll1(void)
static int
packet_read_poll2(u_int32_t *seqnr_p)
{
- static u_int32_t seqnr = 0;
static u_int packet_length = 0;
u_int padlen, need;
u_char *macbuf, *cp, type;
@@ -845,17 +958,17 @@ packet_read_poll2(u_int32_t *seqnr_p)
* increment sequence number for incoming packet
*/
if (mac && mac->enabled) {
- macbuf = mac_compute(mac, seqnr,
+ macbuf = mac_compute(mac, read_seqnr,
buffer_ptr(&incoming_packet),
buffer_len(&incoming_packet));
if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
packet_disconnect("Corrupted MAC on input.");
- DBG(debug("MAC #%d ok", seqnr));
+ DBG(debug("MAC #%d ok", read_seqnr));
buffer_consume(&input, mac->mac_len);
}
if (seqnr_p != NULL)
- *seqnr_p = seqnr;
- if (++seqnr == 0)
+ *seqnr_p = read_seqnr;
+ if (++read_seqnr == 0)
log("incoming seqnr wraps around");
/* get padlen */
diff --git a/crypto/openssh/packet.h b/crypto/openssh/packet.h
index d6bf2aa..3ff7559 100644
--- a/crypto/openssh/packet.h
+++ b/crypto/openssh/packet.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.h,v 1.33 2002/03/04 17:27:39 stevesk Exp $ */
+/* $OpenBSD: packet.h,v 1.35 2002/06/19 18:01:00 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -24,6 +24,7 @@ int packet_get_connection_in(void);
int packet_get_connection_out(void);
void packet_close(void);
void packet_set_encryption_key(const u_char *, u_int, int);
+u_int packet_get_encryption_key(u_char *);
void packet_set_protocol_flags(u_int);
u_int packet_get_protocol_flags(void);
void packet_start_compression(int);
@@ -56,6 +57,16 @@ void *packet_get_string(u_int *length_ptr);
void packet_disconnect(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2)));
+void set_newkeys(int mode);
+int packet_get_keyiv_len(int);
+void packet_get_keyiv(int, u_char *, u_int);
+int packet_get_keycontext(int, u_char *);
+void packet_set_keycontext(int, u_char *);
+u_int32_t packet_get_seqnr(int);
+void packet_set_seqnr(int, u_int32_t);
+int packet_get_ssh1_cipher(void);
+void packet_set_iv(int, u_char *);
+
void packet_write_poll(void);
void packet_write_wait(void);
int packet_have_data_to_write(void);
diff --git a/crypto/openssh/pathnames.h b/crypto/openssh/pathnames.h
index b451312..3bc6b50 100644
--- a/crypto/openssh/pathnames.h
+++ b/crypto/openssh/pathnames.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pathnames.h,v 1.11 2002/02/09 17:37:34 deraadt Exp $ */
+/* $OpenBSD: pathnames.h,v 1.13 2002/05/23 19:24:30 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -110,6 +110,9 @@
*/
#define _PATH_SSH_ASKPASS_DEFAULT "/usr/X11R6/bin/ssh-askpass"
+/* Location of ssh-keysign for hostbased authentication */
+#define _PATH_SSH_KEY_SIGN "/usr/libexec/ssh-keysign"
+
/* xauth for X11 forwarding */
#define _PATH_XAUTH "/usr/X11R6/bin/xauth"
@@ -122,3 +125,6 @@
/* for sftp */
#define _PATH_SFTP_SERVER "/usr/libexec/sftp-server"
#define _PATH_LS "ls"
+
+/* chroot directory for unprivileged user when UsePrivilegeSeparation=yes */
+#define _PATH_PRIVSEP_CHROOT_DIR "/var/empty"
diff --git a/crypto/openssh/radix.c b/crypto/openssh/radix.c
index e604357..580e7e0 100644
--- a/crypto/openssh/radix.c
+++ b/crypto/openssh/radix.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 1999 Dug Song. All rights reserved.
+ * Copyright (c) 2002 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,190 +26,132 @@
#include "includes.h"
#include "uuencode.h"
-RCSID("$OpenBSD: radix.c,v 1.17 2001/11/19 19:02:16 mpech Exp $");
+RCSID("$OpenBSD: radix.c,v 1.21 2002/06/19 00:27:55 deraadt Exp $");
#ifdef AFS
#include <krb.h>
#include <radix.h>
+#include "bufaux.h"
-typedef u_char my_u_char;
-typedef u_int my_u_int32_t;
-typedef u_short my_u_short;
-
-/* Nasty macros from BIND-4.9.2 */
-
-#define GETSHORT(s, cp) { \
- my_u_char *t_cp = (my_u_char *)(cp); \
- (s) = (((my_u_short)t_cp[0]) << 8) \
- | (((my_u_short)t_cp[1])) \
- ; \
- (cp) += 2; \
-}
-
-#define GETLONG(l, cp) { \
- my_u_char *t_cp = (my_u_char *)(cp); \
- (l) = (((my_u_int32_t)t_cp[0]) << 24) \
- | (((my_u_int32_t)t_cp[1]) << 16) \
- | (((my_u_int32_t)t_cp[2]) << 8) \
- | (((my_u_int32_t)t_cp[3])) \
- ; \
- (cp) += 4; \
-}
-
-#define PUTSHORT(s, cp) { \
- my_u_short t_s = (my_u_short)(s); \
- my_u_char *t_cp = (my_u_char *)(cp); \
- *t_cp++ = t_s >> 8; \
- *t_cp = t_s; \
- (cp) += 2; \
-}
+int
+creds_to_radix(CREDENTIALS *creds, u_char *buf, size_t buflen)
+{
+ Buffer b;
+ int ret;
-#define PUTLONG(l, cp) { \
- my_u_int32_t t_l = (my_u_int32_t)(l); \
- my_u_char *t_cp = (my_u_char *)(cp); \
- *t_cp++ = t_l >> 24; \
- *t_cp++ = t_l >> 16; \
- *t_cp++ = t_l >> 8; \
- *t_cp = t_l; \
- (cp) += 4; \
-}
+ buffer_init(&b);
-#define GETSTRING(s, p, p_l) { \
- char *p_targ = (p) + p_l; \
- char *s_c = (s); \
- char *p_c = (p); \
- while (*p_c && (p_c < p_targ)) { \
- *s_c++ = *p_c++; \
- } \
- if (p_c == p_targ) { \
- return 1; \
- } \
- *s_c = *p_c++; \
- (p_l) = (p_l) - (p_c - (p)); \
- (p) = p_c; \
-}
+ buffer_put_char(&b, 1); /* version */
+ buffer_append(&b, creds->service, strlen(creds->service));
+ buffer_put_char(&b, '\0');
+ buffer_append(&b, creds->instance, strlen(creds->instance));
+ buffer_put_char(&b, '\0');
+ buffer_append(&b, creds->realm, strlen(creds->realm));
+ buffer_put_char(&b, '\0');
+ buffer_append(&b, creds->pname, strlen(creds->pname));
+ buffer_put_char(&b, '\0');
+ buffer_append(&b, creds->pinst, strlen(creds->pinst));
+ buffer_put_char(&b, '\0');
-int
-creds_to_radix(CREDENTIALS *creds, u_char *buf, size_t buflen)
-{
- char *p, *s;
- int len;
- char temp[2048];
-
- p = temp;
- *p++ = 1; /* version */
- s = creds->service;
- while (*s)
- *p++ = *s++;
- *p++ = *s;
- s = creds->instance;
- while (*s)
- *p++ = *s++;
- *p++ = *s;
- s = creds->realm;
- while (*s)
- *p++ = *s++;
- *p++ = *s;
-
- s = creds->pname;
- while (*s)
- *p++ = *s++;
- *p++ = *s;
- s = creds->pinst;
- while (*s)
- *p++ = *s++;
- *p++ = *s;
/* Null string to repeat the realm. */
- *p++ = '\0';
+ buffer_put_char(&b, '\0');
- PUTLONG(creds->issue_date, p);
- {
- u_int endTime;
- endTime = (u_int) krb_life_to_time(creds->issue_date,
- creds->lifetime);
- PUTLONG(endTime, p);
- }
+ buffer_put_int(&b, creds->issue_date);
+ buffer_put_int(&b, krb_life_to_time(creds->issue_date,
+ creds->lifetime));
+ buffer_append(&b, creds->session, sizeof(creds->session));
+ buffer_put_short(&b, creds->kvno);
- memcpy(p, &creds->session, sizeof(creds->session));
- p += sizeof(creds->session);
+ /* 32 bit size + data */
+ buffer_put_string(&b, creds->ticket_st.dat, creds->ticket_st.length);
- PUTSHORT(creds->kvno, p);
- PUTLONG(creds->ticket_st.length, p);
+ ret = uuencode(buffer_ptr(&b), buffer_len(&b), (char *)buf, buflen);
- memcpy(p, creds->ticket_st.dat, creds->ticket_st.length);
- p += creds->ticket_st.length;
- len = p - temp;
-
- return (uuencode((u_char *)temp, len, (char *)buf, buflen));
+ buffer_free(&b);
+ return ret;
}
+#define GETSTRING(b, t, tlen) \
+ do { \
+ int i, found = 0; \
+ for (i = 0; i < tlen; i++) { \
+ if (buffer_len(b) == 0) \
+ goto done; \
+ t[i] = buffer_get_char(b); \
+ if (t[i] == '\0') { \
+ found = 1; \
+ break; \
+ } \
+ } \
+ if (!found) \
+ goto done; \
+ } while(0)
+
int
radix_to_creds(const char *buf, CREDENTIALS *creds)
{
+ Buffer b;
+ char c, version, *space, *p;
+ u_int endTime;
+ int len, blen, ret;
- char *p;
- int len, tl;
- char version;
- char temp[2048];
+ ret = 0;
+ blen = strlen(buf);
- len = uudecode(buf, (u_char *)temp, sizeof(temp));
- if (len < 0)
+ /* sanity check for size */
+ if (blen > 8192)
return 0;
- p = temp;
+ buffer_init(&b);
+ space = buffer_append_space(&b, blen);
/* check version and length! */
+ len = uudecode(buf, space, blen);
if (len < 1)
- return 0;
- version = *p;
- p++;
- len--;
+ goto done;
+
+ version = buffer_get_char(&b);
+
+ GETSTRING(&b, creds->service, sizeof creds->service);
+ GETSTRING(&b, creds->instance, sizeof creds->instance);
+ GETSTRING(&b, creds->realm, sizeof creds->realm);
+ GETSTRING(&b, creds->pname, sizeof creds->pname);
+ GETSTRING(&b, creds->pinst, sizeof creds->pinst);
- GETSTRING(creds->service, p, len);
- GETSTRING(creds->instance, p, len);
- GETSTRING(creds->realm, p, len);
+ if (buffer_len(&b) == 0)
+ goto done;
- GETSTRING(creds->pname, p, len);
- GETSTRING(creds->pinst, p, len);
/* Ignore possibly different realm. */
- while (*p && len)
- p++, len--;
- if (len == 0)
- return 0;
- p++, len--;
+ while (buffer_len(&b) > 0 && (c = buffer_get_char(&b)) != '\0')
+ ;
- /* Enough space for remaining fixed-length parts? */
- if (len < (4 + 4 + sizeof(creds->session) + 2 + 4))
- return 0;
+ if (buffer_len(&b) == 0)
+ goto done;
- GETLONG(creds->issue_date, p);
- len -= 4;
- {
- u_int endTime;
- GETLONG(endTime, p);
- len -= 4;
- creds->lifetime = krb_time_to_life(creds->issue_date, endTime);
- }
-
- memcpy(&creds->session, p, sizeof(creds->session));
- p += sizeof(creds->session);
- len -= sizeof(creds->session);
-
- GETSHORT(creds->kvno, p);
- len -= 2;
- GETLONG(creds->ticket_st.length, p);
- len -= 4;
-
- tl = creds->ticket_st.length;
- if (tl < 0 || tl > len || tl > sizeof(creds->ticket_st.dat))
- return 0;
+ creds->issue_date = buffer_get_int(&b);
+
+ endTime = buffer_get_int(&b);
+ creds->lifetime = krb_time_to_life(creds->issue_date, endTime);
+
+ len = buffer_len(&b);
+ if (len < sizeof(creds->session))
+ goto done;
+ memcpy(&creds->session, buffer_ptr(&b), sizeof(creds->session));
+ buffer_consume(&b, sizeof(creds->session));
+
+ creds->kvno = buffer_get_short(&b);
- memcpy(creds->ticket_st.dat, p, tl);
- p += tl;
- len -= tl;
+ p = buffer_get_string(&b, &len);
+ if (len < 0 || len > sizeof(creds->ticket_st.dat))
+ goto done;
+ memcpy(&creds->ticket_st.dat, p, len);
+ creds->ticket_st.length = len;
- return 1;
+ ret = 1;
+done:
+ buffer_free(&b);
+ return ret;
}
#endif /* AFS */
diff --git a/crypto/openssh/readconf.c b/crypto/openssh/readconf.c
index 45e95d9..f07c89a 100644
--- a/crypto/openssh/readconf.c
+++ b/crypto/openssh/readconf.c
@@ -12,7 +12,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: readconf.c,v 1.95 2002/02/04 12:15:25 markus Exp $");
+RCSID("$OpenBSD: readconf.c,v 1.100 2002/06/19 00:27:55 deraadt Exp $");
#include "ssh.h"
#include "xmalloc.h"
@@ -41,7 +41,7 @@ RCSID("$OpenBSD: readconf.c,v 1.95 2002/02/04 12:15:25 markus Exp $");
# that they are given in.
Host *.ngs.fi ngs.fi
- FallBackToRsh no
+ User foo
Host fake.com
HostName another.host.name.real.org
@@ -65,7 +65,7 @@ RCSID("$OpenBSD: readconf.c,v 1.95 2002/02/04 12:15:25 markus Exp $");
ProxyCommand ssh-proxy %h %p
Host *.fr
- UseRsh yes
+ PublicKeyAuthentication no
Host *.su
Cipher none
@@ -79,8 +79,6 @@ RCSID("$OpenBSD: readconf.c,v 1.95 2002/02/04 12:15:25 markus Exp $");
PasswordAuthentication yes
RSAAuthentication yes
RhostsRSAAuthentication yes
- FallBackToRsh no
- UseRsh no
StrictHostKeyChecking yes
KeepAlives no
IdentityFile ~/.ssh/identity
@@ -94,7 +92,7 @@ RCSID("$OpenBSD: readconf.c,v 1.95 2002/02/04 12:15:25 markus Exp $");
typedef enum {
oBadOption,
oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
- oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
+ oPasswordAuthentication, oRSAAuthentication,
oChallengeResponseAuthentication, oXAuthLocation,
#if defined(KRB4) || defined(KRB5)
oKerberosAuthentication,
@@ -115,7 +113,8 @@ typedef enum {
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
- oClearAllForwardings, oNoHostAuthenticationForLocalhost
+ oClearAllForwardings, oNoHostAuthenticationForLocalhost,
+ oDeprecated
} OpCodes;
/* Textual representations of the tokens. */
@@ -150,8 +149,8 @@ static struct {
#ifdef AFS
{ "afstokenpassing", oAFSTokenPassing },
#endif
- { "fallbacktorsh", oFallBackToRsh },
- { "usersh", oUseRsh },
+ { "fallbacktorsh", oDeprecated },
+ { "usersh", oDeprecated },
{ "identityfile", oIdentityFile },
{ "identityfile2", oIdentityFile }, /* alias */
{ "hostname", oHostName },
@@ -371,14 +370,6 @@ parse_flag:
intptr = &options->afs_token_passing;
goto parse_flag;
#endif
- case oFallBackToRsh:
- intptr = &options->fallback_to_rsh;
- goto parse_flag;
-
- case oUseRsh:
- intptr = &options->use_rsh;
- goto parse_flag;
-
case oBatchMode:
intptr = &options->batch_mode;
goto parse_flag;
@@ -676,6 +667,11 @@ parse_int:
*intptr = value;
break;
+ case oDeprecated:
+ debug("%s line %d: Deprecated option \"%s\"",
+ filename, linenum, keyword);
+ return 0;
+
default:
fatal("process_config_line: Unimplemented opcode %d", opcode);
}
@@ -763,8 +759,6 @@ initialize_options(Options * options)
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;
options->check_host_ip = -1;
options->strict_host_key_checking = -1;
@@ -820,7 +814,7 @@ fill_default_options(Options * options)
if (options->use_privileged_port == -1)
options->use_privileged_port = 0;
if (options->rhosts_authentication == -1)
- options->rhosts_authentication = 1;
+ options->rhosts_authentication = 0;
if (options->rsa_authentication == -1)
options->rsa_authentication = 1;
if (options->pubkey_authentication == -1)
@@ -844,13 +838,9 @@ fill_default_options(Options * options)
if (options->kbd_interactive_authentication == -1)
options->kbd_interactive_authentication = 1;
if (options->rhosts_rsa_authentication == -1)
- options->rhosts_rsa_authentication = 1;
+ options->rhosts_rsa_authentication = 0;
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)
- options->use_rsh = 0;
if (options->batch_mode == -1)
options->batch_mode = 0;
if (options->check_host_ip == -1)
diff --git a/crypto/openssh/readconf.h b/crypto/openssh/readconf.h
index 4fa9040..92af535 100644
--- a/crypto/openssh/readconf.h
+++ b/crypto/openssh/readconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.h,v 1.42 2002/03/04 17:27:39 stevesk Exp $ */
+/* $OpenBSD: readconf.h,v 1.43 2002/06/08 05:17:01 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -54,8 +54,6 @@ typedef struct {
* authentication. */
int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */
- int fallback_to_rsh;/* Use rsh if cannot connect with ssh. */
- int use_rsh; /* Always use rsh (don\'t try ssh). */
int batch_mode; /* Batch mode: do not ask for passwords. */
int check_host_ip; /* Also keep track of keys for IP address */
int strict_host_key_checking; /* Strict host key checking. */
diff --git a/crypto/openssh/readpass.c b/crypto/openssh/readpass.c
index c55dd21..dc1b11f 100644
--- a/crypto/openssh/readpass.c
+++ b/crypto/openssh/readpass.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: readpass.c,v 1.26 2002/02/13 00:39:15 markus Exp $");
+RCSID("$OpenBSD: readpass.c,v 1.27 2002/03/26 15:58:46 markus Exp $");
#include <readpassphrase.h>
@@ -120,8 +120,11 @@ read_passphrase(const char *prompt, int flags)
return ssh_askpass(askpass, prompt);
}
- if (readpassphrase(prompt, buf, sizeof buf, rppflags) == NULL)
+ if (readpassphrase(prompt, buf, sizeof buf, rppflags) == NULL) {
+ if (flags & RP_ALLOW_EOF)
+ return NULL;
return xstrdup("");
+ }
ret = xstrdup(buf);
memset(buf, 'x', sizeof buf);
diff --git a/crypto/openssh/readpass.h b/crypto/openssh/readpass.h
index 229973c..a45d32f 100644
--- a/crypto/openssh/readpass.h
+++ b/crypto/openssh/readpass.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: readpass.h,v 1.6 2001/06/26 17:27:24 markus Exp $ */
+/* $OpenBSD: readpass.h,v 1.7 2002/03/26 15:58:46 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -14,5 +14,6 @@
#define RP_ECHO 0x0001
#define RP_ALLOW_STDIN 0x0002
+#define RP_ALLOW_EOF 0x0004
char *read_passphrase(const char *, int);
diff --git a/crypto/openssh/scard.c b/crypto/openssh/scard.c
index e1b1fb6..e71815e 100644
--- a/crypto/openssh/scard.c
+++ b/crypto/openssh/scard.c
@@ -24,16 +24,30 @@
#ifdef SMARTCARD
#include "includes.h"
-RCSID("$OpenBSD: scard.c,v 1.17 2001/12/27 18:22:16 markus Exp $");
+RCSID("$OpenBSD: scard.c,v 1.25 2002/03/26 18:46:59 rees Exp $");
-#include <openssl/engine.h>
+#include <openssl/evp.h>
#include <sectok.h>
#include "key.h"
#include "log.h"
#include "xmalloc.h"
+#include "readpass.h"
#include "scard.h"
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+#define USE_ENGINE
+#define RSA_get_default_method RSA_get_default_openssl_method
+#else
+#endif
+
+#ifdef USE_ENGINE
+#include <openssl/engine.h>
+#define sc_get_rsa sc_get_engine
+#else
+#define sc_get_rsa sc_get_rsa_method
+#endif
+
#define CLA_SSH 0x05
#define INS_DECRYPT 0x10
#define INS_GET_KEYLENGTH 0x20
@@ -42,10 +56,17 @@ RCSID("$OpenBSD: scard.c,v 1.17 2001/12/27 18:22:16 markus Exp $");
#define MAX_BUF_SIZE 256
+u_char DEFAUT0[] = {0xad, 0x9f, 0x61, 0xfe, 0xfa, 0x20, 0xce, 0x63};
+
static int sc_fd = -1;
static char *sc_reader_id = NULL;
+static char *sc_pin = NULL;
static int cla = 0x00; /* class */
+static void sc_mk_digest(const char *pin, u_char *digest);
+static int get_AUT0(u_char *aut0);
+static int try_AUT0(void);
+
/* interface to libsectok */
static int
@@ -126,8 +147,7 @@ sc_read_pubkey(Key * k)
n = NULL;
if (sc_fd < 0) {
- status = sc_init();
- if (status < 0 )
+ if (sc_init() < 0)
goto err;
}
@@ -145,6 +165,12 @@ sc_read_pubkey(Key * k)
n = xmalloc(len);
/* get n */
sectok_apdu(sc_fd, CLA_SSH, INS_GET_PUBKEY, 0, 0, 0, NULL, len, n, &sw);
+
+ if (sw == 0x6982) {
+ if (try_AUT0() < 0)
+ goto err;
+ sectok_apdu(sc_fd, CLA_SSH, INS_GET_PUBKEY, 0, 0, 0, NULL, len, n, &sw);
+ }
if (!sectok_swOK(sw)) {
error("could not obtain public key: %s", sectok_get_sw(sw));
goto err;
@@ -178,7 +204,8 @@ err:
/* private key operations */
static int
-sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding)
+sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa,
+ int padding)
{
u_char *padded = NULL;
int sw, len, olen, status = -1;
@@ -197,16 +224,15 @@ sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding)
len = BN_num_bytes(rsa->n);
padded = xmalloc(len);
- sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, from, 0, NULL, &sw);
- if (!sectok_swOK(sw)) {
- error("sc_private_decrypt: INS_DECRYPT failed: %s",
- sectok_get_sw(sw));
- goto err;
+ sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, from, len, padded, &sw);
+
+ if (sw == 0x6982) {
+ if (try_AUT0() < 0)
+ goto err;
+ sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, from, len, padded, &sw);
}
- sectok_apdu(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, 0, NULL,
- len, padded, &sw);
if (!sectok_swOK(sw)) {
- error("sc_private_decrypt: INS_GET_RESPONSE failed: %s",
+ error("sc_private_decrypt: INS_DECRYPT failed: %s",
sectok_get_sw(sw));
goto err;
}
@@ -220,7 +246,8 @@ err:
}
static int
-sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding)
+sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa,
+ int padding)
{
u_char *padded = NULL;
int sw, len, status = -1;
@@ -238,20 +265,18 @@ sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding)
len = BN_num_bytes(rsa->n);
padded = xmalloc(len);
- if (RSA_padding_add_PKCS1_type_1(padded, len, from, flen) <= 0) {
+ if (RSA_padding_add_PKCS1_type_1(padded, len, (u_char *)from, flen) <= 0) {
error("RSA_padding_add_PKCS1_type_1 failed");
goto err;
}
- sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, 0, NULL, &sw);
- if (!sectok_swOK(sw)) {
- error("sc_private_decrypt: INS_DECRYPT failed: %s",
- sectok_get_sw(sw));
- goto err;
+ sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, len, to, &sw);
+ if (sw == 0x6982) {
+ if (try_AUT0() < 0)
+ goto err;
+ sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, len, to, &sw);
}
- sectok_apdu(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, 0, NULL,
- len, to, &sw);
if (!sectok_swOK(sw)) {
- error("sc_private_decrypt: INS_GET_RESPONSE failed: %s",
+ error("sc_private_encrypt: INS_DECRYPT failed: %s",
sectok_get_sw(sw));
goto err;
}
@@ -275,31 +300,18 @@ sc_finish(RSA *rsa)
return 1;
}
-
/* engine for overloading private key operations */
-static ENGINE *smart_engine = NULL;
-static RSA_METHOD smart_rsa =
-{
- "sectok",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 0,
- NULL,
-};
-
-ENGINE *
-sc_get_engine(void)
+static RSA_METHOD *
+sc_get_rsa_method(void)
{
- RSA_METHOD *def;
+ static RSA_METHOD smart_rsa;
+ const RSA_METHOD *def = RSA_get_default_method();
+
+ /* use the OpenSSL version */
+ memcpy(&smart_rsa, def, sizeof(smart_rsa));
- def = RSA_get_default_openssl_method();
+ smart_rsa.name = "sectok";
/* overload */
smart_rsa.rsa_priv_enc = sc_private_encrypt;
@@ -309,23 +321,22 @@ sc_get_engine(void)
orig_finish = def->finish;
smart_rsa.finish = sc_finish;
- /* just use the OpenSSL version */
- smart_rsa.rsa_pub_enc = def->rsa_pub_enc;
- smart_rsa.rsa_pub_dec = def->rsa_pub_dec;
- smart_rsa.rsa_mod_exp = def->rsa_mod_exp;
- smart_rsa.bn_mod_exp = def->bn_mod_exp;
- smart_rsa.init = def->init;
- smart_rsa.flags = def->flags;
- smart_rsa.app_data = def->app_data;
- smart_rsa.rsa_sign = def->rsa_sign;
- smart_rsa.rsa_verify = def->rsa_verify;
+ return &smart_rsa;
+}
+
+#ifdef USE_ENGINE
+static ENGINE *
+sc_get_engine(void)
+{
+ static ENGINE *smart_engine = NULL;
if ((smart_engine = ENGINE_new()) == NULL)
fatal("ENGINE_new failed");
ENGINE_set_id(smart_engine, "sectok");
ENGINE_set_name(smart_engine, "libsectok");
- ENGINE_set_RSA(smart_engine, &smart_rsa);
+
+ ENGINE_set_RSA(smart_engine, sc_get_rsa_method());
ENGINE_set_DSA(smart_engine, DSA_get_default_openssl_method());
ENGINE_set_DH(smart_engine, DH_get_default_openssl_method());
ENGINE_set_RAND(smart_engine, RAND_SSLeay());
@@ -333,6 +344,7 @@ sc_get_engine(void)
return smart_engine;
}
+#endif
void
sc_close(void)
@@ -343,16 +355,20 @@ sc_close(void)
}
}
-Key *
-sc_get_key(const char *id)
+Key **
+sc_get_keys(const char *id, const char *pin)
{
- Key *k;
- int status;
+ Key *k, *n, **keys;
+ int status, nkeys = 2;
if (sc_reader_id != NULL)
xfree(sc_reader_id);
sc_reader_id = xstrdup(id);
+ if (sc_pin != NULL)
+ xfree(sc_pin);
+ sc_pin = (pin == NULL) ? NULL : xstrdup(pin);
+
k = key_new(KEY_RSA);
if (k == NULL) {
return NULL;
@@ -367,6 +383,175 @@ sc_get_key(const char *id)
key_free(k);
return NULL;
}
- return k;
+ keys = xmalloc((nkeys+1) * sizeof(Key *));
+
+ n = key_new(KEY_RSA1);
+ BN_copy(n->rsa->n, k->rsa->n);
+ BN_copy(n->rsa->e, k->rsa->e);
+ RSA_set_method(n->rsa, sc_get_rsa());
+ n->flags |= KEY_FLAG_EXT;
+ keys[0] = n;
+
+ n = key_new(KEY_RSA);
+ BN_copy(n->rsa->n, k->rsa->n);
+ BN_copy(n->rsa->e, k->rsa->e);
+ RSA_set_method(n->rsa, sc_get_rsa());
+ n->flags |= KEY_FLAG_EXT;
+ keys[1] = n;
+
+ keys[2] = NULL;
+
+ key_free(k);
+ return keys;
+}
+
+#define NUM_RSA_KEY_ELEMENTS 5+1
+#define COPY_RSA_KEY(x, i) \
+ do { \
+ len = BN_num_bytes(prv->rsa->x); \
+ elements[i] = xmalloc(len); \
+ debug("#bytes %d", len); \
+ if (BN_bn2bin(prv->rsa->x, elements[i]) < 0) \
+ goto done; \
+ } while (0)
+
+static void
+sc_mk_digest(const char *pin, u_char *digest)
+{
+ const EVP_MD *evp_md = EVP_sha1();
+ EVP_MD_CTX md;
+
+ EVP_DigestInit(&md, evp_md);
+ EVP_DigestUpdate(&md, pin, strlen(pin));
+ EVP_DigestFinal(&md, digest, NULL);
+}
+
+static int
+get_AUT0(u_char *aut0)
+{
+ char *pass;
+
+ pass = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN);
+ if (pass == NULL)
+ return -1;
+ if (!strcmp(pass, "-")) {
+ memcpy(aut0, DEFAUT0, sizeof DEFAUT0);
+ return 0;
+ }
+ sc_mk_digest(pass, aut0);
+ memset(pass, 0, strlen(pass));
+ xfree(pass);
+ return 0;
+}
+
+static int
+try_AUT0(void)
+{
+ u_char aut0[EVP_MAX_MD_SIZE];
+
+ /* permission denied; try PIN if provided */
+ if (sc_pin && strlen(sc_pin) > 0) {
+ sc_mk_digest(sc_pin, aut0);
+ if (cyberflex_verify_AUT0(sc_fd, cla, aut0, 8) < 0) {
+ error("smartcard passphrase incorrect");
+ return (-1);
+ }
+ } else {
+ /* try default AUT0 key */
+ if (cyberflex_verify_AUT0(sc_fd, cla, DEFAUT0, 8) < 0) {
+ /* default AUT0 key failed; prompt for passphrase */
+ if (get_AUT0(aut0) < 0 ||
+ cyberflex_verify_AUT0(sc_fd, cla, aut0, 8) < 0) {
+ error("smartcard passphrase incorrect");
+ return (-1);
+ }
+ }
+ }
+ return (0);
+}
+
+int
+sc_put_key(Key *prv, const char *id)
+{
+ u_char *elements[NUM_RSA_KEY_ELEMENTS];
+ u_char key_fid[2];
+ u_char AUT0[EVP_MAX_MD_SIZE];
+ int len, status = -1, i, fd = -1, ret;
+ int sw = 0, cla = 0x00;
+
+ for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
+ elements[i] = NULL;
+
+ COPY_RSA_KEY(q, 0);
+ COPY_RSA_KEY(p, 1);
+ COPY_RSA_KEY(iqmp, 2);
+ COPY_RSA_KEY(dmq1, 3);
+ COPY_RSA_KEY(dmp1, 4);
+ COPY_RSA_KEY(n, 5);
+ len = BN_num_bytes(prv->rsa->n);
+ fd = sectok_friendly_open(id, STONOWAIT, &sw);
+ if (fd < 0) {
+ error("sectok_open failed: %s", sectok_get_sw(sw));
+ goto done;
+ }
+ if (! sectok_cardpresent(fd)) {
+ error("smartcard in reader %s not present", id);
+ goto done;
+ }
+ ret = sectok_reset(fd, 0, NULL, &sw);
+ if (ret <= 0) {
+ error("sectok_reset failed: %s", sectok_get_sw(sw));
+ goto done;
+ }
+ if ((cla = cyberflex_inq_class(fd)) < 0) {
+ error("cyberflex_inq_class failed");
+ goto done;
+ }
+ memcpy(AUT0, DEFAUT0, sizeof(DEFAUT0));
+ if (cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) {
+ if (get_AUT0(AUT0) < 0 ||
+ cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) {
+ memset(AUT0, 0, sizeof(DEFAUT0));
+ error("smartcard passphrase incorrect");
+ goto done;
+ }
+ }
+ memset(AUT0, 0, sizeof(DEFAUT0));
+ key_fid[0] = 0x00;
+ key_fid[1] = 0x12;
+ if (cyberflex_load_rsa_priv(fd, cla, key_fid, 5, 8*len, elements,
+ &sw) < 0) {
+ error("cyberflex_load_rsa_priv failed: %s", sectok_get_sw(sw));
+ goto done;
+ }
+ if (!sectok_swOK(sw))
+ goto done;
+ log("cyberflex_load_rsa_priv done");
+ key_fid[0] = 0x73;
+ key_fid[1] = 0x68;
+ if (cyberflex_load_rsa_pub(fd, cla, key_fid, len, elements[5],
+ &sw) < 0) {
+ error("cyberflex_load_rsa_pub failed: %s", sectok_get_sw(sw));
+ goto done;
+ }
+ if (!sectok_swOK(sw))
+ goto done;
+ log("cyberflex_load_rsa_pub done");
+ status = 0;
+
+done:
+ memset(elements[0], '\0', BN_num_bytes(prv->rsa->q));
+ memset(elements[1], '\0', BN_num_bytes(prv->rsa->p));
+ memset(elements[2], '\0', BN_num_bytes(prv->rsa->iqmp));
+ memset(elements[3], '\0', BN_num_bytes(prv->rsa->dmq1));
+ memset(elements[4], '\0', BN_num_bytes(prv->rsa->dmp1));
+ memset(elements[5], '\0', BN_num_bytes(prv->rsa->n));
+
+ for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
+ if (elements[i])
+ xfree(elements[i]);
+ if (fd != -1)
+ sectok_close(fd);
+ return (status);
}
#endif /* SMARTCARD */
diff --git a/crypto/openssh/scard.h b/crypto/openssh/scard.h
index 6ca9916..c0aa9ed 100644
--- a/crypto/openssh/scard.h
+++ b/crypto/openssh/scard.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: scard.h,v 1.7 2002/03/04 17:27:39 stevesk Exp $ */
+/* $OpenBSD: scard.h,v 1.10 2002/03/25 17:34:27 markus Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -24,17 +24,17 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <openssl/engine.h>
-
#ifndef SCARD_H
#define SCARD_H
+#include "key.h"
+
#define SCARD_ERROR_FAIL -1
#define SCARD_ERROR_NOCARD -2
#define SCARD_ERROR_APPLET -3
-Key *sc_get_key(const char*);
-ENGINE *sc_get_engine(void);
+Key **sc_get_keys(const char*, const char*);
void sc_close(void);
+int sc_put_key(Key *, const char*);
#endif
diff --git a/crypto/openssh/scard/Ssh.bin.uu b/crypto/openssh/scard/Ssh.bin.uu
index 1062e21..ea3986a 100644
--- a/crypto/openssh/scard/Ssh.bin.uu
+++ b/crypto/openssh/scard/Ssh.bin.uu
@@ -1,16 +1,17 @@
begin 644 Ssh.bin
-M`P)!%P`501P`;``!`C@"`/Y@\`4`_J'P!0!!%T$;`?Z@\`4`01=!&@'^>/,!
-M`4$701P!_G#S%P'^0],1`?Y@\!0`_G/S'0#^<]4``D$7L`4`_F'3``!!%T$9
-M`?YATP4`_G/5"P7^8=,'`OZAT`$!_J#0$@1!%T$8`0```$$7!`$&`/Y@`;@`
-M`$$8\`H(`$$9\`H``$$:\@\``$$;\B$``$$<\A```/`&__(```0(`!8```9C
-M""T#"<(H+00$*"T%""A;`&19``#P$/_R`P(&`0#(```38`!!70!&$UP`1@09
-M":1+``D*D`!@`"@37`!&!!E6`````*(````$____P````*$````0````*@``
-M`"````"-````,````&H37`!&`QD(2@`)"FX`8``H$UP`1@<9"@#_/2!@`$L1
-M2@`)"F<`8``H$UP`'A-<`$8($1-<`$8(7@!0"!%@`%59"C\`8`!:*PIS:&``
-M6BL37`!&`P,*`(!@`%\K`PH`@&``55D37`!&`P<H$UP`1@0#*`,%8`!565D*
-M;0!@`"A9`/`"__(!`0$)``@```J0`&``*%D`\!/_\@$!`@D`#```8D$7+5\`
-M/"M9````\!+_]@$!`P$`&```$UP`'EX`,D4`#Q-<`!X*`,@)$%X`-P17L`7_
-M\@$!!`(`/```$U\``!-B_J$M7P`%70`*$V+^H"U?``]=`!038OYX+0H$`%\`
-<&5T`'@H$`&``(T4`"0IG`&``*!->`"U9````````
+M`P)!&P`801X`>``!`E@"`/Y@\`4`_J'P!0!!&T$=`?Z@\`4`01M!'`'^>/,!
+M`4$;01X!_G#S%P'^0],1`?Y@\!0`_G/S'0#^<]4``D$;L`4`_F'3``#^8=,%
+M`/ZAT`$!_J#0)P'^H],*`?ZCTPD`_G/5"P7^8=,'`OZAT`H`_J#0$@3^:-,@
+M`T$;`P`%`/Y@`<P``$$<\@\``$$=\B$``$$>\A```/`0__(%`@8!`0H``&``
+M0205!!D)I$L`"0J0`&``*!4$&58``````.P````%____P````.D````0````
+M,P```"````#'````,````(T````R````V!4#&0A*``D*;@!@`"@5!QD*`/\]
+M(6``1A)*``D*9P!@`"@*/P!@`$LK"1)@`$LK!6``4!P$#00#2@`.#01@`%5@
+M`%I@`"@37``>%0@2%0A>`%\($F``9%(`:`H_`&``2RL*<VA@`$LK8`!I"1`U
+M(14#`Q)@`&X<!`T$`TL`"P,28`!D4@`.#01@`%5@`%I@`"A2`"X5`PH$`&``
+M<RL#!6``9%(`'14#"@$"8`!S*P,%8`!D4@`,4@`)"FT`8``H60``\`+_\@$!
+M`0D`"```"I``8``H60#P$__R`0$""0`,``!B01LM7P`\*UD```#P$O_V`0$#
+M`0`8```37``>7@`R10`/$UP`'@H`R`D07@`W!%>P!?_R`0$$`@`\```37P``
+M$V+^H2U?``5=``H38OZ@+5\`#UT`%!-B_G@M"@0`7P`970`>"@0`8``C10`)
+/"F<`8``H$UX`+5D`````
`
end
diff --git a/crypto/openssh/scard/Ssh.java b/crypto/openssh/scard/Ssh.java
index 3692b9b..1f2ae58 100644
--- a/crypto/openssh/scard/Ssh.java
+++ b/crypto/openssh/scard/Ssh.java
@@ -1,4 +1,4 @@
-// $Id: Ssh.java,v 1.2 2001/07/30 20:08:14 rees Exp $
+// $Id: Ssh.java,v 1.3 2002/03/21 22:44:05 rees Exp $
//
// Ssh.java
// SSH / smartcard integration project, smartcard side
@@ -42,6 +42,9 @@ import javacardx.crypto.*;
public class Ssh extends javacard.framework.Applet
{
+ // Change this when the applet changes; hi byte is major, low byte is minor
+ static final short applet_version = (short)0x0102;
+
/* constants declaration */
// code of CLA byte in the command APDU header
static final byte Ssh_CLA =(byte)0x05;
@@ -50,20 +53,19 @@ public class Ssh extends javacard.framework.Applet
static final byte DECRYPT = (byte) 0x10;
static final byte GET_KEYLENGTH = (byte) 0x20;
static final byte GET_PUBKEY = (byte) 0x30;
+ static final byte GET_VERSION = (byte) 0x32;
static final byte GET_RESPONSE = (byte) 0xc0;
- /* instance variables declaration */
static final short keysize = 1024;
+ static final short root_fid = (short)0x3f00;
+ static final short privkey_fid = (short)0x0012;
+ static final short pubkey_fid = (short)(('s'<<8)|'h');
- //RSA_CRT_PrivateKey rsakey;
+ /* instance variables declaration */
AsymKey rsakey;
CyberflexFile file;
CyberflexOS os;
- byte buffer[];
-
- static byte[] keyHdr = {(byte)0xC2, (byte)0x01, (byte)0x05};
-
private Ssh()
{
file = new CyberflexFile();
@@ -98,7 +100,8 @@ public class Ssh extends javacard.framework.Applet
// APDU object carries a byte array (buffer) to
// transfer incoming and outgoing APDU header
// and data bytes between card and CAD
- buffer = apdu.getBuffer();
+ byte buffer[] = apdu.getBuffer();
+ short size, st;
// verify that if the applet can accept this
// APDU message
@@ -111,29 +114,47 @@ public class Ssh extends javacard.framework.Applet
if (buffer[ISO.OFFSET_CLA] != Ssh_CLA)
ISOException.throwIt(ISO.SW_CLA_NOT_SUPPORTED);
//decrypt (apdu);
- short size = (short) (buffer[ISO.OFFSET_LC] & 0x00FF);
+ size = (short) (buffer[ISO.OFFSET_LC] & 0x00FF);
if (apdu.setIncomingAndReceive() != size)
ISOException.throwIt (ISO.SW_WRONG_LENGTH);
+ // check access; depends on bit 2 (x/a)
+ file.selectFile(root_fid);
+ file.selectFile(privkey_fid);
+ st = os.checkAccess(ACL.EXECUTE);
+ if (st != ST.ACCESS_CLEARED) {
+ CyberflexAPDU.prepareSW1SW2(st);
+ ISOException.throwIt(CyberflexAPDU.getSW1SW2());
+ }
+
rsakey.cryptoUpdate (buffer, (short) ISO.OFFSET_CDATA, size,
buffer, (short) ISO.OFFSET_CDATA);
apdu.setOutgoingAndSend ((short) ISO.OFFSET_CDATA, size);
- return;
+ break;
case GET_PUBKEY:
- file.selectFile((short)(0x3f<<8)); // select root
- file.selectFile((short)(('s'<<8)|'h')); // select public key file
- os.readBinaryFile (buffer, (short)0, (short)0, (short)(keysize/8));
- apdu.setOutgoingAndSend((short)0, (short)(keysize/8));
- return;
+ file.selectFile(root_fid); // select root
+ file.selectFile(pubkey_fid); // select public key file
+ size = (short)(file.getFileSize() - 16);
+ st = os.readBinaryFile(buffer, (short)0, (short)0, size);
+ if (st == ST.SUCCESS)
+ apdu.setOutgoingAndSend((short)0, size);
+ else {
+ CyberflexAPDU.prepareSW1SW2(st);
+ ISOException.throwIt(CyberflexAPDU.getSW1SW2());
+ }
+ break;
case GET_KEYLENGTH:
- buffer[0] = (byte)((keysize >> 8) & 0xff);
- buffer[1] = (byte)(keysize & 0xff);
+ Util.setShort(buffer, (short)0, keysize);
+ apdu.setOutgoingAndSend ((short)0, (short)2);
+ break;
+ case GET_VERSION:
+ Util.setShort(buffer, (short)0, applet_version);
apdu.setOutgoingAndSend ((short)0, (short)2);
- return;
+ break;
case GET_RESPONSE:
- return;
+ break;
default:
ISOException.throwIt (ISO.SW_INS_NOT_SUPPORTED);
}
diff --git a/crypto/openssh/scp.1 b/crypto/openssh/scp.1
index 69125c1..c0caff4 100644
--- a/crypto/openssh/scp.1
+++ b/crypto/openssh/scp.1
@@ -9,7 +9,7 @@
.\"
.\" Created: Sun May 7 00:14:37 1995 ylo
.\"
-.\" $OpenBSD: scp.1,v 1.21 2002/01/29 23:50:37 markus Exp $
+.\" $OpenBSD: scp.1,v 1.22 2002/06/20 20:00:05 stevesk Exp $
.\"
.Dd September 25, 1999
.Dt SCP 1
@@ -117,9 +117,9 @@ options.
.It Fl o Ar ssh_option
Can be used to pass options to
.Nm ssh
-in the format used in the
-.Xr ssh 1
-configuration file. This is useful for specifying options
+in the format used in
+.Xr ssh_config 5 .
+This is useful for specifying options
for which there is no separate
.Nm scp
command-line flag. For example, forcing the use of protocol
@@ -152,4 +152,5 @@ California.
.Xr ssh-add 1 ,
.Xr ssh-agent 1 ,
.Xr ssh-keygen 1 ,
+.Xr ssh_config 5
.Xr sshd 8
diff --git a/crypto/openssh/scp.c b/crypto/openssh/scp.c
index 159e4bb..e2a085c 100644
--- a/crypto/openssh/scp.c
+++ b/crypto/openssh/scp.c
@@ -75,7 +75,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: scp.c,v 1.86 2001/12/05 03:56:39 itojun Exp $");
+RCSID("$OpenBSD: scp.c,v 1.91 2002/06/19 00:27:55 deraadt Exp $");
#include "xmalloc.h"
#include "atomicio.h"
@@ -219,10 +219,9 @@ main(argc, argv)
extern int optind;
args.list = NULL;
- addargs(&args, "ssh"); /* overwritten with ssh_program */
+ addargs(&args, "ssh"); /* overwritten with ssh_program */
addargs(&args, "-x");
addargs(&args, "-oForwardAgent no");
- addargs(&args, "-oFallBackToRsh no");
addargs(&args, "-oClearAllForwardings yes");
fflag = tflag = 0;
@@ -354,8 +353,7 @@ toremote(targ, argc, argv)
src = colon(argv[i]);
if (src) { /* remote to remote */
static char *ssh_options =
- "-x -o'FallBackToRsh no' "
- "-o'ClearAllForwardings yes'";
+ "-x -o'ClearAllForwardings yes'";
*src++ = 0;
if (*src == 0)
src = ".";
@@ -756,7 +754,7 @@ sink(argc, argv)
cursize = need;
}
(void) snprintf(namebuf, need, "%s%s%s", targ,
- *targ ? "/" : "", cp);
+ strcmp(targ, "/") ? "/" : "", cp);
np = namebuf;
} else
np = targ;
@@ -931,9 +929,9 @@ void
usage(void)
{
(void) fprintf(stderr,
- "usage: scp [-pqrvBC46] [-F config] [-S ssh] [-P port] [-c cipher] [-i identity]\n"
- " [-o option] f1 f2\n"
- " or: scp [options] f1 ... fn directory\n");
+ "usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n"
+ " [-c cipher] [-i identity] [-o option]\n"
+ " [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
exit(1);
}
@@ -1073,7 +1071,7 @@ progressmeter(int flag)
off_t cursize, abbrevsize;
double elapsed;
int ratio, barlength, i, remaining;
- char buf[256];
+ char buf[512];
if (flag == -1) {
(void) gettimeofday(&start, (struct timezone *) 0);
@@ -1099,10 +1097,13 @@ progressmeter(int flag)
i = barlength * ratio / 100;
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
"|%.*s%*s|", i,
- "***************************************"
- "***************************************"
- "***************************************"
- "***************************************",
+ "*******************************************************"
+ "*******************************************************"
+ "*******************************************************"
+ "*******************************************************"
+ "*******************************************************"
+ "*******************************************************"
+ "*******************************************************",
barlength - i, "");
}
i = 0;
diff --git a/crypto/openssh/servconf.c b/crypto/openssh/servconf.c
index cf2042e..3537e92 100644
--- a/crypto/openssh/servconf.c
+++ b/crypto/openssh/servconf.c
@@ -10,7 +10,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: servconf.c,v 1.101 2002/02/04 12:15:25 markus Exp $");
+RCSID("$OpenBSD: servconf.c,v 1.111 2002/06/20 23:05:55 markus Exp $");
#if defined(KRB4) || defined(KRB5)
#include <krb.h>
@@ -36,6 +36,8 @@ static void add_one_listen_addr(ServerOptions *, char *, u_short);
/* AF_UNSPEC or AF_INET or AF_INET6 */
extern int IPv4or6;
+/* Use of privilege separation or not */
+extern int use_privsep;
/* Initializes the server options to their default values. */
@@ -86,6 +88,7 @@ initialize_server_options(ServerOptions *options)
options->challenge_response_authentication = -1;
options->permit_empty_passwd = -1;
options->use_login = -1;
+ options->compression = -1;
options->allow_tcp_forwarding = -1;
options->num_allow_users = 0;
options->num_deny_users = 0;
@@ -105,6 +108,9 @@ initialize_server_options(ServerOptions *options)
options->client_alive_count_max = -1;
options->authorized_keys_file = NULL;
options->authorized_keys_file2 = NULL;
+
+ /* Needs to be accessable in many places */
+ use_privsep = -1;
}
void
@@ -176,7 +182,7 @@ fill_default_server_options(ServerOptions *options)
options->pubkey_authentication = 1;
#if defined(KRB4) || defined(KRB5)
if (options->kerberos_authentication == -1)
- options->kerberos_authentication = (access(KEYFILE, R_OK) == 0);
+ options->kerberos_authentication = 0;
if (options->kerberos_or_local_passwd == -1)
options->kerberos_or_local_passwd = 1;
if (options->kerberos_ticket_cleanup == -1)
@@ -188,7 +194,7 @@ fill_default_server_options(ServerOptions *options)
#endif
#ifdef AFS
if (options->afs_token_passing == -1)
- options->afs_token_passing = k_hasafs();
+ options->afs_token_passing = 0;
#endif
if (options->password_authentication == -1)
options->password_authentication = 1;
@@ -200,6 +206,8 @@ fill_default_server_options(ServerOptions *options)
options->permit_empty_passwd = 0;
if (options->use_login == -1)
options->use_login = 0;
+ if (options->compression == -1)
+ options->compression = 1;
if (options->allow_tcp_forwarding == -1)
options->allow_tcp_forwarding = 1;
if (options->gateway_ports == -1)
@@ -225,6 +233,10 @@ fill_default_server_options(ServerOptions *options)
}
if (options->authorized_keys_file == NULL)
options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
+
+ /* Turn privilege separation on by default */
+ if (use_privsep == -1)
+ use_privsep = 1;
}
/* Keyword tokens. */
@@ -247,13 +259,14 @@ typedef enum {
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
sStrictModes, sEmptyPasswd, sKeepAlives,
- sUseLogin, sAllowTcpForwarding,
+ sUseLogin, sAllowTcpForwarding, sCompression,
sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
sBanner, sVerifyReverseMapping, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
+ sUsePrivilegeSeparation,
sDeprecated
} ServerOpCodes;
@@ -307,6 +320,7 @@ static struct {
{ "strictmodes", sStrictModes },
{ "permitemptypasswords", sEmptyPasswd },
{ "uselogin", sUseLogin },
+ { "compression", sCompression },
{ "keepalive", sKeepAlives },
{ "allowtcpforwarding", sAllowTcpForwarding },
{ "allowusers", sAllowUsers },
@@ -326,6 +340,7 @@ static struct {
{ "clientalivecountmax", sClientAliveCountMax },
{ "authorizedkeysfile", sAuthorizedKeysFile },
{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
+ { "useprivilegeseparation", sUsePrivilegeSeparation},
{ NULL, sBadOption }
};
@@ -662,6 +677,10 @@ parse_flag:
intptr = &options->use_login;
goto parse_flag;
+ case sCompression:
+ intptr = &options->compression;
+ goto parse_flag;
+
case sGatewayPorts:
intptr = &options->gateway_ports;
goto parse_flag;
@@ -696,6 +715,10 @@ parse_flag:
intptr = &options->allow_tcp_forwarding;
goto parse_flag;
+ case sUsePrivilegeSeparation:
+ intptr = &use_privsep;
+ goto parse_flag;
+
case sAllowUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_allow_users >= MAX_ALLOW_USERS)
diff --git a/crypto/openssh/servconf.h b/crypto/openssh/servconf.h
index 3cdb4491..6fc1272 100644
--- a/crypto/openssh/servconf.h
+++ b/crypto/openssh/servconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.h,v 1.54 2002/03/04 17:27:39 stevesk Exp $ */
+/* $OpenBSD: servconf.h,v 1.58 2002/06/20 23:05:55 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -98,6 +98,7 @@ typedef struct {
int permit_empty_passwd; /* If false, do not permit empty
* passwords. */
int use_login; /* If true, login(1) is used */
+ int compression; /* If true, compression is allowed */
int allow_tcp_forwarding;
u_int num_allow_users;
char *allow_users[MAX_ALLOW_USERS];
@@ -129,7 +130,6 @@ typedef struct {
char *authorized_keys_file; /* File containing public keys */
char *authorized_keys_file2;
-
} ServerOptions;
void initialize_server_options(ServerOptions *);
diff --git a/crypto/openssh/serverloop.c b/crypto/openssh/serverloop.c
index 5dd8a715..b72c921 100644
--- a/crypto/openssh/serverloop.c
+++ b/crypto/openssh/serverloop.c
@@ -35,7 +35,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: serverloop.c,v 1.98 2002/02/06 14:55:16 markus Exp $");
+RCSID("$OpenBSD: serverloop.c,v 1.102 2002/06/11 05:46:20 mpech Exp $");
#include "xmalloc.h"
#include "packet.h"
@@ -318,9 +318,6 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
tvp = &tv;
}
- if (tvp!=NULL)
- debug3("tvp!=NULL kid %d mili %d", (int) child_terminated,
- max_time_milliseconds);
/* Wait for something to happen, or the timeout to expire. */
ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
@@ -673,12 +670,12 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
/* We no longer want our SIGCHLD handler to be called. */
signal(SIGCHLD, SIG_DFL);
- wait_pid = waitpid(-1, &wait_status, 0);
- if (wait_pid == -1)
- packet_disconnect("wait: %.100s", strerror(errno));
- else if (wait_pid != pid)
- error("Strange, wait returned pid %d, expected %d",
- wait_pid, pid);
+ while ((wait_pid = waitpid(-1, &wait_status, 0)) < 0)
+ if (errno != EINTR)
+ packet_disconnect("wait: %.100s", strerror(errno));
+ if (wait_pid != pid)
+ error("Strange, wait returned pid %ld, expected %ld",
+ (long)wait_pid, (long)pid);
/* Check if it exited normally. */
if (WIFEXITED(wait_status)) {
@@ -726,8 +723,10 @@ collect_children(void)
sigaddset(&nset, SIGCHLD);
sigprocmask(SIG_BLOCK, &nset, &oset);
if (child_terminated) {
- while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
- session_close_by_pid(pid, status);
+ while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
+ (pid < 0 && errno == EINTR))
+ if (pid > 0)
+ session_close_by_pid(pid, status);
child_terminated = 0;
}
sigprocmask(SIG_SETMASK, &oset, NULL);
@@ -784,7 +783,7 @@ server_loop2(Authctxt *authctxt)
channel_free_all();
/* free remaining sessions, e.g. remove wtmp entries */
- session_destroy_all();
+ session_destroy_all(NULL);
}
static void
diff --git a/crypto/openssh/session.c b/crypto/openssh/session.c
index 7a12758..a616b7e 100644
--- a/crypto/openssh/session.c
+++ b/crypto/openssh/session.c
@@ -33,7 +33,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: session.c,v 1.128 2002/02/16 00:51:44 markus Exp $");
+RCSID("$OpenBSD: session.c,v 1.138 2002/06/20 23:05:55 markus Exp $");
#include "ssh.h"
#include "ssh1.h"
@@ -56,40 +56,13 @@ RCSID("$OpenBSD: session.c,v 1.128 2002/02/16 00:51:44 markus Exp $");
#include "serverloop.h"
#include "canohost.h"
#include "session.h"
-
-/* types */
-
-#define TTYSZ 64
-typedef struct Session Session;
-struct Session {
- int used;
- int self;
- struct passwd *pw;
- Authctxt *authctxt;
- pid_t pid;
- /* tty */
- char *term;
- int ptyfd, ttyfd, ptymaster;
- int row, col, xpixel, ypixel;
- char tty[TTYSZ];
- /* X11 */
- int display_number;
- char *display;
- int screen;
- char *auth_display;
- char *auth_proto;
- char *auth_data;
- int single_connection;
- /* proto 2 */
- int chanid;
- int is_subsystem;
-};
+#include "monitor_wrap.h"
/* func */
Session *session_new(void);
void session_set_fds(Session *, int, int, int);
-static void session_pty_cleanup(void *);
+void session_pty_cleanup(void *);
void session_proctitle(Session *);
int session_setup_x11fwd(Session *);
void do_exec_pty(Session *, const char *);
@@ -103,7 +76,6 @@ int check_quietlogin(Session *, const char *);
static void do_authenticated1(Authctxt *);
static void do_authenticated2(Authctxt *);
-static void session_close(Session *);
static int session_pty_req(Session *);
/* import */
@@ -123,9 +95,96 @@ const char *original_command = NULL;
Session sessions[MAX_SESSIONS];
#ifdef HAVE_LOGIN_CAP
-static login_cap_t *lc;
+login_cap_t *lc;
#endif
+/* Name and directory of socket for authentication agent forwarding. */
+static char *auth_sock_name = NULL;
+static char *auth_sock_dir = NULL;
+
+/* removes the agent forwarding socket */
+
+static void
+auth_sock_cleanup_proc(void *_pw)
+{
+ struct passwd *pw = _pw;
+
+ if (auth_sock_name != NULL) {
+ temporarily_use_uid(pw);
+ unlink(auth_sock_name);
+ rmdir(auth_sock_dir);
+ auth_sock_name = NULL;
+ restore_uid();
+ }
+}
+
+static int
+auth_input_request_forwarding(struct passwd * pw)
+{
+ Channel *nc;
+ int sock;
+ struct sockaddr_un sunaddr;
+
+ if (auth_sock_name != NULL) {
+ error("authentication forwarding requested twice.");
+ return 0;
+ }
+
+ /* Temporarily drop privileged uid for mkdir/bind. */
+ temporarily_use_uid(pw);
+
+ /* Allocate a buffer for the socket name, and format the name. */
+ auth_sock_name = xmalloc(MAXPATHLEN);
+ auth_sock_dir = xmalloc(MAXPATHLEN);
+ strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
+
+ /* Create private directory for socket */
+ if (mkdtemp(auth_sock_dir) == NULL) {
+ packet_send_debug("Agent forwarding disabled: "
+ "mkdtemp() failed: %.100s", strerror(errno));
+ restore_uid();
+ xfree(auth_sock_name);
+ xfree(auth_sock_dir);
+ auth_sock_name = NULL;
+ auth_sock_dir = NULL;
+ return 0;
+ }
+ snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld",
+ auth_sock_dir, (long) getpid());
+
+ /* delete agent socket on fatal() */
+ fatal_add_cleanup(auth_sock_cleanup_proc, pw);
+
+ /* Create the socket. */
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0)
+ packet_disconnect("socket: %.100s", strerror(errno));
+
+ /* Bind it to the name. */
+ memset(&sunaddr, 0, sizeof(sunaddr));
+ sunaddr.sun_family = AF_UNIX;
+ strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
+
+ if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0)
+ packet_disconnect("bind: %.100s", strerror(errno));
+
+ /* Restore the privileged uid. */
+ restore_uid();
+
+ /* Start listening on the socket. */
+ if (listen(sock, 5) < 0)
+ packet_disconnect("listen: %.100s", strerror(errno));
+
+ /* Allocate a channel for the authentication agent socket. */
+ nc = channel_new("auth socket",
+ SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
+ CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
+ 0, xstrdup("auth socket"), 1);
+ strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
+ return 1;
+}
+
+
void
do_authenticated(Authctxt *authctxt)
{
@@ -138,18 +197,6 @@ do_authenticated(Authctxt *authctxt)
close(startup_pipe);
startup_pipe = -1;
}
-#ifdef HAVE_LOGIN_CAP
- if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL) {
- error("unable to get login class");
- return;
- }
-#ifdef BSD_AUTH
- if (auth_approval(NULL, lc, authctxt->pw->pw_name, "ssh") <= 0) {
- packet_disconnect("Approval failure for %s",
- authctxt->pw->pw_name);
- }
-#endif
-#endif
/* setup the channel layer */
if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
channel_permit_all_opens();
@@ -160,7 +207,7 @@ do_authenticated(Authctxt *authctxt)
do_authenticated1(authctxt);
/* remove agent socket */
- if (auth_get_socket_name())
+ if (auth_sock_name != NULL)
auth_sock_cleanup_proc(authctxt->pw);
#ifdef KRB4
if (options.kerberos_ticket_cleanup)
@@ -211,6 +258,10 @@ do_authenticated1(Authctxt *authctxt)
compression_level);
break;
}
+ if (!options.compression) {
+ debug2("compression disabled");
+ break;
+ }
/* Enable compression after we have responded with SUCCESS. */
enable_compression_after_reply = 1;
success = 1;
@@ -367,7 +418,7 @@ do_authenticated1(Authctxt *authctxt)
void
do_exec_no_pty(Session *s, const char *command)
{
- int pid;
+ pid_t pid;
#ifdef USE_PIPES
int pin[2], pout[2], perr[2];
@@ -583,10 +634,8 @@ void
do_login(Session *s, const char *command)
{
char *time_string;
- char hostname[MAXHOSTNAMELEN];
socklen_t fromlen;
struct sockaddr_storage from;
- time_t last_login_time;
struct passwd * pw = s->pw;
pid_t pid = getpid();
@@ -604,29 +653,25 @@ do_login(Session *s, const char *command)
}
}
- /* Get the time and hostname when the user last logged in. */
- if (options.print_lastlog) {
- hostname[0] = '\0';
- last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
- hostname, sizeof(hostname));
- }
-
/* Record that there was a login on that tty from the remote host. */
- record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
- get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping),
- (struct sockaddr *)&from);
+ if (!use_privsep)
+ record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
+ get_remote_name_or_ip(utmp_len,
+ options.verify_reverse_mapping),
+ (struct sockaddr *)&from);
if (check_quietlogin(s, command))
return;
- if (options.print_lastlog && last_login_time != 0) {
- time_string = ctime(&last_login_time);
+ if (options.print_lastlog && s->last_login_time != 0) {
+ time_string = ctime(&s->last_login_time);
if (strchr(time_string, '\n'))
*strchr(time_string, '\n') = 0;
- if (strcmp(hostname, "") == 0)
+ if (strcmp(s->hostname, "") == 0)
printf("Last login: %s\r\n", time_string);
else
- printf("Last login: %s from %s\r\n", time_string, hostname);
+ printf("Last login: %s from %s\r\n", time_string,
+ s->hostname);
}
do_motd();
@@ -837,9 +882,9 @@ do_setup_env(Session *s, const char *shell)
child_set_env(&env, &envsize, "KRB5CCNAME",
s->authctxt->krb5_ticket_file);
#endif
- if (auth_get_socket_name() != NULL)
+ if (auth_sock_name != NULL)
child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
- auth_get_socket_name());
+ auth_sock_name);
/* read $HOME/.ssh/environment. */
if (!options.use_login) {
@@ -903,7 +948,7 @@ do_rc_files(Session *s, const char *shell)
/* Add authority data to .Xauthority if appropriate. */
if (debug_flag) {
fprintf(stderr,
- "Running %.100s add "
+ "Running %.500s add "
"%.100s %.100s %.100s\n",
options.xauth_location, s->auth_display,
s->auth_proto, s->auth_data);
@@ -947,7 +992,7 @@ do_nologin(struct passwd *pw)
}
/* Set login name, uid, gid, and groups. */
-static void
+void
do_setusercontext(struct passwd *pw)
{
if (getuid() == 0 || geteuid() == 0) {
@@ -979,6 +1024,20 @@ do_setusercontext(struct passwd *pw)
fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
}
+static void
+launch_login(struct passwd *pw, const char *hostname)
+{
+ /* Launch login(1). */
+
+ execl("/usr/bin/login", "login", "-h", hostname,
+ "-p", "-f", "--", pw->pw_name, (char *)NULL);
+
+ /* Login couldn't be executed, die. */
+
+ perror("login");
+ exit(1);
+}
+
/*
* Performs common processing for the child, such as setting up the
* environment, closing extra file descriptors, setting the user and group
@@ -1095,15 +1154,8 @@ do_child(Session *s, const char *command)
signal(SIGPIPE, SIG_DFL);
if (options.use_login) {
- /* Launch login(1). */
-
- execl("/usr/bin/login", "login", "-h", hostname,
- "-p", "-f", "--", pw->pw_name, (char *)NULL);
-
- /* Login couldn't be executed, die. */
-
- perror("login");
- exit(1);
+ launch_login(pw, hostname);
+ /* NEVERREACHED */
}
/* Get the last component of the shell name. */
@@ -1186,12 +1238,12 @@ session_dump(void)
int i;
for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
- debug("dump: used %d session %d %p channel %d pid %d",
+ debug("dump: used %d session %d %p channel %d pid %ld",
s->used,
s->self,
s,
s->chanid,
- s->pid);
+ (long)s->pid);
}
}
@@ -1213,6 +1265,22 @@ session_open(Authctxt *authctxt, int chanid)
return 1;
}
+Session *
+session_by_tty(char *tty)
+{
+ int i;
+ for (i = 0; i < MAX_SESSIONS; i++) {
+ Session *s = &sessions[i];
+ if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
+ debug("session_by_tty: session %d tty %s", i, tty);
+ return s;
+ }
+ }
+ debug("session_by_tty: unknown tty %.100s", tty);
+ session_dump();
+ return NULL;
+}
+
static Session *
session_by_channel(int id)
{
@@ -1233,13 +1301,13 @@ static Session *
session_by_pid(pid_t pid)
{
int i;
- debug("session_by_pid: pid %d", pid);
+ debug("session_by_pid: pid %ld", (long)pid);
for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
if (s->used && s->pid == pid)
return s;
}
- error("session_by_pid: unknown pid %d", pid);
+ error("session_by_pid: unknown pid %ld", (long)pid);
session_dump();
return NULL;
}
@@ -1270,6 +1338,12 @@ session_pty_req(Session *s)
packet_disconnect("Protocol error: you already have a pty.");
return 0;
}
+ /* Get the time and hostname when the user last logged in. */
+ if (options.print_lastlog) {
+ s->hostname[0] = '\0';
+ s->last_login_time = get_last_login_time(s->pw->pw_uid,
+ s->pw->pw_name, s->hostname, sizeof(s->hostname));
+ }
s->term = packet_get_string(&len);
@@ -1290,7 +1364,7 @@ session_pty_req(Session *s)
/* Allocate a pty and open it. */
debug("Allocating pty.");
- if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty))) {
+ if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) {
if (s->term)
xfree(s->term);
s->term = NULL;
@@ -1311,7 +1385,8 @@ session_pty_req(Session *s)
* time in case we call fatal() (e.g., the connection gets closed).
*/
fatal_add_cleanup(session_pty_cleanup, (void *)s);
- pty_setowner(s->pw, s->tty);
+ if (!use_privsep)
+ pty_setowner(s->pw, s->tty);
/* Set window size from the packet. */
pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
@@ -1474,8 +1549,8 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr)
* Function to perform pty cleanup. Also called if we get aborted abnormally
* (e.g., due to a dropped connection).
*/
-static void
-session_pty_cleanup(void *session)
+void
+session_pty_cleanup2(void *session)
{
Session *s = session;
@@ -1493,7 +1568,8 @@ session_pty_cleanup(void *session)
record_logout(s->pid, s->tty);
/* Release the pseudo-tty. */
- pty_release(s->tty);
+ if (getuid() == 0)
+ pty_release(s->tty);
/*
* Close the server side of the socket pairs. We must do this after
@@ -1501,12 +1577,18 @@ session_pty_cleanup(void *session)
* while we're still cleaning up.
*/
if (close(s->ptymaster) < 0)
- error("close(s->ptymaster): %s", strerror(errno));
+ error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno));
/* unlink pty from session */
s->ttyfd = -1;
}
+void
+session_pty_cleanup(void *session)
+{
+ PRIVSEP(session_pty_cleanup2(session));
+}
+
static void
session_exit_message(Session *s, int status)
{
@@ -1515,8 +1597,8 @@ session_exit_message(Session *s, int status)
if ((c = channel_lookup(s->chanid)) == NULL)
fatal("session_exit_message: session %d: no channel %d",
s->self, s->chanid);
- debug("session_exit_message: session %d channel %d pid %d",
- s->self, s->chanid, s->pid);
+ debug("session_exit_message: session %d channel %d pid %ld",
+ s->self, s->chanid, (long)s->pid);
if (WIFEXITED(status)) {
channel_request_start(s->chanid, "exit-status", 0);
@@ -1548,10 +1630,10 @@ session_exit_message(Session *s, int status)
s->chanid = -1;
}
-static void
+void
session_close(Session *s)
{
- debug("session_close: session %d pid %d", s->self, s->pid);
+ debug("session_close: session %d pid %ld", s->self, (long)s->pid);
if (s->ttyfd != -1) {
fatal_remove_cleanup(session_pty_cleanup, (void *)s);
session_pty_cleanup(s);
@@ -1575,7 +1657,8 @@ session_close_by_pid(pid_t pid, int status)
{
Session *s = session_by_pid(pid);
if (s == NULL) {
- debug("session_close_by_pid: no session for pid %d", pid);
+ debug("session_close_by_pid: no session for pid %ld",
+ (long)pid);
return;
}
if (s->chanid != -1)
@@ -1595,7 +1678,8 @@ session_close_by_channel(int id, void *arg)
debug("session_close_by_channel: no session for id %d", id);
return;
}
- debug("session_close_by_channel: channel %d child %d", id, s->pid);
+ debug("session_close_by_channel: channel %d child %ld",
+ id, (long)s->pid);
if (s->pid != 0) {
debug("session_close_by_channel: channel %d: has child", id);
/*
@@ -1615,13 +1699,17 @@ session_close_by_channel(int id, void *arg)
}
void
-session_destroy_all(void)
+session_destroy_all(void (*closefunc)(Session *))
{
int i;
for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
- if (s->used)
- session_close(s);
+ if (s->used) {
+ if (closefunc != NULL)
+ closefunc(s);
+ else
+ session_close(s);
+ }
}
}
diff --git a/crypto/openssh/session.h b/crypto/openssh/session.h
index ec8284a..2a7e4b2 100644
--- a/crypto/openssh/session.h
+++ b/crypto/openssh/session.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.h,v 1.14 2002/02/03 17:53:25 markus Exp $ */
+/* $OpenBSD: session.h,v 1.17 2002/03/29 18:59:32 markus Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -26,12 +26,46 @@
#ifndef SESSION_H
#define SESSION_H
+#define TTYSZ 64
+typedef struct Session Session;
+struct Session {
+ int used;
+ int self;
+ struct passwd *pw;
+ Authctxt *authctxt;
+ pid_t pid;
+ /* tty */
+ char *term;
+ int ptyfd, ttyfd, ptymaster;
+ int row, col, xpixel, ypixel;
+ char tty[TTYSZ];
+ /* last login */
+ char hostname[MAXHOSTNAMELEN];
+ time_t last_login_time;
+ /* X11 */
+ int display_number;
+ char *display;
+ int screen;
+ char *auth_display;
+ char *auth_proto;
+ char *auth_data;
+ int single_connection;
+ /* proto 2 */
+ int chanid;
+ int is_subsystem;
+};
+
void do_authenticated(Authctxt *);
int session_open(Authctxt*, int);
int session_input_channel_req(Channel *, const char *);
void session_close_by_pid(pid_t, int);
void session_close_by_channel(int, void *);
-void session_destroy_all(void);
+void session_destroy_all(void (*)(Session *));
+void session_pty_cleanup2(void *);
+Session *session_new(void);
+Session *session_by_tty(char *);
+void session_close(Session *);
+void do_setusercontext(struct passwd *);
#endif
diff --git a/crypto/openssh/sftp-client.c b/crypto/openssh/sftp-client.c
index 10ac13d..fb3d166 100644
--- a/crypto/openssh/sftp-client.c
+++ b/crypto/openssh/sftp-client.c
@@ -28,7 +28,7 @@
/* XXX: copy between two remote sites */
#include "includes.h"
-RCSID("$OpenBSD: sftp-client.c,v 1.24 2002/02/24 16:57:19 markus Exp $");
+RCSID("$OpenBSD: sftp-client.c,v 1.32 2002/06/09 13:32:01 markus Exp $");
#include <sys/queue.h>
@@ -270,7 +270,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
/* Some filexfer v.0 servers don't support large packets */
if (version == 0)
- ret->transfer_buflen = MAX(ret->transfer_buflen, 20480);
+ ret->transfer_buflen = MIN(ret->transfer_buflen, 20480);
return(ret);
}
@@ -445,7 +445,7 @@ do_rm(struct sftp_conn *conn, char *path)
debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
id = conn->msg_id++;
- send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path,
+ send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path,
strlen(path));
status = get_status(conn->fd_in, id);
if (status != SSH2_FX_OK)
@@ -492,8 +492,8 @@ do_stat(struct sftp_conn *conn, char *path, int quiet)
id = conn->msg_id++;
- send_string_request(conn->fd_out, id,
- conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
+ send_string_request(conn->fd_out, id,
+ conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
path, strlen(path));
return(get_decode_stat(conn->fd_in, id, quiet));
@@ -508,8 +508,8 @@ do_lstat(struct sftp_conn *conn, char *path, int quiet)
if (quiet)
debug("Server version does not support lstat operation");
else
- error("Server version does not support lstat operation");
- return(NULL);
+ log("Server version does not support lstat operation");
+ return(do_stat(conn, path, quiet));
}
id = conn->msg_id++;
@@ -723,7 +723,7 @@ send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
char *handle, u_int handle_len)
{
Buffer msg;
-
+
buffer_init(&msg);
buffer_clear(&msg);
buffer_put_char(&msg, SSH2_FXP_READ);
@@ -733,7 +733,7 @@ send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
buffer_put_int(&msg, len);
send_msg(fd_out, &msg);
buffer_free(&msg);
-}
+}
int
do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
@@ -750,7 +750,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
u_int id;
u_int len;
u_int64_t offset;
- TAILQ_ENTRY(request) tq;
+ TAILQ_ENTRY(request) tq;
};
TAILQ_HEAD(reqhead, request) requests;
struct request *req;
@@ -816,8 +816,10 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
/* Send some more requests */
while (num_req < max_req) {
- debug3("Request range %llu -> %llu (%d/%d)",
- offset, offset + buflen - 1, num_req, max_req);
+ debug3("Request range %llu -> %llu (%d/%d)",
+ (unsigned long long)offset,
+ (unsigned long long)offset + buflen - 1,
+ num_req, max_req);
req = xmalloc(sizeof(*req));
req->id = conn->msg_id++;
req->len = buflen;
@@ -825,7 +827,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
offset += buflen;
num_req++;
TAILQ_INSERT_TAIL(&requests, req, tq);
- send_read_request(conn->fd_out, req->id, req->offset,
+ send_read_request(conn->fd_out, req->id, req->offset,
req->len, handle, handle_len);
}
@@ -855,8 +857,9 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
break;
case SSH2_FXP_DATA:
data = buffer_get_string(&msg, &len);
- debug3("Received data %llu -> %llu", req->offset,
- req->offset + len - 1);
+ debug3("Received data %llu -> %llu",
+ (unsigned long long)req->offset,
+ (unsigned long long)req->offset + len - 1);
if (len > req->len)
fatal("Received more data than asked for "
"%d > %d", len, req->len);
@@ -876,12 +879,14 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
} else {
/* Resend the request for the missing data */
debug3("Short data block, re-requesting "
- "%llu -> %llu (%2d)", req->offset + len,
- req->offset + req->len - 1, num_req);
+ "%llu -> %llu (%2d)",
+ (unsigned long long)req->offset + len,
+ (unsigned long long)req->offset +
+ req->len - 1, num_req);
req->id = conn->msg_id++;
req->len -= len;
req->offset += len;
- send_read_request(conn->fd_out, req->id,
+ send_read_request(conn->fd_out, req->id,
req->offset, req->len, handle, handle_len);
/* Reduce the request size */
if (len < buflen)
@@ -892,7 +897,8 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
/* Only one request at a time
* after the expected EOF */
debug3("Finish at %llu (%2d)",
- offset, num_req);
+ (unsigned long long)offset,
+ num_req);
max_req = 1;
}
else if (max_req < conn->num_requests + 1) {
@@ -911,7 +917,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
fatal("Transfer complete, but requests still in queue");
if (read_error) {
- error("Couldn't read from remote file \"%s\" : %s",
+ error("Couldn't read from remote file \"%s\" : %s",
remote_path, fx2txt(status));
do_close(conn, handle, handle_len);
} else if (write_error) {
@@ -960,7 +966,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
u_int id;
u_int len;
u_int64_t offset;
- TAILQ_ENTRY(outstanding_ack) tq;
+ TAILQ_ENTRY(outstanding_ack) tq;
};
TAILQ_HEAD(ackhead, outstanding_ack) acks;
struct outstanding_ack *ack;
@@ -1042,19 +1048,21 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
buffer_put_string(&msg, data, len);
send_msg(conn->fd_out, &msg);
debug3("Sent message SSH2_FXP_WRITE I:%d O:%llu S:%u",
- id, (u_int64_t)offset, len);
+ id, (unsigned long long)offset, len);
} else if (TAILQ_FIRST(&acks) == NULL)
break;
if (ack == NULL)
fatal("Unexpected ACK %u", id);
- if (id == startid || len == 0 ||
+ if (id == startid || len == 0 ||
id - ackid >= conn->num_requests) {
+ u_int r_id;
+
buffer_clear(&msg);
get_msg(conn->fd_in, &msg);
type = buffer_get_char(&msg);
- id = buffer_get_int(&msg);
+ r_id = buffer_get_int(&msg);
if (type != SSH2_FXP_STATUS)
fatal("Expected SSH2_FXP_STATUS(%d) packet, "
@@ -1065,11 +1073,11 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
/* Find the request in our queue */
for(ack = TAILQ_FIRST(&acks);
- ack != NULL && ack->id != id;
+ ack != NULL && ack->id != r_id;
ack = TAILQ_NEXT(ack, tq))
;
if (ack == NULL)
- fatal("Can't find request for ID %d", id);
+ fatal("Can't find request for ID %d", r_id);
TAILQ_REMOVE(&acks, ack, tq);
if (status != SSH2_FX_OK) {
@@ -1079,8 +1087,8 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
close(local_fd);
goto done;
}
- debug3("In write loop, ack for %u %d bytes at %llu",
- ack->id, ack->len, ack->offset);
+ debug3("In write loop, ack for %u %d bytes at %llu",
+ ack->id, ack->len, (unsigned long long)ack->offset);
++ackid;
free(ack);
}
diff --git a/crypto/openssh/sftp-glob.h b/crypto/openssh/sftp-glob.h
index 488b0a8..9c75491 100644
--- a/crypto/openssh/sftp-glob.h
+++ b/crypto/openssh/sftp-glob.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-glob.h,v 1.6 2002/02/13 00:59:23 djm Exp $ */
+/* $OpenBSD: sftp-glob.h,v 1.7 2002/03/19 10:49:35 markus Exp $ */
/*
* Copyright (c) 2001,2002 Damien Miller. All rights reserved.
@@ -32,7 +32,7 @@
#include "sftp-client.h"
int
-remote_glob(struct sftp_conn *, const char *, int,
+remote_glob(struct sftp_conn *, const char *, int,
int (*)(const char *, int), glob_t *);
#endif
diff --git a/crypto/openssh/sftp-int.c b/crypto/openssh/sftp-int.c
index d986c76..d433141 100644
--- a/crypto/openssh/sftp-int.c
+++ b/crypto/openssh/sftp-int.c
@@ -26,7 +26,7 @@
/* XXX: recursive operations */
#include "includes.h"
-RCSID("$OpenBSD: sftp-int.c,v 1.44 2002/02/13 00:59:23 djm Exp $");
+RCSID("$OpenBSD: sftp-int.c,v 1.46 2002/03/30 18:51:15 markus Exp $");
#include <glob.h>
@@ -178,8 +178,9 @@ local_do_shell(const char *args)
strerror(errno));
_exit(1);
}
- if (waitpid(pid, &status, 0) == -1)
- fatal("Couldn't wait for child: %s", strerror(errno));
+ while (waitpid(pid, &status, 0) == -1)
+ if (errno != EINTR)
+ fatal("Couldn't wait for child: %s", strerror(errno));
if (!WIFEXITED(status))
error("Shell exited abormally");
else if (WEXITSTATUS(status))
@@ -888,8 +889,10 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
file2);
parse_dispatch_command(conn, cmd, &pwd);
+ xfree(dir);
return;
}
+ xfree(dir);
}
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(infile, NULL, _IOLBF, 0);
diff --git a/crypto/openssh/sftp-server.c b/crypto/openssh/sftp-server.c
index b98c5ff..27f33bd 100644
--- a/crypto/openssh/sftp-server.c
+++ b/crypto/openssh/sftp-server.c
@@ -22,7 +22,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
-RCSID("$OpenBSD: sftp-server.c,v 1.33 2002/02/13 00:28:13 markus Exp $");
+RCSID("$OpenBSD: sftp-server.c,v 1.35 2002/06/06 17:30:11 markus Exp $");
#include "buffer.h"
#include "bufaux.h"
@@ -362,7 +362,7 @@ process_init(void)
{
Buffer msg;
- version = buffer_get_int(&iqueue);
+ version = get_int();
TRACE("client version %d", version);
buffer_init(&msg);
buffer_put_char(&msg, SSH2_FXP_VERSION);
@@ -936,10 +936,13 @@ static void
process(void)
{
u_int msg_len;
+ u_int buf_len;
+ u_int consumed;
u_int type;
u_char *cp;
- if (buffer_len(&iqueue) < 5)
+ buf_len = buffer_len(&iqueue);
+ if (buf_len < 5)
return; /* Incomplete message. */
cp = buffer_ptr(&iqueue);
msg_len = GET_32BIT(cp);
@@ -947,9 +950,10 @@ process(void)
error("bad message ");
exit(11);
}
- if (buffer_len(&iqueue) < msg_len + 4)
+ if (buf_len < msg_len + 4)
return;
buffer_consume(&iqueue, 4);
+ buf_len -= 4;
type = buffer_get_char(&iqueue);
switch (type) {
case SSH2_FXP_INIT:
@@ -1016,6 +1020,14 @@ process(void)
error("Unknown message %d", type);
break;
}
+ /* discard the remaining bytes from the current packet */
+ if (buf_len < buffer_len(&iqueue))
+ fatal("iqueue grows");
+ consumed = buf_len - buffer_len(&iqueue);
+ if (msg_len < consumed)
+ fatal("msg_len %d < consumed %d", msg_len, consumed);
+ if (msg_len > consumed)
+ buffer_consume(&iqueue, msg_len - consumed);
}
int
diff --git a/crypto/openssh/sftp.1 b/crypto/openssh/sftp.1
index 2faaff1..0e6d741 100644
--- a/crypto/openssh/sftp.1
+++ b/crypto/openssh/sftp.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: sftp.1,v 1.33 2002/02/26 19:06:43 deraadt Exp $
+.\" $OpenBSD: sftp.1,v 1.35 2002/06/20 20:00:05 stevesk Exp $
.\"
.\" Copyright (c) 2001 Damien Miller. All rights reserved.
.\"
@@ -83,9 +83,9 @@ and
.It Fl o Ar ssh_option
Can be used to pass options to
.Nm ssh
-in the format used in the
-.Xr ssh 1
-configuration file. This is useful for specifying options
+in the format used in
+.Xr ssh_config 5 .
+This is useful for specifying options
for which there is no separate
.Nm sftp
command-line flag. For example, to specify an alternate
@@ -100,7 +100,7 @@ does not have an sftp subsystem configured.
.It Fl v
Raise logging level. This option is also passed to ssh.
.It Fl B Ar buffer_size
-Specify the size of the buffer that
+Specify the size of the buffer that
.Nm
uses when transferring files. Larger buffers require fewer round trips at
the cost of higher memory consumption. The default is 32768 bytes.
@@ -115,13 +115,13 @@ per-user configuration file for
This option is directly passed to
.Xr ssh 1 .
.It Fl P Ar sftp_server path
-Connect directly to a local
-.Nm sftp-server
+Connect directly to a local
+.Nm sftp-server
(rather than via
.Nm ssh )
This option may be useful in debugging the client and server.
.It Fl R Ar num_requests
-Specify how many requests may be outstanding at any one time. Increasing
+Specify how many requests may be outstanding at any one time. Increasing
this may slightly improve file transfer speed but will increase memory
usage. The default is 16 outstanding requests.
.It Fl S Ar program
@@ -263,6 +263,7 @@ Damien Miller <djm@mindrot.org>
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-keygen 1 ,
+.Xr ssh_config 5 ,
.Xr sftp-server 8 ,
.Xr sshd 8
.Rs
diff --git a/crypto/openssh/sftp.c b/crypto/openssh/sftp.c
index 0a7689c..ddc7530 100644
--- a/crypto/openssh/sftp.c
+++ b/crypto/openssh/sftp.c
@@ -24,7 +24,7 @@
#include "includes.h"
-RCSID("$OpenBSD: sftp.c,v 1.26 2002/02/12 12:32:27 djm Exp $");
+RCSID("$OpenBSD: sftp.c,v 1.29 2002/04/02 17:37:48 markus Exp $");
/* XXX: short-form remote directory listings (like 'ls -C') */
@@ -88,7 +88,7 @@ static void
usage(void)
{
extern char *__progname;
-
+
fprintf(stderr,
"usage: %s [-vC1] [-b batchfile] [-o option] [-s subsystem|path] [-B buffer_size]\n"
" [-F config] [-P direct server path] [-S program]\n"
@@ -165,7 +165,7 @@ main(int argc, char **argv)
case 'R':
num_requests = strtol(optarg, &cp, 10);
if (num_requests == 0 || *cp != '\0')
- fatal("Invalid number of requests \"%s\"",
+ fatal("Invalid number of requests \"%s\"",
optarg);
break;
case 'h':
@@ -174,6 +174,8 @@ main(int argc, char **argv)
}
}
+ log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1);
+
if (sftp_direct == NULL) {
if (optind == argc || argc > (optind + 2))
usage();
@@ -203,7 +205,6 @@ main(int argc, char **argv)
usage();
}
- log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1);
addargs(&args, "-oProtocol %d", sshver);
/* no subsystem if the server-spec contains a '/' */
@@ -211,19 +212,19 @@ main(int argc, char **argv)
addargs(&args, "-s");
addargs(&args, "%s", host);
- addargs(&args, "%s", (sftp_server != NULL ?
+ addargs(&args, "%s", (sftp_server != NULL ?
sftp_server : "sftp"));
args.list[0] = ssh_program;
fprintf(stderr, "Connecting to %s...\n", host);
- connect_to_server(ssh_program, args.list, &in, &out,
+ connect_to_server(ssh_program, args.list, &in, &out,
&sshpid);
} else {
args.list = NULL;
addargs(&args, "sftp-server");
fprintf(stderr, "Attaching to %s...\n", sftp_direct);
- connect_to_server(sftp_direct, args.list, &in, &out,
+ connect_to_server(sftp_direct, args.list, &in, &out,
&sshpid);
}
@@ -234,8 +235,10 @@ main(int argc, char **argv)
if (infile != stdin)
fclose(infile);
- if (waitpid(sshpid, NULL, 0) == -1)
- fatal("Couldn't wait for ssh process: %s", strerror(errno));
+ while (waitpid(sshpid, NULL, 0) == -1)
+ if (errno != EINTR)
+ fatal("Couldn't wait for ssh process: %s",
+ strerror(errno));
exit(0);
}
diff --git a/crypto/openssh/ssh-add.1 b/crypto/openssh/ssh-add.1
index 41d5def..2a34a51 100644
--- a/crypto/openssh/ssh-add.1
+++ b/crypto/openssh/ssh-add.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ssh-add.1,v 1.30 2002/02/04 20:41:16 stevesk Exp $
+.\" $OpenBSD: ssh-add.1,v 1.35 2002/06/19 00:27:55 deraadt Exp $
.\"
.\" -*- nroff -*-
.\"
@@ -45,7 +45,8 @@
.Nd adds RSA or DSA identities to the authentication agent
.Sh SYNOPSIS
.Nm ssh-add
-.Op Fl lLdD
+.Op Fl lLdDxX
+.Op Fl t Ar life
.Op Ar
.Nm ssh-add
.Fl s Ar reader
@@ -57,7 +58,7 @@ adds RSA or DSA identities to the authentication agent,
.Xr ssh-agent 1 .
When run without arguments, it adds the files
.Pa $HOME/.ssh/id_rsa ,
-.Pa $HOME/.ssh/id_dsa
+.Pa $HOME/.ssh/id_dsa
and
.Pa $HOME/.ssh/identity .
Alternative file names can be given on the command line.
@@ -83,6 +84,15 @@ Lists public key parameters of all identities currently represented by the agent
Instead of adding the identity, removes the identity from the agent.
.It Fl D
Deletes all identities from the agent.
+.It Fl x
+Lock the agent with a password.
+.It Fl X
+Unlock the agent.
+.It Fl t Ar life
+Set a maximum lifetime when adding identities to an agent.
+The lifetime may be specified in seconds or in a time format
+specified in
+.Xr sshd 8 .
.It Fl s Ar reader
Add key in smartcard
.Ar reader .
@@ -129,6 +139,9 @@ or related script.
may be necessary to redirect the input from
.Pa /dev/null
to make this work.)
+.It Ev SSH_AUTH_SOCK
+Identifies the path of a unix-domain socket used to communicate with the
+agent.
.El
.Sh DIAGNOSTICS
Exit status is 0 on success, 1 if the specified command fails,
diff --git a/crypto/openssh/ssh-add.c b/crypto/openssh/ssh-add.c
index c7079f7..53a4a30 100644
--- a/crypto/openssh/ssh-add.c
+++ b/crypto/openssh/ssh-add.c
@@ -35,7 +35,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: ssh-add.c,v 1.50 2002/01/29 14:27:57 markus Exp $");
+RCSID("$OpenBSD: ssh-add.c,v 1.61 2002/06/19 00:27:55 deraadt Exp $");
#include <openssl/evp.h>
@@ -48,6 +48,7 @@ RCSID("$OpenBSD: ssh-add.c,v 1.50 2002/01/29 14:27:57 markus Exp $");
#include "authfile.h"
#include "pathnames.h"
#include "readpass.h"
+#include "misc.h"
/* argv0 */
extern char *__progname;
@@ -56,10 +57,12 @@ extern char *__progname;
static char *default_files[] = {
_PATH_SSH_CLIENT_ID_RSA,
_PATH_SSH_CLIENT_ID_DSA,
- _PATH_SSH_CLIENT_IDENTITY,
+ _PATH_SSH_CLIENT_IDENTITY,
NULL
};
+/* Default lifetime (0 == forever) */
+static int lifetime = 0;
/* we keep a cache of one passphrases */
static char *pass = NULL;
@@ -155,11 +158,19 @@ add_file(AuthenticationConnection *ac, const char *filename)
strlcpy(msg, "Bad passphrase, try again: ", sizeof msg);
}
}
- if (ssh_add_identity(ac, private, comment)) {
+
+ if (ssh_add_identity_constrained(ac, private, comment, lifetime)) {
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
ret = 0;
- } else
+ if (lifetime != 0)
+ fprintf(stderr,
+ "Lifetime set to %d seconds\n", lifetime);
+ } else if (ssh_add_identity(ac, private, comment)) {
+ fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
+ ret = 0;
+ } else {
fprintf(stderr, "Could not add identity: %s\n", filename);
+ }
xfree(comment);
key_free(private);
@@ -170,7 +181,13 @@ add_file(AuthenticationConnection *ac, const char *filename)
static int
update_card(AuthenticationConnection *ac, int add, const char *id)
{
- if (ssh_update_card(ac, add, id)) {
+ char *pin;
+
+ pin = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN);
+ if (pin == NULL)
+ return -1;
+
+ if (ssh_update_card(ac, add, id, pin)) {
fprintf(stderr, "Card %s: %s\n",
add ? "added" : "removed", id);
return 0;
@@ -217,6 +234,34 @@ list_identities(AuthenticationConnection *ac, int do_fp)
}
static int
+lock_agent(AuthenticationConnection *ac, int lock)
+{
+ char prompt[100], *p1, *p2;
+ int passok = 1, ret = -1;
+
+ strlcpy(prompt, "Enter lock password: ", sizeof(prompt));
+ p1 = read_passphrase(prompt, RP_ALLOW_STDIN);
+ if (lock) {
+ strlcpy(prompt, "Again: ", sizeof prompt);
+ p2 = read_passphrase(prompt, RP_ALLOW_STDIN);
+ if (strcmp(p1, p2) != 0) {
+ fprintf(stderr, "Passwords do not match.\n");
+ passok = 0;
+ }
+ memset(p2, 0, strlen(p2));
+ xfree(p2);
+ }
+ if (passok && ssh_lock_agent(ac, lock, p1)) {
+ fprintf(stderr, "Agent %slocked.\n", lock ? "" : "un");
+ ret = 0;
+ } else
+ fprintf(stderr, "Failed to %slock agent.\n", lock ? "" : "un");
+ memset(p1, 0, strlen(p1));
+ xfree(p1);
+ return -1;
+}
+
+static int
do_file(AuthenticationConnection *ac, int deleting, char *file)
{
if (deleting) {
@@ -238,6 +283,9 @@ usage(void)
fprintf(stderr, " -L List public key parameters of all identities.\n");
fprintf(stderr, " -d Delete identity.\n");
fprintf(stderr, " -D Delete all identities.\n");
+ fprintf(stderr, " -x Lock agent.\n");
+ fprintf(stderr, " -x Unlock agent.\n");
+ fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n");
#ifdef SMARTCARD
fprintf(stderr, " -s reader Add key in smartcard reader.\n");
fprintf(stderr, " -e reader Remove key in smartcard reader.\n");
@@ -261,7 +309,7 @@ main(int argc, char **argv)
fprintf(stderr, "Could not open a connection to your authentication agent.\n");
exit(2);
}
- while ((ch = getopt(argc, argv, "lLdDe:s:")) != -1) {
+ while ((ch = getopt(argc, argv, "lLdDxXe:s:t:")) != -1) {
switch (ch) {
case 'l':
case 'L':
@@ -269,6 +317,12 @@ main(int argc, char **argv)
ret = 1;
goto done;
break;
+ case 'x':
+ case 'X':
+ if (lock_agent(ac, ch == 'x' ? 1 : 0) == -1)
+ ret = 1;
+ goto done;
+ break;
case 'd':
deleting = 1;
break;
@@ -284,6 +338,13 @@ main(int argc, char **argv)
deleting = 1;
sc_reader_id = optarg;
break;
+ case 't':
+ if ((lifetime = convtime(optarg)) == -1) {
+ fprintf(stderr, "Invalid lifetime\n");
+ ret = 1;
+ goto done;
+ }
+ break;
default:
usage();
ret = 1;
@@ -300,6 +361,8 @@ main(int argc, char **argv)
if (argc == 0) {
char buf[MAXPATHLEN];
struct passwd *pw;
+ struct stat st;
+ int count = 0;
if ((pw = getpwuid(getuid())) == NULL) {
fprintf(stderr, "No user found with uid %u\n",
@@ -309,11 +372,17 @@ main(int argc, char **argv)
}
for(i = 0; default_files[i]; i++) {
- snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,
+ snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,
default_files[i]);
+ if (stat(buf, &st) < 0)
+ continue;
if (do_file(ac, deleting, buf) == -1)
ret = 1;
+ else
+ count++;
}
+ if (count == 0)
+ ret = 1;
} else {
for(i = 0; i < argc; i++) {
if (do_file(ac, deleting, argv[i]) == -1)
diff --git a/crypto/openssh/ssh-agent.1 b/crypto/openssh/ssh-agent.1
index 9909ef5..e5ea1e3 100644
--- a/crypto/openssh/ssh-agent.1
+++ b/crypto/openssh/ssh-agent.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ssh-agent.1,v 1.31 2002/02/04 20:41:16 stevesk Exp $
+.\" $OpenBSD: ssh-agent.1,v 1.33 2002/06/19 00:27:55 deraadt Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -42,6 +42,7 @@
.Nd authentication agent
.Sh SYNOPSIS
.Nm ssh-agent
+.Op Fl a Ar bind_address
.Op Fl c Li | Fl s
.Op Fl d
.Op Ar command Op Ar args ...
@@ -64,6 +65,11 @@ machines using
.Pp
The options are as follows:
.Bl -tag -width Ds
+.It Fl a Ar bind_address
+Bind the agent to the unix-domain socket
+.Ar bind_address .
+The default is
+.Pa /tmp/ssh-XXXXXXXX/agent.<pid> .
.It Fl c
Generate C-shell commands on
.Dv stdout .
@@ -96,7 +102,7 @@ When executed without arguments,
.Xr ssh-add 1
adds the files
.Pa $HOME/.ssh/id_rsa ,
-.Pa $HOME/.ssh/id_dsa
+.Pa $HOME/.ssh/id_dsa
and
.Pa $HOME/.ssh/identity .
If the identity has a passphrase,
@@ -135,7 +141,6 @@ by the agent, and the result will be returned to the requester.
This way, private keys are not exposed to clients using the agent.
.Pp
A unix-domain socket is created
-.Pq Pa /tmp/ssh-XXXXXXXX/agent.<pid> ,
and the name of this socket is stored in the
.Ev SSH_AUTH_SOCK
environment
diff --git a/crypto/openssh/ssh-agent.c b/crypto/openssh/ssh-agent.c
index 786f91c..84f75fd 100644
--- a/crypto/openssh/ssh-agent.c
+++ b/crypto/openssh/ssh-agent.c
@@ -35,7 +35,7 @@
#include "includes.h"
#include <sys/queue.h>
-RCSID("$OpenBSD: ssh-agent.c,v 1.82 2002/03/04 17:27:39 stevesk Exp $");
+RCSID("$OpenBSD: ssh-agent.c,v 1.95 2002/06/19 00:27:55 deraadt Exp $");
#include <openssl/evp.h>
#include <openssl/md5.h>
@@ -52,7 +52,6 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.82 2002/03/04 17:27:39 stevesk Exp $");
#include "log.h"
#ifdef SMARTCARD
-#include <openssl/engine.h>
#include "scard.h"
#endif
@@ -67,6 +66,7 @@ typedef struct {
sock_type type;
Buffer input;
Buffer output;
+ Buffer request;
} SocketEntry;
u_int sockets_alloc = 0;
@@ -76,6 +76,7 @@ typedef struct identity {
TAILQ_ENTRY(identity) next;
Key *key;
char *comment;
+ u_int death;
} Identity;
typedef struct {
@@ -95,6 +96,10 @@ pid_t parent_pid = -1;
char socket_name[1024];
char socket_dir[1024];
+/* locking */
+int locked = 0;
+char *lock_passwd = NULL;
+
extern char *__progname;
static void
@@ -116,6 +121,14 @@ idtab_lookup(int version)
return &idtable[version];
}
+static void
+free_identity(Identity *id)
+{
+ key_free(id->key);
+ xfree(id->comment);
+ xfree(id);
+}
+
/* return matching private key for given public key */
static Identity *
lookup_identity(Key *key, int version)
@@ -130,14 +143,6 @@ lookup_identity(Key *key, int version)
return (NULL);
}
-static void
-free_identity(Identity *id)
-{
- key_free(id->key);
- xfree(id->comment);
- xfree(id);
-}
-
/* send list of supported public keys to 'client' */
static void
process_request_identities(SocketEntry *e, int version)
@@ -187,16 +192,16 @@ process_authentication_challenge1(SocketEntry *e)
if ((challenge = BN_new()) == NULL)
fatal("process_authentication_challenge1: BN_new failed");
- buffer_get_int(&e->input); /* ignored */
- buffer_get_bignum(&e->input, key->rsa->e);
- buffer_get_bignum(&e->input, key->rsa->n);
- buffer_get_bignum(&e->input, challenge);
+ buffer_get_int(&e->request); /* ignored */
+ buffer_get_bignum(&e->request, key->rsa->e);
+ buffer_get_bignum(&e->request, key->rsa->n);
+ buffer_get_bignum(&e->request, challenge);
/* Only protocol 1.1 is supported */
- if (buffer_len(&e->input) == 0)
+ if (buffer_len(&e->request) == 0)
goto failure;
- buffer_get(&e->input, session_id, 16);
- response_type = buffer_get_int(&e->input);
+ buffer_get(&e->request, session_id, 16);
+ response_type = buffer_get_int(&e->request);
if (response_type != 1)
goto failure;
@@ -252,10 +257,10 @@ process_sign_request2(SocketEntry *e)
datafellows = 0;
- blob = buffer_get_string(&e->input, &blen);
- data = buffer_get_string(&e->input, &dlen);
+ blob = buffer_get_string(&e->request, &blen);
+ data = buffer_get_string(&e->request, &dlen);
- flags = buffer_get_int(&e->input);
+ flags = buffer_get_int(&e->request);
if (flags & SSH_AGENT_OLD_SIGNATURE)
datafellows = SSH_BUG_SIGBLOB;
@@ -296,16 +301,16 @@ process_remove_identity(SocketEntry *e, int version)
switch (version) {
case 1:
key = key_new(KEY_RSA1);
- bits = buffer_get_int(&e->input);
- buffer_get_bignum(&e->input, key->rsa->e);
- buffer_get_bignum(&e->input, key->rsa->n);
+ bits = buffer_get_int(&e->request);
+ buffer_get_bignum(&e->request, key->rsa->e);
+ buffer_get_bignum(&e->request, key->rsa->n);
if (bits != key_size(key))
log("Warning: identity keysize mismatch: actual %d, announced %d",
key_size(key), bits);
break;
case 2:
- blob = buffer_get_string(&e->input, &blen);
+ blob = buffer_get_string(&e->request, &blen);
key = key_from_blob(blob, blen);
xfree(blob);
break;
@@ -356,7 +361,27 @@ process_remove_all_identities(SocketEntry *e, int version)
/* Send success. */
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
- return;
+}
+
+static void
+reaper(void)
+{
+ Idtab *tab;
+ Identity *id, *nxt;
+ int version;
+ u_int now = time(NULL);
+
+ for (version = 1; version < 3; version++) {
+ tab = idtab_lookup(version);
+ for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
+ nxt = TAILQ_NEXT(id, next);
+ if (id->death != 0 && now >= id->death) {
+ TAILQ_REMOVE(&tab->idlist, id, next);
+ free_identity(id);
+ tab->nentries--;
+ }
+ }
+ }
}
static void
@@ -365,66 +390,76 @@ process_add_identity(SocketEntry *e, int version)
Key *k = NULL;
char *type_name;
char *comment;
- int type, success = 0;
+ int type, success = 0, death = 0;
Idtab *tab = idtab_lookup(version);
switch (version) {
case 1:
k = key_new_private(KEY_RSA1);
- buffer_get_int(&e->input); /* ignored */
- buffer_get_bignum(&e->input, k->rsa->n);
- buffer_get_bignum(&e->input, k->rsa->e);
- buffer_get_bignum(&e->input, k->rsa->d);
- buffer_get_bignum(&e->input, k->rsa->iqmp);
+ buffer_get_int(&e->request); /* ignored */
+ buffer_get_bignum(&e->request, k->rsa->n);
+ buffer_get_bignum(&e->request, k->rsa->e);
+ buffer_get_bignum(&e->request, k->rsa->d);
+ buffer_get_bignum(&e->request, k->rsa->iqmp);
/* SSH and SSL have p and q swapped */
- buffer_get_bignum(&e->input, k->rsa->q); /* p */
- buffer_get_bignum(&e->input, k->rsa->p); /* q */
+ buffer_get_bignum(&e->request, k->rsa->q); /* p */
+ buffer_get_bignum(&e->request, k->rsa->p); /* q */
/* Generate additional parameters */
rsa_generate_additional_parameters(k->rsa);
break;
case 2:
- type_name = buffer_get_string(&e->input, NULL);
+ type_name = buffer_get_string(&e->request, NULL);
type = key_type_from_name(type_name);
xfree(type_name);
switch (type) {
case KEY_DSA:
k = key_new_private(type);
- buffer_get_bignum2(&e->input, k->dsa->p);
- buffer_get_bignum2(&e->input, k->dsa->q);
- buffer_get_bignum2(&e->input, k->dsa->g);
- buffer_get_bignum2(&e->input, k->dsa->pub_key);
- buffer_get_bignum2(&e->input, k->dsa->priv_key);
+ buffer_get_bignum2(&e->request, k->dsa->p);
+ buffer_get_bignum2(&e->request, k->dsa->q);
+ buffer_get_bignum2(&e->request, k->dsa->g);
+ buffer_get_bignum2(&e->request, k->dsa->pub_key);
+ buffer_get_bignum2(&e->request, k->dsa->priv_key);
break;
case KEY_RSA:
k = key_new_private(type);
- buffer_get_bignum2(&e->input, k->rsa->n);
- buffer_get_bignum2(&e->input, k->rsa->e);
- buffer_get_bignum2(&e->input, k->rsa->d);
- buffer_get_bignum2(&e->input, k->rsa->iqmp);
- buffer_get_bignum2(&e->input, k->rsa->p);
- buffer_get_bignum2(&e->input, k->rsa->q);
+ buffer_get_bignum2(&e->request, k->rsa->n);
+ buffer_get_bignum2(&e->request, k->rsa->e);
+ buffer_get_bignum2(&e->request, k->rsa->d);
+ buffer_get_bignum2(&e->request, k->rsa->iqmp);
+ buffer_get_bignum2(&e->request, k->rsa->p);
+ buffer_get_bignum2(&e->request, k->rsa->q);
/* Generate additional parameters */
rsa_generate_additional_parameters(k->rsa);
break;
default:
- buffer_clear(&e->input);
+ buffer_clear(&e->request);
goto send;
}
break;
}
- comment = buffer_get_string(&e->input, NULL);
+ comment = buffer_get_string(&e->request, NULL);
if (k == NULL) {
xfree(comment);
goto send;
}
success = 1;
+ while (buffer_len(&e->request)) {
+ switch (buffer_get_char(&e->request)) {
+ case SSH_AGENT_CONSTRAIN_LIFETIME:
+ death = time(NULL) + buffer_get_int(&e->request);
+ break;
+ default:
+ break;
+ }
+ }
if (lookup_identity(k, version) == NULL) {
Identity *id = xmalloc(sizeof(Identity));
id->key = k;
id->comment = comment;
+ id->death = death;
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
/* Increment the number of identities. */
tab->nentries++;
@@ -438,53 +473,86 @@ send:
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
}
+/* XXX todo: encrypt sensitive data with passphrase */
+static void
+process_lock_agent(SocketEntry *e, int lock)
+{
+ char *passwd;
+ int success = 0;
+
+ passwd = buffer_get_string(&e->request, NULL);
+ if (locked && !lock && strcmp(passwd, lock_passwd) == 0) {
+ locked = 0;
+ memset(lock_passwd, 0, strlen(lock_passwd));
+ xfree(lock_passwd);
+ lock_passwd = NULL;
+ success = 1;
+ } else if (!locked && lock) {
+ locked = 1;
+ lock_passwd = xstrdup(passwd);
+ success = 1;
+ }
+ memset(passwd, 0, strlen(passwd));
+ xfree(passwd);
+
+ buffer_put_int(&e->output, 1);
+ buffer_put_char(&e->output,
+ success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
+}
+
+static void
+no_identities(SocketEntry *e, u_int type)
+{
+ Buffer msg;
+
+ buffer_init(&msg);
+ buffer_put_char(&msg,
+ (type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ?
+ SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
+ buffer_put_int(&msg, 0);
+ buffer_put_int(&e->output, buffer_len(&msg));
+ buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
+ buffer_free(&msg);
+}
#ifdef SMARTCARD
static void
process_add_smartcard_key (SocketEntry *e)
{
+ Identity *id;
Idtab *tab;
- Key *n = NULL, *k = NULL;
- char *sc_reader_id = NULL;
- int success = 0;
+ Key **keys, *k;
+ char *sc_reader_id = NULL, *pin;
+ int i, version, success = 0;
- sc_reader_id = buffer_get_string(&e->input, NULL);
- k = sc_get_key(sc_reader_id);
+ sc_reader_id = buffer_get_string(&e->request, NULL);
+ pin = buffer_get_string(&e->request, NULL);
+ keys = sc_get_keys(sc_reader_id, pin);
xfree(sc_reader_id);
+ xfree(pin);
- if (k == NULL) {
- error("sc_get_pubkey failed");
+ if (keys == NULL || keys[0] == NULL) {
+ error("sc_get_keys failed");
goto send;
}
- success = 1;
-
- tab = idtab_lookup(1);
- k->type = KEY_RSA1;
- if (lookup_identity(k, 1) == NULL) {
- Identity *id = xmalloc(sizeof(Identity));
- n = key_new(KEY_RSA1);
- BN_copy(n->rsa->n, k->rsa->n);
- BN_copy(n->rsa->e, k->rsa->e);
- RSA_set_method(n->rsa, sc_get_engine());
- id->key = n;
- id->comment = xstrdup("rsa1 smartcard");
- TAILQ_INSERT_TAIL(&tab->idlist, id, next);
- tab->nentries++;
- }
- k->type = KEY_RSA;
- tab = idtab_lookup(2);
- if (lookup_identity(k, 2) == NULL) {
- Identity *id = xmalloc(sizeof(Identity));
- n = key_new(KEY_RSA);
- BN_copy(n->rsa->n, k->rsa->n);
- BN_copy(n->rsa->e, k->rsa->e);
- RSA_set_method(n->rsa, sc_get_engine());
- id->key = n;
- id->comment = xstrdup("rsa smartcard");
- TAILQ_INSERT_TAIL(&tab->idlist, id, next);
- tab->nentries++;
+ for (i = 0; keys[i] != NULL; i++) {
+ k = keys[i];
+ version = k->type == KEY_RSA1 ? 1 : 2;
+ tab = idtab_lookup(version);
+ if (lookup_identity(k, version) == NULL) {
+ id = xmalloc(sizeof(Identity));
+ id->key = k;
+ id->comment = xstrdup("smartcard key");
+ id->death = 0;
+ TAILQ_INSERT_TAIL(&tab->idlist, id, next);
+ tab->nentries++;
+ success = 1;
+ } else {
+ key_free(k);
+ }
+ keys[i] = NULL;
}
- key_free(k);
+ xfree(keys);
send:
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output,
@@ -494,39 +562,37 @@ send:
static void
process_remove_smartcard_key(SocketEntry *e)
{
- Key *k = NULL;
- int success = 0;
- char *sc_reader_id = NULL;
+ Identity *id;
+ Idtab *tab;
+ Key **keys, *k = NULL;
+ char *sc_reader_id = NULL, *pin;
+ int i, version, success = 0;
- sc_reader_id = buffer_get_string(&e->input, NULL);
- k = sc_get_key(sc_reader_id);
+ sc_reader_id = buffer_get_string(&e->request, NULL);
+ pin = buffer_get_string(&e->request, NULL);
+ keys = sc_get_keys(sc_reader_id, pin);
xfree(sc_reader_id);
+ xfree(pin);
- if (k == NULL) {
- error("sc_get_pubkey failed");
- } else {
- Identity *id;
- k->type = KEY_RSA1;
- id = lookup_identity(k, 1);
- if (id != NULL) {
- Idtab *tab = idtab_lookup(1);
+ if (keys == NULL || keys[0] == NULL) {
+ error("sc_get_keys failed");
+ goto send;
+ }
+ for (i = 0; keys[i] != NULL; i++) {
+ k = keys[i];
+ version = k->type == KEY_RSA1 ? 1 : 2;
+ if ((id = lookup_identity(k, version)) != NULL) {
+ tab = idtab_lookup(version);
TAILQ_REMOVE(&tab->idlist, id, next);
- free_identity(id);
tab->nentries--;
- success = 1;
- }
- k->type = KEY_RSA;
- id = lookup_identity(k, 2);
- if (id != NULL) {
- Idtab *tab = idtab_lookup(2);
- TAILQ_REMOVE(&tab->idlist, id, next);
free_identity(id);
- tab->nentries--;
success = 1;
}
key_free(k);
+ keys[i] = NULL;
}
-
+ xfree(keys);
+send:
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output,
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
@@ -541,6 +607,10 @@ process_message(SocketEntry *e)
u_int msg_len;
u_int type;
u_char *cp;
+
+ /* kill dead keys */
+ reaper();
+
if (buffer_len(&e->input) < 5)
return; /* Incomplete message. */
cp = buffer_ptr(&e->input);
@@ -549,15 +619,44 @@ process_message(SocketEntry *e)
shutdown(e->fd, SHUT_RDWR);
close(e->fd);
e->type = AUTH_UNUSED;
+ buffer_free(&e->input);
+ buffer_free(&e->output);
+ buffer_free(&e->request);
return;
}
if (buffer_len(&e->input) < msg_len + 4)
return;
+
+ /* move the current input to e->request */
buffer_consume(&e->input, 4);
- type = buffer_get_char(&e->input);
+ buffer_clear(&e->request);
+ buffer_append(&e->request, buffer_ptr(&e->input), msg_len);
+ buffer_consume(&e->input, msg_len);
+ type = buffer_get_char(&e->request);
+
+ /* check wheter agent is locked */
+ if (locked && type != SSH_AGENTC_UNLOCK) {
+ buffer_clear(&e->request);
+ switch (type) {
+ case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
+ case SSH2_AGENTC_REQUEST_IDENTITIES:
+ /* send empty lists */
+ no_identities(e, type);
+ break;
+ default:
+ /* send a fail message for all other request types */
+ buffer_put_int(&e->output, 1);
+ buffer_put_char(&e->output, SSH_AGENT_FAILURE);
+ }
+ return;
+ }
debug("type %d", type);
switch (type) {
+ case SSH_AGENTC_LOCK:
+ case SSH_AGENTC_UNLOCK:
+ process_lock_agent(e, type == SSH_AGENTC_LOCK);
+ break;
/* ssh1 */
case SSH_AGENTC_RSA_CHALLENGE:
process_authentication_challenge1(e);
@@ -566,6 +665,7 @@ process_message(SocketEntry *e)
process_request_identities(e, 1);
break;
case SSH_AGENTC_ADD_RSA_IDENTITY:
+ case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED:
process_add_identity(e, 1);
break;
case SSH_AGENTC_REMOVE_RSA_IDENTITY:
@@ -582,6 +682,7 @@ process_message(SocketEntry *e)
process_request_identities(e, 2);
break;
case SSH2_AGENTC_ADD_IDENTITY:
+ case SSH2_AGENTC_ADD_ID_CONSTRAINED:
process_add_identity(e, 2);
break;
case SSH2_AGENTC_REMOVE_IDENTITY:
@@ -601,7 +702,7 @@ process_message(SocketEntry *e)
default:
/* Unknown message. Respond with failure. */
error("Unknown message %d", type);
- buffer_clear(&e->input);
+ buffer_clear(&e->request);
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_FAILURE);
break;
@@ -624,6 +725,7 @@ new_socket(sock_type type, int fd)
sockets[i].type = type;
buffer_init(&sockets[i].input);
buffer_init(&sockets[i].output);
+ buffer_init(&sockets[i].request);
return;
}
old_alloc = sockets_alloc;
@@ -638,6 +740,7 @@ new_socket(sock_type type, int fd)
sockets[old_alloc].fd = fd;
buffer_init(&sockets[old_alloc].input);
buffer_init(&sockets[old_alloc].output);
+ buffer_init(&sockets[old_alloc].request);
}
static int
@@ -735,6 +838,7 @@ after_select(fd_set *readset, fd_set *writeset)
sockets[i].type = AUTH_UNUSED;
buffer_free(&sockets[i].input);
buffer_free(&sockets[i].output);
+ buffer_free(&sockets[i].request);
break;
}
buffer_consume(&sockets[i].output, len);
@@ -753,6 +857,7 @@ after_select(fd_set *readset, fd_set *writeset)
sockets[i].type = AUTH_UNUSED;
buffer_free(&sockets[i].input);
buffer_free(&sockets[i].output);
+ buffer_free(&sockets[i].request);
break;
}
buffer_append(&sockets[i].input, buf, len);
@@ -811,6 +916,7 @@ usage(void)
fprintf(stderr, " -s Generate Bourne shell commands on stdout.\n");
fprintf(stderr, " -k Kill the current agent.\n");
fprintf(stderr, " -d Debug mode.\n");
+ fprintf(stderr, " -a socket Bind agent socket to given name.\n");
exit(1);
}
@@ -822,12 +928,13 @@ main(int ac, char **av)
struct rlimit rlim;
pid_t pid;
char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
+ char *agentsocket = NULL;
extern int optind;
fd_set *readsetp = NULL, *writesetp = NULL;
SSLeay_add_all_algorithms();
- while ((ch = getopt(ac, av, "cdks")) != -1) {
+ while ((ch = getopt(ac, av, "cdksa:")) != -1) {
switch (ch) {
case 'c':
if (s_flag)
@@ -847,6 +954,9 @@ main(int ac, char **av)
usage();
d_flag++;
break;
+ case 'a':
+ agentsocket = optarg;
+ break;
default:
usage();
}
@@ -857,7 +967,7 @@ main(int ac, char **av)
if (ac > 0 && (c_flag || k_flag || s_flag || d_flag))
usage();
- if (ac == 0 && !c_flag && !k_flag && !s_flag && !d_flag) {
+ if (ac == 0 && !c_flag && !s_flag) {
shell = getenv("SHELL");
if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
c_flag = 1;
@@ -882,19 +992,25 @@ main(int ac, char **av)
format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME);
printf(format, SSH_AGENTPID_ENV_NAME);
- printf("echo Agent pid %d killed;\n", pid);
+ printf("echo Agent pid %ld killed;\n", (long)pid);
exit(0);
}
parent_pid = getpid();
- /* Create private directory for agent socket */
- strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir);
- if (mkdtemp(socket_dir) == NULL) {
- perror("mkdtemp: private socket dir");
- exit(1);
+ if (agentsocket == NULL) {
+ /* Create private directory for agent socket */
+ strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir);
+ if (mkdtemp(socket_dir) == NULL) {
+ perror("mkdtemp: private socket dir");
+ exit(1);
+ }
+ snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir,
+ (long)parent_pid);
+ } else {
+ /* Try to use specified agent socket */
+ socket_dir[0] = '\0';
+ strlcpy(socket_name, agentsocket, sizeof socket_name);
}
- snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir,
- parent_pid);
/*
* Create socket early so it will exist before command gets run from
@@ -926,7 +1042,7 @@ main(int ac, char **av)
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
- printf("echo Agent pid %d;\n", parent_pid);
+ printf("echo Agent pid %ld;\n", (long)parent_pid);
goto skip;
}
pid = fork();
@@ -936,14 +1052,14 @@ main(int ac, char **av)
}
if (pid != 0) { /* Parent - execute the given command. */
close(sock);
- snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid);
+ snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid);
if (ac == 0) {
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
SSH_AGENTPID_ENV_NAME);
- printf("echo Agent pid %d;\n", pid);
+ printf("echo Agent pid %ld;\n", (long)pid);
exit(0);
}
if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||
diff --git a/crypto/openssh/ssh-keygen.1 b/crypto/openssh/ssh-keygen.1
index 6ad94e6..35b0bb9 100644
--- a/crypto/openssh/ssh-keygen.1
+++ b/crypto/openssh/ssh-keygen.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ssh-keygen.1,v 1.53 2002/02/16 14:53:37 stevesk Exp $
+.\" $OpenBSD: ssh-keygen.1,v 1.54 2002/06/19 00:27:55 deraadt Exp $
.\"
.\" -*- nroff -*-
.\"
@@ -86,7 +86,7 @@
generates, manages and converts authentication keys for
.Xr ssh 1 .
.Nm
-can create RSA keys for use by SSH protocol version 1 and RSA or DSA
+can create RSA keys for use by SSH protocol version 1 and RSA or DSA
keys for use by SSH protocol version 2. The type of key to be generated
is specified with the
.Fl t
diff --git a/crypto/openssh/ssh-keygen.c b/crypto/openssh/ssh-keygen.c
index 961fad6..66f00cc 100644
--- a/crypto/openssh/ssh-keygen.c
+++ b/crypto/openssh/ssh-keygen.c
@@ -12,7 +12,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: ssh-keygen.c,v 1.94 2002/02/25 16:33:27 markus Exp $");
+RCSID("$OpenBSD: ssh-keygen.c,v 1.100 2002/06/19 00:27:55 deraadt Exp $");
#include <openssl/evp.h>
#include <openssl/pem.h>
@@ -29,8 +29,6 @@ RCSID("$OpenBSD: ssh-keygen.c,v 1.94 2002/02/25 16:33:27 markus Exp $");
#include "readpass.h"
#ifdef SMARTCARD
-#include <sectok.h>
-#include <openssl/engine.h>
#include "scard.h"
#endif
@@ -138,7 +136,7 @@ load_identity(char *filename)
}
#define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----"
-#define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----"
+#define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----"
#define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
#define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb
@@ -288,6 +286,7 @@ do_convert_from_ssh2(struct passwd *pw)
{
Key *k;
int blen;
+ u_int len;
char line[1024], *p;
u_char blob[8096];
char encoded[8096];
@@ -332,6 +331,12 @@ do_convert_from_ssh2(struct passwd *pw)
*p = '\0';
strlcat(encoded, line, sizeof(encoded));
}
+ len = strlen(encoded);
+ if (((len % 4) == 3) &&
+ (encoded[len-1] == '=') &&
+ (encoded[len-2] == '=') &&
+ (encoded[len-3] == '='))
+ encoded[len-3] = '\0';
blen = uudecode(encoded, blob, sizeof(blob));
if (blen < 0) {
fprintf(stderr, "uudecode failed.\n");
@@ -385,145 +390,47 @@ do_print_public(struct passwd *pw)
}
#ifdef SMARTCARD
-#define NUM_RSA_KEY_ELEMENTS 5+1
-#define COPY_RSA_KEY(x, i) \
- do { \
- len = BN_num_bytes(prv->rsa->x); \
- elements[i] = xmalloc(len); \
- debug("#bytes %d", len); \
- if (BN_bn2bin(prv->rsa->x, elements[i]) < 0) \
- goto done; \
- } while (0)
-
-static int
-get_AUT0(char *aut0)
-{
- EVP_MD *evp_md = EVP_sha1();
- EVP_MD_CTX md;
- char *pass;
-
- pass = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN);
- if (pass == NULL)
- return -1;
- EVP_DigestInit(&md, evp_md);
- EVP_DigestUpdate(&md, pass, strlen(pass));
- EVP_DigestFinal(&md, aut0, NULL);
- memset(pass, 0, strlen(pass));
- xfree(pass);
- return 0;
-}
-
static void
do_upload(struct passwd *pw, const char *sc_reader_id)
{
Key *prv = NULL;
struct stat st;
- u_char *elements[NUM_RSA_KEY_ELEMENTS];
- u_char key_fid[2];
- u_char DEFAUT0[] = {0xad, 0x9f, 0x61, 0xfe, 0xfa, 0x20, 0xce, 0x63};
- u_char AUT0[EVP_MAX_MD_SIZE];
- int len, status = 1, i, fd = -1, ret;
- int sw = 0, cla = 0x00;
-
- for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
- elements[i] = NULL;
+ int ret;
+
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0) {
perror(identity_file);
- goto done;
+ exit(1);
}
prv = load_identity(identity_file);
if (prv == NULL) {
error("load failed");
- goto done;
- }
- COPY_RSA_KEY(q, 0);
- COPY_RSA_KEY(p, 1);
- COPY_RSA_KEY(iqmp, 2);
- COPY_RSA_KEY(dmq1, 3);
- COPY_RSA_KEY(dmp1, 4);
- COPY_RSA_KEY(n, 5);
- len = BN_num_bytes(prv->rsa->n);
- fd = sectok_friendly_open(sc_reader_id, STONOWAIT, &sw);
- if (fd < 0) {
- error("sectok_open failed: %s", sectok_get_sw(sw));
- goto done;
- }
- if (! sectok_cardpresent(fd)) {
- error("smartcard in reader %s not present",
- sc_reader_id);
- goto done;
- }
- ret = sectok_reset(fd, 0, NULL, &sw);
- if (ret <= 0) {
- error("sectok_reset failed: %s", sectok_get_sw(sw));
- goto done;
- }
- if ((cla = cyberflex_inq_class(fd)) < 0) {
- error("cyberflex_inq_class failed");
- goto done;
- }
- memcpy(AUT0, DEFAUT0, sizeof(DEFAUT0));
- if (cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) {
- if (get_AUT0(AUT0) < 0 ||
- cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) {
- error("cyberflex_verify_AUT0 failed");
- goto done;
- }
- }
- key_fid[0] = 0x00;
- key_fid[1] = 0x12;
- if (cyberflex_load_rsa_priv(fd, cla, key_fid, 5, 8*len, elements,
- &sw) < 0) {
- error("cyberflex_load_rsa_priv failed: %s", sectok_get_sw(sw));
- goto done;
- }
- if (!sectok_swOK(sw))
- goto done;
- log("cyberflex_load_rsa_priv done");
- key_fid[0] = 0x73;
- key_fid[1] = 0x68;
- if (cyberflex_load_rsa_pub(fd, cla, key_fid, len, elements[5],
- &sw) < 0) {
- error("cyberflex_load_rsa_pub failed: %s", sectok_get_sw(sw));
- goto done;
+ exit(1);
}
- if (!sectok_swOK(sw))
- goto done;
- log("cyberflex_load_rsa_pub done");
- status = 0;
+ ret = sc_put_key(prv, sc_reader_id);
+ key_free(prv);
+ if (ret < 0)
+ exit(1);
log("loading key done");
-done:
-
- memset(elements[0], '\0', BN_num_bytes(prv->rsa->q));
- memset(elements[1], '\0', BN_num_bytes(prv->rsa->p));
- memset(elements[2], '\0', BN_num_bytes(prv->rsa->iqmp));
- memset(elements[3], '\0', BN_num_bytes(prv->rsa->dmq1));
- memset(elements[4], '\0', BN_num_bytes(prv->rsa->dmp1));
- memset(elements[5], '\0', BN_num_bytes(prv->rsa->n));
-
- if (prv)
- key_free(prv);
- for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
- if (elements[i])
- xfree(elements[i]);
- if (fd != -1)
- sectok_close(fd);
- exit(status);
+ exit(0);
}
static void
do_download(struct passwd *pw, const char *sc_reader_id)
{
- Key *pub = NULL;
+ Key **keys = NULL;
+ int i;
- pub = sc_get_key(sc_reader_id);
- if (pub == NULL)
+ keys = sc_get_keys(sc_reader_id, NULL);
+ if (keys == NULL)
fatal("cannot read public key from smartcard");
- key_write(pub, stdout);
- key_free(pub);
- fprintf(stdout, "\n");
+ for (i = 0; keys[i]; i++) {
+ key_write(keys[i], stdout);
+ key_free(keys[i]);
+ fprintf(stdout, "\n");
+ }
+ xfree(keys);
exit(0);
}
#endif /* SMARTCARD */
diff --git a/crypto/openssh/ssh-keyscan.c b/crypto/openssh/ssh-keyscan.c
index 5fc5330..947f704 100644
--- a/crypto/openssh/ssh-keyscan.c
+++ b/crypto/openssh/ssh-keyscan.c
@@ -7,7 +7,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: ssh-keyscan.c,v 1.35 2002/03/04 18:30:23 stevesk Exp $");
+RCSID("$OpenBSD: ssh-keyscan.c,v 1.36 2002/06/16 21:30:58 itojun Exp $");
#include <sys/queue.h>
#include <errno.h>
@@ -581,7 +581,7 @@ conloop(void)
con *c;
gettimeofday(&now, NULL);
- c = tq.tqh_first;
+ c = TAILQ_FIRST(&tq);
if (c && (c->c_tv.tv_sec > now.tv_sec ||
(c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec > now.tv_usec))) {
@@ -614,12 +614,12 @@ conloop(void)
xfree(r);
xfree(e);
- c = tq.tqh_first;
+ c = TAILQ_FIRST(&tq);
while (c && (c->c_tv.tv_sec < now.tv_sec ||
(c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec < now.tv_usec))) {
int s = c->c_fd;
- c = c->c_link.tqe_next;
+ c = TAILQ_NEXT(c, c_link);
conrecycle(s);
}
}
diff --git a/crypto/openssh/ssh-keysign.8 b/crypto/openssh/ssh-keysign.8
new file mode 100644
index 0000000..ab2cf21
--- /dev/null
+++ b/crypto/openssh/ssh-keysign.8
@@ -0,0 +1,67 @@
+.\" $OpenBSD: ssh-keysign.8,v 1.2 2002/06/10 16:56:30 stevesk Exp $
+.\"
+.\" Copyright (c) 2002 Markus Friedl. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd May 24, 2002
+.Dt SSH-KEYSIGN 8
+.Os
+.Sh NAME
+.Nm ssh-keysign
+.Nd ssh helper program for hostbased authentication
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+.Nm
+is used by
+.Xr ssh 1
+to access the local host keys and generate the digital signature
+required during hostbased authentication with SSH protocol version 2.
+.Nm
+is not intended to be invoked by the user, but from
+.Xr ssh 1 .
+See
+.Xr ssh 1
+and
+.Xr sshd 8
+for more information about hostbased authentication.
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_rsa_key
+These files contain the private parts of the host keys used to
+generate the digital signature. They
+should be owned by root, readable only by root, and not
+accessible to others.
+Since they are readable only by root,
+.Nm
+must be set-uid root if hostbased authentication is used.
+.El
+.Sh SEE ALSO
+.Xr ssh 1 ,
+.Xr ssh-keygen 1 ,
+.Xr sshd 8
+.Sh AUTHORS
+Markus Friedl <markus@openbsd.org>
+.Sh HISTORY
+.Nm
+first appeared in
+.Ox 3.2 .
diff --git a/crypto/openssh/ssh-keysign.c b/crypto/openssh/ssh-keysign.c
new file mode 100644
index 0000000..0f69b9b
--- /dev/null
+++ b/crypto/openssh/ssh-keysign.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2002 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "includes.h"
+RCSID("$OpenBSD: ssh-keysign.c,v 1.4 2002/06/19 00:27:55 deraadt Exp $");
+
+#include <openssl/evp.h>
+
+#include "log.h"
+#include "key.h"
+#include "ssh2.h"
+#include "misc.h"
+#include "xmalloc.h"
+#include "buffer.h"
+#include "bufaux.h"
+#include "authfile.h"
+#include "msg.h"
+#include "canohost.h"
+#include "pathnames.h"
+
+static int
+valid_request(struct passwd *pw, char *host, Key **ret, u_char *data,
+ u_int datalen)
+{
+ Buffer b;
+ Key *key;
+ u_char *pkblob;
+ u_int blen, len;
+ char *pkalg, *p;
+ int pktype, fail;
+
+ fail = 0;
+
+ buffer_init(&b);
+ buffer_append(&b, data, datalen);
+
+ /* session id, currently limited to SHA1 (20 bytes) */
+ p = buffer_get_string(&b, &len);
+ if (len != 20)
+ fail++;
+ xfree(p);
+
+ if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
+ fail++;
+
+ /* server user */
+ buffer_skip_string(&b);
+
+ /* service */
+ p = buffer_get_string(&b, NULL);
+ if (strcmp("ssh-connection", p) != 0)
+ fail++;
+ xfree(p);
+
+ /* method */
+ p = buffer_get_string(&b, NULL);
+ if (strcmp("hostbased", p) != 0)
+ fail++;
+ xfree(p);
+
+ /* pubkey */
+ pkalg = buffer_get_string(&b, NULL);
+ pkblob = buffer_get_string(&b, &blen);
+
+ pktype = key_type_from_name(pkalg);
+ if (pktype == KEY_UNSPEC)
+ fail++;
+ else if ((key = key_from_blob(pkblob, blen)) == NULL)
+ fail++;
+ else if (key->type != pktype)
+ fail++;
+ xfree(pkalg);
+ xfree(pkblob);
+
+ /* client host name, handle trailing dot */
+ p = buffer_get_string(&b, &len);
+ debug2("valid_request: check expect chost %s got %s", host, p);
+ if (strlen(host) != len - 1)
+ fail++;
+ else if (p[len - 1] != '.')
+ fail++;
+ else if (strncasecmp(host, p, len - 1) != 0)
+ fail++;
+ xfree(p);
+
+ /* local user */
+ p = buffer_get_string(&b, NULL);
+
+ if (strcmp(pw->pw_name, p) != 0)
+ fail++;
+ xfree(p);
+
+ /* end of message */
+ if (buffer_len(&b) != 0)
+ fail++;
+
+ debug3("valid_request: fail %d", fail);
+
+ if (fail && key != NULL)
+ key_free(key);
+ else
+ *ret = key;
+
+ return (fail ? -1 : 0);
+}
+
+int
+main(int argc, char **argv)
+{
+ Buffer b;
+ Key *keys[2], *key;
+ struct passwd *pw;
+ int key_fd[2], i, found, version = 2, fd;
+ u_char *signature, *data;
+ char *host;
+ u_int slen, dlen;
+
+ key_fd[0] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY);
+ key_fd[1] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY);
+
+ seteuid(getuid());
+ setuid(getuid());
+
+#ifdef DEBUG_SSH_KEYSIGN
+ log_init("ssh-keysign", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0);
+#endif
+
+ if (key_fd[0] == -1 && key_fd[1] == -1)
+ fatal("could not open any host key");
+
+ if ((pw = getpwuid(getuid())) == NULL)
+ fatal("getpwuid failed");
+ pw = pwcopy(pw);
+
+ SSLeay_add_all_algorithms();
+
+ found = 0;
+ for (i = 0; i < 2; i++) {
+ keys[i] = NULL;
+ if (key_fd[i] == -1)
+ continue;
+ keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC,
+ NULL, NULL);
+ close(key_fd[i]);
+ if (keys[i] != NULL)
+ found = 1;
+ }
+ if (!found)
+ fatal("no hostkey found");
+
+ buffer_init(&b);
+ if (msg_recv(STDIN_FILENO, &b) < 0)
+ fatal("msg_recv failed");
+ if (buffer_get_char(&b) != version)
+ fatal("bad version");
+ fd = buffer_get_int(&b);
+ if ((fd == STDIN_FILENO) || (fd == STDOUT_FILENO))
+ fatal("bad fd");
+ if ((host = get_local_name(fd)) == NULL)
+ fatal("cannot get sockname for fd");
+
+ data = buffer_get_string(&b, &dlen);
+ if (valid_request(pw, host, &key, data, dlen) < 0)
+ fatal("not a valid request");
+ xfree(data);
+ xfree(host);
+
+ found = 0;
+ for (i = 0; i < 2; i++) {
+ if (keys[i] != NULL &&
+ key_equal(key, keys[i])) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ fatal("no matching hostkey found");
+
+ if (key_sign(keys[i], &signature, &slen, data, dlen) != 0)
+ fatal("key_sign failed");
+
+ /* send reply */
+ buffer_clear(&b);
+ buffer_put_string(&b, signature, slen);
+ msg_send(STDOUT_FILENO, version, &b);
+
+ return (0);
+}
diff --git a/crypto/openssh/ssh-keysign/Makefile b/crypto/openssh/ssh-keysign/Makefile
new file mode 100644
index 0000000..1a13d9e
--- /dev/null
+++ b/crypto/openssh/ssh-keysign/Makefile
@@ -0,0 +1,18 @@
+# $OpenBSD: Makefile,v 1.3 2002/05/31 10:30:33 markus Exp $
+
+.PATH: ${.CURDIR}/..
+
+PROG= ssh-keysign
+BINOWN= root
+
+BINMODE?=4555
+
+BINDIR= /usr/libexec
+MAN= ssh-keysign.8
+
+SRCS= ssh-keysign.c
+
+.include <bsd.prog.mk>
+
+LDADD+= -lcrypto -lz
+DPADD+= ${LIBCRYPTO} ${LIBZ}
diff --git a/crypto/openssh/ssh-rsa.c b/crypto/openssh/ssh-rsa.c
index 8e79d4e..3e66294 100644
--- a/crypto/openssh/ssh-rsa.c
+++ b/crypto/openssh/ssh-rsa.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: ssh-rsa.c,v 1.16 2002/02/24 19:14:59 markus Exp $");
+RCSID("$OpenBSD: ssh-rsa.c,v 1.20 2002/06/10 16:53:06 stevesk Exp $");
#include <openssl/evp.h>
#include <openssl/err.h>
@@ -35,6 +35,7 @@ RCSID("$OpenBSD: ssh-rsa.c,v 1.16 2002/02/24 19:14:59 markus Exp $");
#include "key.h"
#include "ssh-rsa.h"
#include "compat.h"
+#include "ssh.h"
/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
int
@@ -54,10 +55,6 @@ ssh_rsa_sign(
error("ssh_rsa_sign: no RSA key");
return -1;
}
- if (datafellows & SSH_BUG_SIGBLOB) {
- error("ssh_rsa_sign: SSH_BUG_SIGBLOB not supported");
- return -1;
- }
nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid);
@@ -118,20 +115,16 @@ ssh_rsa_verify(
EVP_MD_CTX md;
char *ktype;
u_char digest[EVP_MAX_MD_SIZE], *sigblob;
- u_int len, dlen;
+ u_int len, dlen, modlen;
int rlen, ret, nid;
if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) {
error("ssh_rsa_verify: no RSA key");
return -1;
}
- if (datafellows & SSH_BUG_SIGBLOB) {
- error("ssh_rsa_verify: SSH_BUG_SIGBLOB not supported");
- return -1;
- }
- if (BN_num_bits(key->rsa->n) < 768) {
- error("ssh_rsa_verify: n too small: %d bits",
- BN_num_bits(key->rsa->n));
+ if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
+ error("ssh_rsa_verify: RSA modulus too small: %d < minimum %d bits",
+ BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
return -1;
}
buffer_init(&b);
@@ -152,6 +145,21 @@ ssh_rsa_verify(
xfree(sigblob);
return -1;
}
+ /* RSA_verify expects a signature of RSA_size */
+ modlen = RSA_size(key->rsa);
+ if (len > modlen) {
+ error("ssh_rsa_verify: len %d > modlen %d", len, modlen);
+ xfree(sigblob);
+ return -1;
+ } else if (len < modlen) {
+ int diff = modlen - len;
+ debug("ssh_rsa_verify: add padding: modlen %d > len %d",
+ modlen, len);
+ sigblob = xrealloc(sigblob, modlen);
+ memmove(sigblob + diff, sigblob, len);
+ memset(sigblob, 0, diff);
+ len = modlen;
+ }
nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid);
diff --git a/crypto/openssh/ssh.1 b/crypto/openssh/ssh.1
index 43b75dc..8ada41f 100644
--- a/crypto/openssh/ssh.1
+++ b/crypto/openssh/ssh.1
@@ -34,7 +34,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: ssh.1,v 1.148 2002/02/18 17:55:20 markus Exp $
+.\" $OpenBSD: ssh.1,v 1.158 2002/06/20 19:56:07 stevesk Exp $
.Dd September 25, 1999
.Dt SSH 1
.Os
@@ -297,6 +297,12 @@ Background ssh at logout when waiting for forwarded connection / X11 sessions
to terminate
.It Cm ~?
Display a list of escape characters
+.It Cm ~C
+Open command line (only useful for adding port forwardings using the
+.Fl L
+and
+.Fl R
+options)
.It Cm ~R
Request rekeying of the connection (only useful for SSH protocol version 2
and if the peer supports it)
@@ -378,7 +384,7 @@ this mechanism is to prevent man-in-the-middle attacks which could
otherwise be used to circumvent the encryption.
The
.Cm StrictHostKeyChecking
-option (see below) can be used to prevent logins to machines whose
+option can be used to prevent logins to machines whose
host key is not known or has changed.
.Pp
The options are as follows:
@@ -562,13 +568,13 @@ and the
.Dq level
can be controlled by the
.Cm CompressionLevel
-option (see below).
+option.
Compression is desirable on modem lines and other
slow connections, but will only slow down things on fast networks.
The default value can be set on a host-by-host basis in the
configuration files; see the
.Cm Compression
-option below.
+option.
.It Fl F Ar configfile
Specifies an alternative per-user configuration file.
If a configuration file is given on the command line,
@@ -643,580 +649,10 @@ to use IPv6 addresses only.
.El
.Sh CONFIGURATION FILES
.Nm
-obtains configuration data from the following sources in
-the following order:
-command line options, user's configuration file
-.Pq Pa $HOME/.ssh/config ,
-and system-wide configuration file
-.Pq Pa /etc/ssh/ssh_config .
-For each parameter, the first obtained value
-will be used.
-The configuration files contain sections bracketed by
-.Dq Host
-specifications, and that section is only applied for hosts that
-match one of the patterns given in the specification.
-The matched host name is the one given on the command line.
-.Pp
-Since the first obtained value for each parameter is used, more
-host-specific declarations should be given near the beginning of the
-file, and general defaults at the end.
-.Pp
-The configuration file has the following format:
-.Pp
-Empty lines and lines starting with
-.Ql #
-are comments.
-.Pp
-Otherwise a line is of the format
-.Dq keyword arguments .
-Configuration options may be separated by whitespace or
-optional whitespace and exactly one
-.Ql = ;
-the latter format is useful to avoid the need to quote whitespace
-when specifying configuration options using the
-.Nm ssh ,
-.Nm scp
-and
-.Nm sftp
-.Fl o
-option.
-.Pp
-The possible
-keywords and their meanings are as follows (note that
-keywords are case-insensitive and arguments are case-sensitive):
-.Bl -tag -width Ds
-.It Cm Host
-Restricts the following declarations (up to the next
-.Cm Host
-keyword) to be only for those hosts that match one of the patterns
-given after the keyword.
-.Ql \&*
-and
-.Ql ?
-can be used as wildcards in the
-patterns.
-A single
-.Ql \&*
-as a pattern can be used to provide global
-defaults for all hosts.
-The host is the
-.Ar hostname
-argument given on the command line (i.e., the name is not converted to
-a canonicalized host name before matching).
-.It Cm AFSTokenPassing
-Specifies whether to pass AFS tokens to remote host.
-The argument to this keyword must be
-.Dq yes
-or
-.Dq no .
-This option applies to protocol version 1 only.
-.It Cm BatchMode
-If set to
-.Dq yes ,
-passphrase/password querying will be disabled.
-This option is useful in scripts and other batch jobs where no user
-is present to supply the password.
-The argument must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq no .
-.It Cm BindAddress
-Specify the interface to transmit from on machines with multiple
-interfaces or aliased addresses.
-Note that this option does not work if
-.Cm UsePrivilegedPort
-is set to
-.Dq yes .
-.It Cm CheckHostIP
-If this flag is set to
-.Dq yes ,
-ssh will additionally check the host IP address in the
-.Pa known_hosts
-file.
-This allows ssh to detect if a host key changed due to DNS spoofing.
-If the option is set to
-.Dq no ,
-the check will not be executed.
-The default is
-.Dq yes .
-.It Cm Cipher
-Specifies the cipher to use for encrypting the session
-in protocol version 1.
-Currently,
-.Dq blowfish ,
-.Dq 3des ,
-and
-.Dq des
-are supported.
-.Ar des
-is only supported in the
-.Nm
-client for interoperability with legacy protocol 1 implementations
-that do not support the
-.Ar 3des
-cipher. Its use is strongly discouraged due to cryptographic
-weaknesses.
-The default is
-.Dq 3des .
-.It Cm Ciphers
-Specifies the ciphers allowed for protocol version 2
-in order of preference.
-Multiple ciphers must be comma-separated.
-The default is
-.Pp
-.Bd -literal
- ``aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,
- aes192-cbc,aes256-cbc''
-.Ed
-.It Cm ClearAllForwardings
-Specifies that all local, remote and dynamic port forwardings
-specified in the configuration files or on the command line be
-cleared. This option is primarily useful when used from the
-.Nm
-command line to clear port forwardings set in
-configuration files, and is automatically set by
-.Xr scp 1
-and
-.Xr sftp 1 .
-The argument must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq no .
-.It Cm Compression
-Specifies whether to use compression.
-The argument must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq no .
-.It Cm CompressionLevel
-Specifies the compression level to use if compression is enabled.
-The argument must be an integer from 1 (fast) to 9 (slow, best).
-The default level is 6, which is good for most applications.
-The meaning of the values is the same as in
-.Xr gzip 1 .
-Note that this option applies to protocol version 1 only.
-.It Cm ConnectionAttempts
-Specifies the number of tries (one per second) to make before falling
-back to rsh or exiting.
-The argument must be an integer.
-This may be useful in scripts if the connection sometimes fails.
-The default is 1.
-.It Cm DynamicForward
-Specifies that a TCP/IP port on the local machine be forwarded
-over the secure channel, and the application
-protocol is then used to determine where to connect to from the
-remote machine. The argument must be a port number.
-Currently the SOCKS4 protocol is supported, and
-.Nm
-will act as a SOCKS4 server.
-Multiple forwardings may be specified, and
-additional forwardings can be given on the command line. Only
-the superuser can forward privileged ports.
-.It Cm EscapeChar
-Sets the escape character (default:
-.Ql ~ ) .
-The escape character can also
-be set on the command line.
-The argument should be a single character,
-.Ql ^
-followed by a letter, or
-.Dq none
-to disable the escape
-character entirely (making the connection transparent for binary
-data).
-.It Cm FallBackToRsh
-Specifies that if connecting via
-.Nm
-fails due to a connection refused error (there is no
-.Xr sshd 8
-listening on the remote host),
-.Xr rsh 1
-should automatically be used instead (after a suitable warning about
-the session being unencrypted).
-The argument must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq no .
-.It Cm ForwardAgent
-Specifies whether the connection to the authentication agent (if any)
-will be forwarded to the remote machine.
-The argument must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq no .
-.It Cm ForwardX11
-Specifies whether X11 connections will be automatically redirected
-over the secure channel and
-.Ev DISPLAY
-set.
-The argument must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq no .
-.It Cm GatewayPorts
-Specifies whether remote hosts are allowed to connect to local
-forwarded ports.
-By default,
-.Nm
-binds local port forwardings to the loopback addresss. This
-prevents other remote hosts from connecting to forwarded ports.
-.Cm GatewayPorts
-can be used to specify that
-.Nm
-should bind local port forwardings to the wildcard address,
-thus allowing remote hosts to connect to forwarded ports.
-The argument must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq no .
-.It Cm GlobalKnownHostsFile
-Specifies a file to use for the global
-host key database instead of
-.Pa /etc/ssh/ssh_known_hosts .
-.It Cm HostbasedAuthentication
-Specifies whether to try rhosts based authentication with public key
-authentication.
-The argument must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq no .
-This option applies to protocol version 2 only and
-is similar to
-.Cm RhostsRSAAuthentication .
-.It Cm HostKeyAlgorithms
-Specifies the protocol version 2 host key algorithms
-that the client wants to use in order of preference.
-The default for this option is:
-.Dq ssh-rsa,ssh-dss .
-.It Cm HostKeyAlias
-Specifies an alias that should be used instead of the
-real host name when looking up or saving the host key
-in the host key database files.
-This option is useful for tunneling ssh connections
-or for multiple servers running on a single host.
-.It Cm HostName
-Specifies the real host name to log into.
-This can be used to specify nicknames or abbreviations for hosts.
-Default is the name given on the command line.
-Numeric IP addresses are also permitted (both on the command line and in
-.Cm HostName
-specifications).
-.It Cm IdentityFile
-Specifies a file from which the user's RSA or DSA authentication identity
-is read. The default is
-.Pa $HOME/.ssh/identity
-for protocol version 1, and
-.Pa $HOME/.ssh/id_rsa
-and
-.Pa $HOME/.ssh/id_dsa
-for protocol version 2.
-Additionally, any identities represented by the authentication agent
-will be used for authentication.
-The file name may use the tilde
-syntax to refer to a user's home directory.
-It is possible to have
-multiple identity files specified in configuration files; all these
-identities will be tried in sequence.
-.It Cm KeepAlive
-Specifies whether the system should send TCP keepalive messages to the
-other side.
-If they are sent, death of the connection or crash of one
-of the machines will be properly noticed.
-However, this means that
-connections will die if the route is down temporarily, and some people
-find it annoying.
-.Pp
-The default is
-.Dq yes
-(to send keepalives), and the client will notice
-if the network goes down or the remote host dies.
-This is important in scripts, and many users want it too.
-.Pp
-To disable keepalives, the value should be set to
-.Dq no .
-.It Cm KerberosAuthentication
-Specifies whether Kerberos authentication will be used.
-The argument to this keyword must be
-.Dq yes
-or
-.Dq no .
-.It Cm KerberosTgtPassing
-Specifies whether a Kerberos TGT will be forwarded to the server.
-This will only work if the Kerberos server is actually an AFS kaserver.
-The argument to this keyword must be
-.Dq yes
-or
-.Dq no .
-.It Cm LocalForward
-Specifies that a TCP/IP port on the local machine be forwarded over
-the secure channel to the specified host and port from the remote machine.
-The first argument must be a port number, and the second must be
-.Ar host:port .
-IPv6 addresses can be specified with an alternative syntax:
-.Ar host/port .
-Multiple forwardings may be specified, and additional
-forwardings can be given on the command line.
-Only the superuser can forward privileged ports.
-.It Cm LogLevel
-Gives the verbosity level that is used when logging messages from
-.Nm ssh .
-The possible values are:
-QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2 and DEBUG3.
-The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2
-and DEBUG3 each specify higher levels of verbose output.
-.It Cm MACs
-Specifies the MAC (message authentication code) algorithms
-in order of preference.
-The MAC algorithm is used in protocol version 2
-for data integrity protection.
-Multiple algorithms must be comma-separated.
-The default is
-.Dq hmac-md5,hmac-sha1,hmac-ripemd160,hmac-sha1-96,hmac-md5-96 .
-.It Cm NoHostAuthenticationForLocalhost
-This option can be used if the home directory is shared across machines.
-In this case localhost will refer to a different machine on each of
-the machines and the user will get many warnings about changed host keys.
-However, this option disables host authentication for localhost.
-The argument to this keyword must be
-.Dq yes
-or
-.Dq no .
-The default is to check the host key for localhost.
-.It Cm NumberOfPasswordPrompts
-Specifies the number of password prompts before giving up.
-The argument to this keyword must be an integer.
-Default is 3.
-.It Cm PasswordAuthentication
-Specifies whether to use password authentication.
-The argument to this keyword must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq yes .
-.It Cm Port
-Specifies the port number to connect on the remote host.
-Default is 22.
-.It Cm PreferredAuthentications
-Specifies the order in which the client should try protocol 2
-authentication methods. This allows a client to prefer one method (e.g.
-.Cm keyboard-interactive )
-over another method (e.g.
-.Cm password )
-The default for this option is:
-.Dq hostbased,publickey,keyboard-interactive,password .
-.It Cm Protocol
-Specifies the protocol versions
-.Nm
-should support in order of preference.
-The possible values are
-.Dq 1
-and
-.Dq 2 .
-Multiple versions must be comma-separated.
-The default is
-.Dq 2,1 .
-This means that
-.Nm
-tries version 2 and falls back to version 1
-if version 2 is not available.
-.It Cm ProxyCommand
-Specifies the command to use to connect to the server.
-The command
-string extends to the end of the line, and is executed with
-.Pa /bin/sh .
-In the command string,
-.Ql %h
-will be substituted by the host name to
-connect and
-.Ql %p
-by the port.
-The command can be basically anything,
-and should read from its standard input and write to its standard output.
-It should eventually connect an
-.Xr sshd 8
-server running on some machine, or execute
-.Ic sshd -i
-somewhere.
-Host key management will be done using the
-HostName of the host being connected (defaulting to the name typed by
-the user).
-Note that
-.Cm CheckHostIP
-is not available for connects with a proxy command.
-.Pp
-.It Cm PubkeyAuthentication
-Specifies whether to try public key authentication.
-The argument to this keyword must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq yes .
-This option applies to protocol version 2 only.
-.It Cm RemoteForward
-Specifies that a TCP/IP port on the remote machine be forwarded over
-the secure channel to the specified host and port from the local machine.
-The first argument must be a port number, and the second must be
-.Ar host:port .
-IPv6 addresses can be specified with an alternative syntax:
-.Ar host/port .
-Multiple forwardings may be specified, and additional
-forwardings can be given on the command line.
-Only the superuser can forward privileged ports.
-.It Cm RhostsAuthentication
-Specifies whether to try rhosts based authentication.
-Note that this
-declaration only affects the client side and has no effect whatsoever
-on security.
-Disabling rhosts authentication may reduce
-authentication time on slow connections when rhosts authentication is
-not used.
-Most servers do not permit RhostsAuthentication because it
-is not secure (see
-.Cm RhostsRSAAuthentication ) .
-The argument to this keyword must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq yes .
-This option applies to protocol version 1 only.
-.It Cm RhostsRSAAuthentication
-Specifies whether to try rhosts based authentication with RSA host
-authentication.
-The argument must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq yes .
-This option applies to protocol version 1 only.
-.It Cm RSAAuthentication
-Specifies whether to try RSA authentication.
-The argument to this keyword must be
-.Dq yes
-or
-.Dq no .
-RSA authentication will only be
-attempted if the identity file exists, or an authentication agent is
-running.
-The default is
-.Dq yes .
-Note that this option applies to protocol version 1 only.
-.It Cm ChallengeResponseAuthentication
-Specifies whether to use challenge response authentication.
-The argument to this keyword must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq yes .
-.It Cm SmartcardDevice
-Specifies which smartcard device to use. The argument to this keyword is
-the device
-.Nm
-should use to communicate with a smartcard used for storing the user's
-private RSA key. By default, no device is specified and smartcard support
-is not activated.
-.It Cm StrictHostKeyChecking
-If this flag is set to
-.Dq yes ,
-.Nm
-will never automatically add host keys to the
-.Pa $HOME/.ssh/known_hosts
-file, and refuses to connect to hosts whose host key has changed.
-This provides maximum protection against trojan horse attacks,
-however, can be annoying when the
-.Pa /etc/ssh/ssh_known_hosts
-file is poorly maintained, or connections to new hosts are
-frequently made.
-This option forces the user to manually
-add all new hosts.
-If this flag is set to
-.Dq no ,
-.Nm
-will automatically add new host keys to the
-user known hosts files.
-If this flag is set to
-.Dq ask ,
-new host keys
-will be added to the user known host files only after the user
-has confirmed that is what they really want to do, and
-.Nm
-will refuse to connect to hosts whose host key has changed.
-The host keys of
-known hosts will be verified automatically in all cases.
-The argument must be
-.Dq yes ,
-.Dq no
-or
-.Dq ask .
-The default is
-.Dq ask .
-.It Cm UsePrivilegedPort
-Specifies whether to use a privileged port for outgoing connections.
-The argument must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq no .
-Note that this option must be set to
-.Dq yes
-if
-.Cm RhostsAuthentication
-and
-.Cm RhostsRSAAuthentication
-authentications are needed with older servers.
-.It Cm User
-Specifies the user to log in as.
-This can be useful when a different user name is used on different machines.
-This saves the trouble of
-having to remember to give the user name on the command line.
-.It Cm UserKnownHostsFile
-Specifies a file to use for the user
-host key database instead of
-.Pa $HOME/.ssh/known_hosts .
-.It Cm UseRsh
-Specifies that rlogin/rsh should be used for this host.
-It is possible that the host does not at all support the
-.Nm
-protocol.
-This causes
-.Nm
-to immediately execute
-.Xr rsh 1 .
-All other options (except
-.Cm HostName )
-are ignored if this has been specified.
-The argument must be
-.Dq yes
-or
-.Dq no .
-.It Cm XAuthLocation
-Specifies the location of the
-.Xr xauth 1
-program.
-The default is
-.Pa /usr/X11R6/bin/xauth .
-.El
+may additionally obtain configuration data from
+a per-user configuration file and a system-wide configuration file.
+The file format and configuration options are described in
+.Xr ssh_config 5 .
.Sh ENVIRONMENT
.Nm
will normally set the following environment variables:
@@ -1351,13 +787,8 @@ never used automatically and are not necessary; they are only provided for
the convenience of the user.
.It Pa $HOME/.ssh/config
This is the per-user configuration file.
-The format of this file is described above.
-This file is used by the
-.Nm
-client.
-This file does not usually contain any sensitive information,
-but the recommended permissions are read/write for the user, and not
-accessible by others.
+The file format and configuration options are described in
+.Xr ssh_config 5 .
.It Pa $HOME/.ssh/authorized_keys
Lists the public keys (RSA/DSA) that can be used for logging in as this user.
The format of this file is described in the
@@ -1392,19 +823,31 @@ checking the key, because someone with access to the name servers
would then be able to fool host authentication.
.It Pa /etc/ssh/ssh_config
Systemwide configuration file.
-This file provides defaults for those
-values that are not specified in the user's configuration file, and
-for those users who do not have a configuration file.
-This file must be world-readable.
+The file format and configuration options are described in
+.Xr ssh_config 5 .
.It Pa /etc/ssh/ssh_host_key, /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_rsa_key
These three files contain the private parts of the host keys
and are used for
.Cm RhostsRSAAuthentication
and
.Cm HostbasedAuthentication .
-Since they are readable only by root
+If the protocol version 1
+.Cm RhostsRSAAuthentication
+method is used,
+.Nm
+must be setuid root, since the host key is readable only by root.
+For protocol version 2,
+.Nm
+uses
+.Xr ssh-keysign 8
+to access the host keys for
+.Cm HostbasedAuthentication .
+This eliminates the requirement that
+.Nm
+be setuid root when that authentication method is used.
+By default
.Nm
-must be setuid root if these authentication methods are desired.
+is not setuid root.
.It Pa $HOME/.rhosts
This file is used in
.Pa \&.rhosts
@@ -1445,7 +888,7 @@ The purpose for
having this file is to be able to use rhosts authentication with
.Nm
without permitting login with
-.Xr rlogin 1
+.Nm rlogin
or
.Xr rsh 1 .
.It Pa /etc/hosts.equiv
@@ -1502,7 +945,6 @@ created OpenSSH.
Markus Friedl contributed the support for SSH
protocol versions 1.5 and 2.0.
.Sh SEE ALSO
-.Xr rlogin 1 ,
.Xr rsh 1 ,
.Xr scp 1 ,
.Xr sftp 1 ,
@@ -1510,6 +952,8 @@ protocol versions 1.5 and 2.0.
.Xr ssh-agent 1 ,
.Xr ssh-keygen 1 ,
.Xr telnet 1 ,
+.Xr ssh_config 4 ,
+.Xr ssh-keysign 8,
.Xr sshd 8
.Rs
.%A T. Ylonen
@@ -1518,7 +962,7 @@ protocol versions 1.5 and 2.0.
.%A T. Rinne
.%A S. Lehtinen
.%T "SSH Protocol Architecture"
-.%N draft-ietf-secsh-architecture-09.txt
-.%D July 2001
+.%N draft-ietf-secsh-architecture-12.txt
+.%D January 2002
.%O work in progress material
.Re
diff --git a/crypto/openssh/ssh.c b/crypto/openssh/ssh.c
index 44af61f..f59dc44 100644
--- a/crypto/openssh/ssh.c
+++ b/crypto/openssh/ssh.c
@@ -13,6 +13,7 @@
* called by a name other than "ssh" or "Secure Shell".
*
* Copyright (c) 1999 Niels Provos. All rights reserved.
+ * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
* Modified to work with SSL by Niels Provos <provos@citi.umich.edu>
* in Canada (German citizen).
@@ -39,7 +40,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: ssh.c,v 1.164 2002/02/14 23:28:00 markus Exp $");
+RCSID("$OpenBSD: ssh.c,v 1.179 2002/06/12 01:09:52 markus Exp $");
#include <openssl/evp.h>
#include <openssl/err.h>
@@ -52,7 +53,6 @@ RCSID("$OpenBSD: ssh.c,v 1.164 2002/02/14 23:28:00 markus Exp $");
#include "xmalloc.h"
#include "packet.h"
#include "buffer.h"
-#include "uidswap.h"
#include "channels.h"
#include "key.h"
#include "authfd.h"
@@ -70,7 +70,6 @@ RCSID("$OpenBSD: ssh.c,v 1.164 2002/02/14 23:28:00 markus Exp $");
#include "sshtty.h"
#ifdef SMARTCARD
-#include <openssl/engine.h>
#include "scard.h"
#endif
@@ -99,7 +98,7 @@ int stdin_null_flag = 0;
/*
* Flag indicating that ssh should fork after authentication. This is useful
- * so that the pasphrase can be entered manually, and then ssh goes to the
+ * so that the passphrase can be entered manually, and then ssh goes to the
* background.
*/
int fork_after_authentication_flag = 0;
@@ -124,13 +123,11 @@ char *host;
struct sockaddr_storage hostaddr;
/* Private host keys. */
-struct {
- Key **keys;
- int nkeys;
-} sensitive_data;
+Sensitive sensitive_data;
/* Original real UID. */
uid_t original_real_uid;
+uid_t original_effective_uid;
/* command to be executed */
Buffer command;
@@ -138,6 +135,9 @@ Buffer command;
/* Should we execute a command or invoke a subsystem? */
int subsystem_flag = 0;
+/* # of replies received for global requests */
+static int client_global_request_id = 0;
+
/* Prints a help message to the user. This function never returns. */
static void
@@ -192,44 +192,6 @@ usage(void)
exit(1);
}
-/*
- * Connects to the given host using rsh (or prints an error message and exits
- * if rsh is not available). This function never returns.
- */
-static void
-rsh_connect(char *host, char *user, Buffer * command)
-{
- char *args[10];
- int i;
-
- log("Using rsh. WARNING: Connection will not be encrypted.");
- /* Build argument list for rsh. */
- i = 0;
- args[i++] = _PATH_RSH;
- /* host may have to come after user on some systems */
- args[i++] = host;
- if (user) {
- args[i++] = "-l";
- args[i++] = user;
- }
- if (buffer_len(command) > 0) {
- buffer_append(command, "\0", 1);
- args[i++] = buffer_ptr(command);
- }
- args[i++] = NULL;
- if (debug_flag) {
- for (i = 0; args[i]; i++) {
- if (i != 0)
- fprintf(stderr, " ");
- fprintf(stderr, "%s", args[i]);
- }
- fprintf(stderr, "\n");
- }
- execv(_PATH_RSH, args);
- perror(_PATH_RSH);
- exit(1);
-}
-
static int ssh_session(void);
static int ssh_session2(void);
static void load_public_identity_files(void);
@@ -240,14 +202,13 @@ static void load_public_identity_files(void);
int
main(int ac, char **av)
{
- int i, opt, exit_status, cerr;
+ int i, opt, exit_status;
u_short fwd_port, fwd_host_port;
char sfwd_port[6], sfwd_host_port[6];
char *p, *cp, buf[256];
struct stat st;
struct passwd *pw;
int dummy;
- uid_t original_effective_uid;
extern int optind, optreset;
extern char *optarg;
@@ -281,7 +242,7 @@ main(int ac, char **av)
* them when the port has been created (actually, when the connection
* has been made, as we may need to create the port several times).
*/
- temporarily_use_uid(pw);
+ PRIV_END;
/*
* Set our umask to something reasonable, as some files are created
@@ -462,7 +423,7 @@ again:
/* NOTREACHED */
}
if ((fwd_port = a2port(sfwd_port)) == 0 ||
- (fwd_host_port = a2port(sfwd_host_port)) == 0) {
+ (fwd_host_port = a2port(sfwd_host_port)) == 0) {
fprintf(stderr,
"Bad forwarding port(s) '%s'\n", optarg);
exit(1);
@@ -630,52 +591,48 @@ again:
"originating port will not be trusted.");
options.rhosts_authentication = 0;
}
- /*
- * If using rsh has been selected, exec it now (without trying
- * anything else). Note that we must release privileges first.
- */
- if (options.use_rsh) {
- /*
- * Restore our superuser privileges. This must be done
- * before permanently setting the uid.
- */
- restore_uid();
-
- /* Switch to the original uid permanently. */
- permanently_set_uid(pw);
-
- /* Execute rsh. */
- rsh_connect(host, options.user, &command);
- fatal("rsh_connect returned");
- }
- /* Restore our superuser privileges. */
- restore_uid();
-
/* Open a connection to the remote host. */
- cerr = ssh_connect(host, &hostaddr, options.port, IPv4or6,
+ if (ssh_connect(host, &hostaddr, options.port, IPv4or6,
options.connection_attempts,
- original_effective_uid != 0 || !options.use_privileged_port,
- pw, options.proxy_command);
+ original_effective_uid == 0 && options.use_privileged_port,
+ options.proxy_command) != 0)
+ exit(1);
/*
* If we successfully made the connection, load the host private key
* in case we will need it later for combined rsa-rhosts
* authentication. This must be done before releasing extra
* privileges, because the file is only readable by root.
+ * If we cannot access the private keys, load the public keys
+ * instead and try to execute the ssh-keysign helper instead.
*/
sensitive_data.nkeys = 0;
sensitive_data.keys = NULL;
- if (!cerr && (options.rhosts_rsa_authentication ||
- options.hostbased_authentication)) {
+ sensitive_data.external_keysign = 0;
+ if (options.rhosts_rsa_authentication ||
+ options.hostbased_authentication) {
sensitive_data.nkeys = 3;
sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key));
+
+ PRIV_START;
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);
+ PRIV_END;
+
+ if (sensitive_data.keys[0] == NULL &&
+ sensitive_data.keys[1] == NULL &&
+ sensitive_data.keys[2] == NULL) {
+ sensitive_data.keys[1] = key_load_public(
+ _PATH_HOST_DSA_KEY_FILE, NULL);
+ sensitive_data.keys[2] = key_load_public(
+ _PATH_HOST_RSA_KEY_FILE, NULL);
+ sensitive_data.external_keysign = 1;
+ }
}
/*
* Get rid of any extra privileges that we may have. We will no
@@ -684,15 +641,8 @@ again:
* user's home directory if it happens to be on a NFS volume where
* root is mapped to nobody.
*/
-
- /*
- * Note that some legacy systems need to postpone the following call
- * to permanently_set_uid() until the private hostkey is destroyed
- * with RSA_free(). Otherwise the calling user could ptrace() the
- * process, read the private hostkey and impersonate the host.
- * OpenBSD does not allow ptracing of setuid processes.
- */
- permanently_set_uid(pw);
+ seteuid(original_real_uid);
+ setuid(original_real_uid);
/*
* Now that we are back to our own permissions, create ~/.ssh
@@ -703,21 +653,6 @@ again:
if (mkdir(buf, 0700) < 0)
error("Could not create directory '%.200s'.", buf);
- /* Check if the connection failed, and try "rsh" if appropriate. */
- if (cerr) {
- if (!options.fallback_to_rsh)
- exit(1);
- if (options.port != 0)
- log("Secure connection to %.100s on port %hu refused; "
- "reverting to insecure method",
- host, options.port);
- else
- log("Secure connection to %.100s refused; "
- "reverting to insecure method.", host);
-
- rsh_connect(host, options.user, &command);
- fatal("rsh_connect returned");
- }
/* load options.identity_files */
load_public_identity_files();
@@ -735,8 +670,7 @@ again:
signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
/* Log into the remote system. This never returns if the login fails. */
- ssh_login(sensitive_data.keys, sensitive_data.nkeys,
- host, (struct sockaddr *)&hostaddr, pw);
+ ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, pw);
/* We no longer need the private host keys. Clear them now. */
if (sensitive_data.nkeys != 0) {
@@ -788,10 +722,10 @@ x11_get_proto(char **_proto, char **_data)
* XXX: "localhost" match to determine FamilyLocal
* is not perfect.
*/
- snprintf(line, sizeof line, "%.100s list unix:%s 2>"
+ snprintf(line, sizeof line, "%s list unix:%s 2>"
_PATH_DEVNULL, options.xauth_location, display+10);
else
- snprintf(line, sizeof line, "%.100s list %.200s 2>"
+ snprintf(line, sizeof line, "%s list %.200s 2>"
_PATH_DEVNULL, options.xauth_location, display);
debug2("x11_get_proto %s", line);
f = popen(line, "r");
@@ -1021,6 +955,27 @@ client_subsystem_reply(int type, u_int32_t seq, void *ctxt)
len, (u_char *)buffer_ptr(&command), id);
}
+void
+client_global_request_reply(int type, u_int32_t seq, void *ctxt)
+{
+ int i;
+
+ i = client_global_request_id++;
+ if (i >= options.num_remote_forwards) {
+ debug("client_global_request_reply: too many replies %d > %d",
+ i, options.num_remote_forwards);
+ return;
+ }
+ debug("remote forward %s for: listen %d, connect %s:%d",
+ type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
+ options.remote_forwards[i].port,
+ options.remote_forwards[i].host,
+ options.remote_forwards[i].host_port);
+ if (type == SSH2_MSG_REQUEST_FAILURE)
+ log("Warning: remote port forwarding failed for listen port %d",
+ options.remote_forwards[i].port);
+}
+
/* request pty/x11/agent/tcpfwd/shell for channel */
static void
ssh_session2_setup(int id, void *arg)
@@ -1080,7 +1035,7 @@ ssh_session2_setup(int id, void *arg)
debug("Sending subsystem: %.*s", len, (u_char *)buffer_ptr(&command));
channel_request_start(id, "subsystem", /*want reply*/ 1);
/* register callback for reply */
- /* XXX we asume that client_loop has already been called */
+ /* XXX we assume that client_loop has already been called */
dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &client_subsystem_reply);
dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &client_subsystem_reply);
} else {
@@ -1167,40 +1122,29 @@ static void
load_public_identity_files(void)
{
char *filename;
- Key *public;
int i = 0;
-
+ Key *public;
#ifdef SMARTCARD
+ Key **keys;
+
if (options.smartcard_device != NULL &&
- options.num_identity_files + 1 < SSH_MAX_IDENTITY_FILES &&
- (public = sc_get_key(options.smartcard_device)) != NULL ) {
- Key *new;
-
- if (options.num_identity_files + 2 > SSH_MAX_IDENTITY_FILES)
- options.num_identity_files = SSH_MAX_IDENTITY_FILES - 2;
- memmove(&options.identity_files[2], &options.identity_files[0],
- sizeof(char *) * options.num_identity_files);
- options.num_identity_files += 2;
- i = 2;
-
- /* XXX ssh1 vs ssh2 */
- new = key_new(KEY_RSA);
- new->flags = KEY_FLAG_EXT;
- BN_copy(new->rsa->n, public->rsa->n);
- BN_copy(new->rsa->e, public->rsa->e);
- RSA_set_method(new->rsa, sc_get_engine());
- options.identity_keys[0] = new;
- options.identity_files[0] = xstrdup("smartcard rsa key");;
-
- new = key_new(KEY_RSA1);
- new->flags = KEY_FLAG_EXT;
- BN_copy(new->rsa->n, public->rsa->n);
- BN_copy(new->rsa->e, public->rsa->e);
- RSA_set_method(new->rsa, sc_get_engine());
- options.identity_keys[1] = new;
- options.identity_files[1] = xstrdup("smartcard rsa1 key");
-
- key_free(public);
+ options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
+ (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL ) {
+ int count = 0;
+ for (i = 0; keys[i] != NULL; i++) {
+ count++;
+ memmove(&options.identity_files[1], &options.identity_files[0],
+ sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1));
+ memmove(&options.identity_keys[1], &options.identity_keys[0],
+ sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1));
+ options.num_identity_files++;
+ options.identity_keys[0] = keys[i];
+ options.identity_files[0] = xstrdup("smartcard key");;
+ }
+ if (options.num_identity_files > SSH_MAX_IDENTITY_FILES)
+ options.num_identity_files = SSH_MAX_IDENTITY_FILES;
+ i = count;
+ xfree(keys);
}
#endif /* SMARTCARD */
for (; i < options.num_identity_files; i++) {
diff --git a/crypto/openssh/ssh.h b/crypto/openssh/ssh.h
index 7b0ccf3..54c2988 100644
--- a/crypto/openssh/ssh.h
+++ b/crypto/openssh/ssh.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.h,v 1.64 2002/03/04 17:27:39 stevesk Exp $ */
+/* $OpenBSD: ssh.h,v 1.70 2002/06/03 12:04:07 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -31,7 +31,7 @@
#define SSH_MAX_IDENTITY_FILES 100
/*
- * Major protocol version. Different version indicates major incompatiblity
+ * Major protocol version. Different version indicates major incompatibility
* that prevents communication.
*
* Minor protocol version. Different version indicates minor incompatibility
@@ -85,4 +85,14 @@
/* Used to identify ``EscapeChar none'' */
#define SSH_ESCAPECHAR_NONE -2
+/*
+ * unprivileged user when UsePrivilegeSeparation=yes;
+ * sshd will change its privileges to this user and its
+ * primary group.
+ */
+#define SSH_PRIVSEP_USER "sshd"
+
+/* Minimum modulus size (n) for RSA keys. */
+#define SSH_RSA_MINIMUM_MODULUS_SIZE 768
+
#endif /* SSH_H */
diff --git a/crypto/openssh/ssh/Makefile b/crypto/openssh/ssh/Makefile
index f493e1f..80511de 100644
--- a/crypto/openssh/ssh/Makefile
+++ b/crypto/openssh/ssh/Makefile
@@ -1,14 +1,14 @@
-# $OpenBSD: Makefile,v 1.37 2002/03/05 00:49:51 deraadt Exp $
+# $OpenBSD: Makefile,v 1.42 2002/06/20 19:56:07 stevesk Exp $
.PATH: ${.CURDIR}/..
PROG= ssh
BINOWN= root
-BINMODE?=4555
+#BINMODE?=4555
BINDIR= /usr/bin
-MAN= ssh.1
+MAN= ssh.1 ssh_config.5
LINKS= ${BINDIR}/ssh ${BINDIR}/slogin
MLINKS= ssh.1 slogin.1
@@ -20,7 +20,7 @@ SRCS= ssh.c readconf.c clientloop.c sshtty.c \
.if (${KERBEROS5:L} == "yes")
CFLAGS+= -DKRB5 -I${DESTDIR}/usr/include/kerberosV
LDADD+= -lkrb5 -lasn1 -lcom_err
-DPADD+= ${LIBKRB5} ${LIBASN1}
+DPADD+= ${LIBKRB5} ${LIBASN1} ${LIBCOM_ERR}
.endif # KERBEROS5
.if (${KERBEROS:L} == "yes")
@@ -30,11 +30,11 @@ DPADD+= ${LIBKRB}
.if (${AFS:L} == "yes")
CFLAGS+= -DAFS
LDADD+= -lkafs
-DPADD+= ${LIBKRBAFS}
+DPADD+= ${LIBKAFS}
.endif # AFS
.endif # KERBEROS
.include <bsd.prog.mk>
LDADD+= -lcrypto -lz -ldes
-DPADD+= ${LIBCRYPTO} ${LIBZ}
+DPADD+= ${LIBCRYPTO} ${LIBZ} ${LIBDES}
diff --git a/crypto/openssh/ssh_config b/crypto/openssh/ssh_config
index a8a8d72..ef31d43 100644
--- a/crypto/openssh/ssh_config
+++ b/crypto/openssh/ssh_config
@@ -1,9 +1,9 @@
-# $OpenBSD: ssh_config,v 1.12 2002/01/16 17:55:33 stevesk Exp $
+# $OpenBSD: ssh_config,v 1.15 2002/06/20 20:03:34 stevesk Exp $
-# This is the ssh client system-wide configuration file. See ssh(1)
-# for more information. This file provides defaults for users, and
-# the values can be changed in per-user configuration files or on the
-# command line.
+# This is the ssh client system-wide configuration file. See
+# ssh_config(5) for more information. This file provides defaults for
+# users, and the values can be changed in per-user configuration files
+# or on the command line.
# Configuration data is parsed as follows:
# 1. command line options
@@ -18,12 +18,10 @@
# Host *
# ForwardAgent no
# ForwardX11 no
-# RhostsAuthentication yes
-# RhostsRSAAuthentication yes
+# RhostsAuthentication no
+# RhostsRSAAuthentication no
# RSAAuthentication yes
# PasswordAuthentication yes
-# FallBackToRsh no
-# UseRsh no
# BatchMode no
# CheckHostIP yes
# StrictHostKeyChecking ask
diff --git a/crypto/openssh/ssh_config.5 b/crypto/openssh/ssh_config.5
new file mode 100644
index 0000000..53cb0fe
--- /dev/null
+++ b/crypto/openssh/ssh_config.5
@@ -0,0 +1,621 @@
+.\" -*- nroff -*-
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\" All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose. Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: ssh_config.5,v 1.1 2002/06/20 19:56:07 stevesk Exp $
+.Dd September 25, 1999
+.Dt SSH_CONFIG 5
+.Os
+.Sh NAME
+.Nm ssh_config
+.Nd OpenSSH SSH client configuration files
+.Sh SYNOPSIS
+.Bl -tag -width Ds -compact
+.It Pa $HOME/.ssh/config
+.It Pa /etc/ssh/ssh_config
+.El
+.Sh DESCRIPTION
+.Nm ssh
+obtains configuration data from the following sources in
+the following order:
+command line options, user's configuration file
+.Pq Pa $HOME/.ssh/config ,
+and system-wide configuration file
+.Pq Pa /etc/ssh/ssh_config .
+.Pp
+For each parameter, the first obtained value
+will be used.
+The configuration files contain sections bracketed by
+.Dq Host
+specifications, and that section is only applied for hosts that
+match one of the patterns given in the specification.
+The matched host name is the one given on the command line.
+.Pp
+Since the first obtained value for each parameter is used, more
+host-specific declarations should be given near the beginning of the
+file, and general defaults at the end.
+.Pp
+The configuration file has the following format:
+.Pp
+Empty lines and lines starting with
+.Ql #
+are comments.
+.Pp
+Otherwise a line is of the format
+.Dq keyword arguments .
+Configuration options may be separated by whitespace or
+optional whitespace and exactly one
+.Ql = ;
+the latter format is useful to avoid the need to quote whitespace
+when specifying configuration options using the
+.Nm ssh ,
+.Nm scp
+and
+.Nm sftp
+.Fl o
+option.
+.Pp
+The possible
+keywords and their meanings are as follows (note that
+keywords are case-insensitive and arguments are case-sensitive):
+.Bl -tag -width Ds
+.It Cm Host
+Restricts the following declarations (up to the next
+.Cm Host
+keyword) to be only for those hosts that match one of the patterns
+given after the keyword.
+.Ql \&*
+and
+.Ql ?
+can be used as wildcards in the
+patterns.
+A single
+.Ql \&*
+as a pattern can be used to provide global
+defaults for all hosts.
+The host is the
+.Ar hostname
+argument given on the command line (i.e., the name is not converted to
+a canonicalized host name before matching).
+.It Cm AFSTokenPassing
+Specifies whether to pass AFS tokens to remote host.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+This option applies to protocol version 1 only.
+.It Cm BatchMode
+If set to
+.Dq yes ,
+passphrase/password querying will be disabled.
+This option is useful in scripts and other batch jobs where no user
+is present to supply the password.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm BindAddress
+Specify the interface to transmit from on machines with multiple
+interfaces or aliased addresses.
+Note that this option does not work if
+.Cm UsePrivilegedPort
+is set to
+.Dq yes .
+.It Cm ChallengeResponseAuthentication
+Specifies whether to use challenge response authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm CheckHostIP
+If this flag is set to
+.Dq yes ,
+ssh will additionally check the host IP address in the
+.Pa known_hosts
+file.
+This allows ssh to detect if a host key changed due to DNS spoofing.
+If the option is set to
+.Dq no ,
+the check will not be executed.
+The default is
+.Dq yes .
+.It Cm Cipher
+Specifies the cipher to use for encrypting the session
+in protocol version 1.
+Currently,
+.Dq blowfish ,
+.Dq 3des ,
+and
+.Dq des
+are supported.
+.Ar des
+is only supported in the
+.Nm ssh
+client for interoperability with legacy protocol 1 implementations
+that do not support the
+.Ar 3des
+cipher. Its use is strongly discouraged due to cryptographic
+weaknesses.
+The default is
+.Dq 3des .
+.It Cm Ciphers
+Specifies the ciphers allowed for protocol version 2
+in order of preference.
+Multiple ciphers must be comma-separated.
+The default is
+.Pp
+.Bd -literal
+ ``aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,
+ aes192-cbc,aes256-cbc''
+.Ed
+.It Cm ClearAllForwardings
+Specifies that all local, remote and dynamic port forwardings
+specified in the configuration files or on the command line be
+cleared. This option is primarily useful when used from the
+.Nm ssh
+command line to clear port forwardings set in
+configuration files, and is automatically set by
+.Xr scp 1
+and
+.Xr sftp 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm Compression
+Specifies whether to use compression.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm CompressionLevel
+Specifies the compression level to use if compression is enabled.
+The argument must be an integer from 1 (fast) to 9 (slow, best).
+The default level is 6, which is good for most applications.
+The meaning of the values is the same as in
+.Xr gzip 1 .
+Note that this option applies to protocol version 1 only.
+.It Cm ConnectionAttempts
+Specifies the number of tries (one per second) to make before exiting.
+The argument must be an integer.
+This may be useful in scripts if the connection sometimes fails.
+The default is 1.
+.It Cm DynamicForward
+Specifies that a TCP/IP port on the local machine be forwarded
+over the secure channel, and the application
+protocol is then used to determine where to connect to from the
+remote machine. The argument must be a port number.
+Currently the SOCKS4 protocol is supported, and
+.Nm ssh
+will act as a SOCKS4 server.
+Multiple forwardings may be specified, and
+additional forwardings can be given on the command line. Only
+the superuser can forward privileged ports.
+.It Cm EscapeChar
+Sets the escape character (default:
+.Ql ~ ) .
+The escape character can also
+be set on the command line.
+The argument should be a single character,
+.Ql ^
+followed by a letter, or
+.Dq none
+to disable the escape
+character entirely (making the connection transparent for binary
+data).
+.It Cm ForwardAgent
+Specifies whether the connection to the authentication agent (if any)
+will be forwarded to the remote machine.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm ForwardX11
+Specifies whether X11 connections will be automatically redirected
+over the secure channel and
+.Ev DISPLAY
+set.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm GatewayPorts
+Specifies whether remote hosts are allowed to connect to local
+forwarded ports.
+By default,
+.Nm ssh
+binds local port forwardings to the loopback address. This
+prevents other remote hosts from connecting to forwarded ports.
+.Cm GatewayPorts
+can be used to specify that
+.Nm ssh
+should bind local port forwardings to the wildcard address,
+thus allowing remote hosts to connect to forwarded ports.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm GlobalKnownHostsFile
+Specifies a file to use for the global
+host key database instead of
+.Pa /etc/ssh/ssh_known_hosts .
+.It Cm HostbasedAuthentication
+Specifies whether to try rhosts based authentication with public key
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 2 only and
+is similar to
+.Cm RhostsRSAAuthentication .
+.It Cm HostKeyAlgorithms
+Specifies the protocol version 2 host key algorithms
+that the client wants to use in order of preference.
+The default for this option is:
+.Dq ssh-rsa,ssh-dss .
+.It Cm HostKeyAlias
+Specifies an alias that should be used instead of the
+real host name when looking up or saving the host key
+in the host key database files.
+This option is useful for tunneling ssh connections
+or for multiple servers running on a single host.
+.It Cm HostName
+Specifies the real host name to log into.
+This can be used to specify nicknames or abbreviations for hosts.
+Default is the name given on the command line.
+Numeric IP addresses are also permitted (both on the command line and in
+.Cm HostName
+specifications).
+.It Cm IdentityFile
+Specifies a file from which the user's RSA or DSA authentication identity
+is read. The default is
+.Pa $HOME/.ssh/identity
+for protocol version 1, and
+.Pa $HOME/.ssh/id_rsa
+and
+.Pa $HOME/.ssh/id_dsa
+for protocol version 2.
+Additionally, any identities represented by the authentication agent
+will be used for authentication.
+The file name may use the tilde
+syntax to refer to a user's home directory.
+It is possible to have
+multiple identity files specified in configuration files; all these
+identities will be tried in sequence.
+.It Cm KeepAlive
+Specifies whether the system should send TCP keepalive messages to the
+other side.
+If they are sent, death of the connection or crash of one
+of the machines will be properly noticed.
+However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+.Pp
+The default is
+.Dq yes
+(to send keepalives), and the client will notice
+if the network goes down or the remote host dies.
+This is important in scripts, and many users want it too.
+.Pp
+To disable keepalives, the value should be set to
+.Dq no .
+.It Cm KerberosAuthentication
+Specifies whether Kerberos authentication will be used.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+.It Cm KerberosTgtPassing
+Specifies whether a Kerberos TGT will be forwarded to the server.
+This will only work if the Kerberos server is actually an AFS kaserver.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+.It Cm LocalForward
+Specifies that a TCP/IP port on the local machine be forwarded over
+the secure channel to the specified host and port from the remote machine.
+The first argument must be a port number, and the second must be
+.Ar host:port .
+IPv6 addresses can be specified with an alternative syntax:
+.Ar host/port .
+Multiple forwardings may be specified, and additional
+forwardings can be given on the command line.
+Only the superuser can forward privileged ports.
+.It Cm LogLevel
+Gives the verbosity level that is used when logging messages from
+.Nm ssh .
+The possible values are:
+QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2 and DEBUG3.
+The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2
+and DEBUG3 each specify higher levels of verbose output.
+.It Cm MACs
+Specifies the MAC (message authentication code) algorithms
+in order of preference.
+The MAC algorithm is used in protocol version 2
+for data integrity protection.
+Multiple algorithms must be comma-separated.
+The default is
+.Dq hmac-md5,hmac-sha1,hmac-ripemd160,hmac-sha1-96,hmac-md5-96 .
+.It Cm NoHostAuthenticationForLocalhost
+This option can be used if the home directory is shared across machines.
+In this case localhost will refer to a different machine on each of
+the machines and the user will get many warnings about changed host keys.
+However, this option disables host authentication for localhost.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is to check the host key for localhost.
+.It Cm NumberOfPasswordPrompts
+Specifies the number of password prompts before giving up.
+The argument to this keyword must be an integer.
+Default is 3.
+.It Cm PasswordAuthentication
+Specifies whether to use password authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm Port
+Specifies the port number to connect on the remote host.
+Default is 22.
+.It Cm PreferredAuthentications
+Specifies the order in which the client should try protocol 2
+authentication methods. This allows a client to prefer one method (e.g.
+.Cm keyboard-interactive )
+over another method (e.g.
+.Cm password )
+The default for this option is:
+.Dq hostbased,publickey,keyboard-interactive,password .
+.It Cm Protocol
+Specifies the protocol versions
+.Nm ssh
+should support in order of preference.
+The possible values are
+.Dq 1
+and
+.Dq 2 .
+Multiple versions must be comma-separated.
+The default is
+.Dq 2,1 .
+This means that
+.Nm ssh
+tries version 2 and falls back to version 1
+if version 2 is not available.
+.It Cm ProxyCommand
+Specifies the command to use to connect to the server.
+The command
+string extends to the end of the line, and is executed with
+.Pa /bin/sh .
+In the command string,
+.Ql %h
+will be substituted by the host name to
+connect and
+.Ql %p
+by the port.
+The command can be basically anything,
+and should read from its standard input and write to its standard output.
+It should eventually connect an
+.Xr sshd 8
+server running on some machine, or execute
+.Ic sshd -i
+somewhere.
+Host key management will be done using the
+HostName of the host being connected (defaulting to the name typed by
+the user).
+Note that
+.Cm CheckHostIP
+is not available for connects with a proxy command.
+.Pp
+.It Cm PubkeyAuthentication
+Specifies whether to try public key authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+This option applies to protocol version 2 only.
+.It Cm RemoteForward
+Specifies that a TCP/IP port on the remote machine be forwarded over
+the secure channel to the specified host and port from the local machine.
+The first argument must be a port number, and the second must be
+.Ar host:port .
+IPv6 addresses can be specified with an alternative syntax:
+.Ar host/port .
+Multiple forwardings may be specified, and additional
+forwardings can be given on the command line.
+Only the superuser can forward privileged ports.
+.It Cm RhostsAuthentication
+Specifies whether to try rhosts based authentication.
+Note that this
+declaration only affects the client side and has no effect whatsoever
+on security.
+Most servers do not permit RhostsAuthentication because it
+is not secure (see
+.Cm RhostsRSAAuthentication ) .
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 1 only.
+.It Cm RhostsRSAAuthentication
+Specifies whether to try rhosts based authentication with RSA host
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 1 only and requires
+.Nm ssh
+to be setuid root.
+.It Cm RSAAuthentication
+Specifies whether to try RSA authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+RSA authentication will only be
+attempted if the identity file exists, or an authentication agent is
+running.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 1 only.
+.It Cm SmartcardDevice
+Specifies which smartcard device to use. The argument to this keyword is
+the device
+.Nm ssh
+should use to communicate with a smartcard used for storing the user's
+private RSA key. By default, no device is specified and smartcard support
+is not activated.
+.It Cm StrictHostKeyChecking
+If this flag is set to
+.Dq yes ,
+.Nm ssh
+will never automatically add host keys to the
+.Pa $HOME/.ssh/known_hosts
+file, and refuses to connect to hosts whose host key has changed.
+This provides maximum protection against trojan horse attacks,
+however, can be annoying when the
+.Pa /etc/ssh/ssh_known_hosts
+file is poorly maintained, or connections to new hosts are
+frequently made.
+This option forces the user to manually
+add all new hosts.
+If this flag is set to
+.Dq no ,
+.Nm ssh
+will automatically add new host keys to the
+user known hosts files.
+If this flag is set to
+.Dq ask ,
+new host keys
+will be added to the user known host files only after the user
+has confirmed that is what they really want to do, and
+.Nm ssh
+will refuse to connect to hosts whose host key has changed.
+The host keys of
+known hosts will be verified automatically in all cases.
+The argument must be
+.Dq yes ,
+.Dq no
+or
+.Dq ask .
+The default is
+.Dq ask .
+.It Cm UsePrivilegedPort
+Specifies whether to use a privileged port for outgoing connections.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+Note that this option must be set to
+.Dq yes
+if
+.Cm RhostsAuthentication
+and
+.Cm RhostsRSAAuthentication
+authentications are needed with older servers.
+.It Cm User
+Specifies the user to log in as.
+This can be useful when a different user name is used on different machines.
+This saves the trouble of
+having to remember to give the user name on the command line.
+.It Cm UserKnownHostsFile
+Specifies a file to use for the user
+host key database instead of
+.Pa $HOME/.ssh/known_hosts .
+.It Cm XAuthLocation
+Specifies the location of the
+.Xr xauth 1
+program.
+The default is
+.Pa /usr/X11R6/bin/xauth .
+.El
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa $HOME/.ssh/config
+This is the per-user configuration file.
+The format of this file is described above.
+This file is used by the
+.Nm ssh
+client.
+This file does not usually contain any sensitive information,
+but the recommended permissions are read/write for the user, and not
+accessible by others.
+.It Pa /etc/ssh/ssh_config
+Systemwide configuration file.
+This file provides defaults for those
+values that are not specified in the user's configuration file, and
+for those users who do not have a configuration file.
+This file must be world-readable.
+.El
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
+.Sh SEE ALSO
+.Xr ssh 1
diff --git a/crypto/openssh/sshconnect.c b/crypto/openssh/sshconnect.c
index afa40be..52ccf89 100644
--- a/crypto/openssh/sshconnect.c
+++ b/crypto/openssh/sshconnect.c
@@ -13,7 +13,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect.c,v 1.119 2002/01/21 15:13:51 markus Exp $");
+RCSID("$OpenBSD: sshconnect.c,v 1.125 2002/06/19 00:27:55 deraadt Exp $");
#include <openssl/bn.h>
@@ -36,27 +36,20 @@ RCSID("$OpenBSD: sshconnect.c,v 1.119 2002/01/21 15:13:51 markus Exp $");
char *client_version_string = NULL;
char *server_version_string = NULL;
+/* import */
extern Options options;
extern char *__progname;
+extern uid_t original_real_uid;
+extern uid_t original_effective_uid;
static const char *
-sockaddr_ntop(struct sockaddr *sa)
+sockaddr_ntop(struct sockaddr *sa, socklen_t salen)
{
- void *addr;
- static char addrbuf[INET6_ADDRSTRLEN];
+ static char addrbuf[NI_MAXHOST];
- switch (sa->sa_family) {
- case AF_INET:
- addr = &((struct sockaddr_in *)sa)->sin_addr;
- break;
- case AF_INET6:
- addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
- break;
- default:
- /* This case should be protected against elsewhere */
- abort(); /* XXX abort is bad -- do something else */
- }
- inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf));
+ if (getnameinfo(sa, salen, addrbuf, sizeof(addrbuf), NULL, 0,
+ NI_NUMERICHOST) != 0)
+ fatal("sockaddr_ntop: getnameinfo NI_NUMERICHOST failed");
return addrbuf;
}
@@ -64,8 +57,7 @@ sockaddr_ntop(struct sockaddr *sa)
* Connect to the given ssh server using a proxy command.
*/
static int
-ssh_proxy_connect(const char *host, u_short port, struct passwd *pw,
- const char *proxy_command)
+ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
{
Buffer command;
const char *cp;
@@ -115,7 +107,8 @@ ssh_proxy_connect(const char *host, u_short port, struct passwd *pw,
char *argv[10];
/* Child. Permanently give up superuser privileges. */
- permanently_set_uid(pw);
+ seteuid(original_real_uid);
+ setuid(original_real_uid);
/* Redirect stdin and stdout. */
close(pin[1]);
@@ -165,7 +158,7 @@ ssh_proxy_connect(const char *host, u_short port, struct passwd *pw,
* Creates a (possibly privileged) socket for use as the ssh connection.
*/
static int
-ssh_create_socket(struct passwd *pw, int privileged, int family)
+ssh_create_socket(int privileged, int family)
{
int sock, gaierr;
struct addrinfo hints, *res;
@@ -176,22 +169,18 @@ ssh_create_socket(struct passwd *pw, int privileged, int family)
*/
if (privileged) {
int p = IPPORT_RESERVED - 1;
+ PRIV_START;
sock = rresvport_af(&p, family);
+ PRIV_END;
if (sock < 0)
error("rresvport: af=%d %.100s", family, strerror(errno));
else
debug("Allocated local port %d.", p);
return sock;
}
- /*
- * Just create an ordinary socket on arbitrary port. We use
- * the user's uid to create the socket.
- */
- temporarily_use_uid(pw);
sock = socket(family, SOCK_STREAM, 0);
if (sock < 0)
error("socket: %.100s", strerror(errno));
- restore_uid();
/* Bind the socket to an alternative local IP address */
if (options.bind_address == NULL)
@@ -221,9 +210,9 @@ ssh_create_socket(struct passwd *pw, int privileged, int family)
/*
* Opens a TCP/IP connection to the remote server on the given host.
* The address of the remote host will be returned in hostaddr.
- * If port is 0, the default port will be used. If anonymous is zero,
+ * If port is 0, the default port will be used. If needpriv is true,
* a privileged port will be allocated to make the connection.
- * This requires super-user privileges if anonymous is false.
+ * This requires super-user privileges if needpriv is true.
* Connection_attempts specifies the maximum number of tries (one per
* second). If proxy_command is non-NULL, it specifies the command (with %h
* and %p substituted for host and port, respectively) to use to contact
@@ -238,7 +227,7 @@ ssh_create_socket(struct passwd *pw, int privileged, int family)
int
ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
u_short port, int family, int connection_attempts,
- int anonymous, struct passwd *pw, const char *proxy_command)
+ int needpriv, const char *proxy_command)
{
int gaierr;
int on = 1;
@@ -254,8 +243,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
*/
int full_failure = 1;
- debug("ssh_connect: getuid %u geteuid %u anon %d",
- (u_int) getuid(), (u_int) geteuid(), anonymous);
+ debug("ssh_connect: needpriv %d", needpriv);
/* Get default port if port has not been set. */
if (port == 0) {
@@ -267,7 +255,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
}
/* If a proxy command is given, connect using it. */
if (proxy_command != NULL)
- return ssh_proxy_connect(host, port, pw, proxy_command);
+ return ssh_proxy_connect(host, port, proxy_command);
/* No proxy command. */
@@ -303,30 +291,21 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
host, ntop, strport);
/* Create a socket for connecting. */
- sock = ssh_create_socket(pw,
- !anonymous && geteuid() == 0,
- ai->ai_family);
+ sock = ssh_create_socket(needpriv, ai->ai_family);
if (sock < 0)
/* Any error is already output */
continue;
- /* Connect to the host. We use the user's uid in the
- * hope that it will help with tcp_wrappers showing
- * the remote uid as root.
- */
- temporarily_use_uid(pw);
if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) {
/* Successful connection. */
memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
- restore_uid();
break;
} else {
if (errno == ECONNREFUSED)
full_failure = 0;
log("ssh: connect to address %s port %s: %s",
- sockaddr_ntop(ai->ai_addr), strport,
- strerror(errno));
- restore_uid();
+ sockaddr_ntop(ai->ai_addr, ai->ai_addrlen),
+ strport, strerror(errno));
/*
* Close the failed socket; there appear to
* be some problems when reusing a socket for
@@ -784,7 +763,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
len = strlen(msg);
snprintf(msg + len, sizeof(msg) - len,
"\nMatching host key in %s:%d",
- host_file, host_line);
+ host_file, host_line);
}
if (options.strict_host_key_checking == 1) {
log(msg);
@@ -832,7 +811,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
* This function does not require super-user privileges.
*/
void
-ssh_login(Key **keys, int nkeys, const char *orighost,
+ssh_login(Sensitive *sensitive, const char *orighost,
struct sockaddr *hostaddr, struct passwd *pw)
{
char *host, *cp;
@@ -857,10 +836,10 @@ ssh_login(Key **keys, int nkeys, const char *orighost,
/* authenticate user */
if (compat20) {
ssh_kex2(host, hostaddr);
- ssh_userauth2(local_user, server_user, host, keys, nkeys);
+ ssh_userauth2(local_user, server_user, host, sensitive);
} else {
ssh_kex(host, hostaddr);
- ssh_userauth1(local_user, server_user, host, keys, nkeys);
+ ssh_userauth1(local_user, server_user, host, sensitive);
}
}
diff --git a/crypto/openssh/sshconnect.h b/crypto/openssh/sshconnect.h
index b475add..0be30fe 100644
--- a/crypto/openssh/sshconnect.h
+++ b/crypto/openssh/sshconnect.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect.h,v 1.13 2001/10/08 19:05:05 markus Exp $ */
+/* $OpenBSD: sshconnect.h,v 1.17 2002/06/19 00:27:55 deraadt Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -26,21 +26,44 @@
#ifndef SSHCONNECT_H
#define SSHCONNECT_H
+typedef struct Sensitive Sensitive;
+struct Sensitive {
+ Key **keys;
+ int nkeys;
+ int external_keysign;
+};
+
int
ssh_connect(const char *, struct sockaddr_storage *, u_short, int, int,
- int, struct passwd *, const char *);
+ int, const char *);
void
-ssh_login(Key **, int, const char *, struct sockaddr *, struct passwd *);
+ssh_login(Sensitive *, const char *, struct sockaddr *, struct passwd *);
int verify_host_key(char *, struct sockaddr *, Key *);
void ssh_kex(char *, struct sockaddr *);
void ssh_kex2(char *, struct sockaddr *);
-void ssh_userauth1(const char *, const char *, char *, Key **, int);
-void ssh_userauth2(const char *, const char *, char *, Key **, int);
+void ssh_userauth1(const char *, const char *, char *, Sensitive *);
+void ssh_userauth2(const char *, const char *, char *, Sensitive *);
void ssh_put_password(char *);
+
+/*
+ * Macros to raise/lower permissions.
+ */
+#define PRIV_START do { \
+ int save_errno = errno; \
+ (void)seteuid(original_effective_uid); \
+ errno = save_errno; \
+} while (0)
+
+#define PRIV_END do { \
+ int save_errno = errno; \
+ (void)seteuid(original_real_uid); \
+ errno = save_errno; \
+} while (0)
+
#endif
diff --git a/crypto/openssh/sshconnect1.c b/crypto/openssh/sshconnect1.c
index d7722f4..dab2771 100644
--- a/crypto/openssh/sshconnect1.c
+++ b/crypto/openssh/sshconnect1.c
@@ -13,7 +13,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect1.c,v 1.48 2002/02/11 16:15:46 markus Exp $");
+RCSID("$OpenBSD: sshconnect1.c,v 1.51 2002/05/23 19:24:30 markus Exp $");
#include <openssl/bn.h>
#include <openssl/md5.h>
@@ -459,6 +459,8 @@ try_krb4_authentication(void)
/* Get server's response. */
reply = packet_get_string((u_int *) &auth.length);
+ if (auth.length >= MAX_KTXT_LEN)
+ fatal("Kerberos v4: Malformed response from server");
memcpy(auth.dat, reply, auth.length);
xfree(reply);
@@ -843,7 +845,7 @@ try_challenge_response_authentication(void)
error("Permission denied, please try again.");
if (options.cipher == SSH_CIPHER_NONE)
log("WARNING: Encryption is disabled! "
- "Reponse will be transmitted in clear text.");
+ "Response will be transmitted in clear text.");
response = read_passphrase(prompt, 0);
if (strcmp(response, "") == 0) {
xfree(response);
@@ -1090,7 +1092,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
*/
void
ssh_userauth1(const char *local_user, const char *server_user, char *host,
- Key **keys, int nkeys)
+ Sensitive *sensitive)
{
#ifdef KRB5
krb5_context context = NULL;
@@ -1176,9 +1178,11 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host,
*/
if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&
options.rhosts_rsa_authentication) {
- for (i = 0; i < nkeys; i++) {
- if (keys[i] != NULL && keys[i]->type == KEY_RSA1 &&
- try_rhosts_rsa_authentication(local_user, keys[i]))
+ for (i = 0; i < sensitive->nkeys; i++) {
+ if (sensitive->keys[i] != NULL &&
+ sensitive->keys[i]->type == KEY_RSA1 &&
+ try_rhosts_rsa_authentication(local_user,
+ sensitive->keys[i]))
goto success;
}
}
diff --git a/crypto/openssh/sshconnect2.c b/crypto/openssh/sshconnect2.c
index c5b5ee5..c16a318 100644
--- a/crypto/openssh/sshconnect2.c
+++ b/crypto/openssh/sshconnect2.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect2.c,v 1.97 2002/02/25 16:33:27 markus Exp $");
+RCSID("$OpenBSD: sshconnect2.c,v 1.104 2002/06/19 00:27:55 deraadt Exp $");
#include "ssh.h"
#include "ssh2.h"
@@ -45,6 +45,8 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.97 2002/02/25 16:33:27 markus Exp $");
#include "match.h"
#include "dispatch.h"
#include "canohost.h"
+#include "msg.h"
+#include "pathnames.h"
/* import */
extern char *client_version_string;
@@ -154,8 +156,7 @@ struct Authctxt {
int last_key_hint;
AuthenticationConnection *agent;
/* hostbased */
- Key **keys;
- int nkeys;
+ Sensitive *sensitive;
/* kbd-interactive */
int info_req_seen;
};
@@ -172,6 +173,7 @@ void input_userauth_banner(int, u_int32_t, void *);
void input_userauth_error(int, u_int32_t, void *);
void input_userauth_info_req(int, u_int32_t, void *);
void input_userauth_pk_ok(int, u_int32_t, void *);
+void input_userauth_passwd_changereq(int, u_int32_t, void *);
int userauth_none(Authctxt *);
int userauth_pubkey(Authctxt *);
@@ -214,7 +216,7 @@ Authmethod authmethods[] = {
void
ssh_userauth2(const char *local_user, const char *server_user, char *host,
- Key **keys, int nkeys)
+ Sensitive *sensitive)
{
Authctxt authctxt;
int type;
@@ -254,8 +256,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
authctxt.success = 0;
authctxt.method = authmethod_lookup("none");
authctxt.authlist = NULL;
- authctxt.keys = keys;
- authctxt.nkeys = nkeys;
+ authctxt.sensitive = sensitive;
authctxt.info_req_seen = 0;
if (authctxt.method == NULL)
fatal("ssh_userauth2: internal error: cannot send userauth none request");
@@ -391,10 +392,10 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
debug("no key from blob. pkalg %s", pkalg);
break;
}
- if (key->type != pktype) {
+ if (key->type != pktype) {
error("input_userauth_pk_ok: type mismatch "
"for decoded key (received %d, expected %d)",
- key->type, pktype);
+ key->type, pktype);
break;
}
fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
@@ -439,7 +440,7 @@ int
userauth_passwd(Authctxt *authctxt)
{
static int attempt = 0;
- char prompt[80];
+ char prompt[150];
char *password;
if (attempt++ >= options.number_of_password_prompts)
@@ -461,13 +462,85 @@ userauth_passwd(Authctxt *authctxt)
xfree(password);
packet_add_padding(64);
packet_send();
+
+ dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
+ &input_userauth_passwd_changereq);
+
return 1;
}
+/*
+ * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST
+ */
+void
+input_userauth_passwd_changereq(int type, uint32_t seqnr, void *ctxt)
+{
+ Authctxt *authctxt = ctxt;
+ char *info, *lang, *password = NULL, *retype = NULL;
+ char prompt[150];
+
+ debug2("input_userauth_passwd_changereq");
+
+ if (authctxt == NULL)
+ fatal("input_userauth_passwd_changereq: "
+ "no authentication context");
+
+ info = packet_get_string(NULL);
+ lang = packet_get_string(NULL);
+ if (strlen(info) > 0)
+ log("%s", info);
+ xfree(info);
+ xfree(lang);
+ 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_char(1); /* additional info */
+ snprintf(prompt, sizeof(prompt),
+ "Enter %.30s@%.128s's old password: ",
+ authctxt->server_user, authctxt->host);
+ password = read_passphrase(prompt, 0);
+ packet_put_cstring(password);
+ memset(password, 0, strlen(password));
+ xfree(password);
+ password = NULL;
+ while (password == NULL) {
+ snprintf(prompt, sizeof(prompt),
+ "Enter %.30s@%.128s's new password: ",
+ authctxt->server_user, authctxt->host);
+ password = read_passphrase(prompt, RP_ALLOW_EOF);
+ if (password == NULL) {
+ /* bail out */
+ return;
+ }
+ snprintf(prompt, sizeof(prompt),
+ "Retype %.30s@%.128s's new password: ",
+ authctxt->server_user, authctxt->host);
+ retype = read_passphrase(prompt, 0);
+ if (strcmp(password, retype) != 0) {
+ memset(password, 0, strlen(password));
+ xfree(password);
+ log("Mismatch; try again, EOF to quit.");
+ password = NULL;
+ }
+ memset(retype, 0, strlen(retype));
+ xfree(retype);
+ }
+ packet_put_cstring(password);
+ memset(password, 0, strlen(password));
+ xfree(password);
+ packet_add_padding(64);
+ packet_send();
+
+ dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
+ &input_userauth_passwd_changereq);
+}
static void
clear_auth_state(Authctxt *authctxt)
{
/* XXX clear authentication state */
+ dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, NULL);
+
if (authctxt->last_key != NULL && authctxt->last_key_hint == -1) {
debug3("clear_auth_state: key_free %p", authctxt->last_key);
key_free(authctxt->last_key);
@@ -820,14 +893,88 @@ input_userauth_info_req(int type, u_int32_t seq, 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.
- */
+static int
+ssh_keysign(
+ Key *key,
+ u_char **sigp, u_int *lenp,
+ u_char *data, u_int datalen)
+{
+ Buffer b;
+ struct stat st;
+ pid_t pid;
+ int to[2], from[2], status, version = 2;
+
+ debug("ssh_keysign called");
+
+ if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) {
+ error("ssh_keysign: no installed: %s", strerror(errno));
+ return -1;
+ }
+ if (fflush(stdout) != 0)
+ error("ssh_keysign: fflush: %s", strerror(errno));
+ if (pipe(to) < 0) {
+ error("ssh_keysign: pipe: %s", strerror(errno));
+ return -1;
+ }
+ if (pipe(from) < 0) {
+ error("ssh_keysign: pipe: %s", strerror(errno));
+ return -1;
+ }
+ if ((pid = fork()) < 0) {
+ error("ssh_keysign: fork: %s", strerror(errno));
+ return -1;
+ }
+ if (pid == 0) {
+ seteuid(getuid());
+ setuid(getuid());
+ close(from[0]);
+ if (dup2(from[1], STDOUT_FILENO) < 0)
+ fatal("ssh_keysign: dup2: %s", strerror(errno));
+ close(to[1]);
+ if (dup2(to[0], STDIN_FILENO) < 0)
+ fatal("ssh_keysign: dup2: %s", strerror(errno));
+ close(from[1]);
+ close(to[0]);
+ execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0);
+ fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN,
+ strerror(errno));
+ }
+ close(from[1]);
+ close(to[0]);
+
+ buffer_init(&b);
+ buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */
+ buffer_put_string(&b, data, datalen);
+ msg_send(to[1], version, &b);
+
+ if (msg_recv(from[0], &b) < 0) {
+ error("ssh_keysign: no reply");
+ buffer_clear(&b);
+ return -1;
+ }
+ close(from[0]);
+ close(to[1]);
+
+ while (waitpid(pid, &status, 0) < 0)
+ if (errno != EINTR)
+ break;
+
+ if (buffer_get_char(&b) != version) {
+ error("ssh_keysign: bad version");
+ buffer_clear(&b);
+ return -1;
+ }
+ *sigp = buffer_get_string(&b, lenp);
+ buffer_clear(&b);
+
+ return 0;
+}
+
int
userauth_hostbased(Authctxt *authctxt)
{
Key *private = NULL;
+ Sensitive *sensitive = authctxt->sensitive;
Buffer b;
u_char *signature, *blob;
char *chost, *pkalg, *p;
@@ -836,12 +983,12 @@ userauth_hostbased(Authctxt *authctxt)
int ok, i, len, found = 0;
/* check for a useful key */
- for (i = 0; i < authctxt->nkeys; i++) {
- private = authctxt->keys[i];
+ for (i = 0; i < sensitive->nkeys; i++) {
+ private = sensitive->keys[i];
if (private && private->type != KEY_RSA1) {
found = 1;
/* we take and free the key */
- authctxt->keys[i] = NULL;
+ sensitive->keys[i] = NULL;
break;
}
}
@@ -883,7 +1030,12 @@ userauth_hostbased(Authctxt *authctxt)
#ifdef DEBUG_PK
buffer_dump(&b);
#endif
- ok = key_sign(private, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
+ if (sensitive->external_keysign)
+ ok = ssh_keysign(private, &signature, &slen,
+ buffer_ptr(&b), buffer_len(&b));
+ else
+ ok = key_sign(private, &signature, &slen,
+ buffer_ptr(&b), buffer_len(&b));
key_free(private);
buffer_free(&b);
if (ok != 0) {
diff --git a/crypto/openssh/sshd.8 b/crypto/openssh/sshd.8
index 9d579f1..22f8143 100644
--- a/crypto/openssh/sshd.8
+++ b/crypto/openssh/sshd.8
@@ -34,7 +34,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: sshd.8,v 1.170 2002/02/28 20:46:10 stevesk Exp $
+.\" $OpenBSD: sshd.8,v 1.184 2002/06/20 19:56:07 stevesk Exp $
.Dd September 25, 1999
.Dt SSHD 8
.Os
@@ -116,14 +116,14 @@ Rhosts authentication is normally disabled
because it is fundamentally insecure, but can be enabled in the server
configuration file if desired.
System security is not improved unless
-.Xr rshd 8 ,
-.Xr rlogind 8 ,
+.Nm rshd ,
+.Nm rlogind ,
and
-.Xr rexecd 8
+.Xr rexecd
are disabled (thus completely disabling
-.Xr rlogin 1
+.Xr rlogin
and
-.Xr rsh 1
+.Xr rsh
into the machine).
.Pp
.Ss SSH protocol version 2
@@ -320,617 +320,8 @@ reads configuration data from
(or the file specified with
.Fl f
on the command line).
-The file contains keyword-argument pairs, one per line.
-Lines starting with
-.Ql #
-and empty lines are interpreted as comments.
-.Pp
-The possible
-keywords and their meanings are as follows (note that
-keywords are case-insensitive and arguments are case-sensitive):
-.Bl -tag -width Ds
-.It Cm AFSTokenPassing
-Specifies whether an AFS token may be forwarded to the server.
-Default is
-.Dq yes .
-.It Cm AllowGroups
-This keyword can be followed by a list of group name patterns, separated
-by spaces.
-If specified, login is allowed only for users whose primary
-group or supplementary group list matches one of the patterns.
-.Ql \&*
-and
-.Ql ?
-can be used as
-wildcards in the patterns.
-Only group names are valid; a numerical group ID is not recognized.
-By default, login is allowed for all groups.
-.Pp
-.It Cm AllowTcpForwarding
-Specifies whether TCP forwarding is permitted.
-The default is
-.Dq yes .
-Note that disabling TCP forwarding does not improve security unless
-users are also denied shell access, as they can always install their
-own forwarders.
-.Pp
-.It Cm AllowUsers
-This keyword can be followed by a list of user name patterns, separated
-by spaces.
-If specified, login is allowed only for users names that
-match one of the patterns.
-.Ql \&*
-and
-.Ql ?
-can be used as
-wildcards in the patterns.
-Only user names are valid; a numerical user ID is not recognized.
-By default, login is allowed for all users.
-If the pattern takes the form USER@HOST then USER and HOST
-are separately checked, restricting logins to particular
-users from particular hosts.
-.Pp
-.It Cm AuthorizedKeysFile
-Specifies the file that contains the public keys that can be used
-for user authentication.
-.Cm AuthorizedKeysFile
-may contain tokens of the form %T which are substituted during connection
-set-up. The following tokens are defined: %% is replaced by a literal '%',
-%h is replaced by the home directory of the user being authenticated and
-%u is replaced by the username of that user.
-After expansion,
-.Cm AuthorizedKeysFile
-is taken to be an absolute path or one relative to the user's home
-directory.
-The default is
-.Dq .ssh/authorized_keys .
-.It Cm Banner
-In some jurisdictions, sending a warning message before authentication
-may be relevant for getting legal protection.
-The contents of the specified file are sent to the remote user before
-authentication is allowed.
-This option is only available for protocol version 2.
-.Pp
-.It Cm ChallengeResponseAuthentication
-Specifies whether challenge response authentication is allowed.
-All authentication styles from
-.Xr login.conf 5
-are supported.
-The default is
-.Dq yes .
-.It Cm Ciphers
-Specifies the ciphers allowed for protocol version 2.
-Multiple ciphers must be comma-separated.
-The default is
-.Pp
-.Bd -literal
- ``aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,
- aes192-cbc,aes256-cbc''
-.Ed
-.It Cm ClientAliveInterval
-Sets a timeout interval in seconds after which if no data has been received
-from the client,
-.Nm
-will send a message through the encrypted
-channel to request a response from the client.
-The default
-is 0, indicating that these messages will not be sent to the client.
-This option applies to protocol version 2 only.
-.It Cm ClientAliveCountMax
-Sets the number of client alive messages (see above) which may be
-sent without
-.Nm
-receiving any messages back from the client. If this threshold is
-reached while client alive messages are being sent,
-.Nm
-will disconnect the client, terminating the session. It is important
-to note that the use of client alive messages is very different from
-.Cm KeepAlive
-(below). The client alive messages are sent through the
-encrypted channel and therefore will not be spoofable. The TCP keepalive
-option enabled by
-.Cm KeepAlive
-is spoofable. The client alive mechanism is valuable when the client or
-server depend on knowing when a connection has become inactive.
-.Pp
-The default value is 3. If
-.Cm ClientAliveInterval
-(above) is set to 15, and
-.Cm ClientAliveCountMax
-is left at the default, unresponsive ssh clients
-will be disconnected after approximately 45 seconds.
-.It Cm DenyGroups
-This keyword can be followed by a list of group name patterns, separated
-by spaces.
-Login is disallowed for users whose primary group or supplementary
-group list matches one of the patterns.
-.Ql \&*
-and
-.Ql ?
-can be used as
-wildcards in the patterns.
-Only group names are valid; a numerical group ID is not recognized.
-By default, login is allowed for all groups.
-.Pp
-.It Cm DenyUsers
-This keyword can be followed by a list of user name patterns, separated
-by spaces.
-Login is disallowed for user names that match one of the patterns.
-.Ql \&*
-and
-.Ql ?
-can be used as wildcards in the patterns.
-Only user names are valid; a numerical user ID is not recognized.
-By default, login is allowed for all users.
-If the pattern takes the form USER@HOST then USER and HOST
-are separately checked, restricting logins to particular
-users from particular hosts.
-.It Cm GatewayPorts
-Specifies whether remote hosts are allowed to connect to ports
-forwarded for the client.
-By default,
-.Nm
-binds remote port forwardings to the loopback addresss. This
-prevents other remote hosts from connecting to forwarded ports.
-.Cm GatewayPorts
-can be used to specify that
-.Nm
-should bind remote port forwardings to the wildcard address,
-thus allowing remote hosts to connect to forwarded ports.
-The argument must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq no .
-.It Cm HostbasedAuthentication
-Specifies whether rhosts or /etc/hosts.equiv authentication together
-with successful public key client host authentication is allowed
-(hostbased authentication).
-This option is similar to
-.Cm RhostsRSAAuthentication
-and applies to protocol version 2 only.
-The default is
-.Dq no .
-.It Cm HostKey
-Specifies a file containing a private host key
-used by SSH.
-The default is
-.Pa /etc/ssh/ssh_host_key
-for protocol version 1, and
-.Pa /etc/ssh/ssh_host_rsa_key
-and
-.Pa /etc/ssh/ssh_host_dsa_key
-for protocol version 2.
-Note that
-.Nm
-will refuse to use a file if it is group/world-accessible.
-It is possible to have multiple host key files.
-.Dq rsa1
-keys are used for version 1 and
-.Dq dsa
-or
-.Dq rsa
-are used for version 2 of the SSH protocol.
-.It Cm IgnoreRhosts
-Specifies that
-.Pa .rhosts
-and
-.Pa .shosts
-files will not be used in
-.Cm RhostsAuthentication ,
-.Cm RhostsRSAAuthentication
-or
-.Cm HostbasedAuthentication .
-.Pp
-.Pa /etc/hosts.equiv
-and
-.Pa /etc/shosts.equiv
-are still used.
-The default is
-.Dq yes .
-.It Cm IgnoreUserKnownHosts
-Specifies whether
-.Nm
-should ignore the user's
-.Pa $HOME/.ssh/known_hosts
-during
-.Cm RhostsRSAAuthentication
-or
-.Cm HostbasedAuthentication .
-The default is
-.Dq no .
-.It Cm KeepAlive
-Specifies whether the system should send TCP keepalive messages to the
-other side.
-If they are sent, death of the connection or crash of one
-of the machines will be properly noticed.
-However, this means that
-connections will die if the route is down temporarily, and some people
-find it annoying.
-On the other hand, if keepalives are not sent,
-sessions may hang indefinitely on the server, leaving
-.Dq ghost
-users and consuming server resources.
-.Pp
-The default is
-.Dq yes
-(to send keepalives), and the server will notice
-if the network goes down or the client host crashes.
-This avoids infinitely hanging sessions.
-.Pp
-To disable keepalives, the value should be set to
-.Dq no .
-.It Cm KerberosAuthentication
-Specifies whether Kerberos authentication is allowed.
-This can 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.
-To use this option, the server needs a
-Kerberos servtab which allows the verification of the KDC's identity.
-Default is
-.Dq yes .
-.It Cm KerberosOrLocalPasswd
-If set then if password authentication through Kerberos fails then
-the password will be validated via any additional local mechanism
-such as
-.Pa /etc/passwd .
-Default is
-.Dq yes .
-.It Cm KerberosTgtPassing
-Specifies whether a Kerberos TGT may be forwarded to the server.
-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
-.Dq yes .
-.It Cm KeyRegenerationInterval
-In protocol version 1, the ephemeral server key is automatically regenerated
-after this many seconds (if it has been used).
-The purpose of regeneration is to prevent
-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 the local addresses
-.Nm
-should listen on.
-The following forms may be used:
-.Pp
-.Bl -item -offset indent -compact
-.It
-.Cm ListenAddress
-.Sm off
-.Ar host No | Ar IPv4_addr No | Ar IPv6_addr
-.Sm on
-.It
-.Cm ListenAddress
-.Sm off
-.Ar host No | Ar IPv4_addr No : Ar port
-.Sm on
-.It
-.Cm ListenAddress
-.Sm off
-.Oo
-.Ar host No | Ar IPv6_addr Oc : Ar port
-.Sm on
-.El
-.Pp
-If
-.Ar port
-is not specified,
-.Nm
-will listen on the address and all prior
-.Cm Port
-options specified. The default is to listen on all local
-addresses. Multiple
-.Cm ListenAddress
-options are permitted. Additionally, any
-.Cm Port
-options must precede this option for non port qualified 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.
-The default is 600 (seconds).
-.It Cm LogLevel
-Gives the verbosity level that is used when logging messages from
-.Nm sshd .
-The possible values are:
-QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2 and DEBUG3.
-The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2
-and DEBUG3 each specify higher levels of debugging output.
-Logging with a DEBUG level violates the privacy of users
-and is not recommended.
-.It Cm MACs
-Specifies the available MAC (message authentication code) algorithms.
-The MAC algorithm is used in protocol version 2
-for data integrity protection.
-Multiple algorithms must be comma-separated.
-The default is
-.Dq hmac-md5,hmac-sha1,hmac-ripemd160,hmac-sha1-96,hmac-md5-96 .
-.It Cm MaxStartups
-Specifies the maximum number of concurrent unauthenticated connections to the
-.Nm
-daemon.
-Additional connections will be dropped until authentication succeeds or the
-.Cm LoginGraceTime
-expires for a connection.
-The default is 10.
-.Pp
-Alternatively, random early drop can be enabled by specifying
-the three colon separated values
-.Dq start:rate:full
-(e.g., "10:30:60").
-.Nm
-will refuse connection attempts with a probability of
-.Dq rate/100
-(30%)
-if there are currently
-.Dq start
-(10)
-unauthenticated connections.
-The probability increases linearly and all connection attempts
-are refused if the number of unauthenticated connections reaches
-.Dq full
-(60).
-.It Cm PasswordAuthentication
-Specifies whether password authentication is allowed.
-The default is
-.Dq yes .
-.It Cm PermitEmptyPasswords
-When password authentication is allowed, it specifies whether the
-server allows login to accounts with empty password strings.
-The default is
-.Dq no .
-.It Cm PermitRootLogin
-Specifies whether root can login using
-.Xr ssh 1 .
-The argument must be
-.Dq yes ,
-.Dq without-password ,
-.Dq forced-commands-only
-or
-.Dq no .
-The default is
-.Dq yes .
-.Pp
-If this option is set to
-.Dq without-password
-password authentication is disabled for root.
-.Pp
-If this option is set to
-.Dq forced-commands-only
-root login with public key authentication will be allowed,
-but only if the
-.Ar command
-option has been specified
-(which may be useful for taking remote backups even if root login is
-normally not allowed). All other authentication methods are disabled
-for root.
-.Pp
-If this option is set to
-.Dq no
-root is not allowed to login.
-.It Cm PidFile
-Specifies the file that contains the process identifier of the
-.Nm
-daemon.
-The default is
-.Pa /var/run/sshd.pid .
-.It Cm Port
-Specifies the port number that
-.Nm
-listens on.
-The default is 22.
-Multiple options of this type are permitted.
-See also
-.Cm ListenAddress .
-.It Cm PrintLastLog
-Specifies whether
-.Nm
-should print the date and time when the user last logged in.
-The default is
-.Dq yes .
-.It Cm PrintMotd
-Specifies whether
-.Nm
-should print
-.Pa /etc/motd
-when a user logs in interactively.
-(On some systems it is also printed by the shell,
-.Pa /etc/profile ,
-or equivalent.)
-The default is
-.Dq yes .
-.It Cm Protocol
-Specifies the protocol versions
-.Nm
-should support.
-The possible values are
-.Dq 1
-and
-.Dq 2 .
-Multiple versions must be comma-separated.
-The default is
-.Dq 2,1 .
-.It Cm PubkeyAuthentication
-Specifies whether public key authentication is allowed.
-The default is
-.Dq yes .
-Note that this option applies to protocol version 2 only.
-.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.
-.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
-.Dq no .
-This option applies to protocol version 1 only.
-.It Cm RhostsRSAAuthentication
-Specifies whether rhosts or /etc/hosts.equiv authentication together
-with successful RSA host authentication is allowed.
-The default is
-.Dq no .
-This option applies to protocol version 1 only.
-.It Cm RSAAuthentication
-Specifies whether pure RSA authentication is allowed.
-The default is
-.Dq yes .
-This option applies to protocol version 1 only.
-.It Cm ServerKeyBits
-Defines the number of bits in the ephemeral protocol version 1 server key.
-The minimum value is 512, and the default is 768.
-.It Cm StrictModes
-Specifies whether
-.Nm
-should check file modes and ownership of the
-user's files and home directory before accepting login.
-This is normally desirable because novices sometimes accidentally leave their
-directory or files world-writable.
-The default is
-.Dq yes .
-.It Cm Subsystem
-Configures an external subsystem (e.g., file transfer daemon).
-Arguments should be a subsystem name and a command to execute upon subsystem
-request.
-The command
-.Xr sftp-server 8
-implements the
-.Dq sftp
-file transfer subsystem.
-By default no subsystems are defined.
-Note that this option applies to protocol version 2 only.
-.It Cm SyslogFacility
-Gives the facility code that is used when logging messages from
-.Nm sshd .
-The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
-LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
-The default is AUTH.
-.It Cm UseLogin
-Specifies whether
-.Xr login 1
-is used for interactive login sessions.
-The default is
-.Dq no .
-Note that
-.Xr login 1
-is never used for remote command execution.
-Note also, that if this is enabled,
-.Cm X11Forwarding
-will be disabled because
-.Xr login 1
-does not know how to handle
-.Xr xauth 1
-cookies.
-.It Cm VerifyReverseMapping
-Specifies whether
-.Nm
-should try to verify the remote host name and check that
-the resolved host name for the remote IP address maps back to the
-very same IP address.
-The default is
-.Dq no .
-.It Cm X11DisplayOffset
-Specifies the first display number available for
-.Nm sshd Ns 's
-X11 forwarding.
-This prevents
-.Nm
-from interfering with real X11 servers.
-The default is 10.
-.It Cm X11Forwarding
-Specifies whether X11 forwarding is permitted.
-The default is
-.Dq no .
-Note that disabling X11 forwarding does not improve security in any
-way, as users can always install their own forwarders.
-X11 forwarding is automatically disabled if
-.Cm UseLogin
-is enabled.
-.It Cm X11UseLocalhost
-Specifies whether
-.Nm
-should bind the X11 forwarding server to the loopback address or to
-the wildcard address. By default,
-.Nm
-binds the forwarding server to the loopback address and sets the
-hostname part of the
-.Ev DISPLAY
-environment variable to
-.Dq localhost .
-This prevents remote hosts from connecting to the fake display.
-However, some older X11 clients may not function with this
-configuration.
-.Cm X11UseLocalhost
-may be set to
-.Dq no
-to specify that the forwarding server should be bound to the wildcard
-address.
-The argument must be
-.Dq yes
-or
-.Dq no .
-The default is
-.Dq yes .
-.It Cm XAuthLocation
-Specifies the location of the
-.Xr xauth 1
-program.
-The default is
-.Pa /usr/X11R6/bin/xauth .
-.El
-.Ss Time Formats
-.Pp
-.Nm
-command-line arguments and configuration file options that specify time
-may be expressed using a sequence of the form:
-.Sm off
-.Ar time Oo Ar qualifier Oc ,
-.Sm on
-where
-.Ar time
-is a positive integer value and
-.Ar qualifier
-is one of the following:
-.Pp
-.Bl -tag -width Ds -compact -offset indent
-.It Cm <none>
-seconds
-.It Cm s | Cm S
-seconds
-.It Cm m | Cm M
-minutes
-.It Cm h | Cm H
-hours
-.It Cm d | Cm D
-days
-.It Cm w | Cm W
-weeks
-.El
-.Pp
-Each member of the sequence is added together to calculate
-the total time value.
-.Pp
-Time format examples:
-.Pp
-.Bl -tag -width Ds -compact -offset indent
-.It 600
-600 seconds (10 minutes)
-.It 10m
-10 minutes
-.It 1h30m
-1 hour 30 minutes (90 minutes)
-.El
+The file format and configuration options are described in
+.Xr sshd_config 5 .
.Sh LOGIN PROCESS
When a user successfully logs in,
.Nm
@@ -1015,6 +406,10 @@ or the
.Pa id_rsa.pub
file and edit it.
.Pp
+.Nm
+enforces a minimum RSA key modulus size for protocol 1
+and protocol 2 keys of 768 bits.
+.Pp
The options (if present) consist of comma-separated option
specifications.
No spaces are permitted, except within double quotes.
@@ -1162,8 +557,8 @@ cvs.openbsd.org,199.185.137.3 ssh-rsa AAAA1234.....=
.It Pa /etc/ssh/sshd_config
Contains configuration data for
.Nm sshd .
-This file should be writable by root only, but it is recommended
-(though not necessary) that it be world-readable.
+The file format and configuration options are described in
+.Xr sshd_config 5 .
.It Pa /etc/ssh/ssh_host_key, /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_rsa_key
These three files contain the private parts of the host keys.
These files should only be owned by root, readable only by root, and not
@@ -1299,13 +694,17 @@ only by the user; it need not be readable by anyone else.
.It Pa $HOME/.ssh/rc
If this file exists, it is run with /bin/sh after reading the
environment files but before starting the user's shell or command.
-If X11 spoofing is in use, this will receive the "proto cookie" pair in
-standard input (and
+It must not produce any output on stdout; stderr must be used
+instead.
+If X11 forwarding is in use, it will receive the "proto cookie" pair in
+its standard input (and
.Ev DISPLAY
-in environment).
-This must call
+in its environment).
+The script must call
.Xr xauth 1
-in that case.
+because
+.Nm
+will not run xauth automatically to add X11 cookies.
.Pp
The primary purpose of this file is to run any initialization routines
which may be needed before the user's home directory becomes
@@ -1314,15 +713,22 @@ accessible; AFS is a particular example of such an environment.
This file will probably contain some initialization code followed by
something similar to:
.Bd -literal
- if read proto cookie; then
- echo add $DISPLAY $proto $cookie | xauth -q -
+if read proto cookie && [ -n "$DISPLAY" ]; then
+ if [ `echo $DISPLAY | cut -c1-10` = 'localhost:' ]; then
+ # X11UseLocalhost=yes
+ xauth add unix:`echo $DISPLAY |
+ cut -c11-` $proto $cookie
+ else
+ # X11UseLocalhost=no
+ xauth add $DISPLAY $proto $cookie
fi
+fi
.Ed
.Pp
If this file does not exist,
.Pa /etc/ssh/sshrc
is run, and if that
-does not exist either, xauth is used to store the cookie.
+does not exist either, xauth is used to add the cookie.
.Pp
This file should be writable only by the user, and need not be
readable by anyone else.
@@ -1342,6 +748,8 @@ removed many bugs, re-added newer features and
created OpenSSH.
Markus Friedl contributed the support for SSH
protocol versions 1.5 and 2.0.
+Niels Provos and Markus Friedl contributed support
+for privilege separation.
.Sh SEE ALSO
.Xr scp 1 ,
.Xr sftp 1 ,
@@ -1351,6 +759,7 @@ protocol versions 1.5 and 2.0.
.Xr ssh-keygen 1 ,
.Xr login.conf 5 ,
.Xr moduli 5 ,
+.Xr sshd_config 5 ,
.Xr sftp-server 8
.Rs
.%A T. Ylonen
@@ -1359,8 +768,8 @@ protocol versions 1.5 and 2.0.
.%A T. Rinne
.%A S. Lehtinen
.%T "SSH Protocol Architecture"
-.%N draft-ietf-secsh-architecture-09.txt
-.%D July 2001
+.%N draft-ietf-secsh-architecture-12.txt
+.%D January 2002
.%O work in progress material
.Re
.Rs
@@ -1368,7 +777,7 @@ protocol versions 1.5 and 2.0.
.%A N. Provos
.%A W. A. Simpson
.%T "Diffie-Hellman Group Exchange for the SSH Transport Layer Protocol"
-.%N draft-ietf-secsh-dh-group-exchange-01.txt
-.%D April 2001
+.%N draft-ietf-secsh-dh-group-exchange-02.txt
+.%D January 2002
.%O work in progress material
.Re
diff --git a/crypto/openssh/sshd.c b/crypto/openssh/sshd.c
index eca004f..0f04704 100644
--- a/crypto/openssh/sshd.c
+++ b/crypto/openssh/sshd.c
@@ -15,8 +15,10 @@
* called by a name other than "ssh" or "Secure Shell".
*
* SSH2 implementation:
+ * Privilege Separation:
*
- * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved.
+ * Copyright (c) 2002 Niels Provos. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -40,11 +42,12 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshd.c,v 1.228 2002/02/27 21:23:13 stevesk Exp $");
+RCSID("$OpenBSD: sshd.c,v 1.246 2002/06/20 23:05:56 markus Exp $");
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/md5.h>
+#include <openssl/rand.h>
#include "ssh.h"
#include "ssh1.h"
@@ -72,6 +75,11 @@ RCSID("$OpenBSD: sshd.c,v 1.228 2002/02/27 21:23:13 stevesk Exp $");
#include "misc.h"
#include "dispatch.h"
#include "channels.h"
+#include "session.h"
+#include "monitor_mm.h"
+#include "monitor.h"
+#include "monitor_wrap.h"
+#include "monitor_fdpass.h"
#ifdef LIBWRAP
#include <tcpd.h>
@@ -180,8 +188,13 @@ u_int utmp_len = MAXHOSTNAMELEN;
int *startup_pipes = NULL;
int startup_pipe; /* in child */
+/* variables used for privilege separation */
+extern struct monitor *pmonitor;
+extern int use_privsep;
+
/* Prototypes for various functions defined later in this file. */
void destroy_sensitive_data(void);
+void demote_sensitive_data(void);
static void do_ssh1_kex(void);
static void do_ssh2_kex(void);
@@ -254,10 +267,12 @@ sigterm_handler(int sig)
static void
main_sigchld_handler(int sig)
{
+ pid_t pid;
int save_errno = errno;
int status;
- while (waitpid(-1, &status, WNOHANG) > 0)
+ while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
+ (pid < 0 && errno == EINTR))
;
signal(SIGCHLD, main_sigchld_handler);
@@ -350,7 +365,7 @@ sshd_exchange_identification(int sock_in, int sock_out)
fatal_cleanup();
}
- /* Read other side's version identification. */
+ /* Read other sides version identification. */
memset(buf, 0, sizeof(buf));
for (i = 0; i < sizeof(buf) - 1; i++) {
if (atomicio(read, sock_in, &buf[i], 1) != 1) {
@@ -468,6 +483,160 @@ destroy_sensitive_data(void)
memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH);
}
+/* Demote private to public keys for network child */
+void
+demote_sensitive_data(void)
+{
+ Key *tmp;
+ int i;
+
+ if (sensitive_data.server_key) {
+ tmp = key_demote(sensitive_data.server_key);
+ key_free(sensitive_data.server_key);
+ sensitive_data.server_key = tmp;
+ }
+
+ for (i = 0; i < options.num_host_key_files; i++) {
+ if (sensitive_data.host_keys[i]) {
+ tmp = key_demote(sensitive_data.host_keys[i]);
+ key_free(sensitive_data.host_keys[i]);
+ sensitive_data.host_keys[i] = tmp;
+ if (tmp->type == KEY_RSA1)
+ sensitive_data.ssh1_host_key = tmp;
+ }
+ }
+
+ /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */
+}
+
+static void
+privsep_preauth_child(void)
+{
+ u_int32_t rand[256];
+ int i;
+ struct passwd *pw;
+
+ /* Enable challenge-response authentication for privilege separation */
+ privsep_challenge_enable();
+
+ for (i = 0; i < 256; i++)
+ rand[i] = arc4random();
+ RAND_seed(rand, sizeof(rand));
+
+ /* Demote the private keys to public keys. */
+ demote_sensitive_data();
+
+ if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL)
+ fatal("Privilege separation user %s does not exist",
+ SSH_PRIVSEP_USER);
+ memset(pw->pw_passwd, 0, strlen(pw->pw_passwd));
+ endpwent();
+
+ /* Change our root directory*/
+ if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
+ fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
+ strerror(errno));
+ if (chdir("/") == -1)
+ fatal("chdir(\"/\"): %s", strerror(errno));
+
+ /* Drop our privileges */
+ debug3("privsep user:group %u:%u", (u_int)pw->pw_uid,
+ (u_int)pw->pw_gid);
+ do_setusercontext(pw);
+}
+
+static Authctxt*
+privsep_preauth(void)
+{
+ Authctxt *authctxt = NULL;
+ int status;
+ pid_t pid;
+
+ /* Set up unprivileged child process to deal with network data */
+ pmonitor = monitor_init();
+ /* Store a pointer to the kex for later rekeying */
+ pmonitor->m_pkex = &xxx_kex;
+
+ pid = fork();
+ if (pid == -1) {
+ fatal("fork of unprivileged child failed");
+ } else if (pid != 0) {
+ debug2("Network child is on pid %ld", (long)pid);
+
+ close(pmonitor->m_recvfd);
+ authctxt = monitor_child_preauth(pmonitor);
+ close(pmonitor->m_sendfd);
+
+ /* Sync memory */
+ monitor_sync(pmonitor);
+
+ /* Wait for the child's exit status */
+ while (waitpid(pid, &status, 0) < 0)
+ if (errno != EINTR)
+ break;
+ return (authctxt);
+ } else {
+ /* child */
+
+ close(pmonitor->m_sendfd);
+
+ /* Demote the child */
+ if (getuid() == 0 || geteuid() == 0)
+ privsep_preauth_child();
+ setproctitle("%s", "[net]");
+ }
+ return (NULL);
+}
+
+static void
+privsep_postauth(Authctxt *authctxt)
+{
+ extern Authctxt *x_authctxt;
+
+ /* XXX - Remote port forwarding */
+ x_authctxt = authctxt;
+
+ if (authctxt->pw->pw_uid == 0 || options.use_login) {
+ /* File descriptor passing is broken or root login */
+ monitor_apply_keystate(pmonitor);
+ use_privsep = 0;
+ return;
+ }
+
+ /* Authentication complete */
+ alarm(0);
+ if (startup_pipe != -1) {
+ close(startup_pipe);
+ startup_pipe = -1;
+ }
+
+ /* New socket pair */
+ monitor_reinit(pmonitor);
+
+ pmonitor->m_pid = fork();
+ if (pmonitor->m_pid == -1)
+ fatal("fork of unprivileged child failed");
+ else if (pmonitor->m_pid != 0) {
+ debug2("User child is on pid %ld", (long)pmonitor->m_pid);
+ close(pmonitor->m_recvfd);
+ monitor_child_postauth(pmonitor);
+
+ /* NEVERREACHED */
+ exit(0);
+ }
+
+ close(pmonitor->m_sendfd);
+
+ /* Demote the private keys to public keys. */
+ demote_sensitive_data();
+
+ /* Drop privileges */
+ do_setusercontext(authctxt->pw);
+
+ /* It is safe now to apply the key state */
+ monitor_apply_keystate(pmonitor);
+}
+
static char *
list_hostkey_types(void)
{
@@ -497,7 +666,7 @@ list_hostkey_types(void)
return p;
}
-static Key *
+Key *
get_hostkey_by_type(int type)
{
int i;
@@ -509,6 +678,25 @@ get_hostkey_by_type(int type)
return NULL;
}
+Key *
+get_hostkey_by_index(int ind)
+{
+ if (ind < 0 || ind >= options.num_host_key_files)
+ return (NULL);
+ return (sensitive_data.host_keys[ind]);
+}
+
+int
+get_hostkey_index(Key *key)
+{
+ int i;
+ for (i = 0; i < options.num_host_key_files; i++) {
+ if (key == sensitive_data.host_keys[i])
+ return (i);
+ }
+ return (-1);
+}
+
/*
* returns 1 if connection should be dropped, 0 otherwise.
* dropping starts at connection #max_startups_begin with a probability
@@ -585,6 +773,7 @@ main(int ac, char **av)
int listen_sock, maxfd;
int startup_p[2];
int startups = 0;
+ Authctxt *authctxt;
Key *key;
int ret, key_used = 0;
@@ -783,6 +972,19 @@ main(int ac, char **av)
}
}
+ if (use_privsep) {
+ struct passwd *pw;
+ struct stat st;
+
+ if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL)
+ fatal("Privilege separation user %s does not exist",
+ SSH_PRIVSEP_USER);
+ if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) ||
+ (S_ISDIR(st.st_mode) == 0))
+ fatal("Missing privilege separation directory: %s",
+ _PATH_PRIVSEP_CHROOT_DIR);
+ }
+
/* Configuration looks good, so exit if in test mode. */
if (test_flag)
exit(0);
@@ -929,7 +1131,7 @@ main(int ac, char **av)
*/
f = fopen(options.pid_file, "w");
if (f) {
- fprintf(f, "%u\n", (u_int) getpid());
+ fprintf(f, "%ld\n", (long) getpid());
fclose(f);
}
}
@@ -1076,7 +1278,7 @@ main(int ac, char **av)
if (pid < 0)
error("fork: %.100s", strerror(errno));
else
- debug("Forked child %d.", pid);
+ debug("Forked child %ld.", (long)pid);
close(startup_p[1]);
@@ -1103,6 +1305,14 @@ main(int ac, char **av)
/* This is the child processing a new connection. */
/*
+ * Create a new session and process group since the 4.4BSD
+ * setlogin() affects the entire process group. We don't
+ * want the child to be able to affect the parent.
+ */
+ if (setsid() < 0)
+ error("setsid: %.100s", strerror(errno));
+
+ /*
* Disable the key regeneration alarm. We will not regenerate the
* key since we are no longer in a position to give it to anyone. We
* will not restart on SIGHUP since it no longer makes sense.
@@ -1174,7 +1384,7 @@ main(int ac, char **av)
sshd_exchange_identification(sock_in, sock_out);
/*
* Check that the connection comes from a privileged port.
- * Rhosts-Authentication only makes sense from priviledged
+ * Rhosts-Authentication only makes sense from privileged
* programs. Of course, if the intruder has root access on his local
* machine, he can connect from any port. So do not use these
* authentication methods from machines that you do not trust.
@@ -1203,22 +1413,98 @@ main(int ac, char **av)
packet_set_nonblocking();
+ if (use_privsep)
+ if ((authctxt = privsep_preauth()) != NULL)
+ goto authenticated;
+
/* perform the key exchange */
/* authenticate user and start session */
if (compat20) {
do_ssh2_kex();
- do_authentication2();
+ authctxt = do_authentication2();
} else {
do_ssh1_kex();
- do_authentication();
+ authctxt = do_authentication();
+ }
+ /*
+ * If we use privilege separation, the unprivileged child transfers
+ * the current keystate and exits
+ */
+ if (use_privsep) {
+ mm_send_keystate(pmonitor);
+ exit(0);
+ }
+
+ authenticated:
+ /*
+ * In privilege separation, we fork another child and prepare
+ * file descriptor passing.
+ */
+ if (use_privsep) {
+ privsep_postauth(authctxt);
+ /* the monitor process [priv] will not return */
+ if (!compat20)
+ destroy_sensitive_data();
}
+
+ /* Perform session preparation. */
+ do_authenticated(authctxt);
+
/* The connection has been terminated. */
verbose("Closing connection to %.100s", remote_ip);
packet_close();
+
+ if (use_privsep)
+ mm_terminate();
+
exit(0);
}
/*
+ * Decrypt session_key_int using our private server key and private host key
+ * (key with larger modulus first).
+ */
+int
+ssh1_session_key(BIGNUM *session_key_int)
+{
+ int rsafail = 0;
+
+ if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) {
+ /* Server key has bigger modulus. */
+ if (BN_num_bits(sensitive_data.server_key->rsa->n) <
+ BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
+ fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
+ get_remote_ipaddr(),
+ BN_num_bits(sensitive_data.server_key->rsa->n),
+ BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
+ SSH_KEY_BITS_RESERVED);
+ }
+ if (rsa_private_decrypt(session_key_int, session_key_int,
+ sensitive_data.server_key->rsa) <= 0)
+ rsafail++;
+ if (rsa_private_decrypt(session_key_int, session_key_int,
+ sensitive_data.ssh1_host_key->rsa) <= 0)
+ rsafail++;
+ } else {
+ /* Host key has bigger modulus (or they are equal). */
+ if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
+ BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
+ fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",
+ get_remote_ipaddr(),
+ BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
+ BN_num_bits(sensitive_data.server_key->rsa->n),
+ SSH_KEY_BITS_RESERVED);
+ }
+ if (rsa_private_decrypt(session_key_int, session_key_int,
+ sensitive_data.ssh1_host_key->rsa) < 0)
+ rsafail++;
+ if (rsa_private_decrypt(session_key_int, session_key_int,
+ sensitive_data.server_key->rsa) < 0)
+ rsafail++;
+ }
+ return (rsafail);
+}
+/*
* SSH1 key exchange
*/
static void
@@ -1333,43 +1619,9 @@ do_ssh1_kex(void)
packet_set_protocol_flags(protocol_flags);
packet_check_eom();
- /*
- * Decrypt it using our private server key and private host key (key
- * with larger modulus first).
- */
- if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) {
- /* Server key has bigger modulus. */
- if (BN_num_bits(sensitive_data.server_key->rsa->n) <
- BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
- fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
- get_remote_ipaddr(),
- BN_num_bits(sensitive_data.server_key->rsa->n),
- BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
- SSH_KEY_BITS_RESERVED);
- }
- if (rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.server_key->rsa) <= 0)
- rsafail++;
- if (rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.ssh1_host_key->rsa) <= 0)
- rsafail++;
- } else {
- /* Host key has bigger modulus (or they are equal). */
- if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
- BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
- fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",
- get_remote_ipaddr(),
- BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
- BN_num_bits(sensitive_data.server_key->rsa->n),
- SSH_KEY_BITS_RESERVED);
- }
- if (rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.ssh1_host_key->rsa) < 0)
- rsafail++;
- if (rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.server_key->rsa) < 0)
- rsafail++;
- }
+ /* Decrypt session_key_int using host/server keys */
+ rsafail = PRIVSEP(ssh1_session_key(session_key_int));
+
/*
* Extract session key from the decrypted integer. The key is in the
* least significant 256 bits of the integer; the first byte of the
@@ -1420,9 +1672,12 @@ do_ssh1_kex(void)
for (i = 0; i < 16; i++)
session_id[i] = session_key[i] ^ session_key[i + 16];
}
- /* Destroy the private and public keys. They will no longer be needed. */
+ /* Destroy the private and public keys. No longer. */
destroy_sensitive_data();
+ if (use_privsep)
+ mm_ssh1_session_id(session_id);
+
/* Destroy the decrypted integer. It is no longer needed. */
BN_clear_free(session_key_int);
@@ -1434,7 +1689,7 @@ do_ssh1_kex(void)
debug("Received session key; encryption turned on.");
- /* Send an acknowledgement packet. Note that this packet is sent encrypted. */
+ /* Send an acknowledgment packet. Note that this packet is sent encrypted. */
packet_start(SSH_SMSG_SUCCESS);
packet_send();
packet_write_wait();
@@ -1461,6 +1716,10 @@ do_ssh2_kex(void)
myproposal[PROPOSAL_MAC_ALGS_CTOS] =
myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
}
+ if (!options.compression) {
+ myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+ myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
+ }
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
/* start key exchange */
@@ -1469,6 +1728,7 @@ do_ssh2_kex(void)
kex->client_version_string=client_version_string;
kex->server_version_string=server_version_string;
kex->load_host_key=&get_hostkey_by_type;
+ kex->host_key_index=&get_hostkey_index;
xxx_kex = kex;
diff --git a/crypto/openssh/sshd/Makefile b/crypto/openssh/sshd/Makefile
index 8fdd8e6..14ef3e0 100644
--- a/crypto/openssh/sshd/Makefile
+++ b/crypto/openssh/sshd/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.46 2002/03/05 00:49:51 deraadt Exp $
+# $OpenBSD: Makefile,v 1.51 2002/06/20 19:56:07 stevesk Exp $
.PATH: ${.CURDIR}/..
@@ -6,14 +6,16 @@ PROG= sshd
BINOWN= root
BINMODE=555
BINDIR= /usr/sbin
-MAN= sshd.8
+MAN= sshd.8 sshd_config.5
CFLAGS+=-DHAVE_LOGIN_CAP -DBSD_AUTH
SRCS= sshd.c auth-rhosts.c auth-passwd.c auth-rsa.c auth-rh-rsa.c \
- sshpty.c sshlogin.c servconf.c serverloop.c \
+ sshpty.c sshlogin.c servconf.c serverloop.c uidswap.c \
auth.c auth1.c auth2.c auth-options.c session.c \
auth-chall.c auth2-chall.c groupaccess.c \
- auth-skey.c auth-bsdauth.c
+ auth-skey.c auth-bsdauth.c monitor_mm.c monitor.c \
+ auth2-none.c auth2-passwd.c auth2-pubkey.c \
+ auth2-hostbased.c auth2-kbdint.c
.include <bsd.own.mk> # for KERBEROS and AFS
@@ -21,14 +23,14 @@ SRCS= sshd.c auth-rhosts.c auth-passwd.c auth-rsa.c auth-rh-rsa.c \
CFLAGS+=-DKRB5 -I${DESTDIR}/usr/include/kerberosV
SRCS+= auth-krb5.c
LDADD+= -lkrb5 -lkafs -lasn1 -lcom_err
-DPADD+= ${LIBKRB5} ${LIBKAFS} ${LIBASN1}
+DPADD+= ${LIBKRB5} ${LIBKAFS} ${LIBASN1} ${LIBCOM_ERR}
.endif # KERBEROS5
.if (${KERBEROS:L} == "yes")
.if (${AFS:L} == "yes")
CFLAGS+= -DAFS
LDADD+= -lkafs
-DPADD+= ${LIBKRBAFS}
+DPADD+= ${LIBKAFS}
.endif # AFS
CFLAGS+= -DKRB4 -I${DESTDIR}/usr/include/kerberosIV
SRCS+= auth-krb4.c
@@ -39,7 +41,7 @@ DPADD+= ${LIBKRB}
.include <bsd.prog.mk>
LDADD+= -lcrypto -lutil -lz -ldes
-DPADD+= ${LIBCRYPTO} ${LIBUTIL} ${LIBZ}
+DPADD+= ${LIBCRYPTO} ${LIBUTIL} ${LIBZ} ${LIBDES}
.if (${TCP_WRAPPERS:L} == "yes")
CFLAGS+= -DLIBWRAP
diff --git a/crypto/openssh/sshd_config b/crypto/openssh/sshd_config
index 4529861..240cae4 100644
--- a/crypto/openssh/sshd_config
+++ b/crypto/openssh/sshd_config
@@ -1,7 +1,7 @@
-# $OpenBSD: sshd_config,v 1.48 2002/02/19 02:50:59 deraadt Exp $
+# $OpenBSD: sshd_config,v 1.56 2002/06/20 23:37:12 markus Exp $
-# This is the sshd server system-wide configuration file. See sshd(8)
-# for more information.
+# This is the sshd server system-wide configuration file. See
+# sshd_config(5) for more information.
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
@@ -58,13 +58,11 @@
#ChallengeResponseAuthentication yes
# Kerberos options
-# KerberosAuthentication automatically enabled if keyfile exists
-#KerberosAuthentication yes
+#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
-# AFSTokenPassing automatically enabled if k_hasafs() is true
-#AFSTokenPassing yes
+#AFSTokenPassing no
# Kerberos TGT Passing only works with the AFS kaserver
#KerberosTgtPassing no
@@ -76,6 +74,8 @@
#PrintLastLog yes
#KeepAlive yes
#UseLogin no
+#UsePrivilegeSeparation yes
+#Compression yes
#MaxStartups 10
# no default banner path
diff --git a/crypto/openssh/sshd_config.5 b/crypto/openssh/sshd_config.5
new file mode 100644
index 0000000..efa1305
--- /dev/null
+++ b/crypto/openssh/sshd_config.5
@@ -0,0 +1,707 @@
+.\" -*- nroff -*-
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\" All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose. Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: sshd_config.5,v 1.3 2002/06/20 23:37:12 markus Exp $
+.Dd September 25, 1999
+.Dt SSHD_CONFIG 5
+.Os
+.Sh NAME
+.Nm sshd_config
+.Nd OpenSSH SSH daemon configuration file
+.Sh SYNOPSIS
+.Bl -tag -width Ds -compact
+.It Pa /etc/ssh/sshd_config
+.El
+.Sh DESCRIPTION
+.Nm sshd
+reads configuration data from
+.Pa /etc/ssh/sshd_config
+(or the file specified with
+.Fl f
+on the command line).
+The file contains keyword-argument pairs, one per line.
+Lines starting with
+.Ql #
+and empty lines are interpreted as comments.
+.Pp
+The possible
+keywords and their meanings are as follows (note that
+keywords are case-insensitive and arguments are case-sensitive):
+.Bl -tag -width Ds
+.It Cm AFSTokenPassing
+Specifies whether an AFS token may be forwarded to the server.
+Default is
+.Dq no .
+.It Cm AllowGroups
+This keyword can be followed by a list of group name patterns, separated
+by spaces.
+If specified, login is allowed only for users whose primary
+group or supplementary group list matches one of the patterns.
+.Ql \&*
+and
+.Ql ?
+can be used as
+wildcards in the patterns.
+Only group names are valid; a numerical group ID is not recognized.
+By default, login is allowed for all groups.
+.Pp
+.It Cm AllowTcpForwarding
+Specifies whether TCP forwarding is permitted.
+The default is
+.Dq yes .
+Note that disabling TCP forwarding does not improve security unless
+users are also denied shell access, as they can always install their
+own forwarders.
+.Pp
+.It Cm AllowUsers
+This keyword can be followed by a list of user name patterns, separated
+by spaces.
+If specified, login is allowed only for users names that
+match one of the patterns.
+.Ql \&*
+and
+.Ql ?
+can be used as
+wildcards in the patterns.
+Only user names are valid; a numerical user ID is not recognized.
+By default, login is allowed for all users.
+If the pattern takes the form USER@HOST then USER and HOST
+are separately checked, restricting logins to particular
+users from particular hosts.
+.Pp
+.It Cm AuthorizedKeysFile
+Specifies the file that contains the public keys that can be used
+for user authentication.
+.Cm AuthorizedKeysFile
+may contain tokens of the form %T which are substituted during connection
+set-up. The following tokens are defined: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated and
+%u is replaced by the username of that user.
+After expansion,
+.Cm AuthorizedKeysFile
+is taken to be an absolute path or one relative to the user's home
+directory.
+The default is
+.Dq .ssh/authorized_keys .
+.It Cm Banner
+In some jurisdictions, sending a warning message before authentication
+may be relevant for getting legal protection.
+The contents of the specified file are sent to the remote user before
+authentication is allowed.
+This option is only available for protocol version 2.
+By default, no banner is displayed.
+.Pp
+.It Cm ChallengeResponseAuthentication
+Specifies whether challenge response authentication is allowed.
+All authentication styles from
+.Xr login.conf 5
+are supported.
+The default is
+.Dq yes .
+.It Cm Ciphers
+Specifies the ciphers allowed for protocol version 2.
+Multiple ciphers must be comma-separated.
+The default is
+.Pp
+.Bd -literal
+ ``aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,
+ aes192-cbc,aes256-cbc''
+.Ed
+.It Cm ClientAliveInterval
+Sets a timeout interval in seconds after which if no data has been received
+from the client,
+.Nm sshd
+will send a message through the encrypted
+channel to request a response from the client.
+The default
+is 0, indicating that these messages will not be sent to the client.
+This option applies to protocol version 2 only.
+.It Cm ClientAliveCountMax
+Sets the number of client alive messages (see above) which may be
+sent without
+.Nm sshd
+receiving any messages back from the client. If this threshold is
+reached while client alive messages are being sent,
+.Nm sshd
+will disconnect the client, terminating the session. It is important
+to note that the use of client alive messages is very different from
+.Cm KeepAlive
+(below). The client alive messages are sent through the
+encrypted channel and therefore will not be spoofable. The TCP keepalive
+option enabled by
+.Cm KeepAlive
+is spoofable. The client alive mechanism is valuable when the client or
+server depend on knowing when a connection has become inactive.
+.Pp
+The default value is 3. If
+.Cm ClientAliveInterval
+(above) is set to 15, and
+.Cm ClientAliveCountMax
+is left at the default, unresponsive ssh clients
+will be disconnected after approximately 45 seconds.
+.It Cm Compression
+Specifies whether compression is allowed.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm DenyGroups
+This keyword can be followed by a list of group name patterns, separated
+by spaces.
+Login is disallowed for users whose primary group or supplementary
+group list matches one of the patterns.
+.Ql \&*
+and
+.Ql ?
+can be used as
+wildcards in the patterns.
+Only group names are valid; a numerical group ID is not recognized.
+By default, login is allowed for all groups.
+.Pp
+.It Cm DenyUsers
+This keyword can be followed by a list of user name patterns, separated
+by spaces.
+Login is disallowed for user names that match one of the patterns.
+.Ql \&*
+and
+.Ql ?
+can be used as wildcards in the patterns.
+Only user names are valid; a numerical user ID is not recognized.
+By default, login is allowed for all users.
+If the pattern takes the form USER@HOST then USER and HOST
+are separately checked, restricting logins to particular
+users from particular hosts.
+.It Cm GatewayPorts
+Specifies whether remote hosts are allowed to connect to ports
+forwarded for the client.
+By default,
+.Nm sshd
+binds remote port forwardings to the loopback address. This
+prevents other remote hosts from connecting to forwarded ports.
+.Cm GatewayPorts
+can be used to specify that
+.Nm sshd
+should bind remote port forwardings to the wildcard address,
+thus allowing remote hosts to connect to forwarded ports.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm HostbasedAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful public key client host authentication is allowed
+(hostbased authentication).
+This option is similar to
+.Cm RhostsRSAAuthentication
+and applies to protocol version 2 only.
+The default is
+.Dq no .
+.It Cm HostKey
+Specifies a file containing a private host key
+used by SSH.
+The default is
+.Pa /etc/ssh/ssh_host_key
+for protocol version 1, and
+.Pa /etc/ssh/ssh_host_rsa_key
+and
+.Pa /etc/ssh/ssh_host_dsa_key
+for protocol version 2.
+Note that
+.Nm sshd
+will refuse to use a file if it is group/world-accessible.
+It is possible to have multiple host key files.
+.Dq rsa1
+keys are used for version 1 and
+.Dq dsa
+or
+.Dq rsa
+are used for version 2 of the SSH protocol.
+.It Cm IgnoreRhosts
+Specifies that
+.Pa .rhosts
+and
+.Pa .shosts
+files will not be used in
+.Cm RhostsAuthentication ,
+.Cm RhostsRSAAuthentication
+or
+.Cm HostbasedAuthentication .
+.Pp
+.Pa /etc/hosts.equiv
+and
+.Pa /etc/shosts.equiv
+are still used.
+The default is
+.Dq yes .
+.It Cm IgnoreUserKnownHosts
+Specifies whether
+.Nm sshd
+should ignore the user's
+.Pa $HOME/.ssh/known_hosts
+during
+.Cm RhostsRSAAuthentication
+or
+.Cm HostbasedAuthentication .
+The default is
+.Dq no .
+.It Cm KeepAlive
+Specifies whether the system should send TCP keepalive messages to the
+other side.
+If they are sent, death of the connection or crash of one
+of the machines will be properly noticed.
+However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+On the other hand, if keepalives are not sent,
+sessions may hang indefinitely on the server, leaving
+.Dq ghost
+users and consuming server resources.
+.Pp
+The default is
+.Dq yes
+(to send keepalives), and the server will notice
+if the network goes down or the client host crashes.
+This avoids infinitely hanging sessions.
+.Pp
+To disable keepalives, the value should be set to
+.Dq no .
+.It Cm KerberosAuthentication
+Specifies whether Kerberos authentication is allowed.
+This can 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.
+To use this option, the server needs a
+Kerberos servtab which allows the verification of the KDC's identity.
+Default is
+.Dq no .
+.It Cm KerberosOrLocalPasswd
+If set then if password authentication through Kerberos fails then
+the password will be validated via any additional local mechanism
+such as
+.Pa /etc/passwd .
+Default is
+.Dq yes .
+.It Cm KerberosTgtPassing
+Specifies whether a Kerberos TGT may be forwarded to the server.
+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
+.Dq yes .
+.It Cm KeyRegenerationInterval
+In protocol version 1, the ephemeral server key is automatically regenerated
+after this many seconds (if it has been used).
+The purpose of regeneration is to prevent
+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 the local addresses
+.Nm sshd
+should listen on.
+The following forms may be used:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm ListenAddress
+.Sm off
+.Ar host No | Ar IPv4_addr No | Ar IPv6_addr
+.Sm on
+.It
+.Cm ListenAddress
+.Sm off
+.Ar host No | Ar IPv4_addr No : Ar port
+.Sm on
+.It
+.Cm ListenAddress
+.Sm off
+.Oo
+.Ar host No | Ar IPv6_addr Oc : Ar port
+.Sm on
+.El
+.Pp
+If
+.Ar port
+is not specified,
+.Nm sshd
+will listen on the address and all prior
+.Cm Port
+options specified. The default is to listen on all local
+addresses. Multiple
+.Cm ListenAddress
+options are permitted. Additionally, any
+.Cm Port
+options must precede this option for non port qualified 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.
+The default is 600 (seconds).
+.It Cm LogLevel
+Gives the verbosity level that is used when logging messages from
+.Nm sshd .
+The possible values are:
+QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2 and DEBUG3.
+The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2
+and DEBUG3 each specify higher levels of debugging output.
+Logging with a DEBUG level violates the privacy of users
+and is not recommended.
+.It Cm MACs
+Specifies the available MAC (message authentication code) algorithms.
+The MAC algorithm is used in protocol version 2
+for data integrity protection.
+Multiple algorithms must be comma-separated.
+The default is
+.Dq hmac-md5,hmac-sha1,hmac-ripemd160,hmac-sha1-96,hmac-md5-96 .
+.It Cm MaxStartups
+Specifies the maximum number of concurrent unauthenticated connections to the
+.Nm sshd
+daemon.
+Additional connections will be dropped until authentication succeeds or the
+.Cm LoginGraceTime
+expires for a connection.
+The default is 10.
+.Pp
+Alternatively, random early drop can be enabled by specifying
+the three colon separated values
+.Dq start:rate:full
+(e.g., "10:30:60").
+.Nm sshd
+will refuse connection attempts with a probability of
+.Dq rate/100
+(30%)
+if there are currently
+.Dq start
+(10)
+unauthenticated connections.
+The probability increases linearly and all connection attempts
+are refused if the number of unauthenticated connections reaches
+.Dq full
+(60).
+.It Cm PasswordAuthentication
+Specifies whether password authentication is allowed.
+The default is
+.Dq yes .
+.It Cm PermitEmptyPasswords
+When password authentication is allowed, it specifies whether the
+server allows login to accounts with empty password strings.
+The default is
+.Dq no .
+.It Cm PermitRootLogin
+Specifies whether root can login using
+.Xr ssh 1 .
+The argument must be
+.Dq yes ,
+.Dq without-password ,
+.Dq forced-commands-only
+or
+.Dq no .
+The default is
+.Dq yes .
+.Pp
+If this option is set to
+.Dq without-password
+password authentication is disabled for root.
+.Pp
+If this option is set to
+.Dq forced-commands-only
+root login with public key authentication will be allowed,
+but only if the
+.Ar command
+option has been specified
+(which may be useful for taking remote backups even if root login is
+normally not allowed). All other authentication methods are disabled
+for root.
+.Pp
+If this option is set to
+.Dq no
+root is not allowed to login.
+.It Cm PidFile
+Specifies the file that contains the process identifier of the
+.Nm sshd
+daemon.
+The default is
+.Pa /var/run/sshd.pid .
+.It Cm Port
+Specifies the port number that
+.Nm sshd
+listens on.
+The default is 22.
+Multiple options of this type are permitted.
+See also
+.Cm ListenAddress .
+.It Cm PrintLastLog
+Specifies whether
+.Nm sshd
+should print the date and time when the user last logged in.
+The default is
+.Dq yes .
+.It Cm PrintMotd
+Specifies whether
+.Nm sshd
+should print
+.Pa /etc/motd
+when a user logs in interactively.
+(On some systems it is also printed by the shell,
+.Pa /etc/profile ,
+or equivalent.)
+The default is
+.Dq yes .
+.It Cm Protocol
+Specifies the protocol versions
+.Nm sshd
+should support.
+The possible values are
+.Dq 1
+and
+.Dq 2 .
+Multiple versions must be comma-separated.
+The default is
+.Dq 2,1 .
+.It Cm PubkeyAuthentication
+Specifies whether public key authentication is allowed.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.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.
+.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
+.Dq no .
+This option applies to protocol version 1 only.
+.It Cm RhostsRSAAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful RSA host authentication is allowed.
+The default is
+.Dq no .
+This option applies to protocol version 1 only.
+.It Cm RSAAuthentication
+Specifies whether pure RSA authentication is allowed.
+The default is
+.Dq yes .
+This option applies to protocol version 1 only.
+.It Cm ServerKeyBits
+Defines the number of bits in the ephemeral protocol version 1 server key.
+The minimum value is 512, and the default is 768.
+.It Cm StrictModes
+Specifies whether
+.Nm sshd
+should check file modes and ownership of the
+user's files and home directory before accepting login.
+This is normally desirable because novices sometimes accidentally leave their
+directory or files world-writable.
+The default is
+.Dq yes .
+.It Cm Subsystem
+Configures an external subsystem (e.g., file transfer daemon).
+Arguments should be a subsystem name and a command to execute upon subsystem
+request.
+The command
+.Xr sftp-server 8
+implements the
+.Dq sftp
+file transfer subsystem.
+By default no subsystems are defined.
+Note that this option applies to protocol version 2 only.
+.It Cm SyslogFacility
+Gives the facility code that is used when logging messages from
+.Nm sshd .
+The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+The default is AUTH.
+.It Cm UseLogin
+Specifies whether
+.Xr login 1
+is used for interactive login sessions.
+The default is
+.Dq no .
+Note that
+.Xr login 1
+is never used for remote command execution.
+Note also, that if this is enabled,
+.Cm X11Forwarding
+will be disabled because
+.Xr login 1
+does not know how to handle
+.Xr xauth 1
+cookies. If
+.Cm UsePrivilegeSeparation
+is specified, it will be disabled after authentication.
+.It Cm UsePrivilegeSeparation
+Specifies whether
+.Nm sshd
+separates privileges by creating an unprivileged child process
+to deal with incoming network traffic. After successful authentication,
+another process will be created that has the privilege of the authenticated
+user. The goal of privilege separation is to prevent privilege
+escalation by containing any corruption within the unprivileged processes.
+The default is
+.Dq yes .
+.It Cm VerifyReverseMapping
+Specifies whether
+.Nm sshd
+should try to verify the remote host name and check that
+the resolved host name for the remote IP address maps back to the
+very same IP address.
+The default is
+.Dq no .
+.It Cm X11DisplayOffset
+Specifies the first display number available for
+.Nm sshd Ns 's
+X11 forwarding.
+This prevents
+.Nm sshd
+from interfering with real X11 servers.
+The default is 10.
+.It Cm X11Forwarding
+Specifies whether X11 forwarding is permitted.
+The default is
+.Dq no .
+Note that disabling X11 forwarding does not improve security in any
+way, as users can always install their own forwarders.
+X11 forwarding is automatically disabled if
+.Cm UseLogin
+is enabled.
+.It Cm X11UseLocalhost
+Specifies whether
+.Nm sshd
+should bind the X11 forwarding server to the loopback address or to
+the wildcard address. By default,
+.Nm sshd
+binds the forwarding server to the loopback address and sets the
+hostname part of the
+.Ev DISPLAY
+environment variable to
+.Dq localhost .
+This prevents remote hosts from connecting to the fake display.
+However, some older X11 clients may not function with this
+configuration.
+.Cm X11UseLocalhost
+may be set to
+.Dq no
+to specify that the forwarding server should be bound to the wildcard
+address.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm XAuthLocation
+Specifies the location of the
+.Xr xauth 1
+program.
+The default is
+.Pa /usr/X11R6/bin/xauth .
+.El
+.Ss Time Formats
+.Pp
+.Nm sshd
+command-line arguments and configuration file options that specify time
+may be expressed using a sequence of the form:
+.Sm off
+.Ar time Oo Ar qualifier Oc ,
+.Sm on
+where
+.Ar time
+is a positive integer value and
+.Ar qualifier
+is one of the following:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It Cm <none>
+seconds
+.It Cm s | Cm S
+seconds
+.It Cm m | Cm M
+minutes
+.It Cm h | Cm H
+hours
+.It Cm d | Cm D
+days
+.It Cm w | Cm W
+weeks
+.El
+.Pp
+Each member of the sequence is added together to calculate
+the total time value.
+.Pp
+Time format examples:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It 600
+600 seconds (10 minutes)
+.It 10m
+10 minutes
+.It 1h30m
+1 hour 30 minutes (90 minutes)
+.El
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa /etc/ssh/sshd_config
+Contains configuration data for
+.Nm sshd .
+This file should be writable by root only, but it is recommended
+(though not necessary) that it be world-readable.
+.El
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
+Niels Provos and Markus Friedl contributed support
+for privilege separation.
+.Sh SEE ALSO
+.Xr sshd 8
diff --git a/crypto/openssh/ttymodes.c b/crypto/openssh/ttymodes.c
index ccc001f..5cc13dc 100644
--- a/crypto/openssh/ttymodes.c
+++ b/crypto/openssh/ttymodes.c
@@ -43,7 +43,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: ttymodes.c,v 1.16 2001/12/27 20:39:58 markus Exp $");
+RCSID("$OpenBSD: ttymodes.c,v 1.18 2002/06/19 00:27:55 deraadt Exp $");
#include "packet.h"
#include "log.h"
@@ -307,7 +307,6 @@ end:
else
packet_put_raw(buffer_ptr(&buf), buffer_len(&buf));
buffer_free(&buf);
- return;
}
/*
@@ -402,17 +401,17 @@ tty_parse_modes(int fd, int *n_bytes_ptr)
* SSH1:
* Opcodes 1 to 127 are defined to have
* a one-byte argument.
- * Opcodes 128 to 159 are defined to have
- * an integer argument.
- */
+ * Opcodes 128 to 159 are defined to have
+ * an integer argument.
+ */
if (opcode > 0 && opcode < 128) {
n_bytes += 1;
(void) packet_get_char();
break;
} else if (opcode >= 128 && opcode < 160) {
- n_bytes += 4;
- (void) packet_get_int();
- break;
+ n_bytes += 4;
+ (void) packet_get_int();
+ break;
} else {
/*
* It is a truly undefined opcode (160 to 255).
@@ -423,7 +422,7 @@ tty_parse_modes(int fd, int *n_bytes_ptr)
*/
log("parse_tty_modes: unknown opcode %d", opcode);
goto set;
- }
+ }
} else {
/*
* SSH2:
@@ -440,7 +439,7 @@ tty_parse_modes(int fd, int *n_bytes_ptr)
log("parse_tty_modes: unknown opcode %d", opcode);
goto set;
}
- }
+ }
}
}
@@ -457,5 +456,4 @@ set:
/* Set the new modes for the terminal. */
if (tcsetattr(fd, TCSANOW, &tio) == -1)
log("Setting tty modes failed: %.100s", strerror(errno));
- return;
}
diff --git a/crypto/openssh/uidswap.c b/crypto/openssh/uidswap.c
index e794fac..ab43cba 100644
--- a/crypto/openssh/uidswap.c
+++ b/crypto/openssh/uidswap.c
@@ -12,7 +12,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: uidswap.c,v 1.19 2001/12/19 07:18:56 deraadt Exp $");
+RCSID("$OpenBSD: uidswap.c,v 1.22 2002/05/28 21:24:00 stevesk Exp $");
#include "log.h"
#include "uidswap.h"
@@ -46,8 +46,8 @@ temporarily_use_uid(struct passwd *pw)
{
/* Save the current euid, and egroups. */
saved_euid = geteuid();
- debug("temporarily_use_uid: %d/%d (e=%d)",
- pw->pw_uid, pw->pw_gid, saved_euid);
+ debug("temporarily_use_uid: %u/%u (e=%u)",
+ (u_int)pw->pw_uid, (u_int)pw->pw_gid, (u_int)saved_euid);
if (saved_euid != 0) {
privileged = 0;
return;
@@ -71,12 +71,11 @@ temporarily_use_uid(struct passwd *pw)
/* Set the effective uid to the given (unprivileged) uid. */
if (setgroups(user_groupslen, user_groups) < 0)
fatal("setgroups: %.100s", strerror(errno));
- pw->pw_gid = pw->pw_gid;
if (setegid(pw->pw_gid) < 0)
- fatal("setegid %u: %.100s", (u_int) pw->pw_gid,
+ fatal("setegid %u: %.100s", (u_int)pw->pw_gid,
strerror(errno));
if (seteuid(pw->pw_uid) == -1)
- fatal("seteuid %u: %.100s", (u_int) pw->pw_uid,
+ fatal("seteuid %u: %.100s", (u_int)pw->pw_uid,
strerror(errno));
}
@@ -94,11 +93,11 @@ restore_uid(void)
fatal("restore_uid: temporarily_use_uid not effective");
/* Set the effective uid back to the saved privileged uid. */
if (seteuid(saved_euid) < 0)
- fatal("seteuid %u: %.100s", (u_int) saved_euid, strerror(errno));
+ fatal("seteuid %u: %.100s", (u_int)saved_euid, strerror(errno));
if (setgroups(saved_egroupslen, saved_egroups) < 0)
fatal("setgroups: %.100s", strerror(errno));
if (setegid(saved_egid) < 0)
- fatal("setegid %u: %.100s", (u_int) saved_egid, strerror(errno));
+ fatal("setegid %u: %.100s", (u_int)saved_egid, strerror(errno));
temporarily_use_uid_effective = 0;
}
@@ -110,9 +109,9 @@ void
permanently_set_uid(struct passwd *pw)
{
if (temporarily_use_uid_effective)
- fatal("restore_uid: temporarily_use_uid effective");
+ fatal("permanently_set_uid: temporarily_use_uid effective");
if (setgid(pw->pw_gid) < 0)
- fatal("setgid %u: %.100s", (u_int) pw->pw_gid, strerror(errno));
+ fatal("setgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno));
if (setuid(pw->pw_uid) < 0)
- fatal("setuid %u: %.100s", (u_int) pw->pw_uid, strerror(errno));
+ fatal("setuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno));
}
diff --git a/crypto/openssh/version.h b/crypto/openssh/version.h
index b11977f..5c8ec45 100644
--- a/crypto/openssh/version.h
+++ b/crypto/openssh/version.h
@@ -1,3 +1,3 @@
-/* $OpenBSD: version.h,v 1.28 2002/03/06 00:25:55 markus Exp $ */
+/* $OpenBSD: version.h,v 1.33 2002/06/21 15:41:20 markus Exp $ */
-#define SSH_VERSION "OpenSSH_3.1"
+#define SSH_VERSION "OpenSSH_3.3"
diff --git a/crypto/openssh/xmalloc.h b/crypto/openssh/xmalloc.h
index 338a2d2..7ac4b13 100644
--- a/crypto/openssh/xmalloc.h
+++ b/crypto/openssh/xmalloc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: xmalloc.h,v 1.8 2002/03/04 17:27:39 stevesk Exp $ */
+/* $OpenBSD: xmalloc.h,v 1.9 2002/06/19 00:27:55 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -22,6 +22,6 @@
void *xmalloc(size_t);
void *xrealloc(void *, size_t);
void xfree(void *);
-char *xstrdup(const char *);
+char *xstrdup(const char *);
#endif /* XMALLOC_H */
OpenPOWER on IntegriCloud