Vendor import of OpenSSH 3.3.
This commit is contained in:
parent
556a3fb01e
commit
545d5eca42
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor-crypto/openssh/dist/; revision=98675
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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 $
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
182
crypto/openssh/auth2-hostbased.c
Normal file
182
crypto/openssh/auth2-hostbased.c
Normal 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
|
||||
};
|
61
crypto/openssh/auth2-kbdint.c
Normal file
61
crypto/openssh/auth2-kbdint.c
Normal 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
106
crypto/openssh/auth2-none.c
Normal 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
|
||||
};
|
62
crypto/openssh/auth2-passwd.c
Normal file
62
crypto/openssh/auth2-passwd.c
Normal 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
|
||||
};
|
279
crypto/openssh/auth2-pubkey.c
Normal file
279
crypto/openssh/auth2-pubkey.c
Normal 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
|
||||
};
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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],
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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*,"
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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]);
|
||||
|
@ -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(); */
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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, },
|
||||
|
@ -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
1498
crypto/openssh/monitor.c
Normal file
File diff suppressed because it is too large
Load Diff
81
crypto/openssh/monitor.h
Normal file
81
crypto/openssh/monitor.h
Normal 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_ */
|
96
crypto/openssh/monitor_fdpass.c
Normal file
96
crypto/openssh/monitor_fdpass.c
Normal 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;
|
||||
}
|
34
crypto/openssh/monitor_fdpass.h
Normal file
34
crypto/openssh/monitor_fdpass.h
Normal 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
330
crypto/openssh/monitor_mm.c
Normal 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);
|
||||
}
|
66
crypto/openssh/monitor_mm.h
Normal file
66
crypto/openssh/monitor_mm.h
Normal 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_ */
|
920
crypto/openssh/monitor_wrap.c
Normal file
920
crypto/openssh/monitor_wrap.c
Normal 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);
|
||||
}
|
88
crypto/openssh/monitor_wrap.h
Normal file
88
crypto/openssh/monitor_wrap.h
Normal 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
73
crypto/openssh/msg.c
Normal 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
31
crypto/openssh/msg.h
Normal 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
|
@ -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," \
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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 *);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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 ||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
67
crypto/openssh/ssh-keysign.8
Normal file
67
crypto/openssh/ssh-keysign.8
Normal 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 .
|
208
crypto/openssh/ssh-keysign.c
Normal file
208
crypto/openssh/ssh-keysign.c
Normal 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);
|
||||
}
|
18
crypto/openssh/ssh-keysign/Makefile
Normal file
18
crypto/openssh/ssh-keysign/Makefile
Normal 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}
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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++) {
|
||||
|
@ -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 */
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user