Vendor import of OpenSSH 3.3.

This commit is contained in:
Dag-Erling Smørgrav 2002-06-23 14:01:54 +00:00
parent 556a3fb01e
commit 545d5eca42
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor-crypto/openssh/dist/; revision=98675
115 changed files with 8749 additions and 3302 deletions

View File

@ -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

View File

@ -1,9 +1,9 @@
# $OpenBSD: Makefile,v 1.10 2002/02/09 17:37:34 deraadt Exp $
# $OpenBSD: Makefile,v 1.11 2002/05/23 19:24:30 markus Exp $
.include <bsd.own.mk>
SUBDIR= lib ssh sshd ssh-add ssh-keygen ssh-agent scp sftp-server \
ssh-keyscan sftp scard
ssh-keysign ssh-keyscan sftp scard
distribution:
install -C -o root -g wheel -m 0644 ${.CURDIR}/ssh_config \

View File

@ -4,52 +4,33 @@ OpenSSH contains experimental support for authentication using
Cyberflex smartcards and TODOS card readers. To enable this you
need to:
(1) install sectok
$ cd /usr/src/lib/libsectok
$ make obj depend all install includes
$ cd /usr/src/usr.bin/sectok
$ make obj depend all install
(2) enable SMARTCARD support in OpenSSH:
(1) enable SMARTCARD support in OpenSSH:
$ vi /usr/src/usr.bin/ssh/Makefile.inc
and uncomment
CFLAGS+= -DSMARTCARD
LDADD+= -lsectok
(3) load the Java Cardlet to the Cyberflex card:
(2) If you have used a previous version of ssh with your card, you
must remove the old applet and keys.
$ sectok
sectok> login -d
sectok> junload Ssh.bin
sectok> delete 0012
sectok> delete sh
sectok> quit
(3) load the Java Cardlet to the Cyberflex card and set card passphrase:
$ sectok
sectok> login -d
sectok> jload /usr/libdata/ssh/Ssh.bin
sectok> quit
(4) load a RSA key to the card:
please don't use your production RSA keys, since
with the current version of sectok/ssh-keygen
the private key file is still readable
$ ssh-keygen -f /path/to/rsakey -U 1
(where 1 is the reader number, you can also try 0)
In spite of the name, this does not generate a key.
It just loads an already existing key on to the card.
(5) optional:
Change the card password so that only you can
read the private key:
$ sectok
sectok> login -d
sectok> setpass
Enter new AUT0 passphrase:
Re-enter passphrase:
sectok> quit
This prevents reading the key but not use of the
key by the card applet.
Do not forget the passphrase. There is no way to
recover if you do.
@ -57,13 +38,36 @@ need to:
wrong passphrase three times in a row, you will
destroy your card.
(6) tell the ssh client to use the card reader:
(4) load a RSA key to the card:
$ ssh-keygen -f /path/to/rsakey -U 1
(where 1 is the reader number, you can also try 0)
In spite of the name, this does not generate a key.
It just loads an already existing key on to the card.
(5) tell the ssh client to use the card reader:
$ ssh -I 1 otherhost
(7) or tell the agent (don't forget to restart) to use the smartcard:
(6) or tell the agent (don't forget to restart) to use the smartcard:
$ ssh-add -s 1
(7) Optional: If you don't want to use a card passphrase, change the
acl on the private key file:
$ sectok
sectok> login -d
sectok> acl 0012 world: w
world: w
AUT0: w inval
sectok> quit
If you do this, anyone who has access to your card
can assume your identity. This is not recommended.
-markus,
Tue Jul 17 23:54:51 CEST 2001
$OpenBSD: README.smartcard,v 1.8 2002/03/26 18:56:23 rees Exp $

View File

@ -22,12 +22,13 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: auth-bsdauth.c,v 1.2 2001/12/19 07:18:56 deraadt Exp $");
RCSID("$OpenBSD: auth-bsdauth.c,v 1.4 2002/06/19 00:27:55 deraadt Exp $");
#ifdef BSD_AUTH
#include "xmalloc.h"
#include "auth.h"
#include "log.h"
#include "monitor_wrap.h"
static void *
bsdauth_init_ctx(Authctxt *authctxt)
@ -35,7 +36,7 @@ bsdauth_init_ctx(Authctxt *authctxt)
return authctxt;
}
static int
int
bsdauth_query(void *ctx, char **name, char **infotxt,
u_int *numprompts, char ***prompts, u_int **echo_on)
{
@ -56,7 +57,7 @@ bsdauth_query(void *ctx, char **name, char **infotxt,
debug3("bsdauth_query: style %s",
authctxt->style ? authctxt->style : "<default>");
authctxt->as = auth_userchallenge(authctxt->user,
authctxt->style, "auth-ssh", &challenge);
authctxt->style, "auth-ssh", &challenge);
if (authctxt->as == NULL)
challenge = NULL;
debug2("bsdauth_query: <%s>", challenge ? challenge : "empty");
@ -65,8 +66,8 @@ bsdauth_query(void *ctx, char **name, char **infotxt,
if (challenge == NULL)
return -1;
*name = xstrdup("");
*infotxt = xstrdup("");
*name = xstrdup("");
*infotxt = xstrdup("");
*numprompts = 1;
*prompts = xmalloc(*numprompts * sizeof(char*));
*echo_on = xmalloc(*numprompts * sizeof(u_int));
@ -76,7 +77,7 @@ bsdauth_query(void *ctx, char **name, char **infotxt,
return 0;
}
static int
int
bsdauth_respond(void *ctx, u_int numresponses, char **responses)
{
Authctxt *authctxt = ctx;
@ -113,4 +114,12 @@ KbdintDevice bsdauth_device = {
bsdauth_respond,
bsdauth_free_ctx
};
KbdintDevice mm_bsdauth_device = {
"bsdauth",
bsdauth_init_ctx,
mm_bsdauth_query,
mm_bsdauth_respond,
bsdauth_free_ctx
};
#endif

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth-krb4.c,v 1.25 2001/12/19 07:18:56 deraadt Exp $");
RCSID("$OpenBSD: auth-krb4.c,v 1.27 2002/06/11 05:46:20 mpech Exp $");
#include "ssh.h"
#include "ssh1.h"
@ -57,8 +57,8 @@ krb4_init(void *context)
if (lstat("/ticket", &st) != -1)
tkt_root = "/ticket/";
#endif /* AFS */
snprintf(authctxt->krb4_ticket_file, MAXPATHLEN, "%s%u_%d",
tkt_root, authctxt->pw->pw_uid, getpid());
snprintf(authctxt->krb4_ticket_file, MAXPATHLEN, "%s%u_%ld",
tkt_root, authctxt->pw->pw_uid, (long)getpid());
krb_set_tkt_string(authctxt->krb4_ticket_file);
}
/* Register ticket cleanup in case of fatal error. */
@ -253,6 +253,7 @@ auth_krb4(Authctxt *authctxt, KTEXT auth, char **client)
log("Kerberos v4 .klogin authorization failed for %s to "
"account %s", *client, authctxt->user);
xfree(*client);
*client = NULL;
return (0);
}
/* Increment the checksum, and return it encrypted with the

View File

@ -1,11 +1,34 @@
/*
* Kerberos v5 authentication and ticket-passing routines.
*
*
* $FreeBSD$
*/
/*
* Copyright (c) 2002 Daniel Kouril. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: auth-krb5.c,v 1.6 2002/03/04 17:27:39 stevesk Exp $");
RCSID("$OpenBSD: auth-krb5.c,v 1.8 2002/03/19 10:49:35 markus Exp $");
#include "ssh.h"
#include "ssh1.h"

View File

@ -10,7 +10,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth-options.c,v 1.21 2002/01/29 14:32:03 markus Exp $");
RCSID("$OpenBSD: auth-options.c,v 1.24 2002/05/13 20:44:58 markus Exp $");
#include "packet.h"
#include "xmalloc.h"
@ -20,7 +20,10 @@ RCSID("$OpenBSD: auth-options.c,v 1.21 2002/01/29 14:32:03 markus Exp $");
#include "channels.h"
#include "auth-options.h"
#include "servconf.h"
#include "bufaux.h"
#include "misc.h"
#include "monitor_wrap.h"
#include "auth.h"
/* Flags set authorized_keys flags */
int no_port_forwarding_flag = 0;
@ -54,6 +57,7 @@ auth_clear_options(void)
forced_command = NULL;
}
channel_clear_permitted_opens();
auth_debug_reset();
}
/*
@ -75,28 +79,28 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
while (*opts && *opts != ' ' && *opts != '\t') {
cp = "no-port-forwarding";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
packet_send_debug("Port forwarding disabled.");
auth_debug_add("Port forwarding disabled.");
no_port_forwarding_flag = 1;
opts += strlen(cp);
goto next_option;
}
cp = "no-agent-forwarding";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
packet_send_debug("Agent forwarding disabled.");
auth_debug_add("Agent forwarding disabled.");
no_agent_forwarding_flag = 1;
opts += strlen(cp);
goto next_option;
}
cp = "no-X11-forwarding";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
packet_send_debug("X11 forwarding disabled.");
auth_debug_add("X11 forwarding disabled.");
no_x11_forwarding_flag = 1;
opts += strlen(cp);
goto next_option;
}
cp = "no-pty";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
packet_send_debug("Pty allocation disabled.");
auth_debug_add("Pty allocation disabled.");
no_pty_flag = 1;
opts += strlen(cp);
goto next_option;
@ -119,14 +123,14 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
xfree(forced_command);
forced_command = NULL;
goto bad_option;
}
forced_command[i] = 0;
packet_send_debug("Forced command: %.900s", forced_command);
auth_debug_add("Forced command: %.900s", forced_command);
opts++;
goto next_option;
}
@ -151,13 +155,13 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
xfree(s);
goto bad_option;
}
s[i] = 0;
packet_send_debug("Adding to environment: %.900s", s);
auth_debug_add("Adding to environment: %.900s", s);
debug("Adding to environment: %.900s", s);
opts++;
new_envstring = xmalloc(sizeof(struct envstring));
@ -188,7 +192,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
xfree(patterns);
goto bad_option;
@ -202,7 +206,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
"correct key but not from a permitted "
"host (host=%.200s, ip=%.200s).",
pw->pw_name, remote_host, remote_ip);
packet_send_debug("Your host '%.200s' is not "
auth_debug_add("Your host '%.200s' is not "
"permitted to use this key for login.",
remote_host);
/* deny access */
@ -233,7 +237,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
xfree(patterns);
goto bad_option;
@ -244,7 +248,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
sscanf(patterns, "%255[^/]/%5[0-9]", host, sport) != 2) {
debug("%.100s, line %lu: Bad permitopen specification "
"<%.100s>", file, linenum, patterns);
packet_send_debug("%.100s, line %lu: "
auth_debug_add("%.100s, line %lu: "
"Bad permitopen specification", file, linenum);
xfree(patterns);
goto bad_option;
@ -252,7 +256,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
if ((port = a2port(sport)) == 0) {
debug("%.100s, line %lu: Bad permitopen port <%.100s>",
file, linenum, sport);
packet_send_debug("%.100s, line %lu: "
auth_debug_add("%.100s, line %lu: "
"Bad permitopen port", file, linenum);
xfree(patterns);
goto bad_option;
@ -276,14 +280,22 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
opts++;
/* Process the next option. */
}
if (!use_privsep)
auth_debug_send();
/* grant access */
return 1;
bad_option:
log("Bad options in %.100s file, line %lu: %.50s",
file, linenum, opts);
packet_send_debug("Bad options in %.100s file, line %lu: %.50s",
auth_debug_add("Bad options in %.100s file, line %lu: %.50s",
file, linenum, opts);
if (!use_privsep)
auth_debug_send();
/* deny access */
return 0;
}

View File

@ -36,7 +36,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth-passwd.c,v 1.24 2002/03/04 12:43:06 markus Exp $");
RCSID("$OpenBSD: auth-passwd.c,v 1.27 2002/05/24 16:45:16 stevesk Exp $");
#include "packet.h"
#include "log.h"
@ -54,7 +54,6 @@ int
auth_password(Authctxt *authctxt, const char *password)
{
struct passwd * pw = authctxt->pw;
char *encrypted_password;
/* deny if no user. */
if (pw == NULL)
@ -85,14 +84,20 @@ auth_password(Authctxt *authctxt, const char *password)
return 0;
else
return 1;
#endif
#else
/* Check for users with no password. */
if (strcmp(password, "") == 0 && strcmp(pw->pw_passwd, "") == 0)
return 1;
/* Encrypt the candidate password using the proper salt. */
encrypted_password = crypt(password,
(pw->pw_passwd[0] && pw->pw_passwd[1]) ? pw->pw_passwd : "xx");
/* Authentication is accepted if the encrypted passwords are identical. */
return (strcmp(encrypted_password, pw->pw_passwd) == 0);
else {
/* Encrypt the candidate password using the proper salt. */
char *encrypted_password = crypt(password,
(pw->pw_passwd[0] && pw->pw_passwd[1]) ?
pw->pw_passwd : "xx");
/*
* Authentication is accepted if the encrypted passwords
* are identical.
*/
return (strcmp(encrypted_password, pw->pw_passwd) == 0);
}
#endif
}

View File

@ -13,7 +13,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth-rh-rsa.c,v 1.29 2002/03/04 12:43:06 markus Exp $");
RCSID("$OpenBSD: auth-rh-rsa.c,v 1.34 2002/03/25 09:25:06 markus Exp $");
#include "packet.h"
#include "uidswap.h"
@ -25,37 +25,48 @@ RCSID("$OpenBSD: auth-rh-rsa.c,v 1.29 2002/03/04 12:43:06 markus Exp $");
#include "auth.h"
#include "canohost.h"
#include "monitor_wrap.h"
/* import */
extern ServerOptions options;
int
auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
Key *client_host_key)
{
HostStatus host_status;
/* Check if we would accept it using rhosts authentication. */
if (!auth_rhosts(pw, cuser))
return 0;
host_status = check_key_in_hostfiles(pw, client_host_key,
chost, _PATH_SSH_SYSTEM_HOSTFILE,
options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
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, const char *client_user, Key *client_host_key)
auth_rhosts_rsa(struct passwd *pw, char *cuser, Key *client_host_key)
{
extern ServerOptions options;
const char *canonical_hostname;
HostStatus host_status;
char *chost;
debug("Trying rhosts with RSA host authentication for client user %.100s", client_user);
debug("Trying rhosts with RSA host authentication for client user %.100s",
cuser);
if (pw == NULL || client_host_key == NULL || client_host_key->rsa == NULL)
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))
return 0;
chost = (char *)get_canonical_hostname(options.verify_reverse_mapping);
debug("Rhosts RSA authentication: canonical host %.900s", chost);
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,
options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
if (host_status != HOST_OK) {
if (!PRIVSEP(auth_rhosts_rsa_key_allowed(pw, cuser, chost, client_host_key))) {
debug("Rhosts with RSA host authentication denied: unknown or invalid host key");
packet_send_debug("Your host key cannot be verified: unknown or invalid host key.");
return 0;
@ -63,9 +74,9 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, Key *client_host_key
/* A matching host key was found and is known. */
/* Perform the challenge-response dialog with the client for the host key. */
if (!auth_rsa_challenge_dialog(client_host_key->rsa)) {
if (!auth_rsa_challenge_dialog(client_host_key)) {
log("Client on %.800s failed to respond correctly to host authentication.",
canonical_hostname);
chost);
return 0;
}
/*
@ -74,7 +85,7 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, Key *client_host_key
*/
verbose("Rhosts with RSA host authentication accepted for %.100s, %.100s on %.700s.",
pw->pw_name, client_user, canonical_hostname);
pw->pw_name, cuser, chost);
packet_send_debug("Rhosts with RSA host authentication accepted.");
return 1;
}

View File

@ -14,7 +14,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth-rhosts.c,v 1.27 2002/03/04 12:43:06 markus Exp $");
RCSID("$OpenBSD: auth-rhosts.c,v 1.28 2002/05/13 21:26:49 markus Exp $");
#include "packet.h"
#include "uidswap.h"
@ -26,6 +26,7 @@ RCSID("$OpenBSD: auth-rhosts.c,v 1.27 2002/03/04 12:43:06 markus Exp $");
/* import */
extern ServerOptions options;
extern int use_privsep;
/*
* This function processes an rhosts-style file (.rhosts, .shosts, or
@ -69,7 +70,7 @@ check_rhosts_file(const char *filename, const char *hostname,
*/
switch (sscanf(buf, "%s %s %s", hostbuf, userbuf, dummy)) {
case 0:
packet_send_debug("Found empty line in %.100s.", filename);
auth_debug_add("Found empty line in %.100s.", filename);
continue;
case 1:
/* Host name only. */
@ -79,7 +80,7 @@ check_rhosts_file(const char *filename, const char *hostname,
/* Got both host and user name. */
break;
case 3:
packet_send_debug("Found garbage in %.100s.", filename);
auth_debug_add("Found garbage in %.100s.", filename);
continue;
default:
/* Weird... */
@ -106,8 +107,8 @@ check_rhosts_file(const char *filename, const char *hostname,
/* Check for empty host/user names (particularly '+'). */
if (!host[0] || !user[0]) {
/* We come here if either was '+' or '-'. */
packet_send_debug("Ignoring wild host/user names in %.100s.",
filename);
auth_debug_add("Ignoring wild host/user names in %.100s.",
filename);
continue;
}
/* Verify that host name matches. */
@ -130,8 +131,8 @@ check_rhosts_file(const char *filename, const char *hostname,
/* If the entry was negated, deny access. */
if (negated) {
packet_send_debug("Matched negative entry in %.100s.",
filename);
auth_debug_add("Matched negative entry in %.100s.",
filename);
return 0;
}
/* Accept authentication. */
@ -153,16 +154,14 @@ int
auth_rhosts(struct passwd *pw, const char *client_user)
{
const char *hostname, *ipaddr;
int ret;
hostname = get_canonical_hostname(options.verify_reverse_mapping);
ipaddr = get_remote_ipaddr();
ret = auth_rhosts2(pw, client_user, hostname, ipaddr);
return ret;
return auth_rhosts2(pw, client_user, hostname, ipaddr);
}
int
auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
static int
auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostname,
const char *ipaddr)
{
char buf[1024];
@ -205,13 +204,13 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
if (pw->pw_uid != 0) {
if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr,
client_user, pw->pw_name)) {
packet_send_debug("Accepted for %.100s [%.100s] by /etc/hosts.equiv.",
auth_debug_add("Accepted for %.100s [%.100s] by /etc/hosts.equiv.",
hostname, ipaddr);
return 1;
}
if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr,
client_user, pw->pw_name)) {
packet_send_debug("Accepted for %.100s [%.100s] by %.100s.",
auth_debug_add("Accepted for %.100s [%.100s] by %.100s.",
hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV);
return 1;
}
@ -221,19 +220,19 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
* not group or world writable.
*/
if (stat(pw->pw_dir, &st) < 0) {
log("Rhosts authentication refused for %.100s: no home directory %.200s",
pw->pw_name, pw->pw_dir);
packet_send_debug("Rhosts authentication refused for %.100s: no home directory %.200s",
pw->pw_name, pw->pw_dir);
log("Rhosts authentication refused for %.100s: "
"no home directory %.200s", pw->pw_name, pw->pw_dir);
auth_debug_add("Rhosts authentication refused for %.100s: "
"no home directory %.200s", pw->pw_name, pw->pw_dir);
return 0;
}
if (options.strict_modes &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0)) {
log("Rhosts authentication refused for %.100s: bad ownership or modes for home directory.",
pw->pw_name);
packet_send_debug("Rhosts authentication refused for %.100s: bad ownership or modes for home directory.",
pw->pw_name);
log("Rhosts authentication refused for %.100s: "
"bad ownership or modes for home directory.", pw->pw_name);
auth_debug_add("Rhosts authentication refused for %.100s: "
"bad ownership or modes for home directory.", pw->pw_name);
return 0;
}
/* Temporarily use the user's uid. */
@ -259,21 +258,23 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
(st.st_mode & 022) != 0)) {
log("Rhosts authentication refused for %.100s: bad modes for %.200s",
pw->pw_name, buf);
packet_send_debug("Bad file modes for %.200s", buf);
auth_debug_add("Bad file modes for %.200s", buf);
continue;
}
/* Check if we have been configured to ignore .rhosts and .shosts files. */
if (options.ignore_rhosts) {
packet_send_debug("Server has been configured to ignore %.100s.",
rhosts_files[rhosts_file_index]);
auth_debug_add("Server has been configured to ignore %.100s.",
rhosts_files[rhosts_file_index]);
continue;
}
/* Check if authentication is permitted by the file. */
if (check_rhosts_file(buf, hostname, ipaddr, client_user, pw->pw_name)) {
packet_send_debug("Accepted by %.100s.",
rhosts_files[rhosts_file_index]);
auth_debug_add("Accepted by %.100s.",
rhosts_files[rhosts_file_index]);
/* Restore the privileged uid. */
restore_uid();
auth_debug_add("Accepted host %s ip %s client_user %s server_user %s",
hostname, ipaddr, client_user, pw->pw_name);
return 1;
}
}
@ -282,3 +283,16 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
restore_uid();
return 0;
}
int
auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
const char *ipaddr)
{
int ret;
auth_debug_reset();
ret = auth_rhosts2_raw(pw, client_user, hostname, ipaddr);
if (!use_privsep)
auth_debug_send();
return ret;
}

View File

@ -14,7 +14,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth-rsa.c,v 1.50 2001/12/28 14:50:54 markus Exp $");
RCSID("$OpenBSD: auth-rsa.c,v 1.56 2002/06/10 16:53:06 stevesk Exp $");
#include <openssl/rsa.h>
#include <openssl/md5.h>
@ -32,6 +32,8 @@ RCSID("$OpenBSD: auth-rsa.c,v 1.50 2001/12/28 14:50:54 markus Exp $");
#include "servconf.h"
#include "auth.h"
#include "hostfile.h"
#include "monitor_wrap.h"
#include "ssh.h"
/* import */
extern ServerOptions options;
@ -52,6 +54,58 @@ extern u_char session_id[16];
* description of the options.
*/
BIGNUM *
auth_rsa_generate_challenge(Key *key)
{
BIGNUM *challenge;
BN_CTX *ctx;
if ((challenge = BN_new()) == NULL)
fatal("auth_rsa_generate_challenge: BN_new() failed");
/* Generate a random challenge. */
BN_rand(challenge, 256, 0, 0);
if ((ctx = BN_CTX_new()) == NULL)
fatal("auth_rsa_generate_challenge: BN_CTX_new() failed");
BN_mod(challenge, challenge, key->rsa->n, ctx);
BN_CTX_free(ctx);
return challenge;
}
int
auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
{
u_char buf[32], mdbuf[16];
MD5_CTX md;
int len;
/* don't allow short keys */
if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits",
BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
return (0);
}
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
if (len <= 0 || len > 32)
fatal("auth_rsa_verify_response: bad challenge length %d", len);
memset(buf, 0, 32);
BN_bn2bin(challenge, buf + 32 - len);
MD5_Init(&md);
MD5_Update(&md, buf, 32);
MD5_Update(&md, session_id, 16);
MD5_Final(mdbuf, &md);
/* Verify that the response is the original challenge. */
if (memcmp(response, mdbuf, 16) != 0) {
/* Wrong answer. */
return (0);
}
/* Correct answer. */
return (1);
}
/*
* Performs the RSA authentication challenge-response dialog with the client,
* and returns true (non-zero) if the client gave the correct answer to
@ -59,29 +113,19 @@ extern u_char session_id[16];
*/
int
auth_rsa_challenge_dialog(RSA *pk)
auth_rsa_challenge_dialog(Key *key)
{
BIGNUM *challenge, *encrypted_challenge;
BN_CTX *ctx;
u_char buf[32], mdbuf[16], response[16];
MD5_CTX md;
u_int i;
int len;
u_char response[16];
int i, success;
if ((encrypted_challenge = BN_new()) == NULL)
fatal("auth_rsa_challenge_dialog: BN_new() failed");
if ((challenge = BN_new()) == NULL)
fatal("auth_rsa_challenge_dialog: BN_new() failed");
/* Generate a random challenge. */
BN_rand(challenge, 256, 0, 0);
if ((ctx = BN_CTX_new()) == NULL)
fatal("auth_rsa_challenge_dialog: BN_CTX_new() failed");
BN_mod(challenge, challenge, pk->n, ctx);
BN_CTX_free(ctx);
challenge = PRIVSEP(auth_rsa_generate_challenge(key));
/* Encrypt the challenge with the public key. */
rsa_public_encrypt(encrypted_challenge, challenge, pk);
rsa_public_encrypt(encrypted_challenge, challenge, key->rsa);
/* Send the encrypted challenge to the client. */
packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
@ -96,48 +140,26 @@ auth_rsa_challenge_dialog(RSA *pk)
response[i] = packet_get_char();
packet_check_eom();
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
if (len <= 0 || len > 32)
fatal("auth_rsa_challenge_dialog: bad challenge length %d", len);
memset(buf, 0, 32);
BN_bn2bin(challenge, buf + 32 - len);
MD5_Init(&md);
MD5_Update(&md, buf, 32);
MD5_Update(&md, session_id, 16);
MD5_Final(mdbuf, &md);
success = PRIVSEP(auth_rsa_verify_response(key, challenge, response));
BN_clear_free(challenge);
/* Verify that the response is the original challenge. */
if (memcmp(response, mdbuf, 16) != 0) {
/* Wrong answer. */
return 0;
}
/* Correct answer. */
return 1;
return (success);
}
/*
* Performs the RSA authentication dialog with the client. This returns
* 0 if the client could not be authenticated, and 1 if authentication was
* successful. This may exit if there is a serious protocol violation.
* check if there's user key matching client_n,
* return key if login is allowed, NULL otherwise
*/
int
auth_rsa(struct passwd *pw, BIGNUM *client_n)
auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
{
char line[8192], *file;
int authenticated;
int allowed = 0;
u_int bits;
FILE *f;
u_long linenum = 0;
struct stat st;
Key *key;
char *fp;
/* no user given */
if (pw == NULL)
return 0;
/* Temporarily use the user's uid. */
temporarily_use_uid(pw);
@ -151,29 +173,27 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
/* Restore the privileged uid. */
restore_uid();
xfree(file);
return 0;
return (0);
}
/* Open the file containing the authorized keys. */
f = fopen(file, "r");
if (!f) {
/* Restore the privileged uid. */
restore_uid();
packet_send_debug("Could not open %.900s for reading.", file);
packet_send_debug("If your home is on an NFS volume, it may need to be world-readable.");
xfree(file);
return 0;
return (0);
}
if (options.strict_modes &&
secure_filename(f, file, pw, line, sizeof(line)) != 0) {
xfree(file);
fclose(f);
log("Authentication refused: %s", line);
packet_send_debug("Authentication refused: %s", line);
restore_uid();
return 0;
return (0);
}
/* Flag indicating whether authentication has succeeded. */
authenticated = 0;
/* Flag indicating whether the key is allowed. */
allowed = 0;
key = key_new(KEY_RSA1);
@ -238,32 +258,8 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
if (!auth_parse_options(pw, options, file, linenum))
continue;
/* Perform the challenge-response dialog for this key. */
if (!auth_rsa_challenge_dialog(key->rsa)) {
/* Wrong response. */
verbose("Wrong response to RSA authentication challenge.");
packet_send_debug("Wrong response to RSA authentication challenge.");
/*
* Break out of the loop. Otherwise we might send
* another challenge and break the protocol.
*/
break;
}
/*
* Correct response. The client has been successfully
* authenticated. Note that we have not yet processed the
* options; this will be reset if the options cause the
* authentication to be rejected.
* Break out of the loop if authentication was successful;
* otherwise continue searching.
*/
authenticated = 1;
fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
verbose("Found matching %s key: %s",
key_type(key), fp);
xfree(fp);
/* break out, this key is allowed */
allowed = 1;
break;
}
@ -274,13 +270,58 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
xfree(file);
fclose(f);
/* 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);
if (authenticated)
packet_send_debug("RSA authentication accepted.");
else
auth_clear_options();
/* Return authentication result. */
return authenticated;
packet_send_debug("RSA authentication accepted.");
return (1);
}

View File

@ -22,7 +22,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: auth-skey.c,v 1.16 2002/01/12 13:10:29 markus Exp $");
RCSID("$OpenBSD: auth-skey.c,v 1.19 2002/06/19 00:27:55 deraadt Exp $");
#ifdef SKEY
@ -30,6 +30,7 @@ RCSID("$OpenBSD: auth-skey.c,v 1.16 2002/01/12 13:10:29 markus Exp $");
#include "xmalloc.h"
#include "auth.h"
#include "monitor_wrap.h"
static void *
skey_init_ctx(Authctxt *authctxt)
@ -37,9 +38,7 @@ skey_init_ctx(Authctxt *authctxt)
return authctxt;
}
#define PROMPT "\nS/Key Password: "
static int
int
skey_query(void *ctx, char **name, char **infotxt,
u_int* numprompts, char ***prompts, u_int **echo_on)
{
@ -51,23 +50,23 @@ skey_query(void *ctx, char **name, char **infotxt,
if (skeychallenge(&skey, authctxt->user, challenge) == -1)
return -1;
*name = xstrdup("");
*infotxt = xstrdup("");
*name = xstrdup("");
*infotxt = xstrdup("");
*numprompts = 1;
*prompts = xmalloc(*numprompts * sizeof(char*));
*echo_on = xmalloc(*numprompts * sizeof(u_int));
(*echo_on)[0] = 0;
len = strlen(challenge) + strlen(PROMPT) + 1;
len = strlen(challenge) + strlen(SKEY_PROMPT) + 1;
p = xmalloc(len);
strlcpy(p, challenge, len);
strlcat(p, PROMPT, len);
strlcat(p, SKEY_PROMPT, len);
(*prompts)[0] = p;
return 0;
}
static int
int
skey_respond(void *ctx, u_int numresponses, char **responses)
{
Authctxt *authctxt = ctx;
@ -93,4 +92,12 @@ KbdintDevice skey_device = {
skey_respond,
skey_free_ctx
};
KbdintDevice mm_skey_device = {
"skey",
skey_init_ctx,
mm_skey_query,
mm_skey_respond,
skey_free_ctx
};
#endif /* SKEY */

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth.c,v 1.35 2002/03/01 13:12:10 markus Exp $");
RCSID("$OpenBSD: auth.c,v 1.43 2002/05/17 14:27:55 millert Exp $");
#include <libgen.h>
@ -39,10 +39,17 @@ RCSID("$OpenBSD: auth.c,v 1.35 2002/03/01 13:12:10 markus Exp $");
#include "bufaux.h"
#include "uidswap.h"
#include "tildexpand.h"
#include "misc.h"
#include "bufaux.h"
#include "packet.h"
/* import */
extern ServerOptions options;
/* Debugging messages */
Buffer auth_debug;
int auth_debug_init;
/*
* Check if the user is allowed to log in via ssh. If user is listed
* in DenyUsers or one of user's groups is listed in DenyGroups, false
@ -76,7 +83,8 @@ allowed_user(struct passwd * pw)
pw->pw_name, shell);
return 0;
}
if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)))) {
if (S_ISREG(st.st_mode) == 0 ||
(st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
log("User %.100s not allowed because shell %.100s is not executable",
pw->pw_name, shell);
return 0;
@ -90,17 +98,17 @@ allowed_user(struct passwd * pw)
/* Return false if user is listed in DenyUsers */
if (options.num_deny_users > 0) {
for (i = 0; i < options.num_deny_users; i++)
if (match_user(pw->pw_name, hostname, ipaddr,
if (match_user(pw->pw_name, hostname, ipaddr,
options.deny_users[i])) {
log("User %.100s not allowed because listed in DenyUsers",
pw->pw_name);
log("User %.100s not allowed because listed in DenyUsers",
pw->pw_name);
return 0;
}
}
/* Return false if AllowUsers isn't empty and user isn't listed there */
if (options.num_allow_users > 0) {
for (i = 0; i < options.num_allow_users; i++)
if (match_user(pw->pw_name, hostname, ipaddr,
if (match_user(pw->pw_name, hostname, ipaddr,
options.allow_users[i]))
break;
/* i < options.num_allow_users iff we break for loop */
@ -386,3 +394,77 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
}
return 0;
}
struct passwd *
getpwnamallow(const char *user)
{
#ifdef HAVE_LOGIN_CAP
extern login_cap_t *lc;
#ifdef BSD_AUTH
auth_session_t *as;
#endif
#endif
struct passwd *pw;
pw = getpwnam(user);
if (pw == NULL || !allowed_user(pw))
return (NULL);
#ifdef HAVE_LOGIN_CAP
if ((lc = login_getclass(pw->pw_class)) == NULL) {
debug("unable to get login class: %s", user);
return (NULL);
}
#ifdef BSD_AUTH
if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 ||
auth_approval(as, lc, pw->pw_name, "ssh") <= 0) {
debug("Approval failure for %s", user);
pw = NULL;
}
if (as != NULL)
auth_close(as);
#endif
#endif
if (pw != NULL)
return (pwcopy(pw));
return (NULL);
}
void
auth_debug_add(const char *fmt,...)
{
char buf[1024];
va_list args;
if (!auth_debug_init)
return;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
buffer_put_cstring(&auth_debug, buf);
}
void
auth_debug_send(void)
{
char *msg;
if (!auth_debug_init)
return;
while (buffer_len(&auth_debug)) {
msg = buffer_get_string(&auth_debug, NULL);
packet_send_debug("%s", msg);
xfree(msg);
}
}
void
auth_debug_reset(void)
{
if (auth_debug_init)
buffer_clear(&auth_debug);
else {
buffer_init(&auth_debug);
auth_debug_init = 1;
}
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth.h,v 1.29 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: auth.h,v 1.39 2002/05/31 11:35:15 markus Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -43,6 +43,7 @@
#endif
typedef struct Authctxt Authctxt;
typedef struct Authmethod Authmethod;
typedef struct KbdintDevice KbdintDevice;
struct Authctxt {
@ -71,6 +72,12 @@ struct Authctxt {
#endif
};
struct Authmethod {
char *name;
int (*userauth)(Authctxt *authctxt);
int *enabled;
};
/*
* Keyboard interactive device:
* init_ctx returns: non NULL upon success
@ -88,14 +95,21 @@ struct KbdintDevice
void (*free_ctx)(void *ctx);
};
int auth_rhosts(struct passwd *, const char *);
int auth_rhosts(struct passwd *, const char *);
int
auth_rhosts2(struct passwd *, const char *, const char *, const char *);
int auth_rhosts_rsa(struct passwd *, const char *, Key *);
int auth_rhosts_rsa(struct passwd *, char *, Key *);
int auth_password(Authctxt *, const char *);
int auth_rsa(struct passwd *, BIGNUM *);
int auth_rsa_challenge_dialog(RSA *);
int auth_rsa_challenge_dialog(Key *);
BIGNUM *auth_rsa_generate_challenge(Key *);
int auth_rsa_verify_response(Key *, BIGNUM *, u_char[]);
int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
int user_key_allowed(struct passwd *, Key *);
#ifdef KRB4
#include <krb.h>
@ -118,18 +132,27 @@ int auth_krb5_password(Authctxt *authctxt, const char *password);
void krb5_cleanup_proc(void *authctxt);
#endif /* KRB5 */
void do_authentication(void);
void do_authentication2(void);
Authctxt *do_authentication(void);
Authctxt *do_authentication2(void);
Authctxt *authctxt_new(void);
void auth_log(Authctxt *, int, char *, char *);
void userauth_finish(Authctxt *, int, char *);
int auth_root_allowed(char *);
char *auth2_read_banner(void);
void privsep_challenge_enable(void);
int auth2_challenge(Authctxt *, char *);
void auth2_challenge_stop(Authctxt *);
int bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
int bsdauth_respond(void *, u_int, char **);
int skey_query(void *, char **, char **, u_int *, char ***, u_int **);
int skey_respond(void *, u_int, char **);
int allowed_user(struct passwd *);
struct passwd * getpwnamallow(const char *user);
char *get_challenge(Authctxt *);
int verify_response(Authctxt *, const char *);
@ -147,8 +170,20 @@ HostStatus
check_key_in_hostfiles(struct passwd *, Key *, const char *,
const char *, const char *);
/* hostkey handling */
Key *get_hostkey_by_index(int);
Key *get_hostkey_by_type(int);
int get_hostkey_index(Key *);
int ssh1_session_key(BIGNUM *);
/* debug messages during authentication */
void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void auth_debug_send(void);
void auth_debug_reset(void);
#define AUTH_FAIL_MAX 6
#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
#define SKEY_PROMPT "\nS/Key Password: "
#endif

View File

@ -10,7 +10,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth1.c,v 1.35 2002/02/03 17:53:25 markus Exp $");
RCSID("$OpenBSD: auth1.c,v 1.41 2002/06/19 00:27:55 deraadt Exp $");
#include "xmalloc.h"
#include "rsa.h"
@ -24,8 +24,8 @@ RCSID("$OpenBSD: auth1.c,v 1.35 2002/02/03 17:53:25 markus Exp $");
#include "auth.h"
#include "channels.h"
#include "session.h"
#include "misc.h"
#include "uidswap.h"
#include "monitor_wrap.h"
/* import */
extern ServerOptions options;
@ -84,7 +84,7 @@ do_authloop(Authctxt *authctxt)
#if defined(KRB4) || defined(KRB5)
(!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif
auth_password(authctxt, "")) {
PRIVSEP(auth_password(authctxt, ""))) {
auth_log(authctxt, 1, "without authentication", "");
return;
}
@ -204,7 +204,7 @@ do_authloop(Authctxt *authctxt)
if (bits != BN_num_bits(client_host_key->rsa->n))
verbose("Warning: keysize mismatch for client_host_key: "
"actual %d, announced %d",
BN_num_bits(client_host_key->rsa->n), bits);
BN_num_bits(client_host_key->rsa->n), bits);
packet_check_eom();
authenticated = auth_rhosts_rsa(pw, client_user,
@ -243,7 +243,7 @@ do_authloop(Authctxt *authctxt)
packet_check_eom();
/* Try authentication with the password. */
authenticated = auth_password(authctxt, password);
authenticated = PRIVSEP(auth_password(authctxt, password));
memset(password, 0, strlen(password));
xfree(password);
@ -318,13 +318,12 @@ do_authloop(Authctxt *authctxt)
* Performs authentication of an incoming connection. Session key has already
* been exchanged and encryption is enabled.
*/
void
Authctxt *
do_authentication(void)
{
Authctxt *authctxt;
struct passwd *pw;
u_int ulen;
char *p, *user, *style = NULL;
char *user, *style = NULL;
/* Get the name of the user that we wish to log in as. */
packet_read_expect(SSH_CMSG_USER);
@ -336,32 +335,35 @@ do_authentication(void)
if ((style = strchr(user, ':')) != NULL)
*style++ = '\0';
#ifdef KRB5
/* XXX - SSH.com Kerberos v5 braindeath. */
if ((p = strchr(user, '@')) != NULL)
*p = '\0';
if ((datafellows & SSH_BUG_K5USER) &&
options.kerberos_authentication) {
char *p;
if ((p = strchr(user, '@')) != NULL)
*p = '\0';
}
#endif
authctxt = authctxt_new();
authctxt->user = user;
authctxt->style = style;
/* Verify that the user is a valid user. */
pw = getpwnam(user);
if (pw && allowed_user(pw)) {
if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
authctxt->valid = 1;
pw = pwcopy(pw);
} else {
else
debug("do_authentication: illegal user %s", user);
pw = NULL;
}
authctxt->pw = pw;
setproctitle("%s", pw ? user : "unknown");
setproctitle("%s%s", authctxt->pw ? user : "unknown",
use_privsep ? " [net]" : "");
/*
* If we are not running as root, the user must have the same uid as
* the server.
*/
if (getuid() != 0 && pw && pw->pw_uid != getuid())
if (!use_privsep && getuid() != 0 && authctxt->pw &&
authctxt->pw->pw_uid != getuid())
packet_disconnect("Cannot change user when server not running as root.");
/*
@ -375,6 +377,5 @@ do_authentication(void)
packet_send();
packet_write_wait();
/* Perform session preparation. */
do_authenticated(authctxt);
return (authctxt);
}

View File

@ -23,7 +23,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: auth2-chall.c,v 1.16 2002/01/13 17:57:37 markus Exp $");
RCSID("$OpenBSD: auth2-chall.c,v 1.18 2002/06/19 00:27:55 deraadt Exp $");
#include "ssh2.h"
#include "auth.h"
@ -219,7 +219,7 @@ send_userauth_info_request(Authctxt *authctxt)
packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST);
packet_put_cstring(name);
packet_put_cstring(instr);
packet_put_cstring(""); /* language not used */
packet_put_cstring(""); /* language not used */
packet_put_int(numprompts);
for (i = 0; i < numprompts; i++) {
packet_put_cstring(prompts[i]);
@ -310,3 +310,22 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
userauth_finish(authctxt, authenticated, method);
xfree(method);
}
void
privsep_challenge_enable(void)
{
#ifdef BSD_AUTH
extern KbdintDevice mm_bsdauth_device;
#endif
#ifdef SKEY
extern KbdintDevice mm_skey_device;
#endif
/* As long as SSHv1 has devices[0] hard coded this is fine */
#ifdef BSD_AUTH
devices[0] = &mm_bsdauth_device;
#else
#ifdef SKEY
devices[0] = &mm_skey_device;
#endif
#endif
}

View File

@ -0,0 +1,182 @@
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: auth2-hostbased.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
#include "ssh2.h"
#include "xmalloc.h"
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "servconf.h"
#include "compat.h"
#include "bufaux.h"
#include "auth.h"
#include "key.h"
#include "canohost.h"
#include "monitor_wrap.h"
#include "pathnames.h"
/* import */
extern ServerOptions options;
extern u_char *session_id2;
extern int session_id2_len;
static int
userauth_hostbased(Authctxt *authctxt)
{
Buffer b;
Key *key = NULL;
char *pkalg, *cuser, *chost, *service;
u_char *pkblob, *sig;
u_int alen, blen, slen;
int pktype;
int authenticated = 0;
if (!authctxt->valid) {
debug2("userauth_hostbased: disabled because of invalid user");
return 0;
}
pkalg = packet_get_string(&alen);
pkblob = packet_get_string(&blen);
chost = packet_get_string(NULL);
cuser = packet_get_string(NULL);
sig = packet_get_string(&slen);
debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
cuser, chost, pkalg, slen);
#ifdef DEBUG_PK
debug("signature:");
buffer_init(&b);
buffer_append(&b, sig, slen);
buffer_dump(&b);
buffer_free(&b);
#endif
pktype = key_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
/* this is perfectly legal */
log("userauth_hostbased: unsupported "
"public key algorithm: %s", pkalg);
goto done;
}
key = key_from_blob(pkblob, blen);
if (key == NULL) {
error("userauth_hostbased: cannot decode key: %s", pkalg);
goto done;
}
if (key->type != pktype) {
error("userauth_hostbased: type mismatch for decoded key "
"(received %d, expected %d)", key->type, pktype);
goto done;
}
service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
authctxt->service;
buffer_init(&b);
buffer_put_string(&b, session_id2, session_id2_len);
/* reconstruct packet */
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
buffer_put_cstring(&b, authctxt->user);
buffer_put_cstring(&b, service);
buffer_put_cstring(&b, "hostbased");
buffer_put_string(&b, pkalg, alen);
buffer_put_string(&b, pkblob, blen);
buffer_put_cstring(&b, chost);
buffer_put_cstring(&b, cuser);
#ifdef DEBUG_PK
buffer_dump(&b);
#endif
/* test for allowed key and correct signature */
authenticated = 0;
if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
buffer_len(&b))) == 1)
authenticated = 1;
buffer_clear(&b);
done:
debug2("userauth_hostbased: authenticated %d", authenticated);
if (key != NULL)
key_free(key);
xfree(pkalg);
xfree(pkblob);
xfree(cuser);
xfree(chost);
xfree(sig);
return authenticated;
}
/* return 1 if given hostkey is allowed */
int
hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
Key *key)
{
const char *resolvedname, *ipaddr, *lookup;
HostStatus host_status;
int len;
resolvedname = get_canonical_hostname(options.verify_reverse_mapping);
ipaddr = get_remote_ipaddr();
debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
chost, resolvedname, ipaddr);
if (options.hostbased_uses_name_from_packet_only) {
if (auth_rhosts2(pw, cuser, chost, chost) == 0)
return 0;
lookup = chost;
} else {
if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
debug2("stripping trailing dot from chost %s", chost);
chost[len - 1] = '\0';
}
if (strcasecmp(resolvedname, chost) != 0)
log("userauth_hostbased mismatch: "
"client sends %s, but we resolve %s to %s",
chost, ipaddr, resolvedname);
if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
return 0;
lookup = resolvedname;
}
debug2("userauth_hostbased: access allowed by auth_rhosts2");
host_status = check_key_in_hostfiles(pw, key, lookup,
_PATH_SSH_SYSTEM_HOSTFILE,
options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
/* backward compat if no key has been found. */
if (host_status == HOST_NEW)
host_status = check_key_in_hostfiles(pw, key, lookup,
_PATH_SSH_SYSTEM_HOSTFILE2,
options.ignore_user_known_hosts ? NULL :
_PATH_SSH_USER_HOSTFILE2);
return (host_status == HOST_OK);
}
Authmethod method_hostbased = {
"hostbased",
userauth_hostbased,
&options.hostbased_authentication
};

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: auth2-kbdint.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
#include "packet.h"
#include "auth.h"
#include "log.h"
#include "servconf.h"
#include "xmalloc.h"
/* import */
extern ServerOptions options;
static int
userauth_kbdint(Authctxt *authctxt)
{
int authenticated = 0;
char *lang, *devs;
lang = packet_get_string(NULL);
devs = packet_get_string(NULL);
packet_check_eom();
debug("keyboard-interactive devs %s", devs);
if (options.challenge_response_authentication)
authenticated = auth2_challenge(authctxt, devs);
xfree(devs);
xfree(lang);
return authenticated;
}
Authmethod method_kbdint = {
"keyboard-interactive",
userauth_kbdint,
&options.kbd_interactive_authentication
};

