aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2002-06-23 16:09:08 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2002-06-23 16:09:08 +0000
commit80628bacb0b4bc1daaef4e038e755602c972bede (patch)
treecc93abce4a81ab84afa26d861b756d5c77818afa
parentf191b6f96cdb3270a60bcb6219ce0998bdd25cde (diff)
downloadsrc-80628bacb0b4bc1daaef4e038e755602c972bede.tar.gz
src-80628bacb0b4bc1daaef4e038e755602c972bede.zip
Resolve conflicts. Known issues:
- sshd fails to set TERM correctly. - privilege separation may break PAM and is currently turned off. - man pages have not yet been updated I will have these issues resolved, and privilege separation turned on by default, in time for DP2. Sponsored by: DARPA, NAI Labs
Notes
Notes: svn path=/head/; revision=98684
-rw-r--r--crypto/openssh/LICENCE3
-rw-r--r--crypto/openssh/auth-krb4.c7
-rw-r--r--crypto/openssh/auth-krb5.c27
-rw-r--r--crypto/openssh/auth-passwd.c23
-rw-r--r--crypto/openssh/auth-rh-rsa.c59
-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.c51
-rw-r--r--crypto/openssh/auth2-chall.c23
-rw-r--r--crypto/openssh/auth2.c563
-rw-r--r--crypto/openssh/authfd.c56
-rw-r--r--crypto/openssh/authfile.c4
-rw-r--r--crypto/openssh/bufaux.c28
-rw-r--r--crypto/openssh/canohost.c7
-rw-r--r--crypto/openssh/channels.c134
-rw-r--r--crypto/openssh/channels.h16
-rw-r--r--crypto/openssh/cipher.c192
-rw-r--r--crypto/openssh/cipher.h9
-rw-r--r--crypto/openssh/compat.c30
-rw-r--r--crypto/openssh/compat.h4
-rw-r--r--crypto/openssh/key.c49
-rw-r--r--crypto/openssh/monitor.c11
-rw-r--r--crypto/openssh/myproposal.h4
-rw-r--r--crypto/openssh/packet.h13
-rw-r--r--crypto/openssh/pathnames.h8
-rw-r--r--crypto/openssh/readconf.c40
-rw-r--r--crypto/openssh/readconf.h4
-rw-r--r--crypto/openssh/servconf.c29
-rw-r--r--crypto/openssh/servconf.h4
-rw-r--r--crypto/openssh/serverloop.c25
-rw-r--r--crypto/openssh/session.c305
-rw-r--r--crypto/openssh/ssh-add.c83
-rw-r--r--crypto/openssh/ssh-agent.c356
-rw-r--r--crypto/openssh/ssh.c219
-rw-r--r--crypto/openssh/ssh.h14
-rw-r--r--crypto/openssh/ssh_config18
-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.c358
-rw-r--r--crypto/openssh/sshd_config16
-rw-r--r--crypto/openssh/version.h6
45 files changed, 2059 insertions, 1424 deletions
diff --git a/crypto/openssh/LICENCE b/crypto/openssh/LICENCE
index c347446d285c..0e4f97776c8a 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
@@ -253,3 +255,4 @@ OpenSSH contains no GPL code.
* SUCH DAMAGE.
$FreeBSD$
+
diff --git a/crypto/openssh/auth-krb4.c b/crypto/openssh/auth-krb4.c
index 745b9c5175fb..97d2908803e4 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 $");
RCSID("$FreeBSD$");
#include "ssh.h"
@@ -58,8 +58,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. */
@@ -254,6 +254,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 ff23c9870fbc..94344a69cc31 100644
--- a/crypto/openssh/auth-krb5.c
+++ b/crypto/openssh/auth-krb5.c
@@ -1,9 +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 $");
RCSID("$FreeBSD$");
#include "ssh.h"
diff --git a/crypto/openssh/auth-passwd.c b/crypto/openssh/auth-passwd.c
index ab7447f7bec3..ec1b0967df6c 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 $");
RCSID("$FreeBSD$");
#include "packet.h"
@@ -55,7 +55,6 @@ int
auth_password(Authctxt *authctxt, const char *password)
{
struct passwd * pw = authctxt->pw;
- char *encrypted_password;
/* deny if no user. */
if (pw == NULL)
@@ -86,14 +85,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 e9852191d49a..e74ef3d944e0 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 $");
RCSID("$FreeBSD$");
#include "packet.h"
@@ -26,37 +26,48 @@ RCSID("$FreeBSD$");
#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;
@@ -64,9 +75,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;
}
/*
@@ -75,7 +86,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-rsa.c b/crypto/openssh/auth-rsa.c
index 77ea57b583b3..17d7ae924928 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 $");
RCSID("$FreeBSD$");
#include <openssl/rsa.h>
@@ -33,6 +33,8 @@ RCSID("$FreeBSD$");
#include "servconf.h"
#include "auth.h"
#include "hostfile.h"
+#include "monitor_wrap.h"
+#include "ssh.h"
/* import */
extern ServerOptions options;
@@ -53,6 +55,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
@@ -60,29 +114,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);
@@ -97,48 +141,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);
@@ -152,29 +174,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);
@@ -239,32 +259,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;
}
@@ -275,13 +271,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 b538b395a25c..18243ee7693d 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 $");
RCSID("$FreeBSD$");
#ifdef SKEY
@@ -31,6 +31,7 @@ RCSID("$FreeBSD$");
#include "xmalloc.h"
#include "auth.h"
+#include "monitor_wrap.h"
static void *
skey_init_ctx(Authctxt *authctxt)
@@ -38,9 +39,7 @@ skey_init_ctx(Authctxt *authctxt)
return authctxt;
}
-#define PROMPT "\nOPIE Password: "
-
-static int
+int
skey_query(void *ctx, char **name, char **infotxt,
u_int* numprompts, char ***prompts, u_int **echo_on)
{
@@ -54,23 +53,23 @@ skey_query(void *ctx, char **name, char **infotxt,
if (opiechallenge(&opie, 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;
@@ -96,4 +95,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 79332a81f2f3..fbd1361d69f0 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 $");
RCSID("$FreeBSD$");
#include <libgen.h>
@@ -40,10 +40,17 @@ RCSID("$FreeBSD$");
#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
@@ -77,7 +84,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;
@@ -91,17 +99,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 */
@@ -387,3 +395,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 a6265f3947cf..3fc7954aec7e 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 $ */
/* $FreeBSD$ */
/*
@@ -44,6 +44,7 @@
#endif
typedef struct Authctxt Authctxt;
+typedef struct Authmethod Authmethod;
typedef struct KbdintDevice KbdintDevice;
struct Authctxt {
@@ -72,6 +73,12 @@ struct Authctxt {
#endif
};
+struct Authmethod {
+ char *name;
+ int (*userauth)(Authctxt *authctxt);
+ int *enabled;
+};
+
/*
* Keyboard interactive device:
* init_ctx returns: non NULL upon success
@@ -89,14 +96,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>
@@ -119,18 +133,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 *);
@@ -148,8 +171,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 "\nOPIE Password: "
#endif
diff --git a/crypto/openssh/auth1.c b/crypto/openssh/auth1.c
index 9611c6d58fee..8d8b5ce4f99f 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 $");
RCSID("$FreeBSD$");
#include "xmalloc.h"
@@ -26,8 +26,8 @@ RCSID("$FreeBSD$");
#include "channels.h"
#include "session.h"
#include "canohost.h"
-#include "misc.h"
#include "uidswap.h"
+#include "monitor_wrap.h"
#include <login_cap.h>
#include "auth-pam.h"
@@ -104,9 +104,9 @@ do_authloop(Authctxt *authctxt)
(!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif
#ifdef USE_PAM
- auth_pam_password(authctxt, "")) {
+ /* XXX PRIVSEP */ auth_pam_password(authctxt, "")) {
#else
- auth_password(authctxt, "")) {
+ PRIVSEP(auth_password(authctxt, ""))) {
#endif
auth_log(authctxt, 1, "without authentication", "");
return;
@@ -228,7 +228,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,
@@ -267,10 +267,10 @@ do_authloop(Authctxt *authctxt)
#ifdef USE_PAM
/* Do PAM auth with password */
- authenticated = auth_pam_password(authctxt, password);
+ authenticated = /* XXX PRIVSEP */ auth_pam_password(authctxt, password);
#else /* !USE_PAM */
/* Try authentication with the password. */
- authenticated = auth_password(authctxt, password);
+ authenticated = PRIVSEP(auth_password(authctxt, password));
#endif /* USE_PAM */
memset(password, 0, strlen(password));
@@ -418,13 +418,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);
@@ -436,36 +435,39 @@ 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;
#ifdef USE_PAM
- if (pw != NULL)
- start_pam(pw);
+ if (authctxt->pw != NULL)
+ start_pam(authctxt->pw);
#endif
- 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.");
/*
@@ -479,6 +481,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 34fc8f37d1ed..1db7a811e4b5 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 $");
RCSID("$FreeBSD$");
#include "ssh2.h"
@@ -220,7 +220,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]);
@@ -311,3 +311,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.c b/crypto/openssh/auth2.c
index 117415da89bc..72fad089bb71 100644
--- a/crypto/openssh/auth2.c
+++ b/crypto/openssh/auth2.c
@@ -23,35 +23,20 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth2.c,v 1.85 2002/02/24 19:14:59 markus Exp $");
+RCSID("$OpenBSD: auth2.c,v 1.93 2002/05/31 11:35:15 markus Exp $");
RCSID("$FreeBSD$");
-#include <openssl/evp.h>
-
#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"
#ifdef HAVE_LOGIN_CAP
#include <login_cap.h>
@@ -62,14 +47,23 @@ 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 */
-typedef struct Authmethod Authmethod;
-struct Authmethod {
- char *name;
- int (*userauth)(Authctxt *authctxt);
- int *enabled;
+extern Authmethod method_none;
+extern Authmethod method_pubkey;
+extern Authmethod method_passwd;
+extern Authmethod method_kbdint;
+extern Authmethod method_hostbased;
+
+Authmethod *authmethods[] = {
+ &method_none,
+ &method_pubkey,
+ &method_passwd,
+ &method_kbdint,
+ &method_hostbased,
+ NULL
};
/* protocol */
@@ -80,41 +74,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();
@@ -128,7 +95,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
@@ -195,23 +163,24 @@ 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);
#ifdef USE_PAM
- start_pam(pw);
+ start_pam(authctxt->pw);
#endif
} else {
log("input_userauth_request: illegal user %s", user);
authctxt->pw = NULL;
}
- 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: "
@@ -301,289 +270,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();
-#ifdef USE_PAM
- return authctxt->valid ? auth_pam_password(authctxt, "") : 0;
-#else /* !USE_PAM */
- return authctxt->valid ? auth_password(authctxt, "") : 0;
-#endif /* USE_PAM */
-}
-
-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 &&
-#ifdef USE_PAM
- auth_password(authctxt, password) == 1)
-#else
- auth_password(authctxt, password) == 1)
-#endif
- 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*
@@ -597,18 +283,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);
@@ -620,174 +308,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 35a6a3f057aa..69fa6608ae3f 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 $");
RCSID("$FreeBSD$");
#include <openssl/evp.h>
@@ -60,7 +60,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. */
@@ -208,6 +208,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.
*/
@@ -420,8 +440,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);
@@ -436,8 +454,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:
@@ -465,19 +481,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:
@@ -485,6 +510,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;
@@ -494,6 +525,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.
@@ -533,7 +570,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;
@@ -542,6 +579,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/authfile.c b/crypto/openssh/authfile.c
index 80b2fc5de33e..6b632299e604 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 $");
RCSID("$FreeBSD$");
#include <openssl/err.h>
@@ -422,7 +422,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/bufaux.c b/crypto/openssh/bufaux.c
index b7f990900156..17f08552c126 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 $");
RCSID("$FreeBSD$");
#include <openssl/bn.h>
@@ -138,10 +138,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)
{
@@ -159,9 +167,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];
@@ -193,7 +209,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. */
@@ -218,6 +234,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/canohost.c b/crypto/openssh/canohost.c
index 2892aaa715fb..b0a0eb6888cd 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 $");
RCSID("$FreeBSD$");
#include "packet.h"
@@ -43,13 +43,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 9fea66079e8d..00cf29d03851 100644
--- a/crypto/openssh/channels.c
+++ b/crypto/openssh/channels.c
@@ -39,7 +39,7 @@
*/
#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 $");
RCSID("$FreeBSD$");
#include "ssh.h"
@@ -47,7 +47,6 @@ RCSID("$FreeBSD$");
#include "ssh2.h"
#include "packet.h"
#include "xmalloc.h"
-#include "uidswap.h"
#include "log.h"
#include "misc.h"
#include "channels.h"
@@ -130,10 +129,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 */
int IPv4or6 = AF_UNSPEC;
@@ -707,7 +702,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 */
@@ -715,7 +714,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);
}
@@ -1633,12 +1633,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) {
@@ -1727,6 +1733,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 ||
@@ -2109,7 +2122,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();
@@ -2655,105 +2668,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 942573929e1a..12876d3eb36a 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 $ */
/* $FreeBSD$ */
/*
@@ -136,6 +136,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 */
@@ -202,8 +214,6 @@ void deny_input_open(int, u_int32_t, void *);
/* agent forwarding */
void auth_request_forwarding(void);
-char *auth_get_socket_name(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 806c5c1ddda1..0892423bed20 100644
--- a/crypto/openssh/cipher.c
+++ b/crypto/openssh/cipher.c
@@ -35,7 +35,7 @@
*/
#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 $");
RCSID("$FreeBSD$");
#include "xmalloc.h"
@@ -43,18 +43,20 @@ RCSID("$FreeBSD$");
#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 },
@@ -65,25 +67,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)
@@ -334,7 +351,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;
@@ -384,7 +401,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;
@@ -397,6 +414,7 @@ evp_ssh1_bf(void)
return (&ssh1_bf);
}
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
/* RIJNDAEL */
#define RIJNDAEL_BLOCKSIZE 16
struct ssh_rijndael_ctx
@@ -482,7 +500,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;
@@ -499,3 +517,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 8aa5982102cc..3847bda8ae3e 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 $ */
/* $FreeBSD$ */
/*
@@ -82,4 +82,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/compat.c b/crypto/openssh/compat.c
index 576943277e78..3344dd608968 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 $");
RCSID("$FreeBSD$");
#include "buffer.h"
@@ -62,20 +62,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|
@@ -122,8 +128,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 82acc5b6e5ce..a0d25345af1c 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 $ */
/* $FreeBSD$ */
/*
@@ -53,6 +53,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/key.c b/crypto/openssh/key.c
index 05780ab082bd..610ce4ad2697 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 $");
RCSID("$FreeBSD$");
#include <openssl/evp.h>
@@ -780,6 +780,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,
@@ -802,3 +806,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/monitor.c b/crypto/openssh/monitor.c
index 4957be9cd07a..c37da1921cd7 100644
--- a/crypto/openssh/monitor.c
+++ b/crypto/openssh/monitor.c
@@ -26,11 +26,12 @@
#include "includes.h"
RCSID("$OpenBSD: monitor.c,v 1.16 2002/06/21 05:50:51 djm Exp $");
+RCSID("$FreeBSD$");
#include <openssl/dh.h>
#ifdef SKEY
-#include <skey.h>
+#include <opie.h>
#endif
#include "ssh.h"
@@ -656,11 +657,11 @@ mm_answer_bsdauthrespond(int socket, Buffer *m)
int
mm_answer_skeyquery(int socket, Buffer *m)
{
- struct skey skey;
+ struct opie opie;
char challenge[1024];
int res;
- res = skeychallenge(&skey, authctxt->user, challenge);
+ res = opiechallenge(&opie, authctxt->user, challenge);
buffer_clear(m);
buffer_put_int(m, res);
@@ -683,8 +684,8 @@ mm_answer_skeyrespond(int socket, Buffer *m)
authok = (options.challenge_response_authentication &&
authctxt->valid &&
- skey_haskey(authctxt->pw->pw_name) == 0 &&
- skey_passcheck(authctxt->pw->pw_name, response) != -1);
+ opie_haskey(authctxt->pw->pw_name) == 0 &&
+ opie_passverify(authctxt->pw->pw_name, response) != -1);
xfree(response);
diff --git a/crypto/openssh/myproposal.h b/crypto/openssh/myproposal.h
index ca2c25964117..372ac7e17d63 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 $ */
/* $FreeBSD$ */
/*
@@ -28,7 +28,7 @@
#define KEX_DEFAULT_PK_ALG "ssh-dss,ssh-rsa"
#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/packet.h b/crypto/openssh/packet.h
index deaf81cb7bc3..a97d082784d7 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 $ */
/* $FreeBSD$ */
/*
@@ -25,6 +25,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);
@@ -57,6 +58,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 6f4dfc178889..2c3989ca0a58 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 $ */
/* $FreeBSD$ */
/*
@@ -111,6 +111,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"
@@ -120,3 +123,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/readconf.c b/crypto/openssh/readconf.c
index e1eb46931609..ca5b27ffaaec 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 $");
RCSID("$FreeBSD$");
#include "ssh.h"
@@ -42,7 +42,7 @@ RCSID("$FreeBSD$");
# that they are given in.
Host *.ngs.fi ngs.fi
- FallBackToRsh no
+ User foo
Host fake.com
HostName another.host.name.real.org
@@ -66,7 +66,7 @@ RCSID("$FreeBSD$");
ProxyCommand ssh-proxy %h %p
Host *.fr
- UseRsh yes
+ PublicKeyAuthentication no
Host *.su
Cipher none
@@ -80,8 +80,6 @@ RCSID("$FreeBSD$");
PasswordAuthentication yes
RSAAuthentication yes
RhostsRSAAuthentication yes
- FallBackToRsh no
- UseRsh no
StrictHostKeyChecking yes
KeepAlives no
IdentityFile ~/.ssh/identity
@@ -95,7 +93,7 @@ RCSID("$FreeBSD$");
typedef enum {
oBadOption,
oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
- oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
+ oPasswordAuthentication, oRSAAuthentication,
oChallengeResponseAuthentication, oXAuthLocation,
#if defined(KRB4) || defined(KRB5)
oKerberosAuthentication,
@@ -117,7 +115,8 @@ typedef enum {
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
- oVersionAddendum
+ oVersionAddendum,
+ oDeprecated
} OpCodes;
/* Textual representations of the tokens. */
@@ -152,8 +151,8 @@ static struct {
#ifdef AFS
{ "afstokenpassing", oAFSTokenPassing },
#endif
- { "fallbacktorsh", oFallBackToRsh },
- { "usersh", oUseRsh },
+ { "fallbacktorsh", oDeprecated },
+ { "usersh", oDeprecated },
{ "identityfile", oIdentityFile },
{ "identityfile2", oIdentityFile }, /* alias */
{ "hostname", oHostName },
@@ -374,14 +373,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;
@@ -686,6 +677,11 @@ parse_int:
} while (arg != NULL && *arg != '\0');
break;
+ case oDeprecated:
+ debug("%s line %d: Deprecated option \"%s\"",
+ filename, linenum, keyword);
+ return 0;
+
default:
fatal("process_config_line: Unimplemented opcode %d", opcode);
}
@@ -773,8 +769,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;
@@ -830,7 +824,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)
@@ -854,13 +848,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 c310137a2afb..9d326229508e 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 $ */
/* $FreeBSD$ */
/*
@@ -55,8 +55,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/servconf.c b/crypto/openssh/servconf.c
index 1cf7f9d90e6d..415ecca28d72 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 $");
RCSID("$FreeBSD$");
#if defined(KRB4)
@@ -40,6 +40,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. */
@@ -90,6 +92,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;
@@ -111,6 +114,9 @@ initialize_server_options(ServerOptions *options)
options->authorized_keys_file = NULL;
options->authorized_keys_file2 = NULL;
options->check_mail = -1;
+
+ /* Needs to be accessable in many places */
+ use_privsep = -1;
}
void
@@ -205,7 +211,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;
@@ -217,6 +223,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)
@@ -242,6 +250,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 off by default */
+ if (use_privsep == -1)
+ use_privsep = 0;
}
/* Keyword tokens. */
@@ -264,13 +276,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,
sCheckMail, sVersionAddendum,
sDeprecated
} ServerOpCodes;
@@ -324,6 +337,7 @@ static struct {
{ "strictmodes", sStrictModes },
{ "permitemptypasswords", sEmptyPasswd },
{ "uselogin", sUseLogin },
+ { "compression", sCompression },
{ "keepalive", sKeepAlives },
{ "allowtcpforwarding", sAllowTcpForwarding },
{ "allowusers", sAllowUsers },
@@ -343,6 +357,7 @@ static struct {
{ "clientalivecountmax", sClientAliveCountMax },
{ "authorizedkeysfile", sAuthorizedKeysFile },
{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
+ { "useprivilegeseparation", sUsePrivilegeSeparation},
{ "checkmail", sCheckMail },
{ "versionaddendum", sVersionAddendum },
{ NULL, sBadOption }
@@ -681,6 +696,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;
@@ -715,6 +734,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 d5bf6bea1142..862832ab69f2 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 $ */
/* $FreeBSD$ */
/*
@@ -100,6 +100,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];
@@ -132,7 +133,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 c5731d4d3f1e..921005082e21 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 $");
RCSID("$FreeBSD$");
#include "xmalloc.h"
@@ -319,9 +319,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);
@@ -674,12 +671,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)) {
@@ -727,8 +724,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);
@@ -785,7 +784,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 eddcf6c6a34c..2992794623d2 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 $");
RCSID("$FreeBSD$");
#include "ssh.h"
@@ -57,6 +57,7 @@ RCSID("$FreeBSD$");
#include "serverloop.h"
#include "canohost.h"
#include "session.h"
+#include "monitor_wrap.h"
#ifdef __FreeBSD__
#define _PATH_CHPASS "/usr/bin/passwd"
@@ -69,39 +70,11 @@ RCSID("$FreeBSD$");
#include <login_cap.h>
#endif
-/* 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;
-};
-
/* 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 *);
@@ -115,7 +88,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 */
@@ -135,9 +107,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)
{
@@ -150,18 +209,6 @@ do_authenticated(Authctxt *authctxt)
close(startup_pipe);
startup_pipe = -1;
}
-#ifdef HAVE_LOGIN_CAP
- if ((lc = login_getpwclass(authctxt->pw)) == 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();
@@ -172,7 +219,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)
@@ -223,6 +270,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;
@@ -379,7 +430,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];
@@ -603,22 +654,13 @@ do_exec(Session *s, const char *command)
void
do_login(Session *s, const char *command)
{
- FILE *f;
#ifndef USE_PAM
char *time_string;
- char *newcommand = NULL;
#endif
- char buf[256];
-#ifndef USE_PAM
- char hostname[MAXHOSTNAMELEN];
socklen_t fromlen;
struct sockaddr_storage from;
- time_t last_login_time;
-#endif
struct passwd * pw = s->pw;
-#ifndef USE_PAM
pid_t pid = getpid();
-#endif
#ifdef __FreeBSD__
#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */
struct timeval tv;
@@ -644,20 +686,6 @@ do_login(Session *s, const char *command)
}
#endif
-#ifndef USE_PAM
- /* 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);
-#endif
-
#ifdef USE_PAM
/*
* If password change is needed, do it now.
@@ -729,6 +757,13 @@ do_login(Session *s, const char *command)
}
#endif /* HAVE_LOGIN_CAP */
+ /* Record that there was a login on that tty from the remote host. */
+ 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);
+
#ifdef USE_PAM
if (command == NULL && options.print_lastlog &&
!check_quietlogin(s, command) &&
@@ -745,22 +780,27 @@ do_login(Session *s, const char *command)
*/
if (command == NULL && options.print_lastlog &&
- last_login_time != 0 && !check_quietlogin(s, command) &&
+ s->last_login_time != 0 && !check_quietlogin(s, command) &&
!options.use_login) {
- time_string = ctime(&last_login_time);
+ 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);
}
#endif /* !USE_PAM */
if (command == NULL && !check_quietlogin(s, command) &&
!options.use_login) {
#ifdef HAVE_LOGIN_CAP
- const char *fname = login_getcapstr(lc, "copyright", NULL, NULL);
+ const char *fname;
+ char buf[256];
+ FILE *f;
+
+ fname = login_getcapstr(lc, "copyright", NULL, NULL);
if (fname != NULL && (f = fopen(fname, "r")) != NULL) {
while (fgets(buf, sizeof(buf), f) != NULL)
fputs(buf, stdout);
@@ -1033,9 +1073,9 @@ do_setup_env(char **env, Session *s, const char *shell)
do_pam_environment(&env, &envsize);
#endif /* USE_PAM */
- 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) {
@@ -1099,7 +1139,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);
@@ -1143,11 +1183,10 @@ do_nologin(struct passwd *pw)
}
/* Set login name, uid, gid, and groups. */
-static char **
-do_setusercontext(Session *s)
+void
+do_setusercontext(struct passwd *pw)
{
char **env = NULL;
- struct passwd *pw = s->pw;
#ifdef HAVE_LOGIN_CAP
char buf[256];
char **tmpenv;
@@ -1170,9 +1209,6 @@ do_setusercontext(Session *s)
if (getenv("TZ"))
child_set_env(&env, &envsize, "TZ", getenv("TZ"));
- if (s->term)
- child_set_env(&env, &envsize, "TERM", s->term);
-
/* Save parent environment */
tmpenv = environ;
/* Switch to env */
@@ -1207,7 +1243,21 @@ do_setusercontext(Session *s)
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
#endif /* HAVE_LOGIN_CAP */
- return env;
+ return;
+}
+
+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);
}
/*
@@ -1242,7 +1292,7 @@ do_child(Session *s, const char *command)
*/
if (!options.use_login) {
do_nologin(pw);
- env = do_setusercontext(s);
+ do_setusercontext(pw);
}
/*
@@ -1336,15 +1386,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. */
@@ -1450,12 +1493,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);
}
}
@@ -1477,6 +1520,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)
{
@@ -1497,13 +1556,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;
}
@@ -1534,6 +1593,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);
@@ -1554,7 +1619,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;
@@ -1575,7 +1640,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);
@@ -1738,8 +1804,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;
@@ -1757,7 +1823,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
@@ -1765,12 +1832,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)
{
@@ -1779,8 +1852,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);
@@ -1812,10 +1885,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);
@@ -1839,7 +1912,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)
@@ -1859,7 +1933,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);
/*
@@ -1879,13 +1954,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/ssh-add.c b/crypto/openssh/ssh-add.c
index 526a187a0373..3680c0628d77 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 $");
RCSID("$FreeBSD$");
#include <openssl/evp.h>
@@ -49,6 +49,7 @@ RCSID("$FreeBSD$");
#include "authfile.h"
#include "pathnames.h"
#include "readpass.h"
+#include "misc.h"
/* argv0 */
extern char *__progname;
@@ -57,10 +58,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;
@@ -156,11 +159,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);
@@ -171,7 +182,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;
@@ -218,6 +235,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) {
@@ -239,6 +284,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");
@@ -262,7 +310,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':
@@ -270,6 +318,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;
@@ -285,6 +339,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;
@@ -301,6 +362,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",
@@ -310,11 +373,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.c b/crypto/openssh/ssh-agent.c
index 07df7476b983..4fc0f23e9e0d 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 $");
RCSID("$FreeBSD$");
#include <openssl/evp.h>
@@ -53,7 +53,6 @@ RCSID("$FreeBSD$");
#include "log.h"
#ifdef SMARTCARD
-#include <openssl/engine.h>
#include "scard.h"
#endif
@@ -68,6 +67,7 @@ typedef struct {
sock_type type;
Buffer input;
Buffer output;
+ Buffer request;
} SocketEntry;
u_int sockets_alloc = 0;
@@ -77,6 +77,7 @@ typedef struct identity {
TAILQ_ENTRY(identity) next;
Key *key;
char *comment;
+ u_int death;
} Identity;
typedef struct {
@@ -96,6 +97,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
@@ -117,6 +122,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)
@@ -131,14 +144,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)
@@ -188,16 +193,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;
@@ -253,10 +258,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;
@@ -297,16 +302,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;
@@ -357,7 +362,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
@@ -366,66 +391,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++;
@@ -439,53 +474,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,
@@ -495,39 +563,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);
@@ -542,6 +608,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);
@@ -550,15 +620,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);
@@ -567,6 +666,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:
@@ -583,6 +683,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:
@@ -602,7 +703,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;
@@ -625,6 +726,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;
@@ -639,6 +741,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
@@ -736,6 +839,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);
@@ -754,6 +858,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);
@@ -812,6 +917,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);
}
@@ -823,12 +929,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)
@@ -848,6 +955,9 @@ main(int ac, char **av)
usage();
d_flag++;
break;
+ case 'a':
+ agentsocket = optarg;
+ break;
default:
usage();
}
@@ -858,7 +968,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;
@@ -883,19 +993,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
@@ -928,7 +1044,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();
@@ -938,14 +1054,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.c b/crypto/openssh/ssh.c
index e99192045510..cf01550bb719 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 $");
RCSID("$FreeBSD$");
#include <openssl/evp.h>
@@ -53,7 +54,6 @@ RCSID("$FreeBSD$");
#include "xmalloc.h"
#include "packet.h"
#include "buffer.h"
-#include "uidswap.h"
#include "channels.h"
#include "key.h"
#include "authfd.h"
@@ -71,7 +71,6 @@ RCSID("$FreeBSD$");
#include "sshtty.h"
#ifdef SMARTCARD
-#include <openssl/engine.h>
#include "scard.h"
#endif
@@ -100,7 +99,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;
@@ -125,13 +124,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;
@@ -139,6 +136,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
@@ -193,47 +193,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;
-#ifndef _PATH_RSH
-#define _PATH_RSH "/usr/bin/rsh"
-#endif
- 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);
@@ -244,14 +203,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;
@@ -285,7 +243,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
@@ -466,7 +424,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);
@@ -650,52 +608,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
@@ -704,15 +658,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
@@ -723,21 +670,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();
@@ -755,8 +687,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) {
@@ -808,10 +739,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");
@@ -1041,6 +972,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)
@@ -1100,7 +1052,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 {
@@ -1187,40 +1139,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 6848e1e9f160..fd9fd50945b3 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 $ */
/* $FreeBSD$ */
/*
@@ -32,7 +32,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
@@ -86,6 +86,16 @@
/* 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
+
#ifdef USE_PAM
#include "auth-pam.h"
#endif /* USE_PAM */
diff --git a/crypto/openssh/ssh_config b/crypto/openssh/ssh_config
index 07814b6ec1d0..ab6206e449d6 100644
--- a/crypto/openssh/ssh_config
+++ b/crypto/openssh/ssh_config
@@ -1,10 +1,10 @@
-# $OpenBSD: ssh_config,v 1.12 2002/01/16 17:55:33 stevesk Exp $
-# $FreeBSD$
+# $OpenBSD: ssh_config,v 1.15 2002/06/20 20:03:34 stevesk Exp $
+# $FreeBSD$
-# 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
@@ -19,12 +19,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/sshconnect.c b/crypto/openssh/sshconnect.c
index 1a6f8e4759ce..707a9c0088c0 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 $");
RCSID("$FreeBSD$");
#include <openssl/bn.h>
@@ -37,27 +37,20 @@ RCSID("$FreeBSD$");
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;
}
@@ -65,8 +58,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;
@@ -116,7 +108,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]);
@@ -166,7 +159,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;
@@ -177,22 +170,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)
@@ -222,9 +211,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
@@ -239,7 +228,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;
@@ -255,8 +244,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) {
@@ -268,7 +256,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. */
@@ -304,30 +292,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
@@ -785,7 +764,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);
@@ -833,7 +812,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;
@@ -858,10 +837,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 5c1d326643eb..47bbfd5e5f83 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 $ */
/* $FreeBSD$ */
/*
@@ -27,21 +27,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 f021bec20f2d..3cb2d18cfe39 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 $");
RCSID("$FreeBSD$");
#include <openssl/bn.h>
@@ -460,6 +460,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);
@@ -844,7 +846,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);
@@ -1091,7 +1093,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;
@@ -1177,9 +1179,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 283b8d29daa5..7ecbe74cf70d 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 $");
RCSID("$FreeBSD$");
#include "ssh.h"
@@ -46,6 +46,8 @@ RCSID("$FreeBSD$");
#include "match.h"
#include "dispatch.h"
#include "canohost.h"
+#include "msg.h"
+#include "pathnames.h"
/* import */
extern char *client_version_string;
@@ -155,8 +157,7 @@ struct Authctxt {
int last_key_hint;
AuthenticationConnection *agent;
/* hostbased */
- Key **keys;
- int nkeys;
+ Sensitive *sensitive;
/* kbd-interactive */
int info_req_seen;
};
@@ -173,6 +174,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 *);
@@ -215,7 +217,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;
@@ -255,8 +257,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");
@@ -392,10 +393,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);
@@ -440,7 +441,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)
@@ -462,13 +463,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);
@@ -821,14 +894,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;
@@ -837,12 +984,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;
}
}
@@ -884,7 +1031,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.c b/crypto/openssh/sshd.c
index a48fa8c6bc10..fb6cf98b8ee3 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,12 +42,13 @@
*/
#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 $");
RCSID("$FreeBSD$");
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/md5.h>
+#include <openssl/rand.h>
#include "ssh.h"
#include "ssh1.h"
@@ -76,6 +79,11 @@ RCSID("$FreeBSD$");
#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>
@@ -184,8 +192,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);
@@ -258,10 +271,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);
@@ -354,7 +369,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) {
@@ -472,6 +487,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)
{
@@ -501,7 +670,7 @@ list_hostkey_types(void)
return p;
}
-static Key *
+Key *
get_hostkey_by_type(int type)
{
int i;
@@ -513,6 +682,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
@@ -589,6 +777,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;
@@ -787,6 +976,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);
@@ -933,7 +1135,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);
}
}
@@ -1080,7 +1282,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]);
@@ -1107,6 +1309,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.
@@ -1179,7 +1389,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.
@@ -1208,15 +1418,43 @@ 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);
@@ -1225,10 +1463,58 @@ main(int ac, char **av)
#endif /* USE_PAM */
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
@@ -1343,43 +1629,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
@@ -1430,9 +1682,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);
@@ -1444,7 +1699,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();
@@ -1471,6 +1726,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 */
@@ -1479,6 +1738,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_config b/crypto/openssh/sshd_config
index 9bd2d19bde6c..3f39debb905f 100644
--- a/crypto/openssh/sshd_config
+++ b/crypto/openssh/sshd_config
@@ -1,8 +1,8 @@
-# $OpenBSD: src/usr.bin/ssh/sshd_config,v 1.48 2002/02/19 02:50:59 deraadt Exp $
-# $FreeBSD$
+# $OpenBSD: sshd_config,v 1.56 2002/06/20 23:37:12 markus Exp $
+# $FreeBSD$
-# 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
@@ -64,13 +64,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
@@ -83,6 +81,8 @@
#KeepAlive yes
#UseLogin no
#CheckMail yes
+#UsePrivilegeSeparation no
+#Compression yes
#MaxStartups 10
# no default banner path
diff --git a/crypto/openssh/version.h b/crypto/openssh/version.h
index 084dd226cdea..93b15ffa7268 100644
--- a/crypto/openssh/version.h
+++ b/crypto/openssh/version.h
@@ -1,11 +1,11 @@
-/* $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 $ */
/* $FreeBSD$ */
#ifndef SSH_VERSION
#define SSH_VERSION (ssh_version_get())
-#define SSH_VERSION_BASE "OpenSSH_3.1"
-#define SSH_VERSION_ADDENDUM "FreeBSD-20020402"
+#define SSH_VERSION_BASE "OpenSSH_3.3"
+#define SSH_VERSION_ADDENDUM "FreeBSD-20020623"
const char *ssh_version_get(void);
void ssh_version_set_addendum(const char *add);