106
crypto/openssh/auth2-none.c Normal file
View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: auth2-none.c,v 1.3 2002/06/19 00:27:55 deraadt Exp $");
#include "auth.h"
#include "xmalloc.h"
#include "packet.h"
#include "log.h"
#include "servconf.h"
#include "atomicio.h"
#include "compat.h"
#include "ssh2.h"
#include "monitor_wrap.h"
/* import */
extern ServerOptions options;
/* "none" is allowed only one time */
static int none_enabled = 1;
char *
auth2_read_banner(void)
{
struct stat st;
char *banner = NULL;
off_t len, n;
int fd;
if ((fd = open(options.banner, O_RDONLY)) == -1)
return (NULL);
if (fstat(fd, &st) == -1) {
close(fd);
return (NULL);
}
len = st.st_size;
banner = xmalloc(len + 1);
n = atomicio(read, fd, banner, len);
close(fd);
if (n != len) {
free(banner);
return (NULL);
}
banner[n] = '\0';
return (banner);
}
static void
userauth_banner(void)
{
char *banner = NULL;
if (options.banner == NULL || (datafellows & SSH_BUG_BANNER))
return;
if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
goto done;
packet_start(SSH2_MSG_USERAUTH_BANNER);
packet_put_cstring(banner);
packet_put_cstring(""); /* language, unused */
packet_send();
debug("userauth_banner: sent");
done:
if (banner)
xfree(banner);
}
static int
userauth_none(Authctxt *authctxt)
{
none_enabled = 0;
packet_check_eom();
userauth_banner();
return (authctxt->valid ? PRIVSEP(auth_password(authctxt, "")) : 0);
}
Authmethod method_none = {
"none",
userauth_none,
&none_enabled
};

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: auth2-passwd.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
#include "xmalloc.h"
#include "packet.h"
#include "log.h"
#include "auth.h"
#include "monitor_wrap.h"
#include "servconf.h"
/* import */
extern ServerOptions options;
static int
userauth_passwd(Authctxt *authctxt)
{
char *password;
int authenticated = 0;
int change;
u_int len;
change = packet_get_char();
if (change)
log("password change not supported");
password = packet_get_string(&len);
packet_check_eom();
if (authctxt->valid &&
PRIVSEP(auth_password(authctxt, password)) == 1)
authenticated = 1;
memset(password, 0, len);
xfree(password);
return authenticated;
}
Authmethod method_passwd = {
"password",
userauth_passwd,
&options.password_authentication
};

View File

@ -0,0 +1,279 @@
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: auth2-pubkey.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
#include "ssh2.h"
#include "xmalloc.h"
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "servconf.h"
#include "compat.h"
#include "bufaux.h"
#include "auth.h"
#include "key.h"
#include "pathnames.h"
#include "uidswap.h"
#include "auth-options.h"
#include "canohost.h"
#include "monitor_wrap.h"
/* import */
extern ServerOptions options;
extern u_char *session_id2;
extern int session_id2_len;
static int
userauth_pubkey(Authctxt *authctxt)
{
Buffer b;
Key *key = NULL;
char *pkalg;
u_char *pkblob, *sig;
u_int alen, blen, slen;
int have_sig, pktype;
int authenticated = 0;
if (!authctxt->valid) {
debug2("userauth_pubkey: disabled because of invalid user");
return 0;
}
have_sig = packet_get_char();
if (datafellows & SSH_BUG_PKAUTH) {
debug2("userauth_pubkey: SSH_BUG_PKAUTH");
/* no explicit pkalg given */
pkblob = packet_get_string(&blen);
buffer_init(&b);
buffer_append(&b, pkblob, blen);
/* so we have to extract the pkalg from the pkblob */
pkalg = buffer_get_string(&b, &alen);
buffer_free(&b);
} else {
pkalg = packet_get_string(&alen);
pkblob = packet_get_string(&blen);
}
pktype = key_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
/* this is perfectly legal */
log("userauth_pubkey: unsupported public key algorithm: %s",
pkalg);
goto done;
}
key = key_from_blob(pkblob, blen);
if (key == NULL) {
error("userauth_pubkey: cannot decode key: %s", pkalg);
goto done;
}
if (key->type != pktype) {
error("userauth_pubkey: type mismatch for decoded key "
"(received %d, expected %d)", key->type, pktype);
goto done;
}
if (have_sig) {
sig = packet_get_string(&slen);
packet_check_eom();
buffer_init(&b);
if (datafellows & SSH_OLD_SESSIONID) {
buffer_append(&b, session_id2, session_id2_len);
} else {
buffer_put_string(&b, session_id2, session_id2_len);
}
/* reconstruct packet */
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
buffer_put_cstring(&b, authctxt->user);
buffer_put_cstring(&b,
datafellows & SSH_BUG_PKSERVICE ?
"ssh-userauth" :
authctxt->service);
if (datafellows & SSH_BUG_PKAUTH) {
buffer_put_char(&b, have_sig);
} else {
buffer_put_cstring(&b, "publickey");
buffer_put_char(&b, have_sig);
buffer_put_cstring(&b, pkalg);
}
buffer_put_string(&b, pkblob, blen);
#ifdef DEBUG_PK
buffer_dump(&b);
#endif
/* test for correct signature */
authenticated = 0;
if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
buffer_len(&b))) == 1)
authenticated = 1;
buffer_clear(&b);
xfree(sig);
} else {
debug("test whether pkalg/pkblob are acceptable");
packet_check_eom();
/* XXX fake reply and always send PK_OK ? */
/*
* XXX this allows testing whether a user is allowed
* to login: if you happen to have a valid pubkey this
* message is sent. the message is NEVER sent at all
* if a user is not allowed to login. is this an
* issue? -markus
*/
if (PRIVSEP(user_key_allowed(authctxt->pw, key))) {
packet_start(SSH2_MSG_USERAUTH_PK_OK);
packet_put_string(pkalg, alen);
packet_put_string(pkblob, blen);
packet_send();
packet_write_wait();
authctxt->postponed = 1;
}
}
if (authenticated != 1)
auth_clear_options();
done:
debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
if (key != NULL)
key_free(key);
xfree(pkalg);
xfree(pkblob);
return authenticated;
}
/* return 1 if user allows given key */
static int
user_key_allowed2(struct passwd *pw, Key *key, char *file)
{
char line[8192];
int found_key = 0;
FILE *f;
u_long linenum = 0;
struct stat st;
Key *found;
char *fp;
if (pw == NULL)
return 0;
/* Temporarily use the user's uid. */
temporarily_use_uid(pw);
debug("trying public key file %s", file);
/* Fail quietly if file does not exist */
if (stat(file, &st) < 0) {
/* Restore the privileged uid. */
restore_uid();
return 0;
}
/* Open the file containing the authorized keys. */
f = fopen(file, "r");
if (!f) {
/* Restore the privileged uid. */
restore_uid();
return 0;
}
if (options.strict_modes &&
secure_filename(f, file, pw, line, sizeof(line)) != 0) {
fclose(f);
log("Authentication refused: %s", line);
restore_uid();
return 0;
}
found_key = 0;
found = key_new(key->type);
while (fgets(line, sizeof(line), f)) {
char *cp, *options = NULL;
linenum++;
/* Skip leading whitespace, empty and comment lines. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '\n' || *cp == '#')
continue;
if (key_read(found, &cp) != 1) {
/* no key? check if there are options for this key */
int quoted = 0;
debug2("user_key_allowed: check options: '%s'", cp);
options = cp;
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
if (*cp == '\\' && cp[1] == '"')
cp++; /* Skip both */
else if (*cp == '"')
quoted = !quoted;
}
/* Skip remaining whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
if (key_read(found, &cp) != 1) {
debug2("user_key_allowed: advance: '%s'", cp);
/* still no key? advance to next line*/
continue;
}
}
if (key_equal(found, key) &&
auth_parse_options(pw, options, file, linenum) == 1) {
found_key = 1;
debug("matching key found: file %s, line %lu",
file, linenum);
fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
verbose("Found matching %s key: %s",
key_type(found), fp);
xfree(fp);
break;
}
}
restore_uid();
fclose(f);
key_free(found);
if (!found_key)
debug2("key not found");
return found_key;
}
/* check whether given key is in .ssh/authorized_keys* */
int
user_key_allowed(struct passwd *pw, Key *key)
{
int success;
char *file;
file = authorized_keys_file(pw);
success = user_key_allowed2(pw, key, file);
xfree(file);
if (success)
return success;
/* try suffix "2" for backward compat, too */
file = authorized_keys_file2(pw);
success = user_key_allowed2(pw, key, file);
xfree(file);
return success;
}
Authmethod method_pubkey = {
"publickey",
userauth_pubkey,
&options.pubkey_authentication
};

View File

@ -23,48 +23,41 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth2.c,v 1.85 2002/02/24 19:14:59 markus Exp $");
#include <openssl/evp.h>
RCSID("$OpenBSD: auth2.c,v 1.93 2002/05/31 11:35:15 markus Exp $");
#include "ssh2.h"
#include "xmalloc.h"
#include "rsa.h"
#include "sshpty.h"
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "servconf.h"
#include "compat.h"
#include "channels.h"
#include "bufaux.h"
#include "auth.h"
#include "session.h"
#include "dispatch.h"
#include "key.h"
#include "cipher.h"
#include "kex.h"
#include "pathnames.h"
#include "uidswap.h"
#include "auth-options.h"
#include "misc.h"
#include "hostfile.h"
#include "canohost.h"
#include "match.h"
#include "monitor_wrap.h"
/* import */
extern ServerOptions options;
extern u_char *session_id2;
extern int session_id2_len;
static Authctxt *x_authctxt = NULL;
static int one = 1;
Authctxt *x_authctxt = NULL;
typedef struct Authmethod Authmethod;
struct Authmethod {
char *name;
int (*userauth)(Authctxt *authctxt);
int *enabled;
/* methods */
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 */
@ -75,41 +68,14 @@ static void input_userauth_request(int, u_int32_t, void *);
/* helper */
static Authmethod *authmethod_lookup(const char *);
static char *authmethods_get(void);
static int user_key_allowed(struct passwd *, Key *);
static int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
/* auth */
static void userauth_banner(void);
static int userauth_none(Authctxt *);
static int userauth_passwd(Authctxt *);
static int userauth_pubkey(Authctxt *);
static int userauth_hostbased(Authctxt *);
static int userauth_kbdint(Authctxt *);
Authmethod authmethods[] = {
{"none",
userauth_none,
&one},
{"publickey",
userauth_pubkey,
&options.pubkey_authentication},
{"password",
userauth_passwd,
&options.password_authentication},
{"keyboard-interactive",
userauth_kbdint,
&options.kbd_interactive_authentication},
{"hostbased",
userauth_hostbased,
&options.hostbased_authentication},
{NULL, NULL, NULL}
};
int user_key_allowed(struct passwd *, Key *);
int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
/*
* loop until authctxt->success == TRUE
*/
void
Authctxt *
do_authentication2(void)
{
Authctxt *authctxt = authctxt_new();
@ -123,7 +89,8 @@ do_authentication2(void)
dispatch_init(&dispatch_protocol_error);
dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
do_authenticated(authctxt);
return (authctxt);
}
static void
@ -181,19 +148,20 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
if (authctxt->attempt++ == 0) {
/* setup auth context */
struct passwd *pw = NULL;
pw = getpwnam(user);
if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) {
authctxt->pw = pwcopy(pw);
authctxt->pw = PRIVSEP(getpwnamallow(user));
if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
authctxt->valid = 1;
debug2("input_userauth_request: setting up authctxt for %s", user);
} else {
log("input_userauth_request: illegal user %s", user);
}
setproctitle("%s", pw ? user : "unknown");
setproctitle("%s%s", authctxt->pw ? user : "unknown",
use_privsep ? " [net]" : "");
authctxt->user = xstrdup(user);
authctxt->service = xstrdup(service);
authctxt->style = style ? xstrdup(style) : NULL;
if (use_privsep)
mm_inform_authserv(service, style);
} else if (strcmp(user, authctxt->user) != 0 ||
strcmp(service, authctxt->service) != 0) {
packet_disconnect("Change of username or service not allowed: "
@ -259,281 +227,6 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
}
}
static void
userauth_banner(void)
{
struct stat st;
char *banner = NULL;
off_t len, n;
int fd;
if (options.banner == NULL || (datafellows & SSH_BUG_BANNER))
return;
if ((fd = open(options.banner, O_RDONLY)) < 0)
return;
if (fstat(fd, &st) < 0)
goto done;
len = st.st_size;
banner = xmalloc(len + 1);
if ((n = read(fd, banner, len)) < 0)
goto done;
banner[n] = '\0';
packet_start(SSH2_MSG_USERAUTH_BANNER);
packet_put_cstring(banner);
packet_put_cstring(""); /* language, unused */
packet_send();
debug("userauth_banner: sent");
done:
if (banner)
xfree(banner);
close(fd);
return;
}
static int
userauth_none(Authctxt *authctxt)
{
/* disable method "none", only allowed one time */
Authmethod *m = authmethod_lookup("none");
if (m != NULL)
m->enabled = NULL;
packet_check_eom();
userauth_banner();
return authctxt->valid ? auth_password(authctxt, "") : 0;
}
static int
userauth_passwd(Authctxt *authctxt)
{
char *password;
int authenticated = 0;
int change;
u_int len;
change = packet_get_char();
if (change)
log("password change not supported");
password = packet_get_string(&len);
packet_check_eom();
if (authctxt->valid &&
auth_password(authctxt, password) == 1)
authenticated = 1;
memset(password, 0, len);
xfree(password);
return authenticated;
}
static int
userauth_kbdint(Authctxt *authctxt)
{
int authenticated = 0;
char *lang, *devs;
lang = packet_get_string(NULL);
devs = packet_get_string(NULL);
packet_check_eom();
debug("keyboard-interactive devs %s", devs);
if (options.challenge_response_authentication)
authenticated = auth2_challenge(authctxt, devs);
xfree(devs);
xfree(lang);
return authenticated;
}
static int
userauth_pubkey(Authctxt *authctxt)
{
Buffer b;
Key *key = NULL;
char *pkalg;
u_char *pkblob, *sig;
u_int alen, blen, slen;
int have_sig, pktype;
int authenticated = 0;
if (!authctxt->valid) {
debug2("userauth_pubkey: disabled because of invalid user");
return 0;
}
have_sig = packet_get_char();
if (datafellows & SSH_BUG_PKAUTH) {
debug2("userauth_pubkey: SSH_BUG_PKAUTH");
/* no explicit pkalg given */
pkblob = packet_get_string(&blen);
buffer_init(&b);
buffer_append(&b, pkblob, blen);
/* so we have to extract the pkalg from the pkblob */
pkalg = buffer_get_string(&b, &alen);
buffer_free(&b);
} else {
pkalg = packet_get_string(&alen);
pkblob = packet_get_string(&blen);
}
pktype = key_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
/* this is perfectly legal */
log("userauth_pubkey: unsupported public key algorithm: %s",
pkalg);
goto done;
}
key = key_from_blob(pkblob, blen);
if (key == NULL) {
error("userauth_pubkey: cannot decode key: %s", pkalg);
goto done;
}
if (key->type != pktype) {
error("userauth_pubkey: type mismatch for decoded key "
"(received %d, expected %d)", key->type, pktype);
goto done;
}
if (have_sig) {
sig = packet_get_string(&slen);
packet_check_eom();
buffer_init(&b);
if (datafellows & SSH_OLD_SESSIONID) {
buffer_append(&b, session_id2, session_id2_len);
} else {
buffer_put_string(&b, session_id2, session_id2_len);
}
/* reconstruct packet */
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
buffer_put_cstring(&b, authctxt->user);
buffer_put_cstring(&b,
datafellows & SSH_BUG_PKSERVICE ?
"ssh-userauth" :
authctxt->service);
if (datafellows & SSH_BUG_PKAUTH) {
buffer_put_char(&b, have_sig);
} else {
buffer_put_cstring(&b, "publickey");
buffer_put_char(&b, have_sig);
buffer_put_cstring(&b, pkalg);
}
buffer_put_string(&b, pkblob, blen);
#ifdef DEBUG_PK
buffer_dump(&b);
#endif
/* test for correct signature */
if (user_key_allowed(authctxt->pw, key) &&
key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
authenticated = 1;
buffer_clear(&b);
xfree(sig);
} else {
debug("test whether pkalg/pkblob are acceptable");
packet_check_eom();
/* XXX fake reply and always send PK_OK ? */
/*
* XXX this allows testing whether a user is allowed
* to login: if you happen to have a valid pubkey this
* message is sent. the message is NEVER sent at all
* if a user is not allowed to login. is this an
* issue? -markus
*/
if (user_key_allowed(authctxt->pw, key)) {
packet_start(SSH2_MSG_USERAUTH_PK_OK);
packet_put_string(pkalg, alen);
packet_put_string(pkblob, blen);
packet_send();
packet_write_wait();
authctxt->postponed = 1;
}
}
if (authenticated != 1)
auth_clear_options();
done:
debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
if (key != NULL)
key_free(key);
xfree(pkalg);
xfree(pkblob);
return authenticated;
}
static int
userauth_hostbased(Authctxt *authctxt)
{
Buffer b;
Key *key = NULL;
char *pkalg, *cuser, *chost, *service;
u_char *pkblob, *sig;
u_int alen, blen, slen;
int pktype;
int authenticated = 0;
if (!authctxt->valid) {
debug2("userauth_hostbased: disabled because of invalid user");
return 0;
}
pkalg = packet_get_string(&alen);
pkblob = packet_get_string(&blen);
chost = packet_get_string(NULL);
cuser = packet_get_string(NULL);
sig = packet_get_string(&slen);
debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
cuser, chost, pkalg, slen);
#ifdef DEBUG_PK
debug("signature:");
buffer_init(&b);
buffer_append(&b, sig, slen);
buffer_dump(&b);
buffer_free(&b);
#endif
pktype = key_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
/* this is perfectly legal */
log("userauth_hostbased: unsupported "
"public key algorithm: %s", pkalg);
goto done;
}
key = key_from_blob(pkblob, blen);
if (key == NULL) {
error("userauth_hostbased: cannot decode key: %s", pkalg);
goto done;
}
if (key->type != pktype) {
error("userauth_hostbased: type mismatch for decoded key "
"(received %d, expected %d)", key->type, pktype);
goto done;
}
service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
authctxt->service;
buffer_init(&b);
buffer_put_string(&b, session_id2, session_id2_len);
/* reconstruct packet */
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
buffer_put_cstring(&b, authctxt->user);
buffer_put_cstring(&b, service);
buffer_put_cstring(&b, "hostbased");
buffer_put_string(&b, pkalg, alen);
buffer_put_string(&b, pkblob, blen);
buffer_put_cstring(&b, chost);
buffer_put_cstring(&b, cuser);
#ifdef DEBUG_PK
buffer_dump(&b);
#endif
/* test for allowed key and correct signature */
if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) &&
key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
authenticated = 1;
buffer_clear(&b);
done:
debug2("userauth_hostbased: authenticated %d", authenticated);
if (key != NULL)
key_free(key);
xfree(pkalg);
xfree(pkblob);
xfree(cuser);
xfree(chost);
xfree(sig);
return authenticated;
}
/* get current user */
struct passwd*
@ -547,18 +240,20 @@ auth_get_user(void)
static char *
authmethods_get(void)
{
Authmethod *method = NULL;
Buffer b;
char *list;
int i;
buffer_init(&b);
for (method = authmethods; method->name != NULL; method++) {
if (strcmp(method->name, "none") == 0)
for (i = 0; authmethods[i] != NULL; i++) {
if (strcmp(authmethods[i]->name, "none") == 0)
continue;
if (method->enabled != NULL && *(method->enabled) != 0) {
if (authmethods[i]->enabled != NULL &&
*(authmethods[i]->enabled) != 0) {
if (buffer_len(&b) > 0)
buffer_append(&b, ",", 1);
buffer_append(&b, method->name, strlen(method->name));
buffer_append(&b, authmethods[i]->name,
strlen(authmethods[i]->name));
}
}
buffer_append(&b, "\0", 1);
@ -570,174 +265,15 @@ authmethods_get(void)
static Authmethod *
authmethod_lookup(const char *name)
{
Authmethod *method = NULL;
int i;
if (name != NULL)
for (method = authmethods; method->name != NULL; method++)
if (method->enabled != NULL &&
*(method->enabled) != 0 &&
strcmp(name, method->name) == 0)
return method;
debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
for (i = 0; authmethods[i] != NULL; i++)
if (authmethods[i]->enabled != NULL &&
*(authmethods[i]->enabled) != 0 &&
strcmp(name, authmethods[i]->name) == 0)
return authmethods[i];
debug2("Unrecognized authentication method name: %s",
name ? name : "NULL");
return NULL;
}
/* return 1 if user allows given key */
static int
user_key_allowed2(struct passwd *pw, Key *key, char *file)
{
char line[8192];
int found_key = 0;
FILE *f;
u_long linenum = 0;
struct stat st;
Key *found;
char *fp;
if (pw == NULL)
return 0;
/* Temporarily use the user's uid. */
temporarily_use_uid(pw);
debug("trying public key file %s", file);
/* Fail quietly if file does not exist */
if (stat(file, &st) < 0) {
/* Restore the privileged uid. */
restore_uid();
return 0;
}
/* Open the file containing the authorized keys. */
f = fopen(file, "r");
if (!f) {
/* Restore the privileged uid. */
restore_uid();
return 0;
}
if (options.strict_modes &&
secure_filename(f, file, pw, line, sizeof(line)) != 0) {
fclose(f);
log("Authentication refused: %s", line);
restore_uid();
return 0;
}
found_key = 0;
found = key_new(key->type);
while (fgets(line, sizeof(line), f)) {
char *cp, *options = NULL;
linenum++;
/* Skip leading whitespace, empty and comment lines. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '\n' || *cp == '#')
continue;
if (key_read(found, &cp) != 1) {
/* no key? check if there are options for this key */
int quoted = 0;
debug2("user_key_allowed: check options: '%s'", cp);
options = cp;
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
if (*cp == '\\' && cp[1] == '"')
cp++; /* Skip both */
else if (*cp == '"')
quoted = !quoted;
}
/* Skip remaining whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
if (key_read(found, &cp) != 1) {
debug2("user_key_allowed: advance: '%s'", cp);
/* still no key? advance to next line*/
continue;
}
}
if (key_equal(found, key) &&
auth_parse_options(pw, options, file, linenum) == 1) {
found_key = 1;
debug("matching key found: file %s, line %lu",
file, linenum);
fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
verbose("Found matching %s key: %s",
key_type(found), fp);
xfree(fp);
break;
}
}
restore_uid();
fclose(f);
key_free(found);
if (!found_key)
debug2("key not found");
return found_key;
}
/* check whether given key is in .ssh/authorized_keys* */
static int
user_key_allowed(struct passwd *pw, Key *key)
{
int success;
char *file;
file = authorized_keys_file(pw);
success = user_key_allowed2(pw, key, file);
xfree(file);
if (success)
return success;
/* try suffix "2" for backward compat, too */
file = authorized_keys_file2(pw);
success = user_key_allowed2(pw, key, file);
xfree(file);
return success;
}
/* return 1 if given hostkey is allowed */
static int
hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
Key *key)
{
const char *resolvedname, *ipaddr, *lookup;
HostStatus host_status;
int len;
resolvedname = get_canonical_hostname(options.verify_reverse_mapping);
ipaddr = get_remote_ipaddr();
debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
chost, resolvedname, ipaddr);
if (options.hostbased_uses_name_from_packet_only) {
if (auth_rhosts2(pw, cuser, chost, chost) == 0)
return 0;
lookup = chost;
} else {
if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
debug2("stripping trailing dot from chost %s", chost);
chost[len - 1] = '\0';
}
if (strcasecmp(resolvedname, chost) != 0)
log("userauth_hostbased mismatch: "
"client sends %s, but we resolve %s to %s",
chost, ipaddr, resolvedname);
if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
return 0;
lookup = resolvedname;
}
debug2("userauth_hostbased: access allowed by auth_rhosts2");
host_status = check_key_in_hostfiles(pw, key, lookup,
_PATH_SSH_SYSTEM_HOSTFILE,
options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
/* backward compat if no key has been found. */
if (host_status == HOST_NEW)
host_status = check_key_in_hostfiles(pw, key, lookup,
_PATH_SSH_SYSTEM_HOSTFILE2,
options.ignore_user_known_hosts ? NULL :
_PATH_SSH_USER_HOSTFILE2);
return (host_status == HOST_OK);
}

View File

@ -35,7 +35,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: authfd.c,v 1.48 2002/02/24 19:14:59 markus Exp $");
RCSID("$OpenBSD: authfd.c,v 1.55 2002/06/19 00:27:55 deraadt Exp $");
#include <openssl/evp.h>
@ -59,7 +59,7 @@ int decode_reply(int type);
/* macro to check for "agent failure" message */
#define agent_failed(x) \
((x == SSH_AGENT_FAILURE) || (x == SSH_COM_AGENT2_FAILURE) || \
(x == SSH2_AGENT_FAILURE))
(x == SSH2_AGENT_FAILURE))
/* Returns the number of the authentication fd, or -1 if there is none. */
@ -207,6 +207,26 @@ ssh_close_authentication_connection(AuthenticationConnection *auth)
xfree(auth);
}
/* Lock/unlock agent */
int
ssh_lock_agent(AuthenticationConnection *auth, int lock, const char *password)
{
int type;
Buffer msg;
buffer_init(&msg);
buffer_put_char(&msg, lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK);
buffer_put_cstring(&msg, password);
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return 0;
}
type = buffer_get_char(&msg);
buffer_free(&msg);
return decode_reply(type);
}
/*
* Returns the first authentication identity held by the agent.
*/
@ -419,8 +439,6 @@ ssh_agent_sign(AuthenticationConnection *auth,
static void
ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
{
buffer_clear(b);
buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY);
buffer_put_int(b, BN_num_bits(key->n));
buffer_put_bignum(b, key->n);
buffer_put_bignum(b, key->e);
@ -435,8 +453,6 @@ ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
static void
ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
{
buffer_clear(b);
buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY);
buffer_put_cstring(b, key_ssh_name(key));
switch (key->type) {
case KEY_RSA:
@ -464,19 +480,28 @@ ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
*/
int
ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
const char *comment, u_int life)
{
Buffer msg;
int type;
int type, constrained = (life != 0);
buffer_init(&msg);
switch (key->type) {
case KEY_RSA1:
type = constrained ?
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED :
SSH_AGENTC_ADD_RSA_IDENTITY;
buffer_put_char(&msg, type);
ssh_encode_identity_rsa1(&msg, key->rsa, comment);
break;
case KEY_RSA:
case KEY_DSA:
type = constrained ?
SSH2_AGENTC_ADD_ID_CONSTRAINED :
SSH2_AGENTC_ADD_IDENTITY;
buffer_put_char(&msg, type);
ssh_encode_identity_ssh2(&msg, key, comment);
break;
default:
@ -484,6 +509,12 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
return 0;
break;
}
if (constrained) {
if (life != 0) {
buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME);
buffer_put_int(&msg, life);
}
}
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return 0;
@ -493,6 +524,12 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
return decode_reply(type);
}
int
ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
{
return ssh_add_identity_constrained(auth, key, comment, 0);
}
/*
* Removes an identity from the authentication server. This call is not
* meant to be used by normal applications.
@ -532,7 +569,7 @@ ssh_remove_identity(AuthenticationConnection *auth, Key *key)
}
int
ssh_update_card(AuthenticationConnection *auth, int add, const char *reader_id)
ssh_update_card(AuthenticationConnection *auth, int add, const char *reader_id, const char *pin)
{
Buffer msg;
int type;
@ -541,6 +578,7 @@ ssh_update_card(AuthenticationConnection *auth, int add, const char *reader_id)
buffer_put_char(&msg, add ? SSH_AGENTC_ADD_SMARTCARD_KEY :
SSH_AGENTC_REMOVE_SMARTCARD_KEY);
buffer_put_cstring(&msg, reader_id);
buffer_put_cstring(&msg, pin);
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return 0;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: authfd.h,v 1.23 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: authfd.h,v 1.30 2002/06/19 00:27:55 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -40,34 +40,46 @@
/* smartcard */
#define SSH_AGENTC_ADD_SMARTCARD_KEY 20
#define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
#define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
/* lock/unlock the agent */
#define SSH_AGENTC_LOCK 22
#define SSH_AGENTC_UNLOCK 23
/* add key with constraints */
#define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24
#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25
#define SSH_AGENT_CONSTRAIN_LIFETIME 1
/* extended failure messages */
#define SSH2_AGENT_FAILURE 30
/* additional error code for ssh.com's ssh-agent2 */
#define SSH_COM_AGENT2_FAILURE 102
#define SSH_COM_AGENT2_FAILURE 102
#define SSH_AGENT_OLD_SIGNATURE 0x01
typedef struct {
int fd;
Buffer identities;
int howmany;
} AuthenticationConnection;
int fd;
Buffer identities;
int howmany;
} AuthenticationConnection;
int ssh_get_authentication_socket(void);
void ssh_close_authentication_socket(int);
int ssh_get_authentication_socket(void);
void ssh_close_authentication_socket(int);
AuthenticationConnection *ssh_get_authentication_connection(void);
void ssh_close_authentication_connection(AuthenticationConnection *);
void ssh_close_authentication_connection(AuthenticationConnection *);
int ssh_get_num_identities(AuthenticationConnection *, int);
Key *ssh_get_first_identity(AuthenticationConnection *, char **, int);
Key *ssh_get_next_identity(AuthenticationConnection *, char **, int);
int ssh_add_identity(AuthenticationConnection *, Key *, const char *);
int ssh_add_identity_constrained(AuthenticationConnection *, Key *, const char *, u_int);
int ssh_remove_identity(AuthenticationConnection *, Key *);
int ssh_remove_all_identities(AuthenticationConnection *, int);
int ssh_update_card(AuthenticationConnection *, int, const char *);
int ssh_lock_agent(AuthenticationConnection *, int, const char *);
int ssh_update_card(AuthenticationConnection *, int, const char *, const char *);
int
ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16],

View File

@ -36,7 +36,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: authfile.c,v 1.48 2002/02/28 15:46:33 markus Exp $");
RCSID("$OpenBSD: authfile.c,v 1.49 2002/05/23 19:24:30 markus Exp $");
#include <openssl/err.h>
#include <openssl/evp.h>
@ -421,7 +421,7 @@ key_load_private_rsa1(int fd, const char *filename, const char *passphrase,
return NULL;
}
static Key *
Key *
key_load_private_pem(int fd, int type, const char *passphrase,
char **commentp)
{

View File

@ -1,4 +1,4 @@
/* $OpenBSD: authfile.h,v 1.9 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: authfile.h,v 1.10 2002/05/23 19:24:30 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -20,5 +20,6 @@ Key *key_load_public(const char *, char **);
Key *key_load_public_type(int, const char *, char **);
Key *key_load_private(const char *, const char *, char **);
Key *key_load_private_type(int, const char *, const char *, char **);
Key *key_load_private_pem(int, int, const char *, char **);
#endif

View File

@ -37,7 +37,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: bufaux.c,v 1.22 2002/01/18 18:14:17 stevesk Exp $");
RCSID("$OpenBSD: bufaux.c,v 1.25 2002/04/20 09:14:58 markus Exp $");
#include <openssl/bn.h>
#include "bufaux.h"
@ -137,10 +137,18 @@ buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
BN_bin2bn(bin, len, value);
xfree(bin);
}
/*
* Returns an integer from the buffer (4 bytes, msb first).
* Returns integers from the buffer (msb first).
*/
u_short
buffer_get_short(Buffer *buffer)
{
u_char buf[2];
buffer_get(buffer, (char *) buf, 2);
return GET_16BIT(buf);
}
u_int
buffer_get_int(Buffer *buffer)
{
@ -158,8 +166,16 @@ 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)
{
@ -192,7 +208,7 @@ buffer_get_string(Buffer *buffer, u_int *length_ptr)
/* Get the length. */
len = buffer_get_int(buffer);
if (len > 256 * 1024)
fatal("Received packet with bad string length %d", len);
fatal("buffer_get_string: bad string length %d", len);
/* Allocate space for the string. Add one byte for a null character. */
value = xmalloc(len + 1);
/* Get the string. */
@ -217,6 +233,8 @@ buffer_put_string(Buffer *buffer, const void *buf, u_int len)
void
buffer_put_cstring(Buffer *buffer, const char *s)
{
if (s == NULL)
fatal("buffer_put_cstring: s == NULL");
buffer_put_string(buffer, s, strlen(s));
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: bufaux.h,v 1.16 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: bufaux.h,v 1.18 2002/04/20 09:14:58 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -23,6 +23,9 @@ void buffer_put_bignum2(Buffer *, BIGNUM *);
void buffer_get_bignum(Buffer *, BIGNUM *);
void buffer_get_bignum2(Buffer *, BIGNUM *);
u_short buffer_get_short(Buffer *);
void buffer_put_short(Buffer *, u_short);
u_int buffer_get_int(Buffer *);
void buffer_put_int(Buffer *, u_int);
@ -36,4 +39,7 @@ void *buffer_get_string(Buffer *, u_int *);
void buffer_put_string(Buffer *, const void *, u_int);
void buffer_put_cstring(Buffer *, const char *);
#define buffer_skip_string(b) \
do { u_int l = buffer_get_int(b); buffer_consume(b, l); } while(0)
#endif /* BUFAUX_H */

View File

@ -12,7 +12,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: canohost.c,v 1.31 2002/02/27 21:23:13 stevesk Exp $");
RCSID("$OpenBSD: canohost.c,v 1.32 2002/06/11 08:11:45 itojun Exp $");
#include "packet.h"
#include "xmalloc.h"
@ -42,13 +42,14 @@ get_remote_hostname(int socket, int verify_reverse_mapping)
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
if (from.ss_family == AF_INET)
check_ip_options(socket, ntop);
if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
NULL, 0, NI_NUMERICHOST) != 0)
fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
if (from.ss_family == AF_INET)
check_ip_options(socket, ntop);
debug3("Trying to reverse map address %.100s.", ntop);
/* Map the IP address to a host name. */
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),

View File

@ -39,14 +39,13 @@
*/
#include "includes.h"
RCSID("$OpenBSD: channels.c,v 1.171 2002/03/04 19:37:58 markus Exp $");
RCSID("$OpenBSD: channels.c,v 1.175 2002/06/10 22:28:41 markus Exp $");
#include "ssh.h"
#include "ssh1.h"
#include "ssh2.h"
#include "packet.h"
#include "xmalloc.h"
#include "uidswap.h"
#include "log.h"
#include "misc.h"
#include "channels.h"
@ -129,10 +128,6 @@ static u_int x11_fake_data_len;
#define NUM_SOCKS 10
/* Name and directory of socket for authentication agent forwarding. */
static char *auth_sock_name = NULL;
static char *auth_sock_dir = NULL;
/* AF_UNSPEC or AF_INET or AF_INET6 */
static int IPv4or6 = AF_UNSPEC;
@ -706,7 +701,11 @@ channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset)
if (buffer_len(&c->output) > 0) {
FD_SET(c->wfd, writeset);
} else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
chan_obuf_empty(c);
if (CHANNEL_EFD_OUTPUT_ACTIVE(c))
debug2("channel %d: obuf_empty delayed efd %d/(%d)",
c->self, c->efd, buffer_len(&c->extended));
else
chan_obuf_empty(c);
}
}
/** XXX check close conditions, too */
@ -714,7 +713,8 @@ channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset)
if (c->extended_usage == CHAN_EXTENDED_WRITE &&
buffer_len(&c->extended) > 0)
FD_SET(c->efd, writeset);
else if (c->extended_usage == CHAN_EXTENDED_READ &&
else if (!(c->flags & CHAN_EOF_SENT) &&
c->extended_usage == CHAN_EXTENDED_READ &&
buffer_len(&c->extended) < c->remote_window)
FD_SET(c->efd, readset);
}
@ -1632,12 +1632,18 @@ channel_output_poll(void)
fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3");
/*
* input-buffer is empty and read-socket shutdown:
* tell peer, that we will not send more data: send IEOF
* tell peer, that we will not send more data: send IEOF.
* hack for extended data: delay EOF if EFD still in use.
*/
chan_ibuf_empty(c);
if (CHANNEL_EFD_INPUT_ACTIVE(c))
debug2("channel %d: ibuf_empty delayed efd %d/(%d)",
c->self, c->efd, buffer_len(&c->extended));
else
chan_ibuf_empty(c);
}
/* Send extended data, i.e. stderr */
if (compat20 &&
!(c->flags & CHAN_EOF_SENT) &&
c->remote_window > 0 &&
(len = buffer_len(&c->extended)) > 0 &&
c->extended_usage == CHAN_EXTENDED_READ) {
@ -1726,6 +1732,13 @@ channel_input_extended_data(int type, u_int32_t seq, void *ctxt)
log("channel %d: ext data for non open", id);
return;
}
if (c->flags & CHAN_EOF_RCVD) {
if (datafellows & SSH_BUG_EXTEOF)
debug("channel %d: accepting ext data after eof", id);
else
packet_disconnect("Received extended_data after EOF "
"on channel %d.", id);
}
tcode = packet_get_int();
if (c->efd == -1 ||
c->extended_usage != CHAN_EXTENDED_WRITE ||
@ -2108,7 +2121,7 @@ channel_request_remote_forwarding(u_short listen_port,
const char *address_to_bind = "0.0.0.0";
packet_start(SSH2_MSG_GLOBAL_REQUEST);
packet_put_cstring("tcpip-forward");
packet_put_char(0); /* boolean: want reply */
packet_put_char(1); /* boolean: want reply */
packet_put_cstring(address_to_bind);
packet_put_int(listen_port);
packet_send();
@ -2654,105 +2667,6 @@ auth_request_forwarding(void)
packet_write_wait();
}
/*
* Returns the name of the forwarded authentication socket. Returns NULL if
* there is no forwarded authentication socket. The returned value points to
* a static buffer.
*/
char *
auth_get_socket_name(void)
{
return auth_sock_name;
}
/* removes the agent forwarding socket */
void
auth_sock_cleanup_proc(void *_pw)
{
struct passwd *pw = _pw;
if (auth_sock_name) {
temporarily_use_uid(pw);
unlink(auth_sock_name);
rmdir(auth_sock_dir);
auth_sock_name = NULL;
restore_uid();
}
}
/*
* This is called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server.
* This starts forwarding authentication requests.
*/
int
auth_input_request_forwarding(struct passwd * pw)
{
Channel *nc;
int sock;
struct sockaddr_un sunaddr;
if (auth_get_socket_name() != NULL) {
error("authentication forwarding requested twice.");
return 0;
}
/* Temporarily drop privileged uid for mkdir/bind. */
temporarily_use_uid(pw);
/* Allocate a buffer for the socket name, and format the name. */
auth_sock_name = xmalloc(MAXPATHLEN);
auth_sock_dir = xmalloc(MAXPATHLEN);
strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
/* Create private directory for socket */
if (mkdtemp(auth_sock_dir) == NULL) {
packet_send_debug("Agent forwarding disabled: "
"mkdtemp() failed: %.100s", strerror(errno));
restore_uid();
xfree(auth_sock_name);
xfree(auth_sock_dir);
auth_sock_name = NULL;
auth_sock_dir = NULL;
return 0;
}
snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%d",
auth_sock_dir, (int) getpid());
/* delete agent socket on fatal() */
fatal_add_cleanup(auth_sock_cleanup_proc, pw);
/* Create the socket. */
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
packet_disconnect("socket: %.100s", strerror(errno));
/* Bind it to the name. */
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0)
packet_disconnect("bind: %.100s", strerror(errno));
/* Restore the privileged uid. */
restore_uid();
/* Start listening on the socket. */
if (listen(sock, 5) < 0)
packet_disconnect("listen: %.100s", strerror(errno));
/* Allocate a channel for the authentication agent socket. */
nc = channel_new("auth socket",
SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
0, xstrdup("auth socket"), 1);
strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
return 1;
}
/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
void

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.h,v 1.65 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: channels.h,v 1.68 2002/06/10 22:28:41 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -135,6 +135,18 @@ struct Channel {
#define CHAN_CLOSE_SENT 0x01
#define CHAN_CLOSE_RCVD 0x02
#define CHAN_EOF_SENT 0x04
#define CHAN_EOF_RCVD 0x08
/* check whether 'efd' is still in use */
#define CHANNEL_EFD_INPUT_ACTIVE(c) \
(compat20 && c->extended_usage == CHAN_EXTENDED_READ && \
(c->efd != -1 || \
buffer_len(&c->extended) > 0))
#define CHANNEL_EFD_OUTPUT_ACTIVE(c) \
(compat20 && c->extended_usage == CHAN_EXTENDED_WRITE && \
((c->efd != -1 && !(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD))) || \
buffer_len(&c->extended) > 0))
/* channel management */
@ -201,9 +213,6 @@ void deny_input_open(int, u_int32_t, void *);
/* agent forwarding */
void auth_request_forwarding(void);
char *auth_get_socket_name(void);
void auth_sock_cleanup_proc(void *);
int auth_input_request_forwarding(struct passwd *);
void auth_input_open_request(int, u_int32_t, void *);
/* channel close */

View File

@ -35,25 +35,27 @@
*/
#include "includes.h"
RCSID("$OpenBSD: cipher.c,v 1.52 2002/02/18 13:05:32 markus Exp $");
RCSID("$OpenBSD: cipher.c,v 1.59 2002/06/19 18:01:00 markus Exp $");
#include "xmalloc.h"
#include "log.h"
#include "cipher.h"
#include <openssl/md5.h>
#include "rijndael.h"
static EVP_CIPHER *evp_ssh1_3des(void);
static EVP_CIPHER *evp_ssh1_bf(void);
static EVP_CIPHER *evp_rijndael(void);
#if OPENSSL_VERSION_NUMBER < 0x00907000L
#include "rijndael.h"
static const EVP_CIPHER *evp_rijndael(void);
#endif
static const EVP_CIPHER *evp_ssh1_3des(void);
static const EVP_CIPHER *evp_ssh1_bf(void);
struct Cipher {
char *name;
int number; /* for ssh1 only */
u_int block_size;
u_int key_len;
EVP_CIPHER *(*evptype)(void);
const EVP_CIPHER *(*evptype)(void);
} ciphers[] = {
{ "none", SSH_CIPHER_NONE, 8, 0, EVP_enc_null },
{ "des", SSH_CIPHER_DES, 8, 8, EVP_des_cbc },
@ -64,25 +66,40 @@ struct Cipher {
{ "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_bf_cbc },
{ "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_cast5_cbc },
{ "arcfour", SSH_CIPHER_SSH2, 8, 16, EVP_rc4 },
#if OPENSSL_VERSION_NUMBER < 0x00907000L
{ "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, evp_rijndael },
{ "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, evp_rijndael },
{ "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, evp_rijndael },
{ "rijndael-cbc@lysator.liu.se",
SSH_CIPHER_SSH2, 16, 32, evp_rijndael },
#else
{ "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, EVP_aes_128_cbc },
{ "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, EVP_aes_192_cbc },
{ "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc },
{ "rijndael-cbc@lysator.liu.se",
SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc },
#endif
{ NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL }
};
/*--*/
u_int
u_int
cipher_blocksize(Cipher *c)
{
return (c->block_size);
}
u_int
u_int
cipher_keylen(Cipher *c)
{
return (c->key_len);
}
u_int
cipher_get_number(Cipher *c)
{
return (c->number);
}
u_int
cipher_mask_ssh1(int client)
@ -333,7 +350,7 @@ ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
}
return (1);
}
static EVP_CIPHER *
static const EVP_CIPHER *
evp_ssh1_3des(void)
{
static EVP_CIPHER ssh1_3des;
@ -383,7 +400,7 @@ bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len)
swap_bytes(out, out, len);
return (ret);
}
static EVP_CIPHER *
static const EVP_CIPHER *
evp_ssh1_bf(void)
{
static EVP_CIPHER ssh1_bf;
@ -396,6 +413,7 @@ evp_ssh1_bf(void)
return (&ssh1_bf);
}
#if OPENSSL_VERSION_NUMBER < 0x00907000L
/* RIJNDAEL */
#define RIJNDAEL_BLOCKSIZE 16
struct ssh_rijndael_ctx
@ -481,7 +499,7 @@ ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
}
return (1);
}
static EVP_CIPHER *
static const EVP_CIPHER *
evp_rijndael(void)
{
static EVP_CIPHER rijndal_cbc;
@ -498,3 +516,155 @@ evp_rijndael(void)
EVP_CIPH_ALWAYS_CALL_INIT;
return (&rijndal_cbc);
}
#endif
/*
* Exports an IV from the CipherContext required to export the key
* state back from the unprivileged child to the privileged parent
* process.
*/
int
cipher_get_keyiv_len(CipherContext *cc)
{
Cipher *c = cc->cipher;
int ivlen;
if (c->number == SSH_CIPHER_3DES)
ivlen = 24;
else
ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
return (ivlen);
}
void
cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
{
Cipher *c = cc->cipher;
u_char *civ = NULL;
int evplen;
switch (c->number) {
case SSH_CIPHER_SSH2:
case SSH_CIPHER_DES:
case SSH_CIPHER_BLOWFISH:
evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
if (evplen == 0)
return;
if (evplen != len)
fatal("%s: wrong iv length %d != %d", __func__,
evplen, len);
#if OPENSSL_VERSION_NUMBER < 0x00907000L
if (c->evptype == evp_rijndael) {
struct ssh_rijndael_ctx *aesc;
aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
if (aesc == NULL)
fatal("%s: no rijndael context", __func__);
civ = aesc->r_iv;
} else
#endif
{
civ = cc->evp.iv;
}
break;
case SSH_CIPHER_3DES: {
struct ssh1_3des_ctx *desc;
if (len != 24)
fatal("%s: bad 3des iv length: %d", __func__, len);
desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
if (desc == NULL)
fatal("%s: no 3des context", __func__);
debug3("%s: Copying 3DES IV", __func__);
memcpy(iv, desc->k1.iv, 8);
memcpy(iv + 8, desc->k2.iv, 8);
memcpy(iv + 16, desc->k3.iv, 8);
return;
}
default:
fatal("%s: bad cipher %d", __func__, c->number);
}
memcpy(iv, civ, len);
}
void
cipher_set_keyiv(CipherContext *cc, u_char *iv)
{
Cipher *c = cc->cipher;
u_char *div = NULL;
int evplen = 0;
switch (c->number) {
case SSH_CIPHER_SSH2:
case SSH_CIPHER_DES:
case SSH_CIPHER_BLOWFISH:
evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
if (evplen == 0)
return;
#if OPENSSL_VERSION_NUMBER < 0x00907000L
if (c->evptype == evp_rijndael) {
struct ssh_rijndael_ctx *aesc;
aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
if (aesc == NULL)
fatal("%s: no rijndael context", __func__);
div = aesc->r_iv;
} else
#endif
{
div = cc->evp.iv;
}
break;
case SSH_CIPHER_3DES: {
struct ssh1_3des_ctx *desc;
desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
if (desc == NULL)
fatal("%s: no 3des context", __func__);
debug3("%s: Installed 3DES IV", __func__);
memcpy(desc->k1.iv, iv, 8);
memcpy(desc->k2.iv, iv + 8, 8);
memcpy(desc->k3.iv, iv + 16, 8);
return;
}
default:
fatal("%s: bad cipher %d", __func__, c->number);
}
memcpy(div, iv, evplen);
}
#if OPENSSL_VERSION_NUMBER < 0x00907000L
#define EVP_X_STATE(evp) &(evp).c
#define EVP_X_STATE_LEN(evp) sizeof((evp).c)
#else
#define EVP_X_STATE(evp) (evp).cipher_data
#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size
#endif
int
cipher_get_keycontext(CipherContext *cc, u_char *dat)
{
Cipher *c = cc->cipher;
int plen = 0;
if (c->evptype == EVP_rc4) {
plen = EVP_X_STATE_LEN(cc->evp);
if (dat == NULL)
return (plen);
memcpy(dat, EVP_X_STATE(cc->evp), plen);
}
return (plen);
}
void
cipher_set_keycontext(CipherContext *cc, u_char *dat)
{
Cipher *c = cc->cipher;
int plen;
if (c->evptype == EVP_rc4) {
plen = EVP_X_STATE_LEN(cc->evp);
memcpy(EVP_X_STATE(cc->evp), dat, plen);
}
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cipher.h,v 1.32 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: cipher.h,v 1.33 2002/03/18 17:13:15 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -81,4 +81,11 @@ void cipher_cleanup(CipherContext *);
void cipher_set_key_string(CipherContext *, Cipher *, const char *, int);
u_int cipher_blocksize(Cipher *);
u_int cipher_keylen(Cipher *);
u_int cipher_get_number(Cipher *);
void cipher_get_keyiv(CipherContext *, u_char *, u_int);
void cipher_set_keyiv(CipherContext *, u_char *);
int cipher_get_keyiv_len(CipherContext *);
int cipher_get_keycontext(CipherContext *, u_char *);
void cipher_set_keycontext(CipherContext *, u_char *);
#endif /* CIPHER_H */

View File

@ -59,7 +59,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: clientloop.c,v 1.96 2002/02/06 14:55:15 markus Exp $");
RCSID("$OpenBSD: clientloop.c,v 1.101 2002/06/09 13:32:01 markus Exp $");
#include "ssh.h"
#include "ssh1.h"
@ -81,6 +81,7 @@ RCSID("$OpenBSD: clientloop.c,v 1.96 2002/02/06 14:55:15 markus Exp $");
#include "atomicio.h"
#include "sshtty.h"
#include "misc.h"
#include "readpass.h"
/* import options */
extern Options options;
@ -470,6 +471,67 @@ client_process_net_input(fd_set * readset)
}
}
static void
process_cmdline(void)
{
void (*handler)(int);
char *s, *cmd;
u_short fwd_port, fwd_host_port;
char buf[1024], sfwd_port[6], sfwd_host_port[6];
int local = 0;
leave_raw_mode();
handler = signal(SIGINT, SIG_IGN);
cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
if (s == NULL)
goto out;
while (*s && isspace(*s))
s++;
if (*s == 0)
goto out;
if (strlen(s) < 2 || s[0] != '-' || !(s[1] == 'L' || s[1] == 'R')) {
log("Invalid command.");
goto out;
}
if (s[1] == 'L')
local = 1;
if (!local && !compat20) {
log("Not supported for SSH protocol version 1.");
goto out;
}
s += 2;
while (*s && isspace(*s))
s++;
if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]",
sfwd_port, buf, sfwd_host_port) != 3 &&
sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]",
sfwd_port, buf, sfwd_host_port) != 3) {
log("Bad forwarding specification.");
goto out;
}
if ((fwd_port = a2port(sfwd_port)) == 0 ||
(fwd_host_port = a2port(sfwd_host_port)) == 0) {
log("Bad forwarding port(s).");
goto out;
}
if (local) {
if (channel_setup_local_fwd_listener(fwd_port, buf,
fwd_host_port, options.gateway_ports) < 0) {
log("Port forwarding failed.");
goto out;
}
} else
channel_request_remote_forwarding(fwd_port, buf,
fwd_host_port);
log("Forwarding port.");
out:
signal(SIGINT, handler);
enter_raw_mode();
if (cmd)
xfree(cmd);
}
/* process the characters one by one */
static int
process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
@ -574,6 +636,7 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
"%c?\r\n\
Supported escape sequences:\r\n\
~. - terminate connection\r\n\
~C - open a command line\r\n\
~R - Request rekey (SSH protocol 2 only)\r\n\
~^Z - suspend ssh\r\n\
~# - list forwarded connections\r\n\
@ -593,6 +656,10 @@ Supported escape sequences:\r\n\
xfree(s);
continue;
case 'C':
process_cmdline();
continue;
default:
if (ch != escape_char) {
buffer_put_char(bin, escape_char);
@ -1247,6 +1314,7 @@ static void
client_init_dispatch_20(void)
{
dispatch_init(&dispatch_protocol_error);
dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
@ -1260,6 +1328,10 @@ client_init_dispatch_20(void)
/* rekeying */
dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
/* global request reply messages */
dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply);
dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
}
static void
client_init_dispatch_13(void)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.h,v 1.6 2001/06/26 17:27:23 markus Exp $ */
/* $OpenBSD: clientloop.h,v 1.7 2002/04/22 21:04:52 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -37,3 +37,4 @@
/* Client side main loop for the interactive session. */
int client_loop(int, int, int);
void client_global_request_reply(int type, u_int32_t seq, void *ctxt);

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: compat.c,v 1.61 2002/03/06 00:24:39 markus Exp $");
RCSID("$OpenBSD: compat.c,v 1.63 2002/04/10 08:21:47 markus Exp $");
#include "buffer.h"
#include "packet.h"
@ -61,20 +61,26 @@ compat_datafellows(const char *version)
"OpenSSH-2.1*,"
"OpenSSH_2.1*,"
"OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER|
SSH_OLD_DHGEX|SSH_BUG_NOREKEY },
SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
SSH_BUG_EXTEOF},
{ "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES|
SSH_OLD_DHGEX|SSH_BUG_NOREKEY},
SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
SSH_BUG_EXTEOF},
{ "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
SSH_BUG_NOREKEY},
SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
{ "OpenSSH_2.5.0p1*,"
"OpenSSH_2.5.1p1*",
SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
SSH_BUG_NOREKEY },
SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
{ "OpenSSH_2.5.0*,"
"OpenSSH_2.5.1*,"
"OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY },
{ "OpenSSH_2.5.3*", SSH_BUG_NOREKEY },
{ "Sun_SSH_1.0*", SSH_BUG_NOREKEY },
"OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
SSH_BUG_EXTEOF},
{ "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
{ "OpenSSH_2.*,"
"OpenSSH_3.0*,"
"OpenSSH_3.1*", SSH_BUG_EXTEOF},
{ "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
{ "OpenSSH*", 0 },
{ "*MindTerm*", 0 },
{ "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
@ -121,8 +127,12 @@ compat_datafellows(const char *version)
"1.2.19*,"
"1.2.20*,"
"1.2.21*,"
"1.2.22*", SSH_BUG_IGNOREMSG },
{ "1.3.2*", SSH_BUG_IGNOREMSG }, /* f-secure */
"1.2.22*", SSH_BUG_IGNOREMSG|SSH_BUG_K5USER },
{ "1.3.2*", /* F-Secure */
SSH_BUG_IGNOREMSG|SSH_BUG_K5USER },
{ "1.2.1*,"
"1.2.2*,"
"1.2.3*", SSH_BUG_K5USER },
{ "*SSH Compatible Server*", /* Netscreen */
SSH_BUG_PASSWORDPAD },
{ "*OSU_0*,"

View File

@ -1,4 +1,4 @@
/* $OpenBSD: compat.h,v 1.30 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: compat.h,v 1.32 2002/04/10 08:21:47 markus Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
@ -52,6 +52,8 @@
#define SSH_BUG_OPENFAILURE 0x00020000
#define SSH_BUG_DERIVEKEY 0x00040000
#define SSH_BUG_DUMMYCHAN 0x00100000
#define SSH_BUG_EXTEOF 0x00200000
#define SSH_BUG_K5USER 0x00400000
void enable_compat13(void);
void enable_compat20(void);

View File

@ -12,17 +12,19 @@
*/
#include "includes.h"
RCSID("$OpenBSD: compress.c,v 1.17 2001/12/29 21:56:01 stevesk Exp $");
RCSID("$OpenBSD: compress.c,v 1.19 2002/03/18 17:31:54 provos Exp $");
#include "log.h"
#include "buffer.h"
#include "zlib.h"
#include "compress.h"
static z_stream incoming_stream;
static z_stream outgoing_stream;
z_stream incoming_stream;
z_stream outgoing_stream;
static int compress_init_send_called = 0;
static int compress_init_recv_called = 0;
static int inflate_failed = 0;
static int deflate_failed = 0;
/*
* Initializes compression; level is compression level from 1 to 9
@ -62,9 +64,9 @@ buffer_compress_uninit(void)
incoming_stream.total_out, incoming_stream.total_in,
incoming_stream.total_out == 0 ? 0.0 :
(double) incoming_stream.total_in / incoming_stream.total_out);
if (compress_init_recv_called == 1)
if (compress_init_recv_called == 1 && inflate_failed == 0)
inflateEnd(&incoming_stream);
if (compress_init_send_called == 1)
if (compress_init_send_called == 1 && deflate_failed == 0)
deflateEnd(&outgoing_stream);
}
@ -106,6 +108,7 @@ buffer_compress(Buffer * input_buffer, Buffer * output_buffer)
sizeof(buf) - outgoing_stream.avail_out);
break;
default:
deflate_failed = 1;
fatal("buffer_compress: deflate returned %d", status);
/* NOTREACHED */
}
@ -149,6 +152,7 @@ buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer)
*/
return;
default:
inflate_failed = 1;
fatal("buffer_uncompress: inflate returned %d", status);
/* NOTREACHED */
}

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: kex.c,v 1.47 2002/02/28 15:46:33 markus Exp $");
RCSID("$OpenBSD: kex.c,v 1.50 2002/05/15 15:47:49 mouring Exp $");
#include <openssl/crypto.h>
@ -40,9 +40,15 @@ RCSID("$OpenBSD: kex.c,v 1.47 2002/02/28 15:46:33 markus Exp $");
#include "mac.h"
#include "match.h"
#include "dispatch.h"
#include "monitor.h"
#define KEX_COOKIE_LEN 16
/* Use privilege separation for sshd */
int use_privsep;
struct monitor *pmonitor;
/* prototype */
static void kex_kexinit_finish(Kex *);
static void kex_choose_conf(Kex *);
@ -51,16 +57,15 @@ static void kex_choose_conf(Kex *);
static void
kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
{
u_int32_t rand = 0;
int i;
buffer_clear(b);
for (i = 0; i < KEX_COOKIE_LEN; i++) {
if (i % 4 == 0)
rand = arc4random();
buffer_put_char(b, rand & 0xff);
rand >>= 8;
}
/*
* add a dummy cookie, the cookie will be overwritten by
* kex_send_kexinit(), each time a kexinit is set
*/
for (i = 0; i < KEX_COOKIE_LEN; i++)
buffer_put_char(b, 0);
for (i = 0; i < PROPOSAL_MAX; i++)
buffer_put_cstring(b, proposal[i]);
buffer_put_char(b, 0); /* first_kex_packet_follows */
@ -146,6 +151,10 @@ kex_finish(Kex *kex)
void
kex_send_kexinit(Kex *kex)
{
u_int32_t rand = 0;
u_char *cookie;
int i;
if (kex == NULL) {
error("kex_send_kexinit: no kex, cannot rekey");
return;
@ -155,6 +164,17 @@ kex_send_kexinit(Kex *kex)
return;
}
kex->done = 0;
/* generate a random cookie */
if (buffer_len(&kex->my) < KEX_COOKIE_LEN)
fatal("kex_send_kexinit: kex proposal too short");
cookie = buffer_ptr(&kex->my);
for (i = 0; i < KEX_COOKIE_LEN; i++) {
if (i % 4 == 0)
rand = arc4random();
cookie[i] = rand;
rand >>= 8;
}
packet_start(SSH2_MSG_KEXINIT);
packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my));
packet_send();

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kex.h,v 1.29 2002/02/14 23:41:01 markus Exp $ */
/* $OpenBSD: kex.h,v 1.31 2002/05/16 22:02:50 markus Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -79,7 +79,7 @@ struct Enc {
struct Mac {
char *name;
int enabled;
EVP_MD *md;
const EVP_MD *md;
int mac_len;
u_char *key;
int key_len;
@ -111,6 +111,7 @@ struct Kex {
char *server_version_string;
int (*verify_host_key)(Key *);
Key *(*load_host_key)(int);
int (*host_key_index)(Key *);
};
Kex *kex_setup(char *[PROPOSAL_MAX]);

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: kexdh.c,v 1.17 2002/02/28 15:46:33 markus Exp $");
RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $");
#include <openssl/crypto.h>
#include <openssl/bn.h>
@ -37,6 +37,7 @@ RCSID("$OpenBSD: kexdh.c,v 1.17 2002/02/28 15:46:33 markus Exp $");
#include "packet.h"
#include "dh.h"
#include "ssh2.h"
#include "monitor_wrap.h"
static u_char *
kex_dh_hash(
@ -275,7 +276,7 @@ kexdh_server(Kex *kex)
/* sign H */
/* XXX hashlen depends on KEX */
key_sign(server_host_key, &signature, &slen, hash, 20);
PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20));
/* destroy_sensitive_data(); */

View File

@ -24,7 +24,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: kexgex.c,v 1.20 2002/02/28 15:46:33 markus Exp $");
RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $");
#include <openssl/bn.h>
@ -38,6 +38,7 @@ RCSID("$OpenBSD: kexgex.c,v 1.20 2002/02/28 15:46:33 markus Exp $");
#include "dh.h"
#include "ssh2.h"
#include "compat.h"
#include "monitor_wrap.h"
static u_char *
kexgex_hash(
@ -259,7 +260,7 @@ kexgex_server(Kex *kex)
{
BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
Key *server_host_key;
DH *dh = dh;
DH *dh;
u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
u_int sbloblen, klen, kout, slen;
int min = -1, max = -1, nbits = -1, type;
@ -296,7 +297,8 @@ kexgex_server(Kex *kex)
fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d",
min, nbits, max);
dh = choose_dh(min, nbits, max);
/* Contact privileged parent */
dh = PRIVSEP(choose_dh(min, nbits, max));
if (dh == NULL)
packet_disconnect("Protocol error: no matching DH grp found");
@ -379,7 +381,7 @@ kexgex_server(Kex *kex)
/* sign H */
/* XXX hashlen depends on KEX */
key_sign(server_host_key, &signature, &slen, hash, 20);
PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20));
/* destroy_sensitive_data(); */
@ -390,6 +392,7 @@ kexgex_server(Kex *kex)
packet_put_bignum2(dh->pub_key); /* f */
packet_put_string(signature, slen);
packet_send();
xfree(signature);
xfree(server_host_key_blob);
/* have keys, free DH */

View File

@ -32,7 +32,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: key.c,v 1.41 2002/02/28 15:46:33 markus Exp $");
RCSID("$OpenBSD: key.c,v 1.44 2002/05/31 13:16:48 markus Exp $");
#include <openssl/evp.h>
@ -779,6 +779,10 @@ key_sign(
}
}
/*
* key_verify returns 1 for a correct signature, 0 for an incorrect signature
* and -1 on error.
*/
int
key_verify(
Key *key,
@ -801,3 +805,46 @@ key_verify(
break;
}
}
/* Converts a private to a public key */
Key *
key_demote(Key *k)
{
Key *pk;
pk = xmalloc(sizeof(*pk));
pk->type = k->type;
pk->flags = k->flags;
pk->dsa = NULL;
pk->rsa = NULL;
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
if ((pk->rsa = RSA_new()) == NULL)
fatal("key_demote: RSA_new failed");
if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL)
fatal("key_demote: BN_dup failed");
if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
fatal("key_demote: BN_dup failed");
break;
case KEY_DSA:
if ((pk->dsa = DSA_new()) == NULL)
fatal("key_demote: DSA_new failed");
if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL)
fatal("key_demote: BN_dup failed");
if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL)
fatal("key_demote: BN_dup failed");
if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL)
fatal("key_demote: BN_dup failed");
if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL)
fatal("key_demote: BN_dup failed");
break;
default:
fatal("key_free: bad key type %d", k->type);
break;
}
return (pk);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: key.h,v 1.18 2002/02/24 19:14:59 markus Exp $ */
/* $OpenBSD: key.h,v 1.19 2002/03/18 17:23:31 markus Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -58,6 +58,7 @@ struct Key {
Key *key_new(int);
Key *key_new_private(int);
void key_free(Key *);
Key *key_demote(Key *);
int key_equal(Key *, Key *);
char *key_fingerprint(Key *, enum fp_type, enum fp_rep);
char *key_type(Key *);

View File

@ -1,15 +1,15 @@
# $OpenBSD: Makefile,v 1.31 2002/02/22 12:20:34 markus Exp $
# $OpenBSD: Makefile,v 1.36 2002/06/11 15:23:29 hin Exp $
.PATH: ${.CURDIR}/..
LIB= ssh
SRCS= authfd.c authfile.c bufaux.c buffer.c canohost.c channels.c \
SRCS= authfd.c authfile.c bufaux.c buffer.c canohost.c channels.c \
cipher.c compat.c compress.c crc32.c deattack.c fatal.c \
hostfile.c log.c match.c mpaux.c nchan.c packet.c readpass.c \
rsa.c tildexpand.c ttymodes.c uidswap.c xmalloc.c atomicio.c \
rsa.c tildexpand.c ttymodes.c xmalloc.c atomicio.c \
key.c dispatch.c kex.c mac.c uuencode.c misc.c \
rijndael.c ssh-dss.c ssh-rsa.c dh.c kexdh.c kexgex.c \
scard.c
scard.c monitor_wrap.c monitor_fdpass.c msg.c
DEBUGLIBS= no
NOPROFILE= yes
@ -20,6 +20,10 @@ install:
.include <bsd.own.mk>
.if (${KERBEROS5:L} == "yes")
CFLAGS+= -DKRB5 -I${DESTDIR}/usr/include/kerberosV
.endif # KERBEROS5
.if (${KERBEROS:L} == "yes")
CFLAGS+= -DKRB4 -I${DESTDIR}/usr/include/kerberosIV
.if (${AFS:L} == "yes")
@ -28,8 +32,4 @@ SRCS+= radix.c
.endif # AFS
.endif # KERBEROS
.if (${KERBEROS5:L} == "yes")
CFLAGS+= -DKRB5 -I${DESTDIR}/usr/include/kerberosV
.endif # KERBEROS5
.include <bsd.lib.mk>

View File

@ -1,4 +1,4 @@
/* $OpenBSD: log.h,v 1.6 2002/02/22 12:20:34 markus Exp $ */
/* $OpenBSD: log.h,v 1.7 2002/05/19 20:54:52 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -28,7 +28,7 @@ typedef enum {
SYSLOG_FACILITY_LOCAL5,
SYSLOG_FACILITY_LOCAL6,
SYSLOG_FACILITY_LOCAL7,
SYSLOG_FACILITY_NOT_SET = -1,
SYSLOG_FACILITY_NOT_SET = -1
} SyslogFacility;
typedef enum {
@ -40,7 +40,7 @@ typedef enum {
SYSLOG_LEVEL_DEBUG1,
SYSLOG_LEVEL_DEBUG2,
SYSLOG_LEVEL_DEBUG3,
SYSLOG_LEVEL_NOT_SET = -1,
SYSLOG_LEVEL_NOT_SET = -1
} LogLevel;
void log_init(char *, LogLevel, SyslogFacility, int);

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: mac.c,v 1.4 2002/01/25 22:07:40 markus Exp $");
RCSID("$OpenBSD: mac.c,v 1.5 2002/05/16 22:02:50 markus Exp $");
#include <openssl/hmac.h>
@ -36,7 +36,7 @@ RCSID("$OpenBSD: mac.c,v 1.4 2002/01/25 22:07:40 markus Exp $");
struct {
char *name;
EVP_MD * (*mdfunc)(void);
const EVP_MD * (*mdfunc)(void);
int truncatebits; /* truncate digest if != 0 */
} macs[] = {
{ "hmac-sha1", EVP_sha1, 0, },

View File

@ -1,4 +1,4 @@
/* $OpenBSD: misc.h,v 1.11 2002/01/24 21:09:25 stevesk Exp $ */
/* $OpenBSD: misc.h,v 1.12 2002/03/19 10:49:35 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -26,8 +26,8 @@ struct passwd *pwcopy(struct passwd *);
typedef struct arglist arglist;
struct arglist {
char **list;
int num;
int nalloc;
char **list;
int num;
int nalloc;
};
void addargs(arglist *, char *, ...) __attribute__((format(printf, 2, 3)));

1498
crypto/openssh/monitor.c Normal file

File diff suppressed because it is too large Load Diff

81
crypto/openssh/monitor.h Normal file
View File

@ -0,0 +1,81 @@
/* $OpenBSD: monitor.h,v 1.6 2002/06/11 05:46:20 mpech Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MONITOR_H_
#define _MONITOR_H_
enum monitor_reqtype {
MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD,
MONITOR_REQ_BSDAUTHQUERY, MONITOR_ANS_BSDAUTHQUERY,
MONITOR_REQ_BSDAUTHRESPOND, MONITOR_ANS_BSDAUTHRESPOND,
MONITOR_REQ_SKEYQUERY, MONITOR_ANS_SKEYQUERY,
MONITOR_REQ_SKEYRESPOND, MONITOR_ANS_SKEYRESPOND,
MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED,
MONITOR_REQ_KEYVERIFY, MONITOR_ANS_KEYVERIFY,
MONITOR_REQ_KEYEXPORT,
MONITOR_REQ_PTY, MONITOR_ANS_PTY,
MONITOR_REQ_PTYCLEANUP,
MONITOR_REQ_SESSKEY, MONITOR_ANS_SESSKEY,
MONITOR_REQ_SESSID,
MONITOR_REQ_RSAKEYALLOWED, MONITOR_ANS_RSAKEYALLOWED,
MONITOR_REQ_RSACHALLENGE, MONITOR_ANS_RSACHALLENGE,
MONITOR_REQ_RSARESPONSE, MONITOR_ANS_RSARESPONSE,
MONITOR_REQ_TERM
};
struct mm_master;
struct monitor {
int m_recvfd;
int m_sendfd;
struct mm_master *m_zback;
struct mm_master *m_zlib;
struct Kex **m_pkex;
pid_t m_pid;
};
struct monitor *monitor_init(void);
void monitor_reinit(struct monitor *);
void monitor_sync(struct monitor *);
struct Authctxt;
struct Authctxt *monitor_child_preauth(struct monitor *);
void monitor_child_postauth(struct monitor *);
struct mon_table;
int monitor_read(struct monitor*, struct mon_table *, struct mon_table **);
/* Prototypes for request sending and receiving */
void mm_request_send(int, enum monitor_reqtype, Buffer *);
void mm_request_receive(int, Buffer *);
void mm_request_receive_expect(int, enum monitor_reqtype, Buffer *);
#endif /* _MONITOR_H_ */

View File

@ -0,0 +1,96 @@
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: monitor_fdpass.c,v 1.3 2002/06/04 23:05:49 markus Exp $");
#include <sys/uio.h>
#include "log.h"
#include "monitor_fdpass.h"
void
mm_send_fd(int socket, int fd)
{
struct msghdr msg;
char tmp[CMSG_SPACE(sizeof(int))];
struct cmsghdr *cmsg;
struct iovec vec;
char ch = '\0';
int n;
memset(&msg, 0, sizeof(msg));
msg.msg_control = (caddr_t)tmp;
msg.msg_controllen = CMSG_LEN(sizeof(int));
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = fd;
vec.iov_base = &ch;
vec.iov_len = 1;
msg.msg_iov = &vec;
msg.msg_iovlen = 1;
if ((n = sendmsg(socket, &msg, 0)) == -1)
fatal("%s: sendmsg(%d): %s", __func__, fd,
strerror(errno));
if (n != 1)
fatal("%s: sendmsg: expected sent 1 got %d",
__func__, n);
}
int
mm_receive_fd(int socket)
{
struct msghdr msg;
char tmp[CMSG_SPACE(sizeof(int))];
struct cmsghdr *cmsg;
struct iovec vec;
char ch;
int fd, n;
memset(&msg, 0, sizeof(msg));
vec.iov_base = &ch;
vec.iov_len = 1;
msg.msg_iov = &vec;
msg.msg_iovlen = 1;
msg.msg_control = tmp;
msg.msg_controllen = sizeof(tmp);
if ((n = recvmsg(socket, &msg, 0)) == -1)
fatal("%s: recvmsg: %s", __func__, strerror(errno));
if (n != 1)
fatal("%s: recvmsg: expected received 1 got %d",
__func__, n);
cmsg = CMSG_FIRSTHDR(&msg);
if (cmsg->cmsg_type != SCM_RIGHTS)
fatal("%s: expected type %d got %d", __func__,
SCM_RIGHTS, cmsg->cmsg_type);
fd = (*(int *)CMSG_DATA(cmsg));
return fd;
}

View File

@ -0,0 +1,34 @@
/* $OpenBSD: monitor_fdpass.h,v 1.2 2002/03/26 03:24:01 stevesk Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MM_FDPASS_H_
#define _MM_FDPASS_H_
void mm_send_fd(int, int);
int mm_receive_fd(int);
#endif /* _MM_FDPASS_H_ */

330
crypto/openssh/monitor_mm.c Normal file
View File

@ -0,0 +1,330 @@
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: monitor_mm.c,v 1.6 2002/06/04 23:05:49 markus Exp $");
#include <sys/mman.h>
#include "ssh.h"
#include "xmalloc.h"
#include "log.h"
#include "monitor_mm.h"
static int
mm_compare(struct mm_share *a, struct mm_share *b)
{
return ((char *)a->address - (char *)b->address);
}
RB_GENERATE(mmtree, mm_share, next, mm_compare)
static struct mm_share *
mm_make_entry(struct mm_master *mm, struct mmtree *head,
void *address, size_t size)
{
struct mm_share *tmp, *tmp2;
if (mm->mmalloc == NULL)
tmp = xmalloc(sizeof(struct mm_share));
else
tmp = mm_xmalloc(mm->mmalloc, sizeof(struct mm_share));
tmp->address = address;
tmp->size = size;
tmp2 = RB_INSERT(mmtree, head, tmp);
if (tmp2 != NULL)
fatal("mm_make_entry(%p): double address %p->%p(%lu)",
mm, tmp2, address, (u_long)size);
return (tmp);
}
/* Creates a shared memory area of a certain size */
struct mm_master *
mm_create(struct mm_master *mmalloc, size_t size)
{
void *address;
struct mm_master *mm;
if (mmalloc == NULL)
mm = xmalloc(sizeof(struct mm_master));
else
mm = mm_xmalloc(mmalloc, sizeof(struct mm_master));
/*
* If the memory map has a mm_master it can be completely
* shared including authentication between the child
* and the client.
*/
mm->mmalloc = mmalloc;
address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_ANON|MAP_SHARED,
-1, 0);
if (address == MAP_FAILED)
fatal("mmap(%lu): %s", (u_long)size, strerror(errno));
mm->address = address;
mm->size = size;
RB_INIT(&mm->rb_free);
RB_INIT(&mm->rb_allocated);
mm_make_entry(mm, &mm->rb_free, address, size);
return (mm);
}
/* Frees either the allocated or the free list */
static void
mm_freelist(struct mm_master *mmalloc, struct mmtree *head)
{
struct mm_share *mms, *next;
for (mms = RB_ROOT(head); mms; mms = next) {
next = RB_NEXT(mmtree, head, mms);
RB_REMOVE(mmtree, head, mms);
if (mmalloc == NULL)
xfree(mms);
else
mm_free(mmalloc, mms);
}
}
/* Destroys a memory mapped area */
void
mm_destroy(struct mm_master *mm)
{
mm_freelist(mm->mmalloc, &mm->rb_free);
mm_freelist(mm->mmalloc, &mm->rb_allocated);
if (munmap(mm->address, mm->size) == -1)
fatal("munmap(%p, %lu): %s", mm->address, (u_long)mm->size,
strerror(errno));
if (mm->mmalloc == NULL)
xfree(mm);
else
mm_free(mm->mmalloc, mm);
}
void *
mm_xmalloc(struct mm_master *mm, size_t size)
{
void *address;
address = mm_malloc(mm, size);
if (address == NULL)
fatal("%s: mm_malloc(%lu)", __func__, (u_long)size);
return (address);
}
/* Allocates data from a memory mapped area */
void *
mm_malloc(struct mm_master *mm, size_t size)
{
struct mm_share *mms, *tmp;
if (size == 0)
fatal("mm_malloc: try to allocate 0 space");
size = ((size + MM_MINSIZE - 1) / MM_MINSIZE) * MM_MINSIZE;
RB_FOREACH(mms, mmtree, &mm->rb_free) {
if (mms->size >= size)
break;
}
if (mms == NULL)
return (NULL);
/* Debug */
memset(mms->address, 0xd0, size);
tmp = mm_make_entry(mm, &mm->rb_allocated, mms->address, size);
/* Does not change order in RB tree */
mms->size -= size;
mms->address = (u_char *)mms->address + size;
if (mms->size == 0) {
RB_REMOVE(mmtree, &mm->rb_free, mms);
if (mm->mmalloc == NULL)
xfree(mms);
else
mm_free(mm->mmalloc, mms);
}
return (tmp->address);
}
/* Frees memory in a memory mapped area */
void
mm_free(struct mm_master *mm, void *address)
{
struct mm_share *mms, *prev, tmp;
tmp.address = address;
mms = RB_FIND(mmtree, &mm->rb_allocated, &tmp);
if (mms == NULL)
fatal("mm_free(%p): can not find %p", mm, address);
/* Debug */
memset(mms->address, 0xd0, mms->size);
/* Remove from allocated list and insert in free list */
RB_REMOVE(mmtree, &mm->rb_allocated, mms);
if (RB_INSERT(mmtree, &mm->rb_free, mms) != NULL)
fatal("mm_free(%p): double address %p", mm, address);
/* Find previous entry */
prev = mms;
if (RB_LEFT(prev, next)) {
prev = RB_LEFT(prev, next);
while (RB_RIGHT(prev, next))
prev = RB_RIGHT(prev, next);
} else {
if (RB_PARENT(prev, next) &&
(prev == RB_RIGHT(RB_PARENT(prev, next), next)))
prev = RB_PARENT(prev, next);
else {
while (RB_PARENT(prev, next) &&
(prev == RB_LEFT(RB_PARENT(prev, next), next)))
prev = RB_PARENT(prev, next);
prev = RB_PARENT(prev, next);
}
}
/* Check if range does not overlap */
if (prev != NULL && MM_ADDRESS_END(prev) > address)
fatal("mm_free: memory corruption: %p(%lu) > %p",
prev->address, (u_long)prev->size, address);
/* See if we can merge backwards */
if (prev != NULL && MM_ADDRESS_END(prev) == address) {
prev->size += mms->size;
RB_REMOVE(mmtree, &mm->rb_free, mms);
if (mm->mmalloc == NULL)
xfree(mms);
else
mm_free(mm->mmalloc, mms);
} else
prev = mms;
if (prev == NULL)
return;
/* Check if we can merge forwards */
mms = RB_NEXT(mmtree, &mm->rb_free, prev);
if (mms == NULL)
return;
if (MM_ADDRESS_END(prev) > mms->address)
fatal("mm_free: memory corruption: %p < %p(%lu)",
mms->address, prev->address, (u_long)prev->size);
if (MM_ADDRESS_END(prev) != mms->address)
return;
prev->size += mms->size;
RB_REMOVE(mmtree, &mm->rb_free, mms);
if (mm->mmalloc == NULL)
xfree(mms);
else
mm_free(mm->mmalloc, mms);
}
static void
mm_sync_list(struct mmtree *oldtree, struct mmtree *newtree,
struct mm_master *mm, struct mm_master *mmold)
{
struct mm_master *mmalloc = mm->mmalloc;
struct mm_share *mms, *new;
/* Sync free list */
RB_FOREACH(mms, mmtree, oldtree) {
/* Check the values */
mm_memvalid(mmold, mms, sizeof(struct mm_share));
mm_memvalid(mm, mms->address, mms->size);
new = mm_xmalloc(mmalloc, sizeof(struct mm_share));
memcpy(new, mms, sizeof(struct mm_share));
RB_INSERT(mmtree, newtree, new);
}
}
void
mm_share_sync(struct mm_master **pmm, struct mm_master **pmmalloc)
{
struct mm_master *mm;
struct mm_master *mmalloc;
struct mm_master *mmold;
struct mmtree rb_free, rb_allocated;
debug3("%s: Share sync", __func__);
mm = *pmm;
mmold = mm->mmalloc;
mm_memvalid(mmold, mm, sizeof(*mm));
mmalloc = mm_create(NULL, mm->size);
mm = mm_xmalloc(mmalloc, sizeof(struct mm_master));
memcpy(mm, *pmm, sizeof(struct mm_master));
mm->mmalloc = mmalloc;
rb_free = mm->rb_free;
rb_allocated = mm->rb_allocated;
RB_INIT(&mm->rb_free);
RB_INIT(&mm->rb_allocated);
mm_sync_list(&rb_free, &mm->rb_free, mm, mmold);
mm_sync_list(&rb_allocated, &mm->rb_allocated, mm, mmold);
mm_destroy(mmold);
*pmm = mm;
*pmmalloc = mmalloc;
debug3("%s: Share sync end", __func__);
}
void
mm_memvalid(struct mm_master *mm, void *address, size_t size)
{
void *end = (u_char *)address + size;
if (address < mm->address)
fatal("mm_memvalid: address too small: %p", address);
if (end < address)
fatal("mm_memvalid: end < address: %p < %p", end, address);
if (end > (void *)((u_char *)mm->address + mm->size))
fatal("mm_memvalid: address too large: %p", address);
}

View File

@ -0,0 +1,66 @@
/* $OpenBSD: monitor_mm.h,v 1.2 2002/03/26 03:24:01 stevesk Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MM_H_
#define _MM_H_
#include <sys/tree.h>
struct mm_share {
RB_ENTRY(mm_share) next;
void *address;
size_t size;
};
struct mm_master {
RB_HEAD(mmtree, mm_share) rb_free;
struct mmtree rb_allocated;
void *address;
size_t size;
struct mm_master *mmalloc; /* Used to completely share */
int write; /* used to writing to other party */
int read; /* used for reading from other party */
};
RB_PROTOTYPE(mmtree, mm_share, next, mm_compare)
#define MM_MINSIZE 128
#define MM_ADDRESS_END(x) (void *)((u_char *)(x)->address + (x)->size)
struct mm_master *mm_create(struct mm_master *, size_t);
void mm_destroy(struct mm_master *);
void mm_share_sync(struct mm_master **, struct mm_master **);
void *mm_malloc(struct mm_master *, size_t);
void *mm_xmalloc(struct mm_master *, size_t);
void mm_free(struct mm_master *, void *);
void mm_memvalid(struct mm_master *, void *, size_t);
#endif /* _MM_H_ */

View File

@ -0,0 +1,920 @@
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: monitor_wrap.c,v 1.11 2002/06/19 18:01:00 markus Exp $");
#include <openssl/bn.h>
#include <openssl/dh.h>
#include "ssh.h"
#include "dh.h"
#include "kex.h"
#include "auth.h"
#include "buffer.h"
#include "bufaux.h"
#include "packet.h"
#include "mac.h"
#include "log.h"
#include "zlib.h"
#include "monitor.h"
#include "monitor_wrap.h"
#include "xmalloc.h"
#include "atomicio.h"
#include "monitor_fdpass.h"
#include "getput.h"
#include "auth.h"
#include "channels.h"
#include "session.h"
/* Imports */
extern int compat20;
extern Newkeys *newkeys[];
extern z_stream incoming_stream;
extern z_stream outgoing_stream;
extern struct monitor *pmonitor;
extern Buffer input, output;
void
mm_request_send(int socket, enum monitor_reqtype type, Buffer *m)
{
u_char buf[5];
u_int mlen = buffer_len(m);
debug3("%s entering: type %d", __func__, type);
PUT_32BIT(buf, mlen + 1);
buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */
if (atomicio(write, socket, buf, sizeof(buf)) != sizeof(buf))
fatal("%s: write", __func__);
if (atomicio(write, socket, buffer_ptr(m), mlen) != mlen)
fatal("%s: write", __func__);
}
void
mm_request_receive(int socket, Buffer *m)
{
u_char buf[4];
ssize_t res;
u_int msg_len;
debug3("%s entering", __func__);
res = atomicio(read, socket, buf, sizeof(buf));
if (res != sizeof(buf)) {
if (res == 0)
fatal_cleanup();
fatal("%s: read: %ld", __func__, (long)res);
}
msg_len = GET_32BIT(buf);
if (msg_len > 256 * 1024)
fatal("%s: read: bad msg_len %d", __func__, msg_len);
buffer_clear(m);
buffer_append_space(m, msg_len);
res = atomicio(read, socket, buffer_ptr(m), msg_len);
if (res != msg_len)
fatal("%s: read: %ld != msg_len", __func__, (long)res);
}
void
mm_request_receive_expect(int socket, enum monitor_reqtype type, Buffer *m)
{
u_char rtype;
debug3("%s entering: type %d", __func__, type);
mm_request_receive(socket, m);
rtype = buffer_get_char(m);
if (rtype != type)
fatal("%s: read: rtype %d != type %d", __func__,
rtype, type);
}
DH *
mm_choose_dh(int min, int nbits, int max)
{
BIGNUM *p, *g;
int success = 0;
Buffer m;
buffer_init(&m);
buffer_put_int(&m, min);
buffer_put_int(&m, nbits);
buffer_put_int(&m, max);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m);
debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m);
success = buffer_get_char(&m);
if (success == 0)
fatal("%s: MONITOR_ANS_MODULI failed", __func__);
if ((p = BN_new()) == NULL)
fatal("%s: BN_new failed", __func__);
if ((g = BN_new()) == NULL)
fatal("%s: BN_new failed", __func__);
buffer_get_bignum2(&m, p);
buffer_get_bignum2(&m, g);
debug3("%s: remaining %d", __func__, buffer_len(&m));
buffer_free(&m);
return (dh_new_group(g, p));
}
int
mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen)
{
Kex *kex = *pmonitor->m_pkex;
Buffer m;
debug3("%s entering", __func__);
buffer_init(&m);
buffer_put_int(&m, kex->host_key_index(key));
buffer_put_string(&m, data, datalen);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);
debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m);
*sigp = buffer_get_string(&m, lenp);
buffer_free(&m);
return (0);
}
struct passwd *
mm_getpwnamallow(const char *login)
{
Buffer m;
struct passwd *pw;
u_int pwlen;
debug3("%s entering", __func__);
buffer_init(&m);
buffer_put_cstring(&m, login);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m);
debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m);
if (buffer_get_char(&m) == 0) {
buffer_free(&m);
return (NULL);
}
pw = buffer_get_string(&m, &pwlen);
if (pwlen != sizeof(struct passwd))
fatal("%s: struct passwd size mismatch", __func__);
pw->pw_name = buffer_get_string(&m, NULL);
pw->pw_passwd = buffer_get_string(&m, NULL);
pw->pw_gecos = buffer_get_string(&m, NULL);
pw->pw_class = buffer_get_string(&m, NULL);
pw->pw_dir = buffer_get_string(&m, NULL);
pw->pw_shell = buffer_get_string(&m, NULL);
buffer_free(&m);
return (pw);
}
char* mm_auth2_read_banner(void)
{
Buffer m;
char *banner;
debug3("%s entering", __func__);
buffer_init(&m);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
buffer_clear(&m);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTH2_READ_BANNER, &m);
banner = buffer_get_string(&m, NULL);
buffer_free(&m);
return (banner);
}
/* Inform the privileged process about service and style */
void
mm_inform_authserv(char *service, char *style)
{
Buffer m;
debug3("%s entering", __func__);
buffer_init(&m);
buffer_put_cstring(&m, service);
buffer_put_cstring(&m, style ? style : "");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
buffer_free(&m);
}
/* Do the password authentication */
int
mm_auth_password(Authctxt *authctxt, char *password)
{
Buffer m;
int authenticated = 0;
debug3("%s entering", __func__);
buffer_init(&m);
buffer_put_cstring(&m, password);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
authenticated = buffer_get_int(&m);
buffer_free(&m);
debug3("%s: user %sauthenticated",
__func__, authenticated ? "" : "not ");
return (authenticated);
}
int
mm_user_key_allowed(struct passwd *pw, Key *key)
{
return (mm_key_allowed(MM_USERKEY, NULL, NULL, key));
}
int
mm_hostbased_key_allowed(struct passwd *pw, char *user, char *host,
Key *key)
{
return (mm_key_allowed(MM_HOSTKEY, user, host, key));
}
int
mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
char *host, Key *key)
{
int ret;
key->type = KEY_RSA; /* XXX hack for key_to_blob */
ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key);
key->type = KEY_RSA1;
return (ret);
}
static void
mm_send_debug(Buffer *m)
{
char *msg;
while (buffer_len(m)) {
msg = buffer_get_string(m, NULL);
debug3("%s: Sending debug: %s", __func__, msg);
packet_send_debug("%s", msg);
xfree(msg);
}
}
int
mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
{
Buffer m;
u_char *blob;
u_int len;
int allowed = 0;
debug3("%s entering", __func__);
/* Convert the key to a blob and the pass it over */
if (!key_to_blob(key, &blob, &len))
return (0);
buffer_init(&m);
buffer_put_int(&m, type);
buffer_put_cstring(&m, user ? user : "");
buffer_put_cstring(&m, host ? host : "");
buffer_put_string(&m, blob, len);
xfree(blob);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
allowed = buffer_get_int(&m);
/* Send potential debug messages */
mm_send_debug(&m);
buffer_free(&m);
return (allowed);
}
/*
* This key verify needs to send the key type along, because the
* privileged parent makes the decision if the key is allowed
* for authentication.
*/
int
mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
{
Buffer m;
u_char *blob;
u_int len;
int verified = 0;
debug3("%s entering", __func__);
/* Convert the key to a blob and the pass it over */
if (!key_to_blob(key, &blob, &len))
return (0);
buffer_init(&m);
buffer_put_string(&m, blob, len);
buffer_put_string(&m, sig, siglen);
buffer_put_string(&m, data, datalen);
xfree(blob);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
verified = buffer_get_int(&m);
buffer_free(&m);
return (verified);
}
/* Export key state after authentication */
Newkeys *
mm_newkeys_from_blob(u_char *blob, int blen)
{
Buffer b;
u_int len;
Newkeys *newkey = NULL;
Enc *enc;
Mac *mac;
Comp *comp;
debug3("%s: %p(%d)", __func__, blob, blen);
#ifdef DEBUG_PK
dump_base64(stderr, blob, blen);
#endif
buffer_init(&b);
buffer_append(&b, blob, blen);
newkey = xmalloc(sizeof(*newkey));
enc = &newkey->enc;
mac = &newkey->mac;
comp = &newkey->comp;
/* Enc structure */
enc->name = buffer_get_string(&b, NULL);
buffer_get(&b, &enc->cipher, sizeof(enc->cipher));
enc->enabled = buffer_get_int(&b);
enc->block_size = buffer_get_int(&b);
enc->key = buffer_get_string(&b, &enc->key_len);
enc->iv = buffer_get_string(&b, &len);
if (len != enc->block_size)
fatal("%s: bad ivlen: expected %d != %d", __func__,
enc->block_size, len);
if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher)
fatal("%s: bad cipher name %s or pointer %p", __func__,
enc->name, enc->cipher);
/* Mac structure */
mac->name = buffer_get_string(&b, NULL);
if (mac->name == NULL || mac_init(mac, mac->name) == -1)
fatal("%s: can not init mac %s", __func__, mac->name);
mac->enabled = buffer_get_int(&b);
mac->key = buffer_get_string(&b, &len);
if (len > mac->key_len)
fatal("%s: bad mac key length: %d > %d", __func__, len,
mac->key_len);
mac->key_len = len;
/* Comp structure */
comp->type = buffer_get_int(&b);
comp->enabled = buffer_get_int(&b);
comp->name = buffer_get_string(&b, NULL);
len = buffer_len(&b);
if (len != 0)
error("newkeys_from_blob: remaining bytes in blob %d", len);
buffer_free(&b);
return (newkey);
}
int
mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
{
Buffer b;
int len;
u_char *buf;
Enc *enc;
Mac *mac;
Comp *comp;
Newkeys *newkey = newkeys[mode];
debug3("%s: converting %p", __func__, newkey);
if (newkey == NULL) {
error("%s: newkey == NULL", __func__);
return 0;
}
enc = &newkey->enc;
mac = &newkey->mac;
comp = &newkey->comp;
buffer_init(&b);
/* Enc structure */
buffer_put_cstring(&b, enc->name);
/* The cipher struct is constant and shared, you export pointer */
buffer_append(&b, &enc->cipher, sizeof(enc->cipher));
buffer_put_int(&b, enc->enabled);
buffer_put_int(&b, enc->block_size);
buffer_put_string(&b, enc->key, enc->key_len);
packet_get_keyiv(mode, enc->iv, enc->block_size);
buffer_put_string(&b, enc->iv, enc->block_size);
/* Mac structure */
buffer_put_cstring(&b, mac->name);
buffer_put_int(&b, mac->enabled);
buffer_put_string(&b, mac->key, mac->key_len);
/* Comp structure */
buffer_put_int(&b, comp->type);
buffer_put_int(&b, comp->enabled);
buffer_put_cstring(&b, comp->name);
len = buffer_len(&b);
buf = xmalloc(len);
memcpy(buf, buffer_ptr(&b), len);
memset(buffer_ptr(&b), 0, len);
buffer_free(&b);
if (lenp != NULL)
*lenp = len;
if (blobp != NULL)
*blobp = buf;
return len;
}
static void
mm_send_kex(Buffer *m, Kex *kex)
{
buffer_put_string(m, kex->session_id, kex->session_id_len);
buffer_put_int(m, kex->we_need);
buffer_put_int(m, kex->hostkey_type);
buffer_put_int(m, kex->kex_type);
buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my));
buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer));
buffer_put_int(m, kex->flags);
buffer_put_cstring(m, kex->client_version_string);
buffer_put_cstring(m, kex->server_version_string);
}
void
mm_send_keystate(struct monitor *pmonitor)
{
Buffer m;
u_char *blob, *p;
u_int bloblen, plen;
buffer_init(&m);
if (!compat20) {
u_char iv[24];
u_char *key;
u_int ivlen, keylen;
buffer_put_int(&m, packet_get_protocol_flags());
buffer_put_int(&m, packet_get_ssh1_cipher());
debug3("%s: Sending ssh1 KEY+IV", __func__);
keylen = packet_get_encryption_key(NULL);
key = xmalloc(keylen+1); /* add 1 if keylen == 0 */
keylen = packet_get_encryption_key(key);
buffer_put_string(&m, key, keylen);
memset(key, 0, keylen);
xfree(key);
ivlen = packet_get_keyiv_len(MODE_OUT);
packet_get_keyiv(MODE_OUT, iv, ivlen);
buffer_put_string(&m, iv, ivlen);
ivlen = packet_get_keyiv_len(MODE_OUT);
packet_get_keyiv(MODE_IN, iv, ivlen);
buffer_put_string(&m, iv, ivlen);
goto skip;
} else {
/* Kex for rekeying */
mm_send_kex(&m, *pmonitor->m_pkex);
}
debug3("%s: Sending new keys: %p %p",
__func__, newkeys[MODE_OUT], newkeys[MODE_IN]);
/* Keys from Kex */
if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen))
fatal("%s: conversion of newkeys failed", __func__);
buffer_put_string(&m, blob, bloblen);
xfree(blob);
if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen))
fatal("%s: conversion of newkeys failed", __func__);
buffer_put_string(&m, blob, bloblen);
xfree(blob);
buffer_put_int(&m, packet_get_seqnr(MODE_OUT));
buffer_put_int(&m, packet_get_seqnr(MODE_IN));
debug3("%s: New keys have been sent", __func__);
skip:
/* More key context */
plen = packet_get_keycontext(MODE_OUT, NULL);
p = xmalloc(plen+1);
packet_get_keycontext(MODE_OUT, p);
buffer_put_string(&m, p, plen);
xfree(p);
plen = packet_get_keycontext(MODE_IN, NULL);
p = xmalloc(plen+1);
packet_get_keycontext(MODE_IN, p);
buffer_put_string(&m, p, plen);
xfree(p);
/* Compression state */
debug3("%s: Sending compression state", __func__);
buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream));
buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream));
/* Network I/O buffers */
buffer_put_string(&m, buffer_ptr(&input), buffer_len(&input));
buffer_put_string(&m, buffer_ptr(&output), buffer_len(&output));
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m);
debug3("%s: Finished sending state", __func__);
buffer_free(&m);
}
int
mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
{
Buffer m;
u_char *p;
int success = 0;
buffer_init(&m);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m);
success = buffer_get_int(&m);
if (success == 0) {
debug3("%s: pty alloc failed", __func__);
buffer_free(&m);
return (0);
}
p = buffer_get_string(&m, NULL);
buffer_free(&m);
strlcpy(namebuf, p, namebuflen); /* Possible truncation */
xfree(p);
*ptyfd = mm_receive_fd(pmonitor->m_recvfd);
*ttyfd = mm_receive_fd(pmonitor->m_recvfd);
/* Success */
return (1);
}
void
mm_session_pty_cleanup2(void *session)
{
Session *s = session;
Buffer m;
if (s->ttyfd == -1)
return;
buffer_init(&m);
buffer_put_cstring(&m, s->tty);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
buffer_free(&m);
/* closed dup'ed master */
if (close(s->ptymaster) < 0)
error("close(s->ptymaster): %s", strerror(errno));
/* unlink pty from session */
s->ttyfd = -1;
}
/* Request process termination */
void
mm_terminate(void)
{
Buffer m;
buffer_init(&m);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m);
buffer_free(&m);
}
int
mm_ssh1_session_key(BIGNUM *num)
{
int rsafail;
Buffer m;
buffer_init(&m);
buffer_put_bignum2(&m, num);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m);
rsafail = buffer_get_int(&m);
buffer_get_bignum2(&m, num);
buffer_free(&m);
return (rsafail);
}
static void
mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
char ***prompts, u_int **echo_on)
{
*name = xstrdup("");
*infotxt = xstrdup("");
*numprompts = 1;
*prompts = xmalloc(*numprompts * sizeof(char*));
*echo_on = xmalloc(*numprompts * sizeof(u_int));
(*echo_on)[0] = 0;
}
int
mm_bsdauth_query(void *ctx, char **name, char **infotxt,
u_int *numprompts, char ***prompts, u_int **echo_on)
{
Buffer m;
int res;
char *challenge;
debug3("%s: entering", __func__);
buffer_init(&m);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY,
&m);
res = buffer_get_int(&m);
if (res == -1) {
debug3("%s: no challenge", __func__);
buffer_free(&m);
return (-1);
}
/* Get the challenge, and format the response */
challenge = buffer_get_string(&m, NULL);
buffer_free(&m);
mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
(*prompts)[0] = challenge;
debug3("%s: received challenge: %s", __func__, challenge);
return (0);
}
int
mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
{
Buffer m;
int authok;
debug3("%s: entering", __func__);
if (numresponses != 1)
return (-1);
buffer_init(&m);
buffer_put_cstring(&m, responses[0]);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_BSDAUTHRESPOND, &m);
authok = buffer_get_int(&m);
buffer_free(&m);
return ((authok == 0) ? -1 : 0);
}
int
mm_skey_query(void *ctx, char **name, char **infotxt,
u_int *numprompts, char ***prompts, u_int **echo_on)
{
Buffer m;
int len, res;
char *p, *challenge;
debug3("%s: entering", __func__);
buffer_init(&m);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY,
&m);
res = buffer_get_int(&m);
if (res == -1) {
debug3("%s: no challenge", __func__);
buffer_free(&m);
return (-1);
}
/* Get the challenge, and format the response */
challenge = buffer_get_string(&m, NULL);
buffer_free(&m);
debug3("%s: received challenge: %s", __func__, challenge);
mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
len = strlen(challenge) + strlen(SKEY_PROMPT) + 1;
p = xmalloc(len);
strlcpy(p, challenge, len);
strlcat(p, SKEY_PROMPT, len);
(*prompts)[0] = p;
xfree(challenge);
return (0);
}
int
mm_skey_respond(void *ctx, u_int numresponses, char **responses)
{
Buffer m;
int authok;
debug3("%s: entering", __func__);
if (numresponses != 1)
return (-1);
buffer_init(&m);
buffer_put_cstring(&m, responses[0]);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_SKEYRESPOND, &m);
authok = buffer_get_int(&m);
buffer_free(&m);
return ((authok == 0) ? -1 : 0);
}
void
mm_ssh1_session_id(u_char session_id[16])
{
Buffer m;
int i;
debug3("%s entering", __func__);
buffer_init(&m);
for (i = 0; i < 16; i++)
buffer_put_char(&m, session_id[i]);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m);
buffer_free(&m);
}
int
mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
{
Buffer m;
Key *key;
u_char *blob;
u_int blen;
int allowed = 0;
debug3("%s entering", __func__);
buffer_init(&m);
buffer_put_bignum2(&m, client_n);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);
allowed = buffer_get_int(&m);
if (allowed && rkey != NULL) {
blob = buffer_get_string(&m, &blen);
if ((key = key_from_blob(blob, blen)) == NULL)
fatal("%s: key_from_blob failed", __func__);
*rkey = key;
xfree(blob);
}
mm_send_debug(&m);
buffer_free(&m);
return (allowed);
}
BIGNUM *
mm_auth_rsa_generate_challenge(Key *key)
{
Buffer m;
BIGNUM *challenge;
u_char *blob;
u_int blen;
debug3("%s entering", __func__);
if ((challenge = BN_new()) == NULL)
fatal("%s: BN_new failed", __func__);
key->type = KEY_RSA; /* XXX cheat for key_to_blob */
if (key_to_blob(key, &blob, &blen) == 0)
fatal("%s: key_to_blob failed", __func__);
key->type = KEY_RSA1;
buffer_init(&m);
buffer_put_string(&m, blob, blen);
xfree(blob);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m);
buffer_get_bignum2(&m, challenge);
buffer_free(&m);
return (challenge);
}
int
mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
{
Buffer m;
u_char *blob;
u_int blen;
int success = 0;
debug3("%s entering", __func__);
key->type = KEY_RSA; /* XXX cheat for key_to_blob */
if (key_to_blob(key, &blob, &blen) == 0)
fatal("%s: key_to_blob failed", __func__);
key->type = KEY_RSA1;
buffer_init(&m);
buffer_put_string(&m, blob, blen);
buffer_put_string(&m, response, 16);
xfree(blob);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m);
success = buffer_get_int(&m);
buffer_free(&m);
return (success);
}

View File

@ -0,0 +1,88 @@
/* $OpenBSD: monitor_wrap.h,v 1.5 2002/05/12 23:53:45 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MM_WRAP_H_
#define _MM_WRAP_H_
#include "key.h"
#include "buffer.h"
extern int use_privsep;
#define PRIVSEP(x) (use_privsep ? mm_##x : x)
enum mm_keytype {MM_NOKEY, MM_HOSTKEY, MM_USERKEY, MM_RSAHOSTKEY, MM_RSAUSERKEY};
struct monitor;
struct mm_master;
struct passwd;
struct Authctxt;
DH *mm_choose_dh(int, int, int);
int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int);
void mm_inform_authserv(char *, char *);
struct passwd *mm_getpwnamallow(const char *);
char* mm_auth2_read_banner(void);
int mm_auth_password(struct Authctxt *, char *);
int mm_key_allowed(enum mm_keytype, char *, char *, Key *);
int mm_user_key_allowed(struct passwd *, Key *);
int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *);
int mm_auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int);
int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *);
BIGNUM *mm_auth_rsa_generate_challenge(Key *);
void mm_terminate(void);
int mm_pty_allocate(int *, int *, char *, int);
void mm_session_pty_cleanup2(void *);
/* SSHv1 interfaces */
void mm_ssh1_session_id(u_char *);
int mm_ssh1_session_key(BIGNUM *);
/* Key export functions */
struct Newkeys *mm_newkeys_from_blob(u_char *, int);
int mm_newkeys_to_blob(int, u_char **, u_int *);
void monitor_apply_keystate(struct monitor *);
void mm_get_keystate(struct monitor *);
void mm_send_keystate(struct monitor*);
/* bsdauth */
int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
int mm_bsdauth_respond(void *, u_int, char **);
/* skey */
int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
int mm_skey_respond(void *, u_int, char **);
/* zlib allocation hooks */
void *mm_zalloc(struct mm_master *, u_int, u_int);
void mm_zfree(struct mm_master *, void *);
void mm_init_compression(struct mm_master *);
#endif /* _MM_H_ */

73
crypto/openssh/msg.c Normal file
View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: msg.c,v 1.2 2002/06/19 00:27:55 deraadt Exp $");
#include "buffer.h"
#include "getput.h"
#include "log.h"
#include "atomicio.h"
#include "msg.h"
void
msg_send(int fd, u_char type, Buffer *m)
{
u_char buf[5];
u_int mlen = buffer_len(m);
debug3("msg_send: type %d", type);
PUT_32BIT(buf, mlen + 1);
buf[4] = type; /* 1st byte of payload is mesg-type */
if (atomicio(write, fd, buf, sizeof(buf)) != sizeof(buf))
fatal("msg_send: write");
if (atomicio(write, fd, buffer_ptr(m), mlen) != mlen)
fatal("msg_send: write");
}
int
msg_recv(int fd, Buffer *m)
{
u_char buf[4];
ssize_t res;
u_int msg_len;
debug3("msg_recv entering");
res = atomicio(read, fd, buf, sizeof(buf));
if (res != sizeof(buf)) {
if (res == 0)
return -1;
fatal("msg_recv: read: header %d", res);
}
msg_len = GET_32BIT(buf);
if (msg_len > 256 * 1024)
fatal("msg_recv: read: bad msg_len %d", msg_len);
buffer_clear(m);
buffer_append_space(m, msg_len);
res = atomicio(read, fd, buffer_ptr(m), msg_len);
if (res != msg_len)
fatal("msg_recv: read: %ld != msg_len", (long)res);
return 0;
}

31
crypto/openssh/msg.h Normal file
View File

@ -0,0 +1,31 @@
/* $OpenBSD: msg.h,v 1.1 2002/05/23 19:24:30 markus Exp $ */
/*
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SSH_MSG_H
#define SSH_MSG_H
void msg_send(int, u_char, Buffer *);
int msg_recv(int, Buffer *);
#endif

View File

@ -1,4 +1,4 @@
/* $OpenBSD: myproposal.h,v 1.13 2002/01/21 22:30:12 markus Exp $ */
/* $OpenBSD: myproposal.h,v 1.14 2002/04/03 09:26:11 markus Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -27,7 +27,7 @@
#define KEX_DEFAULT_PK_ALG "ssh-rsa,ssh-dss"
#define KEX_DEFAULT_ENCRYPT \
"aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour," \
"aes192-cbc,aes256-cbc"
"aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se"
#define KEX_DEFAULT_MAC \
"hmac-md5,hmac-sha1,hmac-ripemd160," \
"hmac-ripemd160@openssh.com," \

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: nchan.c,v 1.44 2002/01/21 23:27:10 markus Exp $");
RCSID("$OpenBSD: nchan.c,v 1.47 2002/06/19 00:27:55 deraadt Exp $");
#include "ssh1.h"
#include "ssh2.h"
@ -302,6 +302,7 @@ static void
chan_rcvd_eof2(Channel *c)
{
debug("channel %d: rcvd eof", c->self);
c->flags |= CHAN_EOF_RCVD;
if (c->ostate == CHAN_OUTPUT_OPEN)
chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
}
@ -330,6 +331,7 @@ chan_send_eof2(Channel *c)
packet_start(SSH2_MSG_CHANNEL_EOF);
packet_put_int(c->remote_id);
packet_send();
c->flags |= CHAN_EOF_SENT;
break;
default:
error("channel %d: cannot send eof for istate %d",
@ -365,7 +367,8 @@ chan_rcvd_ieof(Channel *c)
else
chan_rcvd_ieof1(c);
if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
buffer_len(&c->output) == 0)
buffer_len(&c->output) == 0 &&
!CHANNEL_EFD_OUTPUT_ACTIVE(c))
chan_obuf_empty(c);
}
void
@ -404,39 +407,30 @@ chan_is_dead(Channel *c, int send)
debug("channel %d: is dead", c->self);
return 1;
}
/*
* we have to delay the close message if the efd (for stderr) is
* still active
*/
if (((c->extended_usage != CHAN_EXTENDED_IGNORE) &&
buffer_len(&c->extended) > 0)
#if 0
|| ((c->extended_usage == CHAN_EXTENDED_READ) &&
c->efd != -1)
#endif
) {
debug2("channel %d: active efd: %d len %d type %s",
c->self, c->efd, buffer_len(&c->extended),
c->extended_usage==CHAN_EXTENDED_READ ?
"read": "write");
} else {
if (!(c->flags & CHAN_CLOSE_SENT)) {
if (send) {
chan_send_close2(c);
} else {
/* channel would be dead if we sent a close */
if (c->flags & CHAN_CLOSE_RCVD) {
debug("channel %d: almost dead",
c->self);
return 1;
}
if ((datafellows & SSH_BUG_EXTEOF) &&
c->extended_usage == CHAN_EXTENDED_WRITE &&
c->efd != -1 &&
buffer_len(&c->extended) > 0) {
debug2("channel %d: active efd: %d len %d",
c->self, c->efd, buffer_len(&c->extended));
return 0;
}
if (!(c->flags & CHAN_CLOSE_SENT)) {
if (send) {
chan_send_close2(c);
} else {
/* channel would be dead if we sent a close */
if (c->flags & CHAN_CLOSE_RCVD) {
debug("channel %d: almost dead",
c->self);
return 1;
}
}
if ((c->flags & CHAN_CLOSE_SENT) &&
(c->flags & CHAN_CLOSE_RCVD)) {
debug("channel %d: is dead", c->self);
return 1;
}
}
if ((c->flags & CHAN_CLOSE_SENT) &&
(c->flags & CHAN_CLOSE_RCVD)) {
debug("channel %d: is dead", c->self);
return 1;
}
return 0;
}

View File

@ -37,7 +37,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: packet.c,v 1.90 2002/02/27 21:23:13 stevesk Exp $");
RCSID("$OpenBSD: packet.c,v 1.95 2002/06/19 18:01:00 markus Exp $");
#include "xmalloc.h"
#include "buffer.h"
@ -60,6 +60,7 @@ RCSID("$OpenBSD: packet.c,v 1.90 2002/02/27 21:23:13 stevesk Exp $");
#include "log.h"
#include "canohost.h"
#include "misc.h"
#include "ssh.h"
#ifdef PACKET_DEBUG
#define DBG(x) x
@ -86,10 +87,10 @@ static CipherContext receive_context;
static CipherContext send_context;
/* Buffer for raw input data from the socket. */
static Buffer input;
Buffer input;
/* Buffer for raw output data going to the socket. */
static Buffer output;
Buffer output;
/* Buffer for the partial outgoing packet being constructed. */
static Buffer outgoing_packet;
@ -115,6 +116,12 @@ static int interactive_mode = 0;
/* Session key information for Encryption and MAC */
Newkeys *newkeys[MODE_MAX];
static u_int32_t read_seqnr = 0;
static u_int32_t send_seqnr = 0;
/* Session key for protocol v1 */
static u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
static u_int ssh1_keylen;
/* roundup current message to extra_pad bytes */
static u_char extra_pad = 0;
@ -171,6 +178,99 @@ packet_connection_is_on_socket(void)
return 1;
}
/*
* Exports an IV from the CipherContext required to export the key
* state back from the unprivileged child to the privileged parent
* process.
*/
void
packet_get_keyiv(int mode, u_char *iv, u_int len)
{
CipherContext *cc;
if (mode == MODE_OUT)
cc = &send_context;
else
cc = &receive_context;
cipher_get_keyiv(cc, iv, len);
}
int
packet_get_keycontext(int mode, u_char *dat)
{
CipherContext *cc;
if (mode == MODE_OUT)
cc = &send_context;
else
cc = &receive_context;
return (cipher_get_keycontext(cc, dat));
}
void
packet_set_keycontext(int mode, u_char *dat)
{
CipherContext *cc;
if (mode == MODE_OUT)
cc = &send_context;
else
cc = &receive_context;
cipher_set_keycontext(cc, dat);
}
int
packet_get_keyiv_len(int mode)
{
CipherContext *cc;
if (mode == MODE_OUT)
cc = &send_context;
else
cc = &receive_context;
return (cipher_get_keyiv_len(cc));
}
void
packet_set_iv(int mode, u_char *dat)
{
CipherContext *cc;
if (mode == MODE_OUT)
cc = &send_context;
else
cc = &receive_context;
cipher_set_keyiv(cc, dat);
}
int
packet_get_ssh1_cipher()
{
return (cipher_get_number(receive_context.cipher));
}
u_int32_t
packet_get_seqnr(int mode)
{
return (mode == MODE_IN ? read_seqnr : send_seqnr);
}
void
packet_set_seqnr(int mode, u_int32_t seqnr)
{
if (mode == MODE_IN)
read_seqnr = seqnr;
else if (mode == MODE_OUT)
send_seqnr = seqnr;
else
fatal("packet_set_seqnr: bad mode %d", mode);
}
/* returns 1 if connection is via ipv4 */
int
@ -291,6 +391,7 @@ packet_start_compression(int level)
* key is used for both sending and reception. However, both directions are
* encrypted independently of each other.
*/
void
packet_set_encryption_key(const u_char *key, u_int keylen,
int number)
@ -300,10 +401,23 @@ packet_set_encryption_key(const u_char *key, u_int keylen,
fatal("packet_set_encryption_key: unknown cipher number %d", number);
if (keylen < 20)
fatal("packet_set_encryption_key: keylen too small: %d", keylen);
if (keylen > SSH_SESSION_KEY_LENGTH)
fatal("packet_set_encryption_key: keylen too big: %d", keylen);
memcpy(ssh1_key, key, keylen);
ssh1_keylen = keylen;
cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT);
cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT);
}
u_int
packet_get_encryption_key(u_char *key)
{
if (key == NULL)
return (ssh1_keylen);
memcpy(key, ssh1_key, ssh1_keylen);
return (ssh1_keylen);
}
/* Start constructing a packet to send. */
void
packet_start(u_char type)
@ -433,7 +547,7 @@ packet_send1(void)
*/
}
static void
void
set_newkeys(int mode)
{
Enc *enc;
@ -477,8 +591,9 @@ set_newkeys(int mode)
DBG(debug("cipher_init_context: %d", mode));
cipher_init(cc, enc->cipher, enc->key, enc->key_len,
enc->iv, enc->block_size, encrypt);
memset(enc->iv, 0, enc->block_size);
memset(enc->key, 0, enc->key_len);
/* Deleting the keys does not gain extra security */
/* memset(enc->iv, 0, enc->block_size);
memset(enc->key, 0, enc->key_len); */
if (comp->type != 0 && comp->enabled == 0) {
packet_init_compression();
if (mode == MODE_OUT)
@ -495,7 +610,6 @@ set_newkeys(int mode)
static void
packet_send2(void)
{
static u_int32_t seqnr = 0;
u_char type, *cp, *macbuf = NULL;
u_char padlen, pad;
u_int packet_length = 0;
@ -549,7 +663,7 @@ packet_send2(void)
/* will wrap if extra_pad+padlen > 255 */
extra_pad = roundup(extra_pad, block_size);
pad = extra_pad - ((len + padlen) % extra_pad);
debug("packet_send2: adding %d (len %d padlen %d extra_pad %d)",
debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)",
pad, len, padlen, extra_pad);
padlen += pad;
extra_pad = 0;
@ -576,10 +690,10 @@ packet_send2(void)
/* compute MAC over seqnr and packet(length fields, payload, padding) */
if (mac && mac->enabled) {
macbuf = mac_compute(mac, seqnr,
macbuf = mac_compute(mac, send_seqnr,
buffer_ptr(&outgoing_packet),
buffer_len(&outgoing_packet));
DBG(debug("done calc MAC out #%d", seqnr));
DBG(debug("done calc MAC out #%d", send_seqnr));
}
/* encrypt packet and append to output buffer. */
cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
@ -593,7 +707,7 @@ packet_send2(void)
buffer_dump(&output);
#endif
/* increment sequence number for outgoing packets */
if (++seqnr == 0)
if (++send_seqnr == 0)
log("outgoing seqnr wraps around");
buffer_clear(&outgoing_packet);
@ -783,7 +897,6 @@ packet_read_poll1(void)
static int
packet_read_poll2(u_int32_t *seqnr_p)
{
static u_int32_t seqnr = 0;
static u_int packet_length = 0;
u_int padlen, need;
u_char *macbuf, *cp, type;
@ -845,17 +958,17 @@ packet_read_poll2(u_int32_t *seqnr_p)
* increment sequence number for incoming packet
*/
if (mac && mac->enabled) {
macbuf = mac_compute(mac, seqnr,
macbuf = mac_compute(mac, read_seqnr,
buffer_ptr(&incoming_packet),
buffer_len(&incoming_packet));
if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
packet_disconnect("Corrupted MAC on input.");
DBG(debug("MAC #%d ok", seqnr));
DBG(debug("MAC #%d ok", read_seqnr));
buffer_consume(&input, mac->mac_len);
}
if (seqnr_p != NULL)
*seqnr_p = seqnr;
if (++seqnr == 0)
*seqnr_p = read_seqnr;
if (++read_seqnr == 0)
log("incoming seqnr wraps around");
/* get padlen */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.h,v 1.33 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: packet.h,v 1.35 2002/06/19 18:01:00 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -24,6 +24,7 @@ int packet_get_connection_in(void);
int packet_get_connection_out(void);
void packet_close(void);
void packet_set_encryption_key(const u_char *, u_int, int);
u_int packet_get_encryption_key(u_char *);
void packet_set_protocol_flags(u_int);
u_int packet_get_protocol_flags(void);
void packet_start_compression(int);
@ -56,6 +57,16 @@ void *packet_get_string(u_int *length_ptr);
void packet_disconnect(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void set_newkeys(int mode);
int packet_get_keyiv_len(int);
void packet_get_keyiv(int, u_char *, u_int);
int packet_get_keycontext(int, u_char *);
void packet_set_keycontext(int, u_char *);
u_int32_t packet_get_seqnr(int);
void packet_set_seqnr(int, u_int32_t);
int packet_get_ssh1_cipher(void);
void packet_set_iv(int, u_char *);
void packet_write_poll(void);
void packet_write_wait(void);
int packet_have_data_to_write(void);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: pathnames.h,v 1.11 2002/02/09 17:37:34 deraadt Exp $ */
/* $OpenBSD: pathnames.h,v 1.13 2002/05/23 19:24:30 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -110,6 +110,9 @@
*/
#define _PATH_SSH_ASKPASS_DEFAULT "/usr/X11R6/bin/ssh-askpass"
/* Location of ssh-keysign for hostbased authentication */
#define _PATH_SSH_KEY_SIGN "/usr/libexec/ssh-keysign"
/* xauth for X11 forwarding */
#define _PATH_XAUTH "/usr/X11R6/bin/xauth"
@ -122,3 +125,6 @@
/* for sftp */
#define _PATH_SFTP_SERVER "/usr/libexec/sftp-server"
#define _PATH_LS "ls"
/* chroot directory for unprivileged user when UsePrivilegeSeparation=yes */
#define _PATH_PRIVSEP_CHROOT_DIR "/var/empty"

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 1999 Dug Song. All rights reserved.
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -25,190 +26,132 @@
#include "includes.h"
#include "uuencode.h"
RCSID("$OpenBSD: radix.c,v 1.17 2001/11/19 19:02:16 mpech Exp $");
RCSID("$OpenBSD: radix.c,v 1.21 2002/06/19 00:27:55 deraadt Exp $");
#ifdef AFS
#include <krb.h>
#include <radix.h>
typedef u_char my_u_char;
typedef u_int my_u_int32_t;
typedef u_short my_u_short;
/* Nasty macros from BIND-4.9.2 */
#define GETSHORT(s, cp) { \
my_u_char *t_cp = (my_u_char *)(cp); \
(s) = (((my_u_short)t_cp[0]) << 8) \
| (((my_u_short)t_cp[1])) \
; \
(cp) += 2; \
}
#define GETLONG(l, cp) { \
my_u_char *t_cp = (my_u_char *)(cp); \
(l) = (((my_u_int32_t)t_cp[0]) << 24) \
| (((my_u_int32_t)t_cp[1]) << 16) \
| (((my_u_int32_t)t_cp[2]) << 8) \
| (((my_u_int32_t)t_cp[3])) \
; \
(cp) += 4; \
}
#define PUTSHORT(s, cp) { \
my_u_short t_s = (my_u_short)(s); \
my_u_char *t_cp = (my_u_char *)(cp); \
*t_cp++ = t_s >> 8; \
*t_cp = t_s; \
(cp) += 2; \
}
#define PUTLONG(l, cp) { \
my_u_int32_t t_l = (my_u_int32_t)(l); \
my_u_char *t_cp = (my_u_char *)(cp); \
*t_cp++ = t_l >> 24; \
*t_cp++ = t_l >> 16; \
*t_cp++ = t_l >> 8; \
*t_cp = t_l; \
(cp) += 4; \
}
#define GETSTRING(s, p, p_l) { \
char *p_targ = (p) + p_l; \
char *s_c = (s); \
char *p_c = (p); \
while (*p_c && (p_c < p_targ)) { \
*s_c++ = *p_c++; \
} \
if (p_c == p_targ) { \
return 1; \
} \
*s_c = *p_c++; \
(p_l) = (p_l) - (p_c - (p)); \
(p) = p_c; \
}
#include "bufaux.h"
int
creds_to_radix(CREDENTIALS *creds, u_char *buf, size_t buflen)
{
char *p, *s;
int len;
char temp[2048];
Buffer b;
int ret;
p = temp;
*p++ = 1; /* version */
s = creds->service;
while (*s)
*p++ = *s++;
*p++ = *s;
s = creds->instance;
while (*s)
*p++ = *s++;
*p++ = *s;
s = creds->realm;
while (*s)
*p++ = *s++;
*p++ = *s;
buffer_init(&b);
buffer_put_char(&b, 1); /* version */
buffer_append(&b, creds->service, strlen(creds->service));
buffer_put_char(&b, '\0');
buffer_append(&b, creds->instance, strlen(creds->instance));
buffer_put_char(&b, '\0');
buffer_append(&b, creds->realm, strlen(creds->realm));
buffer_put_char(&b, '\0');
buffer_append(&b, creds->pname, strlen(creds->pname));
buffer_put_char(&b, '\0');
buffer_append(&b, creds->pinst, strlen(creds->pinst));
buffer_put_char(&b, '\0');
s = creds->pname;
while (*s)
*p++ = *s++;
*p++ = *s;
s = creds->pinst;
while (*s)
*p++ = *s++;
*p++ = *s;
/* Null string to repeat the realm. */
*p++ = '\0';
buffer_put_char(&b, '\0');
PUTLONG(creds->issue_date, p);
{
u_int endTime;
endTime = (u_int) krb_life_to_time(creds->issue_date,
creds->lifetime);
PUTLONG(endTime, p);
}
buffer_put_int(&b, creds->issue_date);
buffer_put_int(&b, krb_life_to_time(creds->issue_date,
creds->lifetime));
buffer_append(&b, creds->session, sizeof(creds->session));
buffer_put_short(&b, creds->kvno);
memcpy(p, &creds->session, sizeof(creds->session));
p += sizeof(creds->session);
/* 32 bit size + data */
buffer_put_string(&b, creds->ticket_st.dat, creds->ticket_st.length);
PUTSHORT(creds->kvno, p);
PUTLONG(creds->ticket_st.length, p);
ret = uuencode(buffer_ptr(&b), buffer_len(&b), (char *)buf, buflen);
memcpy(p, creds->ticket_st.dat, creds->ticket_st.length);
p += creds->ticket_st.length;
len = p - temp;
return (uuencode((u_char *)temp, len, (char *)buf, buflen));
buffer_free(&b);
return ret;
}
#define GETSTRING(b, t, tlen) \
do { \
int i, found = 0; \
for (i = 0; i < tlen; i++) { \
if (buffer_len(b) == 0) \
goto done; \
t[i] = buffer_get_char(b); \
if (t[i] == '\0') { \
found = 1; \
break; \
} \
} \
if (!found) \
goto done; \
} while(0)
int
radix_to_creds(const char *buf, CREDENTIALS *creds)
{
Buffer b;
char c, version, *space, *p;
u_int endTime;
int len, blen, ret;
char *p;
int len, tl;
char version;
char temp[2048];
ret = 0;
blen = strlen(buf);
len = uudecode(buf, (u_char *)temp, sizeof(temp));
if (len < 0)
/* sanity check for size */
if (blen > 8192)
return 0;
p = temp;
buffer_init(&b);
space = buffer_append_space(&b, blen);
/* check version and length! */
len = uudecode(buf, space, blen);
if (len < 1)
return 0;
version = *p;
p++;
len--;
goto done;
GETSTRING(creds->service, p, len);
GETSTRING(creds->instance, p, len);
GETSTRING(creds->realm, p, len);
version = buffer_get_char(&b);
GETSTRING(&b, creds->service, sizeof creds->service);
GETSTRING(&b, creds->instance, sizeof creds->instance);
GETSTRING(&b, creds->realm, sizeof creds->realm);
GETSTRING(&b, creds->pname, sizeof creds->pname);
GETSTRING(&b, creds->pinst, sizeof creds->pinst);
if (buffer_len(&b) == 0)
goto done;
GETSTRING(creds->pname, p, len);
GETSTRING(creds->pinst, p, len);
/* Ignore possibly different realm. */
while (*p && len)
p++, len--;
if (len == 0)
return 0;
p++, len--;
while (buffer_len(&b) > 0 && (c = buffer_get_char(&b)) != '\0')
;
/* Enough space for remaining fixed-length parts? */
if (len < (4 + 4 + sizeof(creds->session) + 2 + 4))
return 0;
if (buffer_len(&b) == 0)
goto done;
GETLONG(creds->issue_date, p);
len -= 4;
{
u_int endTime;
GETLONG(endTime, p);
len -= 4;
creds->lifetime = krb_time_to_life(creds->issue_date, endTime);
}
creds->issue_date = buffer_get_int(&b);
memcpy(&creds->session, p, sizeof(creds->session));
p += sizeof(creds->session);
len -= sizeof(creds->session);
endTime = buffer_get_int(&b);
creds->lifetime = krb_time_to_life(creds->issue_date, endTime);
GETSHORT(creds->kvno, p);
len -= 2;
GETLONG(creds->ticket_st.length, p);
len -= 4;
len = buffer_len(&b);
if (len < sizeof(creds->session))
goto done;
memcpy(&creds->session, buffer_ptr(&b), sizeof(creds->session));
buffer_consume(&b, sizeof(creds->session));
tl = creds->ticket_st.length;
if (tl < 0 || tl > len || tl > sizeof(creds->ticket_st.dat))
return 0;
creds->kvno = buffer_get_short(&b);
memcpy(creds->ticket_st.dat, p, tl);
p += tl;
len -= tl;
p = buffer_get_string(&b, &len);
if (len < 0 || len > sizeof(creds->ticket_st.dat))
goto done;
memcpy(&creds->ticket_st.dat, p, len);
creds->ticket_st.length = len;
return 1;
ret = 1;
done:
buffer_free(&b);
return ret;
}
#endif /* AFS */

View File

@ -12,7 +12,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: readconf.c,v 1.95 2002/02/04 12:15:25 markus Exp $");
RCSID("$OpenBSD: readconf.c,v 1.100 2002/06/19 00:27:55 deraadt Exp $");
#include "ssh.h"
#include "xmalloc.h"
@ -41,7 +41,7 @@ RCSID("$OpenBSD: readconf.c,v 1.95 2002/02/04 12:15:25 markus Exp $");
# that they are given in.
Host *.ngs.fi ngs.fi
FallBackToRsh no
User foo
Host fake.com
HostName another.host.name.real.org
@ -65,7 +65,7 @@ RCSID("$OpenBSD: readconf.c,v 1.95 2002/02/04 12:15:25 markus Exp $");
ProxyCommand ssh-proxy %h %p
Host *.fr
UseRsh yes
PublicKeyAuthentication no
Host *.su
Cipher none
@ -79,8 +79,6 @@ RCSID("$OpenBSD: readconf.c,v 1.95 2002/02/04 12:15:25 markus Exp $");
PasswordAuthentication yes
RSAAuthentication yes
RhostsRSAAuthentication yes
FallBackToRsh no
UseRsh no
StrictHostKeyChecking yes
KeepAlives no
IdentityFile ~/.ssh/identity
@ -94,7 +92,7 @@ RCSID("$OpenBSD: readconf.c,v 1.95 2002/02/04 12:15:25 markus Exp $");
typedef enum {
oBadOption,
oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
oPasswordAuthentication, oRSAAuthentication,
oChallengeResponseAuthentication, oXAuthLocation,
#if defined(KRB4) || defined(KRB5)
oKerberosAuthentication,
@ -115,7 +113,8 @@ typedef enum {
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
oClearAllForwardings, oNoHostAuthenticationForLocalhost
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
oDeprecated
} OpCodes;
/* Textual representations of the tokens. */
@ -150,8 +149,8 @@ static struct {
#ifdef AFS
{ "afstokenpassing", oAFSTokenPassing },
#endif
{ "fallbacktorsh", oFallBackToRsh },
{ "usersh", oUseRsh },
{ "fallbacktorsh", oDeprecated },
{ "usersh", oDeprecated },
{ "identityfile", oIdentityFile },
{ "identityfile2", oIdentityFile }, /* alias */
{ "hostname", oHostName },
@ -371,14 +370,6 @@ process_config_line(Options *options, const char *host,
intptr = &options->afs_token_passing;
goto parse_flag;
#endif
case oFallBackToRsh:
intptr = &options->fallback_to_rsh;
goto parse_flag;
case oUseRsh:
intptr = &options->use_rsh;
goto parse_flag;
case oBatchMode:
intptr = &options->batch_mode;
goto parse_flag;
@ -676,6 +667,11 @@ process_config_line(Options *options, const char *host,
*intptr = value;
break;
case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword);
return 0;
default:
fatal("process_config_line: Unimplemented opcode %d", opcode);
}
@ -763,8 +759,6 @@ initialize_options(Options * options)
options->kbd_interactive_devices = NULL;
options->rhosts_rsa_authentication = -1;
options->hostbased_authentication = -1;
options->fallback_to_rsh = -1;
options->use_rsh = -1;
options->batch_mode = -1;
options->check_host_ip = -1;
options->strict_host_key_checking = -1;
@ -820,7 +814,7 @@ fill_default_options(Options * options)
if (options->use_privileged_port == -1)
options->use_privileged_port = 0;
if (options->rhosts_authentication == -1)
options->rhosts_authentication = 1;
options->rhosts_authentication = 0;
if (options->rsa_authentication == -1)
options->rsa_authentication = 1;
if (options->pubkey_authentication == -1)
@ -844,13 +838,9 @@ fill_default_options(Options * options)
if (options->kbd_interactive_authentication == -1)
options->kbd_interactive_authentication = 1;
if (options->rhosts_rsa_authentication == -1)
options->rhosts_rsa_authentication = 1;
options->rhosts_rsa_authentication = 0;
if (options->hostbased_authentication == -1)
options->hostbased_authentication = 0;
if (options->fallback_to_rsh == -1)
options->fallback_to_rsh = 0;
if (options->use_rsh == -1)
options->use_rsh = 0;
if (options->batch_mode == -1)
options->batch_mode = 0;
if (options->check_host_ip == -1)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.h,v 1.42 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: readconf.h,v 1.43 2002/06/08 05:17:01 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -54,8 +54,6 @@ typedef struct {
* authentication. */
int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */
int fallback_to_rsh;/* Use rsh if cannot connect with ssh. */
int use_rsh; /* Always use rsh (don\'t try ssh). */
int batch_mode; /* Batch mode: do not ask for passwords. */
int check_host_ip; /* Also keep track of keys for IP address */
int strict_host_key_checking; /* Strict host key checking. */

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: readpass.c,v 1.26 2002/02/13 00:39:15 markus Exp $");
RCSID("$OpenBSD: readpass.c,v 1.27 2002/03/26 15:58:46 markus Exp $");
#include <readpassphrase.h>
@ -120,8 +120,11 @@ read_passphrase(const char *prompt, int flags)
return ssh_askpass(askpass, prompt);
}
if (readpassphrase(prompt, buf, sizeof buf, rppflags) == NULL)
if (readpassphrase(prompt, buf, sizeof buf, rppflags) == NULL) {
if (flags & RP_ALLOW_EOF)
return NULL;
return xstrdup("");
}
ret = xstrdup(buf);
memset(buf, 'x', sizeof buf);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readpass.h,v 1.6 2001/06/26 17:27:24 markus Exp $ */
/* $OpenBSD: readpass.h,v 1.7 2002/03/26 15:58:46 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -14,5 +14,6 @@
#define RP_ECHO 0x0001
#define RP_ALLOW_STDIN 0x0002
#define RP_ALLOW_EOF 0x0004
char *read_passphrase(const char *, int);

View File

@ -24,16 +24,30 @@
#ifdef SMARTCARD
#include "includes.h"
RCSID("$OpenBSD: scard.c,v 1.17 2001/12/27 18:22:16 markus Exp $");
RCSID("$OpenBSD: scard.c,v 1.25 2002/03/26 18:46:59 rees Exp $");
#include <openssl/engine.h>
#include <openssl/evp.h>
#include <sectok.h>
#include "key.h"
#include "log.h"
#include "xmalloc.h"
#include "readpass.h"
#include "scard.h"
#if OPENSSL_VERSION_NUMBER < 0x00907000L
#define USE_ENGINE
#define RSA_get_default_method RSA_get_default_openssl_method
#else
#endif
#ifdef USE_ENGINE
#include <openssl/engine.h>
#define sc_get_rsa sc_get_engine
#else
#define sc_get_rsa sc_get_rsa_method
#endif
#define CLA_SSH 0x05
#define INS_DECRYPT 0x10
#define INS_GET_KEYLENGTH 0x20
@ -42,10 +56,17 @@ RCSID("$OpenBSD: scard.c,v 1.17 2001/12/27 18:22:16 markus Exp $");
#define MAX_BUF_SIZE 256
u_char DEFAUT0[] = {0xad, 0x9f, 0x61, 0xfe, 0xfa, 0x20, 0xce, 0x63};
static int sc_fd = -1;
static char *sc_reader_id = NULL;
static char *sc_pin = NULL;
static int cla = 0x00; /* class */
static void sc_mk_digest(const char *pin, u_char *digest);
static int get_AUT0(u_char *aut0);
static int try_AUT0(void);
/* interface to libsectok */
static int
@ -126,8 +147,7 @@ sc_read_pubkey(Key * k)
n = NULL;
if (sc_fd < 0) {
status = sc_init();
if (status < 0 )
if (sc_init() < 0)
goto err;
}
@ -145,6 +165,12 @@ sc_read_pubkey(Key * k)
n = xmalloc(len);
/* get n */
sectok_apdu(sc_fd, CLA_SSH, INS_GET_PUBKEY, 0, 0, 0, NULL, len, n, &sw);
if (sw == 0x6982) {
if (try_AUT0() < 0)
goto err;
sectok_apdu(sc_fd, CLA_SSH, INS_GET_PUBKEY, 0, 0, 0, NULL, len, n, &sw);
}
if (!sectok_swOK(sw)) {
error("could not obtain public key: %s", sectok_get_sw(sw));
goto err;
@ -178,7 +204,8 @@ sc_read_pubkey(Key * k)
/* private key operations */
static int
sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding)
sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa,
int padding)
{
u_char *padded = NULL;
int sw, len, olen, status = -1;
@ -197,19 +224,18 @@ sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding)
len = BN_num_bytes(rsa->n);
padded = xmalloc(len);
sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, from, 0, NULL, &sw);
sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, from, len, padded, &sw);
if (sw == 0x6982) {
if (try_AUT0() < 0)
goto err;
sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, from, len, padded, &sw);
}
if (!sectok_swOK(sw)) {
error("sc_private_decrypt: INS_DECRYPT failed: %s",
sectok_get_sw(sw));
goto err;
}
sectok_apdu(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, 0, NULL,
len, padded, &sw);
if (!sectok_swOK(sw)) {
error("sc_private_decrypt: INS_GET_RESPONSE failed: %s",
sectok_get_sw(sw));
goto err;
}
olen = RSA_padding_check_PKCS1_type_2(to, len, padded + 1, len - 1,
len);
err:
@ -220,7 +246,8 @@ sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding)
}
static int
sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding)
sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa,
int padding)
{
u_char *padded = NULL;
int sw, len, status = -1;
@ -238,20 +265,18 @@ sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding)
len = BN_num_bytes(rsa->n);
padded = xmalloc(len);
if (RSA_padding_add_PKCS1_type_1(padded, len, from, flen) <= 0) {
if (RSA_padding_add_PKCS1_type_1(padded, len, (u_char *)from, flen) <= 0) {
error("RSA_padding_add_PKCS1_type_1 failed");
goto err;
}
sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, 0, NULL, &sw);
if (!sectok_swOK(sw)) {
error("sc_private_decrypt: INS_DECRYPT failed: %s",
sectok_get_sw(sw));
goto err;
sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, len, to, &sw);
if (sw == 0x6982) {
if (try_AUT0() < 0)
goto err;
sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, len, to, &sw);
}
sectok_apdu(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, 0, NULL,
len, to, &sw);
if (!sectok_swOK(sw)) {
error("sc_private_decrypt: INS_GET_RESPONSE failed: %s",
error("sc_private_encrypt: INS_DECRYPT failed: %s",
sectok_get_sw(sw));
goto err;
}
@ -275,31 +300,18 @@ sc_finish(RSA *rsa)
return 1;
}
/* engine for overloading private key operations */
static ENGINE *smart_engine = NULL;
static RSA_METHOD smart_rsa =
static RSA_METHOD *
sc_get_rsa_method(void)
{
"sectok",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
0,
NULL,
};
static RSA_METHOD smart_rsa;
const RSA_METHOD *def = RSA_get_default_method();
ENGINE *
sc_get_engine(void)
{
RSA_METHOD *def;
/* use the OpenSSL version */
memcpy(&smart_rsa, def, sizeof(smart_rsa));
def = RSA_get_default_openssl_method();
smart_rsa.name = "sectok";
/* overload */
smart_rsa.rsa_priv_enc = sc_private_encrypt;
@ -309,23 +321,22 @@ sc_get_engine(void)
orig_finish = def->finish;
smart_rsa.finish = sc_finish;
/* just use the OpenSSL version */
smart_rsa.rsa_pub_enc = def->rsa_pub_enc;
smart_rsa.rsa_pub_dec = def->rsa_pub_dec;
smart_rsa.rsa_mod_exp = def->rsa_mod_exp;
smart_rsa.bn_mod_exp = def->bn_mod_exp;
smart_rsa.init = def->init;
smart_rsa.flags = def->flags;
smart_rsa.app_data = def->app_data;
smart_rsa.rsa_sign = def->rsa_sign;
smart_rsa.rsa_verify = def->rsa_verify;
return &smart_rsa;
}
#ifdef USE_ENGINE
static ENGINE *
sc_get_engine(void)
{
static ENGINE *smart_engine = NULL;
if ((smart_engine = ENGINE_new()) == NULL)
fatal("ENGINE_new failed");
ENGINE_set_id(smart_engine, "sectok");
ENGINE_set_name(smart_engine, "libsectok");
ENGINE_set_RSA(smart_engine, &smart_rsa);
ENGINE_set_RSA(smart_engine, sc_get_rsa_method());
ENGINE_set_DSA(smart_engine, DSA_get_default_openssl_method());
ENGINE_set_DH(smart_engine, DH_get_default_openssl_method());
ENGINE_set_RAND(smart_engine, RAND_SSLeay());
@ -333,6 +344,7 @@ sc_get_engine(void)
return smart_engine;
}
#endif
void
sc_close(void)
@ -343,16 +355,20 @@ sc_close(void)
}
}
Key *
sc_get_key(const char *id)
Key **
sc_get_keys(const char *id, const char *pin)
{
Key *k;
int status;
Key *k, *n, **keys;
int status, nkeys = 2;
if (sc_reader_id != NULL)
xfree(sc_reader_id);
sc_reader_id = xstrdup(id);
if (sc_pin != NULL)
xfree(sc_pin);
sc_pin = (pin == NULL) ? NULL : xstrdup(pin);
k = key_new(KEY_RSA);
if (k == NULL) {
return NULL;
@ -367,6 +383,175 @@ sc_get_key(const char *id)
key_free(k);
return NULL;
}
return k;
keys = xmalloc((nkeys+1) * sizeof(Key *));
n = key_new(KEY_RSA1);
BN_copy(n->rsa->n, k->rsa->n);
BN_copy(n->rsa->e, k->rsa->e);
RSA_set_method(n->rsa, sc_get_rsa());
n->flags |= KEY_FLAG_EXT;
keys[0] = n;
n = key_new(KEY_RSA);
BN_copy(n->rsa->n, k->rsa->n);
BN_copy(n->rsa->e, k->rsa->e);
RSA_set_method(n->rsa, sc_get_rsa());
n->flags |= KEY_FLAG_EXT;
keys[1] = n;
keys[2] = NULL;
key_free(k);
return keys;
}
#define NUM_RSA_KEY_ELEMENTS 5+1
#define COPY_RSA_KEY(x, i) \
do { \
len = BN_num_bytes(prv->rsa->x); \
elements[i] = xmalloc(len); \
debug("#bytes %d", len); \
if (BN_bn2bin(prv->rsa->x, elements[i]) < 0) \
goto done; \
} while (0)
static void
sc_mk_digest(const char *pin, u_char *digest)
{
const EVP_MD *evp_md = EVP_sha1();
EVP_MD_CTX md;
EVP_DigestInit(&md, evp_md);
EVP_DigestUpdate(&md, pin, strlen(pin));
EVP_DigestFinal(&md, digest, NULL);
}
static int
get_AUT0(u_char *aut0)
{
char *pass;
pass = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN);
if (pass == NULL)
return -1;
if (!strcmp(pass, "-")) {
memcpy(aut0, DEFAUT0, sizeof DEFAUT0);
return 0;
}
sc_mk_digest(pass, aut0);
memset(pass, 0, strlen(pass));
xfree(pass);
return 0;
}
static int
try_AUT0(void)
{
u_char aut0[EVP_MAX_MD_SIZE];
/* permission denied; try PIN if provided */
if (sc_pin && strlen(sc_pin) > 0) {
sc_mk_digest(sc_pin, aut0);
if (cyberflex_verify_AUT0(sc_fd, cla, aut0, 8) < 0) {
error("smartcard passphrase incorrect");
return (-1);
}
} else {
/* try default AUT0 key */
if (cyberflex_verify_AUT0(sc_fd, cla, DEFAUT0, 8) < 0) {
/* default AUT0 key failed; prompt for passphrase */
if (get_AUT0(aut0) < 0 ||
cyberflex_verify_AUT0(sc_fd, cla, aut0, 8) < 0) {
error("smartcard passphrase incorrect");
return (-1);
}
}
}
return (0);
}
int
sc_put_key(Key *prv, const char *id)
{
u_char *elements[NUM_RSA_KEY_ELEMENTS];
u_char key_fid[2];
u_char AUT0[EVP_MAX_MD_SIZE];
int len, status = -1, i, fd = -1, ret;
int sw = 0, cla = 0x00;
for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
elements[i] = NULL;
COPY_RSA_KEY(q, 0);
COPY_RSA_KEY(p, 1);
COPY_RSA_KEY(iqmp, 2);
COPY_RSA_KEY(dmq1, 3);
COPY_RSA_KEY(dmp1, 4);
COPY_RSA_KEY(n, 5);
len = BN_num_bytes(prv->rsa->n);
fd = sectok_friendly_open(id, STONOWAIT, &sw);
if (fd < 0) {
error("sectok_open failed: %s", sectok_get_sw(sw));
goto done;
}
if (! sectok_cardpresent(fd)) {
error("smartcard in reader %s not present", id);
goto done;
}
ret = sectok_reset(fd, 0, NULL, &sw);
if (ret <= 0) {
error("sectok_reset failed: %s", sectok_get_sw(sw));
goto done;
}
if ((cla = cyberflex_inq_class(fd)) < 0) {
error("cyberflex_inq_class failed");
goto done;
}
memcpy(AUT0, DEFAUT0, sizeof(DEFAUT0));
if (cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) {
if (get_AUT0(AUT0) < 0 ||
cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) {
memset(AUT0, 0, sizeof(DEFAUT0));
error("smartcard passphrase incorrect");
goto done;
}
}
memset(AUT0, 0, sizeof(DEFAUT0));
key_fid[0] = 0x00;
key_fid[1] = 0x12;
if (cyberflex_load_rsa_priv(fd, cla, key_fid, 5, 8*len, elements,
&sw) < 0) {
error("cyberflex_load_rsa_priv failed: %s", sectok_get_sw(sw));
goto done;
}
if (!sectok_swOK(sw))
goto done;
log("cyberflex_load_rsa_priv done");
key_fid[0] = 0x73;
key_fid[1] = 0x68;
if (cyberflex_load_rsa_pub(fd, cla, key_fid, len, elements[5],
&sw) < 0) {
error("cyberflex_load_rsa_pub failed: %s", sectok_get_sw(sw));
goto done;
}
if (!sectok_swOK(sw))
goto done;
log("cyberflex_load_rsa_pub done");
status = 0;
done:
memset(elements[0], '\0', BN_num_bytes(prv->rsa->q));
memset(elements[1], '\0', BN_num_bytes(prv->rsa->p));
memset(elements[2], '\0', BN_num_bytes(prv->rsa->iqmp));
memset(elements[3], '\0', BN_num_bytes(prv->rsa->dmq1));
memset(elements[4], '\0', BN_num_bytes(prv->rsa->dmp1));
memset(elements[5], '\0', BN_num_bytes(prv->rsa->n));
for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
if (elements[i])
xfree(elements[i]);
if (fd != -1)
sectok_close(fd);
return (status);
}
#endif /* SMARTCARD */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: scard.h,v 1.7 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: scard.h,v 1.10 2002/03/25 17:34:27 markus Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@ -24,17 +24,17 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <openssl/engine.h>
#ifndef SCARD_H
#define SCARD_H
#include "key.h"
#define SCARD_ERROR_FAIL -1
#define SCARD_ERROR_NOCARD -2
#define SCARD_ERROR_APPLET -3
Key *sc_get_key(const char*);
ENGINE *sc_get_engine(void);
Key **sc_get_keys(const char*, const char*);
void sc_close(void);
int sc_put_key(Key *, const char*);
#endif

View File

@ -1,16 +1,17 @@
begin 644 Ssh.bin
M`P)!%P`501P`;``!`C@"`/Y@\`4`_J'P!0!!%T$;`?Z@\`4`01=!&@'^>/,!
M`4$701P!_G#S%P'^0],1`?Y@\!0`_G/S'0#^<]4``D$7L`4`_F'3``!!%T$9
M`?YATP4`_G/5"P7^8=,'`OZAT`$!_J#0$@1!%T$8`0```$$7!`$&`/Y@`;@`
M`$$8\`H(`$$9\`H``$$:\@\``$$;\B$``$$<\A```/`&__(```0(`!8```9C
M""T#"<(H+00$*"T%""A;`&19``#P$/_R`P(&`0#(```38`!!70!&$UP`1@09
M":1+``D*D`!@`"@37`!&!!E6`````*(````$____P````*$````0````*@``
M`"````"-````,````&H37`!&`QD(2@`)"FX`8``H$UP`1@<9"@#_/2!@`$L1
M2@`)"F<`8``H$UP`'A-<`$8($1-<`$8(7@!0"!%@`%59"C\`8`!:*PIS:&``
M6BL37`!&`P,*`(!@`%\K`PH`@&``55D37`!&`P<H$UP`1@0#*`,%8`!565D*
M;0!@`"A9`/`"__(!`0$)``@```J0`&``*%D`\!/_\@$!`@D`#```8D$7+5\`
M/"M9````\!+_]@$!`P$`&```$UP`'EX`,D4`#Q-<`!X*`,@)$%X`-P17L`7_
M\@$!!`(`/```$U\``!-B_J$M7P`%70`*$V+^H"U?``]=`!038OYX+0H$`%\`
<&5T`'@H$`&``(T4`"0IG`&``*!->`"U9````````
M`P)!&P`801X`>``!`E@"`/Y@\`4`_J'P!0!!&T$=`?Z@\`4`01M!'`'^>/,!
M`4$;01X!_G#S%P'^0],1`?Y@\!0`_G/S'0#^<]4``D$;L`4`_F'3``#^8=,%
M`/ZAT`$!_J#0)P'^H],*`?ZCTPD`_G/5"P7^8=,'`OZAT`H`_J#0$@3^:-,@
M`T$;`P`%`/Y@`<P``$$<\@\``$$=\B$``$$>\A```/`0__(%`@8!`0H``&``
M0205!!D)I$L`"0J0`&``*!4$&58``````.P````%____P````.D````0````
M,P```"````#'````,````(T````R````V!4#&0A*``D*;@!@`"@5!QD*`/\]
M(6``1A)*``D*9P!@`"@*/P!@`$LK"1)@`$LK!6``4!P$#00#2@`.#01@`%5@
M`%I@`"@37``>%0@2%0A>`%\($F``9%(`:`H_`&``2RL*<VA@`$LK8`!I"1`U
M(14#`Q)@`&X<!`T$`TL`"P,28`!D4@`.#01@`%5@`%I@`"A2`"X5`PH$`&``
M<RL#!6``9%(`'14#"@$"8`!S*P,%8`!D4@`,4@`)"FT`8``H60``\`+_\@$!
M`0D`"```"I``8``H60#P$__R`0$""0`,``!B01LM7P`\*UD```#P$O_V`0$#
M`0`8```37``>7@`R10`/$UP`'@H`R`D07@`W!%>P!?_R`0$$`@`\```37P``
M$V+^H2U?``5=``H38OZ@+5\`#UT`%!-B_G@M"@0`7P`970`>"@0`8``C10`)
/"F<`8``H$UX`+5D`````
`
end

View File

@ -1,4 +1,4 @@
// $Id: Ssh.java,v 1.2 2001/07/30 20:08:14 rees Exp $
// $Id: Ssh.java,v 1.3 2002/03/21 22:44:05 rees Exp $
//
// Ssh.java
// SSH / smartcard integration project, smartcard side
@ -42,6 +42,9 @@ import javacardx.crypto.*;
public class Ssh extends javacard.framework.Applet
{
// Change this when the applet changes; hi byte is major, low byte is minor
static final short applet_version = (short)0x0102;
/* constants declaration */
// code of CLA byte in the command APDU header
static final byte Ssh_CLA =(byte)0x05;
@ -50,20 +53,19 @@ public class Ssh extends javacard.framework.Applet
static final byte DECRYPT = (byte) 0x10;
static final byte GET_KEYLENGTH = (byte) 0x20;
static final byte GET_PUBKEY = (byte) 0x30;
static final byte GET_VERSION = (byte) 0x32;
static final byte GET_RESPONSE = (byte) 0xc0;
/* instance variables declaration */
static final short keysize = 1024;
static final short root_fid = (short)0x3f00;
static final short privkey_fid = (short)0x0012;
static final short pubkey_fid = (short)(('s'<<8)|'h');
//RSA_CRT_PrivateKey rsakey;
/* instance variables declaration */
AsymKey rsakey;
CyberflexFile file;
CyberflexOS os;
byte buffer[];
static byte[] keyHdr = {(byte)0xC2, (byte)0x01, (byte)0x05};
private Ssh()
{
file = new CyberflexFile();
@ -98,7 +100,8 @@ public class Ssh extends javacard.framework.Applet
// APDU object carries a byte array (buffer) to
// transfer incoming and outgoing APDU header
// and data bytes between card and CAD
buffer = apdu.getBuffer();
byte buffer[] = apdu.getBuffer();
short size, st;
// verify that if the applet can accept this
// APDU message
@ -111,29 +114,47 @@ public class Ssh extends javacard.framework.Applet
if (buffer[ISO.OFFSET_CLA] != Ssh_CLA)
ISOException.throwIt(ISO.SW_CLA_NOT_SUPPORTED);
//decrypt (apdu);
short size = (short) (buffer[ISO.OFFSET_LC] & 0x00FF);
size = (short) (buffer[ISO.OFFSET_LC] & 0x00FF);
if (apdu.setIncomingAndReceive() != size)
ISOException.throwIt (ISO.SW_WRONG_LENGTH);
// check access; depends on bit 2 (x/a)
file.selectFile(root_fid);
file.selectFile(privkey_fid);
st = os.checkAccess(ACL.EXECUTE);
if (st != ST.ACCESS_CLEARED) {
CyberflexAPDU.prepareSW1SW2(st);
ISOException.throwIt(CyberflexAPDU.getSW1SW2());
}
rsakey.cryptoUpdate (buffer, (short) ISO.OFFSET_CDATA, size,
buffer, (short) ISO.OFFSET_CDATA);
apdu.setOutgoingAndSend ((short) ISO.OFFSET_CDATA, size);
return;
break;
case GET_PUBKEY:
file.selectFile((short)(0x3f<<8)); // select root
file.selectFile((short)(('s'<<8)|'h')); // select public key file
os.readBinaryFile (buffer, (short)0, (short)0, (short)(keysize/8));
apdu.setOutgoingAndSend((short)0, (short)(keysize/8));
return;
file.selectFile(root_fid); // select root
file.selectFile(pubkey_fid); // select public key file
size = (short)(file.getFileSize() - 16);
st = os.readBinaryFile(buffer, (short)0, (short)0, size);
if (st == ST.SUCCESS)
apdu.setOutgoingAndSend((short)0, size);
else {
CyberflexAPDU.prepareSW1SW2(st);
ISOException.throwIt(CyberflexAPDU.getSW1SW2());
}
break;
case GET_KEYLENGTH:
buffer[0] = (byte)((keysize >> 8) & 0xff);
buffer[1] = (byte)(keysize & 0xff);
Util.setShort(buffer, (short)0, keysize);
apdu.setOutgoingAndSend ((short)0, (short)2);
return;
break;
case GET_VERSION:
Util.setShort(buffer, (short)0, applet_version);
apdu.setOutgoingAndSend ((short)0, (short)2);
break;
case GET_RESPONSE:
return;
break;
default:
ISOException.throwIt (ISO.SW_INS_NOT_SUPPORTED);
}

View File

@ -9,7 +9,7 @@
.\"
.\" Created: Sun May 7 00:14:37 1995 ylo
.\"
.\" $OpenBSD: scp.1,v 1.21 2002/01/29 23:50:37 markus Exp $
.\" $OpenBSD: scp.1,v 1.22 2002/06/20 20:00:05 stevesk Exp $
.\"
.Dd September 25, 1999
.Dt SCP 1
@ -117,9 +117,9 @@ options.
.It Fl o Ar ssh_option
Can be used to pass options to
.Nm ssh
in the format used in the
.Xr ssh 1
configuration file. This is useful for specifying options
in the format used in
.Xr ssh_config 5 .
This is useful for specifying options
for which there is no separate
.Nm scp
command-line flag. For example, forcing the use of protocol
@ -152,4 +152,5 @@ California.
.Xr ssh-add 1 ,
.Xr ssh-agent 1 ,
.Xr ssh-keygen 1 ,
.Xr ssh_config 5
.Xr sshd 8

View File

@ -75,7 +75,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: scp.c,v 1.86 2001/12/05 03:56:39 itojun Exp $");
RCSID("$OpenBSD: scp.c,v 1.91 2002/06/19 00:27:55 deraadt Exp $");
#include "xmalloc.h"
#include "atomicio.h"
@ -219,10 +219,9 @@ main(argc, argv)
extern int optind;
args.list = NULL;
addargs(&args, "ssh"); /* overwritten with ssh_program */
addargs(&args, "ssh"); /* overwritten with ssh_program */
addargs(&args, "-x");
addargs(&args, "-oForwardAgent no");
addargs(&args, "-oFallBackToRsh no");
addargs(&args, "-oClearAllForwardings yes");
fflag = tflag = 0;
@ -354,8 +353,7 @@ toremote(targ, argc, argv)
src = colon(argv[i]);
if (src) { /* remote to remote */
static char *ssh_options =
"-x -o'FallBackToRsh no' "
"-o'ClearAllForwardings yes'";
"-x -o'ClearAllForwardings yes'";
*src++ = 0;
if (*src == 0)
src = ".";
@ -756,7 +754,7 @@ sink(argc, argv)
cursize = need;
}
(void) snprintf(namebuf, need, "%s%s%s", targ,
*targ ? "/" : "", cp);
strcmp(targ, "/") ? "/" : "", cp);
np = namebuf;
} else
np = targ;
@ -931,9 +929,9 @@ void
usage(void)
{
(void) fprintf(stderr,
"usage: scp [-pqrvBC46] [-F config] [-S ssh] [-P port] [-c cipher] [-i identity]\n"
" [-o option] f1 f2\n"
" or: scp [options] f1 ... fn directory\n");
"usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n"
" [-c cipher] [-i identity] [-o option]\n"
" [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
exit(1);
}
@ -1073,7 +1071,7 @@ progressmeter(int flag)
off_t cursize, abbrevsize;
double elapsed;
int ratio, barlength, i, remaining;
char buf[256];
char buf[512];
if (flag == -1) {
(void) gettimeofday(&start, (struct timezone *) 0);
@ -1099,10 +1097,13 @@ progressmeter(int flag)
i = barlength * ratio / 100;
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
"|%.*s%*s|", i,
"***************************************"
"***************************************"
"***************************************"
"***************************************",
"*******************************************************"
"*******************************************************"
"*******************************************************"
"*******************************************************"
"*******************************************************"
"*******************************************************"
"*******************************************************",
barlength - i, "");
}
i = 0;

View File

@ -10,7 +10,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: servconf.c,v 1.101 2002/02/04 12:15:25 markus Exp $");
RCSID("$OpenBSD: servconf.c,v 1.111 2002/06/20 23:05:55 markus Exp $");
#if defined(KRB4) || defined(KRB5)
#include <krb.h>
@ -36,6 +36,8 @@ static void add_one_listen_addr(ServerOptions *, char *, u_short);
/* AF_UNSPEC or AF_INET or AF_INET6 */
extern int IPv4or6;
/* Use of privilege separation or not */
extern int use_privsep;
/* Initializes the server options to their default values. */
@ -86,6 +88,7 @@ initialize_server_options(ServerOptions *options)
options->challenge_response_authentication = -1;
options->permit_empty_passwd = -1;
options->use_login = -1;
options->compression = -1;
options->allow_tcp_forwarding = -1;
options->num_allow_users = 0;
options->num_deny_users = 0;
@ -105,6 +108,9 @@ initialize_server_options(ServerOptions *options)
options->client_alive_count_max = -1;
options->authorized_keys_file = NULL;
options->authorized_keys_file2 = NULL;
/* Needs to be accessable in many places */
use_privsep = -1;
}
void
@ -176,7 +182,7 @@ fill_default_server_options(ServerOptions *options)
options->pubkey_authentication = 1;
#if defined(KRB4) || defined(KRB5)
if (options->kerberos_authentication == -1)
options->kerberos_authentication = (access(KEYFILE, R_OK) == 0);
options->kerberos_authentication = 0;
if (options->kerberos_or_local_passwd == -1)
options->kerberos_or_local_passwd = 1;
if (options->kerberos_ticket_cleanup == -1)
@ -188,7 +194,7 @@ fill_default_server_options(ServerOptions *options)
#endif
#ifdef AFS
if (options->afs_token_passing == -1)
options->afs_token_passing = k_hasafs();
options->afs_token_passing = 0;
#endif
if (options->password_authentication == -1)
options->password_authentication = 1;
@ -200,6 +206,8 @@ fill_default_server_options(ServerOptions *options)
options->permit_empty_passwd = 0;
if (options->use_login == -1)
options->use_login = 0;
if (options->compression == -1)
options->compression = 1;
if (options->allow_tcp_forwarding == -1)
options->allow_tcp_forwarding = 1;
if (options->gateway_ports == -1)
@ -225,6 +233,10 @@ fill_default_server_options(ServerOptions *options)
}
if (options->authorized_keys_file == NULL)
options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
/* Turn privilege separation on by default */
if (use_privsep == -1)
use_privsep = 1;
}
/* Keyword tokens. */
@ -247,13 +259,14 @@ typedef enum {
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
sStrictModes, sEmptyPasswd, sKeepAlives,
sUseLogin, sAllowTcpForwarding,
sUseLogin, sAllowTcpForwarding, sCompression,
sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
sBanner, sVerifyReverseMapping, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
sUsePrivilegeSeparation,
sDeprecated
} ServerOpCodes;
@ -307,6 +320,7 @@ static struct {
{ "strictmodes", sStrictModes },
{ "permitemptypasswords", sEmptyPasswd },
{ "uselogin", sUseLogin },
{ "compression", sCompression },
{ "keepalive", sKeepAlives },
{ "allowtcpforwarding", sAllowTcpForwarding },
{ "allowusers", sAllowUsers },
@ -326,6 +340,7 @@ static struct {
{ "clientalivecountmax", sClientAliveCountMax },
{ "authorizedkeysfile", sAuthorizedKeysFile },
{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
{ "useprivilegeseparation", sUsePrivilegeSeparation},
{ NULL, sBadOption }
};
@ -662,6 +677,10 @@ process_server_config_line(ServerOptions *options, char *line,
intptr = &options->use_login;
goto parse_flag;
case sCompression:
intptr = &options->compression;
goto parse_flag;
case sGatewayPorts:
intptr = &options->gateway_ports;
goto parse_flag;
@ -696,6 +715,10 @@ process_server_config_line(ServerOptions *options, char *line,
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)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.h,v 1.54 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: servconf.h,v 1.58 2002/06/20 23:05:55 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -98,6 +98,7 @@ typedef struct {
int permit_empty_passwd; /* If false, do not permit empty
* passwords. */
int use_login; /* If true, login(1) is used */
int compression; /* If true, compression is allowed */
int allow_tcp_forwarding;
u_int num_allow_users;
char *allow_users[MAX_ALLOW_USERS];
@ -129,7 +130,6 @@ typedef struct {
char *authorized_keys_file; /* File containing public keys */
char *authorized_keys_file2;
} ServerOptions;
void initialize_server_options(ServerOptions *);

View File

@ -35,7 +35,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: serverloop.c,v 1.98 2002/02/06 14:55:16 markus Exp $");
RCSID("$OpenBSD: serverloop.c,v 1.102 2002/06/11 05:46:20 mpech Exp $");
#include "xmalloc.h"
#include "packet.h"
@ -318,9 +318,6 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
tvp = &tv;
}
if (tvp!=NULL)
debug3("tvp!=NULL kid %d mili %d", (int) child_terminated,
max_time_milliseconds);
/* Wait for something to happen, or the timeout to expire. */
ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
@ -673,12 +670,12 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
/* We no longer want our SIGCHLD handler to be called. */
signal(SIGCHLD, SIG_DFL);
wait_pid = waitpid(-1, &wait_status, 0);
if (wait_pid == -1)
packet_disconnect("wait: %.100s", strerror(errno));
else if (wait_pid != pid)
error("Strange, wait returned pid %d, expected %d",
wait_pid, pid);
while ((wait_pid = waitpid(-1, &wait_status, 0)) < 0)
if (errno != EINTR)
packet_disconnect("wait: %.100s", strerror(errno));
if (wait_pid != pid)
error("Strange, wait returned pid %ld, expected %ld",
(long)wait_pid, (long)pid);
/* Check if it exited normally. */
if (WIFEXITED(wait_status)) {
@ -726,8 +723,10 @@ collect_children(void)
sigaddset(&nset, SIGCHLD);
sigprocmask(SIG_BLOCK, &nset, &oset);
if (child_terminated) {
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
session_close_by_pid(pid, status);
while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
(pid < 0 && errno == EINTR))
if (pid > 0)
session_close_by_pid(pid, status);
child_terminated = 0;
}
sigprocmask(SIG_SETMASK, &oset, NULL);
@ -784,7 +783,7 @@ server_loop2(Authctxt *authctxt)
channel_free_all();
/* free remaining sessions, e.g. remove wtmp entries */
session_destroy_all();
session_destroy_all(NULL);
}
static void

View File

@ -33,7 +33,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: session.c,v 1.128 2002/02/16 00:51:44 markus Exp $");
RCSID("$OpenBSD: session.c,v 1.138 2002/06/20 23:05:55 markus Exp $");
#include "ssh.h"
#include "ssh1.h"
@ -56,40 +56,13 @@ RCSID("$OpenBSD: session.c,v 1.128 2002/02/16 00:51:44 markus Exp $");
#include "serverloop.h"
#include "canohost.h"
#include "session.h"
/* types */
#define TTYSZ 64
typedef struct Session Session;
struct Session {
int used;
int self;
struct passwd *pw;
Authctxt *authctxt;
pid_t pid;
/* tty */
char *term;
int ptyfd, ttyfd, ptymaster;
int row, col, xpixel, ypixel;
char tty[TTYSZ];
/* X11 */
int display_number;
char *display;
int screen;
char *auth_display;
char *auth_proto;
char *auth_data;
int single_connection;
/* proto 2 */
int chanid;
int is_subsystem;
};
#include "monitor_wrap.h"
/* func */
Session *session_new(void);
void session_set_fds(Session *, int, int, int);
static void session_pty_cleanup(void *);
void session_pty_cleanup(void *);
void session_proctitle(Session *);
int session_setup_x11fwd(Session *);
void do_exec_pty(Session *, const char *);
@ -103,7 +76,6 @@ int check_quietlogin(Session *, const char *);
static void do_authenticated1(Authctxt *);
static void do_authenticated2(Authctxt *);
static void session_close(Session *);
static int session_pty_req(Session *);
/* import */
@ -123,9 +95,96 @@ const char *original_command = NULL;
Session sessions[MAX_SESSIONS];
#ifdef HAVE_LOGIN_CAP
static login_cap_t *lc;
login_cap_t *lc;
#endif
/* Name and directory of socket for authentication agent forwarding. */
static char *auth_sock_name = NULL;
static char *auth_sock_dir = NULL;
/* removes the agent forwarding socket */
static void
auth_sock_cleanup_proc(void *_pw)
{
struct passwd *pw = _pw;
if (auth_sock_name != NULL) {
temporarily_use_uid(pw);
unlink(auth_sock_name);
rmdir(auth_sock_dir);
auth_sock_name = NULL;
restore_uid();
}
}
static int
auth_input_request_forwarding(struct passwd * pw)
{
Channel *nc;
int sock;
struct sockaddr_un sunaddr;
if (auth_sock_name != NULL) {
error("authentication forwarding requested twice.");
return 0;
}
/* Temporarily drop privileged uid for mkdir/bind. */
temporarily_use_uid(pw);
/* Allocate a buffer for the socket name, and format the name. */
auth_sock_name = xmalloc(MAXPATHLEN);
auth_sock_dir = xmalloc(MAXPATHLEN);
strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
/* Create private directory for socket */
if (mkdtemp(auth_sock_dir) == NULL) {
packet_send_debug("Agent forwarding disabled: "
"mkdtemp() failed: %.100s", strerror(errno));
restore_uid();
xfree(auth_sock_name);
xfree(auth_sock_dir);
auth_sock_name = NULL;
auth_sock_dir = NULL;
return 0;
}
snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld",
auth_sock_dir, (long) getpid());
/* delete agent socket on fatal() */
fatal_add_cleanup(auth_sock_cleanup_proc, pw);
/* Create the socket. */
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
packet_disconnect("socket: %.100s", strerror(errno));
/* Bind it to the name. */
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0)
packet_disconnect("bind: %.100s", strerror(errno));
/* Restore the privileged uid. */
restore_uid();
/* Start listening on the socket. */
if (listen(sock, 5) < 0)
packet_disconnect("listen: %.100s", strerror(errno));
/* Allocate a channel for the authentication agent socket. */
nc = channel_new("auth socket",
SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
0, xstrdup("auth socket"), 1);
strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
return 1;
}
void
do_authenticated(Authctxt *authctxt)
{
@ -138,18 +197,6 @@ do_authenticated(Authctxt *authctxt)
close(startup_pipe);
startup_pipe = -1;
}
#ifdef HAVE_LOGIN_CAP
if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL) {
error("unable to get login class");
return;
}
#ifdef BSD_AUTH
if (auth_approval(NULL, lc, authctxt->pw->pw_name, "ssh") <= 0) {
packet_disconnect("Approval failure for %s",
authctxt->pw->pw_name);
}
#endif
#endif
/* setup the channel layer */
if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
channel_permit_all_opens();
@ -160,7 +207,7 @@ do_authenticated(Authctxt *authctxt)
do_authenticated1(authctxt);
/* remove agent socket */
if (auth_get_socket_name())
if (auth_sock_name != NULL)
auth_sock_cleanup_proc(authctxt->pw);
#ifdef KRB4
if (options.kerberos_ticket_cleanup)
@ -211,6 +258,10 @@ do_authenticated1(Authctxt *authctxt)
compression_level);
break;
}
if (!options.compression) {
debug2("compression disabled");
break;
}
/* Enable compression after we have responded with SUCCESS. */
enable_compression_after_reply = 1;
success = 1;
@ -367,7 +418,7 @@ do_authenticated1(Authctxt *authctxt)
void
do_exec_no_pty(Session *s, const char *command)
{
int pid;
pid_t pid;
#ifdef USE_PIPES
int pin[2], pout[2], perr[2];
@ -583,10 +634,8 @@ void
do_login(Session *s, const char *command)
{
char *time_string;
char hostname[MAXHOSTNAMELEN];
socklen_t fromlen;
struct sockaddr_storage from;
time_t last_login_time;
struct passwd * pw = s->pw;
pid_t pid = getpid();
@ -604,29 +653,25 @@ do_login(Session *s, const char *command)
}
}
/* Get the time and hostname when the user last logged in. */
if (options.print_lastlog) {
hostname[0] = '\0';
last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
hostname, sizeof(hostname));
}
/* Record that there was a login on that tty from the remote host. */
record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping),
(struct sockaddr *)&from);
if (!use_privsep)
record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
get_remote_name_or_ip(utmp_len,
options.verify_reverse_mapping),
(struct sockaddr *)&from);
if (check_quietlogin(s, command))
return;
if (options.print_lastlog && last_login_time != 0) {
time_string = ctime(&last_login_time);
if (options.print_lastlog && s->last_login_time != 0) {
time_string = ctime(&s->last_login_time);
if (strchr(time_string, '\n'))
*strchr(time_string, '\n') = 0;
if (strcmp(hostname, "") == 0)
if (strcmp(s->hostname, "") == 0)
printf("Last login: %s\r\n", time_string);
else
printf("Last login: %s from %s\r\n", time_string, hostname);
printf("Last login: %s from %s\r\n", time_string,
s->hostname);
}
do_motd();
@ -837,9 +882,9 @@ do_setup_env(Session *s, const char *shell)
child_set_env(&env, &envsize, "KRB5CCNAME",
s->authctxt->krb5_ticket_file);
#endif
if (auth_get_socket_name() != NULL)
if (auth_sock_name != NULL)
child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
auth_get_socket_name());
auth_sock_name);
/* read $HOME/.ssh/environment. */
if (!options.use_login) {
@ -903,7 +948,7 @@ do_rc_files(Session *s, const char *shell)
/* Add authority data to .Xauthority if appropriate. */
if (debug_flag) {
fprintf(stderr,
"Running %.100s add "
"Running %.500s add "
"%.100s %.100s %.100s\n",
options.xauth_location, s->auth_display,
s->auth_proto, s->auth_data);
@ -947,7 +992,7 @@ do_nologin(struct passwd *pw)
}
/* Set login name, uid, gid, and groups. */
static void
void
do_setusercontext(struct passwd *pw)
{
if (getuid() == 0 || geteuid() == 0) {
@ -979,6 +1024,20 @@ do_setusercontext(struct passwd *pw)
fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
}
static void
launch_login(struct passwd *pw, const char *hostname)
{
/* Launch login(1). */
execl("/usr/bin/login", "login", "-h", hostname,
"-p", "-f", "--", pw->pw_name, (char *)NULL);
/* Login couldn't be executed, die. */
perror("login");
exit(1);
}
/*
* Performs common processing for the child, such as setting up the
* environment, closing extra file descriptors, setting the user and group
@ -1095,15 +1154,8 @@ do_child(Session *s, const char *command)
signal(SIGPIPE, SIG_DFL);
if (options.use_login) {
/* Launch login(1). */
execl("/usr/bin/login", "login", "-h", hostname,
"-p", "-f", "--", pw->pw_name, (char *)NULL);
/* Login couldn't be executed, die. */
perror("login");
exit(1);
launch_login(pw, hostname);
/* NEVERREACHED */
}
/* Get the last component of the shell name. */
@ -1186,12 +1238,12 @@ session_dump(void)
int i;
for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
debug("dump: used %d session %d %p channel %d pid %d",
debug("dump: used %d session %d %p channel %d pid %ld",
s->used,
s->self,
s,
s->chanid,
s->pid);
(long)s->pid);
}
}
@ -1213,6 +1265,22 @@ session_open(Authctxt *authctxt, int chanid)
return 1;
}
Session *
session_by_tty(char *tty)
{
int i;
for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
debug("session_by_tty: session %d tty %s", i, tty);
return s;
}
}
debug("session_by_tty: unknown tty %.100s", tty);
session_dump();
return NULL;
}
static Session *
session_by_channel(int id)
{
@ -1233,13 +1301,13 @@ static Session *
session_by_pid(pid_t pid)
{
int i;
debug("session_by_pid: pid %d", pid);
debug("session_by_pid: pid %ld", (long)pid);
for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
if (s->used && s->pid == pid)
return s;
}
error("session_by_pid: unknown pid %d", pid);
error("session_by_pid: unknown pid %ld", (long)pid);
session_dump();
return NULL;
}
@ -1270,6 +1338,12 @@ session_pty_req(Session *s)
packet_disconnect("Protocol error: you already have a pty.");
return 0;
}
/* Get the time and hostname when the user last logged in. */
if (options.print_lastlog) {
s->hostname[0] = '\0';
s->last_login_time = get_last_login_time(s->pw->pw_uid,
s->pw->pw_name, s->hostname, sizeof(s->hostname));
}
s->term = packet_get_string(&len);
@ -1290,7 +1364,7 @@ session_pty_req(Session *s)
/* Allocate a pty and open it. */
debug("Allocating pty.");
if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty))) {
if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) {
if (s->term)
xfree(s->term);
s->term = NULL;
@ -1311,7 +1385,8 @@ session_pty_req(Session *s)
* time in case we call fatal() (e.g., the connection gets closed).
*/
fatal_add_cleanup(session_pty_cleanup, (void *)s);
pty_setowner(s->pw, s->tty);
if (!use_privsep)
pty_setowner(s->pw, s->tty);
/* Set window size from the packet. */
pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
@ -1474,8 +1549,8 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr)
* Function to perform pty cleanup. Also called if we get aborted abnormally
* (e.g., due to a dropped connection).
*/
static void
session_pty_cleanup(void *session)
void
session_pty_cleanup2(void *session)
{
Session *s = session;
@ -1493,7 +1568,8 @@ session_pty_cleanup(void *session)
record_logout(s->pid, s->tty);
/* Release the pseudo-tty. */
pty_release(s->tty);
if (getuid() == 0)
pty_release(s->tty);
/*
* Close the server side of the socket pairs. We must do this after
@ -1501,12 +1577,18 @@ session_pty_cleanup(void *session)
* while we're still cleaning up.
*/
if (close(s->ptymaster) < 0)
error("close(s->ptymaster): %s", strerror(errno));
error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno));
/* unlink pty from session */
s->ttyfd = -1;
}
void
session_pty_cleanup(void *session)
{
PRIVSEP(session_pty_cleanup2(session));
}
static void
session_exit_message(Session *s, int status)
{
@ -1515,8 +1597,8 @@ session_exit_message(Session *s, int status)
if ((c = channel_lookup(s->chanid)) == NULL)
fatal("session_exit_message: session %d: no channel %d",
s->self, s->chanid);
debug("session_exit_message: session %d channel %d pid %d",
s->self, s->chanid, s->pid);
debug("session_exit_message: session %d channel %d pid %ld",
s->self, s->chanid, (long)s->pid);
if (WIFEXITED(status)) {
channel_request_start(s->chanid, "exit-status", 0);
@ -1548,10 +1630,10 @@ session_exit_message(Session *s, int status)
s->chanid = -1;
}
static void
void
session_close(Session *s)
{
debug("session_close: session %d pid %d", s->self, s->pid);
debug("session_close: session %d pid %ld", s->self, (long)s->pid);
if (s->ttyfd != -1) {
fatal_remove_cleanup(session_pty_cleanup, (void *)s);
session_pty_cleanup(s);
@ -1575,7 +1657,8 @@ session_close_by_pid(pid_t pid, int status)
{
Session *s = session_by_pid(pid);
if (s == NULL) {
debug("session_close_by_pid: no session for pid %d", pid);
debug("session_close_by_pid: no session for pid %ld",
(long)pid);
return;
}
if (s->chanid != -1)
@ -1595,7 +1678,8 @@ session_close_by_channel(int id, void *arg)
debug("session_close_by_channel: no session for id %d", id);
return;
}
debug("session_close_by_channel: channel %d child %d", id, s->pid);
debug("session_close_by_channel: channel %d child %ld",
id, (long)s->pid);
if (s->pid != 0) {
debug("session_close_by_channel: channel %d: has child", id);
/*
@ -1615,13 +1699,17 @@ session_close_by_channel(int id, void *arg)
}
void
session_destroy_all(void)
session_destroy_all(void (*closefunc)(Session *))
{
int i;
for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
if (s->used)
session_close(s);
if (s->used) {
if (closefunc != NULL)
closefunc(s);
else
session_close(s);
}
}
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: session.h,v 1.14 2002/02/03 17:53:25 markus Exp $ */
/* $OpenBSD: session.h,v 1.17 2002/03/29 18:59:32 markus Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -26,12 +26,46 @@
#ifndef SESSION_H
#define SESSION_H
#define TTYSZ 64
typedef struct Session Session;
struct Session {
int used;
int self;
struct passwd *pw;
Authctxt *authctxt;
pid_t pid;
/* tty */
char *term;
int ptyfd, ttyfd, ptymaster;
int row, col, xpixel, ypixel;
char tty[TTYSZ];
/* last login */
char hostname[MAXHOSTNAMELEN];
time_t last_login_time;
/* X11 */
int display_number;
char *display;
int screen;
char *auth_display;
char *auth_proto;
char *auth_data;
int single_connection;
/* proto 2 */
int chanid;
int is_subsystem;
};
void do_authenticated(Authctxt *);
int session_open(Authctxt*, int);
int session_input_channel_req(Channel *, const char *);
void session_close_by_pid(pid_t, int);
void session_close_by_channel(int, void *);
void session_destroy_all(void);
void session_destroy_all(void (*)(Session *));
void session_pty_cleanup2(void *);
Session *session_new(void);
Session *session_by_tty(char *);
void session_close(Session *);
void do_setusercontext(struct passwd *);
#endif

View File

@ -28,7 +28,7 @@
/* XXX: copy between two remote sites */
#include "includes.h"
RCSID("$OpenBSD: sftp-client.c,v 1.24 2002/02/24 16:57:19 markus Exp $");
RCSID("$OpenBSD: sftp-client.c,v 1.32 2002/06/09 13:32:01 markus Exp $");
#include <sys/queue.h>
@ -270,7 +270,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
/* Some filexfer v.0 servers don't support large packets */
if (version == 0)
ret->transfer_buflen = MAX(ret->transfer_buflen, 20480);
ret->transfer_buflen = MIN(ret->transfer_buflen, 20480);
return(ret);
}
@ -445,7 +445,7 @@ do_rm(struct sftp_conn *conn, char *path)
debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
id = conn->msg_id++;
send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path,
send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path,
strlen(path));
status = get_status(conn->fd_in, id);
if (status != SSH2_FX_OK)
@ -492,8 +492,8 @@ do_stat(struct sftp_conn *conn, char *path, int quiet)
id = conn->msg_id++;
send_string_request(conn->fd_out, id,
conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
send_string_request(conn->fd_out, id,
conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
path, strlen(path));
return(get_decode_stat(conn->fd_in, id, quiet));
@ -508,8 +508,8 @@ do_lstat(struct sftp_conn *conn, char *path, int quiet)
if (quiet)
debug("Server version does not support lstat operation");
else
error("Server version does not support lstat operation");
return(NULL);
log("Server version does not support lstat operation");
return(do_stat(conn, path, quiet));
}
id = conn->msg_id++;
@ -723,7 +723,7 @@ send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
char *handle, u_int handle_len)
{
Buffer msg;
buffer_init(&msg);
buffer_clear(&msg);
buffer_put_char(&msg, SSH2_FXP_READ);
@ -733,7 +733,7 @@ send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
buffer_put_int(&msg, len);
send_msg(fd_out, &msg);
buffer_free(&msg);
}
}
int
do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
@ -750,7 +750,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
u_int id;
u_int len;
u_int64_t offset;
TAILQ_ENTRY(request) tq;
TAILQ_ENTRY(request) tq;
};
TAILQ_HEAD(reqhead, request) requests;
struct request *req;
@ -816,8 +816,10 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
/* Send some more requests */
while (num_req < max_req) {
debug3("Request range %llu -> %llu (%d/%d)",
offset, offset + buflen - 1, num_req, max_req);
debug3("Request range %llu -> %llu (%d/%d)",
(unsigned long long)offset,
(unsigned long long)offset + buflen - 1,
num_req, max_req);
req = xmalloc(sizeof(*req));
req->id = conn->msg_id++;
req->len = buflen;
@ -825,7 +827,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
offset += buflen;
num_req++;
TAILQ_INSERT_TAIL(&requests, req, tq);
send_read_request(conn->fd_out, req->id, req->offset,
send_read_request(conn->fd_out, req->id, req->offset,
req->len, handle, handle_len);
}
@ -855,8 +857,9 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
break;
case SSH2_FXP_DATA:
data = buffer_get_string(&msg, &len);
debug3("Received data %llu -> %llu", req->offset,
req->offset + len - 1);
debug3("Received data %llu -> %llu",
(unsigned long long)req->offset,
(unsigned long long)req->offset + len - 1);
if (len > req->len)
fatal("Received more data than asked for "
"%d > %d", len, req->len);
@ -876,12 +879,14 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
} else {
/* Resend the request for the missing data */
debug3("Short data block, re-requesting "
"%llu -> %llu (%2d)", req->offset + len,
req->offset + req->len - 1, num_req);
"%llu -> %llu (%2d)",
(unsigned long long)req->offset + len,
(unsigned long long)req->offset +
req->len - 1, num_req);
req->id = conn->msg_id++;
req->len -= len;
req->offset += len;
send_read_request(conn->fd_out, req->id,
send_read_request(conn->fd_out, req->id,
req->offset, req->len, handle, handle_len);
/* Reduce the request size */
if (len < buflen)
@ -892,7 +897,8 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
/* Only one request at a time
* after the expected EOF */
debug3("Finish at %llu (%2d)",
offset, num_req);
(unsigned long long)offset,
num_req);
max_req = 1;
}
else if (max_req < conn->num_requests + 1) {
@ -911,7 +917,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
fatal("Transfer complete, but requests still in queue");
if (read_error) {
error("Couldn't read from remote file \"%s\" : %s",
error("Couldn't read from remote file \"%s\" : %s",
remote_path, fx2txt(status));
do_close(conn, handle, handle_len);
} else if (write_error) {
@ -960,7 +966,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
u_int id;
u_int len;
u_int64_t offset;
TAILQ_ENTRY(outstanding_ack) tq;
TAILQ_ENTRY(outstanding_ack) tq;
};
TAILQ_HEAD(ackhead, outstanding_ack) acks;
struct outstanding_ack *ack;
@ -1042,19 +1048,21 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
buffer_put_string(&msg, data, len);
send_msg(conn->fd_out, &msg);
debug3("Sent message SSH2_FXP_WRITE I:%d O:%llu S:%u",
id, (u_int64_t)offset, len);
id, (unsigned long long)offset, len);
} else if (TAILQ_FIRST(&acks) == NULL)
break;
if (ack == NULL)
fatal("Unexpected ACK %u", id);
if (id == startid || len == 0 ||
if (id == startid || len == 0 ||
id - ackid >= conn->num_requests) {
u_int r_id;
buffer_clear(&msg);
get_msg(conn->fd_in, &msg);
type = buffer_get_char(&msg);
id = buffer_get_int(&msg);
r_id = buffer_get_int(&msg);
if (type != SSH2_FXP_STATUS)
fatal("Expected SSH2_FXP_STATUS(%d) packet, "
@ -1065,11 +1073,11 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
/* Find the request in our queue */
for(ack = TAILQ_FIRST(&acks);
ack != NULL && ack->id != id;
ack != NULL && ack->id != r_id;
ack = TAILQ_NEXT(ack, tq))
;
if (ack == NULL)
fatal("Can't find request for ID %d", id);
fatal("Can't find request for ID %d", r_id);
TAILQ_REMOVE(&acks, ack, tq);
if (status != SSH2_FX_OK) {
@ -1079,8 +1087,8 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
close(local_fd);
goto done;
}
debug3("In write loop, ack for %u %d bytes at %llu",
ack->id, ack->len, ack->offset);
debug3("In write loop, ack for %u %d bytes at %llu",
ack->id, ack->len, (unsigned long long)ack->offset);
++ackid;
free(ack);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sftp-glob.h,v 1.6 2002/02/13 00:59:23 djm Exp $ */
/* $OpenBSD: sftp-glob.h,v 1.7 2002/03/19 10:49:35 markus Exp $ */
/*
* Copyright (c) 2001,2002 Damien Miller. All rights reserved.
@ -32,7 +32,7 @@
#include "sftp-client.h"
int
remote_glob(struct sftp_conn *, const char *, int,
remote_glob(struct sftp_conn *, const char *, int,
int (*)(const char *, int), glob_t *);
#endif

View File

@ -26,7 +26,7 @@
/* XXX: recursive operations */
#include "includes.h"
RCSID("$OpenBSD: sftp-int.c,v 1.44 2002/02/13 00:59:23 djm Exp $");
RCSID("$OpenBSD: sftp-int.c,v 1.46 2002/03/30 18:51:15 markus Exp $");
#include <glob.h>
@ -178,8 +178,9 @@ local_do_shell(const char *args)
strerror(errno));
_exit(1);
}
if (waitpid(pid, &status, 0) == -1)
fatal("Couldn't wait for child: %s", strerror(errno));
while (waitpid(pid, &status, 0) == -1)
if (errno != EINTR)
fatal("Couldn't wait for child: %s", strerror(errno));
if (!WIFEXITED(status))
error("Shell exited abormally");
else if (WEXITSTATUS(status))
@ -888,8 +889,10 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
file2);
parse_dispatch_command(conn, cmd, &pwd);
xfree(dir);
return;
}
xfree(dir);
}
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(infile, NULL, _IOLBF, 0);

View File

@ -22,7 +22,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: sftp-server.c,v 1.33 2002/02/13 00:28:13 markus Exp $");
RCSID("$OpenBSD: sftp-server.c,v 1.35 2002/06/06 17:30:11 markus Exp $");
#include "buffer.h"
#include "bufaux.h"
@ -362,7 +362,7 @@ process_init(void)
{
Buffer msg;
version = buffer_get_int(&iqueue);
version = get_int();
TRACE("client version %d", version);
buffer_init(&msg);
buffer_put_char(&msg, SSH2_FXP_VERSION);
@ -936,10 +936,13 @@ static void
process(void)
{
u_int msg_len;
u_int buf_len;
u_int consumed;
u_int type;
u_char *cp;
if (buffer_len(&iqueue) < 5)
buf_len = buffer_len(&iqueue);
if (buf_len < 5)
return; /* Incomplete message. */
cp = buffer_ptr(&iqueue);
msg_len = GET_32BIT(cp);
@ -947,9 +950,10 @@ process(void)
error("bad message ");
exit(11);
}
if (buffer_len(&iqueue) < msg_len + 4)
if (buf_len < msg_len + 4)
return;
buffer_consume(&iqueue, 4);
buf_len -= 4;
type = buffer_get_char(&iqueue);
switch (type) {
case SSH2_FXP_INIT:
@ -1016,6 +1020,14 @@ process(void)
error("Unknown message %d", type);
break;
}
/* discard the remaining bytes from the current packet */
if (buf_len < buffer_len(&iqueue))
fatal("iqueue grows");
consumed = buf_len - buffer_len(&iqueue);
if (msg_len < consumed)
fatal("msg_len %d < consumed %d", msg_len, consumed);
if (msg_len > consumed)
buffer_consume(&iqueue, msg_len - consumed);
}
int

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: sftp.1,v 1.33 2002/02/26 19:06:43 deraadt Exp $
.\" $OpenBSD: sftp.1,v 1.35 2002/06/20 20:00:05 stevesk Exp $
.\"
.\" Copyright (c) 2001 Damien Miller. All rights reserved.
.\"
@ -83,9 +83,9 @@ and
.It Fl o Ar ssh_option
Can be used to pass options to
.Nm ssh
in the format used in the
.Xr ssh 1
configuration file. This is useful for specifying options
in the format used in
.Xr ssh_config 5 .
This is useful for specifying options
for which there is no separate
.Nm sftp
command-line flag. For example, to specify an alternate
@ -100,7 +100,7 @@ does not have an sftp subsystem configured.
.It Fl v
Raise logging level. This option is also passed to ssh.
.It Fl B Ar buffer_size
Specify the size of the buffer that
Specify the size of the buffer that
.Nm
uses when transferring files. Larger buffers require fewer round trips at
the cost of higher memory consumption. The default is 32768 bytes.
@ -115,13 +115,13 @@ per-user configuration file for
This option is directly passed to
.Xr ssh 1 .
.It Fl P Ar sftp_server path
Connect directly to a local
.Nm sftp-server
Connect directly to a local
.Nm sftp-server
(rather than via
.Nm ssh )
This option may be useful in debugging the client and server.
.It Fl R Ar num_requests
Specify how many requests may be outstanding at any one time. Increasing
Specify how many requests may be outstanding at any one time. Increasing
this may slightly improve file transfer speed but will increase memory
usage. The default is 16 outstanding requests.
.It Fl S Ar program
@ -263,6 +263,7 @@ Damien Miller <djm@mindrot.org>
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-keygen 1 ,
.Xr ssh_config 5 ,
.Xr sftp-server 8 ,
.Xr sshd 8
.Rs

View File

@ -24,7 +24,7 @@
#include "includes.h"
RCSID("$OpenBSD: sftp.c,v 1.26 2002/02/12 12:32:27 djm Exp $");
RCSID("$OpenBSD: sftp.c,v 1.29 2002/04/02 17:37:48 markus Exp $");
/* XXX: short-form remote directory listings (like 'ls -C') */
@ -88,7 +88,7 @@ static void
usage(void)
{
extern char *__progname;
fprintf(stderr,
"usage: %s [-vC1] [-b batchfile] [-o option] [-s subsystem|path] [-B buffer_size]\n"
" [-F config] [-P direct server path] [-S program]\n"
@ -165,7 +165,7 @@ main(int argc, char **argv)
case 'R':
num_requests = strtol(optarg, &cp, 10);
if (num_requests == 0 || *cp != '\0')
fatal("Invalid number of requests \"%s\"",
fatal("Invalid number of requests \"%s\"",
optarg);
break;
case 'h':
@ -174,6 +174,8 @@ main(int argc, char **argv)
}
}
log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1);
if (sftp_direct == NULL) {
if (optind == argc || argc > (optind + 2))
usage();
@ -203,7 +205,6 @@ main(int argc, char **argv)
usage();
}
log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1);
addargs(&args, "-oProtocol %d", sshver);
/* no subsystem if the server-spec contains a '/' */
@ -211,19 +212,19 @@ main(int argc, char **argv)
addargs(&args, "-s");
addargs(&args, "%s", host);
addargs(&args, "%s", (sftp_server != NULL ?
addargs(&args, "%s", (sftp_server != NULL ?
sftp_server : "sftp"));
args.list[0] = ssh_program;
fprintf(stderr, "Connecting to %s...\n", host);
connect_to_server(ssh_program, args.list, &in, &out,
connect_to_server(ssh_program, args.list, &in, &out,
&sshpid);
} else {
args.list = NULL;
addargs(&args, "sftp-server");
fprintf(stderr, "Attaching to %s...\n", sftp_direct);
connect_to_server(sftp_direct, args.list, &in, &out,
connect_to_server(sftp_direct, args.list, &in, &out,
&sshpid);
}
@ -234,8 +235,10 @@ main(int argc, char **argv)
if (infile != stdin)
fclose(infile);
if (waitpid(sshpid, NULL, 0) == -1)
fatal("Couldn't wait for ssh process: %s", strerror(errno));
while (waitpid(sshpid, NULL, 0) == -1)
if (errno != EINTR)
fatal("Couldn't wait for ssh process: %s",
strerror(errno));
exit(0);
}

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-add.1,v 1.30 2002/02/04 20:41:16 stevesk Exp $
.\" $OpenBSD: ssh-add.1,v 1.35 2002/06/19 00:27:55 deraadt Exp $
.\"
.\" -*- nroff -*-
.\"
@ -45,7 +45,8 @@
.Nd adds RSA or DSA identities to the authentication agent
.Sh SYNOPSIS
.Nm ssh-add
.Op Fl lLdD
.Op Fl lLdDxX
.Op Fl t Ar life
.Op Ar
.Nm ssh-add
.Fl s Ar reader
@ -57,7 +58,7 @@ adds RSA or DSA identities to the authentication agent,
.Xr ssh-agent 1 .
When run without arguments, it adds the files
.Pa $HOME/.ssh/id_rsa ,
.Pa $HOME/.ssh/id_dsa
.Pa $HOME/.ssh/id_dsa
and
.Pa $HOME/.ssh/identity .
Alternative file names can be given on the command line.
@ -83,6 +84,15 @@ Lists public key parameters of all identities currently represented by the agent
Instead of adding the identity, removes the identity from the agent.
.It Fl D
Deletes all identities from the agent.
.It Fl x
Lock the agent with a password.
.It Fl X
Unlock the agent.
.It Fl t Ar life
Set a maximum lifetime when adding identities to an agent.
The lifetime may be specified in seconds or in a time format
specified in
.Xr sshd 8 .
.It Fl s Ar reader
Add key in smartcard
.Ar reader .
@ -129,6 +139,9 @@ or related script.
may be necessary to redirect the input from
.Pa /dev/null
to make this work.)
.It Ev SSH_AUTH_SOCK
Identifies the path of a unix-domain socket used to communicate with the
agent.
.El
.Sh DIAGNOSTICS
Exit status is 0 on success, 1 if the specified command fails,

View File

@ -35,7 +35,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: ssh-add.c,v 1.50 2002/01/29 14:27:57 markus Exp $");
RCSID("$OpenBSD: ssh-add.c,v 1.61 2002/06/19 00:27:55 deraadt Exp $");
#include <openssl/evp.h>
@ -48,6 +48,7 @@ RCSID("$OpenBSD: ssh-add.c,v 1.50 2002/01/29 14:27:57 markus Exp $");
#include "authfile.h"
#include "pathnames.h"
#include "readpass.h"
#include "misc.h"
/* argv0 */
extern char *__progname;
@ -56,10 +57,12 @@ extern char *__progname;
static char *default_files[] = {
_PATH_SSH_CLIENT_ID_RSA,
_PATH_SSH_CLIENT_ID_DSA,
_PATH_SSH_CLIENT_IDENTITY,
_PATH_SSH_CLIENT_IDENTITY,
NULL
};
/* Default lifetime (0 == forever) */
static int lifetime = 0;
/* we keep a cache of one passphrases */
static char *pass = NULL;
@ -155,11 +158,19 @@ add_file(AuthenticationConnection *ac, const char *filename)
strlcpy(msg, "Bad passphrase, try again: ", sizeof msg);
}
}
if (ssh_add_identity(ac, private, comment)) {
if (ssh_add_identity_constrained(ac, private, comment, lifetime)) {
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
ret = 0;
} else
if (lifetime != 0)
fprintf(stderr,
"Lifetime set to %d seconds\n", lifetime);
} else if (ssh_add_identity(ac, private, comment)) {
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
ret = 0;
} else {
fprintf(stderr, "Could not add identity: %s\n", filename);
}
xfree(comment);
key_free(private);
@ -170,7 +181,13 @@ add_file(AuthenticationConnection *ac, const char *filename)
static int
update_card(AuthenticationConnection *ac, int add, const char *id)
{
if (ssh_update_card(ac, add, id)) {
char *pin;
pin = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN);
if (pin == NULL)
return -1;
if (ssh_update_card(ac, add, id, pin)) {
fprintf(stderr, "Card %s: %s\n",
add ? "added" : "removed", id);
return 0;
@ -216,6 +233,34 @@ list_identities(AuthenticationConnection *ac, int do_fp)
return 0;
}
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)
{
@ -238,6 +283,9 @@ usage(void)
fprintf(stderr, " -L List public key parameters of all identities.\n");
fprintf(stderr, " -d Delete identity.\n");
fprintf(stderr, " -D Delete all identities.\n");
fprintf(stderr, " -x Lock agent.\n");
fprintf(stderr, " -x Unlock agent.\n");
fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n");
#ifdef SMARTCARD
fprintf(stderr, " -s reader Add key in smartcard reader.\n");
fprintf(stderr, " -e reader Remove key in smartcard reader.\n");
@ -261,7 +309,7 @@ main(int argc, char **argv)
fprintf(stderr, "Could not open a connection to your authentication agent.\n");
exit(2);
}
while ((ch = getopt(argc, argv, "lLdDe:s:")) != -1) {
while ((ch = getopt(argc, argv, "lLdDxXe:s:t:")) != -1) {
switch (ch) {
case 'l':
case 'L':
@ -269,6 +317,12 @@ main(int argc, char **argv)
ret = 1;
goto done;
break;
case 'x':
case 'X':
if (lock_agent(ac, ch == 'x' ? 1 : 0) == -1)
ret = 1;
goto done;
break;
case 'd':
deleting = 1;
break;
@ -284,6 +338,13 @@ main(int argc, char **argv)
deleting = 1;
sc_reader_id = optarg;
break;
case 't':
if ((lifetime = convtime(optarg)) == -1) {
fprintf(stderr, "Invalid lifetime\n");
ret = 1;
goto done;
}
break;
default:
usage();
ret = 1;
@ -300,6 +361,8 @@ main(int argc, char **argv)
if (argc == 0) {
char buf[MAXPATHLEN];
struct passwd *pw;
struct stat st;
int count = 0;
if ((pw = getpwuid(getuid())) == NULL) {
fprintf(stderr, "No user found with uid %u\n",
@ -309,11 +372,17 @@ main(int argc, char **argv)
}
for(i = 0; default_files[i]; i++) {
snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,
snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,
default_files[i]);
if (stat(buf, &st) < 0)
continue;
if (do_file(ac, deleting, buf) == -1)
ret = 1;
else
count++;
}
if (count == 0)
ret = 1;
} else {
for(i = 0; i < argc; i++) {
if (do_file(ac, deleting, argv[i]) == -1)

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-agent.1,v 1.31 2002/02/04 20:41:16 stevesk Exp $
.\" $OpenBSD: ssh-agent.1,v 1.33 2002/06/19 00:27:55 deraadt Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -42,6 +42,7 @@
.Nd authentication agent
.Sh SYNOPSIS
.Nm ssh-agent
.Op Fl a Ar bind_address
.Op Fl c Li | Fl s
.Op Fl d
.Op Ar command Op Ar args ...
@ -64,6 +65,11 @@ machines using
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl a Ar bind_address
Bind the agent to the unix-domain socket
.Ar bind_address .
The default is
.Pa /tmp/ssh-XXXXXXXX/agent.<pid> .
.It Fl c
Generate C-shell commands on
.Dv stdout .
@ -96,7 +102,7 @@ When executed without arguments,
.Xr ssh-add 1
adds the files
.Pa $HOME/.ssh/id_rsa ,
.Pa $HOME/.ssh/id_dsa
.Pa $HOME/.ssh/id_dsa
and
.Pa $HOME/.ssh/identity .
If the identity has a passphrase,
@ -135,7 +141,6 @@ by the agent, and the result will be returned to the requester.
This way, private keys are not exposed to clients using the agent.
.Pp
A unix-domain socket is created
.Pq Pa /tmp/ssh-XXXXXXXX/agent.<pid> ,
and the name of this socket is stored in the
.Ev SSH_AUTH_SOCK
environment

View File

@ -35,7 +35,7 @@
#include "includes.h"
#include <sys/queue.h>
RCSID("$OpenBSD: ssh-agent.c,v 1.82 2002/03/04 17:27:39 stevesk Exp $");
RCSID("$OpenBSD: ssh-agent.c,v 1.95 2002/06/19 00:27:55 deraadt Exp $");
#include <openssl/evp.h>
#include <openssl/md5.h>
@ -52,7 +52,6 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.82 2002/03/04 17:27:39 stevesk Exp $");
#include "log.h"
#ifdef SMARTCARD
#include <openssl/engine.h>
#include "scard.h"
#endif
@ -67,6 +66,7 @@ typedef struct {
sock_type type;
Buffer input;
Buffer output;
Buffer request;
} SocketEntry;
u_int sockets_alloc = 0;
@ -76,6 +76,7 @@ typedef struct identity {
TAILQ_ENTRY(identity) next;
Key *key;
char *comment;
u_int death;
} Identity;
typedef struct {
@ -95,6 +96,10 @@ pid_t parent_pid = -1;
char socket_name[1024];
char socket_dir[1024];
/* locking */
int locked = 0;
char *lock_passwd = NULL;
extern char *__progname;
static void
@ -116,6 +121,14 @@ idtab_lookup(int version)
return &idtable[version];
}
static void
free_identity(Identity *id)
{
key_free(id->key);
xfree(id->comment);
xfree(id);
}
/* return matching private key for given public key */
static Identity *
lookup_identity(Key *key, int version)
@ -130,14 +143,6 @@ lookup_identity(Key *key, int version)
return (NULL);
}
static void
free_identity(Identity *id)
{
key_free(id->key);
xfree(id->comment);
xfree(id);
}
/* send list of supported public keys to 'client' */
static void
process_request_identities(SocketEntry *e, int version)
@ -187,16 +192,16 @@ process_authentication_challenge1(SocketEntry *e)
if ((challenge = BN_new()) == NULL)
fatal("process_authentication_challenge1: BN_new failed");
buffer_get_int(&e->input); /* ignored */
buffer_get_bignum(&e->input, key->rsa->e);
buffer_get_bignum(&e->input, key->rsa->n);
buffer_get_bignum(&e->input, challenge);
buffer_get_int(&e->request); /* ignored */
buffer_get_bignum(&e->request, key->rsa->e);
buffer_get_bignum(&e->request, key->rsa->n);
buffer_get_bignum(&e->request, challenge);
/* Only protocol 1.1 is supported */
if (buffer_len(&e->input) == 0)
if (buffer_len(&e->request) == 0)
goto failure;
buffer_get(&e->input, session_id, 16);
response_type = buffer_get_int(&e->input);
buffer_get(&e->request, session_id, 16);
response_type = buffer_get_int(&e->request);
if (response_type != 1)
goto failure;
@ -252,10 +257,10 @@ process_sign_request2(SocketEntry *e)
datafellows = 0;
blob = buffer_get_string(&e->input, &blen);
data = buffer_get_string(&e->input, &dlen);
blob = buffer_get_string(&e->request, &blen);
data = buffer_get_string(&e->request, &dlen);
flags = buffer_get_int(&e->input);
flags = buffer_get_int(&e->request);
if (flags & SSH_AGENT_OLD_SIGNATURE)
datafellows = SSH_BUG_SIGBLOB;
@ -296,16 +301,16 @@ process_remove_identity(SocketEntry *e, int version)
switch (version) {
case 1:
key = key_new(KEY_RSA1);
bits = buffer_get_int(&e->input);
buffer_get_bignum(&e->input, key->rsa->e);
buffer_get_bignum(&e->input, key->rsa->n);
bits = buffer_get_int(&e->request);
buffer_get_bignum(&e->request, key->rsa->e);
buffer_get_bignum(&e->request, key->rsa->n);
if (bits != key_size(key))
log("Warning: identity keysize mismatch: actual %d, announced %d",
key_size(key), bits);
break;
case 2:
blob = buffer_get_string(&e->input, &blen);
blob = buffer_get_string(&e->request, &blen);
key = key_from_blob(blob, blen);
xfree(blob);
break;
@ -356,7 +361,27 @@ process_remove_all_identities(SocketEntry *e, int version)
/* Send success. */
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
return;
}
static void
reaper(void)
{
Idtab *tab;
Identity *id, *nxt;
int version;
u_int now = time(NULL);
for (version = 1; version < 3; version++) {
tab = idtab_lookup(version);
for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
nxt = TAILQ_NEXT(id, next);
if (id->death != 0 && now >= id->death) {
TAILQ_REMOVE(&tab->idlist, id, next);
free_identity(id);
tab->nentries--;
}
}
}
}
static void
@ -365,66 +390,76 @@ process_add_identity(SocketEntry *e, int version)
Key *k = NULL;
char *type_name;
char *comment;
int type, success = 0;
int type, success = 0, death = 0;
Idtab *tab = idtab_lookup(version);
switch (version) {
case 1:
k = key_new_private(KEY_RSA1);
buffer_get_int(&e->input); /* ignored */
buffer_get_bignum(&e->input, k->rsa->n);
buffer_get_bignum(&e->input, k->rsa->e);
buffer_get_bignum(&e->input, k->rsa->d);
buffer_get_bignum(&e->input, k->rsa->iqmp);
buffer_get_int(&e->request); /* ignored */
buffer_get_bignum(&e->request, k->rsa->n);
buffer_get_bignum(&e->request, k->rsa->e);
buffer_get_bignum(&e->request, k->rsa->d);
buffer_get_bignum(&e->request, k->rsa->iqmp);
/* SSH and SSL have p and q swapped */
buffer_get_bignum(&e->input, k->rsa->q); /* p */
buffer_get_bignum(&e->input, k->rsa->p); /* q */
buffer_get_bignum(&e->request, k->rsa->q); /* p */
buffer_get_bignum(&e->request, k->rsa->p); /* q */
/* Generate additional parameters */
rsa_generate_additional_parameters(k->rsa);
break;
case 2:
type_name = buffer_get_string(&e->input, NULL);
type_name = buffer_get_string(&e->request, NULL);
type = key_type_from_name(type_name);
xfree(type_name);
switch (type) {
case KEY_DSA:
k = key_new_private(type);
buffer_get_bignum2(&e->input, k->dsa->p);
buffer_get_bignum2(&e->input, k->dsa->q);
buffer_get_bignum2(&e->input, k->dsa->g);
buffer_get_bignum2(&e->input, k->dsa->pub_key);
buffer_get_bignum2(&e->input, k->dsa->priv_key);
buffer_get_bignum2(&e->request, k->dsa->p);
buffer_get_bignum2(&e->request, k->dsa->q);
buffer_get_bignum2(&e->request, k->dsa->g);
buffer_get_bignum2(&e->request, k->dsa->pub_key);
buffer_get_bignum2(&e->request, k->dsa->priv_key);
break;
case KEY_RSA:
k = key_new_private(type);
buffer_get_bignum2(&e->input, k->rsa->n);
buffer_get_bignum2(&e->input, k->rsa->e);
buffer_get_bignum2(&e->input, k->rsa->d);
buffer_get_bignum2(&e->input, k->rsa->iqmp);
buffer_get_bignum2(&e->input, k->rsa->p);
buffer_get_bignum2(&e->input, k->rsa->q);
buffer_get_bignum2(&e->request, k->rsa->n);
buffer_get_bignum2(&e->request, k->rsa->e);
buffer_get_bignum2(&e->request, k->rsa->d);
buffer_get_bignum2(&e->request, k->rsa->iqmp);
buffer_get_bignum2(&e->request, k->rsa->p);
buffer_get_bignum2(&e->request, k->rsa->q);
/* Generate additional parameters */
rsa_generate_additional_parameters(k->rsa);
break;
default:
buffer_clear(&e->input);
buffer_clear(&e->request);
goto send;
}
break;
}
comment = buffer_get_string(&e->input, NULL);
comment = buffer_get_string(&e->request, NULL);
if (k == NULL) {
xfree(comment);
goto send;
}
success = 1;
while (buffer_len(&e->request)) {
switch (buffer_get_char(&e->request)) {
case SSH_AGENT_CONSTRAIN_LIFETIME:
death = time(NULL) + buffer_get_int(&e->request);
break;
default:
break;
}
}
if (lookup_identity(k, version) == NULL) {
Identity *id = xmalloc(sizeof(Identity));
id->key = k;
id->comment = comment;
id->death = death;
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
/* Increment the number of identities. */
tab->nentries++;
@ -438,53 +473,86 @@ process_add_identity(SocketEntry *e, int version)
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++;
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;
}
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++;
}
key_free(k);
xfree(keys);
send:
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output,
@ -494,39 +562,37 @@ process_add_smartcard_key (SocketEntry *e)
static void
process_remove_smartcard_key(SocketEntry *e)
{
Key *k = NULL;
int success = 0;
char *sc_reader_id = NULL;
Identity *id;
Idtab *tab;
Key **keys, *k = NULL;
char *sc_reader_id = NULL, *pin;
int i, version, success = 0;
sc_reader_id = buffer_get_string(&e->input, NULL);
k = sc_get_key(sc_reader_id);
sc_reader_id = buffer_get_string(&e->request, NULL);
pin = buffer_get_string(&e->request, NULL);
keys = sc_get_keys(sc_reader_id, pin);
xfree(sc_reader_id);
xfree(pin);
if (k == NULL) {
error("sc_get_pubkey failed");
} else {
Identity *id;
k->type = KEY_RSA1;
id = lookup_identity(k, 1);
if (id != NULL) {
Idtab *tab = idtab_lookup(1);
if (keys == NULL || keys[0] == NULL) {
error("sc_get_keys failed");
goto send;
}
for (i = 0; keys[i] != NULL; i++) {
k = keys[i];
version = k->type == KEY_RSA1 ? 1 : 2;
if ((id = lookup_identity(k, version)) != NULL) {
tab = idtab_lookup(version);
TAILQ_REMOVE(&tab->idlist, id, next);
free_identity(id);
tab->nentries--;
success = 1;
}
k->type = KEY_RSA;
id = lookup_identity(k, 2);
if (id != NULL) {
Idtab *tab = idtab_lookup(2);
TAILQ_REMOVE(&tab->idlist, id, next);
free_identity(id);
tab->nentries--;
success = 1;
}
key_free(k);
keys[i] = NULL;
}
xfree(keys);
send:
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output,
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
@ -541,6 +607,10 @@ process_message(SocketEntry *e)
u_int msg_len;
u_int type;
u_char *cp;
/* kill dead keys */
reaper();
if (buffer_len(&e->input) < 5)
return; /* Incomplete message. */
cp = buffer_ptr(&e->input);
@ -549,15 +619,44 @@ process_message(SocketEntry *e)
shutdown(e->fd, SHUT_RDWR);
close(e->fd);
e->type = AUTH_UNUSED;
buffer_free(&e->input);
buffer_free(&e->output);
buffer_free(&e->request);
return;
}
if (buffer_len(&e->input) < msg_len + 4)
return;
/* move the current input to e->request */
buffer_consume(&e->input, 4);
type = buffer_get_char(&e->input);
buffer_clear(&e->request);
buffer_append(&e->request, buffer_ptr(&e->input), msg_len);
buffer_consume(&e->input, msg_len);
type = buffer_get_char(&e->request);
/* check wheter agent is locked */
if (locked && type != SSH_AGENTC_UNLOCK) {
buffer_clear(&e->request);
switch (type) {
case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
case SSH2_AGENTC_REQUEST_IDENTITIES:
/* send empty lists */
no_identities(e, type);
break;
default:
/* send a fail message for all other request types */
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_FAILURE);
}
return;
}
debug("type %d", type);
switch (type) {
case SSH_AGENTC_LOCK:
case SSH_AGENTC_UNLOCK:
process_lock_agent(e, type == SSH_AGENTC_LOCK);
break;
/* ssh1 */
case SSH_AGENTC_RSA_CHALLENGE:
process_authentication_challenge1(e);
@ -566,6 +665,7 @@ process_message(SocketEntry *e)
process_request_identities(e, 1);
break;
case SSH_AGENTC_ADD_RSA_IDENTITY:
case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED:
process_add_identity(e, 1);
break;
case SSH_AGENTC_REMOVE_RSA_IDENTITY:
@ -582,6 +682,7 @@ process_message(SocketEntry *e)
process_request_identities(e, 2);
break;
case SSH2_AGENTC_ADD_IDENTITY:
case SSH2_AGENTC_ADD_ID_CONSTRAINED:
process_add_identity(e, 2);
break;
case SSH2_AGENTC_REMOVE_IDENTITY:
@ -601,7 +702,7 @@ process_message(SocketEntry *e)
default:
/* Unknown message. Respond with failure. */
error("Unknown message %d", type);
buffer_clear(&e->input);
buffer_clear(&e->request);
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_FAILURE);
break;
@ -624,6 +725,7 @@ new_socket(sock_type type, int fd)
sockets[i].type = type;
buffer_init(&sockets[i].input);
buffer_init(&sockets[i].output);
buffer_init(&sockets[i].request);
return;
}
old_alloc = sockets_alloc;
@ -638,6 +740,7 @@ new_socket(sock_type type, int fd)
sockets[old_alloc].fd = fd;
buffer_init(&sockets[old_alloc].input);
buffer_init(&sockets[old_alloc].output);
buffer_init(&sockets[old_alloc].request);
}
static int
@ -735,6 +838,7 @@ after_select(fd_set *readset, fd_set *writeset)
sockets[i].type = AUTH_UNUSED;
buffer_free(&sockets[i].input);
buffer_free(&sockets[i].output);
buffer_free(&sockets[i].request);
break;
}
buffer_consume(&sockets[i].output, len);
@ -753,6 +857,7 @@ after_select(fd_set *readset, fd_set *writeset)
sockets[i].type = AUTH_UNUSED;
buffer_free(&sockets[i].input);
buffer_free(&sockets[i].output);
buffer_free(&sockets[i].request);
break;
}
buffer_append(&sockets[i].input, buf, len);
@ -811,6 +916,7 @@ usage(void)
fprintf(stderr, " -s Generate Bourne shell commands on stdout.\n");
fprintf(stderr, " -k Kill the current agent.\n");
fprintf(stderr, " -d Debug mode.\n");
fprintf(stderr, " -a socket Bind agent socket to given name.\n");
exit(1);
}
@ -822,12 +928,13 @@ main(int ac, char **av)
struct rlimit rlim;
pid_t pid;
char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
char *agentsocket = NULL;
extern int optind;
fd_set *readsetp = NULL, *writesetp = NULL;
SSLeay_add_all_algorithms();
while ((ch = getopt(ac, av, "cdks")) != -1) {
while ((ch = getopt(ac, av, "cdksa:")) != -1) {
switch (ch) {
case 'c':
if (s_flag)
@ -847,6 +954,9 @@ main(int ac, char **av)
usage();
d_flag++;
break;
case 'a':
agentsocket = optarg;
break;
default:
usage();
}
@ -857,7 +967,7 @@ main(int ac, char **av)
if (ac > 0 && (c_flag || k_flag || s_flag || d_flag))
usage();
if (ac == 0 && !c_flag && !k_flag && !s_flag && !d_flag) {
if (ac == 0 && !c_flag && !s_flag) {
shell = getenv("SHELL");
if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
c_flag = 1;
@ -882,19 +992,25 @@ main(int ac, char **av)
format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME);
printf(format, SSH_AGENTPID_ENV_NAME);
printf("echo Agent pid %d killed;\n", pid);
printf("echo Agent pid %ld killed;\n", (long)pid);
exit(0);
}
parent_pid = getpid();
/* Create private directory for agent socket */
strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir);
if (mkdtemp(socket_dir) == NULL) {
perror("mkdtemp: private socket dir");
exit(1);
if (agentsocket == NULL) {
/* Create private directory for agent socket */
strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir);
if (mkdtemp(socket_dir) == NULL) {
perror("mkdtemp: private socket dir");
exit(1);
}
snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir,
(long)parent_pid);
} else {
/* Try to use specified agent socket */
socket_dir[0] = '\0';
strlcpy(socket_name, agentsocket, sizeof socket_name);
}
snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir,
parent_pid);
/*
* Create socket early so it will exist before command gets run from
@ -926,7 +1042,7 @@ main(int ac, char **av)
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
printf("echo Agent pid %d;\n", parent_pid);
printf("echo Agent pid %ld;\n", (long)parent_pid);
goto skip;
}
pid = fork();
@ -936,14 +1052,14 @@ main(int ac, char **av)
}
if (pid != 0) { /* Parent - execute the given command. */
close(sock);
snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid);
snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid);
if (ac == 0) {
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
SSH_AGENTPID_ENV_NAME);
printf("echo Agent pid %d;\n", pid);
printf("echo Agent pid %ld;\n", (long)pid);
exit(0);
}
if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-keygen.1,v 1.53 2002/02/16 14:53:37 stevesk Exp $
.\" $OpenBSD: ssh-keygen.1,v 1.54 2002/06/19 00:27:55 deraadt Exp $
.\"
.\" -*- nroff -*-
.\"
@ -86,7 +86,7 @@
generates, manages and converts authentication keys for
.Xr ssh 1 .
.Nm
can create RSA keys for use by SSH protocol version 1 and RSA or DSA
can create RSA keys for use by SSH protocol version 1 and RSA or DSA
keys for use by SSH protocol version 2. The type of key to be generated
is specified with the
.Fl t

View File

@ -12,7 +12,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: ssh-keygen.c,v 1.94 2002/02/25 16:33:27 markus Exp $");
RCSID("$OpenBSD: ssh-keygen.c,v 1.100 2002/06/19 00:27:55 deraadt Exp $");
#include <openssl/evp.h>
#include <openssl/pem.h>
@ -29,8 +29,6 @@ RCSID("$OpenBSD: ssh-keygen.c,v 1.94 2002/02/25 16:33:27 markus Exp $");
#include "readpass.h"
#ifdef SMARTCARD
#include <sectok.h>
#include <openssl/engine.h>
#include "scard.h"
#endif
@ -138,7 +136,7 @@ load_identity(char *filename)
}
#define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----"
#define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----"
#define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----"
#define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
#define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb
@ -288,6 +286,7 @@ do_convert_from_ssh2(struct passwd *pw)
{
Key *k;
int blen;
u_int len;
char line[1024], *p;
u_char blob[8096];
char encoded[8096];
@ -332,6 +331,12 @@ do_convert_from_ssh2(struct passwd *pw)
*p = '\0';
strlcat(encoded, line, sizeof(encoded));
}
len = strlen(encoded);
if (((len % 4) == 3) &&
(encoded[len-1] == '=') &&
(encoded[len-2] == '=') &&
(encoded[len-3] == '='))
encoded[len-3] = '\0';
blen = uudecode(encoded, blob, sizeof(blob));
if (blen < 0) {
fprintf(stderr, "uudecode failed.\n");
@ -385,145 +390,47 @@ do_print_public(struct passwd *pw)
}
#ifdef SMARTCARD
#define NUM_RSA_KEY_ELEMENTS 5+1
#define COPY_RSA_KEY(x, i) \
do { \
len = BN_num_bytes(prv->rsa->x); \
elements[i] = xmalloc(len); \
debug("#bytes %d", len); \
if (BN_bn2bin(prv->rsa->x, elements[i]) < 0) \
goto done; \
} while (0)
static int
get_AUT0(char *aut0)
{
EVP_MD *evp_md = EVP_sha1();
EVP_MD_CTX md;
char *pass;
pass = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN);
if (pass == NULL)
return -1;
EVP_DigestInit(&md, evp_md);
EVP_DigestUpdate(&md, pass, strlen(pass));
EVP_DigestFinal(&md, aut0, NULL);
memset(pass, 0, strlen(pass));
xfree(pass);
return 0;
}
static void
do_upload(struct passwd *pw, const char *sc_reader_id)
{
Key *prv = NULL;
struct stat st;
u_char *elements[NUM_RSA_KEY_ELEMENTS];
u_char key_fid[2];
u_char DEFAUT0[] = {0xad, 0x9f, 0x61, 0xfe, 0xfa, 0x20, 0xce, 0x63};
u_char AUT0[EVP_MAX_MD_SIZE];
int len, status = 1, i, fd = -1, ret;
int sw = 0, cla = 0x00;
int ret;
for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
elements[i] = NULL;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0) {
perror(identity_file);
goto done;
exit(1);
}
prv = load_identity(identity_file);
if (prv == NULL) {
error("load failed");
goto done;
exit(1);
}
COPY_RSA_KEY(q, 0);
COPY_RSA_KEY(p, 1);
COPY_RSA_KEY(iqmp, 2);
COPY_RSA_KEY(dmq1, 3);
COPY_RSA_KEY(dmp1, 4);
COPY_RSA_KEY(n, 5);
len = BN_num_bytes(prv->rsa->n);
fd = sectok_friendly_open(sc_reader_id, STONOWAIT, &sw);
if (fd < 0) {
error("sectok_open failed: %s", sectok_get_sw(sw));
goto done;
}
if (! sectok_cardpresent(fd)) {
error("smartcard in reader %s not present",
sc_reader_id);
goto done;
}
ret = sectok_reset(fd, 0, NULL, &sw);
if (ret <= 0) {
error("sectok_reset failed: %s", sectok_get_sw(sw));
goto done;
}
if ((cla = cyberflex_inq_class(fd)) < 0) {
error("cyberflex_inq_class failed");
goto done;
}
memcpy(AUT0, DEFAUT0, sizeof(DEFAUT0));
if (cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) {
if (get_AUT0(AUT0) < 0 ||
cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) {
error("cyberflex_verify_AUT0 failed");
goto done;
}
}
key_fid[0] = 0x00;
key_fid[1] = 0x12;
if (cyberflex_load_rsa_priv(fd, cla, key_fid, 5, 8*len, elements,
&sw) < 0) {
error("cyberflex_load_rsa_priv failed: %s", sectok_get_sw(sw));
goto done;
}
if (!sectok_swOK(sw))
goto done;
log("cyberflex_load_rsa_priv done");
key_fid[0] = 0x73;
key_fid[1] = 0x68;
if (cyberflex_load_rsa_pub(fd, cla, key_fid, len, elements[5],
&sw) < 0) {
error("cyberflex_load_rsa_pub failed: %s", sectok_get_sw(sw));
goto done;
}
if (!sectok_swOK(sw))
goto done;
log("cyberflex_load_rsa_pub done");
status = 0;
ret = sc_put_key(prv, sc_reader_id);
key_free(prv);
if (ret < 0)
exit(1);
log("loading key done");
done:
memset(elements[0], '\0', BN_num_bytes(prv->rsa->q));
memset(elements[1], '\0', BN_num_bytes(prv->rsa->p));
memset(elements[2], '\0', BN_num_bytes(prv->rsa->iqmp));
memset(elements[3], '\0', BN_num_bytes(prv->rsa->dmq1));
memset(elements[4], '\0', BN_num_bytes(prv->rsa->dmp1));
memset(elements[5], '\0', BN_num_bytes(prv->rsa->n));
if (prv)
key_free(prv);
for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
if (elements[i])
xfree(elements[i]);
if (fd != -1)
sectok_close(fd);
exit(status);
exit(0);
}
static void
do_download(struct passwd *pw, const char *sc_reader_id)
{
Key *pub = NULL;
Key **keys = NULL;
int i;
pub = sc_get_key(sc_reader_id);
if (pub == NULL)
keys = sc_get_keys(sc_reader_id, NULL);
if (keys == NULL)
fatal("cannot read public key from smartcard");
key_write(pub, stdout);
key_free(pub);
fprintf(stdout, "\n");
for (i = 0; keys[i]; i++) {
key_write(keys[i], stdout);
key_free(keys[i]);
fprintf(stdout, "\n");
}
xfree(keys);
exit(0);
}
#endif /* SMARTCARD */

View File

@ -7,7 +7,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: ssh-keyscan.c,v 1.35 2002/03/04 18:30:23 stevesk Exp $");
RCSID("$OpenBSD: ssh-keyscan.c,v 1.36 2002/06/16 21:30:58 itojun Exp $");
#include <sys/queue.h>
#include <errno.h>
@ -581,7 +581,7 @@ conloop(void)
con *c;
gettimeofday(&now, NULL);
c = tq.tqh_first;
c = TAILQ_FIRST(&tq);
if (c && (c->c_tv.tv_sec > now.tv_sec ||
(c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec > now.tv_usec))) {
@ -614,12 +614,12 @@ conloop(void)
xfree(r);
xfree(e);
c = tq.tqh_first;
c = TAILQ_FIRST(&tq);
while (c && (c->c_tv.tv_sec < now.tv_sec ||
(c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec < now.tv_usec))) {
int s = c->c_fd;
c = c->c_link.tqe_next;
c = TAILQ_NEXT(c, c_link);
conrecycle(s);
}
}

View File

@ -0,0 +1,67 @@
.\" $OpenBSD: ssh-keysign.8,v 1.2 2002/06/10 16:56:30 stevesk Exp $
.\"
.\" Copyright (c) 2002 Markus Friedl. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd May 24, 2002
.Dt SSH-KEYSIGN 8
.Os
.Sh NAME
.Nm ssh-keysign
.Nd ssh helper program for hostbased authentication
.Sh SYNOPSIS
.Nm
.Sh DESCRIPTION
.Nm
is used by
.Xr ssh 1
to access the local host keys and generate the digital signature
required during hostbased authentication with SSH protocol version 2.
.Nm
is not intended to be invoked by the user, but from
.Xr ssh 1 .
See
.Xr ssh 1
and
.Xr sshd 8
for more information about hostbased authentication.
.Sh FILES
.Bl -tag -width Ds
.It Pa /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_rsa_key
These files contain the private parts of the host keys used to
generate the digital signature. They
should be owned by root, readable only by root, and not
accessible to others.
Since they are readable only by root,
.Nm
must be set-uid root if hostbased authentication is used.
.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-keygen 1 ,
.Xr sshd 8
.Sh AUTHORS
Markus Friedl <markus@openbsd.org>
.Sh HISTORY
.Nm
first appeared in
.Ox 3.2 .

View File

@ -0,0 +1,208 @@
/*
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: ssh-keysign.c,v 1.4 2002/06/19 00:27:55 deraadt Exp $");
#include <openssl/evp.h>
#include "log.h"
#include "key.h"
#include "ssh2.h"
#include "misc.h"
#include "xmalloc.h"
#include "buffer.h"
#include "bufaux.h"
#include "authfile.h"
#include "msg.h"
#include "canohost.h"
#include "pathnames.h"
static int
valid_request(struct passwd *pw, char *host, Key **ret, u_char *data,
u_int datalen)
{
Buffer b;
Key *key;
u_char *pkblob;
u_int blen, len;
char *pkalg, *p;
int pktype, fail;
fail = 0;
buffer_init(&b);
buffer_append(&b, data, datalen);
/* session id, currently limited to SHA1 (20 bytes) */
p = buffer_get_string(&b, &len);
if (len != 20)
fail++;
xfree(p);
if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
fail++;
/* server user */
buffer_skip_string(&b);
/* service */
p = buffer_get_string(&b, NULL);
if (strcmp("ssh-connection", p) != 0)
fail++;
xfree(p);
/* method */
p = buffer_get_string(&b, NULL);
if (strcmp("hostbased", p) != 0)
fail++;
xfree(p);
/* pubkey */
pkalg = buffer_get_string(&b, NULL);
pkblob = buffer_get_string(&b, &blen);
pktype = key_type_from_name(pkalg);
if (pktype == KEY_UNSPEC)
fail++;
else if ((key = key_from_blob(pkblob, blen)) == NULL)
fail++;
else if (key->type != pktype)
fail++;
xfree(pkalg);
xfree(pkblob);
/* client host name, handle trailing dot */
p = buffer_get_string(&b, &len);
debug2("valid_request: check expect chost %s got %s", host, p);
if (strlen(host) != len - 1)
fail++;
else if (p[len - 1] != '.')
fail++;
else if (strncasecmp(host, p, len - 1) != 0)
fail++;
xfree(p);
/* local user */
p = buffer_get_string(&b, NULL);
if (strcmp(pw->pw_name, p) != 0)
fail++;
xfree(p);
/* end of message */
if (buffer_len(&b) != 0)
fail++;
debug3("valid_request: fail %d", fail);
if (fail && key != NULL)
key_free(key);
else
*ret = key;
return (fail ? -1 : 0);
}
int
main(int argc, char **argv)
{
Buffer b;
Key *keys[2], *key;
struct passwd *pw;
int key_fd[2], i, found, version = 2, fd;
u_char *signature, *data;
char *host;
u_int slen, dlen;
key_fd[0] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY);
key_fd[1] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY);
seteuid(getuid());
setuid(getuid());
#ifdef DEBUG_SSH_KEYSIGN
log_init("ssh-keysign", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0);
#endif
if (key_fd[0] == -1 && key_fd[1] == -1)
fatal("could not open any host key");
if ((pw = getpwuid(getuid())) == NULL)
fatal("getpwuid failed");
pw = pwcopy(pw);
SSLeay_add_all_algorithms();
found = 0;
for (i = 0; i < 2; i++) {
keys[i] = NULL;
if (key_fd[i] == -1)
continue;
keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC,
NULL, NULL);
close(key_fd[i]);
if (keys[i] != NULL)
found = 1;
}
if (!found)
fatal("no hostkey found");
buffer_init(&b);
if (msg_recv(STDIN_FILENO, &b) < 0)
fatal("msg_recv failed");
if (buffer_get_char(&b) != version)
fatal("bad version");
fd = buffer_get_int(&b);
if ((fd == STDIN_FILENO) || (fd == STDOUT_FILENO))
fatal("bad fd");
if ((host = get_local_name(fd)) == NULL)
fatal("cannot get sockname for fd");
data = buffer_get_string(&b, &dlen);
if (valid_request(pw, host, &key, data, dlen) < 0)
fatal("not a valid request");
xfree(data);
xfree(host);
found = 0;
for (i = 0; i < 2; i++) {
if (keys[i] != NULL &&
key_equal(key, keys[i])) {
found = 1;
break;
}
}
if (!found)
fatal("no matching hostkey found");
if (key_sign(keys[i], &signature, &slen, data, dlen) != 0)
fatal("key_sign failed");
/* send reply */
buffer_clear(&b);
buffer_put_string(&b, signature, slen);
msg_send(STDOUT_FILENO, version, &b);
return (0);
}

View File

@ -0,0 +1,18 @@
# $OpenBSD: Makefile,v 1.3 2002/05/31 10:30:33 markus Exp $
.PATH: ${.CURDIR}/..
PROG= ssh-keysign
BINOWN= root
BINMODE?=4555
BINDIR= /usr/libexec
MAN= ssh-keysign.8
SRCS= ssh-keysign.c
.include <bsd.prog.mk>
LDADD+= -lcrypto -lz
DPADD+= ${LIBCRYPTO} ${LIBZ}

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: ssh-rsa.c,v 1.16 2002/02/24 19:14:59 markus Exp $");
RCSID("$OpenBSD: ssh-rsa.c,v 1.20 2002/06/10 16:53:06 stevesk Exp $");
#include <openssl/evp.h>
#include <openssl/err.h>
@ -35,6 +35,7 @@ RCSID("$OpenBSD: ssh-rsa.c,v 1.16 2002/02/24 19:14:59 markus Exp $");
#include "key.h"
#include "ssh-rsa.h"
#include "compat.h"
#include "ssh.h"
/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
int
@ -54,10 +55,6 @@ ssh_rsa_sign(
error("ssh_rsa_sign: no RSA key");
return -1;
}
if (datafellows & SSH_BUG_SIGBLOB) {
error("ssh_rsa_sign: SSH_BUG_SIGBLOB not supported");
return -1;
}
nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid);
@ -118,20 +115,16 @@ ssh_rsa_verify(
EVP_MD_CTX md;
char *ktype;
u_char digest[EVP_MAX_MD_SIZE], *sigblob;
u_int len, dlen;
u_int len, dlen, modlen;
int rlen, ret, nid;
if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) {
error("ssh_rsa_verify: no RSA key");
return -1;
}
if (datafellows & SSH_BUG_SIGBLOB) {
error("ssh_rsa_verify: SSH_BUG_SIGBLOB not supported");
return -1;
}
if (BN_num_bits(key->rsa->n) < 768) {
error("ssh_rsa_verify: n too small: %d bits",
BN_num_bits(key->rsa->n));
if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
error("ssh_rsa_verify: RSA modulus too small: %d < minimum %d bits",
BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
return -1;
}
buffer_init(&b);
@ -152,6 +145,21 @@ ssh_rsa_verify(
xfree(sigblob);
return -1;
}
/* RSA_verify expects a signature of RSA_size */
modlen = RSA_size(key->rsa);
if (len > modlen) {
error("ssh_rsa_verify: len %d > modlen %d", len, modlen);
xfree(sigblob);
return -1;
} else if (len < modlen) {
int diff = modlen - len;
debug("ssh_rsa_verify: add padding: modlen %d > len %d",
modlen, len);
sigblob = xrealloc(sigblob, modlen);
memmove(sigblob + diff, sigblob, len);
memset(sigblob, 0, diff);
len = modlen;
}
nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid);

View File

@ -34,7 +34,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: ssh.1,v 1.148 2002/02/18 17:55:20 markus Exp $
.\" $OpenBSD: ssh.1,v 1.158 2002/06/20 19:56:07 stevesk Exp $
.Dd September 25, 1999
.Dt SSH 1
.Os
@ -297,6 +297,12 @@ Background ssh at logout when waiting for forwarded connection / X11 sessions
to terminate
.It Cm ~?
Display a list of escape characters
.It Cm ~C
Open command line (only useful for adding port forwardings using the
.Fl L
and
.Fl R
options)
.It Cm ~R
Request rekeying of the connection (only useful for SSH protocol version 2
and if the peer supports it)
@ -378,7 +384,7 @@ this mechanism is to prevent man-in-the-middle attacks which could
otherwise be used to circumvent the encryption.
The
.Cm StrictHostKeyChecking
option (see below) can be used to prevent logins to machines whose
option can be used to prevent logins to machines whose
host key is not known or has changed.
.Pp
The options are as follows:
@ -562,13 +568,13 @@ and the
.Dq level
can be controlled by the
.Cm CompressionLevel
option (see below).
option.
Compression is desirable on modem lines and other
slow connections, but will only slow down things on fast networks.
The default value can be set on a host-by-host basis in the
configuration files; see the
.Cm Compression
option below.
option.
.It Fl F Ar configfile
Specifies an alternative per-user configuration file.
If a configuration file is given on the command line,
@ -643,580 +649,10 @@ to use IPv6 addresses only.
.El
.Sh CONFIGURATION FILES
.Nm
obtains configuration data from the following sources in
the following order:
command line options, user's configuration file
.Pq Pa $HOME/.ssh/config ,
and system-wide configuration file
.Pq Pa /etc/ssh/ssh_config .
For each parameter, the first obtained value
will be used.
The configuration files contain sections bracketed by
.Dq Host
specifications, and that section is only applied for hosts that
match one of the patterns given in the specification.
The matched host name is the one given on the command line.
.Pp
Since the first obtained value for each parameter is used, more
host-specific declarations should be given near the beginning of the
file, and general defaults at the end.
.Pp
The configuration file has the following format:
.Pp
Empty lines and lines starting with
.Ql #
are comments.
.Pp
Otherwise a line is of the format
.Dq keyword arguments .
Configuration options may be separated by whitespace or
optional whitespace and exactly one
.Ql = ;
the latter format is useful to avoid the need to quote whitespace
when specifying configuration options using the
.Nm ssh ,
.Nm scp
and
.Nm sftp
.Fl o
option.
.Pp
The possible
keywords and their meanings are as follows (note that
keywords are case-insensitive and arguments are case-sensitive):
.Bl -tag -width Ds
.It Cm Host
Restricts the following declarations (up to the next
.Cm Host
keyword) to be only for those hosts that match one of the patterns
given after the keyword.
.Ql \&*
and
.Ql ?
can be used as wildcards in the
patterns.
A single
.Ql \&*
as a pattern can be used to provide global
defaults for all hosts.
The host is the
.Ar hostname
argument given on the command line (i.e., the name is not converted to
a canonicalized host name before matching).
.It Cm AFSTokenPassing
Specifies whether to pass AFS tokens to remote host.
The argument to this keyword must be
.Dq yes
or
.Dq no .
This option applies to protocol version 1 only.
.It Cm BatchMode
If set to
.Dq yes ,
passphrase/password querying will be disabled.
This option is useful in scripts and other batch jobs where no user
is present to supply the password.
The argument must be
.Dq yes
or
.Dq no .
The default is
.Dq no .
.It Cm BindAddress
Specify the interface to transmit from on machines with multiple
interfaces or aliased addresses.
Note that this option does not work if
.Cm UsePrivilegedPort
is set to
.Dq yes .
.It Cm CheckHostIP
If this flag is set to
.Dq yes ,
ssh will additionally check the host IP address in the
.Pa known_hosts
file.
This allows ssh to detect if a host key changed due to DNS spoofing.
If the option is set to
.Dq no ,
the check will not be executed.
The default is
.Dq yes .
.It Cm Cipher
Specifies the cipher to use for encrypting the session
in protocol version 1.
Currently,
.Dq blowfish ,
.Dq 3des ,
and
.Dq des
are supported.
.Ar des
is only supported in the
.Nm
client for interoperability with legacy protocol 1 implementations
that do not support the
.Ar 3des
cipher. Its use is strongly discouraged due to cryptographic
weaknesses.
The default is
.Dq 3des .
.It Cm Ciphers
Specifies the ciphers allowed for protocol version 2
in order of preference.
Multiple ciphers must be comma-separated.
The default is
.Pp
.Bd -literal
``aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,
aes192-cbc,aes256-cbc''
.Ed
.It Cm ClearAllForwardings
Specifies that all local, remote and dynamic port forwardings
specified in the configuration files or on the command line be
cleared. This option is primarily useful when used from the
.Nm
command line to clear port forwardings set in
configuration files, and is automatically set by
.Xr scp 1
and
.Xr sftp 1 .
The argument must be
.Dq yes
or
.Dq no .
The default is
.Dq no .
.It Cm Compression
Specifies whether to use compression.
The argument must be
.Dq yes
or
.Dq no .
The default is
.Dq no .
.It Cm CompressionLevel
Specifies the compression level to use if compression is enabled.
The argument must be an integer from 1 (fast) to 9 (slow, best).
The default level is 6, which is good for most applications.
The meaning of the values is the same as in
.Xr gzip 1 .
Note that this option applies to protocol version 1 only.
.It Cm ConnectionAttempts
Specifies the number of tries (one per second) to make before falling
back to rsh or exiting.
The argument must be an integer.
This may be useful in scripts if the connection sometimes fails.
The default is 1.
.It Cm DynamicForward
Specifies that a TCP/IP port on the local machine be forwarded
over the secure channel, and the application
protocol is then used to determine where to connect to from the
remote machine. The argument must be a port number.
Currently the SOCKS4 protocol is supported, and
.Nm
will act as a SOCKS4 server.
Multiple forwardings may be specified, and
additional forwardings can be given on the command line. Only
the superuser can forward privileged ports.
.It Cm EscapeChar
Sets the escape character (default:
.Ql ~ ) .
The escape character can also
be set on the command line.
The argument should be a single character,
.Ql ^
followed by a letter, or
.Dq none
to disable the escape
character entirely (making the connection transparent for binary
data).
.It Cm FallBackToRsh
Specifies that if connecting via
.Nm
fails due to a connection refused error (there is no
.Xr sshd 8
listening on the remote host),
.Xr rsh 1
should automatically be used instead (after a suitable warning about
the session being unencrypted).
The argument must be
.Dq yes
or
.Dq no .
The default is
.Dq no .
.It Cm ForwardAgent
Specifies whether the connection to the authentication agent (if any)
will be forwarded to the remote machine.
The argument must be
.Dq yes
or
.Dq no .
The default is
.Dq no .
.It Cm ForwardX11
Specifies whether X11 connections will be automatically redirected
over the secure channel and
.Ev DISPLAY
set.
The argument must be
.Dq yes
or
.Dq no .
The default is
.Dq no .
.It Cm GatewayPorts
Specifies whether remote hosts are allowed to connect to local
forwarded ports.
By default,
.Nm
binds local port forwardings to the loopback addresss. This
prevents other remote hosts from connecting to forwarded ports.
.Cm GatewayPorts
can be used to specify that
.Nm
should bind local port forwardings to the wildcard address,
thus allowing remote hosts to connect to forwarded ports.
The argument must be
.Dq yes
or
.Dq no .
The default is
.Dq no .
.It Cm GlobalKnownHostsFile
Specifies a file to use for the global
host key database instead of
.Pa /etc/ssh/ssh_known_hosts .
.It Cm HostbasedAuthentication
Specifies whether to try rhosts based authentication with public key
authentication.
The argument must be
.Dq yes
or
.Dq no .
The default is
.Dq no .
This option applies to protocol version 2 only and
is similar to
.Cm RhostsRSAAuthentication .
.It Cm HostKeyAlgorithms
Specifies the protocol version 2 host key algorithms
that the client wants to use in order of preference.
The default for this option is:
.Dq ssh-rsa,ssh-dss .
.It Cm HostKeyAlias
Specifies an alias that should be used instead of the
real host name when looking up or saving the host key
in the host key database files.
This option is useful for tunneling ssh connections
or for multiple servers running on a single host.
.It Cm HostName
Specifies the real host name to log into.
This can be used to specify nicknames or abbreviations for hosts.
Default is the name given on the command line.
Numeric IP addresses are also permitted (both on the command line and in
.Cm HostName
specifications).
.It Cm IdentityFile
Specifies a file from which the user's RSA or DSA authentication identity
is read. The default is
.Pa $HOME/.ssh/identity
for protocol version 1, and
.Pa $HOME/.ssh/id_rsa
and
.Pa $HOME/.ssh/id_dsa
for protocol version 2.
Additionally, any identities represented by the authentication agent
will be used for authentication.
The file name may use the tilde
syntax to refer to a user's home directory.
It is possible to have
multiple identity files specified in configuration files; all these
identities will be tried in sequence.
.It Cm KeepAlive
Specifies whether the system should send TCP keepalive messages to the
other side.
If they are sent, death of the connection or crash of one
of the machines will be properly noticed.
However, this means that
connections will die if the route is down temporarily, and some people
find it annoying.
.Pp
The default is
.Dq yes
(to send keepalives), and the client will notice
if the network goes down or the remote host dies.
This is important in scripts, and many users want it too.
.Pp
To disable keepalives, the value should be set to
.Dq no .
.It Cm KerberosAuthentication
Specifies whether Kerberos authentication will be used.
The argument to this keyword must be
.Dq yes
or
.Dq no .
.It Cm KerberosTgtPassing
Specifies whether a Kerberos TGT will be forwarded to the server.
This will only work if the Kerberos server is actually an AFS kaserver.
The argument to this keyword must be
.Dq yes
or
.Dq no .
.It Cm LocalForward
Specifies that a TCP/IP port on the local machine be forwarded over
the secure channel to the specified host and port from the remote machine.
The first argument must be a port number, and the second must be
.Ar host:port .
IPv6 addresses can be specified with an alternative syntax:
.Ar host/port .
Multiple forwardings may be specified, and additional
forwardings can be given on the command line.
Only the superuser can forward privileged ports.
.It Cm LogLevel
Gives the verbosity level that is used when logging messages from
.Nm ssh .
The possible values are:
QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2 and DEBUG3.
The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2
and DEBUG3 each specify higher levels of verbose output.
.It Cm MACs
Specifies the MAC (message authentication code) algorithms
in order of preference.
The MAC algorithm is used in protocol version 2
for data integrity protection.
Multiple algorithms must be comma-separated.
The default is
.Dq hmac-md5,hmac-sha1,hmac-ripemd160,hmac-sha1-96,hmac-md5-96 .
.It Cm NoHostAuthenticationForLocalhost
This option can be used if the home directory is shared across machines.
In this case localhost will refer to a different machine on each of
the machines and the user will get many warnings about changed host keys.
However, this option disables host authentication for localhost.
The argument to this keyword must be
.Dq yes
or
.Dq no .
The default is to check the host key for localhost.
.It Cm NumberOfPasswordPrompts
Specifies the number of password prompts before giving up.
The argument to this keyword must be an integer.
Default is 3.
.It Cm PasswordAuthentication
Specifies whether to use password authentication.
The argument to this keyword must be
.Dq yes
or
.Dq no .
The default is
.Dq yes .
.It Cm Port
Specifies the port number to connect on the remote host.
Default is 22.
.It Cm PreferredAuthentications
Specifies the order in which the client should try protocol 2
authentication methods. This allows a client to prefer one method (e.g.
.Cm keyboard-interactive )
over another method (e.g.
.Cm password )
The default for this option is:
.Dq hostbased,publickey,keyboard-interactive,password .
.It Cm Protocol
Specifies the protocol versions
.Nm
should support in order of preference.
The possible values are
.Dq 1
and
.Dq 2 .
Multiple versions must be comma-separated.
The default is
.Dq 2,1 .
This means that
.Nm
tries version 2 and falls back to version 1
if version 2 is not available.
.It Cm ProxyCommand
Specifies the command to use to connect to the server.
The command
string extends to the end of the line, and is executed with
.Pa /bin/sh .
In the command string,
.Ql %h
will be substituted by the host name to
connect and
.Ql %p
by the port.
The command can be basically anything,
and should read from its standard input and write to its standard output.
It should eventually connect an
.Xr sshd 8
server running on some machine, or execute
.Ic sshd -i
somewhere.
Host key management will be done using the
HostName of the host being connected (defaulting to the name typed by
the user).
Note that
.Cm CheckHostIP
is not available for connects with a proxy command.
.Pp
.It Cm PubkeyAuthentication
Specifies whether to try public key authentication.
The argument to this keyword must be
.Dq yes
or
.Dq no .
The default is
.Dq yes .
This option applies to protocol version 2 only.
.It Cm RemoteForward
Specifies that a TCP/IP port on the remote machine be forwarded over
the secure channel to the specified host and port from the local machine.
The first argument must be a port number, and the second must be
.Ar host:port .
IPv6 addresses can be specified with an alternative syntax:
.Ar host/port .
Multiple forwardings may be specified, and additional
forwardings can be given on the command line.
Only the superuser can forward privileged ports.
.It Cm RhostsAuthentication
Specifies whether to try rhosts based authentication.
Note that this
declaration only affects the client side and has no effect whatsoever
on security.
Disabling rhosts authentication may reduce
authentication time on slow connections when rhosts authentication is
not used.
Most servers do not permit RhostsAuthentication because it
is not secure (see
.Cm RhostsRSAAuthentication ) .
The argument to this keyword must be
.Dq yes
or
.Dq no .
The default is
.Dq yes .
This option applies to protocol version 1 only.
.It Cm RhostsRSAAuthentication
Specifies whether to try rhosts based authentication with RSA host
authentication.
The argument must be
.Dq yes
or
.Dq no .
The default is
.Dq yes .
This option applies to protocol version 1 only.
.It Cm RSAAuthentication
Specifies whether to try RSA authentication.
The argument to this keyword must be
.Dq yes
or
.Dq no .
RSA authentication will only be
attempted if the identity file exists, or an authentication agent is
running.
The default is
.Dq yes .
Note that this option applies to protocol version 1 only.
.It Cm ChallengeResponseAuthentication
Specifies whether to use challenge response authentication.
The argument to this keyword must be
.Dq yes
or
.Dq no .
The default is
.Dq yes .
.It Cm SmartcardDevice
Specifies which smartcard device to use. The argument to this keyword is
the device
.Nm
should use to communicate with a smartcard used for storing the user's
private RSA key. By default, no device is specified and smartcard support
is not activated.
.It Cm StrictHostKeyChecking
If this flag is set to
.Dq yes ,
.Nm
will never automatically add host keys to the
.Pa $HOME/.ssh/known_hosts
file, and refuses to connect to hosts whose host key has changed.
This provides maximum protection against trojan horse attacks,
however, can be annoying when the
.Pa /etc/ssh/ssh_known_hosts
file is poorly maintained, or connections to new hosts are
frequently made.
This option forces the user to manually
add all new hosts.
If this flag is set to
.Dq no ,
.Nm
will automatically add new host keys to the
user known hosts files.
If this flag is set to
.Dq ask ,
new host keys
will be added to the user known host files only after the user
has confirmed that is what they really want to do, and
.Nm
will refuse to connect to hosts whose host key has changed.
The host keys of
known hosts will be verified automatically in all cases.
The argument must be
.Dq yes ,
.Dq no
or
.Dq ask .
The default is
.Dq ask .
.It Cm UsePrivilegedPort
Specifies whether to use a privileged port for outgoing connections.
The argument must be
.Dq yes
or
.Dq no .
The default is
.Dq no .
Note that this option must be set to
.Dq yes
if
.Cm RhostsAuthentication
and
.Cm RhostsRSAAuthentication
authentications are needed with older servers.
.It Cm User
Specifies the user to log in as.
This can be useful when a different user name is used on different machines.
This saves the trouble of
having to remember to give the user name on the command line.
.It Cm UserKnownHostsFile
Specifies a file to use for the user
host key database instead of
.Pa $HOME/.ssh/known_hosts .
.It Cm UseRsh
Specifies that rlogin/rsh should be used for this host.
It is possible that the host does not at all support the
.Nm
protocol.
This causes
.Nm
to immediately execute
.Xr rsh 1 .
All other options (except
.Cm HostName )
are ignored if this has been specified.
The argument must be
.Dq yes
or
.Dq no .
.It Cm XAuthLocation
Specifies the location of the
.Xr xauth 1
program.
The default is
.Pa /usr/X11R6/bin/xauth .
.El
may additionally obtain configuration data from
a per-user configuration file and a system-wide configuration file.
The file format and configuration options are described in
.Xr ssh_config 5 .
.Sh ENVIRONMENT
.Nm
will normally set the following environment variables:
@ -1351,13 +787,8 @@ never used automatically and are not necessary; they are only provided for
the convenience of the user.
.It Pa $HOME/.ssh/config
This is the per-user configuration file.
The format of this file is described above.
This file is used by the
.Nm
client.
This file does not usually contain any sensitive information,
but the recommended permissions are read/write for the user, and not
accessible by others.
The file format and configuration options are described in
.Xr ssh_config 5 .
.It Pa $HOME/.ssh/authorized_keys
Lists the public keys (RSA/DSA) that can be used for logging in as this user.
The format of this file is described in the
@ -1392,19 +823,31 @@ checking the key, because someone with access to the name servers
would then be able to fool host authentication.
.It Pa /etc/ssh/ssh_config
Systemwide configuration file.
This file provides defaults for those
values that are not specified in the user's configuration file, and
for those users who do not have a configuration file.
This file must be world-readable.
The file format and configuration options are described in
.Xr ssh_config 5 .
.It Pa /etc/ssh/ssh_host_key, /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_rsa_key
These three files contain the private parts of the host keys
and are used for
.Cm RhostsRSAAuthentication
and
.Cm HostbasedAuthentication .
Since they are readable only by root
If the protocol version 1
.Cm RhostsRSAAuthentication
method is used,
.Nm
must be setuid root if these authentication methods are desired.
must be setuid root, since the host key is readable only by root.
For protocol version 2,
.Nm
uses
.Xr ssh-keysign 8
to access the host keys for
.Cm HostbasedAuthentication .
This eliminates the requirement that
.Nm
be setuid root when that authentication method is used.
By default
.Nm
is not setuid root.
.It Pa $HOME/.rhosts
This file is used in
.Pa \&.rhosts
@ -1445,7 +888,7 @@ The purpose for
having this file is to be able to use rhosts authentication with
.Nm
without permitting login with
.Xr rlogin 1
.Nm rlogin
or
.Xr rsh 1 .
.It Pa /etc/hosts.equiv
@ -1502,7 +945,6 @@ created OpenSSH.
Markus Friedl contributed the support for SSH
protocol versions 1.5 and 2.0.
.Sh SEE ALSO
.Xr rlogin 1 ,
.Xr rsh 1 ,
.Xr scp 1 ,
.Xr sftp 1 ,
@ -1510,6 +952,8 @@ protocol versions 1.5 and 2.0.
.Xr ssh-agent 1 ,
.Xr ssh-keygen 1 ,
.Xr telnet 1 ,
.Xr ssh_config 4 ,
.Xr ssh-keysign 8,
.Xr sshd 8
.Rs
.%A T. Ylonen
@ -1518,7 +962,7 @@ protocol versions 1.5 and 2.0.
.%A T. Rinne
.%A S. Lehtinen
.%T "SSH Protocol Architecture"
.%N draft-ietf-secsh-architecture-09.txt
.%D July 2001
.%N draft-ietf-secsh-architecture-12.txt
.%D January 2002
.%O work in progress material
.Re

View File

@ -13,6 +13,7 @@
* called by a name other than "ssh" or "Secure Shell".
*
* Copyright (c) 1999 Niels Provos. All rights reserved.
* Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
* Modified to work with SSL by Niels Provos <provos@citi.umich.edu>
* in Canada (German citizen).
@ -39,7 +40,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: ssh.c,v 1.164 2002/02/14 23:28:00 markus Exp $");
RCSID("$OpenBSD: ssh.c,v 1.179 2002/06/12 01:09:52 markus Exp $");
#include <openssl/evp.h>
#include <openssl/err.h>
@ -52,7 +53,6 @@ RCSID("$OpenBSD: ssh.c,v 1.164 2002/02/14 23:28:00 markus Exp $");
#include "xmalloc.h"
#include "packet.h"
#include "buffer.h"
#include "uidswap.h"
#include "channels.h"
#include "key.h"
#include "authfd.h"
@ -70,7 +70,6 @@ RCSID("$OpenBSD: ssh.c,v 1.164 2002/02/14 23:28:00 markus Exp $");
#include "sshtty.h"
#ifdef SMARTCARD
#include <openssl/engine.h>
#include "scard.h"
#endif
@ -99,7 +98,7 @@ int stdin_null_flag = 0;
/*
* Flag indicating that ssh should fork after authentication. This is useful
* so that the pasphrase can be entered manually, and then ssh goes to the
* so that the passphrase can be entered manually, and then ssh goes to the
* background.
*/
int fork_after_authentication_flag = 0;
@ -124,13 +123,11 @@ char *host;
struct sockaddr_storage hostaddr;
/* Private host keys. */
struct {
Key **keys;
int nkeys;
} sensitive_data;
Sensitive sensitive_data;
/* Original real UID. */
uid_t original_real_uid;
uid_t original_effective_uid;
/* command to be executed */
Buffer command;
@ -138,6 +135,9 @@ Buffer command;
/* Should we execute a command or invoke a subsystem? */
int subsystem_flag = 0;
/* # of replies received for global requests */
static int client_global_request_id = 0;
/* Prints a help message to the user. This function never returns. */
static void
@ -192,44 +192,6 @@ usage(void)
exit(1);
}
/*
* Connects to the given host using rsh (or prints an error message and exits
* if rsh is not available). This function never returns.
*/
static void
rsh_connect(char *host, char *user, Buffer * command)
{
char *args[10];
int i;
log("Using rsh. WARNING: Connection will not be encrypted.");
/* Build argument list for rsh. */
i = 0;
args[i++] = _PATH_RSH;
/* host may have to come after user on some systems */
args[i++] = host;
if (user) {
args[i++] = "-l";
args[i++] = user;
}
if (buffer_len(command) > 0) {
buffer_append(command, "\0", 1);
args[i++] = buffer_ptr(command);
}
args[i++] = NULL;
if (debug_flag) {
for (i = 0; args[i]; i++) {
if (i != 0)
fprintf(stderr, " ");
fprintf(stderr, "%s", args[i]);
}
fprintf(stderr, "\n");
}
execv(_PATH_RSH, args);
perror(_PATH_RSH);
exit(1);
}
static int ssh_session(void);
static int ssh_session2(void);
static void load_public_identity_files(void);
@ -240,14 +202,13 @@ static void load_public_identity_files(void);
int
main(int ac, char **av)
{
int i, opt, exit_status, cerr;
int i, opt, exit_status;
u_short fwd_port, fwd_host_port;
char sfwd_port[6], sfwd_host_port[6];
char *p, *cp, buf[256];
struct stat st;
struct passwd *pw;
int dummy;
uid_t original_effective_uid;
extern int optind, optreset;
extern char *optarg;
@ -281,7 +242,7 @@ main(int ac, char **av)
* them when the port has been created (actually, when the connection
* has been made, as we may need to create the port several times).
*/
temporarily_use_uid(pw);
PRIV_END;
/*
* Set our umask to something reasonable, as some files are created
@ -462,7 +423,7 @@ main(int ac, char **av)
/* NOTREACHED */
}
if ((fwd_port = a2port(sfwd_port)) == 0 ||
(fwd_host_port = a2port(sfwd_host_port)) == 0) {
(fwd_host_port = a2port(sfwd_host_port)) == 0) {
fprintf(stderr,
"Bad forwarding port(s) '%s'\n", optarg);
exit(1);
@ -630,52 +591,48 @@ main(int ac, char **av)
"originating port will not be trusted.");
options.rhosts_authentication = 0;
}
/*
* If using rsh has been selected, exec it now (without trying
* anything else). Note that we must release privileges first.
*/
if (options.use_rsh) {
/*
* Restore our superuser privileges. This must be done
* before permanently setting the uid.
*/
restore_uid();
/* Switch to the original uid permanently. */
permanently_set_uid(pw);
/* Execute rsh. */
rsh_connect(host, options.user, &command);
fatal("rsh_connect returned");
}
/* Restore our superuser privileges. */
restore_uid();
/* Open a connection to the remote host. */
cerr = ssh_connect(host, &hostaddr, options.port, IPv4or6,
if (ssh_connect(host, &hostaddr, options.port, IPv4or6,
options.connection_attempts,
original_effective_uid != 0 || !options.use_privileged_port,
pw, options.proxy_command);
original_effective_uid == 0 && options.use_privileged_port,
options.proxy_command) != 0)
exit(1);
/*
* If we successfully made the connection, load the host private key
* in case we will need it later for combined rsa-rhosts
* authentication. This must be done before releasing extra
* privileges, because the file is only readable by root.
* If we cannot access the private keys, load the public keys
* instead and try to execute the ssh-keysign helper instead.
*/
sensitive_data.nkeys = 0;
sensitive_data.keys = NULL;
if (!cerr && (options.rhosts_rsa_authentication ||
options.hostbased_authentication)) {
sensitive_data.external_keysign = 0;
if (options.rhosts_rsa_authentication ||
options.hostbased_authentication) {
sensitive_data.nkeys = 3;
sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key));
PRIV_START;
sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
_PATH_HOST_KEY_FILE, "", NULL);
sensitive_data.keys[1] = key_load_private_type(KEY_DSA,
_PATH_HOST_DSA_KEY_FILE, "", NULL);
sensitive_data.keys[2] = key_load_private_type(KEY_RSA,
_PATH_HOST_RSA_KEY_FILE, "", NULL);
PRIV_END;
if (sensitive_data.keys[0] == NULL &&
sensitive_data.keys[1] == NULL &&
sensitive_data.keys[2] == NULL) {
sensitive_data.keys[1] = key_load_public(
_PATH_HOST_DSA_KEY_FILE, NULL);
sensitive_data.keys[2] = key_load_public(
_PATH_HOST_RSA_KEY_FILE, NULL);
sensitive_data.external_keysign = 1;
}
}
/*
* Get rid of any extra privileges that we may have. We will no
@ -684,15 +641,8 @@ main(int ac, char **av)
* user's home directory if it happens to be on a NFS volume where
* root is mapped to nobody.
*/
/*
* Note that some legacy systems need to postpone the following call
* to permanently_set_uid() until the private hostkey is destroyed
* with RSA_free(). Otherwise the calling user could ptrace() the
* process, read the private hostkey and impersonate the host.
* OpenBSD does not allow ptracing of setuid processes.
*/
permanently_set_uid(pw);
seteuid(original_real_uid);
setuid(original_real_uid);
/*
* Now that we are back to our own permissions, create ~/.ssh
@ -703,21 +653,6 @@ main(int ac, char **av)
if (mkdir(buf, 0700) < 0)
error("Could not create directory '%.200s'.", buf);
/* Check if the connection failed, and try "rsh" if appropriate. */
if (cerr) {
if (!options.fallback_to_rsh)
exit(1);
if (options.port != 0)
log("Secure connection to %.100s on port %hu refused; "
"reverting to insecure method",
host, options.port);
else
log("Secure connection to %.100s refused; "
"reverting to insecure method.", host);
rsh_connect(host, options.user, &command);
fatal("rsh_connect returned");
}
/* load options.identity_files */
load_public_identity_files();
@ -735,8 +670,7 @@ main(int ac, char **av)
signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
/* Log into the remote system. This never returns if the login fails. */
ssh_login(sensitive_data.keys, sensitive_data.nkeys,
host, (struct sockaddr *)&hostaddr, pw);
ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, pw);
/* We no longer need the private host keys. Clear them now. */
if (sensitive_data.nkeys != 0) {
@ -788,10 +722,10 @@ x11_get_proto(char **_proto, char **_data)
* XXX: "localhost" match to determine FamilyLocal
* is not perfect.
*/
snprintf(line, sizeof line, "%.100s list unix:%s 2>"
snprintf(line, sizeof line, "%s list unix:%s 2>"
_PATH_DEVNULL, options.xauth_location, display+10);
else
snprintf(line, sizeof line, "%.100s list %.200s 2>"
snprintf(line, sizeof line, "%s list %.200s 2>"
_PATH_DEVNULL, options.xauth_location, display);
debug2("x11_get_proto %s", line);
f = popen(line, "r");
@ -1021,6 +955,27 @@ client_subsystem_reply(int type, u_int32_t seq, void *ctxt)
len, (u_char *)buffer_ptr(&command), id);
}
void
client_global_request_reply(int type, u_int32_t seq, void *ctxt)
{
int i;
i = client_global_request_id++;
if (i >= options.num_remote_forwards) {
debug("client_global_request_reply: too many replies %d > %d",
i, options.num_remote_forwards);
return;
}
debug("remote forward %s for: listen %d, connect %s:%d",
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
options.remote_forwards[i].port,
options.remote_forwards[i].host,
options.remote_forwards[i].host_port);
if (type == SSH2_MSG_REQUEST_FAILURE)
log("Warning: remote port forwarding failed for listen port %d",
options.remote_forwards[i].port);
}
/* request pty/x11/agent/tcpfwd/shell for channel */
static void
ssh_session2_setup(int id, void *arg)
@ -1080,7 +1035,7 @@ ssh_session2_setup(int id, void *arg)
debug("Sending subsystem: %.*s", len, (u_char *)buffer_ptr(&command));
channel_request_start(id, "subsystem", /*want reply*/ 1);
/* register callback for reply */
/* XXX we asume that client_loop has already been called */
/* XXX we assume that client_loop has already been called */
dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &client_subsystem_reply);
dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &client_subsystem_reply);
} else {
@ -1167,40 +1122,29 @@ static void
load_public_identity_files(void)
{
char *filename;
Key *public;
int i = 0;
Key *public;
#ifdef SMARTCARD
Key **keys;
if (options.smartcard_device != NULL &&
options.num_identity_files + 1 < SSH_MAX_IDENTITY_FILES &&
(public = sc_get_key(options.smartcard_device)) != NULL ) {
Key *new;
if (options.num_identity_files + 2 > SSH_MAX_IDENTITY_FILES)
options.num_identity_files = SSH_MAX_IDENTITY_FILES - 2;
memmove(&options.identity_files[2], &options.identity_files[0],
sizeof(char *) * options.num_identity_files);
options.num_identity_files += 2;
i = 2;
/* XXX ssh1 vs ssh2 */
new = key_new(KEY_RSA);
new->flags = KEY_FLAG_EXT;
BN_copy(new->rsa->n, public->rsa->n);
BN_copy(new->rsa->e, public->rsa->e);
RSA_set_method(new->rsa, sc_get_engine());
options.identity_keys[0] = new;
options.identity_files[0] = xstrdup("smartcard rsa key");;
new = key_new(KEY_RSA1);
new->flags = KEY_FLAG_EXT;
BN_copy(new->rsa->n, public->rsa->n);
BN_copy(new->rsa->e, public->rsa->e);
RSA_set_method(new->rsa, sc_get_engine());
options.identity_keys[1] = new;
options.identity_files[1] = xstrdup("smartcard rsa1 key");
key_free(public);
options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
(keys = sc_get_keys(options.smartcard_device, NULL)) != NULL ) {
int count = 0;
for (i = 0; keys[i] != NULL; i++) {
count++;
memmove(&options.identity_files[1], &options.identity_files[0],
sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1));
memmove(&options.identity_keys[1], &options.identity_keys[0],
sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1));
options.num_identity_files++;
options.identity_keys[0] = keys[i];
options.identity_files[0] = xstrdup("smartcard key");;
}
if (options.num_identity_files > SSH_MAX_IDENTITY_FILES)
options.num_identity_files = SSH_MAX_IDENTITY_FILES;
i = count;
xfree(keys);
}
#endif /* SMARTCARD */
for (; i < options.num_identity_files; i++) {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh.h,v 1.64 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: ssh.h,v 1.70 2002/06/03 12:04:07 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -31,7 +31,7 @@
#define SSH_MAX_IDENTITY_FILES 100
/*
* Major protocol version. Different version indicates major incompatiblity
* Major protocol version. Different version indicates major incompatibility
* that prevents communication.
*
* Minor protocol version. Different version indicates minor incompatibility
@ -85,4 +85,14 @@
/* Used to identify ``EscapeChar none'' */
#define SSH_ESCAPECHAR_NONE -2
/*
* unprivileged user when UsePrivilegeSeparation=yes;
* sshd will change its privileges to this user and its
* primary group.
*/
#define SSH_PRIVSEP_USER "sshd"
/* Minimum modulus size (n) for RSA keys. */
#define SSH_RSA_MINIMUM_MODULUS_SIZE 768
#endif /* SSH_H */

View File

@ -1,14 +1,14 @@
# $OpenBSD: Makefile,v 1.37 2002/03/05 00:49:51 deraadt Exp $
# $OpenBSD: Makefile,v 1.42 2002/06/20 19:56:07 stevesk Exp $
.PATH: ${.CURDIR}/..
PROG= ssh
BINOWN= root
BINMODE?=4555
#BINMODE?=4555
BINDIR= /usr/bin
MAN= ssh.1
MAN= ssh.1 ssh_config.5
LINKS= ${BINDIR}/ssh ${BINDIR}/slogin
MLINKS= ssh.1 slogin.1
@ -20,7 +20,7 @@ SRCS= ssh.c readconf.c clientloop.c sshtty.c \
.if (${KERBEROS5:L} == "yes")
CFLAGS+= -DKRB5 -I${DESTDIR}/usr/include/kerberosV
LDADD+= -lkrb5 -lasn1 -lcom_err
DPADD+= ${LIBKRB5} ${LIBASN1}
DPADD+= ${LIBKRB5} ${LIBASN1} ${LIBCOM_ERR}
.endif # KERBEROS5
.if (${KERBEROS:L} == "yes")
@ -30,11 +30,11 @@ DPADD+= ${LIBKRB}
.if (${AFS:L} == "yes")
CFLAGS+= -DAFS
LDADD+= -lkafs
DPADD+= ${LIBKRBAFS}
DPADD+= ${LIBKAFS}
.endif # AFS
.endif # KERBEROS
.include <bsd.prog.mk>
LDADD+= -lcrypto -lz -ldes
DPADD+= ${LIBCRYPTO} ${LIBZ}
DPADD+= ${LIBCRYPTO} ${LIBZ} ${LIBDES}

Some files were not shown because too many files have changed in this diff Show More